#
#

# 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 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"]

  _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 = [_GenInstanceAllocationDict(node, i) for i in 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.")
