示例#1
0
def collect_logs():
    remove_old_tarballs()
    tempdir = tempfile.mkdtemp(prefix=TMPDIR_PREFIX, dir=TMPDIR)
    os.chmod(tempdir, 0o777)

    try:
        for name, path in LOG_DIRS.iteritems():
            if not os.path.exists(path):
                continue
            if os.path.isdir(path):
                shutil.copytree(path, os.path.join(tempdir, name))
            else:
                shutil.copyfile(path, os.path.join(tempdir, name))

        cmd = ['mobmoncli', 'GetStatus']
        cros_build_lib.RunCommand(cmd,
                                  log_stdout_to_file=os.path.join(
                                      tempdir, 'mobmonitor_getstatus'))
    finally:
        tarball = '%s.tgz' % tempdir
        cros_build_lib.CreateTarball(tarball, tempdir)
        osutils.RmDir(tempdir, ignore_missing=True)
    return tarball
示例#2
0
    def configure(self, args):
        """Runs the configure step of the Platform2 build.

    Creates the build root if it doesn't already exists.  Then runs the
    appropriate configure tool. Currenty only GN is supported.
    """
        assert self.can_use_gn()
        # The args was used only for gyp.
        # TODO(crbug.com/767517): remove code for handling args.
        # There is a logic to in the platform eclass file, which detects a .gyp
        # file under project root and passes it to here an arg.
        if args:
            print(
                'Warning: Args for GYP was given. We will no longer use GYP. '
                'Ignoring it and continuing configuration with GN.')

        if not os.path.isdir(self.get_buildroot()):
            os.makedirs(self.get_buildroot())

        if not self.incremental:
            osutils.RmDir(self.get_products_path(), ignore_missing=True)

        self.configure_gn()
示例#3
0
    def _ArchiveTestResults(self, test_results_dir, test_basename):
        """Archives test results to Google Storage.

    Args:
      test_results_dir: Name of the directory containing the test results.
      test_basename: The basename to archive the tests.
    """
        results_path = commands.GetTestResultsDir(self._build_root,
                                                  test_results_dir)

        # Skip archiving if results_path does not exist or is an empty directory.
        if self._NoTestResults(results_path):
            return

        archived_results_dir = os.path.join(self.archive_path, test_basename)
        # Copy relevant files to archvied_results_dir.
        commands.ArchiveTestResults(results_path, archived_results_dir)
        upload_paths = [os.path.basename(archived_results_dir)]
        # Create the compressed tarball to upload.
        # TODO: We should revisit whether uploading the tarball is necessary.
        test_tarball = commands.BuildAndArchiveTestResultsTarball(
            archived_results_dir, self._build_root)
        upload_paths.append(test_tarball)

        got_symbols = self.GetParallel('breakpad_symbols_generated',
                                       pretty_name='breakpad symbols')
        upload_paths += commands.GenerateStackTraces(self._build_root,
                                                     self._current_board,
                                                     test_results_dir,
                                                     self.archive_path,
                                                     got_symbols)

        self._Upload(upload_paths)
        self._PrintFailedTests(results_path, test_basename)

        # Remove the test results directory.
        osutils.RmDir(results_path, ignore_missing=True, sudo=True)
示例#4
0
    def _GenerateTestArtifactsInMoblabDisk(self, vms):
        """Generates test artifacts into devserver cache directory in moblab's disk.

    Args:
      vms: A moblab_vm.MoblabVm instance that has been Createed but not Started.

    Returns:
      The absolute path inside moblab VM where the image cache is located.
    """
        with vms.MountedMoblabDiskContext() as disk_dir:
            # If by any chance this path exists, the permission bits are surely
            # nonsense, since 'moblab' user doesn't exist on the host system.
            osutils.RmDir(os.path.join(disk_dir, _MOBLAB_PAYLOAD_CACHE_DIR),
                          ignore_missing=True,
                          sudo=True)
            payloads_dir = os.path.join(disk_dir, _MOBLAB_PAYLOAD_CACHE_DIR,
                                        self._SubDutTargetImage())
            # moblab VM will chown this folder upon boot, so once again permission
            # bits from the host don't matter.
            osutils.SafeMakedirsNonRoot(payloads_dir)
            target_image_path = os.path.join(self.GetImageDirSymlink(),
                                             constants.TEST_IMAGE_BIN)
            commands.GeneratePayloads(target_image_path=target_image_path,
                                      archive_dir=payloads_dir,
                                      full=True,
                                      delta=False,
                                      stateful=True)
            commands.GenerateQuickProvisionPayloads(
                target_image_path=target_image_path, archive_dir=payloads_dir)
            cwd = os.path.abspath(
                os.path.join(self._build_root, 'chroot', 'build',
                             self._current_board,
                             constants.AUTOTEST_BUILD_PATH, '..'))
            commands.BuildAutotestTarballsForHWTest(self._build_root, cwd,
                                                    payloads_dir)
        return os.path.join(_MOBLAB_STATIC_MOUNT_PATH,
                            _MOBLAB_PAYLOAD_CACHE_DIR)
示例#5
0
def CopyCorpusToSysroot(src_corpus_path):
    """Copies corpus into the sysroot.

  Copies corpus into the sysroot. Doesn't copy if corpus is already in sysroot.

  Args:
    src_corpus_path: A path (in the chroot) to a corpus that will be copied into
      sysroot.

  Returns:
    The path in the sysroot that the corpus was copied to.
  """
    if src_corpus_path is None:
        return None

    if SysrootPath.IsPathInSysroot(src_corpus_path):
        # Don't copy if |src_testcase_path| is already in sysroot. Just return it in
        # the format expected by the caller.
        return SysrootPath(src_corpus_path)

    dest_corpus_path = GetPathForCopy(CORPUS_DIRECTORY_NAME, src_corpus_path)
    osutils.RmDir(dest_corpus_path.chroot, ignore_missing=True)
    shutil.copytree(src_corpus_path, dest_corpus_path.chroot)
    return dest_corpus_path
示例#6
0
def main(argv):
    parser = GetParser()
    options = parser.parse_args(argv)

    if options.gclient == '':
        parser.error('--gclient can not be an empty string!')
    gclient_path = options.gclient or osutils.Which('gclient')
    if not gclient_path:
        gclient_path = os.path.join(constants.DEPOT_TOOLS_DIR, 'gclient')

    try:
        if options.reset:
            # Revert any lingering local changes.
            gclient.Revert(gclient_path, options.chrome_root)

        SyncChrome(gclient_path, options)
    except cros_build_lib.RunCommandError:
        # If we have an error resetting, or syncing, we clobber, and fresh sync.
        logging.warning('Chrome checkout appears corrupt. Clobbering.')
        osutils.RmDir(options.chrome_root, ignore_missing=True, sudo=True)
        osutils.SafeMakedirsNonRoot(options.chrome_root)
        SyncChrome(gclient_path, options)

    return 0
示例#7
0
def PrepareMoblabVmImageCache(vms, builder, payload_dirs):
  """Preload the given payloads into the moblab VM image cache.

  Args:
    vms (MoblabVm): The Moblab VM.
    builder (str): The builder path, used to name the cache dir.
    payload_dirs (list[str]): List of payload directories to load.

  Returns:
    str: Absolute path to the image cache path.
  """
  with vms.MountedMoblabDiskContext() as disk_dir:
    image_cache_root = os.path.join(disk_dir, 'static/prefetched')
    # If by any chance this path exists, the permission bits are surely
    # nonsense, since 'moblab' user doesn't exist on the host system.
    osutils.RmDir(image_cache_root, ignore_missing=True, sudo=True)

    image_cache_dir = os.path.join(image_cache_root, builder)
    osutils.SafeMakedirsNonRoot(image_cache_dir)
    for payload_dir in payload_dirs:
      osutils.CopyDirContents(payload_dir, image_cache_dir, allow_nonempty=True)

  image_cache_rel_dir = image_cache_dir[len(disk_dir):].strip('/')
  return os.path.join('/', 'mnt/moblab', image_cache_rel_dir)
def GenerateBreakpadSymbols(board,
                            breakpad_dir=None,
                            strip_cfi=False,
                            generate_count=None,
                            sysroot=None,
                            num_processes=None,
                            clean_breakpad=False,
                            exclude_dirs=(),
                            file_list=None):
    """Generate symbols for this board.

  If |file_list| is None, symbols are generated for all executables, otherwise
  only for the files included in |file_list|.

  TODO(build):
  This should be merged with buildbot_commands.GenerateBreakpadSymbols()
  once we rewrite cros_generate_breakpad_symbols in python.

  Args:
    board: The board whose symbols we wish to generate
    breakpad_dir: The full path to the breakpad directory where symbols live
    strip_cfi: Do not generate CFI data
    generate_count: If set, only generate this many symbols (meant for testing)
    sysroot: The root where to find the corresponding ELFs
    num_processes: Number of jobs to run in parallel
    clean_breakpad: Should we `rm -rf` the breakpad output dir first; note: we
      do not do any locking, so do not run more than one in parallel when True
    exclude_dirs: List of dirs (relative to |sysroot|) to not search
    file_list: Only generate symbols for files in this list. Each file must be a
      full path (including |sysroot| prefix).
      TODO(build): Support paths w/o |sysroot|.

  Returns:
    The number of errors that were encountered.
  """
    if breakpad_dir is None:
        breakpad_dir = FindBreakpadDir(board)
    if sysroot is None:
        sysroot = cros_build_lib.GetSysroot(board=board)
    if clean_breakpad:
        logging.info('cleaning out %s first', breakpad_dir)
        osutils.RmDir(breakpad_dir, ignore_missing=True, sudo=True)
    # Make sure non-root can write out symbols as needed.
    osutils.SafeMakedirs(breakpad_dir, sudo=True)
    if not os.access(breakpad_dir, os.W_OK):
        cros_build_lib.SudoRunCommand(
            ['chown', '-R', str(os.getuid()), breakpad_dir])
    debug_dir = FindDebugDir(board)
    exclude_paths = [os.path.join(debug_dir, x) for x in exclude_dirs]
    if file_list is None:
        file_list = []
    file_filter = dict.fromkeys([os.path.normpath(x) for x in file_list],
                                False)

    logging.info('generating breakpad symbols using %s', debug_dir)

    # Let's locate all the debug_files and elfs first along with the debug file
    # sizes.  This way we can start processing the largest files first in parallel
    # with the small ones.
    # If |file_list| was given, ignore all other files.
    targets = []
    for root, dirs, files in os.walk(debug_dir):
        if root in exclude_paths:
            logging.info('Skipping excluded dir %s', root)
            del dirs[:]
            continue

        for debug_file in files:
            debug_file = os.path.join(root, debug_file)
            # Turn /build/$BOARD/usr/lib/debug/sbin/foo.debug into
            # /build/$BOARD/sbin/foo.
            elf_file = os.path.join(sysroot, debug_file[len(debug_dir) + 1:-6])

            if file_filter:
                if elf_file in file_filter:
                    file_filter[elf_file] = True
                elif debug_file in file_filter:
                    file_filter[debug_file] = True
                else:
                    continue

            # Filter out files based on common issues with the debug file.
            if not debug_file.endswith('.debug'):
                continue

            elif debug_file.endswith('.ko.debug'):
                logging.debug('Skipping kernel module %s', debug_file)
                continue

            elif os.path.islink(debug_file):
                # The build-id stuff is common enough to filter out by default.
                if '/.build-id/' in debug_file:
                    msg = logging.debug
                else:
                    msg = logging.warning
                msg('Skipping symbolic link %s', debug_file)
                continue

            # Filter out files based on common issues with the elf file.
            if not os.path.exists(elf_file):
                # Sometimes we filter out programs from /usr/bin but leave behind
                # the .debug file.
                logging.warning('Skipping missing %s', elf_file)
                continue

            targets.append((os.path.getsize(debug_file), elf_file, debug_file))

    bg_errors = multiprocessing.Value('i')
    if file_filter:
        files_not_found = [
            x for x, found in file_filter.iteritems() if not found
        ]
        bg_errors.value += len(files_not_found)
        if files_not_found:
            logging.error('Failed to find requested files: %s',
                          files_not_found)

    # Now start generating symbols for the discovered elfs.
    with parallel.BackgroundTaskRunner(GenerateBreakpadSymbol,
                                       breakpad_dir=breakpad_dir,
                                       strip_cfi=strip_cfi,
                                       num_errors=bg_errors,
                                       processes=num_processes) as queue:
        for _, elf_file, debug_file in sorted(targets, reverse=True):
            if generate_count == 0:
                break

            queue.put([elf_file, debug_file])
            if generate_count is not None:
                generate_count -= 1
                if generate_count == 0:
                    break

    return bg_errors.value
示例#9
0
    def Build(self, commit_label):
        """Builds a Chromium for CrOS.

    If reuse_build, it first checks if the build exists. If so, uses it.
    Otherwise, it builds CrOS Chrome using SimpleChrome flow:
      http://www.chromium.org/chromium-os/how-tos-and-troubleshooting/
      building-chromium-browser
    and optionally archives the build output.

    Args:
      commit_label: Commit label used for build archive path naming.

    Returns:
      Path to build to deploy. None if it fails to build.
    """
        archive_path = os.path.join(self.archive_base,
                                    'out_%s_%s' % (self.board, commit_label),
                                    'Release')
        # See if archive build available.
        if self.reuse_build:
            if os.path.isdir(archive_path):
                logging.info('Use archive build: %s', archive_path)
                return archive_path
            else:
                logging.info('Archive build not found: %s', archive_path)

        # Build CrOS Chrome.
        logging.info('Building chromium@%s by using SimpleChrome flow',
                     commit_label)
        # Clean build.
        build_out_dir = os.path.join('out_' + self.board, 'Release')
        build_out_full_path = os.path.join(self.repo_dir, build_out_dir)
        osutils.RmDir(build_out_full_path, ignore_missing=True)

        with cros_build_lib.TimedSection() as timer:
            self.GclientSync()
            error_step = None
            result = self.chrome_sdk.Run(
                ['bash', '-c',
                 'gn gen %s --args="$GN_ARGS"' % build_out_dir],
                run_args=self.log_output_args)
            if result.returncode:
                error_step = 'gn gen'
            else:
                result = self.chrome_sdk.Ninja(
                    targets=['chrome', 'chrome_sandbox', 'nacl_helper'],
                    run_args=self.log_output_args)
                if result.returncode:
                    error_step = 'ninja'
            if error_step:
                logging.error(
                    '%s for commit %s failed. returncode %d. stderr %s',
                    error_step, commit_label, result.returncode, result.stderr)
                return None

        logging.info('Build successfully. Elapsed time: %s', timer.delta)
        if self.archive_build:
            logging.info('Archiving build from %s to %s', build_out_full_path,
                         archive_path)
            # mkdir parent of archive_path so that shutil.move can rename instead of
            # copying the 30GB build result.
            osutils.SafeMakedirs(os.path.dirname(archive_path))
            shutil.move(build_out_full_path, archive_path)
            return archive_path
        return build_out_dir
示例#10
0
def main(argv):
  conf = cros_build_lib.LoadKeyValueFile(
      os.path.join(constants.SOURCE_ROOT, constants.SDK_VERSION_FILE),
      ignore_missing=True)
  sdk_latest_version = conf.get('SDK_LATEST_VERSION', '<unknown>')
  bootstrap_latest_version = conf.get('BOOTSTRAP_LATEST_VERSION', '<unknown>')
  parser, commands = _CreateParser(sdk_latest_version, bootstrap_latest_version)
  options = parser.parse_args(argv)
  chroot_command = options.commands

  # Some sanity checks first, before we ask for sudo credentials.
  cros_build_lib.AssertOutsideChroot()

  host = os.uname()[4]
  if host != 'x86_64':
    parser.error(
        "cros_sdk is currently only supported on x86_64; you're running"
        " %s.  Please find a x86_64 machine." % (host,))

  _ReportMissing(osutils.FindMissingBinaries(NEEDED_TOOLS))
  if options.proxy_sim:
    _ReportMissing(osutils.FindMissingBinaries(PROXY_NEEDED_TOOLS))

  _ReExecuteIfNeeded([sys.argv[0]] + argv)
  if options.ns_pid:
    first_pid = namespaces.CreatePidNs()
  else:
    first_pid = None

  # Expand out the aliases...
  if options.replace:
    options.delete = options.create = True

  if options.bootstrap:
    options.create = True

  # If a command is not given, default to enter.
  # pylint: disable=protected-access
  # This _group_actions access sucks, but upstream decided to not include an
  # alternative to optparse's option_list, and this is what they recommend.
  options.enter |= not any(getattr(options, x.dest)
                           for x in commands._group_actions)
  # pylint: enable=protected-access
  options.enter |= bool(chroot_command)

  if options.enter and options.delete and not options.create:
    parser.error("Trying to enter the chroot when --delete "
                 "was specified makes no sense.")

  # Finally, discern if we need to create the chroot.
  chroot_exists = os.path.exists(options.chroot)
  if options.create or options.enter:
    # Only create if it's being wiped, or if it doesn't exist.
    if not options.delete and chroot_exists:
      options.create = False
    else:
      options.download = True

  # Finally, flip create if necessary.
  if options.enter:
    options.create |= not chroot_exists

  if not options.sdk_version:
    sdk_version = (bootstrap_latest_version if options.bootstrap
                   else sdk_latest_version)
  else:
    sdk_version = options.sdk_version
  if options.buildbot_log_version:
    logging.PrintBuildbotStepText(sdk_version)

  # Based on selections, determine the tarball to fetch.
  if options.sdk_url:
    urls = [options.sdk_url]
  elif options.bootstrap:
    urls = GetStage3Urls(sdk_version)
  else:
    urls = GetArchStageTarballs(sdk_version)

  # Get URLs for the toolchains overlay, if one is to be used.
  toolchains_overlay_urls = None
  if not options.bootstrap:
    toolchains = None
    if options.toolchains:
      toolchains = options.toolchains.split(',')
    elif options.board:
      toolchains = toolchain.GetToolchainsForBoard(options.board).keys()

    if toolchains:
      toolchains_overlay_urls = GetToolchainsOverlayUrls(sdk_version,
                                                         toolchains)

  lock_path = os.path.dirname(options.chroot)
  lock_path = os.path.join(
      lock_path, '.%s_lock' % os.path.basename(options.chroot).lstrip('.'))
  with cgroups.SimpleContainChildren('cros_sdk', pid=first_pid):
    with locking.FileLock(lock_path, 'chroot lock') as lock:
      toolchains_overlay_tarball = None

      if options.proxy_sim:
        _ProxySimSetup(options)

      if options.delete and os.path.exists(options.chroot):
        lock.write_lock()
        DeleteChroot(options.chroot)

      sdk_cache = os.path.join(options.cache_dir, 'sdks')
      distfiles_cache = os.path.join(options.cache_dir, 'distfiles')
      osutils.SafeMakedirsNonRoot(options.cache_dir)

      for target in (sdk_cache, distfiles_cache):
        src = os.path.join(constants.SOURCE_ROOT, os.path.basename(target))
        if not os.path.exists(src):
          osutils.SafeMakedirsNonRoot(target)
          continue
        lock.write_lock(
            "Upgrade to %r needed but chroot is locked; please exit "
            "all instances so this upgrade can finish." % src)
        if not os.path.exists(src):
          # Note that while waiting for the write lock, src may've vanished;
          # it's a rare race during the upgrade process that's a byproduct
          # of us avoiding taking a write lock to do the src check.  If we
          # took a write lock for that check, it would effectively limit
          # all cros_sdk for a chroot to a single instance.
          osutils.SafeMakedirsNonRoot(target)
        elif not os.path.exists(target):
          # Upgrade occurred, but a reversion, or something whacky
          # occurred writing to the old location.  Wipe and continue.
          os.rename(src, target)
        else:
          # Upgrade occurred once already, but either a reversion or
          # some before/after separate cros_sdk usage is at play.
          # Wipe and continue.
          osutils.RmDir(src)

      if options.download:
        lock.write_lock()
        sdk_tarball = FetchRemoteTarballs(
            sdk_cache, urls, 'stage3' if options.bootstrap else 'SDK')
        if toolchains_overlay_urls:
          toolchains_overlay_tarball = FetchRemoteTarballs(
              sdk_cache, toolchains_overlay_urls, 'SDK toolchains overlay',
              allow_none=True)

      if options.create:
        lock.write_lock()
        CreateChroot(options.chroot, sdk_tarball, toolchains_overlay_tarball,
                     options.cache_dir,
                     nousepkg=(options.bootstrap or options.nousepkg))

      if options.enter:
        lock.read_lock()
        EnterChroot(options.chroot, options.cache_dir, options.chrome_root,
                    options.chrome_root_mount, options.workspace,
                    chroot_command)
示例#11
0
def CreateVMImage(image=None, board=None, updatable=True, dest_dir=None):
  """Returns the path of the image built to run in a VM.

  By default, the returned VM is a test image that can run full update
  testing on it. If there exists a VM image with the matching
  |updatable| setting, this method returns the path to the existing
  image. If |dest_dir| is set, it will copy/create the VM image to the
  |dest_dir|.

  Args:
    image: Path to the (non-VM) image. Defaults to None to use the latest
      image for the board.
    board: Board that the image was built with. If None, attempts to use the
      configured default board.
    updatable: Create a VM image that supports AU.
    dest_dir: If set, create/copy the VM image to |dest|; otherwise,
      use the folder where |image| resides.
  """
  if not image and not board:
    raise VMError('Cannot create VM when both image and board are None.')

  image_dir = os.path.dirname(image)
  src_path = dest_path = os.path.join(image_dir, constants.VM_IMAGE_BIN)

  if dest_dir:
    dest_path = os.path.join(dest_dir, constants.VM_IMAGE_BIN)

  exists = False
  # Do not create a new VM image if a matching image already exists.
  exists = os.path.exists(src_path) and (
      not updatable or VMIsUpdatable(src_path))

  if exists and dest_dir:
    # Copy the existing VM image to dest_dir.
    shutil.copyfile(src_path, dest_path)

  if not exists:
    # No existing VM image that we can reuse. Create a new VM image.
    logging.info('Creating %s', dest_path)
    cmd = [os.path.join(constants.CROSUTILS_DIR, 'image_to_vm.sh'),
           '--test_image']

    if image:
      cmd.append('--from=%s' % path_util.ToChrootPath(image_dir))

    if updatable:
      cmd.extend(['--disk_layout', '2gb-rootfs-updatable'])

    if board:
      cmd.extend(['--board', board])

    # image_to_vm.sh only runs in chroot, but dest_dir may not be
    # reachable from chroot. In that case, we copy it to a temporary
    # directory in chroot, and then move it to dest_dir .
    tempdir = None
    if dest_dir:
      # Create a temporary directory in chroot to store the VM
      # image. This is to avoid the case where dest_dir is not
      # reachable within chroot.
      tempdir = cros_build_lib.run(
          ['mktemp', '-d'],
          capture_output=True,
          enter_chroot=True).output.strip()
      cmd.append('--to=%s' % tempdir)

    msg = 'Failed to create the VM image'
    try:
      cros_build_lib.run(cmd, enter_chroot=True, cwd=constants.SOURCE_ROOT)
    except cros_build_lib.RunCommandError as e:
      logging.error('%s: %s', msg, e)
      if tempdir:
        osutils.RmDir(
            path_util.FromChrootPath(tempdir), ignore_missing=True)
      raise VMError(msg)

    if dest_dir:
      # Move VM from tempdir to dest_dir.
      shutil.move(
          path_util.FromChrootPath(
              os.path.join(tempdir, constants.VM_IMAGE_BIN)), dest_path)
      osutils.RmDir(path_util.FromChrootPath(tempdir), ignore_missing=True)

  if not os.path.exists(dest_path):
    raise VMError(msg)

  return dest_path
示例#12
0
 def _RmVMDir(self):
   """Cleanup vm_dir."""
   osutils.RmDir(self.vm_dir, ignore_missing=True, sudo=self.use_sudo)
示例#13
0
def DelAUTempDirectory(host_name, pid):
    """Delete the directory including auto-update-related logs."""
    osutils.RmDir(GetAUTempDirectory(host_name, pid))
示例#14
0
 def _DeleteArchivedTrybotImages(self):
     """Clear all previous archive images to save space."""
     for trybot in (False, True):
         archive_root = self._run.GetArchive().GetLocalArchiveRoot(
             trybot=trybot)
         osutils.RmDir(archive_root, ignore_missing=True)
示例#15
0
def main(argv):
    # Turn on strict sudo checks.
    cros_build_lib.STRICT_SUDO = True
    conf = key_value_store.LoadFile(os.path.join(constants.SOURCE_ROOT,
                                                 constants.SDK_VERSION_FILE),
                                    ignore_missing=True)
    sdk_latest_version = conf.get('SDK_LATEST_VERSION', '<unknown>')
    bootstrap_frozen_version = conf.get('BOOTSTRAP_FROZEN_VERSION',
                                        '<unknown>')

    # Use latest SDK for bootstrapping if requested. Use a frozen version of SDK
    # for bootstrapping if BOOTSTRAP_FROZEN_VERSION is set.
    bootstrap_latest_version = (sdk_latest_version if bootstrap_frozen_version
                                == '<unknown>' else bootstrap_frozen_version)
    parser, commands = _CreateParser(sdk_latest_version,
                                     bootstrap_latest_version)
    options = parser.parse_args(argv)
    chroot_command = options.commands

    # Some sanity checks first, before we ask for sudo credentials.
    cros_build_lib.AssertOutsideChroot()

    host = os.uname()[4]
    if host != 'x86_64':
        cros_build_lib.Die(
            "cros_sdk is currently only supported on x86_64; you're running"
            ' %s.  Please find a x86_64 machine.' % (host, ))

    # Merge the outside PATH setting if we re-execed ourselves.
    if 'CHROMEOS_SUDO_PATH' in os.environ:
        os.environ['PATH'] = '%s:%s' % (os.environ.pop('CHROMEOS_SUDO_PATH'),
                                        os.environ['PATH'])

    _ReportMissing(osutils.FindMissingBinaries(NEEDED_TOOLS))
    if options.proxy_sim:
        _ReportMissing(osutils.FindMissingBinaries(PROXY_NEEDED_TOOLS))
    missing_image_tools = osutils.FindMissingBinaries(IMAGE_NEEDED_TOOLS)

    if (sdk_latest_version == '<unknown>'
            or bootstrap_latest_version == '<unknown>'):
        cros_build_lib.Die(
            'No SDK version was found. '
            'Are you in a Chromium source tree instead of Chromium OS?\n\n'
            'Please change to a directory inside your Chromium OS source tree\n'
            'and retry.  If you need to setup a Chromium OS source tree, see\n'
            '  https://dev.chromium.org/chromium-os/developer-guide')

    any_snapshot_operation = (options.snapshot_create
                              or options.snapshot_restore
                              or options.snapshot_delete
                              or options.snapshot_list)
    if any_snapshot_operation and not options.use_image:
        cros_build_lib.Die('Snapshot operations are not compatible with '
                           '--nouse-image.')

    if (options.snapshot_delete
            and options.snapshot_delete == options.snapshot_restore):
        parser.error('Cannot --snapshot_delete the same snapshot you are '
                     'restoring with --snapshot_restore.')

    _ReExecuteIfNeeded([sys.argv[0]] + argv)

    lock_path = os.path.dirname(options.chroot)
    lock_path = os.path.join(
        lock_path, '.%s_lock' % os.path.basename(options.chroot).lstrip('.'))

    # Expand out the aliases...
    if options.replace:
        options.delete = options.create = True

    if options.bootstrap:
        options.create = True

    # If a command is not given, default to enter.
    # pylint: disable=protected-access
    # This _group_actions access sucks, but upstream decided to not include an
    # alternative to optparse's option_list, and this is what they recommend.
    options.enter |= not any(
        getattr(options, x.dest) for x in commands._group_actions)
    # pylint: enable=protected-access
    options.enter |= bool(chroot_command)

    if (options.delete and not options.create
            and (options.enter or any_snapshot_operation)):
        parser.error('Trying to enter or snapshot the chroot when --delete '
                     'was specified makes no sense.')

    if (options.unmount
            and (options.create or options.enter or any_snapshot_operation)):
        parser.error(
            '--unmount cannot be specified with other chroot actions.')

    if options.working_dir is not None and not os.path.isabs(
            options.working_dir):
        options.working_dir = path_util.ToChrootPath(options.working_dir)

    # Discern if we need to create the chroot.
    chroot_exists = cros_sdk_lib.IsChrootReady(options.chroot)
    if (options.use_image and not chroot_exists and not options.delete
            and not options.unmount and not missing_image_tools
            and os.path.exists(_ImageFileForChroot(options.chroot))):
        # Try to re-mount an existing image in case the user has rebooted.
        with cgroups.SimpleContainChildren('cros_sdk'):
            with locking.FileLock(lock_path, 'chroot lock') as lock:
                logging.debug(
                    'Checking if existing chroot image can be mounted.')
                lock.write_lock()
                cros_sdk_lib.MountChroot(options.chroot, create=False)
                chroot_exists = cros_sdk_lib.IsChrootReady(options.chroot)
                if chroot_exists:
                    logging.notice('Mounted existing image %s on chroot',
                                   _ImageFileForChroot(options.chroot))

    # Finally, flip create if necessary.
    if options.enter or options.snapshot_create:
        options.create |= not chroot_exists

    # Make sure we will download if we plan to create.
    options.download |= options.create

    # Anything that needs to manipulate the main chroot mount or communicate with
    # LVM needs to be done here before we enter the new namespaces.

    # If deleting, do it regardless of the use_image flag so that a
    # previously-created loopback chroot can also be cleaned up.
    # TODO(bmgordon): See if the DeleteChroot call below can be removed in
    # favor of this block.
    chroot_deleted = False
    if options.delete:
        with cgroups.SimpleContainChildren('cros_sdk'):
            # Set a timeout of 300 seconds when getting the lock.
            with locking.FileLock(lock_path,
                                  'chroot lock',
                                  blocking_timeout=300) as lock:
                try:
                    lock.write_lock()
                except timeout_util.TimeoutError as e:
                    logging.error('Acquiring write_lock on %s failed: %s',
                                  lock_path, e)
                    if not options.force:
                        cros_build_lib.Die(
                            'Exiting; use --force to continue w/o lock.')
                    else:
                        logging.warning(
                            'cros_sdk was invoked with force option, continuing.'
                        )
                if missing_image_tools:
                    logging.notice('Unmounting chroot.')
                    osutils.UmountTree(options.chroot)
                else:
                    logging.notice('Deleting chroot.')
                    cros_sdk_lib.CleanupChrootMount(options.chroot,
                                                    delete=True)
                    chroot_deleted = True

    # If cleanup was requested, we have to do it while we're still in the original
    # namespace.  Since cleaning up the mount will interfere with any other
    # commands, we exit here.  The check above should have made sure that no other
    # action was requested, anyway.
    if options.unmount:
        # Set a timeout of 300 seconds when getting the lock.
        with locking.FileLock(lock_path, 'chroot lock',
                              blocking_timeout=300) as lock:
            try:
                lock.write_lock()
            except timeout_util.TimeoutError as e:
                logging.error('Acquiring write_lock on %s failed: %s',
                              lock_path, e)
                logging.warning(
                    'Continuing with CleanupChroot(%s), which will umount the tree.',
                    options.chroot)
            # We can call CleanupChroot (which calls cros_sdk_lib.CleanupChrootMount)
            # even if we don't get the lock because it will attempt to unmount the
            # tree and will print diagnostic information from 'fuser', 'lsof', and
            # 'ps'.
            CleanupChroot(options.chroot)
            sys.exit(0)

    # Make sure the main chroot mount is visible.  Contents will be filled in
    # below if needed.
    if options.create and options.use_image:
        if missing_image_tools:
            raise SystemExit("""The tool(s) %s were not found.
Please make sure the lvm2 and thin-provisioning-tools packages
are installed on your host.
Example(ubuntu):
  sudo apt-get install lvm2 thin-provisioning-tools

If you want to run without lvm2, pass --nouse-image (chroot
snapshots will be unavailable).""" % ', '.join(missing_image_tools))

        logging.debug('Making sure chroot image is mounted.')
        with cgroups.SimpleContainChildren('cros_sdk'):
            with locking.FileLock(lock_path, 'chroot lock') as lock:
                lock.write_lock()
                if not cros_sdk_lib.MountChroot(options.chroot, create=True):
                    cros_build_lib.Die('Unable to mount %s on chroot',
                                       _ImageFileForChroot(options.chroot))
                logging.notice('Mounted %s on chroot',
                               _ImageFileForChroot(options.chroot))

    # Snapshot operations will always need the VG/LV, but other actions won't.
    if any_snapshot_operation:
        with cgroups.SimpleContainChildren('cros_sdk'):
            with locking.FileLock(lock_path, 'chroot lock') as lock:
                chroot_vg, chroot_lv = cros_sdk_lib.FindChrootMountSource(
                    options.chroot)
                if not chroot_vg or not chroot_lv:
                    cros_build_lib.Die('Unable to find VG/LV for chroot %s',
                                       options.chroot)

                # Delete snapshot before creating a new one.  This allows the user to
                # throw out old state, create a new snapshot, and enter the chroot in a
                # single call to cros_sdk.  Since restore involves deleting, also do it
                # before creating.
                if options.snapshot_restore:
                    lock.write_lock()
                    valid_snapshots = ListChrootSnapshots(chroot_vg, chroot_lv)
                    if options.snapshot_restore not in valid_snapshots:
                        cros_build_lib.Die(
                            '%s is not a valid snapshot to restore to. '
                            'Valid snapshots: %s', options.snapshot_restore,
                            ', '.join(valid_snapshots))
                    osutils.UmountTree(options.chroot)
                    if not RestoreChrootSnapshot(options.snapshot_restore,
                                                 chroot_vg, chroot_lv):
                        cros_build_lib.Die(
                            'Unable to restore chroot to snapshot.')
                    if not cros_sdk_lib.MountChroot(options.chroot,
                                                    create=False):
                        cros_build_lib.Die(
                            'Unable to mount restored snapshot onto chroot.')

                # Use a read lock for snapshot delete and create even though they modify
                # the filesystem, because they don't modify the mounted chroot itself.
                # The underlying LVM commands take their own locks, so conflicting
                # concurrent operations here may crash cros_sdk, but won't corrupt the
                # chroot image.  This tradeoff seems worth it to allow snapshot
                # operations on chroots that have a process inside.
                if options.snapshot_delete:
                    lock.read_lock()
                    DeleteChrootSnapshot(options.snapshot_delete, chroot_vg,
                                         chroot_lv)

                if options.snapshot_create:
                    lock.read_lock()
                    if not CreateChrootSnapshot(options.snapshot_create,
                                                chroot_vg, chroot_lv):
                        cros_build_lib.Die('Unable to create snapshot.')

    img_path = _ImageFileForChroot(options.chroot)
    if (options.use_image and os.path.exists(options.chroot)
            and os.path.exists(img_path)):
        img_stat = os.stat(img_path)
        img_used_bytes = img_stat.st_blocks * 512

        mount_stat = os.statvfs(options.chroot)
        mount_used_bytes = mount_stat.f_frsize * (mount_stat.f_blocks -
                                                  mount_stat.f_bfree)

        extra_gbs = (img_used_bytes - mount_used_bytes) // 2**30
        if extra_gbs > MAX_UNUSED_IMAGE_GBS:
            logging.notice(
                '%s is using %s GiB more than needed.  Running '
                'fstrim.', img_path, extra_gbs)
            cmd = ['fstrim', options.chroot]
            try:
                cros_build_lib.dbg_run(cmd)
            except cros_build_lib.RunCommandError as e:
                logging.warning(
                    'Running fstrim failed. Consider running fstrim on '
                    'your chroot manually.\n%s', e)

    # Enter a new set of namespaces.  Everything after here cannot directly affect
    # the hosts's mounts or alter LVM volumes.
    namespaces.SimpleUnshare()
    if options.ns_pid:
        first_pid = namespaces.CreatePidNs()
    else:
        first_pid = None

    if options.snapshot_list:
        for snap in ListChrootSnapshots(chroot_vg, chroot_lv):
            print(snap)
        sys.exit(0)

    if not options.sdk_version:
        sdk_version = (bootstrap_latest_version
                       if options.bootstrap else sdk_latest_version)
    else:
        sdk_version = options.sdk_version
    if options.buildbot_log_version:
        logging.PrintBuildbotStepText(sdk_version)

    # Based on selections, determine the tarball to fetch.
    if options.download:
        if options.sdk_url:
            urls = [options.sdk_url]
        else:
            urls = GetArchStageTarballs(sdk_version)

    with cgroups.SimpleContainChildren('cros_sdk', pid=first_pid):
        with locking.FileLock(lock_path, 'chroot lock') as lock:
            if options.proxy_sim:
                _ProxySimSetup(options)

            if (options.delete and not chroot_deleted and
                (os.path.exists(options.chroot)
                 or os.path.exists(_ImageFileForChroot(options.chroot)))):
                lock.write_lock()
                DeleteChroot(options.chroot)

            sdk_cache = os.path.join(options.cache_dir, 'sdks')
            distfiles_cache = os.path.join(options.cache_dir, 'distfiles')
            osutils.SafeMakedirsNonRoot(options.cache_dir)

            for target in (sdk_cache, distfiles_cache):
                src = os.path.join(constants.SOURCE_ROOT,
                                   os.path.basename(target))
                if not os.path.exists(src):
                    osutils.SafeMakedirsNonRoot(target)
                    continue
                lock.write_lock(
                    'Upgrade to %r needed but chroot is locked; please exit '
                    'all instances so this upgrade can finish.' % src)
                if not os.path.exists(src):
                    # Note that while waiting for the write lock, src may've vanished;
                    # it's a rare race during the upgrade process that's a byproduct
                    # of us avoiding taking a write lock to do the src check.  If we
                    # took a write lock for that check, it would effectively limit
                    # all cros_sdk for a chroot to a single instance.
                    osutils.SafeMakedirsNonRoot(target)
                elif not os.path.exists(target):
                    # Upgrade occurred, but a reversion, or something whacky
                    # occurred writing to the old location.  Wipe and continue.
                    os.rename(src, target)
                else:
                    # Upgrade occurred once already, but either a reversion or
                    # some before/after separate cros_sdk usage is at play.
                    # Wipe and continue.
                    osutils.RmDir(src)

            if options.download:
                lock.write_lock()
                sdk_tarball = FetchRemoteTarballs(
                    sdk_cache, urls, 'stage3' if options.bootstrap else 'SDK')

            if options.create:
                lock.write_lock()
                # Recheck if the chroot is set up here before creating to make sure we
                # account for whatever the various delete/unmount/remount steps above
                # have done.
                if cros_sdk_lib.IsChrootReady(options.chroot):
                    logging.debug('Chroot already exists.  Skipping creation.')
                else:
                    CreateChroot(options.chroot,
                                 sdk_tarball,
                                 options.cache_dir,
                                 nousepkg=(options.bootstrap
                                           or options.nousepkg))

            if options.enter:
                lock.read_lock()
                EnterChroot(options.chroot, options.cache_dir,
                            options.chrome_root, options.chrome_root_mount,
                            options.goma_dir, options.goma_client_json,
                            options.working_dir, chroot_command)
示例#16
0
    def Initialize(self,
                   local_manifest=None,
                   manifest_repo_url=None,
                   extra_args=()):
        """Initializes a repository.  Optionally forces a local manifest.

    Args:
      local_manifest: The absolute path to a custom manifest to use.  This will
                      replace .repo/manifest.xml.
      manifest_repo_url: A new value for manifest_repo_url.
      extra_args: Extra args to pass to 'repo init'
    """
        if manifest_repo_url:
            self.manifest_repo_url = manifest_repo_url

        # Do a sanity check on the repo; if it exists and we can't pull a
        # manifest from it, we know it's fairly screwed up and needs a fresh
        # rebuild.
        if os.path.exists(os.path.join(self.directory, '.repo',
                                       'manifest.xml')):
            cmd = [self.repo_cmd, 'manifest']
            try:
                cros_build_lib.RunCommand(cmd,
                                          cwd=self.directory,
                                          capture_output=True)
            except cros_build_lib.RunCommandError:
                logging.warning("Wiping %r due to `repo manifest` failure",
                                self.directory)
                paths = [
                    os.path.join(self.directory, '.repo', x)
                    for x in ('manifest.xml', 'manifests.git', 'manifests',
                              'repo')
                ]
                cros_build_lib.SudoRunCommand(['rm', '-rf'] + paths)
                self._repo_update_needed = False

        # Wipe local_manifest.xml if it exists- it can interfere w/ things in
        # bad ways (duplicate projects, etc); we control this repository, thus
        # we can destroy it.
        osutils.SafeUnlink(os.path.join(self.directory, 'local_manifest.xml'))

        # Force a repo self update first; during reinit, repo doesn't do the
        # update itself, but we could be doing the init on a repo version less
        # then v1.9.4, which didn't have proper support for doing reinit that
        # involved changing the manifest branch in use; thus selfupdate.
        # Additionally, if the self update fails for *any* reason, wipe the repo
        # innards and force repo init to redownload it; same end result, just
        # less efficient.
        # Additionally, note that this method may be called multiple times;
        # thus code appropriately.
        if self._repo_update_needed:
            cmd = [self.repo_cmd, 'selfupdate']
            try:
                cros_build_lib.RunCommand(cmd, cwd=self.directory)
            except cros_build_lib.RunCommandError:
                osutils.RmDir(os.path.join(self.directory, '.repo', 'repo'),
                              ignore_missing=True)
            self._repo_update_needed = False

        # Use our own repo, in case android.kernel.org (the default location) is
        # down.
        init_cmd = [
            self.repo_cmd, 'init', '--repo-url', self.repo_url,
            '--manifest-url', self.manifest_repo_url
        ]
        if self._referenced_repo:
            init_cmd.extend(['--reference', self._referenced_repo])
        if self._manifest:
            init_cmd.extend(['--manifest-name', self._manifest])
        if self._depth is not None:
            init_cmd.extend(['--depth', str(self._depth)])
        init_cmd.extend(extra_args)
        # Handle branch / manifest options.
        if self.branch:
            init_cmd.extend(['--manifest-branch', self.branch])
        if self.repo_branch:
            init_cmd.extend(['--repo-branch', self.repo_branch])
        if self.groups:
            init_cmd.extend(['--groups', self.groups])

        cros_build_lib.RunCommand(init_cmd,
                                  cwd=self.directory,
                                  input='\n\ny\n')
        if local_manifest and local_manifest != self._manifest:
            self._SwitchToLocalManifest(local_manifest)
示例#17
0
def CleanBuildRoot(root, repo, cache_dir, build_state):
    """Some kinds of branch transitions break builds.

  This method ensures that cbuildbot's buildroot is a clean checkout on the
  given branch when it starts. If necessary (a branch transition) it will wipe
  assorted state that cannot be safely reused from the previous build.

  Args:
    root: Root directory owned by cbuildbot_launch.
    repo: repository.RepoRepository instance.
    cache_dir: Cache directory.
    build_state: BuildSummary object containing the current build state that
        will be saved into the cleaned root.  The distfiles_ts property will
        be updated if the distfiles cache is cleaned.
  """
    previous_state = GetLastBuildState(root)
    SetLastBuildState(root, build_state)
    SanitizeCacheDir(cache_dir)
    build_state.distfiles_ts = _MaybeCleanDistfiles(
        cache_dir, previous_state.distfiles_ts)

    if previous_state.buildroot_layout != BUILDROOT_BUILDROOT_LAYOUT:
        logging.PrintBuildbotStepText('Unknown layout: Wiping buildroot.')
        metrics.Counter(METRIC_CLOBBER).increment(
            fields=field({}, reason='layout_change'))
        chroot_dir = os.path.join(root, constants.DEFAULT_CHROOT_DIR)
        if os.path.exists(chroot_dir) or os.path.exists(chroot_dir + '.img'):
            cros_sdk_lib.CleanupChrootMount(chroot_dir, delete=True)
        osutils.RmDir(root, ignore_missing=True, sudo=True)
        osutils.RmDir(cache_dir, ignore_missing=True, sudo=True)
    else:
        if previous_state.branch != repo.branch:
            logging.PrintBuildbotStepText('Branch change: Cleaning buildroot.')
            logging.info('Unmatched branch: %s -> %s', previous_state.branch,
                         repo.branch)
            metrics.Counter(METRIC_BRANCH_CLEANUP).increment(
                fields=field({}, old_branch=previous_state.branch))

            logging.info('Remove Chroot.')
            chroot_dir = os.path.join(repo.directory,
                                      constants.DEFAULT_CHROOT_DIR)
            if os.path.exists(chroot_dir) or os.path.exists(chroot_dir +
                                                            '.img'):
                cros_sdk_lib.CleanupChrootMount(chroot_dir, delete=True)

            logging.info('Remove Chrome checkout.')
            osutils.RmDir(os.path.join(repo.directory, '.cache', 'distfiles'),
                          ignore_missing=True,
                          sudo=True)

    try:
        # If there is any failure doing the cleanup, wipe everything.
        # The previous run might have been killed in the middle leaving stale git
        # locks. Clean those up, first.
        repo.PreLoad()

        # If the previous build didn't exit normally, run an expensive step to
        # cleanup abandoned git locks.
        if previous_state.status not in (constants.BUILDER_STATUS_FAILED,
                                         constants.BUILDER_STATUS_PASSED):
            repo.CleanStaleLocks()

        repo.BuildRootGitCleanup(prune_all=True)
    except Exception:
        logging.info('Checkout cleanup failed, wiping buildroot:',
                     exc_info=True)
        metrics.Counter(METRIC_CLOBBER).increment(
            fields=field({}, reason='repo_cleanup_failure'))
        repository.ClearBuildRoot(repo.directory)

    # Ensure buildroot exists. Save the state we are prepped for.
    osutils.SafeMakedirs(repo.directory)
    SetLastBuildState(root, build_state)
示例#18
0
def RunTestSuite(buildroot,
                 board,
                 image_path,
                 results_dir,
                 test_config,
                 whitelist_chrome_crashes,
                 archive_dir,
                 ssh_private_key=None,
                 ssh_port=9228):
    """Runs the test harness suite."""
    results_dir_in_chroot = os.path.join(buildroot, 'chroot',
                                         results_dir.lstrip('/'))
    osutils.RmDir(results_dir_in_chroot, ignore_missing=True)

    test_type = test_config.test_type
    cwd = os.path.join(buildroot, 'src', 'scripts')
    dut_type = 'gce' if test_type == constants.GCE_SUITE_TEST_TYPE else 'vm'

    cmd = [
        'bin/ctest',
        '--board=%s' % board,
        '--type=%s' % dut_type, '--no_graphics', '--verbose',
        '--target_image=%s' % image_path,
        '--test_results_root=%s' % results_dir_in_chroot
    ]

    if test_type not in constants.VALID_VM_TEST_TYPES:
        raise AssertionError('Unrecognized test type %r' % test_type)

    if test_type == constants.FULL_AU_TEST_TYPE:
        cmd.append('--archive_dir=%s' % archive_dir)
    elif test_type in [
            constants.VM_SUITE_TEST_TYPE, constants.GCE_SUITE_TEST_TYPE
    ]:
        cmd.append('--ssh_port=%s' % ssh_port)
        cmd.append('--only_verify')
        cmd.append('--suite=%s' % test_config.test_suite)
    else:
        cmd.append('--quick_update')

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

    if ssh_private_key is not None:
        cmd.append('--ssh_private_key=%s' % ssh_private_key)

    # Give tests 10 minutes to clean up before shutting down.
    result = cros_build_lib.RunCommand(cmd,
                                       cwd=cwd,
                                       error_code_ok=True,
                                       kill_timeout=10 * 60)
    if result.returncode:
        if os.path.exists(results_dir_in_chroot):
            error = '%s exited with code %d' % (' '.join(cmd),
                                                result.returncode)
            with open(results_dir_in_chroot + '/failed_test_command',
                      'w') as failed:
                failed.write(error)

        raise failures_lib.TestFailure('** VMTests failed with code %d **' %
                                       result.returncode)
示例#19
0
def CleanupChrootMount(chroot=None,
                       buildroot=None,
                       delete=False,
                       proc_mounts='/proc/mounts'):
    """Unmounts a chroot and cleans up attached devices.

  This function attempts to perform all of the cleanup steps even if the chroot
  directory and/or image isn't present.  This ensures that a partially destroyed
  chroot can still be cleaned up.  This function does not remove the actual
  chroot directory (or its content for non-loopback chroots).

  Args:
    chroot: Full path to the chroot to examine, or None to find it relative
        to |buildroot|.
    buildroot: Ignored if |chroot| is set.  If |chroot| is None, find the chroot
        relative to |buildroot|.
    delete: Delete chroot contents and the .img file after cleaning up.  If
        |delete| is False, the chroot contents will still be present and
        can be immediately re-mounted without recreating a fresh chroot.
    proc_mounts: The path to a list of mounts to read (intended for testing).
  """
    if chroot is None and buildroot is None:
        raise ValueError('need either |chroot| or |buildroot| to search')
    if chroot is None:
        chroot = os.path.join(buildroot, constants.DEFAULT_CHROOT_DIR)
    chroot_img = chroot + '.img'

    # Try to find the VG that might already be mounted on the chroot before we
    # unmount it.
    vg_name, _ = FindChrootMountSource(chroot, proc_mounts=proc_mounts)

    try:
        osutils.UmountTree(chroot)
    except cros_build_lib.RunCommandError as e:
        # TODO(lamontjones): Dump some information to help find the process still
        # inside the chroot, causing crbug.com/923432.  In the end, this is likely
        # to become fuser -k.
        fs_debug = GetFileSystemDebug(chroot, run_ps=True)
        raise Error(
            'Umount failed: %s.\nfuser output=%s\nlsof output=%s\nps output=%s\n'
            % (e.result.error, fs_debug.fuser, fs_debug.lsof, fs_debug.ps))

    # Find the loopback device by either matching the VG or the image.
    chroot_dev = None
    if vg_name:
        cmd = [
            'vgs', '-q', '--noheadings', '-o', 'pv_name', '--unbuffered',
            vg_name
        ]
        result = cros_build_lib.sudo_run(cmd,
                                         capture_output=True,
                                         check=False,
                                         print_cmd=False,
                                         encoding='utf-8')
        if result.returncode == 0:
            chroot_dev = result.output.strip()
        else:
            vg_name = None
    if not chroot_dev:
        chroot_dev = _DeviceFromFile(chroot_img)

    # If we didn't find a mounted VG before but we did find a loopback device,
    # re-check for a VG attached to the loopback.
    if not vg_name:
        vg_name = FindVolumeGroupForDevice(chroot, chroot_dev)
        if vg_name:
            cmd = ['vgs', vg_name]
            result = cros_build_lib.sudo_run(cmd,
                                             capture_output=True,
                                             check=False,
                                             print_cmd=False,
                                             encoding='utf-8')
            if result.returncode != 0:
                vg_name = None

    # Clean up all the pieces we found above.
    if vg_name:
        cmd = ['vgchange', '-an', vg_name]
        cros_build_lib.sudo_run(cmd, capture_output=True, print_cmd=False)
    if chroot_dev:
        cmd = ['losetup', '-d', chroot_dev]
        cros_build_lib.sudo_run(cmd, capture_output=True, print_cmd=False)
    if delete:
        osutils.SafeUnlink(chroot_img)
        osutils.RmDir(chroot, ignore_missing=True, sudo=True)

    if chroot_dev:
        # Force a rescan after everything is gone to make sure lvmetad is updated.
        _RescanDeviceLvmMetadata(chroot_dev)
示例#20
0
 def Cleanup(self):
     """Remove chrome checkout."""
     osutils.RmDir(self._checkout_dir, ignore_missing=True)
示例#21
0
 def Clean(path):
     """Helper wrapper for the dry-run checks"""
     if self.options.dry_run:
         _LogClean(path)
     else:
         osutils.RmDir(path, ignore_missing=True, sudo=True)
  def PerformStage(self):
    chroot_dir = os.path.join(self._build_root, constants.DEFAULT_CHROOT_DIR)
    sdk_dir = os.path.join(chroot_dir, 'build/amd64-host')
    tmp_dir = os.path.join(chroot_dir, 'tmp')
    osutils.SafeMakedirs(tmp_dir, mode=0o777, sudo=True)
    overlay_output_dir = os.path.join(chroot_dir, constants.SDK_OVERLAYS_OUTPUT)
    osutils.RmDir(overlay_output_dir, ignore_missing=True, sudo=True)
    osutils.SafeMakedirs(overlay_output_dir, mode=0o777, sudo=True)
    overlay_tarball_template = os.path.join(
        overlay_output_dir, TOOLCHAINS_OVERLAY_TARBALL_TEMPLATE)

    # Generate an overlay tarball for each unique toolchain combination. We
    # restrict ourselves to (a) board configs that are available to the builder
    # (naturally), and (b) toolchains that are part of the 'sdk' set.
    sdk_toolchains = set(toolchain.GetToolchainsForBoard('sdk'))
    generated = set()
    for board in self._run.site_config.GetBoards():
      try:
        toolchains = set(toolchain.GetToolchainsForBoard(board).keys())
      except portage_util.MissingOverlayError:
        # The board overlay may not exist, e.g. on external builders.
        continue

      toolchains_str = '-'.join(sorted(toolchains))
      if not toolchains.issubset(sdk_toolchains) or toolchains_str in generated:
        continue

      with osutils.TempDir(
          prefix='toolchains-overlay-%s.' % toolchains_str,
          base_dir=tmp_dir,
          sudo_rm=True) as overlay_dir:
        # NOTE: We let MountOverlayContext remove the mount point created by
        # the TempDir context below, because it has built-in retries for rmdir
        # EBUSY errors that are due to unmount lag.
        with osutils.TempDir(
            prefix='amd64-host-%s.' % toolchains_str,
            base_dir=tmp_dir,
            delete=False) as merged_dir:
          with osutils.MountOverlayContext(
              sdk_dir, overlay_dir, merged_dir, cleanup=True):
            sysroot = merged_dir[len(chroot_dir):]
            cmd = [
                'cros_setup_toolchains', '--targets=boards',
                '--include-boards=%s' % board,
                '--sysroot=%s' % sysroot
            ]
            commands.RunBuildScript(
                self._build_root,
                cmd,
                chromite_cmd=True,
                enter_chroot=True,
                sudo=True,
                extra_env=self._portage_extra_env)

        # NOTE: Make sure that the overlay directory is owned root:root and has
        # 0o755 perms; apparently, these things are preserved through
        # tarring/untarring and might cause havoc if overlooked.
        os.chmod(overlay_dir, 0o755)
        cros_build_lib.sudo_run(['chown', 'root:root', overlay_dir])
        CreateTarball(overlay_dir,
                      overlay_tarball_template % {'toolchains': toolchains_str})

      generated.add(toolchains_str)
示例#23
0
 def Clean(path):
   """Helper wrapper for the dry-run checks"""
   if self.options.dry_run:
     logging.notice('would have cleaned: %s', path)
   else:
     osutils.RmDir(path, ignore_missing=True, sudo=True)
示例#24
0
def main(argv):
    options = ParseArgs(argv)

    if not cros_build_lib.IsInsideChroot():
        raise commandline.ChrootRequiredError()

    if os.geteuid() != 0:
        cros_build_lib.SudoRunCommand(sys.argv)
        return

    # sysroot must have a trailing / as the tree dictionary produced by
    # create_trees in indexed with a trailing /.
    sysroot = cros_build_lib.GetSysroot(options.board) + '/'
    trees = create_trees(target_root=sysroot, config_root=sysroot)

    vartree = trees[sysroot]['vartree']

    cache_dir = os.path.join(path_util.FindCacheDir(),
                             'cros_install_debug_syms-v' + CACHE_VERSION)

    if options.clearcache:
        osutils.RmDir(cache_dir, ignore_missing=True)

    binhost_cache = None
    if options.cachebinhost:
        binhost_cache = cache.DiskCache(cache_dir)

    boto_file = vartree.settings['BOTO_CONFIG']
    if boto_file:
        os.environ['BOTO_CONFIG'] = boto_file

    gs_context = gs.GSContext()
    symbols_mapping = RemoteSymbols(vartree, binhost_cache)

    if options.all:
        to_install = vartree.dbapi.cpv_all()
    else:
        to_install = [
            GetMatchingCPV(p, vartree.dbapi) for p in options.packages
        ]

    to_install = [
        p for p in to_install
        if ShouldGetSymbols(p, vartree.dbapi, symbols_mapping)
    ]

    if not to_install:
        logging.info('nothing to do, exit')
        return

    with DebugSymbolsInstaller(vartree, gs_context, sysroot,
                               not options.debug) as installer:
        args = [(p, symbols_mapping[p]) for p in to_install]
        parallel.RunTasksInProcessPool(installer.Install,
                                       args,
                                       processes=options.jobs)

    logging.debug('installation done, updating packages index file')
    packages_dir = os.path.join(sysroot, 'packages')
    packages_file = os.path.join(packages_dir, 'Packages')
    # binpkg will set DEBUG_SYMBOLS automatically if it detects the debug symbols
    # in the packages dir.
    pkgindex = binpkg.GrabLocalPackageIndex(packages_dir)
    with open(packages_file, 'w') as p:
        pkgindex.Write(p)
示例#25
0
 def _DeleteChromeBuildOutput(self):
     chrome_src = os.path.join(self._run.options.chrome_root, 'src')
     for out_dir in glob.glob(os.path.join(chrome_src, 'out_*')):
         osutils.RmDir(out_dir)
示例#26
0
 def Uninstall(self):
     """Removes an LLVM binary from sysroot. Undoes Install."""
     osutils.RmDir(self.install_dir, ignore_missing=True, sudo=True)
     osutils.SafeUnlink(self.binary_chroot_dest_path, sudo=True)
示例#27
0
def main(argv):
    usage = """usage: %prog [options] [VAR1=val1 .. VARn=valn -- args]

This script is used for manipulating local chroot environments; creating,
deleting, downloading, etc.  If given --enter (or no args), it defaults
to an interactive bash shell within the chroot.

If given args those are passed to the chroot environment, and executed."""
    conf = cros_build_lib.LoadKeyValueFile(os.path.join(
        constants.SOURCE_ROOT, constants.SDK_VERSION_FILE),
                                           ignore_missing=True)
    sdk_latest_version = conf.get('COREOS_SDK_VERSION', '<unknown>')

    parser = commandline.OptionParser(usage=usage, caching=True)

    commands = parser.add_option_group("Commands")
    commands.add_option('--enter',
                        action='store_true',
                        default=False,
                        help='Enter the SDK chroot.  Implies --create.')
    commands.add_option(
        '--create',
        action='store_true',
        default=False,
        help='Create the chroot only if it does not already exist.  '
        'Implies --download.')
    commands.add_option(
        '--bootstrap',
        action='store_true',
        default=False,
        help='Build everything from scratch, including the sdk.  '
        'Use this only if you need to validate a change '
        'that affects SDK creation itself (toolchain and '
        'build are typically the only folk who need this).  '
        'Note this will quite heavily slow down the build.  '
        'This option implies --create --nousepkg.')
    commands.add_option(
        '-r',
        '--replace',
        action='store_true',
        default=False,
        help='Replace an existing SDK chroot.  Basically an alias '
        'for --delete --create.')
    commands.add_option('--delete',
                        action='store_true',
                        default=False,
                        help='Delete the current SDK chroot if it exists.')
    commands.add_option('--download',
                        action='store_true',
                        default=False,
                        help='Download the sdk.')

    # Global options:
    default_chroot = os.path.join(constants.SOURCE_ROOT,
                                  constants.DEFAULT_CHROOT_DIR)
    parser.add_option('--chroot',
                      dest='chroot',
                      default=default_chroot,
                      type='path',
                      help=('SDK chroot dir name [%s]' %
                            constants.DEFAULT_CHROOT_DIR))

    parser.add_option('--chrome_root',
                      default=None,
                      type='path',
                      help='Mount this chrome root into the SDK chroot')
    parser.add_option('--chrome_root_mount',
                      default=None,
                      type='path',
                      help='Mount chrome into this path inside SDK chroot')
    parser.add_option(
        '--nousepkg',
        action='store_true',
        default=False,
        help='Do not use binary packages when creating a chroot.')
    parser.add_option('--nogetbinpkg',
                      action='store_true',
                      default=False,
                      help='Do not fetch remote binary packages.')
    parser.add_option('-u',
                      '--url',
                      dest='sdk_url',
                      default=None,
                      help=('''Use sdk tarball located at this url.
                             Use file:// for local files.'''))
    parser.add_option('--sdk-version',
                      default=sdk_latest_version,
                      help='Use this sdk version. Current is %default.')
    options, chroot_command = parser.parse_args(argv)

    # Some sanity checks first, before we ask for sudo credentials.
    cros_build_lib.AssertOutsideChroot()

    host = os.uname()[4]
    if host != 'x86_64':
        parser.error(
            "cros_sdk is currently only supported on x86_64; you're running"
            " %s.  Please find a x86_64 machine." % (host, ))

    missing = osutils.FindMissingBinaries(NEEDED_TOOLS)
    if missing:
        parser.error(
            ('The tool(s) %s were not found.\n'
             'Please install the appropriate package in your host.\n'
             'Example(ubuntu):\n'
             '  sudo apt-get install <packagename>' % (', '.join(missing))))

    _ReExecuteIfNeeded([sys.argv[0]] + argv)

    # Expand out the aliases...
    if options.replace:
        options.delete = options.create = True

    if options.bootstrap:
        options.create = True

    # If a command is not given, default to enter.
    options.enter |= not any(
        getattr(options, x.dest) for x in commands.option_list)
    options.enter |= bool(chroot_command)

    if options.enter and options.delete and not options.create:
        parser.error("Trying to enter the chroot when --delete "
                     "was specified makes no sense.")

    # Finally, discern if we need to create the chroot.
    chroot_exists = os.path.exists(options.chroot)
    if options.create or options.enter:
        # Only create if it's being wiped, or if it doesn't exist.
        if not options.delete and chroot_exists:
            options.create = False
        else:
            options.download = True

    # Finally, flip create if necessary.
    if options.enter:
        options.create |= not chroot_exists

    # Based on selections, fetch the tarball.
    if options.sdk_url:
        urls = [options.sdk_url]
    else:
        urls = GetArchStageTarballs(options.sdk_version)

    lock_path = os.path.dirname(options.chroot)
    lock_path = os.path.join(lock_path,
                             '.%s_lock' % os.path.basename(options.chroot))
    with cgroups.SimpleContainChildren('cros_sdk'):
        with locking.FileLock(lock_path, 'chroot lock') as lock:

            if options.delete and os.path.exists(options.chroot):
                lock.write_lock()
                DeleteChroot(options.chroot)

            sdk_cache = os.path.join(options.cache_dir, 'sdks')
            distfiles_cache = os.path.join(options.cache_dir, 'distfiles')
            osutils.SafeMakedirs(options.cache_dir)

            for target in (sdk_cache, distfiles_cache):
                src = os.path.join(constants.SOURCE_ROOT,
                                   os.path.basename(target))
                if not os.path.exists(src):
                    osutils.SafeMakedirs(target)
                    continue
                lock.write_lock(
                    "Upgrade to %r needed but chroot is locked; please exit "
                    "all instances so this upgrade can finish." % src)
                if not os.path.exists(src):
                    # Note that while waiting for the write lock, src may've vanished;
                    # it's a rare race during the upgrade process that's a byproduct
                    # of us avoiding taking a write lock to do the src check.  If we
                    # took a write lock for that check, it would effectively limit
                    # all cros_sdk for a chroot to a single instance.
                    osutils.SafeMakedirs(target)
                elif not os.path.exists(target):
                    # Upgrade occurred, but a reversion, or something whacky
                    # occurred writing to the old location.  Wipe and continue.
                    os.rename(src, target)
                else:
                    # Upgrade occurred once already, but either a reversion or
                    # some before/after separate cros_sdk usage is at play.
                    # Wipe and continue.
                    osutils.RmDir(src)

            if options.download:
                lock.write_lock()
                sdk_tarball = FetchRemoteTarballs(sdk_cache, urls)

            if options.create:
                lock.write_lock()
                CreateChroot(options.chroot,
                             sdk_tarball,
                             options.cache_dir,
                             nousepkg=(options.bootstrap or options.nousepkg),
                             nogetbinpkg=options.nogetbinpkg)

            if options.enter:
                lock.read_lock()
                EnterChroot(options.chroot, options.cache_dir,
                            options.chrome_root, options.chrome_root_mount,
                            chroot_command)
示例#28
0
def CleanBuildRoot(root, repo, metrics_fields, build_state):
    """Some kinds of branch transitions break builds.

  This method ensures that cbuildbot's buildroot is a clean checkout on the
  given branch when it starts. If necessary (a branch transition) it will wipe
  assorted state that cannot be safely reused from the previous build.

  Args:
    root: Root directory owned by cbuildbot_launch.
    repo: repository.RepoRepository instance.
    metrics_fields: Dictionary of fields to include in metrics.
    build_state: BuildSummary object containing the current build state that
        will be saved into the cleaned root.  The distfiles_ts property will
        be updated if the distfiles cache is cleaned.
  """
    previous_state = GetLastBuildState(root)
    build_state.distfiles_ts = _MaybeCleanDistfiles(
        repo, previous_state.distfiles_ts, metrics_fields)

    if previous_state.buildroot_layout != BUILDROOT_BUILDROOT_LAYOUT:
        logging.PrintBuildbotStepText('Unknown layout: Wiping buildroot.')
        metrics.Counter(METRIC_CLOBBER).increment(
            field(metrics_fields, reason='layout_change'))
        chroot_dir = os.path.join(root, constants.DEFAULT_CHROOT_DIR)
        if os.path.exists(chroot_dir) or os.path.exists(chroot_dir + '.img'):
            cros_sdk_lib.CleanupChrootMount(chroot_dir, delete_image=True)
        osutils.RmDir(root, ignore_missing=True, sudo=True)
    else:
        if previous_state.branch != repo.branch:
            logging.PrintBuildbotStepText('Branch change: Cleaning buildroot.')
            logging.info('Unmatched branch: %s -> %s', previous_state.branch,
                         repo.branch)
            metrics.Counter(METRIC_BRANCH_CLEANUP).increment(
                field(metrics_fields, old_branch=previous_state.branch))

            logging.info('Remove Chroot.')
            chroot_dir = os.path.join(repo.directory,
                                      constants.DEFAULT_CHROOT_DIR)
            if os.path.exists(chroot_dir) or os.path.exists(chroot_dir +
                                                            '.img'):
                cros_sdk_lib.CleanupChrootMount(chroot_dir, delete_image=True)
            osutils.RmDir(chroot_dir, ignore_missing=True, sudo=True)

            logging.info('Remove Chrome checkout.')
            osutils.RmDir(os.path.join(repo.directory, '.cache', 'distfiles'),
                          ignore_missing=True,
                          sudo=True)

        try:
            # If there is any failure doing the cleanup, wipe everything.
            repo.BuildRootGitCleanup(prune_all=True)
        except Exception:
            logging.info('Checkout cleanup failed, wiping buildroot:',
                         exc_info=True)
            metrics.Counter(METRIC_CLOBBER).increment(
                field(metrics_fields, reason='repo_cleanup_failure'))
            repository.ClearBuildRoot(repo.directory)

    # Ensure buildroot exists. Save the state we are prepped for.
    osutils.SafeMakedirs(repo.directory)
    if not build_state.distfiles_ts:
        build_state.distfiles_ts = time.time()
    SetLastBuildState(root, build_state)