# Copyright (c) 2011 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 implementation of an au_worker for virtual machines."""

import os
import shutil

import constants
from chromite.lib import cros_build_lib
from crostestutils.au_test_harness import au_worker
from crostestutils.au_test_harness import update_exception


class VMAUWorker(au_worker.AUWorker):
  """Test harness for updating virtual machines."""

  def __init__(self, options, test_results_root):
    """Processes vm-specific options."""
    super(VMAUWorker, self).__init__(options, test_results_root)
    self.graphics_flag = ''
    if options.no_graphics: self.graphics_flag = '--no_graphics'
    if not self.board:
      cros_build_lib.Die('Need board to convert base image to vm.')
    self.whitelist_chrome_crashes = options.whitelist_chrome_crashes

  def _KillExistingVM(self, pid_file):
    """Kills an existing VM specified by the pid_file."""
    if os.path.exists(pid_file):
      cmd = ['./bin/cros_stop_vm', '--kvm_pid=%s' % pid_file]
      cros_build_lib.RunCommand(cmd, print_cmd=False, error_code_ok=True,
                                cwd=constants.CROSUTILS_DIR)

  def CleanUp(self):
    """Stop the vm after a test."""
    self._KillExistingVM(self._kvm_pid_file)

  def PrepareBase(self, image_path, signed_base=False):
    """Creates an update-able VM based on base image."""
    self.PrepareVMBase(image_path, signed_base)

  @staticmethod
  def _HandleFail(log_directory, fail_directory):
    parent_dir = os.path.dirname(fail_directory)
    if not os.path.isdir(parent_dir):
      os.makedirs(parent_dir)

    try:
      shutil.copytree(log_directory, fail_directory)
    except shutil.Error as e:
      cros_build_lib.Warning('Ignoring errors %s', e)

  def UpdateImage(self, image_path, src_image_path='', stateful_change='old',
                  proxy_port='', private_key_path=None):
    """Updates VM image with image_path."""
    log_directory, fail_directory = self.GetNextResultsPath('update')
    stateful_change_flag = self.GetStatefulChangeFlag(stateful_change)
    if src_image_path and self._first_update:
      src_image_path = self.vm_image_path
      self._first_update = False

    cmd = ['%s/bin/cros_run_vm_update' % constants.CROSUTILS_DIR,
           '--vm_image_path=%s' % self.vm_image_path,
           '--update_log=%s' % os.path.join(log_directory, 'update_engine.log'),
           '--copy',
           self.graphics_flag,
           '--persist',
           '--kvm_pid=%s' % self._kvm_pid_file,
           '--ssh_port=%s' % self._ssh_port,
           stateful_change_flag,
          ]
    self.AppendUpdateFlags(cmd, image_path, src_image_path, proxy_port,
                           private_key_path)
    self.TestInfo(self.GetUpdateMessage(image_path, src_image_path, True,
                                        proxy_port))
    try:
      self.RunUpdateCmd(cmd, log_directory)
    except update_exception.UpdateException:
      self._HandleFail(log_directory, fail_directory)
      raise

  def UpdateUsingPayload(self, update_path, stateful_change='old',
                         proxy_port=None):
    """Updates a vm image using cros_run_vm_update."""
    log_directory, fail_directory = self.GetNextResultsPath('update')
    stateful_change_flag = self.GetStatefulChangeFlag(stateful_change)
    cmd = ['%s/bin/cros_run_vm_update' % constants.CROSUTILS_DIR,
           '--payload=%s' % update_path,
           '--vm_image_path=%s' % self.vm_image_path,
           '--update_log=%s' % os.path.join(log_directory, 'update_engine.log'),
           '--copy',
           self.graphics_flag,
           '--persist',
           '--kvm_pid=%s' % self._kvm_pid_file,
           '--ssh_port=%s' % self._ssh_port,
           stateful_change_flag,
          ]
    if proxy_port: cmd.append('--proxy_port=%s' % proxy_port)
    self.TestInfo(self.GetUpdateMessage(update_path, None, True, proxy_port))
    try:
      self.RunUpdateCmd(cmd, log_directory)
    except update_exception.UpdateException:
      self._HandleFail(log_directory, fail_directory)
      raise

  def AppendUpdateFlags(self, cmd, image_path, src_image_path, proxy_port,
                        private_key_path, for_vm=False):
    """Appends common args to an update cmd defined by an array.

    Calls super function with for_vm set to True.

    Args:
      See AppendUpdateFlags for description of args.
    """
    super(VMAUWorker, self).AppendUpdateFlags(
        cmd, image_path, src_image_path, proxy_port, private_key_path,
        for_vm=True)

  # pylint: disable-msg=W0221
  def VerifyImage(self, test=''):
    """Runs vm smoke suite or any single test to verify image.

    Returns True upon success.  Prints test output and returns False otherwise.
    """
    log_directory, fail_directory = self.GetNextResultsPath('autotest_tests')
    (_, _, log_directory_in_chroot) = log_directory.rpartition('chroot')
    # image_to_live already verifies lsb-release matching.  This is just
    # for additional steps.
    if not test: test = self.verify_suite

    command = ['./bin/cros_run_vm_test',
               '--board=%s' % self.board,
               '--image_path=%s' % self.vm_image_path,
               '--copy',
               '--persist',
               '--kvm_pid=%s' % self._kvm_pid_file,
               '--ssh_port=%s' % self._ssh_port,
               '--results_dir_root=%s' % log_directory_in_chroot,
               '--verbose=0',
               test,
              ]
    if self.graphics_flag: command.append(self.graphics_flag)
    if self.whitelist_chrome_crashes:
      command.append('--whitelist_chrome_crashes')
    self.TestInfo('Running smoke suite to verify image.')
    result = cros_build_lib.RunCommandCaptureOutput(
        command, print_cmd=False, combine_stdout_stderr=True,
        cwd=constants.CROSUTILS_DIR, error_code_ok=True)

    # If the command failed or printed warnings, print the output.
    if result.returncode != 0 or '@@@STEP_WARNINGS@@@' in result.output:
      print result.output
      self._HandleFail(log_directory, fail_directory)

    return result.returncode == 0
