#
#

# Copyright (C) 2014 Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


"""Performance testing QA tests.

"""

import datetime
import functools
import itertools
import threading
import time

from ganeti import constants

import qa_config
import qa_error
from qa_instance_utils import GetGenericAddParameters
import qa_job_utils
import qa_logging
import qa_utils


MAX_JOB_SUBMISSION_DURATION = 15.0


class _JobQueueDriver(object):
  """This class handles polling of jobs and reacting on status changes.

  Jobs are added via the L{AddJob} method, and can have callback functions
  assigned to them. Those are called as soon as the job enters the appropriate
  state. Callback functions can add new jobs to the driver as needed.

  A call to L{WaitForCompletion} finally polls Ganeti until all jobs have
  succeeded.

  """

  _UNKNOWN_STATUS = "unknown"

  class _JobEntry(object):
    """Internal class representing a job entry.

    """
    def __init__(self, job_id, running_fn, success_fn):
      self.job_id = job_id
      self.running_fn = running_fn
      self.success_fn = success_fn

    def __str__(self):
      return str(self.job_id)

  def __init__(self):
    self._jobs = {}
    self._running_notified = set()
    self._jobs_per_status = {}
    self._lock = threading.RLock()

  def AddJob(self, job_id, running_fn=None, success_fn=None):
    """Add a job to the driver.

    @type job_id: of ints
    @param job_id: job id to add to the driver
    @type running_fn: function taking a L{_JobQueueDriver} and an int
    @param running_fn: function called once when a job changes to running state
                       (or success state, if the running state was too short)
    @type success_fn: function taking a L{_JobQueueDriver} and an int
    @param success_fn: function called for each successful job id

    """
    with self._lock:
      self._jobs[job_id] = _JobQueueDriver._JobEntry(job_id,
                                                     running_fn,
                                                     success_fn)
      # the status will be updated on the next call to _FetchJobStatuses
      self._jobs_per_status.setdefault(self._UNKNOWN_STATUS, []).append(job_id)

  def _FetchJobStatuses(self):
    """Retrieves status information of the given jobs.

    """
    job_statuses = qa_job_utils.GetJobStatuses(self._GetJobIds())

    new_statuses = {}
    for job_id, status in job_statuses.items():
      new_statuses.setdefault(status, []).append(self._jobs[int(job_id)])
    self._jobs_per_status = new_statuses

  def _GetJobIds(self):
    return list(self._jobs.keys())

  def _GetJobsInStatuses(self, statuses):
    """Returns a list of L{_JobEntry} of all jobs in the given statuses.

    @type statuses: iterable of strings
    @param statuses: jobs in those statuses are returned
    @rtype: list of L{_JobEntry}
    @return: list of job entries in the requested statuses

    """
    ret = []
    for state in statuses:
      ret.extend(self._jobs_per_status.get(state, []))
    return ret

  def _UpdateJobStatuses(self):
    """Retrieves job statuses from the cluster and updates internal state.

    """
    self._FetchJobStatuses()
    error_jobs = self._GetJobsInStatuses([constants.JOB_STATUS_ERROR])
    if error_jobs:
      raise qa_error.Error(
        "Jobs %s are in error state!" % [job.job_id for job in error_jobs])

    for job in self._GetJobsInStatuses([constants.JOB_STATUS_RUNNING,
                                        constants.JOB_STATUS_SUCCESS]):
      if job.job_id not in self._running_notified:
        if job.running_fn is not None:
          job.running_fn(self, job.job_id)
        self._running_notified.add(job.job_id)

    for job in self._GetJobsInStatuses([constants.JOB_STATUS_SUCCESS]):
      if job.success_fn is not None:
        job.success_fn(self, job.job_id)

      # we're done with this job
      del self._jobs[job.job_id]

  def _HasPendingJobs(self):
    """Checks if there are still jobs pending.

    @rtype: bool
    @return: C{True} if there are still jobs which have not succeeded

    """
    with self._lock:
      self._UpdateJobStatuses()
      uncompleted_jobs = self._GetJobsInStatuses(
        constants.JOB_STATUS_ALL - constants.JOBS_FINALIZED)
      unknown_jobs = self._GetJobsInStatuses([self._UNKNOWN_STATUS])
      return len(uncompleted_jobs) > 0 or len(unknown_jobs) > 0

  def WaitForCompletion(self):
    """Wait for the completion of all registered jobs.

    """
    while self._HasPendingJobs():
      time.sleep(2)

    with self._lock:
      if self._jobs:
        raise qa_error.Error(
          "Jobs %s didn't finish in success state!" % self._GetJobIds())


def _AcquireAllInstances():
  """Generator for acquiring all instances in the QA config.

  """
  try:
    while True:
      instance = qa_config.AcquireInstance()
      yield instance
  except qa_error.OutOfInstancesError:
    pass


def _AcquireAllNodes():
  """Generator for acquiring all nodes in the QA config.

  """
  exclude = []
  try:
    while True:
      node = qa_config.AcquireNode(exclude=exclude)
      exclude.append(node)
      yield node
  except qa_error.OutOfNodesError:
    pass


def _ExecuteJobSubmittingCmd(cmd):
  """Executes a job submitting command and returns the resulting job ID.

  This will fail if submitting the job takes longer than
  L{MAX_JOB_SUBMISSION_DURATION}.

  @type cmd: list of string or string
  @param cmd: the job producing command to execute on the cluster
  @rtype: int
  @return: job-id

  """
  start = datetime.datetime.now()
  result = qa_job_utils.ExecuteJobProducingCommand(cmd)
  duration = qa_utils.TimedeltaToTotalSeconds(datetime.datetime.now() - start)
  if duration > MAX_JOB_SUBMISSION_DURATION:
    print(qa_logging.FormatWarning(
      "Executing '%s' took %f seconds, a maximum of %f was expected" %
      (cmd, duration, MAX_JOB_SUBMISSION_DURATION)))
  return result


def _SubmitInstanceCreationJob(instance, disk_template=None):
  """Submit an instance creation job.

  @type instance: L{qa_config._QaInstance}
  @param instance: instance to submit a create command for
  @type disk_template: string
  @param disk_template: disk template for the new instance or C{None} which
                        causes the default disk template to be used
  @rtype: int
  @return: job id of the submitted creation job

  """
  if disk_template is None:
    disk_template = qa_config.GetDefaultDiskTemplate()
  try:
    cmd = (["gnt-instance", "add", "--submit",
            "--os-type=%s" % qa_config.get("os"),
            "--disk-template=%s" % disk_template] +
           GetGenericAddParameters(instance, disk_template))
    cmd.append(instance.name)

    instance.SetDiskTemplate(disk_template)

    return _ExecuteJobSubmittingCmd(cmd)
  except:
    instance.Release()
    raise


def _SubmitInstanceRemoveJob(instance):
  """Submit an instance remove job.

  @type instance: L{qa_config._QaInstance}
  @param instance: the instance to remove
  @rtype: int
  @return: job id of the submitted remove job

  """
  try:
    cmd = (["gnt-instance", "remove", "--submit", "-f"])
    cmd.append(instance.name)

    return _ExecuteJobSubmittingCmd(cmd)
  finally:
    instance.Release()


def _TestParallelInstanceCreationAndRemoval(max_instances=None,
                                            disk_template=None,
                                            custom_job_driver=None):
  """Tests parallel creation and immediate removal of instances.

  @type max_instances: int
  @param max_instances: maximum number of instances to create
  @type disk_template: string
  @param disk_template: disk template for the new instances or C{None} which
                        causes the default disk template to be used
  @type custom_job_driver: _JobQueueDriver
  @param custom_job_driver: a custom L{_JobQueueDriver} to use if not L{None}.
                            If one is specified, C{WaitForCompletion} is _not_
                            called on it.

  """
  job_driver = custom_job_driver or _JobQueueDriver()

  def _CreateSuccessFn(instance, job_driver, _):
    job_id = _SubmitInstanceRemoveJob(instance)
    job_driver.AddJob(job_id)

  instance_generator = _AcquireAllInstances()
  if max_instances is not None:
    instance_generator = itertools.islice(instance_generator, max_instances)

  for instance in instance_generator:
    job_id = _SubmitInstanceCreationJob(instance, disk_template=disk_template)
    job_driver.AddJob(
      job_id, success_fn=functools.partial(_CreateSuccessFn, instance))

  if custom_job_driver is None:
    job_driver.WaitForCompletion()


def TestParallelMaxInstanceCreationPerformance():
  """PERFORMANCE: Parallel instance creation (instance count = max).

  """
  _TestParallelInstanceCreationAndRemoval()


def TestParallelNodeCountInstanceCreationPerformance():
  """PERFORMANCE: Parallel instance creation (instance count = node count).

  """
  nodes = list(_AcquireAllNodes())
  _TestParallelInstanceCreationAndRemoval(max_instances=len(nodes))
  qa_config.ReleaseManyNodes(nodes)


def CreateAllInstances():
  """Create all instances configured in QA config in the cluster.

  @rtype: list of L{qa_config._QaInstance}
  @return: list of instances created in the cluster

  """
  job_driver = _JobQueueDriver()
  instances = list(_AcquireAllInstances())
  for instance in instances:
    job_id = _SubmitInstanceCreationJob(instance)
    job_driver.AddJob(job_id)

  job_driver.WaitForCompletion()
  return instances


def RemoveAllInstances(instances):
  """Removes all given instances from the cluster.

  @type instances: list of L{qa_config._QaInstance}
  @param instances:

  """
  job_driver = _JobQueueDriver()
  for instance in instances:
    job_id = _SubmitInstanceRemoveJob(instance)
    job_driver.AddJob(job_id)

  job_driver.WaitForCompletion()


def TestParallelModify(instances):
  """PERFORMANCE: Parallel instance modify.

  @type instances: list of L{qa_config._QaInstance}
  @param instances: list of instances to issue modify commands against

  """
  job_driver = _JobQueueDriver()
  # set min mem to same value as max mem
  new_min_mem = qa_config.get(constants.BE_MAXMEM)
  for instance in instances:
    cmd = (["gnt-instance", "modify", "--submit",
            "-B", "%s=%s" % (constants.BE_MINMEM, new_min_mem)])
    cmd.append(instance.name)
    job_driver.AddJob(_ExecuteJobSubmittingCmd(cmd))

    cmd = (["gnt-instance", "modify", "--submit",
            "-O", "fake_os_param=fake_value"])
    cmd.append(instance.name)
    job_driver.AddJob(_ExecuteJobSubmittingCmd(cmd))

    cmd = (["gnt-instance", "modify", "--submit",
            "-O", "fake_os_param=fake_value",
            "-B", "%s=%s" % (constants.BE_MINMEM, new_min_mem)])
    cmd.append(instance.name)
    job_driver.AddJob(_ExecuteJobSubmittingCmd(cmd))

  job_driver.WaitForCompletion()


def TestParallelInstanceOSOperations(instances):
  """PERFORMANCE: Parallel instance OS operations.

  Note: This test leaves the instances either running or stopped, there's no
  guarantee on the actual status.

  @type instances: list of L{qa_config._QaInstance}
  @param instances: list of instances to issue lifecycle commands against

  """
  OPS = ["start", "shutdown", "reboot", "reinstall"]
  job_driver = _JobQueueDriver()

  def _SubmitNextOperation(instance, start, idx, job_driver, _):
    if idx == len(OPS):
      return
    op_idx = (start + idx) % len(OPS)

    next_fn = functools.partial(_SubmitNextOperation, instance, start, idx + 1)

    if OPS[op_idx] == "reinstall" and \
        instance.disk_template == constants.DT_DISKLESS:
      # no reinstall possible with diskless instances
      next_fn(job_driver, None)
      return
    elif OPS[op_idx] == "reinstall":
      # the instance has to be shut down for reinstall to work
      shutdown_cmd = ["gnt-instance", "shutdown", "--submit", instance.name]
      cmd = ["gnt-instance", "reinstall", "--submit", "-f", instance.name]

      job_driver.AddJob(_ExecuteJobSubmittingCmd(shutdown_cmd),
                        running_fn=lambda _, __: job_driver.AddJob(
                          _ExecuteJobSubmittingCmd(cmd),
                          running_fn=next_fn))
    else:
      cmd = ["gnt-instance", OPS[op_idx], "--submit"]
      if OPS[op_idx] == "reinstall":
        cmd.append("-f")
      cmd.append(instance.name)

      job_id = _ExecuteJobSubmittingCmd(cmd)
      job_driver.AddJob(job_id, running_fn=next_fn)

  for start, instance in enumerate(instances):
    _SubmitNextOperation(instance, start % len(OPS), 0, job_driver, None)

  job_driver.WaitForCompletion()


def TestParallelInstanceQueries(instances):
  """PERFORMANCE: Parallel instance queries.

  @type instances: list of L{qa_config._QaInstance}
  @param instances: list of instances to issue queries against

  """
  threads = qa_job_utils.QAThreadGroup()
  for instance in instances:
    cmd = ["gnt-instance", "info", instance.name]
    info_thread = qa_job_utils.QAThread(qa_utils.AssertCommand, [cmd], {})
    threads.Start(info_thread)

    cmd = ["gnt-instance", "list"]
    list_thread = qa_job_utils.QAThread(qa_utils.AssertCommand, [cmd], {})
    threads.Start(list_thread)

  threads.JoinAndReraise()


def TestJobQueueSubmissionPerformance():
  """PERFORMANCE: Job queue submission performance.

  This test exercises the job queue and verifies that the job submission time
  does not increase as more jobs are added.

  """
  MAX_CLUSTER_INFO_SECONDS = 15.0
  job_driver = _JobQueueDriver()
  submission_durations = []

  def _VerifySubmissionDuration(duration_seconds):
    # only start to verify the submission duration once we got data from the
    # first 10 job submissions
    if len(submission_durations) >= 10:
      avg_duration = sum(submission_durations) / len(submission_durations)
      max_duration = avg_duration * 1.5
      if duration_seconds > max_duration:
        print(qa_logging.FormatWarning(
          "Submitting a delay job took %f seconds, max %f expected" %
          (duration_seconds, max_duration)))
    else:
      submission_durations.append(duration_seconds)

  def _SubmitDelayJob(count):
    for _ in range(count):
      cmd = ["gnt-debug", "delay", "--submit", "0.1"]

      start = datetime.datetime.now()
      job_id = _ExecuteJobSubmittingCmd(cmd)
      duration_seconds = \
        qa_utils.TimedeltaToTotalSeconds(datetime.datetime.now() - start)
      _VerifySubmissionDuration(duration_seconds)

      job_driver.AddJob(job_id)

  threads = qa_job_utils.QAThreadGroup()
  for i in range(10):
    thread = qa_job_utils.QAThread(_SubmitDelayJob, [20], {})
    threads.Start(thread)

  threads.JoinAndReraise()

  qa_utils.AssertCommand(["gnt-cluster", "info"],
                         max_seconds=MAX_CLUSTER_INFO_SECONDS)

  job_driver.WaitForCompletion()


def TestParallelDRBDInstanceCreationPerformance():
  """PERFORMANCE: Parallel DRBD backed instance creation.

  """
  assert qa_config.IsTemplateSupported(constants.DT_DRBD8)

  nodes = list(_AcquireAllNodes())
  _TestParallelInstanceCreationAndRemoval(max_instances=len(nodes) * 2,
                                          disk_template=constants.DT_DRBD8)
  qa_config.ReleaseManyNodes(nodes)


def TestParallelPlainInstanceCreationPerformance():
  """PERFORMANCE: Parallel plain backed instance creation.

  """
  assert qa_config.IsTemplateSupported(constants.DT_PLAIN)

  nodes = list(_AcquireAllNodes())
  _TestParallelInstanceCreationAndRemoval(max_instances=len(nodes) * 2,
                                          disk_template=constants.DT_PLAIN)
  qa_config.ReleaseManyNodes(nodes)


def _TestInstanceOperationInParallelToInstanceCreation(*cmds):
  """Run the given test command in parallel to an instance creation.

  @type cmds: list of list of strings
  @param cmds: commands to execute in parallel to an instance creation. Each
               command in the list is executed once the previous job starts
               to run.

  """
  def _SubmitNextCommand(cmd_idx, job_driver, _):
    if cmd_idx >= len(cmds):
      return
    job_id = _ExecuteJobSubmittingCmd(cmds[cmd_idx])
    job_driver.AddJob(
      job_id, running_fn=functools.partial(_SubmitNextCommand, cmd_idx + 1))

  assert qa_config.IsTemplateSupported(constants.DT_DRBD8)
  assert len(cmds) > 0

  job_driver = _JobQueueDriver()
  _SubmitNextCommand(0, job_driver, None)

  _TestParallelInstanceCreationAndRemoval(max_instances=1,
                                          disk_template=constants.DT_DRBD8,
                                          custom_job_driver=job_driver)

  job_driver.WaitForCompletion()


def TestParallelInstanceFailover(instance):
  """PERFORMANCE: Instance failover with parallel instance creation.

  """
  _TestInstanceOperationInParallelToInstanceCreation(
    ["gnt-instance", "failover", "--submit", "-f", "--shutdown-timeout=0",
     instance.name])


def TestParallelInstanceMigration(instance):
  """PERFORMANCE: Instance migration with parallel instance creation.

  """
  _TestInstanceOperationInParallelToInstanceCreation(
    ["gnt-instance", "migrate", "--submit", "-f", instance.name])


def TestParallelInstanceReplaceDisks(instance):
  """PERFORMANCE: Instance replace-disks with parallel instance creation.

  """
  _TestInstanceOperationInParallelToInstanceCreation(
    ["gnt-instance", "replace-disks", "--submit", "--early-release", "-p",
     instance.name])


def TestParallelInstanceReboot(instance):
  """PERFORMANCE: Instance reboot with parallel instance creation.

  """
  _TestInstanceOperationInParallelToInstanceCreation(
    ["gnt-instance", "reboot", "--submit", instance.name])


def TestParallelInstanceReinstall(instance):
  """PERFORMANCE: Instance reinstall with parallel instance creation.

  """
  # instance reinstall requires the instance to be down
  qa_utils.AssertCommand(["gnt-instance", "stop", instance.name])

  _TestInstanceOperationInParallelToInstanceCreation(
    ["gnt-instance", "reinstall", "--submit", "-f", instance.name])

  qa_utils.AssertCommand(["gnt-instance", "start", instance.name])


def TestParallelInstanceRename(instance):
  """PERFORMANCE: Instance rename with parallel instance creation.

  """
  # instance rename requires the instance to be down
  qa_utils.AssertCommand(["gnt-instance", "stop", instance.name])

  new_instance = qa_config.AcquireInstance()
  try:
    _TestInstanceOperationInParallelToInstanceCreation(
      ["gnt-instance", "rename", "--submit", instance.name, new_instance.name],
      ["gnt-instance", "rename", "--submit", new_instance.name, instance.name])
  finally:
    new_instance.Release()

  qa_utils.AssertCommand(["gnt-instance", "start", instance.name])
