# -*- coding: utf-8 -*-
# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Module containing stages that generate and/or archive artifacts."""

from __future__ import print_function

import datetime
import glob
import itertools
import json
import multiprocessing
import re
import os
import shutil

from chromite.cbuildbot import commands
from chromite.lib import failures_lib
from chromite.lib import config_lib
from chromite.lib import constants
from chromite.cbuildbot import prebuilts
from chromite.cbuildbot.stages import generic_stages
from chromite.lib import cros_build_lib
from chromite.lib import cros_logging as logging
from chromite.lib import gs
from chromite.lib import osutils
from chromite.lib import parallel
from chromite.lib import path_util
from chromite.lib import pformat
from chromite.lib import portage_util

_FULL_BINHOST = 'FULL_BINHOST'
_PORTAGE_BINHOST = 'PORTAGE_BINHOST'


class DebugSymbolsUploadException(Exception):
  """Thrown if DebugSymbols fails during upload."""


class NothingToArchiveException(Exception):
  """Thrown if ArchiveStage found nothing to archive."""

  # We duplicate __init__ to specify a default for message.
  # pylint: disable=useless-super-delegation
  def __init__(self, message='No images found to archive.'):
    super(NothingToArchiveException, self).__init__(message)


class ArchiveStage(generic_stages.BoardSpecificBuilderStage,
                   generic_stages.ArchivingStageMixin):
  """Archives build and test artifacts for developer consumption.

  Attributes:
    release_tag: The release tag. E.g. 2981.0.0
    version: The full version string, including the milestone.
        E.g. R26-2981.0.0-b123
  """

  option_name = 'archive'
  config_name = 'archive'
  category = constants.CI_INFRA_STAGE

  # This stage is intended to run in the background, in parallel with tests.
  def __init__(self,
               builder_run,
               buildstore,
               board,
               chrome_version=None,
               **kwargs):
    super(ArchiveStage, self).__init__(builder_run, buildstore, board, **kwargs)
    self.chrome_version = chrome_version

    # TODO(mtennant): Places that use this release_tag attribute should
    # move to use self._run.attrs.release_tag directly.
    self.release_tag = getattr(self._run.attrs, 'release_tag', None)

    self._recovery_image_status_queue = multiprocessing.Queue()
    self._release_upload_queue = multiprocessing.Queue()
    self._upload_queue = multiprocessing.Queue()
    self.artifacts = []

  def WaitForRecoveryImage(self):
    """Wait until artifacts needed by SignerTest stage are created.

    Returns:
      True if artifacts created successfully.
      False otherwise.
    """
    logging.info('Waiting for recovery image...')
    status = self._recovery_image_status_queue.get()
    # Put the status back so other SignerTestStage instances don't starve.
    self._recovery_image_status_queue.put(status)
    return status

  def ArchiveStrippedPackages(self):
    """Generate and archive stripped versions of packages requested."""
    tarball = commands.BuildStrippedPackagesTarball(
        self._build_root, self._current_board,
        self._run.config.upload_stripped_packages, self.archive_path)
    if tarball is not None:
      self._upload_queue.put([tarball])

  def LoadArtifactsList(self, board, image_dir):
    """Load the list of artifacts to upload for this board.

    It attempts to load a JSON file, scripts/artifacts.json, from the
    overlay directories for this board. This file specifies the artifacts
    to generate, if it can't be found, it will use a default set that
    uploads every .bin file as a .tar.xz file.

    See BuildStandaloneArchive in cbuildbot_commands.py for format docs.
    """
    custom_artifacts_file = portage_util.ReadOverlayFile(
        'scripts/artifacts.json', board=board)
    artifacts = None

    if custom_artifacts_file is not None:
      json_file = json.loads(custom_artifacts_file)
      artifacts = json_file.get('artifacts')

    if artifacts is None:
      artifacts = []
      for image_file in glob.glob(os.path.join(image_dir, '*.bin')):
        basename = os.path.basename(image_file)
        info = {'input': [basename], 'archive': 'tar', 'compress': 'xz'}
        artifacts.append(info)
      # We add the dlc folder (if exists) as artifact so we can copy all DLC
      # artifacts as is.
      if os.path.isdir(os.path.join(image_dir, 'dlc')):
        artifacts.append({'input': ['dlc']})

    for artifact in artifacts:
      # Resolve the (possible) globs in the input list, and store
      # the actual set of files to use in 'paths'
      paths = []
      for s in artifact['input']:
        glob_paths = glob.glob(os.path.join(image_dir, s))
        if not glob_paths:
          logging.warning('No artifacts generated for input: %s', s)
        else:
          for path in glob_paths:
            paths.append(os.path.relpath(path, image_dir))
      artifact['paths'] = paths
    self.artifacts = artifacts

  def IsArchivedFile(self, filename):
    """Return True if filename is the name of a file being archived."""
    for artifact in self.artifacts:
      for path in itertools.chain(artifact['paths'], artifact['input']):
        if os.path.basename(path) == filename:
          return True
    return False

  def PerformStage(self):
    buildroot = self._build_root
    config = self._run.config
    board = self._current_board
    debug = self._run.options.debug_forced
    upload_url = self.upload_url
    archive_path = self.archive_path
    image_dir = self.GetImageDirSymlink()

    extra_env = {}
    if config['useflags']:
      extra_env['USE'] = ' '.join(config['useflags'])

    if not archive_path:
      raise NothingToArchiveException()

    # The following functions are run in parallel (except where indicated
    # otherwise)
    # \- BuildAndArchiveArtifacts
    #    \- ArchiveReleaseArtifacts
    #       \- ArchiveFirmwareImages
    #       \- BuildAndArchiveAllImages
    #          (builds recovery image first, then launches functions below)
    #          \- BuildAndArchiveFactoryImages
    #          \- ArchiveStandaloneArtifacts
    #             \- ArchiveStandaloneArtifact
    #          \- ArchiveZipFiles
    #          \- ArchiveHWQual
    #          \- ArchiveLicenseFile
    #       \- PushImage (blocks on BuildAndArchiveAllImages)
    #    \- ArchiveManifest
    #    \- ArchiveStrippedPackages
    #    \- ArchiveImageScripts
    #    \- ArchiveEbuildLogs

    def ArchiveManifest():
      """Create manifest.xml snapshot of the built code."""
      output_manifest = os.path.join(archive_path, 'manifest.xml')
      cmd = ['repo', 'manifest', '-r', '-o', output_manifest]
      cros_build_lib.run(cmd, cwd=buildroot, capture_output=True)
      self._upload_queue.put(['manifest.xml'])

    def BuildAndArchiveFactoryImages():
      """Build and archive the factory zip file.

      The factory zip file consists of the factory toolkit and the factory
      install image. Both are built here.
      """
      # Build factory install image and create a symlink to it.
      factory_install_symlink = None
      if 'factory_install' in config['images']:
        logging.info('Running commands.BuildFactoryInstallImage')
        alias = commands.BuildFactoryInstallImage(buildroot, board, extra_env)
        factory_install_symlink = self.GetImageDirSymlink(alias)
        if config['factory_install_netboot']:
          logging.info('Running commands.MakeNetboot')
          commands.MakeNetboot(buildroot, board, factory_install_symlink)

      # Build and upload factory zip if needed.
      if factory_install_symlink or config['factory_toolkit']:
        logging.info('Running commands.BuildFactoryZip')
        filename = commands.BuildFactoryZip(buildroot, board, archive_path,
                                            factory_install_symlink,
                                            self._run.attrs.release_tag)
        self._release_upload_queue.put([filename])

    def ArchiveStandaloneArtifact(artifact_info):
      """Build and upload a single archive."""
      if artifact_info['paths']:
        logging.info('Running commands.BuildStandaloneArchive')
        for path in commands.BuildStandaloneArchive(archive_path, image_dir,
                                                    artifact_info):
          self._release_upload_queue.put([path])

    def ArchiveStandaloneArtifacts():
      """Build and upload standalone archives for each image."""
      if config['upload_standalone_images']:
        parallel.RunTasksInProcessPool(ArchiveStandaloneArtifact,
                                       [[x] for x in self.artifacts])

    def ArchiveEbuildLogs():
      """Tar and archive Ebuild logs.

      This includes all the files in /build/$BOARD/tmp/portage/logs.
      """
      logging.info('Running commands.BuildEbuildLogsTarball')
      tarpath = commands.BuildEbuildLogsTarball(
          self._build_root, self._current_board, self.archive_path)
      if tarpath is not None:
        self._upload_queue.put([tarpath])

    def ArchiveZipFiles():
      """Build and archive zip files.

      This includes:
        - image.zip (all images in one big zip file)
      """
      # Zip up everything in the image directory.
      logging.info('Running commands.BuildImageZip')
      image_zip = commands.BuildImageZip(archive_path, image_dir)
      self._release_upload_queue.put([image_zip])

    def ArchiveHWQual():
      """Build and archive the HWQual images."""
      # TODO(petermayo): This logic needs to be exported from the BuildTargets
      # stage rather than copied/re-evaluated here.
      # TODO(mtennant): Make this autotest_built concept into a run param.
      autotest_built = (
          self._run.options.tests and config['upload_hw_test_artifacts'])

      if config['hwqual'] and autotest_built:
        # Build the full autotest tarball for hwqual image. We don't upload it,
        # as it's fairly large and only needed by the hwqual tarball.
        logging.info('Archiving full autotest tarball locally ...')
        logging.info('Running commands.BuildFullAutotestTarball')
        tarball = commands.BuildFullAutotestTarball(
            self._build_root, self._current_board, image_dir)
        self.board_runattrs.SetParallel('autotest_tarball_generated', True)
        logging.info('Running commands.ArchiveFile')
        commands.ArchiveFile(tarball, archive_path)

        # Build hwqual image and upload to Google Storage.
        hwqual_name = 'chromeos-hwqual-%s-%s' % (board, self.version)
        logging.info('Running commands.ArchiveHWQual')
        filename = commands.ArchiveHWQual(buildroot, hwqual_name, archive_path,
                                          image_dir)
        self._release_upload_queue.put([filename])
      else:
        self.board_runattrs.SetParallel('autotest_tarball_generated', True)

    def ArchiveLicenseFile():
      """Archive licensing file."""
      filename = 'license_credits.html'
      filepath = os.path.join(image_dir, filename)
      if os.path.isfile(filepath):
        shutil.copy(filepath, archive_path)
        self._release_upload_queue.put([filename])

    def ArchiveFirmwareImages():
      """Archive firmware images built from source if available."""
      logging.info('Running commands.BuildFirmwareArchive')
      archive = commands.BuildFirmwareArchive(buildroot, board, archive_path)
      if archive:
        self._release_upload_queue.put([archive])

    def BuildAndArchiveAllImages():
      # Generate the recovery image. To conserve loop devices, we try to only
      # run one instance of build_image at a time. TODO(davidjames): Move the
      # image generation out of the archive stage.
      self.LoadArtifactsList(self._current_board, image_dir)

      # If there's no plan to run ArchiveHWQual, VMTest should start asap.
      if not config['images']:
        self.board_runattrs.SetParallel('autotest_tarball_generated', True)

      # For recovery image to be generated correctly, BuildRecoveryImage must
      # run before BuildAndArchiveFactoryImages.
      if 'recovery' in config.images:
        assert os.path.isfile(os.path.join(image_dir, constants.BASE_IMAGE_BIN))
        logging.info('Running commands.BuildRecoveryImage')
        commands.BuildRecoveryImage(buildroot, board, image_dir, extra_env)
        self._recovery_image_status_queue.put(True)
        recovery_image = constants.RECOVERY_IMAGE_BIN
        if not self.IsArchivedFile(recovery_image):
          info = {
              'paths': [recovery_image],
              'input': [recovery_image],
              'archive': 'tar',
              'compress': 'xz'
          }
          self.artifacts.append(info)
      else:
        self._recovery_image_status_queue.put(False)

      if config['images']:
        steps = [
            BuildAndArchiveFactoryImages,
            ArchiveLicenseFile,
            ArchiveHWQual,
            ArchiveStandaloneArtifacts,
            ArchiveZipFiles,
        ]
        parallel.RunParallelSteps(steps)

    def ArchiveImageScripts():
      """Archive tarball of generated image manipulation scripts."""
      target = os.path.join(archive_path, constants.IMAGE_SCRIPTS_TAR)
      files = glob.glob(os.path.join(image_dir, '*.sh'))
      files = [os.path.basename(f) for f in files]
      cros_build_lib.CreateTarball(target, image_dir, inputs=files)
      self._upload_queue.put([constants.IMAGE_SCRIPTS_TAR])

    def PushImage():
      # This helper script is only available on internal manifests currently.
      if not config['internal']:
        return

      self.GetParallel('debug_tarball_generated', pretty_name='debug tarball')

      # Needed for stateful.tgz
      self.GetParallel('test_artifacts_uploaded', pretty_name='test artifacts')

      # Now that all data has been generated, we can upload the final result to
      # the image server.
      # TODO: When we support branches fully, the friendly name of the branch
      # needs to be used with PushImages
      sign_types = []
      if config['sign_types']:
        sign_types = config['sign_types']
      logging.info('Running commands.PushImages')
      urls = commands.PushImages(
          board=board,
          archive_url=upload_url,
          dryrun=debug or not config['push_image'],
          profile=self._run.options.profile or config['profile'],
          sign_types=sign_types)
      self.board_runattrs.SetParallel('instruction_urls_per_channel', urls)

    def ArchiveReleaseArtifacts():
      with self.ArtifactUploader(self._release_upload_queue, archive=False):
        steps = [BuildAndArchiveAllImages, ArchiveFirmwareImages]
        parallel.RunParallelSteps(steps)
      PushImage()

    def BuildAndArchiveArtifacts():
      # Run archiving steps in parallel.
      steps = [
          ArchiveReleaseArtifacts, ArchiveManifest,
          self.ArchiveStrippedPackages, ArchiveEbuildLogs
      ]
      if config['images']:
        steps.append(ArchiveImageScripts)

      with self.ArtifactUploader(self._upload_queue, archive=False):
        parallel.RunParallelSteps(steps)

      # Make sure no stage posted to the release queue when it should have used
      # the normal upload queue.  The release queue is processed in parallel and
      # then ignored, so there shouldn't be any items left in here.
      assert self._release_upload_queue.empty()

    if not self._run.config.afdo_generate_min:
      BuildAndArchiveArtifacts()
    self.board_runattrs.SetParallel('autotest_tarball_generated', True)

  def HandleSkip(self):
    """Tell other stages to not wait on us if we are skipped."""
    self.board_runattrs.SetParallel('autotest_tarball_generated', True)
    return super(ArchiveStage, self).HandleSkip()

  def _HandleStageException(self, exc_info):
    # Tell the HWTestStage not to wait for artifacts to be uploaded
    # in case ArchiveStage throws an exception.
    self._recovery_image_status_queue.put(False)
    self.board_runattrs.SetParallel('instruction_urls_per_channel', None)
    self.board_runattrs.SetParallel('autotest_tarball_generated', True)
    return super(ArchiveStage, self)._HandleStageException(exc_info)


class CPEExportStage(generic_stages.BoardSpecificBuilderStage,
                     generic_stages.ArchivingStageMixin):
  """Handles generation & upload of package CPE information."""

  config_name = 'cpe_export'
  category = constants.CI_INFRA_STAGE

  @failures_lib.SetFailureType(failures_lib.InfrastructureFailure)
  def PerformStage(self):
    """Generate and upload CPE files."""
    buildroot = self._build_root
    board = self._current_board
    useflags = self._run.config.useflags

    logging.info('Generating CPE export.')
    result = commands.GenerateCPEExport(buildroot, board, useflags)

    logging.info('Writing CPE export to files for archive.')
    warnings_filename = os.path.join(self.archive_path,
                                     'cpe-warnings-chromeos-%s.txt' % board)
    results_filename = os.path.join(self.archive_path,
                                    'cpe-chromeos-%s.json' % board)

    osutils.WriteFile(warnings_filename, result.error)
    osutils.WriteFile(results_filename, result.output)

    logging.info('Uploading CPE files.')
    self.UploadArtifact(os.path.basename(warnings_filename), archive=False)
    self.UploadArtifact(os.path.basename(results_filename), archive=False)


class BuildConfigsExportStage(generic_stages.BoardSpecificBuilderStage,
                              generic_stages.ArchivingStageMixin):
  """Handles generation & upload of build related configs.

  NOTES: this is an ephemeral stage just to gather build config data for
    crbug.com/974795 and will be removed once that project finished.
  """
  config_name = 'run_build_configs_export'
  category = constants.CI_INFRA_STAGE

  @failures_lib.SetFailureType(failures_lib.InfrastructureFailure)
  def PerformStage(self):
    """Generate and upload build configs.

    The build config includes config.yaml (for unibuild) and USE flags.
    """
    board = self._current_board
    config_useflags = self._run.config.useflags

    logging.info('Generating build configs.')
    results = commands.GenerateBuildConfigs(board, config_useflags)

    results_str = pformat.json(results)
    logging.info('Results:\n%s', results_str)

    logging.info('Writing build configs to files for archive.')
    results_filename = os.path.join(self.archive_path,
                                    'chromeos-build-configs-%s.json' % board)

    osutils.WriteFile(results_filename, results_str)

    logging.info('Uploading build config files.')
    self.UploadArtifact(os.path.basename(results_filename), archive=False)


class DebugSymbolsStage(generic_stages.BoardSpecificBuilderStage,
                        generic_stages.ArchivingStageMixin):
  """Handles generation & upload of debug symbols."""

  config_name = 'debug_symbols'
  category = constants.PRODUCT_OS_STAGE

  @failures_lib.SetFailureType(failures_lib.InfrastructureFailure)
  def PerformStage(self):
    """Generate debug symbols and upload debug.tgz."""
    buildroot = self._build_root
    board = self._current_board
    dryrun = self._run.config.basic_builder

    # Generate breakpad symbols of Chrome OS binaries.
    commands.GenerateBreakpadSymbols(buildroot, board,
                                     self._run.options.debug_forced)

    # Generate breakpad symbols of Android binaries if we have a symbol archive.
    # This archive is created by AndroidDebugSymbolsStage in Android PFQ.
    # This must be done after GenerateBreakpadSymbols because it clobbers the
    # output directory.
    symbols_file = os.path.join(self.archive_path,
                                constants.ANDROID_SYMBOLS_FILE)
    if os.path.exists(symbols_file):
      commands.GenerateAndroidBreakpadSymbols(buildroot, board, symbols_file)

    self.board_runattrs.SetParallel('breakpad_symbols_generated', True)

    # Upload them.
    self.GenerateDebugTarball(upload=not dryrun)

    # Upload debug/breakpad tarball.
    self.GenerateDebugBreakpadTarball(upload=not dryrun)

    # Upload them to crash server.
    if self._run.config.upload_symbols and not dryrun:
      self.UploadSymbols(buildroot, board)

    self.board_runattrs.SetParallel('debug_symbols_completed', True)

  def GenerateDebugTarball(self, upload=True):
    """Generate and upload the debug tarball.

    Args:
      upload: Boolean indicating whether to upload the generated debug tarball.
    """
    filename = commands.GenerateDebugTarball(
        self._build_root, self._current_board, self.archive_path,
        self._run.config.archive_build_debug)
    if upload:
      self.UploadArtifact(filename, archive=False)
    else:
      logging.info('DebugSymbolsStage dryrun: would have uploaded %s', filename)
    logging.info('Announcing availability of debug tarball now.')
    self.board_runattrs.SetParallel('debug_tarball_generated', True)

  def GenerateDebugBreakpadTarball(self, upload=True):
    """Generate and upload the debug tarball with only breakpad files.

    Args:
      upload: Boolean indicating whether to upload the generated debug tarball.
    """
    filename = commands.GenerateDebugTarball(
        self._build_root,
        self._current_board,
        self.archive_path,
        False,
        archive_name='debug_breakpad.tar.xz')
    if upload:
      self.UploadArtifact(filename, archive=False)
    else:
      logging.info('DebugSymbolsStage dryrun: would have uploaded %s', filename)

  def UploadSymbols(self, buildroot, board):
    """Upload generated debug symbols."""
    failed_name = 'failed_upload_symbols.list'
    failed_list = os.path.join(self.archive_path, failed_name)

    if self._run.options.remote_trybot or self._run.options.debug_forced:
      # For debug builds, limit ourselves to just uploading 1 symbol.
      # This way trybots and such still exercise this code.
      cnt = 1
      official = False
    else:
      cnt = None
      official = self._run.config.chromeos_official

    upload_passed = True
    try:
      commands.UploadSymbols(buildroot, board, official, cnt, failed_list)
    except failures_lib.BuildScriptFailure:
      upload_passed = False

    if os.path.exists(failed_list):
      self.UploadArtifact(failed_name, archive=False)

      logging.notice('To upload the missing symbols from this build, run:')
      for url in self._GetUploadUrls(filename=failed_name):
        logging.notice('upload_symbols --failed-list %s %s',
                       os.path.join(url, failed_name),
                       os.path.join(url, 'debug_breakpad.tar.xz'))

    # Delay throwing the exception until after we uploaded the list.
    if not upload_passed:
      raise DebugSymbolsUploadException('Failed to upload all symbols.')

  def _SymbolsNotGenerated(self):
    """Tell other stages that our symbols were not generated."""
    self.board_runattrs.SetParallelDefault('breakpad_symbols_generated', False)
    self.board_runattrs.SetParallelDefault('debug_tarball_generated', False)

  def HandleSkip(self):
    """Tell other stages to not wait on us if we are skipped."""
    self._SymbolsNotGenerated()
    self.board_runattrs.SetParallel('debug_symbols_completed', True)
    return super(DebugSymbolsStage, self).HandleSkip()

  def _HandleStageException(self, exc_info):
    """Tell other stages to not wait on us if we die for some reason."""
    self._SymbolsNotGenerated()
    self.board_runattrs.SetParallel('debug_symbols_completed', True)

    # TODO(dgarrett): Get failures tracked in metrics (crbug.com/652463).
    exc_type, e, _ = exc_info
    if (issubclass(exc_type, DebugSymbolsUploadException) or
        (isinstance(e, failures_lib.CompoundFailure) and
         e.MatchesFailureType(DebugSymbolsUploadException))):
      return self._HandleExceptionAsWarning(exc_info)

    return super(DebugSymbolsStage, self)._HandleStageException(exc_info)


class UploadPrebuiltsStage(generic_stages.BoardSpecificBuilderStage):
  """Uploads binaries generated by this build for developer use."""

  option_name = 'prebuilts'
  config_name = 'prebuilts'
  category = constants.CI_INFRA_STAGE

  def __init__(self, builder_run, buildstore, board, version=None, **kwargs):
    self.prebuilts_version = version
    super(UploadPrebuiltsStage, self).__init__(builder_run, buildstore, board,
                                               **kwargs)

  def GenerateCommonArgs(self, inc_chrome_ver=True):
    """Generate common prebuilt arguments."""
    generated_args = []
    if self._run.options.debug:
      generated_args.extend(['--debug', '--dry-run'])

    profile = self._run.options.profile or self._run.config.profile
    if profile:
      generated_args.extend(['--profile', profile])

    # Generate the version if we are a manifest_version build.
    if self._run.config.manifest_version:
      version = self._run.GetVersion(include_chrome=inc_chrome_ver)
    else:
      version = self.prebuilts_version
    if version is not None:
      generated_args.extend(['--set-version', version])

    if self._run.config.git_sync and self._run.options.publish:
      # Git sync should never be set for pfq type builds.
      assert not config_lib.IsPFQType(self._prebuilt_type)
      generated_args.extend(['--git-sync'])

    return generated_args

  @classmethod
  def _AddOptionsForSlave(cls, slave_config, board):
    """Private helper method to add upload_prebuilts args for a slave builder.

    Args:
      slave_config: The build config of a slave builder.
      board: The name of the "master" board on the master builder.

    Returns:
      An array of options to add to upload_prebuilts array that allow a master
      to submit prebuilt conf modifications on behalf of a slave.
    """
    args = []
    if slave_config['prebuilts']:
      for slave_board in slave_config['boards']:
        if slave_config['master'] and slave_board == board:
          # Ignore self.
          continue

        args.extend(['--slave-board', slave_board])
        slave_profile = slave_config['profile']
        if slave_profile:
          args.extend(['--slave-profile', slave_profile])

    return args

  @failures_lib.SetFailureType(failures_lib.InfrastructureFailure)
  def PerformStage(self):
    """Uploads prebuilts for master and slave builders."""
    prebuilt_type = self._prebuilt_type
    board = self._current_board

    # Whether we publish public or private prebuilts.
    public = self._run.config.prebuilts == constants.PUBLIC
    # Common args we generate for all types of builds.
    generated_args = self.GenerateCommonArgs()
    # Args we specifically add for public/private build types.
    public_args, private_args = [], []
    # Public / private builders.
    public_builders, private_builders = [], []

    common_kwargs = {
        'buildroot': self._build_root,
        'category': prebuilt_type,
        'version': self.prebuilts_version,
    }

    # Upload the public prebuilts, if any.
    if public_builders or public:
      public_board = board if public else None
      prebuilts.UploadPrebuilts(
          private_bucket=False,
          board=public_board,
          extra_args=generated_args + public_args,
          **common_kwargs)

    # Upload the private prebuilts, if any.
    if private_builders or not public:
      private_board = board if not public else None
      prebuilts.UploadPrebuilts(
          private_bucket=True,
          board=private_board,
          extra_args=generated_args + private_args,
          **common_kwargs)


class DevInstallerPrebuiltsStage(UploadPrebuiltsStage):
  """Stage that uploads DevInstaller prebuilts."""

  config_name = 'dev_installer_prebuilts'
  category = constants.CI_INFRA_STAGE

  @failures_lib.SetFailureType(failures_lib.InfrastructureFailure)
  def PerformStage(self):
    generated_args = self.GenerateCommonArgs(inc_chrome_ver=False)
    prebuilts.UploadDevInstallerPrebuilts(
        binhost_bucket=self._run.config.binhost_bucket,
        binhost_key=self._run.config.binhost_key,
        binhost_base_url=self._run.config.binhost_base_url,
        buildroot=self._build_root,
        board=self._current_board,
        extra_args=generated_args)


class UploadTestArtifactsStage(generic_stages.BoardSpecificBuilderStage,
                               generic_stages.ArchivingStageMixin):
  """Upload needed hardware test artifacts."""

  category = constants.CI_INFRA_STAGE

  def BuildAutotestTarballs(self):
    """Build the autotest tarballs."""
    with osutils.TempDir(prefix='cbuildbot-autotest') as tempdir:
      with self.ArtifactUploader(strict=True) as queue:
        cwd = os.path.abspath(
            os.path.join(self._build_root, 'chroot', 'build',
                         self._current_board, constants.AUTOTEST_BUILD_PATH,
                         '..'))
        logging.debug(
            'Running BuildAutotestTarballsForHWTest root %s cwd %s target %s',
            self._build_root, cwd, tempdir)
        for tarball in commands.BuildAutotestTarballsForHWTest(
            self._build_root, cwd, tempdir):
          queue.put([tarball])

  def BuildTastTarball(self):
    """Build the tarball containing private Tast test bundles."""
    with osutils.TempDir(prefix='cbuildbot-tast') as tempdir:
      cwd = os.path.abspath(
          os.path.join(self._build_root, 'chroot', 'build',
                       self._current_board, 'build'))
      logging.info('Running commands.BuildTastBundleTarball')
      tarball = commands.BuildTastBundleTarball(
          self._build_root, cwd, tempdir)
      if tarball:
        self.UploadArtifact(tarball)

  def BuildGuestImagesTarball(self):
    """Build the tarball containing guest images test bundles."""
    with osutils.TempDir(prefix='cbuildbot-guest-images') as tempdir:
      logging.info('Running commands.BuildPinnedGuestImagesTarball')
      tarball = commands.BuildPinnedGuestImagesTarball(
          self._build_root, self._current_board, tempdir)
      if tarball:
        self.UploadArtifact(tarball)

  def _GeneratePayloads(self, image_name, **kwargs):
    """Generate and upload payloads for |image_name|.

    Args:
      image_name: The image to use.
      **kwargs: Keyword arguments to pass to commands.GeneratePayloads.
    """
    with osutils.TempDir(prefix='cbuildbot-payloads') as tempdir:
      with self.ArtifactUploader() as queue:
        image_path = os.path.join(self.GetImageDirSymlink(), image_name)
        logging.info('Running commands.GeneratePayloads')
        commands.GeneratePayloads(image_path, tempdir, **kwargs)
        logging.info('Running commands.GenerateQuickProvisionPayloads')
        commands.GenerateQuickProvisionPayloads(image_path, tempdir)
        for payload in os.listdir(tempdir):
          queue.put([os.path.join(tempdir, payload)])

  def BuildUpdatePayloads(self):
    """Archives update payloads when they are ready."""
    # If we are not configured to generate payloads, don't.
    if not (self._run.options.build and self._run.options.tests and
            self._run.config.upload_hw_test_artifacts and
            self._run.config.images):
      return

    # If there are no images to generate payloads from, don't.
    got_images = self.GetParallel('images_generated', pretty_name='images')
    if not got_images:
      return

    payload_type = self._run.config.payload_image
    if payload_type is None:
      payload_type = 'base'
      for t in ['test', 'dev']:
        if t in self._run.config.images:
          payload_type = t
          break
    image_name = constants.IMAGE_TYPE_TO_NAME[payload_type]
    logging.info('Generating payloads to upload for %s', image_name)
    self._GeneratePayloads(image_name, full=True, stateful=True, delta=True,
                           dlc=True)

  @failures_lib.SetFailureType(failures_lib.InfrastructureFailure)
  def PerformStage(self):
    """Upload any needed HWTest artifacts."""
    # BuildUpdatePayloads also uploads the payloads to GS.
    steps = [self.BuildUpdatePayloads]

    if (self._run.ShouldBuildAutotest() and
        self._run.config.upload_hw_test_artifacts):
      steps.append(self.BuildAutotestTarballs)
      steps.append(self.BuildTastTarball)
      steps.append(self.BuildGuestImagesTarball)

    parallel.RunParallelSteps(steps)
    # If we encountered any exceptions with any of the steps, they should have
    # set the attribute to False.
    self.board_runattrs.SetParallelDefault('test_artifacts_uploaded', True)

  def _HandleStageException(self, exc_info):
    # Tell the test stages not to wait for artifacts to be uploaded in case
    # UploadTestArtifacts throws an exception.
    self.board_runattrs.SetParallel('test_artifacts_uploaded', False)

    return super(UploadTestArtifactsStage, self)._HandleStageException(exc_info)

  def HandleSkip(self):
    """Launch DebugSymbolsStage if UnitTestStage is skipped."""
    self.board_runattrs.SetParallel('test_artifacts_uploaded', False)
    return super(UploadTestArtifactsStage, self).HandleSkip()


# TODO(mtennant): This class continues to exist only for subclasses that still
# need self.archive_stage.  Hopefully, we can get rid of that need, eventually.
class ArchivingStage(generic_stages.BoardSpecificBuilderStage,
                     generic_stages.ArchivingStageMixin):
  """Helper for stages that archive files.

  See ArchivingStageMixin for functionality.

  Attributes:
    archive_stage: The ArchiveStage instance for this board.
  """

  category = constants.CI_INFRA_STAGE

  def __init__(self, builder_run, buildstore, board, archive_stage, **kwargs):
    super(ArchivingStage, self).__init__(builder_run, buildstore, board,
                                         **kwargs)
    self.archive_stage = archive_stage


# This stage generates and uploads the sysroot for the build
# containing all the packages built previously in build packages stage.
class GenerateSysrootStage(generic_stages.BoardSpecificBuilderStage,
                           generic_stages.ArchivingStageMixin):
  """Generate and upload the sysroot for the board."""

  category = constants.CI_INFRA_STAGE

  def __init__(self, *args, **kwargs):
    super(GenerateSysrootStage, self).__init__(*args, **kwargs)
    self._upload_queue = multiprocessing.Queue()

  def _GenerateSysroot(self):
    """Generate and upload a sysroot for the board."""
    assert self.archive_path.startswith(self._build_root)
    extra_env = {}
    pkgs = self.GetListOfPackagesToBuild()
    sysroot_tarball = constants.TARGET_SYSROOT_TAR
    if self._run.config.useflags:
      extra_env['USE'] = ' '.join(self._run.config.useflags)
    in_chroot_path = path_util.ToChrootPath(self.archive_path)
    cmd = [
        'cros_generate_sysroot', '--out-file', sysroot_tarball, '--out-dir',
        in_chroot_path, '--board', self._current_board, '--package',
        ' '.join(pkgs)
    ]
    cros_build_lib.run(
        cmd, cwd=self._build_root, enter_chroot=True, extra_env=extra_env)
    self._upload_queue.put([sysroot_tarball])

  def PerformStage(self):
    with self.ArtifactUploader(self._upload_queue, archive=False):
      self._GenerateSysroot()


# This stage generates and uploads the clang-tidy warnings files for the
# build, for all the packages built in build packages stage with
# WITH_TIDY=1.
class GenerateTidyWarningsStage(generic_stages.BoardSpecificBuilderStage,
                                generic_stages.ArchivingStageMixin):
  """Generate and upload the warnings files for the board."""

  category = constants.CI_INFRA_STAGE

  CLANG_TIDY_TAR = 'clang_tidy_warnings.tar.xz'
  GS_URL = 'gs://chromeos-clang-tidy-artifacts/clang-tidy-1'

  def __init__(self, *args, **kwargs):
    super(GenerateTidyWarningsStage, self).__init__(*args, **kwargs)
    self._upload_queue = multiprocessing.Queue()

  def _UploadTidyWarnings(self, path, tar_file):
    """Upload the warnings tarball to the clang-tidy gs bucket."""
    gs_context = gs.GSContext()
    filename = os.path.join(path, tar_file)

    debug = self._run.options.debug_forced
    if debug:
      logging.info('Debug run: not uploading tarball.')
      logging.info('If this were not a debug run, would upload %s to %s.',
                   filename, self.GS_URL)
      return

    try:
      logging.info('Uploading tarball %s to %s', filename, self.GS_URL)
      gs_context.CopyInto(filename, self.GS_URL)
    except:
      logging.info('Error: Unable to upload tarball %s to %s', filename,
                   self.GS_URL)
      raise

  def _GenerateTidyWarnings(self):
    """Generate and upload the tidy warnings files for the board."""
    assert self.archive_path.startswith(self._build_root)
    logs_dir = os.path.join('/tmp', 'clang-tidy-logs', self._current_board)
    timestamp = datetime.datetime.strftime(datetime.datetime.now(), '%Y%m%d')
    clang_tidy_tarball = '%s.%s.%s' % (self._current_board, timestamp,
                                       self.CLANG_TIDY_TAR)
    in_chroot_path = path_util.ToChrootPath(self.archive_path)
    out_chroot_path = os.path.abspath(
        os.path.join(self._build_root, 'chroot', self.archive_path))
    cmd = [
        'cros_generate_tidy_warnings', '--out-file', clang_tidy_tarball,
        '--out-dir', in_chroot_path, '--board', self._current_board,
        '--logs-dir', logs_dir
    ]
    cros_build_lib.run(cmd, cwd=self._build_root, enter_chroot=True)
    self._UploadTidyWarnings(out_chroot_path, clang_tidy_tarball)
    self._upload_queue.put([clang_tidy_tarball])

  def PerformStage(self):
    with self.ArtifactUploader(self._upload_queue, archive=False):
      self._GenerateTidyWarnings()


# This stage collects and uploads the LLVM PGO profile files for the build.
class CollectPGOProfilesStage(generic_stages.BoardSpecificBuilderStage,
                              generic_stages.ArchivingStageMixin):
  """Collect and upload PGO profile files for the board."""

  category = constants.CI_INFRA_STAGE
  PROFDATA_TAR = 'llvm_profdata.tar.xz'
  LLVM_METADATA = 'llvm_metadata.json'
  PROFDATA = 'llvm.profdata'

  def __init__(self, *args, **kwargs):
    super(CollectPGOProfilesStage, self).__init__(*args, **kwargs)
    self._upload_queue = multiprocessing.Queue()
    self._merge_cmd = ''

  @staticmethod
  def _ParseUseFlagState(use_flags):
    """Converts the textual output of equery to a +/- USE flag list."""
    # Equery prints out a large header. The lines we're interested in look
    # like:
    # " + - use_flag : foo", where `use_flag` is the name of the use flag, the
    # initial - or + says whether the flag is enabled by default, and the
    # second one says whether the flag was enabled upon installation. `foo` is
    # the description, but that's unimportant to us.
    matcher = re.compile(r'^\s+[+-]\s+([+-])\s+(\S+)\s+:', re.MULTILINE)
    matches = matcher.findall(use_flags)
    return [state + flag_name for state, flag_name in matches]

  @staticmethod
  def _ParseLLVMHeadSHA(version_string):
    # The first line of clang's version string looks something like:
    # Chromium OS 10.0_pre377782_p20200113-r1 clang version 10.0.0 \
    # (/var/cache/chromeos-cache/distfiles/host/egit-src/llvm-project \
    # 4e8231b5cf0f5f62c7a51a857e29f5be5cb55734)
    #
    # The SHA after llvm-project is the SHA we're looking for.
    # Note that len('4e8231b5cf0f5f62c7a51a857e29f5be5cb55734') == 40.
    sha_re = re.compile(r'llvm-project ([A-Fa-f0-9]{40})\)$')
    first_line = version_string.splitlines()[0].strip()
    match = sha_re.search(first_line)
    if not match:
      raise ValueError("Can't recognize the version string %r" % first_line)
    return match.group(1)

  def _CollectLLVMMetadata(self):
    def check_chroot_output(command):
      cmd = cros_build_lib.run(command, enter_chroot=True, stdout=True,
                               encoding='utf-8')
      return cmd.output

    # The baked-in clang should be the one we're looking for. If not, yell.
    llvm_uses = check_chroot_output(
        ['equery', '-C', '-N', 'uses', 'sys-devel/llvm'])
    use_vars = self._ParseUseFlagState(llvm_uses)
    if '+llvm_pgo_generate' not in use_vars:
      raise ValueError("The pgo_generate flag isn't enabled; USE flags: %r" %
                       sorted(use_vars))

    clang_version_str = check_chroot_output(['clang', '--version'])
    head_sha = self._ParseLLVMHeadSHA(clang_version_str)
    metadata_output_path = os.path.join(self.archive_path, self.LLVM_METADATA)
    pformat.json({'head_sha': head_sha}, fp=metadata_output_path, compact=True)
    # This is a tiny JSON file, so it doesn't need to be tarred/compressed.
    self._upload_queue.put([metadata_output_path])

  def _CollectPGOProfiles(self):
    """Collect and upload PGO profiles for the board."""
    assert self.archive_path.startswith(self._build_root)

    # Look for profiles generated by instrumented LLVM
    out_chroot = os.path.abspath(
        os.path.join(self._build_root, 'chroot'))
    cov_data_location = 'build/%s/build/coverage_data' % self._current_board
    out_chroot_cov_data = os.path.join(out_chroot, cov_data_location)
    try:
      profiles_dirs = [root for root, _, _ in os.walk(out_chroot_cov_data)
                       if os.path.basename(root) == 'raw_profiles']
      if not profiles_dirs:
        raise Exception('No profile directories found.')
      # Get out of chroot profile paths, and convert to in chroot paths
      profraws = [path_util.ToChrootPath(os.path.join(profiles_dir, f))
                  for profiles_dir in profiles_dirs
                  for f in os.listdir(profiles_dir)]
      if not profraws:
        raise Exception('No profraw files found in profiles directory.')
    except:
      logging.info('Error: Not able to collect correct profiles.')
      raise

    # Create profdata file and make tarball
    in_chroot_path = path_util.ToChrootPath(self.archive_path)
    profdata_loc = os.path.join(in_chroot_path, self.PROFDATA)

    out_chroot_path = os.path.join(out_chroot, self.archive_path)
    out_profdata_loc = os.path.join(out_chroot_path, self.PROFDATA)

    # There can bee too many profraws to merge, put them as a list in the file
    # so that bash will not complain about arguments getting too long.
    profraw_list = os.path.join(in_chroot_path, 'profraw_list')
    out_profraw_list = os.path.join(out_chroot_path, 'profraw_list')

    with open(out_profraw_list, 'w') as f:
      f.write('\n'.join(profraws))

    self._merge_cmd = ['llvm-profdata', 'merge',
                       '-output', profdata_loc,
                       '-f', profraw_list]
    cros_build_lib.run(self._merge_cmd, cwd=self._build_root, enter_chroot=True)

    cros_build_lib.CreateTarball(self.PROFDATA_TAR, cwd=out_chroot_path,
                                 inputs=[out_profdata_loc])

    # Upload profdata tarball
    self._upload_queue.put([self.PROFDATA_TAR])

  def PerformStage(self):
    with self.ArtifactUploader(self._upload_queue, archive=False):
      self._CollectPGOProfiles()
      self._CollectLLVMMetadata()
