Example #1
0
    def _StageOnMoblab(self, tempdir):
        """Stage the generated payloads and test bits on a moblab device.

    Args:
      tempdir: Temporary Directory that contains the generated payloads and
               test bits.
    """
        with remote_access.ChromiumOSDeviceHandler(
                self.options.remote) as device:
            device.RunCommand(['mkdir', '-p', self.stage_directory])
            for f in os.listdir(tempdir):
                device.CopyToDevice(os.path.join(tempdir, f),
                                    self.stage_directory)
            device.RunCommand(['chown', '-R', 'moblab:moblab', MOBLAB_TMP_DIR])
            # Delete this image from the Devserver in case it was previously staged.
            device.RunCommand([
                'rm', '-rf',
                os.path.join(MOBLAB_STATIC_DIR, self.staged_image_name)
            ])
            stage_url = DEVSERVER_STAGE_URL % dict(
                moblab=self.options.remote, staged_dir=self.stage_directory)
            # Stage the image from the moblab, as port 8080 might not be reachable
            # from the developer's system.
            res = device.RunCommand(
                ['curl', '--fail',
                 cros_build_lib.ShellQuote(stage_url)],
                error_code_ok=True)
            if res.returncode == 0:
                logging.info('\n\nStaging Completed!')
                logging.info('Image is staged on Moblab as %s',
                             self.staged_image_name)
            else:
                logging.info('Staging failed. Error Message: %s', res.error)

            device.RunCommand(['rm', '-rf', self.stage_directory])
  def run(self, cmd, **kwargs):
    """Executes a shell command on the device with output captured by default.

    Also sets environment variables using dictionary provided by
    keyword argument |extra_env|.

    Args:
      cmd: command to run. See RemoteAccess.RemoteSh documentation.
      **kwargs: keyword arguments to pass along with cmd. See
        RemoteAccess.RemoteSh documentation.
    """
    # Handle setting environment variables on the device by copying
    # and sourcing a temporary environment file.
    extra_env = kwargs.pop('extra_env', None)
    if extra_env:
      remote_sudo = kwargs.pop('remote_sudo', False)
      if remote_sudo and self.GetAgent().username == ROOT_ACCOUNT:
        remote_sudo = False

      new_cmd = []
      flat_vars = ['%s=%s' % (k, cros_build_lib.ShellQuote(v))
                   for k, v in extra_env.items()]

      # If the vars are too large for the command line, do it indirectly.
      # We pick 32k somewhat arbitrarily -- the kernel should accept this
      # and rarely should remote commands get near that size.
      ARG_MAX = 32 * 1024

      # What the command line would generally look like on the remote.
      if isinstance(cmd, six.string_types):
        if not kwargs.get('shell', False):
          raise ValueError("'shell' must be True when 'cmd' is a string.")
        cmdline = ' '.join(flat_vars) + ' ' + cmd
      else:
        if kwargs.get('shell', False):
          raise ValueError("'shell' must be False when 'cmd' is a list.")
        cmdline = ' '.join(flat_vars + cmd)
      if len(cmdline) > ARG_MAX:
        env_list = ['export %s' % x for x in flat_vars]
        with tempfile.NamedTemporaryFile(dir=self.tempdir.tempdir,
                                         prefix='env') as f:
          logging.debug('Environment variables: %s', ' '.join(env_list))
          osutils.WriteFile(f.name, '\n'.join(env_list))
          self.CopyToWorkDir(f.name)
          env_file = os.path.join(self.work_dir, os.path.basename(f.name))
          new_cmd += ['.', '%s;' % env_file]
          if remote_sudo:
            new_cmd += ['sudo', '-E']
      else:
        if remote_sudo:
          new_cmd += ['sudo']
        new_cmd += flat_vars

      if isinstance(cmd, six.string_types):
        cmd = ' '.join(new_cmd) + ' ' + cmd
      else:
        cmd = new_cmd + cmd

    return self.BaseRunCommand(cmd, **kwargs)
Example #3
0
  def _QuickProvision(self, device):
    """Performs a quick provision of device.

    Returns:
      A dictionary of extracted key-value pairs returned from the script
      execution.

    Raises:
      cros_build_lib.RunCommandError: error executing command or script
      remote_access.SSHConnectionError: SSH connection error
    """
    pid = os.getpid()
    pgid = os.getpgid(pid)
    if self.progress_tracker is None:
      self.progress_tracker = cros_update_progress.AUProgress(self.host_name,
                                                              pgid)

    dut_script = '/tmp/quick-provision'
    status_url = self._MakeStatusUrl(self.devserver_url, self.host_name, pgid)
    cmd = ('curl -o %s %s && bash '
           '%s --status_url %s %s %s') % (
               dut_script, os.path.join(self.static_url, 'quick-provision'),
               dut_script, cros_build_lib.ShellQuote(status_url),
               self.build_name, self.static_url,
           )
    # Quick provision script issues a reboot and might result in the SSH
    # connection being terminated so set ssh_error_ok so that output can
    # still be captured.
    results = device.RunCommand(cmd, log_output=True, capture_output=True,
                                ssh_error_ok=True, shell=True, encoding='utf-8')
    key_re = re.compile(r'^KEYVAL: ([^\d\W]\w*)=(.*)$')
    matches = [key_re.match(l) for l in results.output.splitlines()]
    keyvals = {m.group(1): m.group(2) for m in matches if m}
    logging.info('DUT returned keyvals: %s', keyvals)

    # If there was an SSH error, check the keyvals to see if it actually
    # completed and suppress the error if so.
    if results.returncode == remote_access.SSH_ERROR_CODE:
      if 'COMPLETED' in keyvals:
        logging.warning('Quick provision completed with ssh error, ignoring...')
      else:
        logging.error('Incomplete quick provision failed with ssh error')
        raise remote_access.SSHConnectionError(results.error)

    return keyvals
  def RemoteSh(self, cmd, connect_settings=None, check=True,
               remote_sudo=False, remote_user=None, ssh_error_ok=False,
               **kwargs):
    """Run a sh command on the remote device through ssh.

    Args:
      cmd: The command string or list to run. None or empty string/list will
           start an interactive session.
      connect_settings: The SSH connect settings to use.
      check: Throw an exception when the command exits with a non-zero
             returncode.  This does not cover the case where the ssh command
             itself fails (return code 255).  See ssh_error_ok.
      ssh_error_ok: Does not throw an exception when the ssh command itself
                    fails (return code 255).
      remote_sudo: If set, run the command in remote shell with sudo.
      remote_user: If set, run the command as the specified user.
      **kwargs: See cros_build_lib.run documentation.

    Returns:
      A CommandResult object.  The returncode is the returncode of the command,
      or 255 if ssh encountered an error (could not connect, connection
      interrupted, etc.)

    Raises:
      RunCommandError when error is not ignored through the check flag.
      SSHConnectionError when ssh command error is not ignored through
      the ssh_error_ok flag.
    """
    kwargs.setdefault('capture_output', True)
    kwargs.setdefault('encoding', 'utf-8')
    kwargs.setdefault('debug_level', self.debug_level)
    # Force English SSH messages. SSHConnectionError.IsKnownHostsMismatch()
    # requires English errors to detect a known_hosts key mismatch error.
    kwargs.setdefault('extra_env', {})['LC_MESSAGES'] = 'C'

    prev_user = self.username
    if remote_user:
      self.username = remote_user

    ssh_cmd = self.GetSSHCommand(connect_settings=connect_settings)

    if cmd:
      ssh_cmd.append('--')

      if remote_sudo and self.username != ROOT_ACCOUNT:
        # Prepend sudo to cmd.
        ssh_cmd.append('sudo')

      if isinstance(cmd, six.string_types):
        if kwargs.get('shell'):
          ssh_cmd = '%s %s' % (' '.join(ssh_cmd),
                               cros_build_lib.ShellQuote(cmd))
        else:
          ssh_cmd += [cmd]
      else:
        ssh_cmd += cmd

    try:
      return cros_build_lib.run(ssh_cmd, **kwargs)
    except cros_build_lib.RunCommandError as e:
      if ((e.result.returncode == SSH_ERROR_CODE and ssh_error_ok) or
          (e.result.returncode and e.result.returncode != SSH_ERROR_CODE
           and not check)):
        return e.result
      elif e.result.returncode == SSH_ERROR_CODE:
        raise SSHConnectionError(e.result.error)
      else:
        raise
    finally:
      # Restore the previous user if we temporarily changed it earlier.
      self.username = prev_user
 def testShellQuoteOjbects(self):
     """Test objects passed to ShellQuote."""
     self.assertEqual('None', cros_build_lib.ShellQuote(None))
     self.assertNotEqual('', cros_build_lib.ShellQuote(object))
 def aux(s):
     return cros_build_lib.ShellUnquote(cros_build_lib.ShellQuote(s))
Example #7
0
def main(argv):
    """Checks if a project is correctly formatted with clang-format.

  Returns 1 if there are any clang-format-worthy changes in the project (or
  on a provided list of files/directories in the project), 0 otherwise.
  """

    parser = commandline.ArgumentParser(description=__doc__)
    parser.add_argument('--clang-format',
                        default=_GetDefaultClangFormatPath(),
                        help='The path of the clang-format executable.')
    parser.add_argument('--git-clang-format',
                        default=os.path.join(BUILDTOOLS_PATH, 'clang_format',
                                             'script', 'git-clang-format'),
                        help='The path of the git-clang-format executable.')
    parser.add_argument('--style',
                        metavar='STYLE',
                        type=str,
                        default='file',
                        help='The style that clang-format will use.')
    parser.add_argument('--extensions',
                        metavar='EXTENSIONS',
                        type=str,
                        help='Comma-separated list of file extensions to '
                        'format.')
    parser.add_argument('--fix',
                        action='store_true',
                        help='Fix any formatting errors automatically.')

    scope = parser.add_mutually_exclusive_group(required=True)
    scope.add_argument('--commit',
                       type=str,
                       default='HEAD',
                       help='Specify the commit to validate.')
    scope.add_argument('--working-tree',
                       action='store_true',
                       help='Validates the files that have changed from '
                       'HEAD in the working directory.')

    parser.add_argument('files',
                        type=str,
                        nargs='*',
                        help='If specified, only consider differences in '
                        'these files/directories.')

    opts = parser.parse_args(argv)

    cmd = [opts.git_clang_format, '--binary', opts.clang_format, '--diff']
    if opts.style:
        cmd.extend(['--style', opts.style])
    if opts.extensions:
        cmd.extend(['--extensions', opts.extensions])
    if not opts.working_tree:
        cmd.extend(['%s^' % opts.commit, opts.commit])
    cmd.extend(['--'] + opts.files)

    # Fail gracefully if clang-format itself aborts/fails.
    try:
        result = cros_build_lib.RunCommand(cmd=cmd,
                                           print_cmd=False,
                                           stdout_to_pipe=True)
    except cros_build_lib.RunCommandError as e:
        print('clang-format failed:\n' + str(e), file=sys.stderr)
        print('\nPlease report this to the clang team.', file=sys.stderr)
        return 1

    stdout = result.output
    if stdout.rstrip('\n') == 'no modified files to format':
        # This is always printed when only files that clang-format does not
        # understand were modified.
        return 0

    diff_filenames = []
    for line in stdout.splitlines():
        if line.startswith(DIFF_MARKER_PREFIX):
            diff_filenames.append(line[len(DIFF_MARKER_PREFIX):].rstrip())

    if diff_filenames:
        if opts.fix:
            cros_build_lib.RunCommand(cmd=['git', 'apply'],
                                      print_cmd=False,
                                      input=stdout)
        else:
            print('The following files have formatting errors:')
            for filename in diff_filenames:
                print('\t%s' % filename)
            print('You can run `%s --fix %s` to fix this' %
                  (sys.argv[0], ' '.join(
                      cros_build_lib.ShellQuote(arg) for arg in argv)))
            return 1