#
#

# Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 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.


"""Remote API QA tests.

"""

import copy
import functools
import itertools
import os.path
import random
import re
import tempfile
import uuid as uuid_module

from ganeti import cli
from ganeti import compat
from ganeti import constants
from ganeti import errors
from ganeti import locking
from ganeti import objects
from ganeti import opcodes
from ganeti import pathutils
from ganeti import qlang
from ganeti import query
from ganeti import rapi
from ganeti import utils

from ganeti.http.auth import ParsePasswordFile
import ganeti.rapi.client        # pylint: disable=W0611
import ganeti.rapi.client_utils

import qa_config
import qa_error
import qa_logging
import qa_utils

from qa_instance import GetInstanceInfo
from qa_instance import IsDiskReplacingSupported
from qa_instance import IsFailoverSupported
from qa_instance import IsMigrationSupported
from qa_job_utils import RunWithLocks
from qa_utils import (AssertEqual, AssertIn, AssertMatch, AssertCommand,
                      StartLocalCommand)
from qa_utils import InstanceCheck, INST_DOWN, INST_UP, FIRST_ARG


_rapi_ca = None
_rapi_client = None
_rapi_username = None
_rapi_password = None

# The files to copy if the RAPI files QA config value is set
_FILES_TO_COPY = [
  pathutils.CLUSTER_DOMAIN_SECRET_FILE,
  pathutils.RAPI_CERT_FILE,
  pathutils.RAPI_USERS_FILE,
]


def _EnsureRapiFilesPresence():
  """Ensures that the specified RAPI files are present on the cluster, if any.

  """
  rapi_files_location = qa_config.get("rapi-files-location", None)
  if rapi_files_location is None:
    # No files to be had
    return

  print qa_logging.FormatWarning("Replacing the certificate and users file on"
                                 " the node with the ones provided in %s"
                                 % rapi_files_location)

  # The RAPI files
  AssertCommand(["mkdir", "-p", pathutils.RAPI_DATA_DIR])

  for filename in _FILES_TO_COPY:
    basename = os.path.split(filename)[-1]
    AssertCommand(["cp", os.path.join(rapi_files_location, basename),
                   filename])
    AssertCommand(["gnt-cluster", "copyfile", filename])

  # The certificates have to be reloaded now
  AssertCommand(["service", "ganeti", "restart"])


def ReloadCertificates(ensure_presence=True):
  """Reloads the client RAPI certificate with the one present on the node.

  If the QA is set up to use a specific certificate using the
  "rapi-files-location" parameter, it will be put in place prior to retrieving
  it.

  """
  if ensure_presence:
    _EnsureRapiFilesPresence()

  if _rapi_username is None or _rapi_password is None:
    raise qa_error.Error("RAPI username and password have to be set before"
                         " attempting to reload a certificate.")

  # pylint: disable=W0603
  # due to global usage
  global _rapi_ca
  global _rapi_client

  master = qa_config.GetMasterNode()

  # Load RAPI certificate from master node
  cmd = ["openssl", "x509", "-in",
         qa_utils.MakeNodePath(master, pathutils.RAPI_CERT_FILE)]

  # Write to temporary file
  _rapi_ca = tempfile.NamedTemporaryFile()
  _rapi_ca.write(qa_utils.GetCommandOutput(master.primary,
                                           utils.ShellQuoteArgs(cmd)))
  _rapi_ca.flush()

  port = qa_config.get("rapi-port", default=constants.DEFAULT_RAPI_PORT)
  cfg_curl = rapi.client.GenericCurlConfig(cafile=_rapi_ca.name,
                                           proxy="")

  if qa_config.UseVirtualCluster():
    # TODO: Implement full support for RAPI on virtual clusters
    print qa_logging.FormatWarning("RAPI tests are not yet supported on"
                                   " virtual clusters and will be disabled")

    assert _rapi_client is None
  else:
    _rapi_client = rapi.client.GanetiRapiClient(master.primary, port=port,
                                                username=_rapi_username,
                                                password=_rapi_password,
                                                curl_config_fn=cfg_curl)

    print "RAPI protocol version: %s" % _rapi_client.GetVersion()


#TODO(riba): Remove in 2.13, used just by rapi-workload which disappears there
def GetClient():
  """Retrieves the RAPI client prepared by this module.

  """
  return _rapi_client


def _CreateRapiUser(rapi_user):
  """RAPI credentials creation, with the secret auto-generated.

  """
  rapi_secret = utils.GenerateSecret()

  master = qa_config.GetMasterNode()

  rapi_users_path = qa_utils.MakeNodePath(master, pathutils.RAPI_USERS_FILE)
  rapi_dir = os.path.dirname(rapi_users_path)

  fh = tempfile.NamedTemporaryFile()
  try:
    fh.write("%s %s write\n" % (rapi_user, rapi_secret))
    fh.flush()

    tmpru = qa_utils.UploadFile(master.primary, fh.name)
    try:
      AssertCommand(["mkdir", "-p", rapi_dir])
      AssertCommand(["mv", tmpru, rapi_users_path])
    finally:
      AssertCommand(["rm", "-f", tmpru])
  finally:
    fh.close()

  # The certificates have to be reloaded now
  AssertCommand(["service", "ganeti", "restart"])

  return rapi_secret


def _LookupRapiSecret(rapi_user):
  """Find the RAPI secret for the given user on the QA machines.

  @param rapi_user: Login user
  @return: Login secret for the user

  """
  CTEXT = "{CLEARTEXT}"
  master = qa_config.GetMasterNode()
  cmd = ["cat", qa_utils.MakeNodePath(master, pathutils.RAPI_USERS_FILE)]
  file_content = qa_utils.GetCommandOutput(master.primary,
                                           utils.ShellQuoteArgs(cmd))
  users = ParsePasswordFile(file_content)
  entry = users.get(rapi_user)
  if not entry:
    raise qa_error.Error("User %s not found in RAPI users file" % rapi_user)
  secret = entry.password
  if secret.upper().startswith(CTEXT):
    secret = secret[len(CTEXT):]
  elif secret.startswith("{"):
    raise qa_error.Error("Unsupported password schema for RAPI user %s:"
                         " not a clear text password" % rapi_user)
  return secret


def _ReadRapiSecret(password_file_path):
  """Reads a RAPI secret stored locally.

  @type password_file_path: string
  @return: Login secret for the user

  """
  try:
    with open(password_file_path, 'r') as pw_file:
      return pw_file.readline().strip()
  except IOError:
    raise qa_error.Error("Could not open the RAPI password file located at"
                         " %s" % password_file_path)


def _GetRapiSecret(rapi_user):
  """Returns the secret to be used for RAPI access.

  Where exactly this secret can be found depends on the QA configuration
  options, and this function invokes additional tools as needed. It can
  look up a local secret, a remote one, or create a user with a new secret.

  @param rapi_user: Login user
  @return: Login secret for the user

  """
  password_file_path = qa_config.get("rapi-password-file", None)
  if password_file_path is not None:
    # If the password file is specified, we use the password within.
    # The file must be present on the QA runner.
    return _ReadRapiSecret(password_file_path)
  else:
    # On an existing cluster, just find out the user's secret
    return _LookupRapiSecret(rapi_user)


def SetupRapi():
  """Sets up the RAPI certificate and usernames for the client.

  """
  if not Enabled():
    return (None, None)

  # pylint: disable=W0603
  # due to global usage
  global _rapi_username
  global _rapi_password

  _rapi_username = qa_config.get("rapi-user", "ganeti-qa")

  if qa_config.TestEnabled("create-cluster") and \
     qa_config.get("rapi-files-location") is None:
    # For a new cluster, we have to invent a secret and a user, unless it has
    # been provided separately
    _rapi_password = _CreateRapiUser(_rapi_username)
  else:
    _EnsureRapiFilesPresence()
    _rapi_password = _GetRapiSecret(_rapi_username)

  # Once a username and password have been set, we can fetch the certs and
  # get all we need for a working RAPI client.
  ReloadCertificates(ensure_presence=False)


INSTANCE_FIELDS = ("name", "os", "pnode", "snodes",
                   "admin_state",
                   "disk_template", "disk.sizes", "disk.spindles",
                   "nic.ips", "nic.macs", "nic.modes", "nic.links",
                   "beparams", "hvparams",
                   "oper_state", "oper_ram", "oper_vcpus", "status", "tags")

NODE_FIELDS = ("name", "dtotal", "dfree", "sptotal", "spfree",
               "mtotal", "mnode", "mfree",
               "pinst_cnt", "sinst_cnt", "tags")

GROUP_FIELDS = compat.UniqueFrozenset([
  "name", "uuid",
  "alloc_policy",
  "node_cnt", "node_list",
  ])

JOB_FIELDS = compat.UniqueFrozenset([
  "id", "ops", "status", "summary",
  "opstatus", "opresult", "oplog",
  "received_ts", "start_ts", "end_ts",
  ])

FILTER_FIELDS = compat.UniqueFrozenset([
  "watermark",
  "priority",
  "predicates",
  "action",
  "reason_trail",
  "uuid",
  ])

LIST_FIELDS = ("id", "uri")


def Enabled():
  """Return whether remote API tests should be run.

  """
  # TODO: Implement RAPI tests for virtual clusters
  return (qa_config.TestEnabled("rapi") and
          not qa_config.UseVirtualCluster())


def _DoTests(uris):
  # pylint: disable=W0212
  # due to _SendRequest usage
  results = []

  for uri, verify, method, body in uris:
    assert uri.startswith("/")

    print "%s %s" % (method, uri)
    data = _rapi_client._SendRequest(method, uri, None, body)

    if verify is not None:
      if callable(verify):
        verify(data)
      else:
        AssertEqual(data, verify)

    results.append(data)

  return results


# pylint: disable=W0212
# Due to _SendRequest usage
def _DoGetPutTests(get_uri, modify_uri, opcode_params, rapi_only_aliases=None,
                   modify_method="PUT", exceptions=None, set_exceptions=None):
  """ Test if all params of an object can be retrieved, and set as well.

  @type get_uri: string
  @param get_uri: The URI from which information about the object can be
                  retrieved.
  @type modify_uri: string
  @param modify_uri: The URI which can be used to modify the object.
  @type opcode_params: list of tuple
  @param opcode_params: The parameters of the underlying opcode, used to
                        determine which parameters are actually present.
  @type rapi_only_aliases: list of string or None
  @param rapi_only_aliases: Aliases for parameters which differ from the opcode,
                            and become renamed before opcode submission.
  @type modify_method: string
  @param modify_method: The method to be used in the modification.
  @type exceptions: list of string or None
  @param exceptions: The parameters which have not been exposed and should not
                     be tested at all.
  @type set_exceptions: list of string or None
  @param set_exceptions: The parameters whose setting should not be tested as a
                         part of this test.

  """

  assert get_uri.startswith("/")
  assert modify_uri.startswith("/")

  if exceptions is None:
    exceptions = []
  if set_exceptions is None:
    set_exceptions = []

  print "Testing get/modify symmetry of %s and %s" % (get_uri, modify_uri)

  # First we see if all parameters of the opcode are returned through RAPI
  params_of_interest = map(lambda x: x[0], opcode_params)

  # The RAPI-specific aliases are to be checked as well
  if rapi_only_aliases is not None:
    params_of_interest.extend(rapi_only_aliases)

  info = _rapi_client._SendRequest("GET", get_uri, None, {})

  missing_params = filter(lambda x: x not in info and x not in exceptions,
                          params_of_interest)
  if missing_params:
    raise qa_error.Error("The parameters %s which can be set through the "
                         "appropriate opcode are not present in the response "
                         "from %s" % (','.join(missing_params), get_uri))

  print "GET successful at %s" % get_uri

  # Then if we can perform a set with the same values as received
  put_payload = {}
  for param in params_of_interest:
    if param not in exceptions and param not in set_exceptions:
      put_payload[param] = info[param]

  _rapi_client._SendRequest(modify_method, modify_uri, None, put_payload)

  print "%s successful at %s" % (modify_method, modify_uri)
# pylint: enable=W0212


def _VerifyReturnsJob(data):
  if not isinstance(data, int):
    AssertMatch(data, r"^\d+$")


def TestVersion():
  """Testing remote API version.

  """
  _DoTests([
    ("/version", constants.RAPI_VERSION, "GET", None),
    ])


def TestEmptyCluster():
  """Testing remote API on an empty cluster.

  """
  master = qa_config.GetMasterNode()
  master_full = qa_utils.ResolveNodeName(master)

  def _VerifyInfo(data):
    AssertIn("name", data)
    AssertIn("master", data)
    AssertEqual(data["master"], master_full)

  def _VerifyNodes(data):
    master_entry = {
      "id": master_full,
      "uri": "/2/nodes/%s" % master_full,
      }
    AssertIn(master_entry, data)

  def _VerifyNodesBulk(data):
    for node in data:
      for entry in NODE_FIELDS:
        AssertIn(entry, node)

  def _VerifyGroups(data):
    default_group = {
      "name": constants.INITIAL_NODE_GROUP_NAME,
      "uri": "/2/groups/" + constants.INITIAL_NODE_GROUP_NAME,
      }
    AssertIn(default_group, data)

  def _VerifyGroupsBulk(data):
    for group in data:
      for field in GROUP_FIELDS:
        AssertIn(field, group)

  def _VerifyFiltersBulk(data):
    for group in data:
      for field in FILTER_FIELDS:
        AssertIn(field, group)

  _DoTests([
    ("/", None, "GET", None),
    ("/2/info", _VerifyInfo, "GET", None),
    ("/2/tags", None, "GET", None),
    ("/2/nodes", _VerifyNodes, "GET", None),
    ("/2/nodes?bulk=1", _VerifyNodesBulk, "GET", None),
    ("/2/groups", _VerifyGroups, "GET", None),
    ("/2/groups?bulk=1", _VerifyGroupsBulk, "GET", None),
    ("/2/instances", [], "GET", None),
    ("/2/instances?bulk=1", [], "GET", None),
    ("/2/os", None, "GET", None),
    ("/2/filters", [], "GET", None),
    ("/2/filters?bulk=1", _VerifyFiltersBulk, "GET", None),
    ])

  # Test HTTP Not Found
  for method in ["GET", "PUT", "POST", "DELETE"]:
    try:
      _DoTests([("/99/resource/not/here/99", None, method, None)])
    except rapi.client.GanetiApiError, err:
      AssertEqual(err.code, 404)
    else:
      raise qa_error.Error("Non-existent resource didn't return HTTP 404")

  # Test HTTP Not Implemented
  for method in ["PUT", "POST", "DELETE"]:
    try:
      _DoTests([("/version", None, method, None)])
    except rapi.client.GanetiApiError, err:
      AssertEqual(err.code, 501)
    else:
      raise qa_error.Error("Non-implemented method didn't fail")

  # Test GET/PUT symmetry
  LEGITIMATELY_MISSING = [
    "force",       # Standard option
    "add_uids",    # Modifies UID pool, is not a param itself
    "remove_uids", # Same as above
    "osparams_private_cluster", # Should not be returned
  ]
  NOT_EXPOSED_YET = ["hv_state", "disk_state", "modify_etc_hosts"]
  # The nicparams are returned under the default entry, yet accepted as they
  # are - this is a TODO to fix!
  DEFAULT_ISSUES = ["nicparams"]
  # Cannot be set over RAPI due to security issues
  FORBIDDEN_PARAMS = ["compression_tools"]

  _DoGetPutTests("/2/info", "/2/modify", opcodes.OpClusterSetParams.OP_PARAMS,
                 exceptions=(LEGITIMATELY_MISSING + NOT_EXPOSED_YET),
                 set_exceptions=DEFAULT_ISSUES + FORBIDDEN_PARAMS)


def TestRapiQuery():
  """Testing resource queries via remote API.

  """
  # FIXME: the tests are failing if no LVM is enabled, investigate
  # if it is a bug in the QA or in the code
  if not qa_config.IsStorageTypeSupported(constants.ST_LVM_VG):
    return

  master_name = qa_utils.ResolveNodeName(qa_config.GetMasterNode())
  rnd = random.Random(7818)

  for what in constants.QR_VIA_RAPI:
    namefield = {
      constants.QR_JOB: "id",
      constants.QR_EXPORT: "export",
      constants.QR_FILTER: "uuid",
    }.get(what, "name")

    all_fields = query.ALL_FIELDS[what].keys()
    rnd.shuffle(all_fields)

    # No fields, should return everything
    result = _rapi_client.QueryFields(what)
    qresult = objects.QueryFieldsResponse.FromDict(result)
    AssertEqual(len(qresult.fields), len(all_fields))

    # One field
    result = _rapi_client.QueryFields(what, fields=[namefield])
    qresult = objects.QueryFieldsResponse.FromDict(result)
    AssertEqual(len(qresult.fields), 1)

    # Specify all fields, order must be correct
    result = _rapi_client.QueryFields(what, fields=all_fields)
    qresult = objects.QueryFieldsResponse.FromDict(result)
    AssertEqual(len(qresult.fields), len(all_fields))
    AssertEqual([fdef.name for fdef in qresult.fields], all_fields)

    # Unknown field
    result = _rapi_client.QueryFields(what, fields=["_unknown!"])
    qresult = objects.QueryFieldsResponse.FromDict(result)
    AssertEqual(len(qresult.fields), 1)
    AssertEqual(qresult.fields[0].name, "_unknown!")
    AssertEqual(qresult.fields[0].kind, constants.QFT_UNKNOWN)

    # Try once more, this time without the client
    _DoTests([
      ("/2/query/%s/fields" % what, None, "GET", None),
      ("/2/query/%s/fields?fields=%s,%s,%s" % (what, namefield, namefield,
                                               all_fields[0]),
       None, "GET", None),
      ])

    # Try missing query argument
    try:
      _DoTests([
        ("/2/query/%s" % what, None, "GET", None),
        ])
    except rapi.client.GanetiApiError, err:
      AssertEqual(err.code, 400)
    else:
      raise qa_error.Error("Request missing 'fields' parameter didn't fail")

    def _Check(exp_fields, data):
      qresult = objects.QueryResponse.FromDict(data)
      AssertEqual([fdef.name for fdef in qresult.fields], exp_fields)
      if not isinstance(qresult.data, list):
        raise qa_error.Error("Query did not return a list")

    _DoTests([
      # Specify fields in query
      ("/2/query/%s?fields=%s" % (what, ",".join(all_fields)),
       compat.partial(_Check, all_fields), "GET", None),

      ("/2/query/%s?fields=%s" % (what, namefield),
       compat.partial(_Check, [namefield]), "GET", None),

      # Note the spaces
      ("/2/query/%s?fields=%s,%%20%s%%09,%s%%20" %
       (what, namefield, namefield, namefield),
       compat.partial(_Check, [namefield] * 3), "GET", None)])

    if what in constants.QR_VIA_RAPI_PUT:
      _DoTests([
        # PUT with fields in query
        ("/2/query/%s?fields=%s" % (what, namefield),
         compat.partial(_Check, [namefield]), "PUT", {}),

        ("/2/query/%s" % what, compat.partial(_Check, [namefield] * 4), "PUT", {
           "fields": [namefield] * 4,
           }),

        ("/2/query/%s" % what, compat.partial(_Check, all_fields), "PUT", {
           "fields": all_fields,
           }),

        ("/2/query/%s" % what, compat.partial(_Check, [namefield] * 4), "PUT", {
           "fields": [namefield] * 4
         })])

    if what in constants.QR_VIA_RAPI_PUT:
      trivial_filter = {
        constants.QR_JOB: [qlang.OP_GE, namefield, 0],
      }.get(what, [qlang.OP_REGEXP, namefield, ".*"])

      _DoTests([
        # With filter
        ("/2/query/%s" % what, compat.partial(_Check, all_fields), "PUT", {
           "fields": all_fields,
           "filter": trivial_filter
           }),
        ])

    if what == constants.QR_NODE:
      # Test with filter
      (nodes, ) = _DoTests(
        [("/2/query/%s" % what,
          compat.partial(_Check, ["name", "master"]), "PUT",
          {"fields": ["name", "master"],
           "filter": [qlang.OP_TRUE, "master"],
           })])
      qresult = objects.QueryResponse.FromDict(nodes)
      AssertEqual(qresult.data, [
        [[constants.RS_NORMAL, master_name], [constants.RS_NORMAL, True]],
        ])


@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
def TestInstance(instance):
  """Testing getting instance(s) info via remote API.

  """
  def _VerifyInstance(data):
    for entry in INSTANCE_FIELDS:
      AssertIn(entry, data)

  def _VerifyInstancesList(data):
    for instance in data:
      for entry in LIST_FIELDS:
        AssertIn(entry, instance)

  def _VerifyInstancesBulk(data):
    for instance_data in data:
      _VerifyInstance(instance_data)

  _DoTests([
    ("/2/instances/%s" % instance.name, _VerifyInstance, "GET", None),
    ("/2/instances", _VerifyInstancesList, "GET", None),
    ("/2/instances?bulk=1", _VerifyInstancesBulk, "GET", None),
    ("/2/instances/%s/activate-disks" % instance.name,
     _VerifyReturnsJob, "PUT", None),
    ("/2/instances/%s/deactivate-disks" % instance.name,
     _VerifyReturnsJob, "PUT", None),
    ])

  # Test OpBackupPrepare
  (job_id, ) = _DoTests([
    ("/2/instances/%s/prepare-export?mode=%s" %
     (instance.name, constants.EXPORT_MODE_REMOTE),
     _VerifyReturnsJob, "PUT", None),
    ])

  result = _WaitForRapiJob(job_id)[0]
  AssertEqual(len(result["handshake"]), 3)
  AssertEqual(result["handshake"][0], constants.RIE_VERSION)
  AssertEqual(len(result["x509_key_name"]), 3)
  AssertIn("-----BEGIN CERTIFICATE-----", result["x509_ca"])


def TestNode(node):
  """Testing getting node(s) info via remote API.

  """
  def _VerifyNode(data):
    for entry in NODE_FIELDS:
      AssertIn(entry, data)

  def _VerifyNodesList(data):
    for node in data:
      for entry in LIST_FIELDS:
        AssertIn(entry, node)

  def _VerifyNodesBulk(data):
    for node_data in data:
      _VerifyNode(node_data)

  _DoTests([
    ("/2/nodes/%s" % node.primary, _VerifyNode, "GET", None),
    ("/2/nodes", _VerifyNodesList, "GET", None),
    ("/2/nodes?bulk=1", _VerifyNodesBulk, "GET", None),
    ])

  # Not parameters of the node, but controlling opcode behavior
  LEGITIMATELY_MISSING = ["force", "powered"]
  # Identifying the node - RAPI provides these itself
  IDENTIFIERS = ["node_name", "node_uuid"]
  # As the name states, these can be set but not retrieved yet
  NOT_EXPOSED_YET = ["hv_state", "disk_state", "auto_promote",
                     "debug", "verbose"]

  _DoGetPutTests("/2/nodes/%s" % node.primary,
                 "/2/nodes/%s/modify" % node.primary,
                 opcodes.OpNodeSetParams.OP_PARAMS,
                 modify_method="POST",
                 exceptions=(LEGITIMATELY_MISSING + NOT_EXPOSED_YET +
                             IDENTIFIERS))


def _FilterTags(seq):
  """Removes unwanted tags from a sequence.

  """
  ignore_re = qa_config.get("ignore-tags-re", None)

  if ignore_re:
    return itertools.ifilterfalse(re.compile(ignore_re).match, seq)
  else:
    return seq


def TestTags(kind, name, tags):
  """Tests .../tags resources.

  """
  if kind == constants.TAG_CLUSTER:
    uri = "/2/tags"
  elif kind == constants.TAG_NODE:
    uri = "/2/nodes/%s/tags" % name
  elif kind == constants.TAG_INSTANCE:
    uri = "/2/instances/%s/tags" % name
  elif kind == constants.TAG_NODEGROUP:
    uri = "/2/groups/%s/tags" % name
  elif kind == constants.TAG_NETWORK:
    uri = "/2/networks/%s/tags" % name
  else:
    raise errors.ProgrammerError("Unknown tag kind")

  def _VerifyTags(data):
    AssertEqual(sorted(tags), sorted(_FilterTags(data)))

  queryargs = "&".join("tag=%s" % i for i in tags)

  # Add tags
  (job_id, ) = _DoTests([
    ("%s?%s" % (uri, queryargs), _VerifyReturnsJob, "PUT", None),
    ])
  _WaitForRapiJob(job_id)

  # Retrieve tags
  _DoTests([
    (uri, _VerifyTags, "GET", None),
    ])

  # Remove tags
  (job_id, ) = _DoTests([
    ("%s?%s" % (uri, queryargs), _VerifyReturnsJob, "DELETE", None),
    ])
  _WaitForRapiJob(job_id)


def _WaitForRapiJob(job_id):
  """Waits for a job to finish.

  """
  def _VerifyJob(data):
    AssertEqual(data["id"], job_id)
    for field in JOB_FIELDS:
      AssertIn(field, data)

  _DoTests([
    ("/2/jobs/%s" % job_id, _VerifyJob, "GET", None),
    ])

  return rapi.client_utils.PollJob(_rapi_client, job_id,
                                   cli.StdioJobPollReportCb())


def TestRapiNodeGroups():
  """Test several node group operations using RAPI.

  """
  (group1, group2, group3) = qa_utils.GetNonexistentGroups(3)

  # Create a group with no attributes
  body = {
    "name": group1,
    }

  (job_id, ) = _DoTests([
    ("/2/groups", _VerifyReturnsJob, "POST", body),
    ])

  _WaitForRapiJob(job_id)

  # Create a group specifying alloc_policy
  body = {
    "name": group2,
    "alloc_policy": constants.ALLOC_POLICY_UNALLOCABLE,
    }

  (job_id, ) = _DoTests([
    ("/2/groups", _VerifyReturnsJob, "POST", body),
    ])

  _WaitForRapiJob(job_id)

  # Modify alloc_policy
  body = {
    "alloc_policy": constants.ALLOC_POLICY_UNALLOCABLE,
    }

  (job_id, ) = _DoTests([
    ("/2/groups/%s/modify" % group1, _VerifyReturnsJob, "PUT", body),
    ])

  _WaitForRapiJob(job_id)

  # Rename a group
  body = {
    "new_name": group3,
    }

  (job_id, ) = _DoTests([
    ("/2/groups/%s/rename" % group2, _VerifyReturnsJob, "PUT", body),
    ])

  _WaitForRapiJob(job_id)

  # Test for get/set symmetry

  # Identifying the node - RAPI provides these itself
  IDENTIFIERS = ["group_name"]
  # As the name states, not exposed yet
  NOT_EXPOSED_YET = ["hv_state", "disk_state"]

  # The parameters we do not want to get and set (as that sets the
  # group-specific params to the filled ones)
  FILLED_PARAMS = ["ndparams", "ipolicy", "diskparams"]

  # The aliases that we can use to perform this test with the group-specific
  # params
  CUSTOM_PARAMS = ["custom_ndparams", "custom_ipolicy", "custom_diskparams"]

  _DoGetPutTests("/2/groups/%s" % group3, "/2/groups/%s/modify" % group3,
                 opcodes.OpGroupSetParams.OP_PARAMS,
                 rapi_only_aliases=CUSTOM_PARAMS,
                 exceptions=(IDENTIFIERS + NOT_EXPOSED_YET),
                 set_exceptions=FILLED_PARAMS)

  # Delete groups
  for group in [group1, group3]:
    (job_id, ) = _DoTests([
      ("/2/groups/%s" % group, _VerifyReturnsJob, "DELETE", None),
      ])

    _WaitForRapiJob(job_id)


def TestRapiInstanceAdd(node, use_client):
  """Test adding a new instance via RAPI"""
  if not qa_config.IsTemplateSupported(constants.DT_PLAIN):
    return
  instance = qa_config.AcquireInstance()
  instance.SetDiskTemplate(constants.DT_PLAIN)
  try:
    disks = [{"size": utils.ParseUnit(d.get("size")),
              "name": str(d.get("name"))}
             for d in qa_config.GetDiskOptions()]
    nic0_mac = instance.GetNicMacAddr(0, constants.VALUE_GENERATE)
    nics = [{
      constants.INIC_MAC: nic0_mac,
      }]

    beparams = {
      constants.BE_MAXMEM: utils.ParseUnit(qa_config.get(constants.BE_MAXMEM)),
      constants.BE_MINMEM: utils.ParseUnit(qa_config.get(constants.BE_MINMEM)),
      }

    if use_client:
      job_id = _rapi_client.CreateInstance(constants.INSTANCE_CREATE,
                                           instance.name,
                                           constants.DT_PLAIN,
                                           disks, nics,
                                           os=qa_config.get("os"),
                                           pnode=node.primary,
                                           beparams=beparams)
    else:
      body = {
        "__version__": 1,
        "mode": constants.INSTANCE_CREATE,
        "name": instance.name,
        "os_type": qa_config.get("os"),
        "disk_template": constants.DT_PLAIN,
        "pnode": node.primary,
        "beparams": beparams,
        "disks": disks,
        "nics": nics,
        }

      (job_id, ) = _DoTests([
        ("/2/instances", _VerifyReturnsJob, "POST", body),
        ])

    _WaitForRapiJob(job_id)

    return instance
  except:
    instance.Release()
    raise


def _GenInstanceAllocationDict(node, instance):
  """Creates an instance allocation dict to be used with the RAPI"""
  instance.SetDiskTemplate(constants.DT_PLAIN)

  disks = [{"size": utils.ParseUnit(d.get("size")),
              "name": str(d.get("name"))}
             for d in qa_config.GetDiskOptions()]

  nic0_mac = instance.GetNicMacAddr(0, constants.VALUE_GENERATE)
  nics = [{
    constants.INIC_MAC: nic0_mac,
    }]

  beparams = {
    constants.BE_MAXMEM: utils.ParseUnit(qa_config.get(constants.BE_MAXMEM)),
    constants.BE_MINMEM: utils.ParseUnit(qa_config.get(constants.BE_MINMEM)),
    }

  return _rapi_client.InstanceAllocation(constants.INSTANCE_CREATE,
                                         instance.name,
                                         constants.DT_PLAIN,
                                         disks, nics,
                                         os=qa_config.get("os"),
                                         pnode=node.primary,
                                         beparams=beparams)


def TestRapiInstanceMultiAlloc(node):
  """Test adding two new instances via the RAPI instance-multi-alloc method"""
  if not qa_config.IsTemplateSupported(constants.DT_PLAIN):
    return

  JOBS_KEY = "jobs"

  instance_one = qa_config.AcquireInstance()
  instance_two = qa_config.AcquireInstance()
  instance_list = [instance_one, instance_two]
  try:
    rapi_dicts = map(functools.partial(_GenInstanceAllocationDict, node),
                     instance_list)

    job_id = _rapi_client.InstancesMultiAlloc(rapi_dicts)

    results, = _WaitForRapiJob(job_id)

    if JOBS_KEY not in results:
      raise qa_error.Error("RAPI instance-multi-alloc did not deliver "
                           "information about created jobs")

    if len(results[JOBS_KEY]) != len(instance_list):
      raise qa_error.Error("RAPI instance-multi-alloc failed to return the "
                           "desired number of jobs!")

    for success, job in results[JOBS_KEY]:
      if success:
        _WaitForRapiJob(job)
      else:
        raise qa_error.Error("Failed to create instance in "
                             "instance-multi-alloc call")
  except:
    # Note that although released, it may be that some of the instance creations
    # have in fact succeeded. Handling this in a better way may be possible, but
    # is not necessary as the QA has already failed at this point.
    for instance in instance_list:
      instance.Release()
    raise

  return (instance_one, instance_two)


@InstanceCheck(None, INST_DOWN, FIRST_ARG)
def TestRapiInstanceRemove(instance, use_client):
  """Test removing instance via RAPI"""
  # FIXME: this does not work if LVM is not enabled. Find out if this is a bug
  # in RAPI or in the test
  if not qa_config.IsStorageTypeSupported(constants.ST_LVM_VG):
    return

  if use_client:
    job_id = _rapi_client.DeleteInstance(instance.name)
  else:
    (job_id, ) = _DoTests([
      ("/2/instances/%s" % instance.name, _VerifyReturnsJob, "DELETE", None),
      ])

  _WaitForRapiJob(job_id)


@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
def TestRapiInstanceMigrate(instance):
  """Test migrating instance via RAPI"""
  if not IsMigrationSupported(instance):
    print qa_logging.FormatInfo("Instance doesn't support migration, skipping"
                                " test")
    return
  # Move to secondary node
  _WaitForRapiJob(_rapi_client.MigrateInstance(instance.name))
  qa_utils.RunInstanceCheck(instance, True)
  # And back to previous primary
  _WaitForRapiJob(_rapi_client.MigrateInstance(instance.name))


@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
def TestRapiInstanceFailover(instance):
  """Test failing over instance via RAPI"""
  if not IsFailoverSupported(instance):
    print qa_logging.FormatInfo("Instance doesn't support failover, skipping"
                                " test")
    return
  # Move to secondary node
  _WaitForRapiJob(_rapi_client.FailoverInstance(instance.name))
  qa_utils.RunInstanceCheck(instance, True)
  # And back to previous primary
  _WaitForRapiJob(_rapi_client.FailoverInstance(instance.name))


@InstanceCheck(INST_UP, INST_DOWN, FIRST_ARG)
def TestRapiInstanceShutdown(instance):
  """Test stopping an instance via RAPI"""
  _WaitForRapiJob(_rapi_client.ShutdownInstance(instance.name))


@InstanceCheck(INST_DOWN, INST_UP, FIRST_ARG)
def TestRapiInstanceStartup(instance):
  """Test starting an instance via RAPI"""
  _WaitForRapiJob(_rapi_client.StartupInstance(instance.name))


@InstanceCheck(INST_DOWN, INST_DOWN, FIRST_ARG)
def TestRapiInstanceRenameAndBack(rename_source, rename_target):
  """Test renaming instance via RAPI

  This must leave the instance with the original name (in the
  non-failure case).

  """
  _WaitForRapiJob(_rapi_client.RenameInstance(rename_source, rename_target))
  qa_utils.RunInstanceCheck(rename_source, False)
  qa_utils.RunInstanceCheck(rename_target, False)
  _WaitForRapiJob(_rapi_client.RenameInstance(rename_target, rename_source))
  qa_utils.RunInstanceCheck(rename_target, False)


@InstanceCheck(INST_DOWN, INST_DOWN, FIRST_ARG)
def TestRapiInstanceReinstall(instance):
  """Test reinstalling an instance via RAPI"""
  if instance.disk_template == constants.DT_DISKLESS:
    print qa_logging.FormatInfo("Test not supported for diskless instances")
    return

  _WaitForRapiJob(_rapi_client.ReinstallInstance(instance.name))
  # By default, the instance is started again
  qa_utils.RunInstanceCheck(instance, True)

  # Reinstall again without starting
  _WaitForRapiJob(_rapi_client.ReinstallInstance(instance.name,
                                                 no_startup=True))


@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
def TestRapiInstanceReplaceDisks(instance):
  """Test replacing instance disks via RAPI"""
  if not IsDiskReplacingSupported(instance):
    print qa_logging.FormatInfo("Instance doesn't support disk replacing,"
                                " skipping test")
    return
  fn = _rapi_client.ReplaceInstanceDisks
  _WaitForRapiJob(fn(instance.name,
                     mode=constants.REPLACE_DISK_AUTO, disks=[]))
  _WaitForRapiJob(fn(instance.name,
                     mode=constants.REPLACE_DISK_SEC, disks="0"))


@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
def TestRapiInstanceModify(instance):
  """Test modifying instance via RAPI"""
  default_hv = qa_config.GetDefaultHypervisor()

  def _ModifyInstance(**kwargs):
    _WaitForRapiJob(_rapi_client.ModifyInstance(instance.name, **kwargs))

  _ModifyInstance(beparams={
    constants.BE_VCPUS: 3,
    })

  _ModifyInstance(beparams={
    constants.BE_VCPUS: constants.VALUE_DEFAULT,
    })

  if default_hv == constants.HT_XEN_PVM:
    _ModifyInstance(hvparams={
      constants.HV_KERNEL_ARGS: "single",
      })
    _ModifyInstance(hvparams={
      constants.HV_KERNEL_ARGS: constants.VALUE_DEFAULT,
      })
  elif default_hv == constants.HT_XEN_HVM:
    _ModifyInstance(hvparams={
      constants.HV_BOOT_ORDER: "acn",
      })
    _ModifyInstance(hvparams={
      constants.HV_BOOT_ORDER: constants.VALUE_DEFAULT,
      })


@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
def TestRapiInstanceConsole(instance):
  """Test getting instance console information via RAPI"""
  result = _rapi_client.GetInstanceConsole(instance.name)
  console = objects.InstanceConsole.FromDict(result)
  AssertEqual(console.Validate(), None)
  AssertEqual(console.instance, qa_utils.ResolveInstanceName(instance.name))


@InstanceCheck(INST_DOWN, INST_DOWN, FIRST_ARG)
def TestRapiStoppedInstanceConsole(instance):
  """Test getting stopped instance's console information via RAPI"""
  try:
    _rapi_client.GetInstanceConsole(instance.name)
  except rapi.client.GanetiApiError, err:
    AssertEqual(err.code, 503)
  else:
    raise qa_error.Error("Getting console for stopped instance didn't"
                         " return HTTP 503")


def GetOperatingSystems():
  """Retrieves a list of all available operating systems.

  """
  return _rapi_client.GetOperatingSystems()


def _InvokeMoveInstance(current_dest_inst, current_src_inst, rapi_pw_filename,
                        joint_master, perform_checks, target_nodes=None):
  """ Invokes the move-instance tool for testing purposes.

  """
  # Some uses of this test might require that RAPI-only commands are used,
  # and the checks are command-line based.
  if perform_checks:
    qa_utils.RunInstanceCheck(current_dest_inst, False)

  cmd = [
      "../tools/move-instance",
      "--verbose",
      "--src-ca-file=%s" % _rapi_ca.name,
      "--src-username=%s" % _rapi_username,
      "--src-password-file=%s" % rapi_pw_filename,
      "--dest-instance-name=%s" % current_dest_inst,
      ]

  if target_nodes:
    pnode, snode = target_nodes
    cmd.extend([
      "--dest-primary-node=%s" % pnode,
      "--dest-secondary-node=%s" % snode,
      ])
  else:
    cmd.extend([
      "--iallocator=%s" % constants.IALLOC_HAIL,
      "--opportunistic-tries=1",
      ])

  cmd.extend([
    "--net=0:mac=%s" % constants.VALUE_GENERATE,
    joint_master,
    joint_master,
    current_src_inst,
    ])

  AssertEqual(StartLocalCommand(cmd).wait(), 0)

  if perform_checks:
    qa_utils.RunInstanceCheck(current_src_inst, False)
    qa_utils.RunInstanceCheck(current_dest_inst, True)


def TestInterClusterInstanceMove(src_instance, dest_instance,
                                 inodes, tnode, perform_checks=True):
  """Test tools/move-instance"""
  master = qa_config.GetMasterNode()

  rapi_pw_file = tempfile.NamedTemporaryFile()
  rapi_pw_file.write(_rapi_password)
  rapi_pw_file.flush()

  # Needed only if checks are to be performed
  if perform_checks:
    dest_instance.SetDiskTemplate(src_instance.disk_template)

  # TODO: Run some instance tests before moving back

  if len(inodes) > 1:
    # No disk template currently requires more than 1 secondary node. If this
    # changes, either this test must be skipped or the script must be updated.
    assert len(inodes) == 2
    snode = inodes[1]
  else:
    # Instance is not redundant, but we still need to pass a node
    # (which will be ignored)
    snode = tnode
  pnode = inodes[0]

  # pnode:snode are the *current* nodes, and the first move is an
  # iallocator-guided move outside of pnode. The node lock for the pnode
  # assures that this happens, and while we cannot be sure where the instance
  # will land, it is a real move.
  locks = {locking.LEVEL_NODE: [pnode.primary]}
  RunWithLocks(_InvokeMoveInstance, locks, 600.0, False,
               dest_instance.name, src_instance.name, rapi_pw_file.name,
               master.primary, perform_checks)

  # And then back to pnode:snode
  _InvokeMoveInstance(src_instance.name, dest_instance.name, rapi_pw_file.name,
                      master.primary, perform_checks,
                      target_nodes=(pnode.primary, snode.primary))


def TestFilters():
  """Testing filter management via the remote API.

  """

  body = {
    "priority": 10,
    "predicates": [],
    "action": "CONTINUE",
    "reason": [(constants.OPCODE_REASON_SRC_USER,
               "reason1",
               utils.EpochNano())],
  }

  body1 = copy.deepcopy(body)
  body1["priority"] = 20

  # Query filters
  _DoTests([("/2/filters", [], "GET", None)])

  # Add a filter via POST and delete it again
  uuid = _DoTests([("/2/filters", None, "POST", body)])[0]
  uuid_module.UUID(uuid)  # Check if uuid is a valid UUID
  _DoTests([("/2/filters/%s" % uuid, lambda r: r is None, "DELETE", None)])

  _DoTests([
    # Check PUT-inserting a nonexistent filter with given UUID
    ("/2/filters/%s" % uuid, lambda u: u == uuid, "PUT", body),
    # Check PUT-inserting an existent filter with given UUID
    ("/2/filters/%s" % uuid, lambda u: u == uuid, "PUT", body1),
    # Check that the update changed the filter
    ("/2/filters/%s" % uuid, lambda f: f["priority"] == 20, "GET", None),
    # Delete it again
    ("/2/filters/%s" % uuid, lambda r: r is None, "DELETE", None),
    ])

  # Add multiple filters, query and delete them
  uuids = _DoTests([
    ("/2/filters", None, "POST", body),
    ("/2/filters", None, "POST", body),
    ("/2/filters", None, "POST", body),
    ])
  _DoTests([("/2/filters", lambda rs: [r["uuid"] for r in rs] == uuids,
             "GET", None)])
  for u in uuids:
    _DoTests([("/2/filters/%s" % u, lambda r: r is None, "DELETE", None)])


_DRBD_SECRET_RE = re.compile('shared-secret.*"([0-9A-Fa-f]+)"')


def _RetrieveSecret(instance, pnode):
  """Retrieves the DRBD secret given an instance object and the primary node.

  @type instance: L{qa_config._QaInstance}
  @type pnode: L{qa_config._QaNode}

  @rtype: string

  """
  instance_info = GetInstanceInfo(instance.name)

  # We are interested in only the first disk on the primary
  drbd_minor = instance_info["drbd-minors"][pnode.primary][0]

  # This form should work for all DRBD versions
  drbd_command = ("drbdsetup show %d; drbdsetup %d show || true" %
                  (drbd_minor, drbd_minor))
  instance_drbd_info = \
    qa_utils.GetCommandOutput(pnode.primary, drbd_command)

  match_obj = _DRBD_SECRET_RE.search(instance_drbd_info)
  if match_obj is None:
    raise qa_error.Error("Could not retrieve DRBD secret for instance %s from"
                         " node %s." % (instance.name, pnode.primary))

  return match_obj.groups(0)[0]


def TestInstanceDataCensorship(instance, inodes):
  """Test protection of sensitive instance data."""

  if instance.disk_template != constants.DT_DRBD8:
    print qa_utils.FormatInfo("Only the DRBD secret is a sensitive parameter"
                              " right now, skipping for non-DRBD instance.")
    return

  drbd_secret = _RetrieveSecret(instance, inodes[0])

  job_id = _rapi_client.GetInstanceInfo(instance.name)
  if not _rapi_client.WaitForJobCompletion(job_id):
    raise qa_error.Error("Could not fetch instance info for instance %s" %
                         instance.name)
  info_dict = _rapi_client.GetJobStatus(job_id)

  if drbd_secret in str(info_dict):
    print qa_utils.FormatInfo("DRBD secret: %s" % drbd_secret)
    print qa_utils.FormatInfo("Retrieved data\n%s" % str(info_dict))
    raise qa_error.Error("Found DRBD secret in contents of RAPI instance info"
                         " call; see above.")
