Esempio n. 1
0
def RunPackage(output_dir,
               target,
               package_path,
               run_args,
               symbolizer_config=None):
    """Copies the Fuchsia package at |package_path| to the target,
  executes it with |run_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.
  run_args: The command-linearguments which will be passed to the Fuchsia process.
  symbolizer_config: A newline delimited list of source files contained in the
                     package. Omitting this parameter will disable symbolization.

  Returns the exit code of the remote package process."""

    if symbolizer_config:
        if logging.getLogger().getEffectiveLevel() == logging.DEBUG:
            logging.debug('Contents of package "%s":' %
                          os.path.basename(package_path))
            for next_line in open(symbolizer_config, 'r'):
                logging.debug('  ' + next_line.strip().split('=')[0])
            logging.debug('')

    # Deploy the package file to a unique path on the target.
    # The package's UUID length is truncated so as to not overrun the filename
    # field in the backtrace output.
    unique_package_name = 'package-%s.far' % str(uuid.uuid4())[:18]
    deployed_package_path = '/tmp/' + unique_package_name
    target.PutFile(package_path, deployed_package_path)

    try:
        command = ['run', deployed_package_path] + run_args
        process = target.RunCommandPiped(command,
                                         stdin=open(os.devnull, 'r'),
                                         stdout=subprocess.PIPE,
                                         stderr=subprocess.STDOUT)
        if symbolizer_config:
            # Decorate the process output stream with the symbolizer.
            output = FilterStream(process.stdout, unique_package_name,
                                  symbolizer_config, output_dir)
        else:
            output = process.stdout

        for next_line in output:
            print next_line

        process.wait()
        if process.returncode != 0:
            # The test runner returns an error status code if *any* tests fail,
            # so we should proceed anyway.
            logging.warning('Command exited with non-zero status code %d.' %
                            process.returncode)
    finally:
        logging.debug('Cleaning up package file.')
        target.RunCommand(['rm', deployed_package_path])

    return process.returncode
Esempio n. 2
0
def RunPackage(output_dir, target, package_path, package_name, run_args,
               symbolizer_config=None):
  """Copies the Fuchsia package at |package_path| to the target,
  executes it with |run_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.
  run_args: The arguments which will be passed to the Fuchsia process.
  symbolizer_config: A newline delimited list of source files contained
                     in the package. Omitting this parameter will disable
                     symbolization.

  Returns the exit code of the remote package process."""


  logging.debug('Copying package to target.')
  tmp_path = os.path.join('/tmp', os.path.basename(package_path))
  target.PutFile(package_path, tmp_path)

  logging.debug('Installing package.')
  p = target.RunCommandPiped(['pm', 'install', tmp_path],
                             stderr=subprocess.PIPE)
  output = p.stderr.readlines()
  p.wait()
  if p.returncode != 0:
    # Don't error out if the package already exists on the device.
    if len(output) != 1 or 'ErrAlreadyExists' not in output[0]:
      raise Exception('Error when installing package: %s' % '\n'.join(output))

  logging.debug('Running package.')
  command = ['run', package_name] + run_args
  process = target.RunCommandPiped(command,
                                   stdin=open(os.devnull, 'r'),
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.STDOUT)

  if symbolizer_config:
    # Decorate the process output stream with the symbolizer.
    output = FilterStream(process.stdout, package_name,
                          symbolizer_config, output_dir)
  else:
    logging.warn('Symbolization is DISABLED.')
    output = process.stdout

  for next_line in output:
    print next_line.strip()

  process.wait()
  if process.returncode != 0:
    # The test runner returns an error status code if *any* tests fail,
    # so we should proceed anyway.
    logging.warning('Command exited with non-zero status code %d.' %
                    process.returncode)

  return process.returncode
Esempio n. 3
0
def RunPackage(output_dir,
               target,
               package_path,
               run_args,
               symbolizer_config=None):
    """Copies the Fuchsia package at |package_path| to the target,
  executes it with |run_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.
  run_args: The command-linearguments which will be passed to the Fuchsia process.
  symbolizer_config: A newline delimited list of source files contained in the
                     package. Omitting this parameter will disable symbolization.

  Returns the exit code of the remote package process."""

    package_name = _Deploy(target, output_dir, package_path)
    command = ['run', package_name] + run_args
    process = target.RunCommandPiped(command,
                                     stdin=open(os.devnull, 'r'),
                                     stdout=subprocess.PIPE,
                                     stderr=subprocess.STDOUT)

    if symbolizer_config:
        # Decorate the process output stream with the symbolizer.
        output = FilterStream(process.stdout, package_name, symbolizer_config,
                              output_dir)
    else:
        output = process.stdout

    for next_line in output:
        print next_line

    process.wait()
    if process.returncode != 0:
        # The test runner returns an error status code if *any* tests fail,
        # so we should proceed anyway.
        logging.warning('Command exited with non-zero status code %d.' %
                        process.returncode)

    return process.returncode
Esempio n. 4
0
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
Esempio n. 5
0
def RunPackage(output_dir,
               target,
               package_path,
               package_name,
               package_deps,
               run_args,
               system_logging,
               install_only,
               symbolizer_config=None):
    """Copies the Fuchsia package at |package_path| to the target,
  executes it with |run_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.
  run_args: The arguments which will be passed to the Fuchsia process.
  system_logging: If set, connects a system log reader to the target.
  install_only: If set, skips the package execution step.
  symbolizer_config: A newline delimited list of source files contained
                     in the package. Omitting this parameter will disable
                     symbolization.

  Returns the exit code of the remote package process."""

    system_logger = _AttachKernelLogReader(target) if 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()

        for next_package_path in ([package_path] + package_deps):
            logging.info('Installing ' + os.path.basename(next_package_path) +
                         '.')

            # Copy the package archive.
            install_path = os.path.join('/data',
                                        os.path.basename(next_package_path))
            target.PutFile(next_package_path, install_path)

            # Install the package.
            p = target.RunCommandPiped(['pm', 'install', install_path],
                                       stderr=subprocess.PIPE)
            output = p.stderr.readlines()
            p.wait()
            if p.returncode != 0:
                # Don't error out if the package already exists on the device.
                if len(output) != 1 or 'ErrAlreadyExists' not in output[0]:
                    raise Exception('Error while installing: %s' %
                                    '\n'.join(output))

            # Clean up the package archive.
            target.RunCommand(['rm', install_path])

        if system_logger:
            log_output_quit_event.set()
            log_output_thread.join(timeout=_JOIN_TIMEOUT_SECS)

        if install_only:
            logging.info('Installation complete.')
            return

        logging.info('Running application.')
        command = ['run', package_name] + run_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 symbolizer_config:
            # Decorate the process output stream with the symbolizer.
            output = FilterStream(task_output, package_name, 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()

    return process.returncode