def Start(self): if self._auto: logging.debug('Starting automatic device deployment.') node_name = boot_data.GetNodeName(self._output_dir) self._host = self.__Discover(node_name) if self._host and self._WaitUntilReady(retries=0): if not self._SDKHashMatches(): logging.info('SDK hash does not match, rebooting.') self.RunCommand(['dm', 'reboot']) self._started = False else: logging.info('Connected to an already booted device.') self._new_instance = False return logging.info('Netbooting Fuchsia. ' + 'Please ensure that your device is in bootloader mode.') bootserver_path = os.path.join(SDK_ROOT, 'tools', 'bootserver') bootserver_command = [ bootserver_path, '-1', '--efi', EnsurePathExists(boot_data.GetTargetFile(self._GetTargetSdkArch(), 'local.esp.blk')), '--fvm', EnsurePathExists(boot_data.GetTargetFile(self._GetTargetSdkArch(), 'fvm.sparse.blk')), '--fvm', EnsurePathExists( boot_data.ConfigureDataFVM(self._output_dir, boot_data.FVM_TYPE_SPARSE)), EnsurePathExists(boot_data.GetTargetFile(self._GetTargetSdkArch(), 'fuchsia.zbi')), '--'] + boot_data.GetKernelArgs(self._output_dir) logging.debug(' '.join(bootserver_command)) subprocess.check_call(bootserver_command) # Start loglistener to save system logs. if self._system_log_file: loglistener_path = os.path.join(SDK_ROOT, 'tools', 'loglistener') self._loglistener = subprocess.Popen( [loglistener_path, node_name], stdout=self._system_log_file, stderr=subprocess.STDOUT, stdin=open(os.devnull)) logging.debug('Waiting for device to join network.') for retry in xrange(CONNECT_RETRY_COUNT): self._host = self.__Discover(node_name) if self._host: break time.sleep(CONNECT_RETRY_WAIT_SECS) if not self._host: raise Exception('Couldn\'t connect to device.') logging.debug('host=%s, port=%d' % (self._host, self._port)) self._WaitUntilReady(); # Update the target's hash to match the current tree's. self.PutFile(os.path.join(SDK_ROOT, '.hash'), TARGET_HASH_FILE_PATH)
def Start(self): if self._auto: logging.debug('Starting automatic device deployment.') node_name = boot_data.GetNodeName(self._output_dir) self._host = self.__Discover(node_name) if self._host and self._WaitUntilReady(retries=0): logging.info('Connected to an already booted device.') self._new_instance = False return logging.info('Netbooting Fuchsia. ' + 'Please ensure that your device is in bootloader mode.') bootserver_path = os.path.join(SDK_ROOT, 'tools', 'bootserver') bootserver_command = [ bootserver_path, '-1', '--efi', EnsurePathExists(boot_data.GetTargetFile(self._GetTargetSdkArch(), 'local.esp.blk')), '--fvm', EnsurePathExists(boot_data.GetTargetFile(self._GetTargetSdkArch(), 'fvm.sparse.blk')), '--fvm', EnsurePathExists( boot_data.ConfigureDataFVM(self._output_dir, boot_data.FVM_TYPE_SPARSE)), EnsurePathExists(boot_data.GetTargetFile(self._GetTargetSdkArch(), 'zircon.bin')), EnsurePathExists(boot_data.GetTargetFile(self._GetTargetSdkArch(), 'bootdata-blob.bin')), '--'] + boot_data.GetKernelArgs(self._output_dir) logging.debug(' '.join(bootserver_command)) subprocess.check_call(bootserver_command) # Setup loglistener. Logs will be redirected to stdout if the device takes # longer than expected to boot. loglistener_path = os.path.join(SDK_ROOT, 'tools', 'loglistener') loglistener = subprocess.Popen([loglistener_path, node_name], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=open(os.devnull)) self._SetSystemLogsReader( log_reader.LogReader(loglistener, loglistener.stdout)) logging.debug('Waiting for device to join network.') for retry in xrange(CONNECT_RETRY_COUNT): if retry == CONNECT_RETRY_COUNT_BEFORE_LOGGING: self._system_logs_reader.RedirectTo(sys.stdout); self._host = self.__Discover(node_name) if self._host: break time.sleep(CONNECT_RETRY_WAIT_SECS) if not self._host: raise Exception('Couldn\'t connect to device.') logging.debug('host=%s, port=%d' % (self._host, self._port)) self._WaitUntilReady();
def Start(self): if self._auto: logging.debug('Starting automatic device deployment.') node_name = boot_data.GetNodeName(self._output_dir) self._host = self.__Discover(node_name) if self._host and self._WaitUntilReady(retries=0): logging.info('Connected to an already booted device.') self._new_instance = False return logging.info( 'Netbooting Fuchsia. ' + 'Please ensure that your device is in bootloader mode.') bootserver_path = os.path.join(common.SDK_ROOT, 'tools', 'bootserver') data_fvm_path = boot_data.ConfigureDataFVM( self._output_dir, boot_data.FVM_TYPE_SPARSE) bootserver_command = [bootserver_path, '-1', '--efi', boot_data.GetTargetFile(self._GetTargetSdkArch(), 'local.esp.blk'), '--fvm', boot_data.GetTargetFile(self._GetTargetSdkArch(), 'fvm.sparse.blk'), '--fvm', data_fvm_path, boot_data.GetTargetFile(self._GetTargetSdkArch(), 'zircon.bin'), boot_data.GetTargetFile(self._GetTargetSdkArch(), 'bootdata-blob.bin'), '--'] + \ boot_data.GetKernelArgs(self._output_dir) logging.debug(' '.join(bootserver_command)) subprocess.check_call(bootserver_command) logging.debug('Waiting for device to join network.') for _ in xrange(CONNECT_RETRY_COUNT): self._host = self.__Discover(node_name) if self._host: break time.sleep(CONNECT_RETRY_WAIT_SECS) if not self._host: raise Exception('Couldn\'t connect to device.') logging.debug('host=%s, port=%d' % (self._host, self._port)) self._WaitUntilReady()
def Start(self): qemu_path = os.path.join(common.SDK_ROOT, 'qemu', 'bin', 'qemu-system-' + self._GetTargetSdkArch()) kernel_args = boot_data.GetKernelArgs(self._output_dir) qemu_command = [ qemu_path, '-m', str(self._ram_size_mb), '-nographic', '-kernel', boot_data.GetTargetFile(self._GetTargetSdkArch(), 'zircon.bin'), '-initrd', boot_data.GetTargetFile(self._GetTargetSdkArch(), 'bootdata-blob.bin'), '-smp', '4', # Attach the blobstore and data volumes. Use snapshot mode to discard # any changes. '-snapshot', '-drive', 'file=%s,format=qcow2,if=none,id=data,snapshot=on' % os.path.join(self._output_dir, 'fvm.blk.qcow2'), '-drive', 'file=%s,format=qcow2,if=none,id=blobstore,snapshot=on' % self._MakeQcowDisk( boot_data.ConfigureDataFVM(self._output_dir, False)), '-device', 'virtio-blk-pci,drive=data', '-device', 'virtio-blk-pci,drive=blobstore', # Use stdio for the guest OS only; don't attach the QEMU interactive # monitor. '-serial', 'stdio', '-monitor', 'none', # TERM=dumb tells the guest OS to not emit ANSI commands that trigger # noisy ANSI spew from the user's terminal emulator. '-append', 'TERM=dumb ' + ' '.join(kernel_args) ] # Configure the machine & CPU to emulate, based on the target architecture. # Enable lightweight virtualization (KVM) if the host and guest OS run on # the same architecture. if self._target_cpu == 'arm64': qemu_command.extend([ '-machine', 'virt', '-cpu', 'cortex-a53', ]) netdev_type = 'virtio-net-pci' if platform.machine() == 'aarch64': qemu_command.append('-enable-kvm') else: qemu_command.extend([ '-machine', 'q35', '-cpu', 'host,migratable=no', ]) netdev_type = 'e1000' if platform.machine() == 'x86_64': qemu_command.append('-enable-kvm') # Configure virtual network. It is used in the tests to connect to # testserver running on the host. netdev_config = 'user,id=net0,net=%s,dhcpstart=%s,host=%s' % \ (GUEST_NET, GUEST_IP_ADDRESS, HOST_IP_ADDRESS) self._host_ssh_port = _GetAvailableTcpPort() netdev_config += ",hostfwd=tcp::%s-:22" % self._host_ssh_port qemu_command.extend([ '-netdev', netdev_config, '-device', '%s,netdev=net0,mac=%s' % (netdev_type, GUEST_MAC_ADDRESS), ]) # We pass a separate stdin stream to qemu. Sharing stdin across processes # leads to flakiness due to the OS prematurely killing the stream and the # Python script panicking and aborting. # The precise root cause is still nebulous, but this fix works. # See crbug.com/741194. logging.debug('Launching QEMU.') logging.debug(' '.join(qemu_command)) stdio_flags = {'stdin': open(os.devnull)} if logging.getLogger().getEffectiveLevel() != logging.DEBUG: # Output the Fuchsia debug log. stdio_flags['stdout'] = open(os.devnull) stdio_flags['stderr'] = open(os.devnull) self._qemu_process = subprocess.Popen(qemu_command, **stdio_flags) self._WaitUntilReady()
def Start(self): qemu_path = os.path.join( QEMU_ROOT, 'bin', 'qemu-system-' + self._GetTargetSdkLegacyArch()) kernel_args = boot_data.GetKernelArgs(self._output_dir) # TERM=dumb tells the guest OS to not emit ANSI commands that trigger # noisy ANSI spew from the user's terminal emulator. kernel_args.append('TERM=dumb') # Enable logging to the serial port. This is a temporary fix to investigate # the root cause for https://crbug.com/869753 . kernel_args.append('kernel.serial=legacy') qemu_command = [ qemu_path, '-m', str(self._ram_size_mb), '-nographic', '-kernel', EnsurePathExists( boot_data.GetTargetFile(self._GetTargetSdkArch(), 'zircon.bin')), '-initrd', EnsurePathExists( boot_data.GetTargetFile(self._GetTargetSdkArch(), 'bootdata-blob.bin')), '-smp', '4', # Attach the blobstore and data volumes. Use snapshot mode to discard # any changes. '-snapshot', '-drive', 'file=%s,format=qcow2,if=none,id=data,snapshot=on' % EnsurePathExists(os.path.join(self._output_dir, 'fvm.blk.qcow2')), '-drive', 'file=%s,format=qcow2,if=none,id=blobstore,snapshot=on' % EnsurePathExists( boot_data.ConfigureDataFVM(self._output_dir, boot_data.FVM_TYPE_QCOW)), '-device', 'virtio-blk-pci,drive=data', '-device', 'virtio-blk-pci,drive=blobstore', # Use stdio for the guest OS only; don't attach the QEMU interactive # monitor. '-serial', 'stdio', '-monitor', 'none', '-append', ' '.join(kernel_args) ] # Configure the machine & CPU to emulate, based on the target architecture. # Enable lightweight virtualization (KVM) if the host and guest OS run on # the same architecture. if self._target_cpu == 'arm64': qemu_command.extend([ '-machine', 'virt', '-cpu', 'cortex-a53', ]) netdev_type = 'virtio-net-pci' if platform.machine() == 'aarch64': qemu_command.append('-enable-kvm') else: qemu_command.extend([ '-machine', 'q35', '-cpu', 'host,migratable=no', ]) netdev_type = 'e1000' if platform.machine() == 'x86_64': qemu_command.append('-enable-kvm') # Configure virtual network. It is used in the tests to connect to # testserver running on the host. netdev_config = 'user,id=net0,net=%s,dhcpstart=%s,host=%s' % \ (GUEST_NET, GUEST_IP_ADDRESS, HOST_IP_ADDRESS) self._host_ssh_port = _GetAvailableTcpPort() netdev_config += ",hostfwd=tcp::%s-:22" % self._host_ssh_port qemu_command.extend([ '-netdev', netdev_config, '-device', '%s,netdev=net0,mac=%s' % (netdev_type, GUEST_MAC_ADDRESS), ]) # We pass a separate stdin stream to qemu. Sharing stdin across processes # leads to flakiness due to the OS prematurely killing the stream and the # Python script panicking and aborting. # The precise root cause is still nebulous, but this fix works. # See crbug.com/741194. logging.debug('Launching QEMU.') logging.debug(' '.join(qemu_command)) # Zircon sends debug logs to serial port (see kernel.serial=legacy flag # above). Serial port is redirected to a file through QEMU stdout. # This approach is used instead of loglistener to debug # https://crbug.com/86975 . if self._system_log_file: stdout = self._system_log_file stderr = subprocess.STDOUT else: stdout = open(os.devnull) stderr = sys.stderr self._qemu_process = subprocess.Popen(qemu_command, stdin=open(os.devnull), stdout=stdout, stderr=stderr) self._WaitUntilReady()