# -*- 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 the generic stages."""

from __future__ import print_function

import contextlib
import copy
import fnmatch
import json
import os
import re
import sys
import tempfile
import time
import traceback

import six

from chromite.cbuildbot import commands
from chromite.cbuildbot import repository
from chromite.cbuildbot import topology
from chromite.lib import auth
from chromite.lib import buildbucket_lib
from chromite.lib import builder_status_lib
from chromite.lib import constants
from chromite.lib import cros_build_lib
from chromite.lib import cros_logging as logging
from chromite.lib import failures_lib
from chromite.lib import failure_message_lib
from chromite.lib import gs
from chromite.lib import metrics
from chromite.lib import osutils
from chromite.lib import parallel
from chromite.lib import perf_uploader
from chromite.lib import portage_util
from chromite.lib import results_lib
from chromite.lib import retry_util
from chromite.lib import timeout_util
from chromite.lib.buildstore import BuildIdentifier


class BuilderStage(object):
  """Parent class for stages to be performed by a builder."""
  # Used to remove 'Stage' suffix of stage class when generating stage name.
  name_stage_re = re.compile(r'(\w+)Stage')
  category = constants.UNCATEGORIZED_STAGE

  # TODO(sosa): Remove these once we have a SEND/RECIEVE IPC mechanism
  # implemented.
  overlays = None
  push_overlays = None

  # Class should set this if they have a corresponding no<stage> option that
  # skips their stage.
  # TODO(mtennant): Rename this something like skip_option_name.
  option_name = None

  # Class should set this if they have a corresponding setting in
  # the build_config that skips their stage.
  # TODO(mtennant): Rename this something like skip_config_name.
  config_name = None

  @classmethod
  def StageNamePrefix(cls):
    """Return cls.__name__ with any 'Stage' suffix removed."""
    match = cls.name_stage_re.match(cls.__name__)
    assert match, 'Class name %s does not end with Stage' % cls.__name__
    return match.group(1)

  def __init__(self,
               builder_run,
               buildstore,
               suffix=None,
               attempt=None,
               max_retry=None,
               build_root=None):
    """Create a builder stage.

    Args:
      builder_run: The BuilderRun object for the run this stage is part of.
      buildstore: BuildStore object to make DB calls.
      suffix: The suffix to append to the buildbot name. Defaults to None.
      attempt: If this build is to be retried, the current attempt number
        (starting from 1). Defaults to None. Is only valid if |max_retry| is
        also specified.
      max_retry: The maximum number of retries. Defaults to None. Is only valid
        if |attempt| is also specified.
      build_root: Override the builder_run build_root.
    """
    self._run = builder_run
    self.buildstore = buildstore

    self._attempt = attempt
    self._max_retry = max_retry
    self._build_stage_id = None

    # Construct self.name, the name string for this stage instance.
    self.name = self._prefix = self.StageNamePrefix()
    if suffix:
      self.name += suffix

    # TODO(mtennant): Phase this out and use self._run.bot_id directly.
    self._bot_id = self._run.bot_id

    # self._boards holds list of boards involved in this run.
    # TODO(mtennant): Replace self._boards with a self._run.boards?
    self._boards = self._run.config.boards

    self._build_root = os.path.abspath(build_root or self._run.buildroot)

    self.build_config = self._run.config.name
    self.metrics_branch = self._run.options.branch
    self.metrics_tryjob = self._run.options.remote_trybot

    self._prebuilt_type = None
    if self._run.ShouldUploadPrebuilts():
      self._prebuilt_type = self._run.config.build_type

    # Determine correct android_rev.
    self._android_rev = self._run.config.android_rev
    if self._run.options.android_rev:
      self._android_rev = self._run.options.android_rev

    # Determine correct chrome_rev.
    self._chrome_rev = self._run.config.chrome_rev
    if self._run.options.chrome_rev:
      self._chrome_rev = self._run.options.chrome_rev

    # USE and enviroment variable settings.
    self._portage_extra_env = {}
    useflags = self._run.config.useflags[:]

    if self._run.options.clobber:
      self._portage_extra_env['IGNORE_PREFLIGHT_BINHOST'] = '1'

    if self._run.options.chrome_root:
      self._portage_extra_env['CHROME_ORIGIN'] = 'LOCAL_SOURCE'

    self._latest_toolchain = (
        self._run.config.latest_toolchain or self._run.options.latest_toolchain)
    if self._latest_toolchain and self._run.config.gcc_githash:
      useflags.append('git_gcc')
      self._portage_extra_env['GCC_GITHASH'] = self._run.config.gcc_githash

    if useflags:
      self._portage_extra_env['USE'] = ' '.join(useflags)

    if self._run.config.separate_debug_symbols:
      self._portage_extra_env['FEATURES'] = 'separatedebug'

    # Note: BuildStartStage is a special case: Since it is created before we
    # have a valid |build_id|, it is not logged in cidb.
    self._InsertBuildStageInCIDB(name=self.name)

  def GetStageNames(self):
    """Get a list of the places where this stage has recorded results."""
    return [self.name]

  def GetBuildStageIDs(self):
    """Get a list of build stage ids in cidb corresponding to this stage."""
    return [self._build_stage_id] if self._build_stage_id is not None else []

  def UpdateSuffix(self, tag, child_suffix):
    """Update the suffix arg for the init call.

    Use this function to concatenate the tag for the current class with the
    suffix passed in by a child class.
    This function is expected to be called before __init__, and as such should
    not use any object attributes.

    Args:
      tag: The tag for this class. Should not be None.
      child_suffix: The suffix passed up by the child class. May be None.

    Returns:
      Extended suffix that incoroporates the tag, to be passed up to the parent
      class's __init__.
    """
    if child_suffix is None:
      child_suffix = ''
    return ' [%s]%s' % (tag, child_suffix)

  # TODO(akeshet): Eliminate this method and update the callers to use
  # builder run directly.
  def ConstructDashboardURL(self, stage=None):
    """Return the dashboard URL

    This is the direct link to buildbot logs as seen in build.chromium.org

    Args:
      stage: Link to a specific |stage|, otherwise the general buildbot log

    Returns:
      The fully formed URL
    """
    return self._run.ConstructDashboardURL(stage=stage)

  def _UploadPerfValues(self, *args, **kwargs):
    """Helper for uploading perf values.

    This currently handles common checks only.  We could make perf values more
    integrated in the overall stage running process in the future though if we
    had more stages that cared about this.
    """
    # Only upload perf data for buildbots as the data from local tryjobs
    # probably isn't useful to us.
    if not self._run.options.buildbot:
      return

    try:
      retry_util.RetryException(perf_uploader.PerfUploadingError, 3,
                                perf_uploader.UploadPerfValues, *args, **kwargs)
    except perf_uploader.PerfUploadingError:
      logging.exception('Uploading perf data failed')

  def _InsertBuildStageInCIDB(self,
                              name,
                              board=None,
                              status=constants.BUILDER_STATUS_PLANNED):
    """Insert a build stage in cidb.

      Expected arguments are the same as cidb.InsertBuildStage, except
      |build_id|, which is populated here.
    """
    build_identifier, _ = self._run.GetCIDBHandle()
    build_id = build_identifier.cidb_id
    if build_id:
      self._build_stage_id = self.buildstore.InsertBuildStage(
          build_id, name, board, status)

  def _FinishBuildStageInCIDBAndMonarch(self,
                                        stage_result,
                                        status,
                                        elapsed_time_seconds=0):
    """Mark the stage as finished in cidb.

    Args:
      stage_result: results_lib.Results.* object of this stage.
      status: The finish status of the build. Enum type
          constants.BUILDER_COMPLETED_STATUSES
      elapsed_time_seconds: (optional) Elapsed time in stage, in seconds.
    """
    if self._build_stage_id is not None and self.buildstore.AreClientsReady():
      self.buildstore.FinishBuildStage(self._build_stage_id, status)

    fields = {
        'status': status,
        'name': self.name,
        'build_config': self._run.config.name,
        'important': self._run.config.important
    }

    metrics.CumulativeSecondsDistribution(constants.MON_STAGE_DURATION).add(
        elapsed_time_seconds, fields=fields)
    metrics.Counter(constants.MON_STAGE_COMP_COUNT).increment(fields=fields)
    common_metrics_fields = {
        'branch_name': self.metrics_branch,
        'build_config': self.build_config,
        'tryjob': self.metrics_tryjob,
    }
    duration_metrics_fields = copy.deepcopy(common_metrics_fields)
    duration_metrics_fields.update({'stage': self.name, 'status': status})
    if self.metrics_branch is not None:
      metrics.FloatMetric(constants.MON_STAGE_INSTANCE_DURATION).set(
          elapsed_time_seconds, fields=duration_metrics_fields)
    if (isinstance(stage_result, BaseException) and
        self._build_stage_id is not None):
      failed_metrics_fields = copy.deepcopy(common_metrics_fields)
      failed_metrics_fields.update({
          'failed_stage': self.name,
          'category': self.category
      })
      if self.buildstore.AreClientsReady():
        failures_lib.ReportStageFailure(
            stage_result,
            metrics_fields=failed_metrics_fields)

  def _StartBuildStageInCIDB(self):
    """Mark the stage as inflight in cidb."""
    if self._build_stage_id is not None and self.buildstore.AreClientsReady():
      self.buildstore.StartBuildStage(self._build_stage_id)

  def _WaitBuildStageInCIDB(self):
    """Mark the stage as waiting in cidb."""
    if self._build_stage_id is not None and self.buildstore.AreClientsReady():
      self.buildstore.WaitBuildStage(self._build_stage_id)

  def _TranslateResultToCIDBStatus(self, result):
    """Translates the different result_lib.Result results to builder statuses.

    Args:
      result: Same as the result passed to results_lib.Result.Record()

    Returns:
      A value in the enum constants.BUILDER_ALL_STATUSES.
    """
    if result == results_lib.Results.SUCCESS:
      return constants.BUILDER_STATUS_PASSED
    elif result == results_lib.Results.FORGIVEN:
      return constants.BUILDER_STATUS_FORGIVEN
    elif result == results_lib.Results.SKIPPED:
      return constants.BUILDER_STATUS_SKIPPED
    else:
      logging.info('Translating result %s to fail.', result)
      return constants.BUILDER_STATUS_FAILED

  def GetRepoRepository(self, **kwargs):
    """Create a new repo repository object."""
    manifest_url = self._run.options.manifest_repo_url
    if manifest_url is None:
      manifest_url = self._run.config.manifest_repo_url

    manifest_branch = self._run.config.manifest_branch
    if manifest_branch is None:
      manifest_branch = self._run.manifest_branch

    kwargs.setdefault('manifest_repo_url', manifest_url)
    kwargs.setdefault('directory', self._build_root)
    kwargs.setdefault('referenced_repo', self._run.options.reference_repo)
    kwargs.setdefault('branch', manifest_branch)
    kwargs.setdefault('manifest', self._run.config.manifest)
    kwargs.setdefault('git_cache_dir', self._run.options.git_cache_dir)
    kwargs.setdefault('groups', 'all')

    # pass in preserve_paths so that repository.RepoRepository
    # knows what paths to preserve when executing clean_up_repo
    if hasattr(self._run.options, 'preserve_paths'):
      kwargs.setdefault('preserve_paths', self._run.options.preserve_paths)

    return repository.RepoRepository(**kwargs)

  def GetBuildbucketClient(self):
    """Build a buildbucket_client instance for Buildbucket related operations.

    Returns:
      An instance of buildbucket_lib.BuildbucketClient if the build is using
      Buildbucket as the scheduler; else, None.
    """
    if buildbucket_lib.GetServiceAccount(constants.CHROMEOS_SERVICE_ACCOUNT):
      return buildbucket_lib.BuildbucketClient(
          auth.GetAccessToken,
          None,
          service_account_json=constants.CHROMEOS_SERVICE_ACCOUNT)

    if self._run.InProduction():
      # If the build using Buildbucket is running on buildbot and
      # is in production mode, buildbucket_client cannot be None.
      raise buildbucket_lib.NoBuildbucketClientException(
          'Buildbucket_client is None. '
          'Please check if the buildbot has a valid service account file. '
          'Please find the service account json file at %s.' %
          constants.CHROMEOS_SERVICE_ACCOUNT)

    return None

  def GetScheduledSlaveBuildbucketIds(self):
    """Get buildbucket_ids list of the scheduled slave builds.

    Returns:
      A list of buildbucket_ids (strings) of the slave builds. The list doesn't
      contain the old builds which were retried in Buildbucket.
    """
    buildbucket_ids = None
    if self._run.config.slave_configs:
      buildbucket_ids = buildbucket_lib.GetBuildbucketIds(
          self._run.attrs.metadata)

    return buildbucket_ids

  def GetBuildFailureMessageFromBuildStore(self, buildstore, build_identifier):
    """Get message summarizing failures of this build from BuildStore.

    Args:
      buildstore: An instance of BuildStore to make DB calls.
      build_identifier: The instance of BuildIdentifier of the current build.

    Returns:
      An instance of build_failure_message.BuildFailureMessage.
    """
    stage_failures = buildstore.GetBuildsFailures([
        build_identifier.buildbucket_id])
    failure_msg_manager = failure_message_lib.FailureMessageManager()
    failure_messages = failure_msg_manager.ConstructStageFailureMessages(
        stage_failures)
    master_build_identifier = BuildIdentifier(
        self._run.options.master_build_id,
        self._run.options.master_buildbucket_id)
    aborted = builder_status_lib.BuilderStatusManager.AbortedBySelfDestruction(
        buildstore, build_identifier.buildbucket_id,
        master_build_identifier)

    return builder_status_lib.BuilderStatusManager.CreateBuildFailureMessage(
        self._run.config.name,
        self._run.config.overlays,
        self._run.ConstructDashboardURL(),
        failure_messages,
        aborted_by_self_destruction=aborted)

  def GetBuildFailureMessageFromResults(self):
    """Get message summarizing failures of this build from result_lib.Results.

    Returns:
      An instance of build_failure_message.BuildFailureMessage.
    """
    failure_messages = results_lib.Results.GetStageFailureMessage()
    return builder_status_lib.BuilderStatusManager.CreateBuildFailureMessage(
        self._run.config.name, self._run.config.overlays,
        self._run.ConstructDashboardURL(), failure_messages)

  def GetBuildFailureMessage(self):
    """Get message summarizing failure of this build."""
    build_identifier, _ = self._run.GetCIDBHandle()
    if self.buildstore.AreClientsReady():
      return self.GetBuildFailureMessageFromBuildStore(
          self.buildstore, build_identifier)
    else:
      return self.GetBuildFailureMessageFromResults()

  def GetJobKeyvals(self):
    """Get job keyvals for the build stage."""
    build_identifier, _ = self._run.GetCIDBHandle()
    build_id = build_identifier.cidb_id
    if self._run.options.master_buildbucket_id:
      master_status = self.buildstore.GetBuildStatuses(
          [self._run.options.master_buildbucket_id])[0]
      master_config = master_status['build_config']
    else:
      master_config = None
    job_keyvals = {
        constants.JOB_KEYVAL_DATASTORE_PARENT_KEY: (
            'Build', build_id),
        constants.JOB_KEYVAL_CIDB_BUILD_ID:
            build_id,
        constants.JOB_KEYVAL_BUILD_CONFIG:
            self._run.config.name,
        constants.JOB_KEYVAL_BRANCH:
            self._run.options.branch,
        constants.JOB_KEYVAL_MASTER_BUILD_CONFIG:
            master_config
    }
    return job_keyvals

  def _Print(self, msg):
    """Prints a msg to stderr."""
    sys.stdout.flush()
    print(msg, file=sys.stderr)
    sys.stderr.flush()

  def _PrintLoudly(self, msg):
    """Prints a msg with loudly."""

    border_line = '*' * 60
    edge = '*' * 2

    sys.stdout.flush()
    print(border_line, file=sys.stderr)

    msg_lines = msg.split('\n')

    # If the last line is whitespace only drop it.
    if not msg_lines[-1].rstrip():
      del msg_lines[-1]

    for msg_line in msg_lines:
      print('%s %s' % (edge, msg_line), file=sys.stderr)

    print(border_line, file=sys.stderr)
    sys.stderr.flush()

  def _GetPortageEnvVar(self, envvar, board):
    """Get a portage environment variable for the configuration's board.

    Args:
      envvar: The environment variable to get. E.g. 'PORTAGE_BINHOST'.
      board: The board to apply, if any.  Specify None to use host.

    Returns:
      The value of the environment variable, as a string. If no such variable
      can be found, return the empty string.
    """
    return portage_util.PortageqEnvvar(
        envvar, board=board, allow_undefined=True)

  def _GetSlaveConfigs(self):
    """Get the slave configs for the current build config.

    This assumes self._run.config is a master config.

    Returns:
      A list of build configs corresponding to the slaves for the master
        build config at self._run.config.

    Raises:
      See config_lib.Config.GetSlavesForMaster for details.
    """
    experimental_builders = self._run.attrs.metadata.GetValueWithDefault(
        constants.METADATA_EXPERIMENTAL_BUILDERS, [])
    slave_configs = self._run.site_config.GetSlavesForMaster(
        self._run.config, self._run.options)
    slave_configs = [
        config for config in slave_configs
        if config['name'] not in experimental_builders
    ]
    return slave_configs

  def _GetSlaveConfigMap(self, important_only=True):
    """Get slave config map for the current build config.

    This assumes self._run.config is a master config.

    Args:
      important_only: If True, only get important slaves.

    Returns:
      A map of slave_name to slave_config for the current master.

    Raises:
      See config_lib.Config.GetSlaveConfigMapForMaster for details.
    """

    slave_config_map = self._run.site_config.GetSlaveConfigMapForMaster(
        self._run.config, self._run.options, important_only=important_only)
    if important_only:
      experimental_builders = self._run.attrs.metadata.GetValueWithDefault(
          constants.METADATA_EXPERIMENTAL_BUILDERS, [])
      slave_config_map = {
          k: v
          for k, v in slave_config_map.items()
          if k not in experimental_builders
      }
    return slave_config_map

  def _BeginStepForBuildbot(self, tag=None):
    """Called before a stage is performed.

    Args:
      tag: Extra tag to add to the stage name on the waterfall.
    """
    waterfall_name = self.name
    if tag is not None:
      waterfall_name += tag
    logging.PrintBuildbotStepName(waterfall_name)

    self._PrintLoudly(
        'Start Stage %s - %s\n\n%s' %
        (self.name, cros_build_lib.UserDateTimeFormat(), self.__doc__))

  def Finish(self):
    """Called after a stage has already completed.

    Will be called on both success or failure. EXPECTIONS WILL BE LOGGED AND
    IGNORED, and will not fail the stage.

    This is an appropriate place for non-essential cleanup/reporting work.
    """

  def WaitUntilReady(self):
    """Wait until all the preconditions for the stage are satisfied.

    Can be overridden by stages. If it returns True, trigger the run
    of PerformStage; else, skip this stage.

    Returns:
      By default it just returns True. Subclass can override it
        to return the boolean indicating if Wait succeeds and
        if PerformStage should be run
    """
    return True

  def PerformStage(self):
    """Run the actual commands needed for this stage.

    Subclassed stages must override this function.
    """

  def _HandleExceptionAsSuccess(self, _exc_info):
    """Use instead of HandleStageException to ignore an exception."""
    return (results_lib.Results.SUCCESS, None, False)

  @staticmethod
  def _StringifyException(exc_info):
    """Convert an exception into a string.

    Args:
      exc_info: A (type, value, traceback) tuple as returned by sys.exc_info().

    Returns:
      A string description of the exception.
    """
    exc_type, exc_value = exc_info[:2]
    if issubclass(exc_type, failures_lib.StepFailure):
      return str(exc_value)
    else:
      return ''.join(traceback.format_exception(*exc_info))

  @classmethod
  def _HandleExceptionAsWarning(cls, exc_info, retrying=False):
    """Use instead of HandleStageException to treat an exception as a warning.

    This is used by the ForgivingBuilderStage's to treat any exceptions as
    warnings instead of stage failures.
    """
    description = cls._StringifyException(exc_info)
    logging.PrintBuildbotStepWarnings()
    logging.warning(description)
    return (results_lib.Results.FORGIVEN, description, retrying)

  @classmethod
  def _HandleExceptionAsError(cls, exc_info):
    """Handle an exception as an error, but ignore stage retry settings.

    Meant as a helper for _HandleStageException code only.

    Args:
      exc_info: A (type, value, traceback) tuple as returned by sys.exc_info().

    Returns:
      Result tuple of (exception, description, retrying).
    """
    # Tell the user about the exception, and record it.
    retrying = False
    description = cls._StringifyException(exc_info)
    logging.PrintBuildbotStepFailure()
    logging.error(description)
    return (exc_info[1], description, retrying)

  def _HandleStageException(self, exc_info):
    """Called when PerformStage throws an exception.  Can be overriden.

    Args:
      exc_info: A (type, value, traceback) tuple as returned by sys.exc_info().

    Returns:
      Result tuple of (exception, description, retrying).  If it isn't an
      exception, then description will be None.
    """
    if self._attempt and self._max_retry and self._attempt <= self._max_retry:
      return self._HandleExceptionAsWarning(exc_info, retrying=True)
    else:
      return self._HandleExceptionAsError(exc_info)

  def _TopHandleStageException(self):
    """Called when PerformStage throws an unhandled exception.

    Should only be called by the Run function.  Provides a wrapper around
    _HandleStageException to handle buggy handlers.  We must go deeper...
    """
    exc_info = sys.exc_info()
    try:
      return self._HandleStageException(exc_info)
    except Exception:
      logging.error(
          'An exception was thrown while running _HandleStageException')
      logging.error('The original exception was:', exc_info=exc_info)
      logging.error('The new exception is:', exc_info=True)
      return self._HandleExceptionAsError(exc_info)

  def HandleSkip(self):
    """Run if the stage is skipped."""
    # This is a hook used by some subclasses.

  def _RecordResult(self, *args, **kwargs):
    """Record a successful or failed result."""
    results_lib.Results.Record(*args, **kwargs)

  def _ShouldSkipStage(self):
    """Decide if we were requested to skip this stage."""
    return (
        self.option_name and not getattr(self._run.options, self.option_name) or
        self.config_name and not getattr(self._run.config, self.config_name))

  def Run(self):
    """Have the builder execute the stage."""
    skip_stage = self._ShouldSkipStage()
    previous_record = results_lib.Results.PreviouslyCompletedRecord(self.name)
    if skip_stage:
      # We do not log the beginning of a skipped stage.
      pass
    elif previous_record is not None:
      self._BeginStepForBuildbot(' : [PREVIOUSLY PROCESSED]')
    else:
      self._BeginStepForBuildbot()

    try:
      # Set default values
      result = None
      cidb_result = None
      description = None
      board = ''
      elapsed_time = None
      start_time = time.time()

      if skip_stage:
        self._StartBuildStageInCIDB()
        self.HandleSkip()
        result = results_lib.Results.SKIPPED
        return

      if previous_record:
        self._StartBuildStageInCIDB()
        self._PrintLoudly('Stage %s processed previously' % self.name)
        self.HandleSkip()
        # Success is stored in the results log for a stage that completed
        # successfully in a previous run. But, we report the truth to CIDB.
        result = results_lib.Results.SUCCESS
        cidb_result = constants.BUILDER_STATUS_SKIPPED
        # Copy over metadata from the previous record. instead of returning
        # metadata about the current run.
        board = previous_record.board
        elapsed_time = float(previous_record.time)
        return

      self._WaitBuildStageInCIDB()
      ready = self.WaitUntilReady()
      if not ready:
        self._PrintLoudly(
            'Stage %s precondition failed while waiting to start.' % self.name)
        # If WaitUntilReady is false, mark stage as skipped in Results and CIDB
        result = results_lib.Results.SKIPPED
        return

      #  Ready to start, mark buildStage as inflight in CIDB
      self._Print('Preconditions for the stage successfully met. '
                  'Beginning to execute stage...')
      self._StartBuildStageInCIDB()

      start_time = time.time()
      sys.stdout.flush()
      sys.stderr.flush()
      # TODO(davidjames): Verify that PerformStage always returns None. See
      # crbug.com/264781
      self.PerformStage()
      result = results_lib.Results.SUCCESS
    except SystemExit as e:
      if e.code != 0:
        result, description, _ = self._TopHandleStageException()

      raise
    except Exception as e:
      if isinstance(e, failures_lib.ExitEarlyException):
        # One stage finished and exited early, not a failure.
        result = results_lib.Results.SUCCESS
        raise

      # Tell the build bot this step failed for the waterfall.
      result, description, retrying = self._TopHandleStageException()
      if result not in (results_lib.Results.FORGIVEN,
                        results_lib.Results.SUCCESS):
        if isinstance(e, failures_lib.StepFailure):
          raise
        else:
          raise failures_lib.StepFailure()
      elif retrying:
        raise failures_lib.RetriableStepFailure()
    except BaseException:
      result, description, _ = self._TopHandleStageException()
      raise
    finally:
      # Some cases explicitly set a cidb status. For others, infer.
      if cidb_result is None:
        cidb_result = self._TranslateResultToCIDBStatus(result)
      if elapsed_time is None:
        elapsed_time = time.time() - start_time

      self._RecordResult(
          self.name,
          result,
          description,
          prefix=self._prefix,
          board=board,
          time=elapsed_time,
          build_stage_id=None)
      self._FinishBuildStageInCIDBAndMonarch(result, cidb_result, elapsed_time)

      try:
        self.Finish()
      except Exception as e:
        # Failures here are OUTSIDE of the stage and not handled well. Log and
        # continue with the assumption that the ReportStage will re-upload this
        # data or report a failure correctly.
        logging.warning('IGNORED: Finish failure: %s', e)

      self._PrintLoudly('Finished Stage %s - %s' %
                        (self.name, cros_build_lib.UserDateTimeFormat()))

      sys.stdout.flush()
      sys.stderr.flush()


class NonHaltingBuilderStage(BuilderStage):
  """Build stage that fails a build but finishes the other steps."""

  def Run(self):
    try:
      super(NonHaltingBuilderStage, self).Run()
    except failures_lib.StepFailure:
      name = self.__class__.__name__
      logging.error('Ignoring StepFailure in %s', name)


class ForgivingBuilderStage(BuilderStage):
  """Build stage that turns a build step red but not a build."""

  def _HandleStageException(self, exc_info):
    """Override and don't set status to FAIL but FORGIVEN instead."""
    return self._HandleExceptionAsWarning(exc_info)


class RetryStage(object):
  """Retry a given stage multiple times to see if it passes."""
  category = constants.UNCATEGORIZED_STAGE

  def __init__(self, builder_run, buildstore, max_retry, stage, *args,
               **kwargs):
    """Create a RetryStage object.

    Args:
      builder_run: See arguments to BuilderStage.__init__()
      buildstore: BuildStore instance to make DB calls with.
      max_retry: The number of times to try the given stage.
      stage: The stage class to create.
      *args: A list of arguments to pass to the stage constructor.
      **kwargs: A list of keyword arguments to pass to the stage constructor.
    """
    self._run = builder_run
    self.buildstore = buildstore
    self.max_retry = max_retry
    self.stage = stage
    self.args = (builder_run, buildstore,) + args
    self.kwargs = kwargs
    self.names = []
    self._build_stage_ids = []
    self.attempt = None

  def GetStageNames(self):
    """Get a list of the places where this stage has recorded results."""
    return self.names[:]

  def GetBuildStageIDs(self):
    """Get a list of build stage ids in cidb corresponding to this stage."""
    return self._build_stage_ids[:]

  def _PerformStage(self):
    """Run the stage once, incrementing the attempt number as needed."""
    suffix = ' (attempt %d)' % (self.attempt,)
    stage_obj = self.stage(
        *self.args,
        attempt=self.attempt,
        max_retry=self.max_retry,
        suffix=suffix,
        **self.kwargs)
    self.names.extend(stage_obj.GetStageNames())
    self._build_stage_ids.extend(stage_obj.GetBuildStageIDs())
    self.attempt += 1
    stage_obj.Run()

  def Run(self):
    """Retry the given stage multiple times to see if it passes."""
    self.attempt = 1
    retry_util.RetryException(failures_lib.RetriableStepFailure, self.max_retry,
                              self._PerformStage)


class RepeatStage(object):
  """Run a given stage multiple times to see if it fails."""
  category = constants.UNCATEGORIZED_STAGE

  def __init__(self, builder_run, buildstore, count, stage, *args, **kwargs):
    """Create a RepeatStage object.

    Args:
      builder_run: See arguments to BuilderStage.__init__()
      buildstore: BuildStore instance to make DB calls with.
      count: The number of times to try the given stage.
      stage: The stage class to create.
      *args: A list of arguments to pass to the stage constructor.
      **kwargs: A list of keyword arguments to pass to the stage constructor.
    """
    self._run = builder_run
    self.buildstore = buildstore
    self.count = count
    self.stage = stage
    self.args = (builder_run,) + args
    self.kwargs = kwargs
    self.names = []
    self._build_stage_ids = []
    self.attempt = None

  def GetStageNames(self):
    """Get a list of the places where this stage has recorded results."""
    return self.names[:]

  def GetBuildStageIDs(self):
    """Get a list of build stage ids in cidb corresponding to this stage."""
    return self._build_stage_ids[:]

  def _PerformStage(self):
    """Run the stage once."""
    suffix = ' (attempt %d)' % (self.attempt,)
    stage_obj = self.stage(
        *self.args, attempt=self.attempt, suffix=suffix, **self.kwargs)
    self.names.extend(stage_obj.GetStageNames())
    self._build_stage_ids.extend(stage_obj.GetBuildStageIDs())
    stage_obj.Run()

  def Run(self):
    """Retry the given stage multiple times to see if it passes."""
    for i in range(self.count):
      self.attempt = i + 1
      self._PerformStage()


class BoardSpecificBuilderStage(BuilderStage):
  """Builder stage that is specific to a board.

  The following attributes are provided on self:
    _current_board: The active board for this stage.
    board_runattrs: BoardRunAttributes object for this stage.
  """

  def __init__(self, builder_run, buildstore, board, suffix=None, **kwargs):
    if not isinstance(board, six.string_types):
      raise TypeError('Expected string, got %r' % (board,))

    self._current_board = board

    self.board_runattrs = builder_run.GetBoardRunAttrs(board)

    # Add a board name suffix to differentiate between various boards (in case
    # more than one board is built on a single builder.)
    if len(builder_run.config.boards) > 1 or builder_run.config.grouped:
      suffix = self.UpdateSuffix(board, suffix)

    super(BoardSpecificBuilderStage, self).__init__(
        builder_run, buildstore, suffix=suffix, **kwargs)

  def _RecordResult(self, *args, **kwargs):
    """Record a successful or failed result."""
    kwargs.setdefault('board', self._current_board)
    super(BoardSpecificBuilderStage, self)._RecordResult(*args, **kwargs)

  def _InsertBuildStageInCIDB(self,
                              name,
                              board=None,
                              status=constants.BUILDER_STATUS_PLANNED):
    """Insert a build stage in cidb."""
    if not board:
      board = self._current_board
    super(BoardSpecificBuilderStage, self)._InsertBuildStageInCIDB(
        name, board, status)

  def GetListOfPackagesToBuild(self):
    """Returns a list of packages to build."""

    # If we have defined explicit packages to build for ChromeOS Findit
    # integration, add those to the list of _run.config.packages to build.
    packages = []
    if self._run.options.cbb_build_packages:
      logging.info('Adding list of packages to build for ChromeOS Findit: %s',
                   self._run.options.cbb_build_packages)
      packages += self._run.options.cbb_build_packages
    if self._run.config.packages:
      packages += self._run.config.packages

    # Short circuit if there are any Findit or explicit builds specified.
    if packages:
      return packages

    # TODO: the logic below is duplicated from the build_packages
    # script. Once we switch to `cros build`, we should consolidate
    # the logic in a shared location.
    packages += [constants.TARGET_OS_PKG]
    # Build Dev packages by default.
    packages += [constants.TARGET_OS_DEV_PKG]
    # Build test packages by default.
    packages += [constants.TARGET_OS_TEST_PKG]
    # Build factory packages if requested by config.
    if self._run.config.factory:
      packages += [
          'virtual/target-os-factory', 'virtual/target-os-factory-shim'
      ]

    if self._run.ShouldBuildAutotest():
      packages += ['chromeos-base/autotest-all']

    return packages

  def GetParallel(self, board_attr, timeout=None, pretty_name=None):
    """Wait for given |board_attr| to show up.

    Args:
      board_attr: A valid board runattribute name.
      timeout: Timeout in seconds.  None value means wait forever.
      pretty_name: Optional name to use instead of raw board_attr in
        log messages.

    Returns:
      Value of board_attr found.

    Raises:
      AttrTimeoutError if timeout occurs.
    """
    timeout_str = 'forever'
    if timeout is not None:
      timeout_str = '%d minutes' % int((timeout / 60.0) + 0.5)

    if pretty_name is None:
      pretty_name = board_attr

    logging.info('Waiting up to %s for %s ...', timeout_str, pretty_name)
    return self.board_runattrs.GetParallel(board_attr, timeout=timeout)

  def GetImageDirSymlink(self, pointer='latest-cbuildbot', buildroot=None):
    """Get the location of the current image."""

    if not buildroot:
      buildroot = self._run.buildroot

    return os.path.join(buildroot, 'src', 'build', 'images',
                        self._current_board, pointer)


class ArchivingStageMixin(object):
  """Stage with utilities for uploading artifacts.

  This provides functionality for doing archiving.  All it needs is access
  to the BuilderRun object at self._run.  No __init__ needed.

  Attributes:
    acl: GS ACL to use for uploads.
    archive: Archive object.
    archive_path: Local path where archives are kept for this run.  Also copy
      of self.archive.archive_path.
    download_url: The URL where artifacts for this run can be downloaded.
      Also copy of self.archive.download_url.
    upload_url: The Google Storage location where artifacts for this run should
      be uploaded.  Also copy of self.archive.upload_url.
    version: Copy of self.archive.version.
  """

  PROCESSES = 10

  @property
  def archive(self):
    """Retrieve the Archive object to use."""
    # pylint: disable=attribute-defined-outside-init
    if not hasattr(self, '_archive'):
      self._archive = self._run.GetArchive()

    return self._archive

  @property
  def acl(self):
    """Retrieve GS ACL to use for uploads."""
    return self.archive.upload_acl

  # TODO(mtennant): Get rid of this property.
  @property
  def version(self):
    """Retrieve the ChromeOS version for the archiving."""
    return self.archive.version

  @property
  def archive_path(self):
    """Local path where archives are kept for this run."""
    return self.archive.archive_path

  @property
  def upload_url(self):
    """The GS location where artifacts should be uploaded for this run."""
    return self.archive.upload_url

  @property
  def download_url(self):
    """The URL where artifacts for this run can be downloaded."""
    return self.archive.download_url

  @contextlib.contextmanager
  def ArtifactUploader(self, queue=None, archive=True, strict=True):
    """Upload each queued input in the background.

    This context manager starts a set of workers in the background, who each
    wait for input on the specified queue. These workers run
    self.UploadArtifact(*args, archive=archive) for each input in the queue.

    Args:
      queue: Queue to use. Add artifacts to this queue, and they will be
        uploaded in the background.  If None, one will be created on the fly.
      archive: Whether to automatically copy files to the archive dir.
      strict: Whether to treat upload errors as fatal.

    Returns:
      The queue to use. This is only useful if you did not supply a queue.
    """
    upload = lambda path: self.UploadArtifact(path, archive, strict)
    with parallel.BackgroundTaskRunner(
        upload, queue=queue, processes=self.PROCESSES) as bg_queue:
      yield bg_queue

  def PrintDownloadLink(self, filename, prefix='', text_to_display=None):
    """Log a link to an artifact in Google Storage and return the URL.

    Args:
      filename: The filename of the uploaded file.
      prefix: The prefix to put in front of the filename.
      text_to_display: Text to display. If None, use |prefix| + |filename|.

    Returns:
      The download URL.
    """
    url = '%s/%s' % (self.download_url.rstrip('/'), filename)
    if not text_to_display:
      text_to_display = '%s%s' % (prefix, filename)
    logging.PrintBuildbotLink(text_to_display, url)
    return url

  def _IsInUploadBlacklist(self, filename):
    """Check if this file is blacklisted to go into a board's extra buckets.

    Args:
      filename: The filename of the file we want to check is in the blacklist.

    Returns:
      True if the file is blacklisted, False otherwise.
    """
    for blacklisted_file in constants.EXTRA_BUCKETS_FILES_BLACKLIST:
      if fnmatch.fnmatch(filename, blacklisted_file):
        return True
    return False

  def _FilterBuildFromMoblab(self, url, bot_id):
    """Deteminine if this is a build that should not be copied to moblab.

    Args:
      url: The gs url of the target bucket.
      bot_id: The name of the bot

    Returns:
      True is the build should not be copied to this moblab url
    """
    bot_filter_list = ['paladin', 'trybot', 'pfq', 'pre-cq', 'tryjob',
                       'postsubmit']
    if ('moblab' in url and
        any(filter in bot_id for filter in bot_filter_list)):
      return True
    return False

  def _GetUploadUrls(self, filename, builder_run=None, prefix=None):
    """Returns a list of all urls for which to upload filename to.

    Args:
      filename: The filename of the file we want to upload.
      builder_run: builder_run object from which to get the board, base upload
                   url, and bot_id. If none, this stage's values.
    """
    board = None
    urls = [self.upload_url]
    bot_id = self._bot_id
    if builder_run:
      urls = [builder_run.GetArchive().upload_url]
      bot_id = builder_run.GetArchive().bot_id
      if (builder_run.config['boards'] and
          len(builder_run.config['boards']) == 1):
        board = builder_run.config['boards'][0]
    if (not self._IsInUploadBlacklist(filename) and
        (hasattr(self, '_current_board') or board)):
      board = board or self._current_board
      custom_artifacts_file = portage_util.ReadOverlayFile(
          'scripts/artifacts.json', board=board,
          buildroot=self._build_root)
      if custom_artifacts_file is not None:
        json_file = json.loads(custom_artifacts_file)
        for url in json_file.get('extra_upload_urls', []):
          # Moblab users do not need the paladin, pfq or trybot
          # builds, filter those bots from extra uploads.
          if self._FilterBuildFromMoblab(url, bot_id):
            continue
          urls.append('/'.join([url, bot_id, self.version]))
    if prefix:
      urls = [u + '/' + prefix for u in urls]
    return urls

  @failures_lib.SetFailureType(failures_lib.InfrastructureFailure)
  def UploadArtifact(self, path, archive=True, strict=True, prefix=None):
    """Upload generated artifact to Google Storage.

    Args:
      path: Path of local file to upload to Google Storage
        if |archive| is True. Otherwise, this is the name of the file
        in self.archive_path.
      archive: Whether to automatically copy files to the archive dir.
      strict: Whether to treat upload errors as fatal.
      prefix: When not None, add an additional directory prefix by this value.
    """
    filename = path
    if archive:
      filename = commands.ArchiveFile(path, self.archive_path)
    upload_urls = self._GetUploadUrls(filename, prefix=prefix)
    try:
      commands.UploadArchivedFile(
          self.archive_path,
          upload_urls,
          filename,
          self._run.options.debug_forced,
          update_list=True,
          acl=self.acl)
    except failures_lib.GSUploadFailure as e:
      logging.PrintBuildbotStepText('Upload failed')
      if e.HasFatalFailure(
          whitelist=[gs.GSContextException, timeout_util.TimeoutError]):
        raise
      elif strict:
        raise
      else:
        # Treat gsutil flake as a warning if it's the only problem.
        self._HandleExceptionAsWarning(sys.exc_info())

  @failures_lib.SetFailureType(failures_lib.InfrastructureFailure)
  def UploadMetadata(self,
                     upload_queue=None,
                     filename=constants.METADATA_JSON,
                     export=False):
    """Create and upload JSON file of the builder run's metadata, and to cidb.

    This uses the existing metadata stored in the builder run. The default
    metadata.json file should only be uploaded once, at the end of the run,
    and considered immutable. During the build, intermediate metadata snapshots
    can be uploaded to other files, such as partial-metadata.json.

    This method also updates the metadata in the cidb database, if there is a
    valid cidb connection set up.

    Args:
      upload_queue: If specified then put the artifact file to upload on
        this queue.  If None then upload it directly now.
      filename: Name of file to dump metadata to.
                Defaults to constants.METADATA_JSON
      export: If true, constants.METADATA_TAGS will be exported to gcloud.

    Returns:
      If upload was successful or not
    """
    metadata_json = os.path.join(self.archive_path, filename)

    # Stages may run in parallel, so we have to do atomic updates on this.
    logging.info('Writing metadata to %s.', metadata_json)
    osutils.WriteFile(
        metadata_json,
        self._run.attrs.metadata.GetJSON(),
        atomic=True,
        makedirs=True)

    if upload_queue is not None:
      logging.info('Adding metadata file %s to upload queue.', metadata_json)
      upload_queue.put([filename])
    else:
      logging.info('Uploading metadata file %s now.', metadata_json)
      self.UploadArtifact(filename, archive=False)

    build_identifier, _ = self._run.GetCIDBHandle()
    build_id = build_identifier.cidb_id
    if self.buildstore.AreClientsReady():
      logging.info('Writing updated metadata to database for build_id %s.',
                   build_id)
      self.buildstore.UpdateMetadata(build_id, self._run.attrs.metadata)
      if export:
        d = self._run.attrs.metadata.GetDict()
        if constants.METADATA_TAGS in d:
          c_file = topology.topology.get(topology.DATASTORE_WRITER_CREDS_KEY)
          if c_file:
            with tempfile.NamedTemporaryFile() as f:
              logging.info('Export tags to gcloud via %s.', f.name)
              logging.debug('Exporting: %s', d[constants.METADATA_TAGS])
              osutils.WriteFile(
                  f.name,
                  json.dumps(d[constants.METADATA_TAGS]),
                  atomic=True,
                  makedirs=True)
              commands.ExportToGCloud(
                  self._build_root, c_file, f.name, caller=type(self).__name__)
          else:
            logging.warn('No datastore credential file found, Skipping Export')
            return False
    else:
      logging.info('Skipping database update, no database or build_id.')
      return False
    return True
