# Copyright 2015 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.

"""Stage a custom image on a Moblab device or in Google Storage."""

from __future__ import print_function

import httplib
import os
import re
import shutil
import urllib2

from chromite.cbuildbot import commands, constants
from chromite.cli import command
from chromite.lib import cros_build_lib
from chromite.lib import cros_logging as logging
from chromite.lib import dev_server_wrapper
from chromite.lib import gs
from chromite.lib import remote_access
from chromite.lib import osutils


DEVSERVER_STATIC_DIR = cros_build_lib.FromChrootPath(
    os.path.join(constants.CHROOT_SOURCE_ROOT, 'devserver', 'static'))
MOBLAB_STATIC_DIR = '/mnt/moblab/static'
MOBLAB_TMP_DIR = os.path.join(MOBLAB_STATIC_DIR, 'tmp')
BOARD_BUILD_DIR = 'usr/local/build'
DEVSERVER_STAGE_URL = ('http://%(moblab)s:8080/stage?local_path=%(staged_dir)s'
                       '&artifacts=full_payload,stateful,test_suites,'
                       'control_files,autotest_packages')
CUSTOM_BUILD_NAME = '%(board)s-custom/%(build)s'


class CustomImageStagingException(Exception):
  """Thrown when there is an error staging an custom image."""


def GSURLRegexHelper(gsurl):
  """Helper to do regex matching on a Google Storage URL

  Args:
    gsurl: Google Storage URL to match.

  Returns:
    Regex Match Object with groups(board, type, & build_name) or None if there
    was no match.
  """
  return re.match(r'gs://.*/(trybot-)?(?P<board>[\w-]+)-(?P<type>\w+)/'
                  r'(?P<build_name>R\d+-[\d.ab-]+)', gsurl)


@command.CommandDecorator('stage')
class StageCommand(command.CliCommand):
  """Remotely stages an image onto a MobLab device or into Google Storage.

  The image to be staged may be a local custom image built in the chroot or an
  official image in Google Storage. The test binaries will always come from the
  local build root regardless of the image source.

  This script generates/copies the update payloads and test binaries required.
  It then stages them on the Moblab's devserver or copies them into the
  specified Google Storage Bucket.

  The image name to then use for testing is outputted at the end of this
  script.
  """

  EPILOG = """
To stage a local image path onto a moblab device:
  cros stage /path/to/board/build/chromiumos-test-image.bin <moblab>

To stage an official image with custom test binaries onto a moblab device:
  cros stage <gs_image_dir> <moblab>

To stage a local image path into a Google Storage Bucket:
  cros stage /path/to/board/build/chromiumos-test-image.bin <gs_base_path>
    --boto_file=<boto_file_path>

NOTES:
* The autotest bits used to test this image will be the latest in your
  build sysroot! I.E. if you emerge new autotest changes after producing the
  image you wish to stage, there is a chance that the changes will not match.
* The custom image will only stay on the Moblab device for 24 hours at which
  point it will be wiped.
"""

  @classmethod
  def AddParser(cls, parser):
    """Add parser arguments."""
    super(StageCommand, cls).AddParser(parser)
    parser.add_argument(
        'image', nargs='?', default='latest', help='Path to image we want to '
        'stage. If a local path, it should be in the format of '
        '/.../.../board/build/<image>.bin . If a Google Storage path it should'
        'be in the format of '
        'gs://<bucket-name>/<board>-<builder type>/<build name>')
    parser.add_argument(
        'remote', help='MobLab device that has password-less SSH set up via '
        'the chroot already. Or Google Storage Bucket in the form of '
        'gs://<bucket-name>/')
    parser.add_argument(
        '--boto_file', dest='boto_file', default=None,
        help='Path to boto file to use when uploading to Google Storage. If '
        'none the default chroot boto file is used.')

  def __init__(self, options):
    """Initializes cros stage."""
    super(StageCommand, self).__init__(options)
    self.board = None
    # Determine if we are staging a local custom image or an official image.
    if self.options.image.startswith('gs://'):
      self._remote_image = True
      self.staged_image_name = self._GenerateImageNameFromGSUrl(
          self.options.image)
    else:
      self._remote_image = False
      self.staged_image_name = self._GenerateImageNameFromLocalPath(
          self.options.image)
    self.stage_directory = os.path.join(MOBLAB_TMP_DIR, self.staged_image_name)

    # Determine if the staging destination is a Moblab or Google Storage.
    if self.options.remote.startswith('gs://'):
      self._remote_is_moblab = False
    else:
      self._remote_is_moblab = True

  def _GenerateImageNameFromLocalPath(self, image):
    """Generate the name as which |image| will be staged onto Moblab.

    Args:
      image: Path to image we want to stage. It should be in the format of
             /.../.../board/build/<image>.bin

    Returns:
      Name the image will be staged as.

    Raises:
      CustomImageStagingException: If the image name supplied is not valid.
    """
    realpath = osutils.ExpandPath(image)
    if not realpath.endswith('.bin'):
      raise CustomImageStagingException(
          'Image path: %s does not end in .bin !' % realpath)
    build_name = os.path.basename(os.path.dirname(realpath))
    # Custom builds are name with the suffix of '-a1' but the build itself
    # is missing this suffix in its filesystem. Therefore lets rename the build
    # name to match the name inside the build.
    if build_name.endswith('-a1'):
      build_name = build_name[:-len('-a1')]

    self.board = os.path.basename(os.path.dirname(os.path.dirname(realpath)))
    return CUSTOM_BUILD_NAME % dict(board=self.board, build=build_name)

  def _GenerateImageNameFromGSUrl(self, image):
    """Generate the name as which |image| will be staged onto Moblab.

    Args:
      image: GS Url to the image we want to stage. It should be in the format
             gs://<bucket-name>/<board>-<builder type>/<build name>

    Returns:
      Name the image will be staged as.

    Raises:
      CustomImageStagingException: If the image name supplied is not valid.
    """
    match = GSURLRegexHelper(image)
    if not match:
      raise CustomImageStagingException(
          'Image URL: %s is improperly defined!' % image)
    self.board = match.group('board')
    return CUSTOM_BUILD_NAME % dict(board=self.board,
                                    build=match.group('build_name'))

  def _DownloadPayloads(self, tempdir):
    """Download from GS the update payloads we require.

    Args:
      tempdir: Temporary Directory to store the downloaded payloads.
    """
    gs_context = gs.GSContext(boto_file=self.options.boto_file)
    gs_context.Copy(os.path.join(self.options.image, 'stateful.tgz'), tempdir)
    gs_context.Copy(os.path.join(self.options.image, '*_full*'), tempdir)

  def _GeneratePayloads(self, tempdir):
    """Generate the update payloads we require.

    Args:
      tempdir: Temporary Directory to store the generated payloads.
    """
    dev_server_wrapper.GetUpdatePayloadsFromLocalPath(
        self.options.image, tempdir, static_dir=DEVSERVER_STATIC_DIR)
    rootfs_payload = os.path.join(tempdir, dev_server_wrapper.ROOTFS_FILENAME)
    # Devservers will look for a file named *_full_*.
    shutil.move(rootfs_payload, os.path.join(tempdir, 'update_full_dev.bin'))

  def _GenerateTestBits(self, tempdir):
    """Generate and transfer to the Moblab the test bits we require.

    Args:
      tempdir: Temporary Directory to store the generated test artifacts.
    """
    build_root = cros_build_lib.GetSysroot(board=self.board)
    cwd = os.path.join(build_root, BOARD_BUILD_DIR)
    tarball_funcs = [commands.BuildAutotestControlFilesTarball,
                     commands.BuildAutotestPackagesTarball,
                     commands.BuildAutotestTestSuitesTarball]
    for tarball_func in tarball_funcs:
      tarball_func(build_root, cwd, tempdir)

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

    Args:
      tempdir: Temporary Directory that contains the generated payloads and
               test bits.
    """
    with remote_access.ChromiumOSDeviceHandler(self.options.remote) as device:
      device.RunCommand(['mkdir', '-p', self.stage_directory])
      for f in os.listdir(tempdir):
        device.CopyToDevice(os.path.join(tempdir, f), self.stage_directory)
      device.RunCommand(['chown', '-R', 'moblab:moblab',
                         MOBLAB_TMP_DIR])
      # Delete this image from the Devserver in case it was previously staged.
      device.RunCommand(['rm', '-rf', os.path.join(MOBLAB_STATIC_DIR,
                                                   self.staged_image_name)])
      try:
        stage_url = DEVSERVER_STAGE_URL % dict(moblab=self.options.remote,
                                               staged_dir=self.stage_directory)
        res = urllib2.urlopen(stage_url).read()
      except (urllib2.HTTPError, httplib.HTTPException, urllib2.URLError) as e:
        logging.error('Unable to stage artifacts on moblab. Error: %s', e)
      else:
        if res == 'Success':
          logging.info('\n\nStaging Completed!')
          logging.info('Image is staged on Moblab as %s',
                       self.staged_image_name)
        else:
          logging.info('Staging failed. Error Message: %s', res)
      finally:
        device.RunCommand(['rm', '-rf', self.stage_directory])

  def _StageOnGS(self, tempdir):
    """Stage the generated payloads and test bits into a Google Storage bucket.

    Args:
      tempdir: Temporary Directory that contains the generated payloads and
               test bits.
    """
    gs_context = gs.GSContext(boto_file=self.options.boto_file)
    for f in os.listdir(tempdir):
      gs_context.CopyInto(os.path.join(tempdir, f), os.path.join(
          self.options.remote, self.staged_image_name))
    logging.info('\n\nStaging Completed!')
    logging.info('Image is staged in Google Storage as %s',
                 self.staged_image_name)

  def Run(self):
    """Perform the cros stage command."""
    logging.info('Attempting to stage: %s as Image: %s at Location: %s',
                 self.options.image, self.staged_image_name,
                 self.options.remote)
    osutils.SafeMakedirsNonRoot(DEVSERVER_STATIC_DIR)

    with osutils.TempDir() as tempdir:
      if self._remote_image:
        self._DownloadPayloads(tempdir)
      else:
        self._GeneratePayloads(tempdir)
      self._GenerateTestBits(tempdir)
      if self._remote_is_moblab:
        self._StageOnMoblab(tempdir)
      else:
        self._StageOnGS(tempdir)
