def SetupTestServer(target, test_concurrency): """Provisions a forwarding test server and configures |target| to use it. Returns a Popen object for the test server process.""" logging.debug('Starting test server.') spawning_server = chrome_test_server_spawner.SpawningServer( 0, SSHPortForwarder(target), test_concurrency) forwarded_port = common.ConnectPortForwardingTask( target, spawning_server.server_port) spawning_server.Start() logging.debug('Test server listening for connections (port=%d)' % spawning_server.server_port) logging.debug('Forwarded port is %d' % forwarded_port) config_file = tempfile.NamedTemporaryFile(delete=True) # Clean up the config JSON to only pass ports. See https://crbug.com/810209 . config_file.write(json.dumps({ 'name': 'testserver', 'address': '127.0.0.1', 'spawner_url_base': 'http://localhost:%d' % forwarded_port })) config_file.flush() target.PutFile(config_file.name, '/tmp/net-test-server-config') return spawning_server
def SetupTestServer(target, test_concurrency, for_package, for_realms=[]): """Provisions a forwarding test server and configures |target| to use it. Returns a Popen object for the test server process.""" logging.debug('Starting test server.') # The TestLauncher can launch more jobs than the limit specified with # --test-launcher-jobs so the max number of spawned test servers is set to # twice that limit here. See https://crbug.com/913156#c19. spawning_server = chrome_test_server_spawner.SpawningServer( 0, SSHPortForwarder(target), test_concurrency * 2) forwarded_port = common.ConnectPortForwardingTask( target, spawning_server.server_port) spawning_server.Start() logging.debug('Test server listening for connections (port=%d)' % spawning_server.server_port) logging.debug('Forwarded port is %d' % forwarded_port) config_file = tempfile.NamedTemporaryFile(delete=True) config_file.write( json.dumps( {'spawner_url_base': 'http://localhost:%d' % forwarded_port})) config_file.flush() target.PutFile(config_file.name, '/tmp/net-test-server-config', for_package=for_package, for_realms=for_realms) return spawning_server
def __init__(self, target): AmberRepo.__init__(self, target) self._with_count = 0 self._amber_root = tempfile.mkdtemp() pm_tool = common.GetHostToolPathFromPlatform('pm') subprocess.check_call([pm_tool, 'newrepo', '-repo', self._amber_root]) logging.info('Creating and serving temporary Amber root: {}.'.format( self._amber_root)) serve_port = common.GetAvailableTcpPort() self._pm_serve_task = subprocess.Popen([ pm_tool, 'serve', '-d', os.path.join(self._amber_root, 'repository'), '-l', ':%d' % serve_port, '-q' ]) # Block until "pm serve" starts serving HTTP traffic at |serve_port|. timeout = time.time() + _PM_SERVE_LIVENESS_TIMEOUT_SECS while True: try: urllib2.urlopen('http://localhost:%d' % serve_port, timeout=1).read() break except urllib2.URLError: logging.info('Waiting until \'pm serve\' is up...') if time.time() >= timeout: raise Exception('Timed out while waiting for \'pm serve\'.') time.sleep(1) remote_port = common.ConnectPortForwardingTask(target, serve_port, 0) self._RegisterAmberRepository(self._amber_root, remote_port)
def InstallPackage(self, package_path, package_name, package_deps): """Installs a package and it's dependencies on the device. If the package is already installed then it will be updated to the new version. package_path: Path to the .far file to be installed. package_name: Package name. package_deps: List of .far files with the packages that the main package depends on. These packages are installed or updated as well. """ try: tuf_root = tempfile.mkdtemp() pm_serve_task = None subprocess.check_call([_PM, 'newrepo', '-repo', tuf_root]) # Serve the |tuf_root| using 'pm serve' and configure the target to pull # from it. serve_port = common.GetAvailableTcpPort() pm_serve_task = subprocess.Popen([ _PM, 'serve', '-d', os.path.join(tuf_root, 'repository'), '-l', ':%d' % serve_port, '-q' ]) # Publish all packages to the serving TUF repository under |tuf_root|. all_packages = [package_path] + package_deps for next_package_path in all_packages: _PublishPackage(tuf_root, next_package_path) _WaitForPmServeToBeReady(serve_port) remote_port = common.ConnectPortForwardingTask(self, serve_port, 0) self._RegisterAmberRepository(tuf_root, remote_port) # Install all packages. for next_package_path in all_packages: install_package_name, package_version = \ _GetPackageInfo(next_package_path) logging.info('Installing %s version %s.' % (install_package_name, package_version)) return_code = self.RunCommand( [ 'amberctl', 'get_up', '-n', install_package_name, '-v', package_version ], timeout_secs=_INSTALL_TIMEOUT_SECS) if return_code != 0: raise Exception('Error while installing %s.' % install_package_name) finally: self._UnregisterAmberRepository() if pm_serve_task: pm_serve_task.kill() shutil.rmtree(tuf_root)
def __init__(self, target): super(ManagedPkgRepo, self).__init__() self._with_count = 0 self._target = target self._pkg_root = tempfile.mkdtemp() pm_tool = common.GetHostToolPathFromPlatform('pm') subprocess.check_call([pm_tool, 'newrepo', '-repo', self._pkg_root]) logging.debug( 'Creating and serving temporary package root: {}.'.format( self._pkg_root)) with tempfile.NamedTemporaryFile() as pm_port_file: # Flags for `pm serve`: # https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/src/sys/pkg/bin/pm/cmd/pm/serve/serve.go self._pm_serve_task = subprocess.Popen([ pm_tool, 'serve', '-d', os.path.join(self._pkg_root, 'repository'), '-c', '2', # Use config.json format v2, the default for pkgctl. '-q', # Don't log transfer activity. '-l', ':0', # Bind to ephemeral port. '-f', pm_port_file.name # Publish port number to |pm_port_file|. ]) # Busywait until 'pm serve' starts the server and publishes its port to # a temporary file. timeout = time.time() + _PM_SERVE_LISTEN_TIMEOUT_SECS serve_port = None while not serve_port: if time.time() > timeout: raise Exception( 'Timeout waiting for \'pm serve\' to publish its port.' ) with open(pm_port_file.name, 'r', encoding='utf8') as serve_port_file: serve_port = serve_port_file.read() time.sleep(_PM_SERVE_POLL_INTERVAL) serve_port = int(serve_port) logging.debug('pm serve is active on port {}.'.format(serve_port)) remote_port = common.ConnectPortForwardingTask(target, serve_port, 0) self._RegisterPkgRepository(self._pkg_root, remote_port)
def RunPackage(output_dir, target, package_path, package_name, package_deps, package_args, args): """Copies the Fuchsia package at |package_path| to the target, executes it with |package_args|, and symbolizes its output. output_dir: The path containing the build output files. target: The deployment Target object that will run the package. package_path: The path to the .far package file. package_name: The name of app specified by package metadata. package_args: The arguments which will be passed to the Fuchsia process. args: Structure of arguments to configure how the package will be run. Returns the exit code of the remote package process.""" system_logger = (_AttachKernelLogReader(target) if args.system_logging else None) try: if system_logger: # Spin up a thread to asynchronously dump the system log to stdout # for easier diagnoses of early, pre-execution failures. log_output_quit_event = multiprocessing.Event() log_output_thread = threading.Thread( target=lambda: _DrainStreamToStdout(system_logger.stdout, log_output_quit_event)) log_output_thread.daemon = True log_output_thread.start() tuf_root = tempfile.mkdtemp() pm_serve_task = None # Publish all packages to the serving TUF repository under |tuf_root|. subprocess.check_call([PM, 'newrepo', '-repo', tuf_root]) all_packages = [package_path] + package_deps for next_package_path in all_packages: PublishPackage(tuf_root, next_package_path) # Serve the |tuf_root| using 'pm serve' and configure the target to pull # from it. # TODO(kmarshall): Use -q to suppress pm serve output once blob push # is confirmed to be running stably on bots. serve_port = common.GetAvailableTcpPort() pm_serve_task = subprocess.Popen([ PM, 'serve', '-d', os.path.join(tuf_root, 'repository'), '-l', ':%d' % serve_port, '-q' ]) remote_port = common.ConnectPortForwardingTask(target, serve_port, 0) _RegisterAmberRepository(target, tuf_root, remote_port) # Install all packages. for next_package_path in all_packages: install_package_name, package_version = GetPackageInfo( next_package_path) logging.info('Installing %s version %s.' % (install_package_name, package_version)) return_code = target.RunCommand([ 'amber_ctl', 'get_up', '-n', install_package_name, '-v', package_version ]) if return_code != 0: raise Exception('Error while installing %s.' % install_package_name) if system_logger: log_output_quit_event.set() log_output_thread.join(timeout=_JOIN_TIMEOUT_SECS) if args.install_only: logging.info('Installation complete.') return logging.info('Running application.') command = ['run', _GetComponentUri(package_name)] + package_args process = target.RunCommandPiped(command, stdin=open(os.devnull, 'r'), stdout=subprocess.PIPE, stderr=subprocess.STDOUT) if system_logger: task_output = _ReadMergedLines( [process.stdout, system_logger.stdout]) else: task_output = process.stdout if args.symbolizer_config: # Decorate the process output stream with the symbolizer. output = FilterStream(task_output, package_name, args.symbolizer_config, output_dir) else: logging.warn('Symbolization is DISABLED.') output = process.stdout for next_line in output: print next_line.rstrip() process.wait() if process.returncode == 0: logging.info('Process exited normally with status code 0.') else: # The test runner returns an error status code if *any* tests fail, # so we should proceed anyway. logging.warning('Process exited with status code %d.' % process.returncode) finally: if system_logger: logging.info('Terminating kernel log reader.') log_output_quit_event.set() log_output_thread.join() system_logger.kill() _UnregisterAmberRepository(target) if pm_serve_task: pm_serve_task.kill() shutil.rmtree(tuf_root) return process.returncode
def Map(self, port_pairs): for p in port_pairs: _, host_port = p self._port_mapping[host_port] = \ common.ConnectPortForwardingTask(self._target, host_port)