#
#

# Copyright (C) 2006, 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.


"""Functions used by the node daemon

@var _ALLOWED_UPLOAD_FILES: denotes which files are accepted in
     the L{UploadFile} function
@var _ALLOWED_CLEAN_DIRS: denotes which directories are accepted
     in the L{_CleanDirectory} function

"""

# pylint: disable=E1103,C0302

# E1103: %s %r has no %r member (but some types could not be
# inferred), because the _TryOSFromDisk returns either (True, os_obj)
# or (False, "string") which confuses pylint

# C0302: This module has become too big and should be split up


import base64
import errno
import logging
import os
import os.path
import pycurl
import random
import re
import shutil
import signal
import stat
import tempfile
import time
import zlib
import contextlib
import collections

from ganeti import errors
from ganeti import http
from ganeti import utils
from ganeti import ssh
from ganeti import hypervisor
from ganeti.hypervisor import hv_base
from ganeti import constants
from ganeti.storage import bdev
from ganeti.storage import drbd
from ganeti.storage import extstorage
from ganeti.storage import filestorage
from ganeti import objects
from ganeti import ssconf
from ganeti import serializer
from ganeti import netutils
from ganeti import runtime
from ganeti import compat
from ganeti import pathutils
from ganeti import vcluster
from ganeti import ht
from ganeti.storage.base import BlockDev
from ganeti.storage.drbd import DRBD8
from ganeti import hooksmaster
import ganeti.metad as metad


_BOOT_ID_PATH = "/proc/sys/kernel/random/boot_id"
_ALLOWED_CLEAN_DIRS = compat.UniqueFrozenset([
  pathutils.DATA_DIR,
  pathutils.JOB_QUEUE_ARCHIVE_DIR,
  pathutils.QUEUE_DIR,
  pathutils.CRYPTO_KEYS_DIR,
  ])
_MAX_SSL_CERT_VALIDITY = 7 * 24 * 60 * 60
_X509_KEY_FILE = "key"
_X509_CERT_FILE = "cert"
_IES_STATUS_FILE = "status"
_IES_PID_FILE = "pid"
_IES_CA_FILE = "ca"

#: Valid LVS output line regex
_LVSLINE_REGEX = re.compile(r"^ *([^|]+)\|([^|]+)\|([0-9.]+)\|([^|]{6,})\|?$")

# Actions for the master setup script
_MASTER_START = "start"
_MASTER_STOP = "stop"

#: Maximum file permissions for restricted command directory and executables
_RCMD_MAX_MODE = (stat.S_IRWXU |
                  stat.S_IRGRP | stat.S_IXGRP |
                  stat.S_IROTH | stat.S_IXOTH)

#: Delay before returning an error for restricted commands
_RCMD_INVALID_DELAY = 10

#: How long to wait to acquire lock for restricted commands (shorter than
#: L{_RCMD_INVALID_DELAY}) to reduce blockage of noded forks when many
#: command requests arrive
_RCMD_LOCK_TIMEOUT = _RCMD_INVALID_DELAY * 0.8


class RPCFail(Exception):
  """Class denoting RPC failure.

  Its argument is the error message.

  """


def _GetInstReasonFilename(instance_name):
  """Path of the file containing the reason of the instance status change.

  @type instance_name: string
  @param instance_name: The name of the instance
  @rtype: string
  @return: The path of the file

  """
  return utils.PathJoin(pathutils.INSTANCE_REASON_DIR, instance_name)


def _StoreInstReasonTrail(instance_name, trail):
  """Serialize a reason trail related to an instance change of state to file.

  The exact location of the file depends on the name of the instance and on
  the configuration of the Ganeti cluster defined at deploy time.

  @type instance_name: string
  @param instance_name: The name of the instance

  @type trail: list of reasons
  @param trail: reason trail

  @rtype: None

  """
  json = serializer.DumpJson(trail)
  filename = _GetInstReasonFilename(instance_name)
  utils.WriteFile(filename, data=json)


def _Fail(msg, *args, **kwargs):
  """Log an error and the raise an RPCFail exception.

  This exception is then handled specially in the ganeti daemon and
  turned into a 'failed' return type. As such, this function is a
  useful shortcut for logging the error and returning it to the master
  daemon.

  @type msg: string
  @param msg: the text of the exception
  @raise RPCFail

  """
  if args:
    msg = msg % args
  if "log" not in kwargs or kwargs["log"]: # if we should log this error
    if "exc" in kwargs and kwargs["exc"]:
      logging.exception(msg)
    else:
      logging.error(msg)
  raise RPCFail(msg)


def _GetConfig():
  """Simple wrapper to return a SimpleStore.

  @rtype: L{ssconf.SimpleStore}
  @return: a SimpleStore instance

  """
  return ssconf.SimpleStore()


def _GetSshRunner(cluster_name):
  """Simple wrapper to return an SshRunner.

  @type cluster_name: str
  @param cluster_name: the cluster name, which is needed
      by the SshRunner constructor
  @rtype: L{ssh.SshRunner}
  @return: an SshRunner instance

  """
  return ssh.SshRunner(cluster_name)


def _Decompress(data):
  """Unpacks data compressed by the RPC client.

  @type data: list or tuple
  @param data: Data sent by RPC client
  @rtype: str
  @return: Decompressed data

  """
  assert isinstance(data, (list, tuple))
  assert len(data) == 2
  (encoding, content) = data
  if encoding == constants.RPC_ENCODING_NONE:
    return content
  elif encoding == constants.RPC_ENCODING_ZLIB_BASE64:
    return zlib.decompress(base64.b64decode(content))
  else:
    raise AssertionError("Unknown data encoding")


def _CleanDirectory(path, exclude=None):
  """Removes all regular files in a directory.

  @type path: str
  @param path: the directory to clean
  @type exclude: list
  @param exclude: list of files to be excluded, defaults
      to the empty list

  """
  if path not in _ALLOWED_CLEAN_DIRS:
    _Fail("Path passed to _CleanDirectory not in allowed clean targets: '%s'",
          path)

  if not os.path.isdir(path):
    return
  if exclude is None:
    exclude = []
  else:
    # Normalize excluded paths
    exclude = [os.path.normpath(i) for i in exclude]

  for rel_name in utils.ListVisibleFiles(path):
    full_name = utils.PathJoin(path, rel_name)
    if full_name in exclude:
      continue
    if os.path.isfile(full_name) and not os.path.islink(full_name):
      utils.RemoveFile(full_name)


def _BuildUploadFileList():
  """Build the list of allowed upload files.

  This is abstracted so that it's built only once at module import time.

  """
  allowed_files = set([
    pathutils.CLUSTER_CONF_FILE,
    pathutils.ETC_HOSTS,
    pathutils.SSH_KNOWN_HOSTS_FILE,
    pathutils.VNC_PASSWORD_FILE,
    pathutils.RAPI_CERT_FILE,
    pathutils.SPICE_CERT_FILE,
    pathutils.SPICE_CACERT_FILE,
    pathutils.RAPI_USERS_FILE,
    pathutils.CONFD_HMAC_KEY,
    pathutils.CLUSTER_DOMAIN_SECRET_FILE,
    ])

  for hv_name in constants.HYPER_TYPES:
    hv_class = hypervisor.GetHypervisorClass(hv_name)
    allowed_files.update(hv_class.GetAncillaryFiles()[0])

  assert pathutils.FILE_STORAGE_PATHS_FILE not in allowed_files, \
    "Allowed file storage paths should never be uploaded via RPC"

  return frozenset(allowed_files)


_ALLOWED_UPLOAD_FILES = _BuildUploadFileList()


def JobQueuePurge():
  """Removes job queue files and archived jobs.

  @rtype: tuple
  @return: True, None

  """
  _CleanDirectory(pathutils.QUEUE_DIR, exclude=[pathutils.JOB_QUEUE_LOCK_FILE])
  _CleanDirectory(pathutils.JOB_QUEUE_ARCHIVE_DIR)


def GetMasterNodeName():
  """Returns the master node name.

  @rtype: string
  @return: name of the master node
  @raise RPCFail: in case of errors

  """
  try:
    return _GetConfig().GetMasterNode()
  except errors.ConfigurationError, err:
    _Fail("Cluster configuration incomplete: %s", err, exc=True)


def RunLocalHooks(hook_opcode, hooks_path, env_builder_fn):
  """Decorator that runs hooks before and after the decorated function.

  @type hook_opcode: string
  @param hook_opcode: opcode of the hook
  @type hooks_path: string
  @param hooks_path: path of the hooks
  @type env_builder_fn: function
  @param env_builder_fn: function that returns a dictionary containing the
    environment variables for the hooks. Will get all the parameters of the
    decorated function.
  @raise RPCFail: in case of pre-hook failure

  """
  def decorator(fn):
    def wrapper(*args, **kwargs):
      _, myself = ssconf.GetMasterAndMyself()
      nodes = ([myself], [myself])  # these hooks run locally

      env_fn = compat.partial(env_builder_fn, *args, **kwargs)

      cfg = _GetConfig()
      hr = HooksRunner()
      hm = hooksmaster.HooksMaster(hook_opcode, hooks_path, nodes,
                                   hr.RunLocalHooks, None, env_fn, None,
                                   logging.warning, cfg.GetClusterName(),
                                   cfg.GetMasterNode())
      hm.RunPhase(constants.HOOKS_PHASE_PRE)
      result = fn(*args, **kwargs)
      hm.RunPhase(constants.HOOKS_PHASE_POST)

      return result
    return wrapper
  return decorator


def _BuildMasterIpEnv(master_params, use_external_mip_script=None):
  """Builds environment variables for master IP hooks.

  @type master_params: L{objects.MasterNetworkParameters}
  @param master_params: network parameters of the master
  @type use_external_mip_script: boolean
  @param use_external_mip_script: whether to use an external master IP
    address setup script (unused, but necessary per the implementation of the
    _RunLocalHooks decorator)

  """
  # pylint: disable=W0613
  ver = netutils.IPAddress.GetVersionFromAddressFamily(master_params.ip_family)
  env = {
    "MASTER_NETDEV": master_params.netdev,
    "MASTER_IP": master_params.ip,
    "MASTER_NETMASK": str(master_params.netmask),
    "CLUSTER_IP_VERSION": str(ver),
  }

  return env


def _RunMasterSetupScript(master_params, action, use_external_mip_script):
  """Execute the master IP address setup script.

  @type master_params: L{objects.MasterNetworkParameters}
  @param master_params: network parameters of the master
  @type action: string
  @param action: action to pass to the script. Must be one of
    L{backend._MASTER_START} or L{backend._MASTER_STOP}
  @type use_external_mip_script: boolean
  @param use_external_mip_script: whether to use an external master IP
    address setup script
  @raise backend.RPCFail: if there are errors during the execution of the
    script

  """
  env = _BuildMasterIpEnv(master_params)

  if use_external_mip_script:
    setup_script = pathutils.EXTERNAL_MASTER_SETUP_SCRIPT
  else:
    setup_script = pathutils.DEFAULT_MASTER_SETUP_SCRIPT

  result = utils.RunCmd([setup_script, action], env=env, reset_env=True)

  if result.failed:
    _Fail("Failed to %s the master IP. Script return value: %s, output: '%s'" %
          (action, result.exit_code, result.output), log=True)


@RunLocalHooks(constants.FAKE_OP_MASTER_TURNUP, "master-ip-turnup",
               _BuildMasterIpEnv)
def ActivateMasterIp(master_params, use_external_mip_script):
  """Activate the IP address of the master daemon.

  @type master_params: L{objects.MasterNetworkParameters}
  @param master_params: network parameters of the master
  @type use_external_mip_script: boolean
  @param use_external_mip_script: whether to use an external master IP
    address setup script
  @raise RPCFail: in case of errors during the IP startup

  """
  _RunMasterSetupScript(master_params, _MASTER_START,
                        use_external_mip_script)


def StartMasterDaemons(no_voting):
  """Activate local node as master node.

  The function will start the master daemons (ganeti-masterd and ganeti-rapi).

  @type no_voting: boolean
  @param no_voting: whether to start ganeti-masterd without a node vote
      but still non-interactively
  @rtype: None

  """

  if no_voting:
    daemon_args = "--no-voting --yes-do-it"
  else:
    daemon_args = ""

  env = {
    "EXTRA_LUXID_ARGS": daemon_args,
    "EXTRA_WCONFD_ARGS": daemon_args,
    }

  result = utils.RunCmd([pathutils.DAEMON_UTIL, "start-master"], env=env)
  if result.failed:
    msg = "Can't start Ganeti master: %s" % result.output
    logging.error(msg)
    _Fail(msg)


@RunLocalHooks(constants.FAKE_OP_MASTER_TURNDOWN, "master-ip-turndown",
               _BuildMasterIpEnv)
def DeactivateMasterIp(master_params, use_external_mip_script):
  """Deactivate the master IP on this node.

  @type master_params: L{objects.MasterNetworkParameters}
  @param master_params: network parameters of the master
  @type use_external_mip_script: boolean
  @param use_external_mip_script: whether to use an external master IP
    address setup script
  @raise RPCFail: in case of errors during the IP turndown

  """
  _RunMasterSetupScript(master_params, _MASTER_STOP,
                        use_external_mip_script)


def StopMasterDaemons():
  """Stop the master daemons on this node.

  Stop the master daemons (ganeti-masterd and ganeti-rapi) on this node.

  @rtype: None

  """
  # TODO: log and report back to the caller the error failures; we
  # need to decide in which case we fail the RPC for this

  result = utils.RunCmd([pathutils.DAEMON_UTIL, "stop-master"])
  if result.failed:
    logging.error("Could not stop Ganeti master, command %s had exitcode %s"
                  " and error %s",
                  result.cmd, result.exit_code, result.output)


def ChangeMasterNetmask(old_netmask, netmask, master_ip, master_netdev):
  """Change the netmask of the master IP.

  @param old_netmask: the old value of the netmask
  @param netmask: the new value of the netmask
  @param master_ip: the master IP
  @param master_netdev: the master network device

  """
  if old_netmask == netmask:
    return

  if not netutils.IPAddress.Own(master_ip):
    _Fail("The master IP address is not up, not attempting to change its"
          " netmask")

  result = utils.RunCmd([constants.IP_COMMAND_PATH, "address", "add",
                         "%s/%s" % (master_ip, netmask),
                         "dev", master_netdev, "label",
                         "%s:0" % master_netdev])
  if result.failed:
    _Fail("Could not set the new netmask on the master IP address")

  result = utils.RunCmd([constants.IP_COMMAND_PATH, "address", "del",
                         "%s/%s" % (master_ip, old_netmask),
                         "dev", master_netdev, "label",
                         "%s:0" % master_netdev])
  if result.failed:
    _Fail("Could not bring down the master IP address with the old netmask")


def EtcHostsModify(mode, host, ip):
  """Modify a host entry in /etc/hosts.

  @param mode: The mode to operate. Either add or remove entry
  @param host: The host to operate on
  @param ip: The ip associated with the entry

  """
  if mode == constants.ETC_HOSTS_ADD:
    if not ip:
      RPCFail("Mode 'add' needs 'ip' parameter, but parameter not"
              " present")
    utils.AddHostToEtcHosts(host, ip)
  elif mode == constants.ETC_HOSTS_REMOVE:
    if ip:
      RPCFail("Mode 'remove' does not allow 'ip' parameter, but"
              " parameter is present")
    utils.RemoveHostFromEtcHosts(host)
  else:
    RPCFail("Mode not supported")


def LeaveCluster(modify_ssh_setup):
  """Cleans up and remove the current node.

  This function cleans up and prepares the current node to be removed
  from the cluster.

  If processing is successful, then it raises an
  L{errors.QuitGanetiException} which is used as a special case to
  shutdown the node daemon.

  @param modify_ssh_setup: boolean

  """
  _CleanDirectory(pathutils.DATA_DIR)
  _CleanDirectory(pathutils.CRYPTO_KEYS_DIR)
  JobQueuePurge()

  if modify_ssh_setup:
    try:
      priv_key, pub_key, auth_keys = ssh.GetUserFiles(constants.SSH_LOGIN_USER)

      ssh.RemoveAuthorizedKey(auth_keys, utils.ReadFile(pub_key))

      utils.RemoveFile(priv_key)
      utils.RemoveFile(pub_key)
    except errors.OpExecError:
      logging.exception("Error while processing ssh files")
    except IOError:
      logging.exception("At least one SSH file was not accessible.")

  try:
    utils.RemoveFile(pathutils.CONFD_HMAC_KEY)
    utils.RemoveFile(pathutils.RAPI_CERT_FILE)
    utils.RemoveFile(pathutils.SPICE_CERT_FILE)
    utils.RemoveFile(pathutils.SPICE_CACERT_FILE)
    utils.RemoveFile(pathutils.NODED_CERT_FILE)
  except: # pylint: disable=W0702
    logging.exception("Error while removing cluster secrets")

  utils.StopDaemon(constants.CONFD)
  utils.StopDaemon(constants.MOND)
  utils.StopDaemon(constants.KVMD)

  # Raise a custom exception (handled in ganeti-noded)
  raise errors.QuitGanetiException(True, "Shutdown scheduled")


def _CheckStorageParams(params, num_params):
  """Performs sanity checks for storage parameters.

  @type params: list
  @param params: list of storage parameters
  @type num_params: int
  @param num_params: expected number of parameters

  """
  if params is None:
    raise errors.ProgrammerError("No storage parameters for storage"
                                 " reporting is provided.")
  if not isinstance(params, list):
    raise errors.ProgrammerError("The storage parameters are not of type"
                                 " list: '%s'" % params)
  if not len(params) == num_params:
    raise errors.ProgrammerError("Did not receive the expected number of"
                                 "storage parameters: expected %s,"
                                 " received '%s'" % (num_params, len(params)))


def _CheckLvmStorageParams(params):
  """Performs sanity check for the 'exclusive storage' flag.

  @see: C{_CheckStorageParams}

  """
  _CheckStorageParams(params, 1)
  excl_stor = params[0]
  if not isinstance(params[0], bool):
    raise errors.ProgrammerError("Exclusive storage parameter is not"
                                 " boolean: '%s'." % excl_stor)
  return excl_stor


def _GetLvmVgSpaceInfo(name, params):
  """Wrapper around C{_GetVgInfo} which checks the storage parameters.

  @type name: string
  @param name: name of the volume group
  @type params: list
  @param params: list of storage parameters, which in this case should be
    containing only one for exclusive storage

  """
  excl_stor = _CheckLvmStorageParams(params)
  return _GetVgInfo(name, excl_stor)


def _GetVgInfo(
    name, excl_stor, info_fn=bdev.LogicalVolume.GetVGInfo):
  """Retrieves information about a LVM volume group.

  """
  # TODO: GetVGInfo supports returning information for multiple VGs at once
  vginfo = info_fn([name], excl_stor)
  if vginfo:
    vg_free = int(round(vginfo[0][0], 0))
    vg_size = int(round(vginfo[0][1], 0))
  else:
    vg_free = None
    vg_size = None

  return {
    "type": constants.ST_LVM_VG,
    "name": name,
    "storage_free": vg_free,
    "storage_size": vg_size,
    }


def _GetLvmPvSpaceInfo(name, params):
  """Wrapper around C{_GetVgSpindlesInfo} with sanity checks.

  @see: C{_GetLvmVgSpaceInfo}

  """
  excl_stor = _CheckLvmStorageParams(params)
  return _GetVgSpindlesInfo(name, excl_stor)


def _GetVgSpindlesInfo(
    name, excl_stor, info_fn=bdev.LogicalVolume.GetVgSpindlesInfo):
  """Retrieves information about spindles in an LVM volume group.

  @type name: string
  @param name: VG name
  @type excl_stor: bool
  @param excl_stor: exclusive storage
  @rtype: dict
  @return: dictionary whose keys are "name", "vg_free", "vg_size" for VG name,
      free spindles, total spindles respectively

  """
  if excl_stor:
    (vg_free, vg_size) = info_fn(name)
  else:
    vg_free = 0
    vg_size = 0
  return {
    "type": constants.ST_LVM_PV,
    "name": name,
    "storage_free": vg_free,
    "storage_size": vg_size,
    }


def _GetHvInfo(name, hvparams, get_hv_fn=hypervisor.GetHypervisor):
  """Retrieves node information from a hypervisor.

  The information returned depends on the hypervisor. Common items:

    - vg_size is the size of the configured volume group in MiB
    - vg_free is the free size of the volume group in MiB
    - memory_dom0 is the memory allocated for domain0 in MiB
    - memory_free is the currently available (free) ram in MiB
    - memory_total is the total number of ram in MiB
    - hv_version: the hypervisor version, if available

  @type hvparams: dict of string
  @param hvparams: the hypervisor's hvparams

  """
  return get_hv_fn(name).GetNodeInfo(hvparams=hvparams)


def _GetHvInfoAll(hv_specs, get_hv_fn=hypervisor.GetHypervisor):
  """Retrieves node information for all hypervisors.

  See C{_GetHvInfo} for information on the output.

  @type hv_specs: list of pairs (string, dict of strings)
  @param hv_specs: list of pairs of a hypervisor's name and its hvparams

  """
  if hv_specs is None:
    return None

  result = []
  for hvname, hvparams in hv_specs:
    result.append(_GetHvInfo(hvname, hvparams, get_hv_fn))
  return result


def _GetNamedNodeInfo(names, fn):
  """Calls C{fn} for all names in C{names} and returns a dictionary.

  @rtype: None or dict

  """
  if names is None:
    return None
  else:
    return map(fn, names)


def GetNodeInfo(storage_units, hv_specs):
  """Gives back a hash with different information about the node.

  @type storage_units: list of tuples (string, string, list)
  @param storage_units: List of tuples (storage unit, identifier, parameters) to
    ask for disk space information. In case of lvm-vg, the identifier is
    the VG name. The parameters can contain additional, storage-type-specific
    parameters, for example exclusive storage for lvm storage.
  @type hv_specs: list of pairs (string, dict of strings)
  @param hv_specs: list of pairs of a hypervisor's name and its hvparams
  @rtype: tuple; (string, None/dict, None/dict)
  @return: Tuple containing boot ID, volume group information and hypervisor
    information

  """
  bootid = utils.ReadFile(_BOOT_ID_PATH, size=128).rstrip("\n")
  storage_info = _GetNamedNodeInfo(
    storage_units,
    (lambda (storage_type, storage_key, storage_params):
        _ApplyStorageInfoFunction(storage_type, storage_key, storage_params)))
  hv_info = _GetHvInfoAll(hv_specs)
  return (bootid, storage_info, hv_info)


def _GetFileStorageSpaceInfo(path, params):
  """Wrapper around filestorage.GetSpaceInfo.

  The purpose of this wrapper is to call filestorage.GetFileStorageSpaceInfo
  and ignore the *args parameter to not leak it into the filestorage
  module's code.

  @see: C{filestorage.GetFileStorageSpaceInfo} for description of the
    parameters.

  """
  _CheckStorageParams(params, 0)
  return filestorage.GetFileStorageSpaceInfo(path)


# FIXME: implement storage reporting for all missing storage types.
_STORAGE_TYPE_INFO_FN = {
  constants.ST_BLOCK: None,
  constants.ST_DISKLESS: None,
  constants.ST_EXT: None,
  constants.ST_FILE: _GetFileStorageSpaceInfo,
  constants.ST_LVM_PV: _GetLvmPvSpaceInfo,
  constants.ST_LVM_VG: _GetLvmVgSpaceInfo,
  constants.ST_SHARED_FILE: None,
  constants.ST_GLUSTER: None,
  constants.ST_RADOS: None,
}


def _ApplyStorageInfoFunction(storage_type, storage_key, *args):
  """Looks up and applies the correct function to calculate free and total
  storage for the given storage type.

  @type storage_type: string
  @param storage_type: the storage type for which the storage shall be reported.
  @type storage_key: string
  @param storage_key: identifier of a storage unit, e.g. the volume group name
    of an LVM storage unit
  @type args: any
  @param args: various parameters that can be used for storage reporting. These
    parameters and their semantics vary from storage type to storage type and
    are just propagated in this function.
  @return: the results of the application of the storage space function (see
    _STORAGE_TYPE_INFO_FN) if storage space reporting is implemented for that
    storage type
  @raises NotImplementedError: for storage types who don't support space
    reporting yet
  """
  fn = _STORAGE_TYPE_INFO_FN[storage_type]
  if fn is not None:
    return fn(storage_key, *args)
  else:
    raise NotImplementedError


def _CheckExclusivePvs(pvi_list):
  """Check that PVs are not shared among LVs

  @type pvi_list: list of L{objects.LvmPvInfo} objects
  @param pvi_list: information about the PVs

  @rtype: list of tuples (string, list of strings)
  @return: offending volumes, as tuples: (pv_name, [lv1_name, lv2_name...])

  """
  res = []
  for pvi in pvi_list:
    if len(pvi.lv_list) > 1:
      res.append((pvi.name, pvi.lv_list))
  return res


def _VerifyHypervisors(what, vm_capable, result, all_hvparams,
                       get_hv_fn=hypervisor.GetHypervisor):
  """Verifies the hypervisor. Appends the results to the 'results' list.

  @type what: C{dict}
  @param what: a dictionary of things to check
  @type vm_capable: boolean
  @param vm_capable: whether or not this node is vm capable
  @type result: dict
  @param result: dictionary of verification results; results of the
    verifications in this function will be added here
  @type all_hvparams: dict of dict of string
  @param all_hvparams: dictionary mapping hypervisor names to hvparams
  @type get_hv_fn: function
  @param get_hv_fn: function to retrieve the hypervisor, to improve testability

  """
  if not vm_capable:
    return

  if constants.NV_HYPERVISOR in what:
    result[constants.NV_HYPERVISOR] = {}
    for hv_name in what[constants.NV_HYPERVISOR]:
      hvparams = all_hvparams[hv_name]
      try:
        val = get_hv_fn(hv_name).Verify(hvparams=hvparams)
      except errors.HypervisorError, err:
        val = "Error while checking hypervisor: %s" % str(err)
      result[constants.NV_HYPERVISOR][hv_name] = val


def _VerifyHvparams(what, vm_capable, result,
                    get_hv_fn=hypervisor.GetHypervisor):
  """Verifies the hvparams. Appends the results to the 'results' list.

  @type what: C{dict}
  @param what: a dictionary of things to check
  @type vm_capable: boolean
  @param vm_capable: whether or not this node is vm capable
  @type result: dict
  @param result: dictionary of verification results; results of the
    verifications in this function will be added here
  @type get_hv_fn: function
  @param get_hv_fn: function to retrieve the hypervisor, to improve testability

  """
  if not vm_capable:
    return

  if constants.NV_HVPARAMS in what:
    result[constants.NV_HVPARAMS] = []
    for source, hv_name, hvparms in what[constants.NV_HVPARAMS]:
      try:
        logging.info("Validating hv %s, %s", hv_name, hvparms)
        get_hv_fn(hv_name).ValidateParameters(hvparms)
      except errors.HypervisorError, err:
        result[constants.NV_HVPARAMS].append((source, hv_name, str(err)))


def _VerifyInstanceList(what, vm_capable, result, all_hvparams):
  """Verifies the instance list.

  @type what: C{dict}
  @param what: a dictionary of things to check
  @type vm_capable: boolean
  @param vm_capable: whether or not this node is vm capable
  @type result: dict
  @param result: dictionary of verification results; results of the
    verifications in this function will be added here
  @type all_hvparams: dict of dict of string
  @param all_hvparams: dictionary mapping hypervisor names to hvparams

  """
  if constants.NV_INSTANCELIST in what and vm_capable:
    # GetInstanceList can fail
    try:
      val = GetInstanceList(what[constants.NV_INSTANCELIST],
                            all_hvparams=all_hvparams)
    except RPCFail, err:
      val = str(err)
    result[constants.NV_INSTANCELIST] = val


def _VerifyNodeInfo(what, vm_capable, result, all_hvparams):
  """Verifies the node info.

  @type what: C{dict}
  @param what: a dictionary of things to check
  @type vm_capable: boolean
  @param vm_capable: whether or not this node is vm capable
  @type result: dict
  @param result: dictionary of verification results; results of the
    verifications in this function will be added here
  @type all_hvparams: dict of dict of string
  @param all_hvparams: dictionary mapping hypervisor names to hvparams

  """
  if constants.NV_HVINFO in what and vm_capable:
    hvname = what[constants.NV_HVINFO]
    hyper = hypervisor.GetHypervisor(hvname)
    hvparams = all_hvparams[hvname]
    result[constants.NV_HVINFO] = hyper.GetNodeInfo(hvparams=hvparams)


def _VerifyClientCertificate(cert_file=pathutils.NODED_CLIENT_CERT_FILE):
  """Verify the existance and validity of the client SSL certificate.

  Also, verify that the client certificate is not self-signed. Self-
  signed client certificates stem from Ganeti versions 2.12.0 - 2.12.4
  and should be replaced by client certificates signed by the server
  certificate. Hence we output a warning when we encounter a self-signed
  one.

  """
  create_cert_cmd = "gnt-cluster renew-crypto --new-node-certificates"
  if not os.path.exists(cert_file):
    return (constants.CV_ERROR,
            "The client certificate does not exist. Run '%s' to create"
            " client certificates for all nodes." % create_cert_cmd)

  (errcode, msg) = utils.VerifyCertificate(cert_file)
  if errcode is not None:
    return (errcode, msg)

  (errcode, msg) = utils.IsCertificateSelfSigned(cert_file)
  if errcode is not None:
    return (errcode, msg)

  # if everything is fine, we return the digest to be compared to the config
  return (None, utils.GetCertificateDigest(cert_filename=cert_file))


def _VerifySshSetup(node_status_list, my_name, ssh_key_type,
                    ganeti_pub_keys_file=pathutils.SSH_PUB_KEYS):
  """Verifies the state of the SSH key files.

  @type node_status_list: list of tuples
  @param node_status_list: list of nodes of the cluster associated with a
    couple of flags: (uuid, name, is_master_candidate,
    is_potential_master_candidate, online)
  @type my_name: str
  @param my_name: name of this node
  @type ssh_key_type: one of L{constants.SSHK_ALL}
  @param ssh_key_type: type of key used on nodes
  @type ganeti_pub_keys_file: str
  @param ganeti_pub_keys_file: filename of the public keys file

  """
  if node_status_list is None:
    return ["No node list to check against the pub_key_file received."]

  my_status_list = [(my_uuid, name, mc, pot_mc, online) for
                    (my_uuid, name, mc, pot_mc, online)
                    in node_status_list if name == my_name]
  if len(my_status_list) == 0:
    return ["Cannot find node information for node '%s'." % my_name]
  (my_uuid, _, _, potential_master_candidate, online) = \
     my_status_list[0]

  result = []

  if not os.path.exists(ganeti_pub_keys_file):
    result.append("The public key file '%s' does not exist. Consider running"
                  " 'gnt-cluster renew-crypto --new-ssh-keys"
                  " [--no-ssh-key-check]' to fix this." % ganeti_pub_keys_file)
    return result

  pot_mc_uuids = [uuid for (uuid, _, _, _, _) in node_status_list]
  offline_nodes = [uuid for (uuid, _, _, _, online) in node_status_list
                   if not online]
  pub_keys = ssh.QueryPubKeyFile(None, key_file=ganeti_pub_keys_file)

  if potential_master_candidate:
    # Check that the set of potential master candidates matches the
    # public key file
    pub_uuids_set = set(pub_keys.keys()) - set(offline_nodes)
    pot_mc_uuids_set = set(pot_mc_uuids) - set(offline_nodes)
    missing_uuids = set([])
    if pub_uuids_set != pot_mc_uuids_set:
      unknown_uuids = pub_uuids_set - pot_mc_uuids_set
      if unknown_uuids:
        result.append("The following node UUIDs are listed in the public key"
                      " file on node '%s', but are not potential master"
                      " candidates: %s."
                      % (my_name, ", ".join(list(unknown_uuids))))
      missing_uuids = pot_mc_uuids_set - pub_uuids_set
      if missing_uuids:
        result.append("The following node UUIDs of potential master candidates"
                      " are missing in the public key file on node %s: %s."
                      % (my_name, ", ".join(list(missing_uuids))))

    (_, key_files) = \
      ssh.GetAllUserFiles(constants.SSH_LOGIN_USER, mkdir=False, dircheck=False)
    (_, node_pub_key_file) = key_files[ssh_key_type]

    my_keys = pub_keys[my_uuid]

    node_pub_key = utils.ReadFile(node_pub_key_file)
    if node_pub_key.strip() not in my_keys:
      result.append("The dsa key of node %s does not match this node's key"
                    " in the pub key file." % my_name)
    if len(my_keys) != 1:
      result.append("There is more than one key for node %s in the public key"
                    " file." % my_name)
  else:
    if len(pub_keys.keys()) > 0:
      result.append("The public key file of node '%s' is not empty, although"
                    " the node is not a potential master candidate."
                    % my_name)

  # Check that all master candidate keys are in the authorized_keys file
  (auth_key_file, _) = \
    ssh.GetAllUserFiles(constants.SSH_LOGIN_USER, mkdir=False, dircheck=False)
  for (uuid, name, mc, _, online) in node_status_list:
    if not online:
      continue
    if uuid in missing_uuids:
      continue
    if mc:
      for key in pub_keys[uuid]:
        if not ssh.HasAuthorizedKey(auth_key_file, key):
          result.append("A SSH key of master candidate '%s' (UUID: '%s') is"
                        " not in the 'authorized_keys' file of node '%s'."
                        % (name, uuid, my_name))
    else:
      for key in pub_keys[uuid]:
        if name != my_name and ssh.HasAuthorizedKey(auth_key_file, key):
          result.append("A SSH key of normal node '%s' (UUID: '%s') is in the"
                        " 'authorized_keys' file of node '%s'."
                        % (name, uuid, my_name))
        if name == my_name and not ssh.HasAuthorizedKey(auth_key_file, key):
          result.append("A SSH key of normal node '%s' (UUID: '%s') is not"
                        " in the 'authorized_keys' file of itself."
                        % (my_name, uuid))

  return result


def _VerifySshClutter(node_status_list, my_name):
  """Verifies that the 'authorized_keys' files are not cluttered up.

  @type node_status_list: list of tuples
  @param node_status_list: list of nodes of the cluster associated with a
    couple of flags: (uuid, name, is_master_candidate,
    is_potential_master_candidate, online)
  @type my_name: str
  @param my_name: name of this node

  """
  result = []
  (auth_key_file, _) = \
    ssh.GetAllUserFiles(constants.SSH_LOGIN_USER, mkdir=False, dircheck=False)
  node_names = [name for (_, name, _, _) in node_status_list]
  multiple_occurrences = ssh.CheckForMultipleKeys(auth_key_file, node_names)
  if multiple_occurrences:
    msg = "There are hosts which have more than one SSH key stored for the" \
          " same user in the 'authorized_keys' file of node %s. This can be" \
          " due to an unsuccessful operation which cluttered up the" \
          " 'authorized_keys' file. We recommend to clean this up manually. " \
          % my_name
    for host, occ in multiple_occurrences.items():
      msg += "Entry for '%s' in lines %s. " % (host, utils.CommaJoin(occ))
    result.append(msg)

  return result


def VerifyNodeNetTest(my_name, test_config):
  """Verify nodes are reachable.

  @type my_name: string
  @param my_name: name of the node this test is running on

  @type test_config: tuple (node_list, master_candidate_list)
  @param test_config: configuration for test as passed from
      LUClusterVerify() in what[constants.NV_NODENETTEST]

  @rtype: dict
  @return: a dictionary with node names as keys and error messages
      as values
  """
  result = {}
  nodes, master_candidates = test_config
  port = netutils.GetDaemonPort(constants.NODED)

  if my_name not in master_candidates:
    return result

  my_pip, my_sip = next(
      ((pip, sip) for name, pip, sip in nodes if name == my_name),
      (None, None)
  )
  if not my_pip:
    result[my_name] = ("Can't find my own primary/secondary IP"
                       " in the node list")
    return result

  for name, pip, sip in nodes:
    fail = []
    if not netutils.TcpPing(pip, port, source=my_pip):
      fail.append("primary")
      if sip != pip:
        if not netutils.TcpPing(sip, port, source=my_sip):
          fail.append("secondary")
      if fail:
        result[name] = ("failure using the %s interface(s)" %
                        " and ".join(fail))
  return result


def VerifyMasterIP(my_name, test_config):
  """Verify master IP is reachable.

  @type my_name: string
  @param my_name: name of the node this test is running on

  @type test_config: tuple (master_name, master_up, master_candidates)
  @param test_config: configuration for test as passed from
      LUClusterVerify() in what[constants.NV_MASTERIP]

  @rtype: bool or None
  @return: Boolean test result, None if skipped
  """
  master_name, master_ip, master_candidates = test_config
  port = netutils.GetDaemonPort(constants.NODED)
  if my_name not in master_candidates:
    return None

  if master_name == my_name:
    source = constants.IP4_ADDRESS_LOCALHOST
  else:
    source = None
  return netutils.TcpPing(master_ip, port, source=source)


def VerifyNode(what, cluster_name, all_hvparams):
  """Verify the status of the local node.

  Based on the input L{what} parameter, various checks are done on the
  local node.

  If the I{filelist} key is present, this list of
  files is checksummed and the file/checksum pairs are returned.

  If the I{nodelist} key is present, we check that we have
  connectivity via ssh with the target nodes (and check the hostname
  report).

  If the I{node-net-test} key is present, we check that we have
  connectivity to the given nodes via both primary IP and, if
  applicable, secondary IPs.

  @type what: C{dict}
  @param what: a dictionary of things to check:
      - filelist: list of files for which to compute checksums
      - nodelist: list of nodes we should check ssh communication with
      - node-net-test: list of nodes we should check node daemon port
        connectivity with
      - hypervisor: list with hypervisors to run the verify for
  @type cluster_name: string
  @param cluster_name: the cluster's name
  @type all_hvparams: dict of dict of strings
  @param all_hvparams: a dictionary mapping hypervisor names to hvparams
  @rtype: dict
  @return: a dictionary with the same keys as the input dict, and
      values representing the result of the checks

  """
  result = {}
  my_name = netutils.Hostname.GetSysName()
  vm_capable = my_name not in what.get(constants.NV_NONVMNODES, [])

  _VerifyHypervisors(what, vm_capable, result, all_hvparams)
  _VerifyHvparams(what, vm_capable, result)

  if constants.NV_FILELIST in what:
    fingerprints = utils.FingerprintFiles(map(vcluster.LocalizeVirtualPath,
                                              what[constants.NV_FILELIST]))
    result[constants.NV_FILELIST] = \
      dict((vcluster.MakeVirtualPath(key), value)
           for (key, value) in fingerprints.items())

  if constants.NV_CLIENT_CERT in what:
    result[constants.NV_CLIENT_CERT] = _VerifyClientCertificate()

  if constants.NV_SSH_SETUP in what:
    node_status_list, key_type = what[constants.NV_SSH_SETUP]
    result[constants.NV_SSH_SETUP] = \
      _VerifySshSetup(node_status_list, my_name, key_type)
    if constants.NV_SSH_CLUTTER in what:
      result[constants.NV_SSH_CLUTTER] = \
        _VerifySshClutter(what[constants.NV_SSH_SETUP], my_name)

  if constants.NV_NODELIST in what:
    (nodes, bynode, mcs) = what[constants.NV_NODELIST]

    # Add nodes from other groups (different for each node)
    try:
      nodes.extend(bynode[my_name])
    except KeyError:
      pass

    # Use a random order
    random.shuffle(nodes)

    # Try to contact all nodes
    val = {}
    ssh_port_map = ssconf.SimpleStore().GetSshPortMap()
    for node in nodes:
      # We only test if master candidates can communicate to other nodes.
      # We cannot test if normal nodes cannot communicate with other nodes,
      # because the administrator might have installed additional SSH keys,
      # over which Ganeti has no power.
      if my_name in mcs:
        success, message = _GetSshRunner(cluster_name). \
                              VerifyNodeHostname(node, ssh_port_map[node])
        if not success:
          val[node] = message

    result[constants.NV_NODELIST] = val

  if constants.NV_NODENETTEST in what:
    result[constants.NV_NODENETTEST] = VerifyNodeNetTest(
        my_name, what[constants.NV_NODENETTEST])

  if constants.NV_MASTERIP in what:
    result[constants.NV_MASTERIP] = VerifyMasterIP(
        my_name, what[constants.NV_MASTERIP])

  if constants.NV_USERSCRIPTS in what:
    result[constants.NV_USERSCRIPTS] = \
      [script for script in what[constants.NV_USERSCRIPTS]
       if not utils.IsExecutable(script)]

  if constants.NV_OOB_PATHS in what:
    result[constants.NV_OOB_PATHS] = tmp = []
    for path in what[constants.NV_OOB_PATHS]:
      try:
        st = os.stat(path)
      except OSError, err:
        tmp.append("error stating out of band helper: %s" % err)
      else:
        if stat.S_ISREG(st.st_mode):
          if stat.S_IMODE(st.st_mode) & stat.S_IXUSR:
            tmp.append(None)
          else:
            tmp.append("out of band helper %s is not executable" % path)
        else:
          tmp.append("out of band helper %s is not a file" % path)

  if constants.NV_LVLIST in what and vm_capable:
    try:
      val = GetVolumeList(utils.ListVolumeGroups().keys())
    except RPCFail, err:
      val = str(err)
    result[constants.NV_LVLIST] = val

  _VerifyInstanceList(what, vm_capable, result, all_hvparams)

  if constants.NV_VGLIST in what and vm_capable:
    result[constants.NV_VGLIST] = utils.ListVolumeGroups()

  if constants.NV_PVLIST in what and vm_capable:
    check_exclusive_pvs = constants.NV_EXCLUSIVEPVS in what
    val = bdev.LogicalVolume.GetPVInfo(what[constants.NV_PVLIST],
                                       filter_allocatable=False,
                                       include_lvs=check_exclusive_pvs)
    if check_exclusive_pvs:
      result[constants.NV_EXCLUSIVEPVS] = _CheckExclusivePvs(val)
      for pvi in val:
        # Avoid sending useless data on the wire
        pvi.lv_list = []
    result[constants.NV_PVLIST] = map(objects.LvmPvInfo.ToDict, val)

  if constants.NV_VERSION in what:
    result[constants.NV_VERSION] = (constants.PROTOCOL_VERSION,
                                    constants.RELEASE_VERSION)

  _VerifyNodeInfo(what, vm_capable, result, all_hvparams)

  if constants.NV_DRBDVERSION in what and vm_capable:
    try:
      drbd_version = DRBD8.GetProcInfo().GetVersionString()
    except errors.BlockDeviceError, err:
      logging.warning("Can't get DRBD version", exc_info=True)
      drbd_version = str(err)
    result[constants.NV_DRBDVERSION] = drbd_version

  if constants.NV_DRBDLIST in what and vm_capable:
    try:
      used_minors = drbd.DRBD8.GetUsedDevs()
    except errors.BlockDeviceError, err:
      logging.warning("Can't get used minors list", exc_info=True)
      used_minors = str(err)
    result[constants.NV_DRBDLIST] = used_minors

  if constants.NV_DRBDHELPER in what and vm_capable:
    status = True
    try:
      payload = drbd.DRBD8.GetUsermodeHelper()
    except errors.BlockDeviceError, err:
      logging.error("Can't get DRBD usermode helper: %s", str(err))
      status = False
      payload = str(err)
    result[constants.NV_DRBDHELPER] = (status, payload)

  if constants.NV_NODESETUP in what:
    result[constants.NV_NODESETUP] = tmpr = []
    if not os.path.isdir("/sys/block") or not os.path.isdir("/sys/class/net"):
      tmpr.append("The sysfs filesytem doesn't seem to be mounted"
                  " under /sys, missing required directories /sys/block"
                  " and /sys/class/net")
    if (not os.path.isdir("/proc/sys") or
        not os.path.isfile("/proc/sysrq-trigger")):
      tmpr.append("The procfs filesystem doesn't seem to be mounted"
                  " under /proc, missing required directory /proc/sys and"
                  " the file /proc/sysrq-trigger")

  if constants.NV_TIME in what:
    result[constants.NV_TIME] = utils.SplitTime(time.time())

  if constants.NV_OSLIST in what and vm_capable:
    result[constants.NV_OSLIST] = DiagnoseOS()

  if constants.NV_BRIDGES in what and vm_capable:
    result[constants.NV_BRIDGES] = [bridge
                                    for bridge in what[constants.NV_BRIDGES]
                                    if not utils.BridgeExists(bridge)]

  if what.get(constants.NV_ACCEPTED_STORAGE_PATHS) == my_name:
    result[constants.NV_ACCEPTED_STORAGE_PATHS] = \
        filestorage.ComputeWrongFileStoragePaths()

  if what.get(constants.NV_FILE_STORAGE_PATH):
    pathresult = filestorage.CheckFileStoragePath(
        what[constants.NV_FILE_STORAGE_PATH])
    if pathresult:
      result[constants.NV_FILE_STORAGE_PATH] = pathresult

  if what.get(constants.NV_SHARED_FILE_STORAGE_PATH):
    pathresult = filestorage.CheckFileStoragePath(
        what[constants.NV_SHARED_FILE_STORAGE_PATH])
    if pathresult:
      result[constants.NV_SHARED_FILE_STORAGE_PATH] = pathresult

  return result


def GetCryptoTokens(token_requests):
  """Perform actions on the node's cryptographic tokens.

  Token types can be 'ssl' or 'ssh'. So far only some actions are implemented
  for 'ssl'. Action 'get' returns the digest of the public client ssl
  certificate. Action 'create' creates a new client certificate and private key
  and also returns the digest of the certificate. The third parameter of a
  token request are optional parameters for the actions, so far only the
  filename is supported.

  @type token_requests: list of tuples of (string, string, dict), where the
    first string is in constants.CRYPTO_TYPES, the second in
    constants.CRYPTO_ACTIONS. The third parameter is a dictionary of string
    to string.
  @param token_requests: list of requests of cryptographic tokens and actions
    to perform on them. The actions come with a dictionary of options.
  @rtype: list of tuples (string, string)
  @return: list of tuples of the token type and the public crypto token

  """
  tokens = []
  for (token_type, action, _) in token_requests:
    if token_type not in constants.CRYPTO_TYPES:
      raise errors.ProgrammerError("Token type '%s' not supported." %
                                   token_type)
    if action not in constants.CRYPTO_ACTIONS:
      raise errors.ProgrammerError("Action '%s' is not supported." %
                                   action)
    if token_type == constants.CRYPTO_TYPE_SSL_DIGEST:
      tokens.append((token_type,
                     utils.GetCertificateDigest()))
  return tokens


def EnsureDaemon(daemon_name, run):
  """Ensures the given daemon is running or stopped.

  @type daemon_name: string
  @param daemon_name: name of the daemon (e.g., constants.KVMD)

  @type run: bool
  @param run: whether to start or stop the daemon

  @rtype: bool
  @return: 'True' if daemon successfully started/stopped,
           'False' otherwise

  """
  allowed_daemons = [constants.KVMD]

  if daemon_name not in allowed_daemons:
    fn = lambda _: False
  elif run:
    fn = utils.EnsureDaemon
  else:
    fn = utils.StopDaemon

  return fn(daemon_name)


def _InitSshUpdateData(data, noded_cert_file, ssconf_store):
  (_, noded_cert) = \
    utils.ExtractX509Certificate(utils.ReadFile(noded_cert_file))
  data[constants.SSHS_NODE_DAEMON_CERTIFICATE] = noded_cert

  cluster_name = ssconf_store.GetClusterName()
  data[constants.SSHS_CLUSTER_NAME] = cluster_name


def AddNodeSshKey(node_uuid, node_name,
                  potential_master_candidates,
                  to_authorized_keys=False,
                  to_public_keys=False,
                  get_public_keys=False,
                  pub_key_file=pathutils.SSH_PUB_KEYS,
                  ssconf_store=None,
                  noded_cert_file=pathutils.NODED_CERT_FILE,
                  run_cmd_fn=ssh.RunSshCmdWithStdin,
                  ssh_update_debug=False,
                  ssh_update_verbose=False):
  """Distributes a node's public SSH key across the cluster.

  Note that this function should only be executed on the master node, which
  then will copy the new node's key to all nodes in the cluster via SSH.

  Also note: at least one of the flags C{to_authorized_keys},
  C{to_public_keys}, and C{get_public_keys} has to be set to C{True} for
  the function to actually perform any actions.

  @type node_uuid: str
  @param node_uuid: the UUID of the node whose key is added
  @type node_name: str
  @param node_name: the name of the node whose key is added
  @type potential_master_candidates: list of str
  @param potential_master_candidates: list of node names of potential master
    candidates; this should match the list of uuids in the public key file
  @type to_authorized_keys: boolean
  @param to_authorized_keys: whether the key should be added to the
    C{authorized_keys} file of all nodes
  @type to_public_keys: boolean
  @param to_public_keys: whether the keys should be added to the public key file
  @type get_public_keys: boolean
  @param get_public_keys: whether the node should add the clusters' public keys
    to its {ganeti_pub_keys} file

  """
  node_list = [SshAddNodeInfo(name=node_name, uuid=node_uuid,
                              to_authorized_keys=to_authorized_keys,
                              to_public_keys=to_public_keys,
                              get_public_keys=get_public_keys)]
  return AddNodeSshKeyBulk(node_list,
                           potential_master_candidates,
                           pub_key_file=pub_key_file,
                           ssconf_store=ssconf_store,
                           noded_cert_file=noded_cert_file,
                           run_cmd_fn=run_cmd_fn,
                           ssh_update_debug=ssh_update_debug,
                           ssh_update_verbose=ssh_update_verbose)


# Node info named tuple specifically for the use with AddNodeSshKeyBulk
SshAddNodeInfo = collections.namedtuple(
  "SshAddNodeInfo",
  ["uuid",
   "name",
   "to_authorized_keys",
   "to_public_keys",
   "get_public_keys"])


def AddNodeSshKeyBulk(node_list,
                      potential_master_candidates,
                      pub_key_file=pathutils.SSH_PUB_KEYS,
                      ssconf_store=None,
                      noded_cert_file=pathutils.NODED_CERT_FILE,
                      run_cmd_fn=ssh.RunSshCmdWithStdin,
                      ssh_update_debug=False,
                      ssh_update_verbose=False):
  """Distributes a node's public SSH key across the cluster.

  Note that this function should only be executed on the master node, which
  then will copy the new node's key to all nodes in the cluster via SSH.

  Also note: at least one of the flags C{to_authorized_keys},
  C{to_public_keys}, and C{get_public_keys} has to be set to C{True} for
  the function to actually perform any actions.

  @type node_list: list of SshAddNodeInfo tuples
  @param node_list: list of tuples containing the necessary node information for
    adding their keys
  @type potential_master_candidates: list of str
  @param potential_master_candidates: list of node names of potential master
    candidates; this should match the list of uuids in the public key file

  """
  # whether there are any keys to be added or retrieved at all
  to_authorized_keys = any([node_info.to_authorized_keys for node_info in
                            node_list])
  to_public_keys = any([node_info.to_public_keys for node_info in
                        node_list])

  if not ssconf_store:
    ssconf_store = ssconf.SimpleStore()

  for node_info in node_list:
    # replacement not necessary for keys that are not supposed to be in the
    # list of public keys
    if not node_info.to_public_keys:
      continue
    # Check and fix sanity of key file
    keys_by_name = ssh.QueryPubKeyFile([node_info.name], key_file=pub_key_file)
    keys_by_uuid = ssh.QueryPubKeyFile([node_info.uuid], key_file=pub_key_file)

    if (not keys_by_name or node_info.name not in keys_by_name) \
        and (not keys_by_uuid or node_info.uuid not in keys_by_uuid):
      raise errors.SshUpdateError(
        "No keys found for the new node '%s' (UUID %s) in the list of public"
        " SSH keys, neither for the name or the UUID" %
        (node_info.name, node_info.uuid))
    else:
      if node_info.name in keys_by_name:
        # Replace the name by UUID in the file as the name should only be used
        # temporarily
        ssh.ReplaceNameByUuid(node_info.uuid, node_info.name,
                              error_fn=errors.SshUpdateError,
                              key_file=pub_key_file)

  # Retrieve updated map of UUIDs to keys
  keys_by_uuid = ssh.QueryPubKeyFile(
      [node_info.uuid for node_info in node_list], key_file=pub_key_file)

  # Update the master node's key files
  (auth_key_file, _) = \
    ssh.GetAllUserFiles(constants.SSH_LOGIN_USER, mkdir=False, dircheck=False)
  for node_info in node_list:
    if node_info.to_authorized_keys:
      ssh.AddAuthorizedKeys(auth_key_file, keys_by_uuid[node_info.uuid])

  base_data = {}
  _InitSshUpdateData(base_data, noded_cert_file, ssconf_store)
  cluster_name = base_data[constants.SSHS_CLUSTER_NAME]

  ssh_port_map = ssconf_store.GetSshPortMap()

  # Update the target nodes themselves
  for node_info in node_list:
    logging.debug("Updating SSH key files of target node '%s'.", node_info.name)
    if node_info.get_public_keys:
      node_data = {}
      _InitSshUpdateData(node_data, noded_cert_file, ssconf_store)
      all_keys = ssh.QueryPubKeyFile(None, key_file=pub_key_file)
      node_data[constants.SSHS_SSH_PUBLIC_KEYS] = \
        (constants.SSHS_OVERRIDE, all_keys)

      try:
        backoff = 5  # seconds
        utils.RetryByNumberOfTimes(
            constants.SSHS_MAX_RETRIES, backoff,
            errors.SshUpdateError,
            run_cmd_fn, cluster_name, node_info.name, pathutils.SSH_UPDATE,
            ssh_port_map.get(node_info.name), node_data,
            debug=ssh_update_debug, verbose=ssh_update_verbose,
            use_cluster_key=False, ask_key=False, strict_host_check=False)
      except errors.SshUpdateError as e:
        # Clean up the master's public key file if adding key fails
        if node_info.to_public_keys:
          ssh.RemovePublicKey(node_info.uuid)
        raise e

  # Update all nodes except master and the target nodes
  keys_by_uuid_auth = ssh.QueryPubKeyFile(
      [node_info.uuid for node_info in node_list
       if node_info.to_authorized_keys],
      key_file=pub_key_file)
  if to_authorized_keys:
    base_data[constants.SSHS_SSH_AUTHORIZED_KEYS] = \
      (constants.SSHS_ADD, keys_by_uuid_auth)

  pot_mc_data = base_data.copy()
  keys_by_uuid_pub = ssh.QueryPubKeyFile(
      [node_info.uuid for node_info in node_list
       if node_info.to_public_keys],
      key_file=pub_key_file)
  if to_public_keys:
    pot_mc_data[constants.SSHS_SSH_PUBLIC_KEYS] = \
      (constants.SSHS_REPLACE_OR_ADD, keys_by_uuid_pub)

  all_nodes = ssconf_store.GetNodeList()
  master_node = ssconf_store.GetMasterNode()
  online_nodes = ssconf_store.GetOnlineNodeList()

  node_errors = []
  for node in all_nodes:
    if node == master_node:
      logging.debug("Skipping master node '%s'.", master_node)
      continue
    if node not in online_nodes:
      logging.debug("Skipping offline node '%s'.", node)
      continue
    if node in potential_master_candidates:
      logging.debug("Updating SSH key files of node '%s'.", node)
      try:
        backoff = 5  # seconds
        utils.RetryByNumberOfTimes(
            constants.SSHS_MAX_RETRIES, backoff, errors.SshUpdateError,
            run_cmd_fn, cluster_name, node, pathutils.SSH_UPDATE,
            ssh_port_map.get(node), pot_mc_data,
            debug=ssh_update_debug, verbose=ssh_update_verbose,
            use_cluster_key=False, ask_key=False, strict_host_check=False)
      except errors.SshUpdateError as last_exception:
        error_msg = ("When adding the key of node '%s', updating SSH key"
                     " files of node '%s' failed after %s retries."
                     " Not trying again. Last error was: %s." %
                     (node, node_info.name, constants.SSHS_MAX_RETRIES,
                      last_exception))
        node_errors.append((node, error_msg))
        # We only log the error and don't throw an exception, because
        # one unreachable node shall not abort the entire procedure.
        logging.error(error_msg)

    else:
      if to_authorized_keys:
        run_cmd_fn(cluster_name, node, pathutils.SSH_UPDATE,
                   ssh_port_map.get(node), base_data,
                   debug=ssh_update_debug, verbose=ssh_update_verbose,
                   use_cluster_key=False, ask_key=False,
                   strict_host_check=False)

  return node_errors


# TODO: will be fixed with pending patch series.
# pylint: disable=R0913
def RemoveNodeSshKey(node_uuid, node_name,
                     master_candidate_uuids,
                     potential_master_candidates,
                     master_uuid=None,
                     keys_to_remove=None,
                     from_authorized_keys=False,
                     from_public_keys=False,
                     clear_authorized_keys=False,
                     clear_public_keys=False,
                     pub_key_file=pathutils.SSH_PUB_KEYS,
                     ssconf_store=None,
                     noded_cert_file=pathutils.NODED_CERT_FILE,
                     readd=False,
                     run_cmd_fn=ssh.RunSshCmdWithStdin,
                     ssh_update_debug=False,
                     ssh_update_verbose=False):
  """Removes the node's SSH keys from the key files and distributes those.

  Note that at least one of the flags C{from_authorized_keys},
  C{from_public_keys}, C{clear_authorized_keys}, and C{clear_public_keys}
  has to be set to C{True} for the function to perform any action at all.
  Not doing so will trigger an assertion in the function.

  @type node_uuid: str
  @param node_uuid: UUID of the node whose key is removed
  @type node_name: str
  @param node_name: name of the node whose key is remove
  @type master_candidate_uuids: list of str
  @param master_candidate_uuids: list of UUIDs of the current master candidates
  @type potential_master_candidates: list of str
  @param potential_master_candidates: list of names of potential master
    candidates
  @type keys_to_remove: dict of str to list of str
  @param keys_to_remove: a dictionary mapping node UUIDS to lists of SSH keys
    to be removed. This list is supposed to be used only if the keys are not
    in the public keys file. This is for example the case when removing a
    master node's key.
  @type from_authorized_keys: boolean
  @param from_authorized_keys: whether or not the key should be removed
    from the C{authorized_keys} file
  @type from_public_keys: boolean
  @param from_public_keys: whether or not the key should be remove from
    the C{ganeti_pub_keys} file
  @type clear_authorized_keys: boolean
  @param clear_authorized_keys: whether or not the C{authorized_keys} file
    should be cleared on the node whose keys are removed
  @type clear_public_keys: boolean
  @param clear_public_keys: whether to clear the node's C{ganeti_pub_key} file
  @type readd: boolean
  @param readd: whether this is called during a readd operation.
  @rtype: list of string
  @returns: list of feedback messages

  """
  node_list = [SshRemoveNodeInfo(uuid=node_uuid,
                                 name=node_name,
                                 from_authorized_keys=from_authorized_keys,
                                 from_public_keys=from_public_keys,
                                 clear_authorized_keys=clear_authorized_keys,
                                 clear_public_keys=clear_public_keys)]
  return RemoveNodeSshKeyBulk(node_list,
                              master_candidate_uuids,
                              potential_master_candidates,
                              master_uuid=master_uuid,
                              keys_to_remove=keys_to_remove,
                              pub_key_file=pub_key_file,
                              ssconf_store=ssconf_store,
                              noded_cert_file=noded_cert_file,
                              readd=readd,
                              run_cmd_fn=run_cmd_fn,
                              ssh_update_debug=ssh_update_debug,
                              ssh_update_verbose=ssh_update_verbose)


# Node info named tuple specifically for the use with RemoveNodeSshKeyBulk
SshRemoveNodeInfo = collections.namedtuple(
  "SshRemoveNodeInfo",
  ["uuid",
   "name",
   "from_authorized_keys",
   "from_public_keys",
   "clear_authorized_keys",
   "clear_public_keys"])


def RemoveNodeSshKeyBulk(node_list,
                         master_candidate_uuids,
                         potential_master_candidates,
                         master_uuid=None,
                         keys_to_remove=None,
                         pub_key_file=pathutils.SSH_PUB_KEYS,
                         ssconf_store=None,
                         noded_cert_file=pathutils.NODED_CERT_FILE,
                         readd=False,
                         run_cmd_fn=ssh.RunSshCmdWithStdin,
                         ssh_update_debug=False,
                         ssh_update_verbose=False):
  """Removes the node's SSH keys from the key files and distributes those.

  Note that at least one of the flags C{from_authorized_keys},
  C{from_public_keys}, C{clear_authorized_keys}, and C{clear_public_keys}
  of at least one node has to be set to C{True} for the function to perform any
  action at all. Not doing so will trigger an assertion in the function.

  @type node_list: list of C{SshRemoveNodeInfo}.
  @param node_list: list of information about nodes whose keys are being removed
  @type master_candidate_uuids: list of str
  @param master_candidate_uuids: list of UUIDs of the current master candidates
  @type potential_master_candidates: list of str
  @param potential_master_candidates: list of names of potential master
    candidates
  @type keys_to_remove: dict of str to list of str
  @param keys_to_remove: a dictionary mapping node UUIDS to lists of SSH keys
    to be removed. This list is supposed to be used only if the keys are not
    in the public keys file. This is for example the case when removing a
    master node's key.
  @type readd: boolean
  @param readd: whether this is called during a readd operation.
  @rtype: list of string
  @returns: list of feedback messages

  """
  # Non-disruptive error messages, list of (node, msg) pairs
  result_msgs = []

  # whether there are any keys to be added or retrieved at all
  from_authorized_keys = any([node_info.from_authorized_keys for node_info in
                              node_list])
  from_public_keys = any([node_info.from_public_keys for node_info in
                          node_list])
  clear_authorized_keys = any([node_info.clear_authorized_keys for node_info in
                               node_list])
  clear_public_keys = any([node_info.clear_public_keys for node_info in
                           node_list])

  # Make sure at least one of these flags is true.
  if not (from_authorized_keys or from_public_keys or clear_authorized_keys
          or clear_public_keys):
    raise errors.SshUpdateError("No removal from any key file was requested.")

  if not ssconf_store:
    ssconf_store = ssconf.SimpleStore()

  master_node = ssconf_store.GetMasterNode()
  ssh_port_map = ssconf_store.GetSshPortMap()

  all_keys_to_remove = {}
  if from_authorized_keys or from_public_keys:
    for node_info in node_list:
      # Skip nodes that don't actually need any keys to be removed.
      if not (node_info.from_authorized_keys or node_info.from_public_keys):
        continue
      if node_info.name == master_node and not keys_to_remove:
        raise errors.SshUpdateError("Cannot remove the master node's keys.")
      if keys_to_remove:
        keys = keys_to_remove
      else:
        keys = ssh.QueryPubKeyFile([node_info.uuid], key_file=pub_key_file)
        if (not keys or node_info.uuid not in keys) and not readd:
          raise errors.SshUpdateError("Node '%s' not found in the list of"
                                      " public SSH keys. It seems someone"
                                      " tries to remove a key from outside"
                                      " the cluster!" % node_info.uuid)
        # During an upgrade all nodes have the master key. In this case we
        # should not remove it to avoid accidentally shutting down cluster
        # SSH communication
        master_keys = None
        if master_uuid:
          master_keys = ssh.QueryPubKeyFile([master_uuid],
                                            key_file=pub_key_file)
          for master_key in master_keys:
            if master_key in keys[node_info.uuid]:
              keys[node_info.uuid].remove(master_key)

      all_keys_to_remove.update(keys)

    if all_keys_to_remove:
      base_data = {}
      _InitSshUpdateData(base_data, noded_cert_file, ssconf_store)
      cluster_name = base_data[constants.SSHS_CLUSTER_NAME]

      if from_authorized_keys:
        # UUIDs of nodes that are supposed to be removed from the
        # authorized_keys files.
        nodes_remove_from_authorized_keys = [
            node_info.uuid for node_info in node_list
            if node_info.from_authorized_keys]
        keys_to_remove_from_authorized_keys = dict([
            (uuid, keys) for (uuid, keys) in all_keys_to_remove.items()
            if uuid in nodes_remove_from_authorized_keys])
        base_data[constants.SSHS_SSH_AUTHORIZED_KEYS] = \
          (constants.SSHS_REMOVE, keys_to_remove_from_authorized_keys)
        (auth_key_file, _) = \
          ssh.GetAllUserFiles(constants.SSH_LOGIN_USER, mkdir=False,
                              dircheck=False)

        for uuid in nodes_remove_from_authorized_keys:
          ssh.RemoveAuthorizedKeys(auth_key_file,
                                   keys_to_remove_from_authorized_keys[uuid])

      pot_mc_data = base_data.copy()

      if from_public_keys:
        nodes_remove_from_public_keys = [
            node_info.uuid for node_info in node_list
            if node_info.from_public_keys]
        keys_to_remove_from_public_keys = dict([
            (uuid, keys) for (uuid, keys) in all_keys_to_remove.items()
            if uuid in nodes_remove_from_public_keys])
        pot_mc_data[constants.SSHS_SSH_PUBLIC_KEYS] = \
          (constants.SSHS_REMOVE, keys_to_remove_from_public_keys)

      all_nodes = ssconf_store.GetNodeList()
      online_nodes = ssconf_store.GetOnlineNodeList()
      all_nodes_to_remove = [node_info.name for node_info in node_list]
      logging.debug("Removing keys of nodes '%s' from all nodes but itself and"
                    " master.", ", ".join(all_nodes_to_remove))
      for node in all_nodes:
        if node == master_node:
          logging.debug("Skipping master node '%s'.", master_node)
          continue
        if node not in online_nodes:
          logging.debug("Skipping offline node '%s'.", node)
          continue
        if node in all_nodes_to_remove:
          logging.debug("Skipping node whose key is removed itself '%s'.", node)
          continue
        ssh_port = ssh_port_map.get(node)
        if not ssh_port:
          raise errors.OpExecError("No SSH port information available for"
                                   " node '%s', map: %s." %
                                   (node, ssh_port_map))
        error_msg_final = ("When removing the key of node '%s', updating the"
                           " SSH key files of node '%s' failed. Last error"
                           " was: %s.")
        if node in potential_master_candidates:
          logging.debug("Updating key setup of potential master candidate node"
                        " %s.", node)
          try:
            backoff = 5  # seconds
            utils.RetryByNumberOfTimes(
                constants.SSHS_MAX_RETRIES, backoff, errors.SshUpdateError,
                run_cmd_fn, cluster_name, node, pathutils.SSH_UPDATE,
                ssh_port, pot_mc_data,
                debug=ssh_update_debug, verbose=ssh_update_verbose,
                use_cluster_key=False, ask_key=False, strict_host_check=False)
          except errors.SshUpdateError as last_exception:
            error_msg = error_msg_final % (
                node_info.name, node, last_exception)
            result_msgs.append((node, error_msg))
            logging.error(error_msg)

        else:
          if from_authorized_keys:
            logging.debug("Updating key setup of normal node %s.", node)
            try:
              backoff = 5  # seconds
              utils.RetryByNumberOfTimes(
                  constants.SSHS_MAX_RETRIES, backoff, errors.SshUpdateError,
                  run_cmd_fn, cluster_name, node, pathutils.SSH_UPDATE,
                  ssh_port, base_data,
                  debug=ssh_update_debug, verbose=ssh_update_verbose,
                  use_cluster_key=False, ask_key=False, strict_host_check=False)
            except errors.SshUpdateError as last_exception:
              error_msg = error_msg_final % (
                  node_info.name, node, last_exception)
              result_msgs.append((node, error_msg))
              logging.error(error_msg)

  for node_info in node_list:
    if node_info.clear_authorized_keys or node_info.from_public_keys or \
        node_info.clear_public_keys:
      data = {}
      _InitSshUpdateData(data, noded_cert_file, ssconf_store)
      cluster_name = data[constants.SSHS_CLUSTER_NAME]
      ssh_port = ssh_port_map.get(node_info.name)
      if not ssh_port:
        raise errors.OpExecError("No SSH port information available for"
                                 " node '%s', which is leaving the cluster.")

      if node_info.clear_authorized_keys:
        # The 'authorized_keys' file is not solely managed by Ganeti. Therefore,
        # we have to specify exactly which keys to clear to leave keys untouched
        # that were not added by Ganeti.
        other_master_candidate_uuids = [uuid for uuid in master_candidate_uuids
                                        if uuid != node_info.uuid]
        candidate_keys = ssh.QueryPubKeyFile(other_master_candidate_uuids,
                                             key_file=pub_key_file)
        data[constants.SSHS_SSH_AUTHORIZED_KEYS] = \
          (constants.SSHS_REMOVE, candidate_keys)

      if node_info.clear_public_keys:
        data[constants.SSHS_SSH_PUBLIC_KEYS] = \
          (constants.SSHS_CLEAR, {})
      elif node_info.from_public_keys:
        # Since clearing the public keys subsumes removing just a single key,
        # we only do it if clear_public_keys is 'False'.

        if all_keys_to_remove:
          data[constants.SSHS_SSH_PUBLIC_KEYS] = \
            (constants.SSHS_REMOVE, all_keys_to_remove)

      # If we have no changes to any keyfile, just return
      if not (constants.SSHS_SSH_PUBLIC_KEYS in data or
              constants.SSHS_SSH_AUTHORIZED_KEYS in data):
        return

      logging.debug("Updating SSH key setup of target node '%s'.",
                    node_info.name)
      try:
        backoff = 5  # seconds
        utils.RetryByNumberOfTimes(
            constants.SSHS_MAX_RETRIES, backoff,
            errors.SshUpdateError,
            run_cmd_fn, cluster_name, node_info.name, pathutils.SSH_UPDATE,
            ssh_port, data,
            debug=ssh_update_debug, verbose=ssh_update_verbose,
            use_cluster_key=False, ask_key=False, strict_host_check=False)
      except errors.SshUpdateError as last_exception:
        result_msgs.append(
            (node_info.name,
             ("Removing SSH keys from node '%s' failed."
              " This can happen when the node is already unreachable."
              " Error: %s" % (node_info.name, last_exception))))

  if all_keys_to_remove and from_public_keys:
    for node_uuid in nodes_remove_from_public_keys:
      ssh.RemovePublicKey(node_uuid, key_file=pub_key_file)

  return result_msgs
# pylint: enable=R0913


def RemoveSshKeyFromPublicKeyFile(node_name,
                                  pub_key_file=pathutils.SSH_PUB_KEYS,
                                  ssconf_store=None):
  """Removes a SSH key from the master's public key file.

  This is an operation that is only used to clean up after failed operations
  (for example failed hooks before adding a node). To avoid abuse of this
  function (and the matching RPC call), we add a safety check to make sure
  that only stray keys can be removed that belong to nodes that are not
  in the cluster (anymore).

  @type node_name: string
  @param node_name: the name of the node whose key is removed

  """
  if not ssconf_store:
    ssconf_store = ssconf.SimpleStore()

  node_list = ssconf_store.GetNodeList()

  if node_name in node_list:
    raise errors.SshUpdateError("Cannot remove key of node '%s',"
                                " because it still belongs to the cluster."
                                % node_name)

  keys_by_name = ssh.QueryPubKeyFile([node_name], key_file=pub_key_file)
  if not keys_by_name or node_name not in keys_by_name:
    logging.info("The node '%s' whose key is supposed to be removed does not"
                 " have an entry in the public key file. Hence, there is"
                 " nothing left to do.", node_name)

  ssh.RemovePublicKey(node_name, key_file=pub_key_file)


def _GenerateNodeSshKey(node_name, ssh_port_map, ssh_key_type, ssh_key_bits,
                        ssconf_store=None,
                        noded_cert_file=pathutils.NODED_CERT_FILE,
                        run_cmd_fn=ssh.RunSshCmdWithStdin,
                        suffix="",
                        ssh_update_debug=False,
                        ssh_update_verbose=False):
  """Generates the root SSH key pair on the node.

  @type node_name: str
  @param node_name: name of the node whose key is remove
  @type ssh_port_map: dict of str to int
  @param ssh_port_map: mapping of node names to their SSH port
  @type ssh_key_type: One of L{constants.SSHK_ALL}
  @param ssh_key_type: the type of SSH key to be generated
  @type ssh_key_bits: int
  @param ssh_key_bits: the length of the key to be generated

  """
  if not ssconf_store:
    ssconf_store = ssconf.SimpleStore()

  data = {}
  _InitSshUpdateData(data, noded_cert_file, ssconf_store)
  cluster_name = data[constants.SSHS_CLUSTER_NAME]
  data[constants.SSHS_GENERATE] = (ssh_key_type, ssh_key_bits, suffix)

  run_cmd_fn(cluster_name, node_name, pathutils.SSH_UPDATE,
             ssh_port_map.get(node_name), data,
             debug=ssh_update_debug, verbose=ssh_update_verbose,
             use_cluster_key=False, ask_key=False, strict_host_check=False)


def _GetMasterNodeUUID(node_uuid_name_map, master_node_name):
  master_node_uuids = [node_uuid for (node_uuid, node_name)
                       in node_uuid_name_map
                       if node_name == master_node_name]
  if len(master_node_uuids) != 1:
    raise errors.SshUpdateError("No (unique) master UUID found. Master node"
                                " name: '%s', Master UUID: '%s'" %
                                (master_node_name, master_node_uuids))
  return master_node_uuids[0]


def _GetOldMasterKeys(master_node_uuid, pub_key_file):
  old_master_keys_by_uuid = ssh.QueryPubKeyFile([master_node_uuid],
                                                key_file=pub_key_file)
  if not old_master_keys_by_uuid:
    raise errors.SshUpdateError("No public key of the master node (UUID '%s')"
                                " found, not generating a new key."
                                % master_node_uuid)
  return old_master_keys_by_uuid


def RenewSshKeys(node_uuids, node_names, master_candidate_uuids,
                 potential_master_candidates, old_key_type, new_key_type,
                 new_key_bits,
                 ganeti_pub_keys_file=pathutils.SSH_PUB_KEYS,
                 ssconf_store=None,
                 noded_cert_file=pathutils.NODED_CERT_FILE,
                 run_cmd_fn=ssh.RunSshCmdWithStdin,
                 ssh_update_debug=False,
                 ssh_update_verbose=False):
  """Renews all SSH keys and updates authorized_keys and ganeti_pub_keys.

  @type node_uuids: list of str
  @param node_uuids: list of node UUIDs whose keys should be renewed
  @type node_names: list of str
  @param node_names: list of node names whose keys should be removed. This list
    should match the C{node_uuids} parameter
  @type master_candidate_uuids: list of str
  @param master_candidate_uuids: list of UUIDs of master candidates or
    master node
  @type old_key_type: One of L{constants.SSHK_ALL}
  @param old_key_type: the type of SSH key already present on nodes
  @type new_key_type: One of L{constants.SSHK_ALL}
  @param new_key_type: the type of SSH key to be generated
  @type new_key_bits: int
  @param new_key_bits: the length of the key to be generated
  @type ganeti_pub_keys_file: str
  @param ganeti_pub_keys_file: file path of the the public key file
  @type noded_cert_file: str
  @param noded_cert_file: path of the noded SSL certificate file
  @type run_cmd_fn: function
  @param run_cmd_fn: function to run commands on remote nodes via SSH
  @raises ProgrammerError: if node_uuids and node_names don't match;
    SshUpdateError if a node's key is missing from the public key file,
    if a node's new SSH key could not be fetched from it, if there is
    none or more than one entry in the public key list for the master
    node.

  """
  if not ssconf_store:
    ssconf_store = ssconf.SimpleStore()
  cluster_name = ssconf_store.GetClusterName()

  if not len(node_uuids) == len(node_names):
    raise errors.ProgrammerError("List of nodes UUIDs and node names"
                                 " does not match in length.")

  old_pub_keyfile = ssh.GetSshPubKeyFilename(old_key_type)
  new_pub_keyfile = ssh.GetSshPubKeyFilename(new_key_type)
  old_master_key = ssh.ReadLocalSshPubKeys([old_key_type])

  node_uuid_name_map = zip(node_uuids, node_names)

  master_node_name = ssconf_store.GetMasterNode()
  master_node_uuid = _GetMasterNodeUUID(node_uuid_name_map, master_node_name)
  ssh_port_map = ssconf_store.GetSshPortMap()
  # List of all node errors that happened, but which did not abort the
  # procedure as a whole. It is important that this is a list to have a
  # somewhat chronological history of events.
  all_node_errors = []

  # process non-master nodes

  # keys to add in bulk at the end
  node_keys_to_add = []

  # list of all nodes
  node_list = []

  # list of keys to be removed before generating new keys
  node_info_to_remove = []

  for node_uuid, node_name in node_uuid_name_map:
    if node_name == master_node_name:
      continue
    master_candidate = node_uuid in master_candidate_uuids
    potential_master_candidate = node_name in potential_master_candidates
    node_list.append((node_uuid, node_name, master_candidate,
                      potential_master_candidate))

    if master_candidate:
      logging.debug("Fetching old SSH key from node '%s'.", node_name)
      old_pub_key = ssh.ReadRemoteSshPubKey(old_pub_keyfile,
                                            node_name, cluster_name,
                                            ssh_port_map[node_name],
                                            False, # ask_key
                                            False) # key_check
      if old_pub_key != old_master_key:
        # If we are already in a multi-key setup (that is past Ganeti 2.12),
        # we can safely remove the old key of the node. Otherwise, we cannot
        # remove that node's key, because it is also the master node's key
        # and that would terminate all communication from the master to the
        # node.
        node_info_to_remove.append(SshRemoveNodeInfo(
            uuid=node_uuid,
            name=node_name,
            from_authorized_keys=master_candidate,
            from_public_keys=False,
            clear_authorized_keys=False,
            clear_public_keys=False))
      else:
        logging.debug("Old key of node '%s' is the same as the current master"
                      " key. Not deleting that key on the node.", node_name)

  logging.debug("Removing old SSH keys of all master candidates.")
  if node_info_to_remove:
    node_errors = RemoveNodeSshKeyBulk(
        node_info_to_remove,
        master_candidate_uuids,
        potential_master_candidates,
        master_uuid=master_node_uuid,
        pub_key_file=ganeti_pub_keys_file,
        ssconf_store=ssconf_store,
        noded_cert_file=noded_cert_file,
        run_cmd_fn=run_cmd_fn,
        ssh_update_debug=ssh_update_debug,
        ssh_update_verbose=ssh_update_verbose)
    if node_errors:
      all_node_errors = all_node_errors + node_errors

  for (node_uuid, node_name, master_candidate, potential_master_candidate) \
      in node_list:

    logging.debug("Generating new SSH key for node '%s'.", node_name)
    _GenerateNodeSshKey(node_name, ssh_port_map, new_key_type, new_key_bits,
                        ssconf_store=ssconf_store,
                        noded_cert_file=noded_cert_file,
                        run_cmd_fn=run_cmd_fn,
                        ssh_update_verbose=ssh_update_verbose,
                        ssh_update_debug=ssh_update_debug)

    try:
      logging.debug("Fetching newly created SSH key from node '%s'.", node_name)
      pub_key = ssh.ReadRemoteSshPubKey(new_pub_keyfile,
                                        node_name, cluster_name,
                                        ssh_port_map[node_name],
                                        False, # ask_key
                                        False) # key_check
    except:
      raise errors.SshUpdateError("Could not fetch key of node %s"
                                  " (UUID %s)" % (node_name, node_uuid))

    if potential_master_candidate:
      ssh.RemovePublicKey(node_uuid, key_file=ganeti_pub_keys_file)
      ssh.AddPublicKey(node_uuid, pub_key, key_file=ganeti_pub_keys_file)

    node_info = SshAddNodeInfo(name=node_name,
                               uuid=node_uuid,
                               to_authorized_keys=master_candidate,
                               to_public_keys=potential_master_candidate,
                               get_public_keys=True)
    node_keys_to_add.append(node_info)

  node_errors = AddNodeSshKeyBulk(
      node_keys_to_add, potential_master_candidates,
      pub_key_file=ganeti_pub_keys_file, ssconf_store=ssconf_store,
      noded_cert_file=noded_cert_file,
      run_cmd_fn=run_cmd_fn,
      ssh_update_debug=ssh_update_debug,
      ssh_update_verbose=ssh_update_verbose)
  if node_errors:
    all_node_errors = all_node_errors + node_errors

  # Renewing the master node's key

  # Preserve the old keys for now
  old_master_keys_by_uuid = _GetOldMasterKeys(master_node_uuid,
                                              ganeti_pub_keys_file)

  # Generate a new master key with a suffix, don't touch the old one for now
  logging.debug("Generate new ssh key of master.")
  _GenerateNodeSshKey(master_node_name, ssh_port_map,
                      new_key_type, new_key_bits,
                      ssconf_store=ssconf_store,
                      noded_cert_file=noded_cert_file,
                      run_cmd_fn=run_cmd_fn,
                      suffix=constants.SSHS_MASTER_SUFFIX,
                      ssh_update_debug=ssh_update_debug,
                      ssh_update_verbose=ssh_update_verbose)
  # Read newly created master key
  new_master_keys = ssh.ReadLocalSshPubKeys(
      [new_key_type], suffix=constants.SSHS_MASTER_SUFFIX)

  # Replace master key in the master nodes' public key file
  ssh.RemovePublicKey(master_node_uuid, key_file=ganeti_pub_keys_file)
  for pub_key in new_master_keys:
    ssh.AddPublicKey(master_node_uuid, pub_key, key_file=ganeti_pub_keys_file)

  # Add new master key to all node's public and authorized keys
  logging.debug("Add new master key to all nodes.")
  node_errors = AddNodeSshKey(
      master_node_uuid, master_node_name, potential_master_candidates,
      to_authorized_keys=True, to_public_keys=True,
      get_public_keys=False, pub_key_file=ganeti_pub_keys_file,
      ssconf_store=ssconf_store, noded_cert_file=noded_cert_file,
      run_cmd_fn=run_cmd_fn,
      ssh_update_debug=ssh_update_debug,
      ssh_update_verbose=ssh_update_verbose)
  if node_errors:
    all_node_errors = all_node_errors + node_errors

  # Remove the old key file and rename the new key to the non-temporary filename
  ssh.ReplaceSshKeys(new_key_type, new_key_type,
                     src_key_suffix=constants.SSHS_MASTER_SUFFIX)

  # Remove old key from authorized keys
  (auth_key_file, _) = \
      ssh.GetAllUserFiles(constants.SSH_LOGIN_USER, mkdir=False, dircheck=False)
  ssh.RemoveAuthorizedKeys(auth_key_file,
                           old_master_keys_by_uuid[master_node_uuid])

  # Remove the old key from all node's authorized keys file
  logging.debug("Remove the old master key from all nodes.")
  node_errors = RemoveNodeSshKey(
      master_node_uuid, master_node_name, master_candidate_uuids,
      potential_master_candidates,
      keys_to_remove=old_master_keys_by_uuid, from_authorized_keys=True,
      from_public_keys=False, clear_authorized_keys=False,
      clear_public_keys=False,
      pub_key_file=ganeti_pub_keys_file,
      ssconf_store=ssconf_store,
      noded_cert_file=noded_cert_file,
      run_cmd_fn=run_cmd_fn,
      ssh_update_debug=ssh_update_debug,
      ssh_update_verbose=ssh_update_verbose)
  if node_errors:
    all_node_errors = all_node_errors + node_errors

  return all_node_errors


def GetBlockDevSizes(devices):
  """Return the size of the given block devices

  @type devices: list
  @param devices: list of block device nodes to query
  @rtype: dict
  @return:
    dictionary of all block devices under /dev (key). The value is their
    size in MiB.

    {'/dev/disk/by-uuid/123456-12321231-312312-312': 124}

  """
  DEV_PREFIX = "/dev/"
  blockdevs = {}

  for devpath in devices:
    if not utils.IsBelowDir(DEV_PREFIX, devpath):
      continue

    try:
      st = os.stat(devpath)
    except EnvironmentError, err:
      logging.warning("Error stat()'ing device %s: %s", devpath, str(err))
      continue

    if stat.S_ISBLK(st.st_mode):
      result = utils.RunCmd(["blockdev", "--getsize64", devpath])
      if result.failed:
        # We don't want to fail, just do not list this device as available
        logging.warning("Cannot get size for block device %s", devpath)
        continue

      size = int(result.stdout) / (1024 * 1024)
      blockdevs[devpath] = size
  return blockdevs


def GetVolumeList(vg_names):
  """Compute list of logical volumes and their size.

  @type vg_names: list
  @param vg_names: the volume groups whose LVs we should list, or
      empty for all volume groups
  @rtype: dict
  @return:
      dictionary of all partions (key) with value being a tuple of
      their size (in MiB), inactive and online status::

        {'xenvg/test1': ('20.06', True, True)}

      in case of errors, a string is returned with the error
      details.

  """
  lvs = {}
  sep = "|"
  if not vg_names:
    vg_names = []
  result = utils.RunCmd(["lvs", "--noheadings", "--units=m", "--nosuffix",
                         "--separator=%s" % sep,
                         "-ovg_name,lv_name,lv_size,lv_attr"] + vg_names)
  if result.failed:
    _Fail("Failed to list logical volumes, lvs output: %s", result.output)

  for line in result.stdout.splitlines():
    line = line.strip()
    match = _LVSLINE_REGEX.match(line)
    if not match:
      logging.error("Invalid line returned from lvs output: '%s'", line)
      continue
    vg_name, name, size, attr = match.groups()
    inactive = attr[4] == "-"
    online = attr[5] == "o"
    virtual = attr[0] == "v"
    if virtual:
      # we don't want to report such volumes as existing, since they
      # don't really hold data
      continue
    lvs[vg_name + "/" + name] = (size, inactive, online)

  return lvs


def ListVolumeGroups():
  """List the volume groups and their size.

  @rtype: dict
  @return: dictionary with keys volume name and values the
      size of the volume

  """
  return utils.ListVolumeGroups()


def NodeVolumes():
  """List all volumes on this node.

  @rtype: list
  @return:
    A list of dictionaries, each having four keys:
      - name: the logical volume name,
      - size: the size of the logical volume
      - dev: the physical device on which the LV lives
      - vg: the volume group to which it belongs

    In case of errors, we return an empty list and log the
    error.

    Note that since a logical volume can live on multiple physical
    volumes, the resulting list might include a logical volume
    multiple times.

  """
  result = utils.RunCmd(["lvs", "--noheadings", "--units=m", "--nosuffix",
                         "--separator=|",
                         "--options=lv_name,lv_size,devices,vg_name"])
  if result.failed:
    _Fail("Failed to list logical volumes, lvs output: %s",
          result.output)

  def parse_dev(dev):
    return dev.split("(")[0]

  def handle_dev(dev):
    return [parse_dev(x) for x in dev.split(",")]

  def map_line(line):
    line = [v.strip() for v in line]
    return [{"name": line[0], "size": line[1],
             "dev": dev, "vg": line[3]} for dev in handle_dev(line[2])]

  all_devs = []
  for line in result.stdout.splitlines():
    if line.count("|") >= 3:
      all_devs.extend(map_line(line.split("|")))
    else:
      logging.warning("Strange line in the output from lvs: '%s'", line)
  return all_devs


def BridgesExist(bridges_list):
  """Check if a list of bridges exist on the current node.

  @rtype: boolean
  @return: C{True} if all of them exist, C{False} otherwise

  """
  missing = []
  for bridge in bridges_list:
    if not utils.BridgeExists(bridge):
      missing.append(bridge)

  if missing:
    _Fail("Missing bridges %s", utils.CommaJoin(missing))


def GetInstanceListForHypervisor(hname, hvparams=None,
                                 get_hv_fn=hypervisor.GetHypervisor):
  """Provides a list of instances of the given hypervisor.

  @type hname: string
  @param hname: name of the hypervisor
  @type hvparams: dict of strings
  @param hvparams: hypervisor parameters for the given hypervisor
  @type get_hv_fn: function
  @param get_hv_fn: function that returns a hypervisor for the given hypervisor
    name; optional parameter to increase testability

  @rtype: list
  @return: a list of all running instances on the current node
    - instance1.example.com
    - instance2.example.com

  """
  try:
    return get_hv_fn(hname).ListInstances(hvparams=hvparams)
  except errors.HypervisorError, err:
    _Fail("Error enumerating instances (hypervisor %s): %s",
          hname, err, exc=True)


def GetInstanceList(hypervisor_list, all_hvparams=None,
                    get_hv_fn=hypervisor.GetHypervisor):
  """Provides a list of instances.

  @type hypervisor_list: list
  @param hypervisor_list: the list of hypervisors to query information
  @type all_hvparams: dict of dict of strings
  @param all_hvparams: a dictionary mapping hypervisor types to respective
    cluster-wide hypervisor parameters
  @type get_hv_fn: function
  @param get_hv_fn: function that returns a hypervisor for the given hypervisor
    name; optional parameter to increase testability

  @rtype: list
  @return: a list of all running instances on the current node
    - instance1.example.com
    - instance2.example.com

  """
  results = []
  for hname in hypervisor_list:
    hvparams = all_hvparams[hname]
    results.extend(GetInstanceListForHypervisor(hname, hvparams=hvparams,
                                                get_hv_fn=get_hv_fn))
  return results


def GetInstanceInfo(instance, hname, hvparams=None):
  """Gives back the information about an instance as a dictionary.

  @type instance: string
  @param instance: the instance name
  @type hname: string
  @param hname: the hypervisor type of the instance
  @type hvparams: dict of strings
  @param hvparams: the instance's hvparams

  @rtype: dict
  @return: dictionary with the following keys:
      - memory: memory size of instance (int)
      - state: state of instance (HvInstanceState)
      - time: cpu time of instance (float)
      - vcpus: the number of vcpus (int)

  """
  output = {}

  iinfo = hypervisor.GetHypervisor(hname).GetInstanceInfo(instance,
                                                          hvparams=hvparams)
  if iinfo is not None:
    output["memory"] = iinfo[2]
    output["vcpus"] = iinfo[3]
    output["state"] = iinfo[4]
    output["time"] = iinfo[5]

  return output


def GetInstanceMigratable(instance):
  """Computes whether an instance can be migrated.

  @type instance: L{objects.Instance}
  @param instance: object representing the instance to be checked.

  @rtype: tuple
  @return: tuple of (result, description) where:
      - result: whether the instance can be migrated or not
      - description: a description of the issue, if relevant

  """
  hyper = hypervisor.GetHypervisor(instance.hypervisor)
  iname = instance.name
  if iname not in hyper.ListInstances(hvparams=instance.hvparams):
    _Fail("Instance %s is not running", iname)

  for idx in range(len(instance.disks_info)):
    link_name = _GetBlockDevSymlinkPath(iname, idx)
    if not os.path.islink(link_name):
      logging.warning("Instance %s is missing symlink %s for disk %d",
                      iname, link_name, idx)


def GetAllInstancesInfo(hypervisor_list, all_hvparams):
  """Gather data about all instances.

  This is the equivalent of L{GetInstanceInfo}, except that it
  computes data for all instances at once, thus being faster if one
  needs data about more than one instance.

  @type hypervisor_list: list
  @param hypervisor_list: list of hypervisors to query for instance data
  @type all_hvparams: dict of dict of strings
  @param all_hvparams: mapping of hypervisor names to hvparams

  @rtype: dict
  @return: dictionary of instance: data, with data having the following keys:
      - memory: memory size of instance (int)
      - state: xen state of instance (string)
      - time: cpu time of instance (float)
      - vcpus: the number of vcpus

  """
  output = {}
  for hname in hypervisor_list:
    hvparams = all_hvparams[hname]
    iinfo = hypervisor.GetHypervisor(hname).GetAllInstancesInfo(hvparams)
    if iinfo:
      for name, _, memory, vcpus, state, times in iinfo:
        value = {
          "memory": memory,
          "vcpus": vcpus,
          "state": state,
          "time": times,
          }
        if name in output:
          # we only check static parameters, like memory and vcpus,
          # and not state and time which can change between the
          # invocations of the different hypervisors
          for key in "memory", "vcpus":
            if value[key] != output[name][key]:
              _Fail("Instance %s is running twice"
                    " with different parameters", name)
        output[name] = value

  return output


def GetInstanceConsoleInfo(instance_param_dict,
                           get_hv_fn=hypervisor.GetHypervisor):
  """Gather data about the console access of a set of instances of this node.

  This function assumes that the caller already knows which instances are on
  this node, by calling a function such as L{GetAllInstancesInfo} or
  L{GetInstanceList}.

  For every instance, a large amount of configuration data needs to be
  provided to the hypervisor interface in order to receive the console
  information. Whether this could or should be cut down can be discussed.
  The information is provided in a dictionary indexed by instance name,
  allowing any number of instance queries to be done.

  @type instance_param_dict: dict of string to tuple of dictionaries, where the
    dictionaries represent: L{objects.Instance}, L{objects.Node},
    L{objects.NodeGroup}, HvParams, BeParams
  @param instance_param_dict: mapping of instance name to parameters necessary
    for console information retrieval

  @rtype: dict
  @return: dictionary of instance: data, with data having the following keys:
      - instance: instance name
      - kind: console kind
      - message: used with kind == CONS_MESSAGE, indicates console to be
                 unavailable, supplies error message
      - host: host to connect to
      - port: port to use
      - user: user for login
      - command: the command, broken into parts as an array
      - display: unknown, potentially unused?

  """

  output = {}
  for inst_name in instance_param_dict:
    instance = instance_param_dict[inst_name]["instance"]
    pnode = instance_param_dict[inst_name]["node"]
    group = instance_param_dict[inst_name]["group"]
    hvparams = instance_param_dict[inst_name]["hvParams"]
    beparams = instance_param_dict[inst_name]["beParams"]

    instance = objects.Instance.FromDict(instance)
    pnode = objects.Node.FromDict(pnode)
    group = objects.NodeGroup.FromDict(group)

    h = get_hv_fn(instance.hypervisor)
    output[inst_name] = h.GetInstanceConsole(instance, pnode, group,
                                             hvparams, beparams).ToDict()

  return output


def _InstanceLogName(kind, os_name, instance, component):
  """Compute the OS log filename for a given instance and operation.

  The instance name and os name are passed in as strings since not all
  operations have these as part of an instance object.

  @type kind: string
  @param kind: the operation type (e.g. add, import, etc.)
  @type os_name: string
  @param os_name: the os name
  @type instance: string
  @param instance: the name of the instance being imported/added/etc.
  @type component: string or None
  @param component: the name of the component of the instance being
      transferred

  """
  # TODO: Use tempfile.mkstemp to create unique filename
  if component:
    assert "/" not in component
    c_msg = "-%s" % component
  else:
    c_msg = ""
  base = ("%s-%s-%s%s-%s.log" %
          (kind, os_name, instance, c_msg, utils.TimestampForFilename()))
  return utils.PathJoin(pathutils.LOG_OS_DIR, base)


def InstanceOsAdd(instance, reinstall, debug):
  """Add an OS to an instance.

  @type instance: L{objects.Instance}
  @param instance: Instance whose OS is to be installed
  @type reinstall: boolean
  @param reinstall: whether this is an instance reinstall
  @type debug: integer
  @param debug: debug level, passed to the OS scripts
  @rtype: None

  """
  inst_os = OSFromDisk(instance.os)

  create_env = OSEnvironment(instance, inst_os, debug)
  if reinstall:
    create_env["INSTANCE_REINSTALL"] = "1"

  logfile = _InstanceLogName("add", instance.os, instance.name, None)

  result = utils.RunCmd([inst_os.create_script], env=create_env,
                        cwd=inst_os.path, output=logfile, reset_env=True)
  if result.failed:
    logging.error("os create command '%s' returned error: %s, logfile: %s,"
                  " output: %s", result.cmd, result.fail_reason, logfile,
                  result.output)
    lines = [utils.SafeEncode(val)
             for val in utils.TailFile(logfile, lines=20)]
    _Fail("OS create script failed (%s), last lines in the"
          " log file:\n%s", result.fail_reason, "\n".join(lines), log=False)


def RunRenameInstance(instance, old_name, debug):
  """Run the OS rename script for an instance.

  @type instance: L{objects.Instance}
  @param instance: Instance whose OS is to be installed
  @type old_name: string
  @param old_name: previous instance name
  @type debug: integer
  @param debug: debug level, passed to the OS scripts
  @rtype: boolean
  @return: the success of the operation

  """
  inst_os = OSFromDisk(instance.os)

  rename_env = OSEnvironment(instance, inst_os, debug)
  rename_env["OLD_INSTANCE_NAME"] = old_name

  logfile = _InstanceLogName("rename", instance.os,
                             "%s-%s" % (old_name, instance.name), None)

  result = utils.RunCmd([inst_os.rename_script], env=rename_env,
                        cwd=inst_os.path, output=logfile, reset_env=True)

  if result.failed:
    logging.error("os create command '%s' returned error: %s output: %s",
                  result.cmd, result.fail_reason, result.output)
    lines = [utils.SafeEncode(val)
             for val in utils.TailFile(logfile, lines=20)]
    _Fail("OS rename script failed (%s), last lines in the"
          " log file:\n%s", result.fail_reason, "\n".join(lines), log=False)


def _GetBlockDevSymlinkPath(instance_name, idx, _dir=None):
  """Returns symlink path for block device.

  """
  if _dir is None:
    _dir = pathutils.DISK_LINKS_DIR

  return utils.PathJoin(_dir,
                        ("%s%s%s" %
                         (instance_name, constants.DISK_SEPARATOR, idx)))


def _SymlinkBlockDev(instance_name, device_path, idx):
  """Set up symlinks to a instance's block device.

  This is an auxiliary function run when an instance is start (on the primary
  node) or when an instance is migrated (on the target node).


  @param instance_name: the name of the target instance
  @param device_path: path of the physical block device, on the node
  @param idx: the disk index
  @return: absolute path to the disk's symlink

  """
  # In case we have only a userspace access URI, device_path is None
  if not device_path:
    return None

  link_name = _GetBlockDevSymlinkPath(instance_name, idx)
  try:
    os.symlink(device_path, link_name)
  except OSError, err:
    if err.errno == errno.EEXIST:
      if (not os.path.islink(link_name) or
          os.readlink(link_name) != device_path):
        os.remove(link_name)
        os.symlink(device_path, link_name)
    else:
      raise

  return link_name


def _RemoveBlockDevLinks(instance_name, disks):
  """Remove the block device symlinks belonging to the given instance.

  """
  for idx, _ in enumerate(disks):
    link_name = _GetBlockDevSymlinkPath(instance_name, idx)
    if os.path.islink(link_name):
      try:
        os.remove(link_name)
      except OSError:
        logging.exception("Can't remove symlink '%s'", link_name)


def _CalculateDeviceURI(instance, disk, device):
  """Get the URI for the device.

  @type instance: L{objects.Instance}
  @param instance: the instance which disk belongs to
  @type disk: L{objects.Disk}
  @param disk: the target disk object
  @type device: L{bdev.BlockDev}
  @param device: the corresponding BlockDevice
  @rtype: string
  @return: the device uri if any else None

  """
  access_mode = disk.params.get(constants.LDP_ACCESS,
                                constants.DISK_KERNELSPACE)
  if access_mode == constants.DISK_USERSPACE:
    # This can raise errors.BlockDeviceError
    return device.GetUserspaceAccessUri(instance.hypervisor)
  else:
    return None


def _GatherAndLinkBlockDevs(instance):
  """Set up an instance's block device(s).

  This is run on the primary node at instance startup. The block
  devices must be already assembled.

  @type instance: L{objects.Instance}
  @param instance: the instance whose disks we should assemble
  @rtype: list
  @return: list of (disk_object, link_name, drive_uri)

  """
  block_devices = []
  for idx, disk in enumerate(instance.disks_info):
    device = _RecursiveFindBD(disk)
    if device is None:
      raise errors.BlockDeviceError("Block device '%s' is not set up." %
                                    str(disk))
    device.Open()
    try:
      link_name = _SymlinkBlockDev(instance.name, device.dev_path, idx)
    except OSError, e:
      raise errors.BlockDeviceError("Cannot create block device symlink: %s" %
                                    e.strerror)
    uri = _CalculateDeviceURI(instance, disk, device)

    block_devices.append((disk, link_name, uri))

  return block_devices


def _IsInstanceUserDown(instance_info):
  return instance_info and \
      "state" in instance_info and \
      hv_base.HvInstanceState.IsShutdown(instance_info["state"])


def _GetInstanceInfo(instance):
  """Helper function L{GetInstanceInfo}"""
  return GetInstanceInfo(instance.name, instance.hypervisor,
                         hvparams=instance.hvparams)


def StartInstance(instance, startup_paused, reason, store_reason=True):
  """Start an instance.

  @type instance: L{objects.Instance}
  @param instance: the instance object
  @type startup_paused: bool
  @param instance: pause instance at startup?
  @type reason: list of reasons
  @param reason: the reason trail for this startup
  @type store_reason: boolean
  @param store_reason: whether to store the shutdown reason trail on file
  @rtype: None

  """
  instance_info = _GetInstanceInfo(instance)

  if instance_info and not _IsInstanceUserDown(instance_info):
    logging.info("Instance '%s' already running, not starting", instance.name)
    return

  try:
    block_devices = _GatherAndLinkBlockDevs(instance)
    hyper = hypervisor.GetHypervisor(instance.hypervisor)
    hyper.StartInstance(instance, block_devices, startup_paused)
    if store_reason:
      _StoreInstReasonTrail(instance.name, reason)
  except errors.BlockDeviceError, err:
    _Fail("Block device error: %s", err, exc=True)
  except errors.HypervisorError, err:
    _RemoveBlockDevLinks(instance.name, instance.disks_info)
    _Fail("Hypervisor error: %s", err, exc=True)


def InstanceShutdown(instance, timeout, reason, store_reason=True):
  """Shut an instance down.

  @note: this functions uses polling with a hardcoded timeout.

  @type instance: L{objects.Instance}
  @param instance: the instance object
  @type timeout: integer
  @param timeout: maximum timeout for soft shutdown
  @type reason: list of reasons
  @param reason: the reason trail for this shutdown
  @type store_reason: boolean
  @param store_reason: whether to store the shutdown reason trail on file
  @rtype: None

  """
  hyper = hypervisor.GetHypervisor(instance.hypervisor)

  if not _GetInstanceInfo(instance):
    logging.info("Instance '%s' not running, doing nothing", instance.name)
    return

  class _TryShutdown(object):
    def __init__(self):
      self.tried_once = False

    def __call__(self):
      try:
        hyper.StopInstance(instance, retry=self.tried_once, timeout=timeout)
        if store_reason:
          _StoreInstReasonTrail(instance.name, reason)
      except errors.HypervisorError, err:
        # if the instance does no longer exist, consider this success and go to
        # cleanup, otherwise fail without retrying
        if _GetInstanceInfo(instance):
          _Fail("Failed to stop instance '%s': %s", instance.name, err)
        return

      # TODO: Cleanup hypervisor implementations to prevent them from failing
      # silently. We could easily decide if we want to retry or not by using
      # HypervisorSoftError()/HypervisorHardError()
      self.tried_once = True
      if _GetInstanceInfo(instance):
        raise utils.RetryAgain()

  try:
    utils.Retry(_TryShutdown(), 5, timeout)
  except utils.RetryTimeout:
    # the shutdown did not succeed
    logging.error("Shutdown of '%s' unsuccessful, forcing", instance.name)

    try:
      hyper.StopInstance(instance, force=True)
    except errors.HypervisorError, err:
      # only raise an error if the instance still exists, otherwise
      # the error could simply be "instance ... unknown"!
      if _GetInstanceInfo(instance):
        _Fail("Failed to force stop instance '%s': %s", instance.name, err)

    time.sleep(1)

    if _GetInstanceInfo(instance):
      _Fail("Could not shutdown instance '%s' even by destroy", instance.name)

  try:
    hyper.CleanupInstance(instance.name)
  except errors.HypervisorError, err:
    logging.warning("Failed to execute post-shutdown cleanup step: %s", err)

  _RemoveBlockDevLinks(instance.name, instance.disks_info)


def InstanceReboot(instance, reboot_type, shutdown_timeout, reason):
  """Reboot an instance.

  @type instance: L{objects.Instance}
  @param instance: the instance object to reboot
  @type reboot_type: str
  @param reboot_type: the type of reboot, one the following
    constants:
      - L{constants.INSTANCE_REBOOT_SOFT}: only reboot the
        instance OS, do not recreate the VM
      - L{constants.INSTANCE_REBOOT_HARD}: tear down and
        restart the VM (at the hypervisor level)
      - the other reboot type (L{constants.INSTANCE_REBOOT_FULL}) is
        not accepted here, since that mode is handled differently, in
        cmdlib, and translates into full stop and start of the
        instance (instead of a call_instance_reboot RPC)
  @type shutdown_timeout: integer
  @param shutdown_timeout: maximum timeout for soft shutdown
  @type reason: list of reasons
  @param reason: the reason trail for this reboot
  @rtype: None

  """
  # TODO: this is inconsistent with 'StartInstance' and 'InstanceShutdown'
  # because those functions simply 'return' on error whereas this one
  # raises an exception with '_Fail'
  if not _GetInstanceInfo(instance):
    _Fail("Cannot reboot instance '%s' that is not running", instance.name)

  hyper = hypervisor.GetHypervisor(instance.hypervisor)
  if reboot_type == constants.INSTANCE_REBOOT_SOFT:
    try:
      hyper.RebootInstance(instance)
    except errors.HypervisorError, err:
      _Fail("Failed to soft reboot instance '%s': %s", instance.name, err)
  elif reboot_type == constants.INSTANCE_REBOOT_HARD:
    try:
      InstanceShutdown(instance, shutdown_timeout, reason, store_reason=False)
      result = StartInstance(instance, False, reason, store_reason=False)
      _StoreInstReasonTrail(instance.name, reason)
      return result
    except errors.HypervisorError, err:
      _Fail("Failed to hard reboot instance '%s': %s", instance.name, err)
  else:
    _Fail("Invalid reboot_type received: '%s'", reboot_type)


def InstanceBalloonMemory(instance, memory):
  """Resize an instance's memory.

  @type instance: L{objects.Instance}
  @param instance: the instance object
  @type memory: int
  @param memory: new memory amount in MB
  @rtype: None

  """
  hyper = hypervisor.GetHypervisor(instance.hypervisor)
  running = hyper.ListInstances(hvparams=instance.hvparams)
  if instance.name not in running:
    logging.info("Instance %s is not running, cannot balloon", instance.name)
    return
  try:
    hyper.BalloonInstanceMemory(instance, memory)
  except errors.HypervisorError, err:
    _Fail("Failed to balloon instance memory: %s", err, exc=True)


def MigrationInfo(instance):
  """Gather information about an instance to be migrated.

  @type instance: L{objects.Instance}
  @param instance: the instance definition

  """
  hyper = hypervisor.GetHypervisor(instance.hypervisor)
  try:
    info = hyper.MigrationInfo(instance)
  except errors.HypervisorError, err:
    _Fail("Failed to fetch migration information: %s", err, exc=True)
  return info


def AcceptInstance(instance, info, target):
  """Prepare the node to accept an instance.

  @type instance: L{objects.Instance}
  @param instance: the instance definition
  @type info: string/data (opaque)
  @param info: migration information, from the source node
  @type target: string
  @param target: target host (usually ip), on this node

  """
  hyper = hypervisor.GetHypervisor(instance.hypervisor)
  try:
    hyper.AcceptInstance(instance, info, target)
  except errors.HypervisorError, err:
    _Fail("Failed to accept instance: %s", err, exc=True)


def FinalizeMigrationDst(instance, info, success):
  """Finalize any preparation to accept an instance.

  @type instance: L{objects.Instance}
  @param instance: the instance definition
  @type info: string/data (opaque)
  @param info: migration information, from the source node
  @type success: boolean
  @param success: whether the migration was a success or a failure

  """
  hyper = hypervisor.GetHypervisor(instance.hypervisor)
  try:
    hyper.FinalizeMigrationDst(instance, info, success)
  except errors.HypervisorError, err:
    _Fail("Failed to finalize migration on the target node: %s", err, exc=True)


def MigrateInstance(cluster_name, instance, target, live):
  """Migrates an instance to another node.

  @type cluster_name: string
  @param cluster_name: name of the cluster
  @type instance: L{objects.Instance}
  @param instance: the instance definition
  @type target: string
  @param target: the target node name
  @type live: boolean
  @param live: whether the migration should be done live or not (the
      interpretation of this parameter is left to the hypervisor)
  @raise RPCFail: if migration fails for some reason

  """
  hyper = hypervisor.GetHypervisor(instance.hypervisor)

  try:
    hyper.MigrateInstance(cluster_name, instance, target, live)
  except errors.HypervisorError, err:
    _Fail("Failed to migrate instance: %s", err, exc=True)


def FinalizeMigrationSource(instance, success, live):
  """Finalize the instance migration on the source node.

  @type instance: L{objects.Instance}
  @param instance: the instance definition of the migrated instance
  @type success: bool
  @param success: whether the migration succeeded or not
  @type live: bool
  @param live: whether the user requested a live migration or not
  @raise RPCFail: If the execution fails for some reason

  """
  hyper = hypervisor.GetHypervisor(instance.hypervisor)

  try:
    hyper.FinalizeMigrationSource(instance, success, live)
  except Exception, err:  # pylint: disable=W0703
    _Fail("Failed to finalize the migration on the source node: %s", err,
          exc=True)


def GetMigrationStatus(instance):
  """Get the migration status

  @type instance: L{objects.Instance}
  @param instance: the instance that is being migrated
  @rtype: L{objects.MigrationStatus}
  @return: the status of the current migration (one of
           L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
           progress info that can be retrieved from the hypervisor
  @raise RPCFail: If the migration status cannot be retrieved

  """
  hyper = hypervisor.GetHypervisor(instance.hypervisor)
  try:
    return hyper.GetMigrationStatus(instance)
  except Exception, err:  # pylint: disable=W0703
    _Fail("Failed to get migration status: %s", err, exc=True)


def HotplugDevice(instance, action, dev_type, device, extra, seq):
  """Hotplug a device

  Hotplug is currently supported only for KVM Hypervisor.
  @type instance: L{objects.Instance}
  @param instance: the instance to which we hotplug a device
  @type action: string
  @param action: the hotplug action to perform
  @type dev_type: string
  @param dev_type: the device type to hotplug
  @type device: either L{objects.NIC} or L{objects.Disk}
  @param device: the device object to hotplug
  @type extra: tuple
  @param extra: extra info used for disk hotplug (disk link, drive uri)
  @type seq: int
  @param seq: the index of the device from master perspective
  @raise RPCFail: in case instance does not have KVM hypervisor

  """
  hyper = hypervisor.GetHypervisor(instance.hypervisor)
  try:
    hyper.VerifyHotplugSupport(instance, action, dev_type)
  except errors.HotplugError, err:
    _Fail("Hotplug is not supported: %s", err)

  if action == constants.HOTPLUG_ACTION_ADD:
    fn = hyper.HotAddDevice
  elif action == constants.HOTPLUG_ACTION_REMOVE:
    fn = hyper.HotDelDevice
  elif action == constants.HOTPLUG_ACTION_MODIFY:
    fn = hyper.HotModDevice
  else:
    assert action in constants.HOTPLUG_ALL_ACTIONS

  return fn(instance, dev_type, device, extra, seq)


def HotplugSupported(instance):
  """Checks if hotplug is generally supported.

  """
  hyper = hypervisor.GetHypervisor(instance.hypervisor)
  try:
    hyper.HotplugSupported(instance)
  except errors.HotplugError, err:
    _Fail("Hotplug is not supported: %s", err)


def ModifyInstanceMetadata(metadata):
  """Sends instance data to the metadata daemon.

  Uses the Luxi transport layer to communicate with the metadata
  daemon configuration server.  It starts the metadata daemon if it is
  not running.
  The daemon must be enabled during at configuration time.

  @type metadata: dict
  @param metadata: instance metadata obtained by calling
                   L{objects.Instance.ToDict} on an instance object

  """
  if not constants.ENABLE_METAD:
    raise errors.ProgrammerError("The metadata deamon is disabled, yet"
                                 " ModifyInstanceMetadata has been called")

  if not utils.IsDaemonAlive(constants.METAD):
    result = utils.RunCmd([pathutils.DAEMON_UTIL, "start", constants.METAD])
    if result.failed:
      raise errors.HypervisorError("Failed to start metadata daemon")

  with contextlib.closing(metad.Client()) as client:
    client.UpdateConfig(metadata)


def BlockdevCreate(disk, size, owner, on_primary, info, excl_stor):
  """Creates a block device for an instance.

  @type disk: L{objects.Disk}
  @param disk: the object describing the disk we should create
  @type size: int
  @param size: the size of the physical underlying device, in MiB
  @type owner: str
  @param owner: the name of the instance for which disk is created,
      used for device cache data
  @type on_primary: boolean
  @param on_primary:  indicates if it is the primary node or not
  @type info: string
  @param info: string that will be sent to the physical device
      creation, used for example to set (LVM) tags on LVs
  @type excl_stor: boolean
  @param excl_stor: Whether exclusive_storage is active

  @return: the new unique_id of the device (this can sometime be
      computed only after creation), or None. On secondary nodes,
      it's not required to return anything.

  """
  # TODO: remove the obsolete "size" argument
  # pylint: disable=W0613
  clist = []
  if disk.children:
    for child in disk.children:
      try:
        crdev = _RecursiveAssembleBD(child, owner, on_primary)
      except errors.BlockDeviceError, err:
        _Fail("Can't assemble device %s: %s", child, err)
      if on_primary or disk.AssembleOnSecondary():
        # we need the children open in case the device itself has to
        # be assembled
        try:
          # pylint: disable=E1103
          crdev.Open()
        except errors.BlockDeviceError, err:
          _Fail("Can't make child '%s' read-write: %s", child, err)
      clist.append(crdev)

  try:
    device = bdev.Create(disk, clist, excl_stor)
  except errors.BlockDeviceError, err:
    _Fail("Can't create block device: %s", err)

  if on_primary or disk.AssembleOnSecondary():
    try:
      device.Assemble()
    except errors.BlockDeviceError, err:
      _Fail("Can't assemble device after creation, unusual event: %s", err)
    if on_primary or disk.OpenOnSecondary():
      try:
        device.Open(force=True)
      except errors.BlockDeviceError, err:
        _Fail("Can't make device r/w after creation, unusual event: %s", err)
    DevCacheManager.UpdateCache(device.dev_path, owner,
                                on_primary, disk.iv_name)

  device.SetInfo(info)

  return device.unique_id


def _DumpDevice(source_path, target_path, offset, size, truncate):
  """This function images/wipes the device using a local file.

  @type source_path: string
  @param source_path: path of the image or data source (e.g., "/dev/zero")

  @type target_path: string
  @param target_path: path of the device to image/wipe

  @type offset: int
  @param offset: offset in MiB in the output file

  @type size: int
  @param size: maximum size in MiB to write (data source might be smaller)

  @type truncate: bool
  @param truncate: whether the file should be truncated

  @return: None
  @raise RPCFail: in case of failure

  """
  # Internal sizes are always in Mebibytes; if the following "dd" command
  # should use a different block size the offset and size given to this
  # function must be adjusted accordingly before being passed to "dd".
  block_size = constants.DD_BLOCK_SIZE

  cmd = [constants.DD_CMD, "if=%s" % source_path, "seek=%d" % offset,
         "bs=%s" % block_size, "oflag=direct", "of=%s" % target_path,
         "count=%d" % size]

  if not truncate:
    cmd.append("conv=notrunc")

  result = utils.RunCmd(cmd)

  if result.failed:
    _Fail("Dump command '%s' exited with error: %s; output: %s", result.cmd,
          result.fail_reason, result.output)


def _DownloadAndDumpDevice(source_url, target_path, size):
  """This function images a device using a downloaded image file.

  @type source_url: string
  @param source_url: URL of image to dump to disk

  @type target_path: string
  @param target_path: path of the device to image

  @type size: int
  @param size: maximum size in MiB to write (data source might be smaller)

  @rtype: NoneType
  @return: None
  @raise RPCFail: in case of download or write failures

  """
  class DDParams(object):
    def __init__(self, current_size, total_size):
      self.current_size = current_size
      self.total_size = total_size
      self.image_size_error = False

  def dd_write(ddparams, out):
    if ddparams.current_size < ddparams.total_size:
      ddparams.current_size += len(out)
      target_file.write(out)
    else:
      ddparams.image_size_error = True
      return -1

  target_file = open(target_path, "r+")
  ddparams = DDParams(0, 1024 * 1024 * size)

  curl = pycurl.Curl()
  curl.setopt(pycurl.VERBOSE, True)
  curl.setopt(pycurl.NOSIGNAL, True)
  curl.setopt(pycurl.USERAGENT, http.HTTP_GANETI_VERSION)
  curl.setopt(pycurl.URL, source_url)
  curl.setopt(pycurl.WRITEFUNCTION, lambda out: dd_write(ddparams, out))

  try:
    curl.perform()
  except pycurl.error:
    if ddparams.image_size_error:
      _Fail("Disk image larger than the disk")
    else:
      raise

  target_file.close()


def BlockdevConvert(src_disk, target_disk):
  """Copies data from source block device to target.

  This function gets the export and import commands from the source and
  target devices respectively, and then concatenates them to a single
  command using a pipe ("|"). Finally, executes the unified command that
  will transfer the data between the devices during the disk template
  conversion operation.

  @type src_disk: L{objects.Disk}
  @param src_disk: the disk object we want to copy from
  @type target_disk: L{objects.Disk}
  @param target_disk: the disk object we want to copy to

  @rtype: NoneType
  @return: None
  @raise RPCFail: in case of failure

  """
  src_dev = _RecursiveFindBD(src_disk)
  if src_dev is None:
    _Fail("Cannot copy from device '%s': device not found", src_disk.uuid)

  dest_dev = _RecursiveFindBD(target_disk)
  if dest_dev is None:
    _Fail("Cannot copy to device '%s': device not found", target_disk.uuid)

  src_cmd = src_dev.Export()
  dest_cmd = dest_dev.Import()
  command = "%s | %s" % (utils.ShellQuoteArgs(src_cmd),
                         utils.ShellQuoteArgs(dest_cmd))

  result = utils.RunCmd(command)
  if result.failed:
    _Fail("Disk conversion command '%s' exited with error: %s; output: %s",
          result.cmd, result.fail_reason, result.output)


def BlockdevWipe(disk, offset, size):
  """Wipes a block device.

  @type disk: L{objects.Disk}
  @param disk: the disk object we want to wipe
  @type offset: int
  @param offset: The offset in MiB in the file
  @type size: int
  @param size: The size in MiB to write

  """
  try:
    rdev = _RecursiveFindBD(disk)
  except errors.BlockDeviceError:
    rdev = None

  if not rdev:
    _Fail("Cannot wipe device %s: device not found", disk.iv_name)
  if offset < 0:
    _Fail("Negative offset")
  if size < 0:
    _Fail("Negative size")
  if offset > rdev.size:
    _Fail("Wipe offset is bigger than device size")
  if (offset + size) > rdev.size:
    _Fail("Wipe offset and size are bigger than device size")

  _DumpDevice("/dev/zero", rdev.dev_path, offset, size, True)


def BlockdevImage(disk, image, size):
  """Images a block device either by dumping a local file or
  downloading a URL.

  @type disk: L{objects.Disk}
  @param disk: the disk object we want to image

  @type image: string
  @param image: file path to the disk image be dumped

  @type size: int
  @param size: The size in MiB to write

  @rtype: NoneType
  @return: None
  @raise RPCFail: in case of failure

  """
  if not (utils.IsUrl(image) or os.path.exists(image)):
    _Fail("Image '%s' not found", image)

  try:
    rdev = _RecursiveFindBD(disk)
  except errors.BlockDeviceError:
    rdev = None

  if not rdev:
    _Fail("Cannot image device %s: device not found", disk.iv_name)
  if size < 0:
    _Fail("Negative size")
  if size > rdev.size:
    _Fail("Image size is bigger than device size")

  if utils.IsUrl(image):
    _DownloadAndDumpDevice(image, rdev.dev_path, size)
  else:
    _DumpDevice(image, rdev.dev_path, 0, size, False)


def BlockdevPauseResumeSync(disks, pause):
  """Pause or resume the sync of the block device.

  @type disks: list of L{objects.Disk}
  @param disks: the disks object we want to pause/resume
  @type pause: bool
  @param pause: Wheater to pause or resume

  """
  success = []
  for disk in disks:
    try:
      rdev = _RecursiveFindBD(disk)
    except errors.BlockDeviceError:
      rdev = None

    if not rdev:
      success.append((False, ("Cannot change sync for device %s:"
                              " device not found" % disk.iv_name)))
      continue

    result = rdev.PauseResumeSync(pause)

    if result:
      success.append((result, None))
    else:
      if pause:
        msg = "Pause"
      else:
        msg = "Resume"
      success.append((result, "%s for device %s failed" % (msg, disk.iv_name)))

  return success


def BlockdevRemove(disk):
  """Remove a block device.

  @note: This is intended to be called recursively.

  @type disk: L{objects.Disk}
  @param disk: the disk object we should remove
  @rtype: boolean
  @return: the success of the operation

  """
  msgs = []
  try:
    rdev = _RecursiveFindBD(disk)
  except errors.BlockDeviceError, err:
    # probably can't attach
    logging.info("Can't attach to device %s in remove", disk)
    rdev = None
  if rdev is not None:
    r_path = rdev.dev_path

    def _TryRemove():
      try:
        rdev.Remove()
        return []
      except errors.BlockDeviceError, err:
        return [str(err)]

    msgs.extend(utils.SimpleRetry([], _TryRemove,
                                  constants.DISK_REMOVE_RETRY_INTERVAL,
                                  constants.DISK_REMOVE_RETRY_TIMEOUT))

    if not msgs:
      DevCacheManager.RemoveCache(r_path)

  if disk.children:
    for child in disk.children:
      try:
        BlockdevRemove(child)
      except RPCFail, err:
        msgs.append(str(err))

  if msgs:
    _Fail("; ".join(msgs))


def _RecursiveAssembleBD(disk, owner, as_primary):
  """Activate a block device for an instance.

  This is run on the primary and secondary nodes for an instance.

  @note: this function is called recursively.

  @type disk: L{objects.Disk}
  @param disk: the disk we try to assemble
  @type owner: str
  @param owner: the name of the instance which owns the disk
  @type as_primary: boolean
  @param as_primary: if we should make the block device
      read/write

  @return: the assembled device or None (in case no device
      was assembled)
  @raise errors.BlockDeviceError: in case there is an error
      during the activation of the children or the device
      itself

  """
  children = []
  if disk.children:
    mcn = disk.ChildrenNeeded()
    if mcn == -1:
      mcn = 0 # max number of Nones allowed
    else:
      mcn = len(disk.children) - mcn # max number of Nones
    for chld_disk in disk.children:
      try:
        cdev = _RecursiveAssembleBD(chld_disk, owner, as_primary)
      except errors.BlockDeviceError, err:
        if children.count(None) >= mcn:
          raise
        cdev = None
        logging.error("Error in child activation (but continuing): %s",
                      str(err))
      children.append(cdev)

  if as_primary or disk.AssembleOnSecondary():
    r_dev = bdev.Assemble(disk, children)
    result = r_dev
    if as_primary or disk.OpenOnSecondary():
      r_dev.Open()
    DevCacheManager.UpdateCache(r_dev.dev_path, owner,
                                as_primary, disk.iv_name)

  else:
    result = True
  return result


def BlockdevAssemble(disk, instance, as_primary, idx):
  """Activate a block device for an instance.

  This is a wrapper over _RecursiveAssembleBD.

  @rtype: str or boolean
  @return: a tuple with the C{/dev/...} path and the created symlink
      for primary nodes, and (C{True}, C{True}) for secondary nodes

  """
  try:
    result = _RecursiveAssembleBD(disk, instance.name, as_primary)
    if isinstance(result, BlockDev):
      # pylint: disable=E1103
      dev_path = result.dev_path
      link_name = None
      uri = None
      if as_primary:
        link_name = _SymlinkBlockDev(instance.name, dev_path, idx)
        uri = _CalculateDeviceURI(instance, disk, result)
    elif result:
      return result, result
    else:
      _Fail("Unexpected result from _RecursiveAssembleBD")
  except errors.BlockDeviceError, err:
    _Fail("Error while assembling disk: %s", err, exc=True)
  except OSError, err:
    _Fail("Error while symlinking disk: %s", err, exc=True)

  return dev_path, link_name, uri


def BlockdevShutdown(disk):
  """Shut down a block device.

  First, if the device is assembled (Attach() is successful), then
  the device is shutdown. Then the children of the device are
  shutdown.

  This function is called recursively. Note that we don't cache the
  children or such, as oppossed to assemble, shutdown of different
  devices doesn't require that the upper device was active.

  @type disk: L{objects.Disk}
  @param disk: the description of the disk we should
      shutdown
  @rtype: None

  """
  msgs = []
  r_dev = _RecursiveFindBD(disk)
  if r_dev is not None:
    r_path = r_dev.dev_path
    try:
      r_dev.Shutdown()
      DevCacheManager.RemoveCache(r_path)
    except errors.BlockDeviceError, err:
      msgs.append(str(err))

  if disk.children:
    for child in disk.children:
      try:
        BlockdevShutdown(child)
      except RPCFail, err:
        msgs.append(str(err))

  if msgs:
    _Fail("; ".join(msgs))


def BlockdevAddchildren(parent_cdev, new_cdevs):
  """Extend a mirrored block device.

  @type parent_cdev: L{objects.Disk}
  @param parent_cdev: the disk to which we should add children
  @type new_cdevs: list of L{objects.Disk}
  @param new_cdevs: the list of children which we should add
  @rtype: None

  """
  parent_bdev = _RecursiveFindBD(parent_cdev)
  if parent_bdev is None:
    _Fail("Can't find parent device '%s' in add children", parent_cdev)
  new_bdevs = [_RecursiveFindBD(disk) for disk in new_cdevs]
  if new_bdevs.count(None) > 0:
    _Fail("Can't find new device(s) to add: %s:%s", new_bdevs, new_cdevs)
  parent_bdev.AddChildren(new_bdevs)


def BlockdevRemovechildren(parent_cdev, new_cdevs):
  """Shrink a mirrored block device.

  @type parent_cdev: L{objects.Disk}
  @param parent_cdev: the disk from which we should remove children
  @type new_cdevs: list of L{objects.Disk}
  @param new_cdevs: the list of children which we should remove
  @rtype: None

  """
  parent_bdev = _RecursiveFindBD(parent_cdev)
  if parent_bdev is None:
    _Fail("Can't find parent device '%s' in remove children", parent_cdev)
  devs = []
  for disk in new_cdevs:
    rpath = disk.StaticDevPath()
    if rpath is None:
      bd = _RecursiveFindBD(disk)
      if bd is None:
        _Fail("Can't find device %s while removing children", disk)
      else:
        devs.append(bd.dev_path)
    else:
      if not utils.IsNormAbsPath(rpath):
        _Fail("Strange path returned from StaticDevPath: '%s'", rpath)
      devs.append(rpath)
  parent_bdev.RemoveChildren(devs)


def BlockdevGetmirrorstatus(disks):
  """Get the mirroring status of a list of devices.

  @type disks: list of L{objects.Disk}
  @param disks: the list of disks which we should query
  @rtype: disk
  @return: List of L{objects.BlockDevStatus}, one for each disk
  @raise errors.BlockDeviceError: if any of the disks cannot be
      found

  """
  stats = []
  for dsk in disks:
    rbd = _RecursiveFindBD(dsk)
    if rbd is None:
      _Fail("Can't find device %s", dsk)

    stats.append(rbd.CombinedSyncStatus())

  return stats


def BlockdevGetmirrorstatusMulti(disks):
  """Get the mirroring status of a list of devices.

  @type disks: list of L{objects.Disk}
  @param disks: the list of disks which we should query
  @rtype: disk
  @return: List of tuples, (bool, status), one for each disk; bool denotes
    success/failure, status is L{objects.BlockDevStatus} on success, string
    otherwise

  """
  result = []
  lvs_cache = None
  is_plain_disk = compat.any([_CheckForPlainDisk(d) for d in disks])
  if is_plain_disk:
    lvs_cache = bdev.LogicalVolume._GetLvGlobalInfo()
  for disk in disks:
    try:
      rbd = _RecursiveFindBD(disk, lvs_cache=lvs_cache)
      if rbd is None:
        result.append((False, "Can't find device %s" % disk))
        continue

      status = rbd.CombinedSyncStatus()
    except errors.BlockDeviceError, err:
      logging.exception("Error while getting disk status")
      result.append((False, str(err)))
    else:
      result.append((True, status))

  assert len(disks) == len(result)

  return result


def _CheckForPlainDisk(disk):
  """Check within a disk and its children if there is a plain disk type.

  @type disk: L{objects.Disk}
  @param disk: the disk we are checking
  @rtype: bool
  @return: whether or not there is a plain disk type

  """
  if disk.dev_type == constants.DT_PLAIN:
    return True
  if disk.children:
    return compat.any([_CheckForPlainDisk(d) for d in disk.children])
  return False


def _RecursiveFindBD(disk, lvs_cache=None):
  """Check if a device is activated.

  If so, return information about the real device.

  @type disk: L{objects.Disk}
  @param disk: the disk object we need to find

  @return: None if the device can't be found,
      otherwise the device instance

  """
  children = []
  if disk.children:
    for chdisk in disk.children:
      children.append(_RecursiveFindBD(chdisk, lvs_cache=lvs_cache))

  return bdev.FindDevice(disk, children, lvs_cache=lvs_cache)


def _OpenRealBD(disk):
  """Opens the underlying block device of a disk.

  @type disk: L{objects.Disk}
  @param disk: the disk object we want to open

  """
  real_disk = _RecursiveFindBD(disk)
  if real_disk is None:
    _Fail("Block device '%s' is not set up", disk)

  real_disk.Open()

  return real_disk


def BlockdevFind(disk):
  """Check if a device is activated.

  If it is, return information about the real device.

  @type disk: L{objects.Disk}
  @param disk: the disk to find
  @rtype: None or objects.BlockDevStatus
  @return: None if the disk cannot be found, otherwise a the current
           information

  """
  try:
    rbd = _RecursiveFindBD(disk)
  except errors.BlockDeviceError, err:
    _Fail("Failed to find device: %s", err, exc=True)

  if rbd is None:
    return None

  return rbd.GetSyncStatus()


def BlockdevGetdimensions(disks):
  """Computes the size of the given disks.

  If a disk is not found, returns None instead.

  @type disks: list of L{objects.Disk}
  @param disks: the list of disk to compute the size for
  @rtype: list
  @return: list with elements None if the disk cannot be found,
      otherwise the pair (size, spindles), where spindles is None if the
      device doesn't support that

  """
  result = []
  for cf in disks:
    try:
      rbd = _RecursiveFindBD(cf)
    except errors.BlockDeviceError:
      result.append(None)
      continue
    if rbd is None:
      result.append(None)
    else:
      result.append(rbd.GetActualDimensions())
  return result


def UploadFile(file_name, data, mode, uid, gid, atime, mtime):
  """Write a file to the filesystem.

  This allows the master to overwrite(!) a file. It will only perform
  the operation if the file belongs to a list of configuration files.

  @type file_name: str
  @param file_name: the target file name
  @type data: str
  @param data: the new contents of the file
  @type mode: int
  @param mode: the mode to give the file (can be None)
  @type uid: string
  @param uid: the owner of the file
  @type gid: string
  @param gid: the group of the file
  @type atime: float
  @param atime: the atime to set on the file (can be None)
  @type mtime: float
  @param mtime: the mtime to set on the file (can be None)
  @rtype: None

  """
  file_name = vcluster.LocalizeVirtualPath(file_name)

  if not os.path.isabs(file_name):
    _Fail("Filename passed to UploadFile is not absolute: '%s'", file_name)

  if file_name not in _ALLOWED_UPLOAD_FILES:
    _Fail("Filename passed to UploadFile not in allowed upload targets: '%s'",
          file_name)

  raw_data = _Decompress(data)

  if not (isinstance(uid, basestring) and isinstance(gid, basestring)):
    _Fail("Invalid username/groupname type")

  getents = runtime.GetEnts()
  uid = getents.LookupUser(uid)
  gid = getents.LookupGroup(gid)

  utils.SafeWriteFile(file_name, None,
                      data=raw_data, mode=mode, uid=uid, gid=gid,
                      atime=atime, mtime=mtime)


def RunOob(oob_program, command, node, timeout):
  """Executes oob_program with given command on given node.

  @param oob_program: The path to the executable oob_program
  @param command: The command to invoke on oob_program
  @param node: The node given as an argument to the program
  @param timeout: Timeout after which we kill the oob program

  @return: stdout
  @raise RPCFail: If execution fails for some reason

  """
  result = utils.RunCmd([oob_program, command, node], timeout=timeout)

  if result.failed:
    _Fail("'%s' failed with reason '%s'; output: %s", result.cmd,
          result.fail_reason, result.output)

  return result.stdout


def _OSOndiskAPIVersion(os_dir):
  """Compute and return the API version of a given OS.

  This function will try to read the API version of the OS residing in
  the 'os_dir' directory.

  @type os_dir: str
  @param os_dir: the directory in which we should look for the OS
  @rtype: tuple
  @return: tuple (status, data) with status denoting the validity and
      data holding either the valid versions or an error message

  """
  api_file = utils.PathJoin(os_dir, constants.OS_API_FILE)

  try:
    st = os.stat(api_file)
  except EnvironmentError, err:
    return False, ("Required file '%s' not found under path %s: %s" %
                   (constants.OS_API_FILE, os_dir, utils.ErrnoOrStr(err)))

  if not stat.S_ISREG(stat.S_IFMT(st.st_mode)):
    return False, ("File '%s' in %s is not a regular file" %
                   (constants.OS_API_FILE, os_dir))

  try:
    api_versions = utils.ReadFile(api_file).splitlines()
  except EnvironmentError, err:
    return False, ("Error while reading the API version file at %s: %s" %
                   (api_file, utils.ErrnoOrStr(err)))

  try:
    api_versions = [int(version.strip()) for version in api_versions]
  except (TypeError, ValueError), err:
    return False, ("API version(s) can't be converted to integer: %s" %
                   str(err))

  return True, api_versions


def DiagnoseOS(top_dirs=None):
  """Compute the validity for all OSes.

  @type top_dirs: list
  @param top_dirs: the list of directories in which to
      search (if not given defaults to
      L{pathutils.OS_SEARCH_PATH})
  @rtype: list of L{objects.OS}
  @return: a list of tuples (name, path, status, diagnose, variants,
      parameters, api_version) for all (potential) OSes under all
      search paths, where:
          - name is the (potential) OS name
          - path is the full path to the OS
          - status True/False is the validity of the OS
          - diagnose is the error message for an invalid OS, otherwise empty
          - variants is a list of supported OS variants, if any
          - parameters is a list of (name, help) parameters, if any
          - api_version is a list of support OS API versions

  """
  if top_dirs is None:
    top_dirs = pathutils.OS_SEARCH_PATH

  result = []
  for dir_name in top_dirs:
    if os.path.isdir(dir_name):
      try:
        f_names = utils.ListVisibleFiles(dir_name)
      except EnvironmentError, err:
        logging.exception("Can't list the OS directory %s: %s", dir_name, err)
        break
      for name in f_names:
        os_path = utils.PathJoin(dir_name, name)
        status, os_inst = _TryOSFromDisk(name, base_dir=dir_name)
        if status:
          diagnose = ""
          variants = os_inst.supported_variants
          parameters = os_inst.supported_parameters
          api_versions = os_inst.api_versions
          trusted = False if os_inst.create_script_untrusted else True
        else:
          diagnose = os_inst
          variants = parameters = api_versions = []
          trusted = True
        result.append((name, os_path, status, diagnose, variants,
                       parameters, api_versions, trusted))

  return result


def _TryOSFromDisk(name, base_dir=None):
  """Create an OS instance from disk.

  This function will return an OS instance if the given name is a
  valid OS name.

  @type base_dir: string
  @keyword base_dir: Base directory containing OS installations.
                     Defaults to a search in all the OS_SEARCH_PATH dirs.
  @rtype: tuple
  @return: success and either the OS instance if we find a valid one,
      or error message

  """
  if base_dir is None:
    os_dir = utils.FindFile(name, pathutils.OS_SEARCH_PATH, os.path.isdir)
  else:
    os_dir = utils.FindFile(name, [base_dir], os.path.isdir)

  if os_dir is None:
    return False, "Directory for OS %s not found in search path" % name

  status, api_versions = _OSOndiskAPIVersion(os_dir)
  if not status:
    # push the error up
    return status, api_versions

  if not constants.OS_API_VERSIONS.intersection(api_versions):
    return False, ("API version mismatch for path '%s': found %s, want %s." %
                   (os_dir, api_versions, constants.OS_API_VERSIONS))

  # OS Files dictionary, we will populate it with the absolute path
  # names; if the value is True, then it is a required file, otherwise
  # an optional one
  os_files = dict.fromkeys(constants.OS_SCRIPTS, True)

  os_files[constants.OS_SCRIPT_CREATE] = False
  os_files[constants.OS_SCRIPT_CREATE_UNTRUSTED] = False

  if max(api_versions) >= constants.OS_API_V15:
    os_files[constants.OS_VARIANTS_FILE] = False

  if max(api_versions) >= constants.OS_API_V20:
    os_files[constants.OS_PARAMETERS_FILE] = True
  else:
    del os_files[constants.OS_SCRIPT_VERIFY]

  for (filename, required) in os_files.items():
    os_files[filename] = utils.PathJoin(os_dir, filename)

    try:
      st = os.stat(os_files[filename])
    except EnvironmentError, err:
      if err.errno == errno.ENOENT and not required:
        del os_files[filename]
        continue
      return False, ("File '%s' under path '%s' is missing (%s)" %
                     (filename, os_dir, utils.ErrnoOrStr(err)))

    if not stat.S_ISREG(stat.S_IFMT(st.st_mode)):
      return False, ("File '%s' under path '%s' is not a regular file" %
                     (filename, os_dir))

    if filename in constants.OS_SCRIPTS:
      if stat.S_IMODE(st.st_mode) & stat.S_IXUSR != stat.S_IXUSR:
        return False, ("File '%s' under path '%s' is not executable" %
                       (filename, os_dir))

  if not constants.OS_SCRIPT_CREATE in os_files and \
        not constants.OS_SCRIPT_CREATE_UNTRUSTED in os_files:
    return False, ("A create script (trusted or untrusted) under path '%s'"
                   " must exist" % os_dir)

  create_script = os_files.get(constants.OS_SCRIPT_CREATE, None)
  create_script_untrusted = os_files.get(constants.OS_SCRIPT_CREATE_UNTRUSTED,
                                         None)

  variants = []
  if constants.OS_VARIANTS_FILE in os_files:
    variants_file = os_files[constants.OS_VARIANTS_FILE]
    try:
      variants = \
        utils.FilterEmptyLinesAndComments(utils.ReadFile(variants_file))
    except EnvironmentError, err:
      # we accept missing files, but not other errors
      if err.errno != errno.ENOENT:
        return False, ("Error while reading the OS variants file at %s: %s" %
                       (variants_file, utils.ErrnoOrStr(err)))

  parameters = []
  if constants.OS_PARAMETERS_FILE in os_files:
    parameters_file = os_files[constants.OS_PARAMETERS_FILE]
    try:
      parameters = utils.ReadFile(parameters_file).splitlines()
    except EnvironmentError, err:
      return False, ("Error while reading the OS parameters file at %s: %s" %
                     (parameters_file, utils.ErrnoOrStr(err)))
    parameters = [v.split(None, 1) for v in parameters]

  os_obj = objects.OS(name=name, path=os_dir,
                      create_script=create_script,
                      create_script_untrusted=create_script_untrusted,
                      export_script=os_files[constants.OS_SCRIPT_EXPORT],
                      import_script=os_files[constants.OS_SCRIPT_IMPORT],
                      rename_script=os_files[constants.OS_SCRIPT_RENAME],
                      verify_script=os_files.get(constants.OS_SCRIPT_VERIFY,
                                                 None),
                      supported_variants=variants,
                      supported_parameters=parameters,
                      api_versions=api_versions)
  return True, os_obj


def OSFromDisk(name, base_dir=None):
  """Create an OS instance from disk.

  This function will return an OS instance if the given name is a
  valid OS name. Otherwise, it will raise an appropriate
  L{RPCFail} exception, detailing why this is not a valid OS.

  This is just a wrapper over L{_TryOSFromDisk}, which doesn't raise
  an exception but returns true/false status data.

  @type base_dir: string
  @keyword base_dir: Base directory containing OS installations.
                     Defaults to a search in all the OS_SEARCH_PATH dirs.
  @rtype: L{objects.OS}
  @return: the OS instance if we find a valid one
  @raise RPCFail: if we don't find a valid OS

  """
  name_only = objects.OS.GetName(name)
  status, payload = _TryOSFromDisk(name_only, base_dir)

  if not status:
    _Fail(payload)

  return payload


def OSCoreEnv(os_name, inst_os, os_params, debug=0):
  """Calculate the basic environment for an os script.

  @type os_name: str
  @param os_name: full operating system name (including variant)
  @type inst_os: L{objects.OS}
  @param inst_os: operating system for which the environment is being built
  @type os_params: dict
  @param os_params: the OS parameters
  @type debug: integer
  @param debug: debug level (0 or 1, for OS Api 10)
  @rtype: dict
  @return: dict of environment variables
  @raise errors.BlockDeviceError: if the block device
      cannot be found

  """
  result = {}
  api_version = \
    max(constants.OS_API_VERSIONS.intersection(inst_os.api_versions))
  result["OS_API_VERSION"] = "%d" % api_version
  result["OS_NAME"] = inst_os.name
  result["DEBUG_LEVEL"] = "%d" % debug

  # OS variants
  if api_version >= constants.OS_API_V15 and inst_os.supported_variants:
    variant = objects.OS.GetVariant(os_name)
    if not variant:
      variant = inst_os.supported_variants[0]
  else:
    variant = ""
  result["OS_VARIANT"] = variant

  # OS params
  for pname, pvalue in os_params.items():
    result["OSP_%s" % pname.upper().replace("-", "_")] = pvalue

  # Set a default path otherwise programs called by OS scripts (or
  # even hooks called from OS scripts) might break, and we don't want
  # to have each script require setting a PATH variable
  result["PATH"] = constants.HOOKS_PATH

  return result


def OSEnvironment(instance, inst_os, debug=0):
  """Calculate the environment for an os script.

  @type instance: L{objects.Instance}
  @param instance: target instance for the os script run
  @type inst_os: L{objects.OS}
  @param inst_os: operating system for which the environment is being built
  @type debug: integer
  @param debug: debug level (0 or 1, for OS Api 10)
  @rtype: dict
  @return: dict of environment variables
  @raise errors.BlockDeviceError: if the block device
      cannot be found

  """
  result = OSCoreEnv(instance.os, inst_os, objects.FillDict(instance.osparams,
                     instance.osparams_private.Unprivate()), debug=debug)

  for attr in ["name", "os", "uuid", "ctime", "mtime", "primary_node"]:
    result["INSTANCE_%s" % attr.upper()] = str(getattr(instance, attr))

  result["HYPERVISOR"] = instance.hypervisor
  result["DISK_COUNT"] = "%d" % len(instance.disks_info)
  result["NIC_COUNT"] = "%d" % len(instance.nics)
  result["INSTANCE_SECONDARY_NODES"] = \
      ("%s" % " ".join(instance.secondary_nodes))

  # Disks
  for idx, disk in enumerate(instance.disks_info):
    real_disk = _OpenRealBD(disk)
    uri = _CalculateDeviceURI(instance, disk, real_disk)
    result["DISK_%d_ACCESS" % idx] = disk.mode
    result["DISK_%d_UUID" % idx] = disk.uuid
    if real_disk.dev_path:
      result["DISK_%d_PATH" % idx] = real_disk.dev_path
    if uri:
      result["DISK_%d_URI" % idx] = uri
    if disk.name:
      result["DISK_%d_NAME" % idx] = disk.name
    if constants.HV_DISK_TYPE in instance.hvparams:
      result["DISK_%d_FRONTEND_TYPE" % idx] = \
        instance.hvparams[constants.HV_DISK_TYPE]
    if disk.dev_type in constants.DTS_BLOCK:
      result["DISK_%d_BACKEND_TYPE" % idx] = "block"
    elif disk.dev_type in constants.DTS_FILEBASED:
      result["DISK_%d_BACKEND_TYPE" % idx] = \
        "file:%s" % disk.logical_id[0]

  # NICs
  for idx, nic in enumerate(instance.nics):
    result["NIC_%d_MAC" % idx] = nic.mac
    result["NIC_%d_UUID" % idx] = nic.uuid
    if nic.name:
      result["NIC_%d_NAME" % idx] = nic.name
    if nic.ip:
      result["NIC_%d_IP" % idx] = nic.ip
    result["NIC_%d_MODE" % idx] = nic.nicparams[constants.NIC_MODE]
    if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
      result["NIC_%d_BRIDGE" % idx] = nic.nicparams[constants.NIC_LINK]
    if nic.nicparams[constants.NIC_LINK]:
      result["NIC_%d_LINK" % idx] = nic.nicparams[constants.NIC_LINK]
    if nic.netinfo:
      nobj = objects.Network.FromDict(nic.netinfo)
      result.update(nobj.HooksDict("NIC_%d_" % idx))
    if constants.HV_NIC_TYPE in instance.hvparams:
      result["NIC_%d_FRONTEND_TYPE" % idx] = \
        instance.hvparams[constants.HV_NIC_TYPE]

  # HV/BE params
  for source, kind in [(instance.beparams, "BE"), (instance.hvparams, "HV")]:
    for key, value in source.items():
      result["INSTANCE_%s_%s" % (kind, key)] = str(value)

  return result


def DiagnoseExtStorage(top_dirs=None):
  """Compute the validity for all ExtStorage Providers.

  @type top_dirs: list
  @param top_dirs: the list of directories in which to
      search (if not given defaults to
      L{pathutils.ES_SEARCH_PATH})
  @rtype: list of L{objects.ExtStorage}
  @return: a list of tuples (name, path, status, diagnose, parameters)
      for all (potential) ExtStorage Providers under all
      search paths, where:
          - name is the (potential) ExtStorage Provider
          - path is the full path to the ExtStorage Provider
          - status True/False is the validity of the ExtStorage Provider
          - diagnose is the error message for an invalid ExtStorage Provider,
            otherwise empty
          - parameters is a list of (name, help) parameters, if any

  """
  if top_dirs is None:
    top_dirs = pathutils.ES_SEARCH_PATH

  result = []
  for dir_name in top_dirs:
    if os.path.isdir(dir_name):
      try:
        f_names = utils.ListVisibleFiles(dir_name)
      except EnvironmentError, err:
        logging.exception("Can't list the ExtStorage directory %s: %s",
                          dir_name, err)
        break
      for name in f_names:
        es_path = utils.PathJoin(dir_name, name)
        status, es_inst = extstorage.ExtStorageFromDisk(name, base_dir=dir_name)
        if status:
          diagnose = ""
          parameters = es_inst.supported_parameters
        else:
          diagnose = es_inst
          parameters = []
        result.append((name, es_path, status, diagnose, parameters))

  return result


def BlockdevGrow(disk, amount, dryrun, backingstore, excl_stor):
  """Grow a stack of block devices.

  This function is called recursively, with the childrens being the
  first ones to resize.

  @type disk: L{objects.Disk}
  @param disk: the disk to be grown
  @type amount: integer
  @param amount: the amount (in mebibytes) to grow with
  @type dryrun: boolean
  @param dryrun: whether to execute the operation in simulation mode
      only, without actually increasing the size
  @param backingstore: whether to execute the operation on backing storage
      only, or on "logical" storage only; e.g. DRBD is logical storage,
      whereas LVM, file, RBD are backing storage
  @rtype: (status, result)
  @type excl_stor: boolean
  @param excl_stor: Whether exclusive_storage is active
  @return: a tuple with the status of the operation (True/False), and
      the errors message if status is False

  """
  r_dev = _RecursiveFindBD(disk)
  if r_dev is None:
    _Fail("Cannot find block device %s", disk)

  try:
    r_dev.Grow(amount, dryrun, backingstore, excl_stor)
  except errors.BlockDeviceError, err:
    _Fail("Failed to grow block device: %s", err, exc=True)


def BlockdevSnapshot(disk, snap_name, snap_size):
  """Create a snapshot copy of a block device.

  This function is called recursively, and the snapshot is actually created
  just for the leaf lvm backend device.

  @type disk: L{objects.Disk}
  @param disk: the disk to be snapshotted
  @type snap_name: string
  @param snap_name: the name of the snapshot
  @type snap_size: int
  @param snap_size: the size of the snapshot
  @rtype: string
  @return: snapshot disk ID as (vg, lv)

  """
  def _DiskSnapshot(disk, snap_name=None, snap_size=None):
    r_dev = _RecursiveFindBD(disk)
    if r_dev is not None:
      return r_dev.Snapshot(snap_name=snap_name, snap_size=snap_size)
    else:
      _Fail("Cannot find block device %s", disk)

  if disk.SupportsSnapshots():
    if disk.dev_type == constants.DT_DRBD8:
      if not disk.children:
        _Fail("DRBD device '%s' without backing storage cannot be snapshotted",
              disk.unique_id)
      return BlockdevSnapshot(disk.children[0], snap_name, snap_size)
    else:
      return _DiskSnapshot(disk, snap_name, snap_size)
  else:
    _Fail("Cannot snapshot block device '%s' of type '%s'",
          disk.logical_id, disk.dev_type)


def BlockdevSetInfo(disk, info):
  """Sets 'metadata' information on block devices.

  This function sets 'info' metadata on block devices. Initial
  information is set at device creation; this function should be used
  for example after renames.

  @type disk: L{objects.Disk}
  @param disk: the disk to be grown
  @type info: string
  @param info: new 'info' metadata
  @rtype: (status, result)
  @return: a tuple with the status of the operation (True/False), and
      the errors message if status is False

  """
  r_dev = _RecursiveFindBD(disk)
  if r_dev is None:
    _Fail("Cannot find block device %s", disk)

  try:
    r_dev.SetInfo(info)
  except errors.BlockDeviceError, err:
    _Fail("Failed to set information on block device: %s", err, exc=True)


def FinalizeExport(instance, snap_disks):
  """Write out the export configuration information.

  @type instance: L{objects.Instance}
  @param instance: the instance which we export, used for
      saving configuration
  @type snap_disks: list of L{objects.Disk}
  @param snap_disks: list of snapshot block devices, which
      will be used to get the actual name of the dump file

  @rtype: None

  """
  destdir = utils.PathJoin(pathutils.EXPORT_DIR, instance.name + ".new")
  finaldestdir = utils.PathJoin(pathutils.EXPORT_DIR, instance.name)
  disk_template = utils.GetDiskTemplate(snap_disks)

  config = objects.SerializableConfigParser()

  config.add_section(constants.INISECT_EXP)
  config.set(constants.INISECT_EXP, "version", str(constants.EXPORT_VERSION))
  config.set(constants.INISECT_EXP, "timestamp", "%d" % int(time.time()))
  config.set(constants.INISECT_EXP, "source", instance.primary_node)
  config.set(constants.INISECT_EXP, "os", instance.os)
  config.set(constants.INISECT_EXP, "compression", "none")

  config.add_section(constants.INISECT_INS)
  config.set(constants.INISECT_INS, "name", instance.name)
  config.set(constants.INISECT_INS, "maxmem", "%d" %
             instance.beparams[constants.BE_MAXMEM])
  config.set(constants.INISECT_INS, "minmem", "%d" %
             instance.beparams[constants.BE_MINMEM])
  # "memory" is deprecated, but useful for exporting to old ganeti versions
  config.set(constants.INISECT_INS, "memory", "%d" %
             instance.beparams[constants.BE_MAXMEM])
  config.set(constants.INISECT_INS, "vcpus", "%d" %
             instance.beparams[constants.BE_VCPUS])
  config.set(constants.INISECT_INS, "disk_template", disk_template)
  config.set(constants.INISECT_INS, "hypervisor", instance.hypervisor)
  config.set(constants.INISECT_INS, "tags", " ".join(instance.GetTags()))

  nic_total = 0
  for nic_count, nic in enumerate(instance.nics):
    nic_total += 1
    config.set(constants.INISECT_INS, "nic%d_mac" %
               nic_count, "%s" % nic.mac)
    config.set(constants.INISECT_INS, "nic%d_ip" % nic_count, "%s" % nic.ip)
    config.set(constants.INISECT_INS, "nic%d_network" % nic_count,
               "%s" % nic.network)
    config.set(constants.INISECT_INS, "nic%d_name" % nic_count,
               "%s" % nic.name)
    for param in constants.NICS_PARAMETER_TYPES:
      config.set(constants.INISECT_INS, "nic%d_%s" % (nic_count, param),
                 "%s" % nic.nicparams.get(param, None))
  # TODO: redundant: on load can read nics until it doesn't exist
  config.set(constants.INISECT_INS, "nic_count", "%d" % nic_total)

  disk_total = 0
  for disk_count, disk in enumerate(snap_disks):
    if disk:
      disk_total += 1
      config.set(constants.INISECT_INS, "disk%d_ivname" % disk_count,
                 ("%s" % disk.iv_name))
      config.set(constants.INISECT_INS, "disk%d_dump" % disk_count,
                 ("%s" % disk.uuid))
      config.set(constants.INISECT_INS, "disk%d_size" % disk_count,
                 ("%d" % disk.size))
      config.set(constants.INISECT_INS, "disk%d_name" % disk_count,
                 "%s" % disk.name)

  config.set(constants.INISECT_INS, "disk_count", "%d" % disk_total)

  # New-style hypervisor/backend parameters

  config.add_section(constants.INISECT_HYP)
  for name, value in instance.hvparams.items():
    if name not in constants.HVC_GLOBALS:
      config.set(constants.INISECT_HYP, name, str(value))

  config.add_section(constants.INISECT_BEP)
  for name, value in instance.beparams.items():
    config.set(constants.INISECT_BEP, name, str(value))

  config.add_section(constants.INISECT_OSP)
  for name, value in instance.osparams.items():
    config.set(constants.INISECT_OSP, name, str(value))

  config.add_section(constants.INISECT_OSP_PRIVATE)
  for name, value in instance.osparams_private.items():
    config.set(constants.INISECT_OSP_PRIVATE, name, str(value.Get()))

  utils.WriteFile(utils.PathJoin(destdir, constants.EXPORT_CONF_FILE),
                  data=config.Dumps())
  shutil.rmtree(finaldestdir, ignore_errors=True)
  shutil.move(destdir, finaldestdir)


def ExportInfo(dest):
  """Get export configuration information.

  @type dest: str
  @param dest: directory containing the export

  @rtype: L{objects.SerializableConfigParser}
  @return: a serializable config file containing the
      export info

  """
  cff = utils.PathJoin(dest, constants.EXPORT_CONF_FILE)

  config = objects.SerializableConfigParser()
  config.read(cff)

  if (not config.has_section(constants.INISECT_EXP) or
      not config.has_section(constants.INISECT_INS)):
    _Fail("Export info file doesn't have the required fields")

  return config.Dumps()


def ListExports():
  """Return a list of exports currently available on this machine.

  @rtype: list
  @return: list of the exports

  """
  if os.path.isdir(pathutils.EXPORT_DIR):
    return sorted(utils.ListVisibleFiles(pathutils.EXPORT_DIR))
  else:
    _Fail("No exports directory")


def RemoveExport(export):
  """Remove an existing export from the node.

  @type export: str
  @param export: the name of the export to remove
  @rtype: None

  """
  target = utils.PathJoin(pathutils.EXPORT_DIR, export)

  try:
    shutil.rmtree(target)
  except EnvironmentError, err:
    _Fail("Error while removing the export: %s", err, exc=True)


def BlockdevRename(devlist):
  """Rename a list of block devices.

  @type devlist: list of tuples
  @param devlist: list of tuples of the form  (disk, new_unique_id); disk is
      an L{objects.Disk} object describing the current disk, and new
      unique_id is the name we rename it to
  @rtype: boolean
  @return: True if all renames succeeded, False otherwise

  """
  msgs = []
  result = True
  for disk, unique_id in devlist:
    dev = _RecursiveFindBD(disk)
    if dev is None:
      msgs.append("Can't find device %s in rename" % str(disk))
      result = False
      continue
    try:
      old_rpath = dev.dev_path
      dev.Rename(unique_id)
      new_rpath = dev.dev_path
      if old_rpath != new_rpath:
        DevCacheManager.RemoveCache(old_rpath)
        # FIXME: we should add the new cache information here, like:
        # DevCacheManager.UpdateCache(new_rpath, owner, ...)
        # but we don't have the owner here - maybe parse from existing
        # cache? for now, we only lose lvm data when we rename, which
        # is less critical than DRBD or MD
    except errors.BlockDeviceError, err:
      msgs.append("Can't rename device '%s' to '%s': %s" %
                  (dev, unique_id, err))
      logging.exception("Can't rename device '%s' to '%s'", dev, unique_id)
      result = False
  if not result:
    _Fail("; ".join(msgs))


def _TransformFileStorageDir(fs_dir):
  """Checks whether given file_storage_dir is valid.

  Checks wheter the given fs_dir is within the cluster-wide default
  file_storage_dir or the shared_file_storage_dir, which are stored in
  SimpleStore. Only paths under those directories are allowed.

  @type fs_dir: str
  @param fs_dir: the path to check

  @return: the normalized path if valid, None otherwise

  """
  filestorage.CheckFileStoragePath(fs_dir)

  return os.path.normpath(fs_dir)


def CreateFileStorageDir(file_storage_dir):
  """Create file storage directory.

  @type file_storage_dir: str
  @param file_storage_dir: directory to create

  @rtype: tuple
  @return: tuple with first element a boolean indicating wheter dir
      creation was successful or not

  """
  file_storage_dir = _TransformFileStorageDir(file_storage_dir)
  if os.path.exists(file_storage_dir):
    if not os.path.isdir(file_storage_dir):
      _Fail("Specified storage dir '%s' is not a directory",
            file_storage_dir)
  else:
    try:
      os.makedirs(file_storage_dir, 0750)
    except OSError, err:
      _Fail("Cannot create file storage directory '%s': %s",
            file_storage_dir, err, exc=True)


def RemoveFileStorageDir(file_storage_dir):
  """Remove file storage directory.

  Remove it only if it's empty. If not log an error and return.

  @type file_storage_dir: str
  @param file_storage_dir: the directory we should cleanup
  @rtype: tuple (success,)
  @return: tuple of one element, C{success}, denoting
      whether the operation was successful

  """
  file_storage_dir = _TransformFileStorageDir(file_storage_dir)
  if os.path.exists(file_storage_dir):
    if not os.path.isdir(file_storage_dir):
      _Fail("Specified Storage directory '%s' is not a directory",
            file_storage_dir)
    # deletes dir only if empty, otherwise we want to fail the rpc call
    try:
      os.rmdir(file_storage_dir)
    except OSError, err:
      _Fail("Cannot remove file storage directory '%s': %s",
            file_storage_dir, err)


def RenameFileStorageDir(old_file_storage_dir, new_file_storage_dir):
  """Rename the file storage directory.

  @type old_file_storage_dir: str
  @param old_file_storage_dir: the current path
  @type new_file_storage_dir: str
  @param new_file_storage_dir: the name we should rename to
  @rtype: tuple (success,)
  @return: tuple of one element, C{success}, denoting
      whether the operation was successful

  """
  old_file_storage_dir = _TransformFileStorageDir(old_file_storage_dir)
  new_file_storage_dir = _TransformFileStorageDir(new_file_storage_dir)
  if not os.path.exists(new_file_storage_dir):
    if os.path.isdir(old_file_storage_dir):
      try:
        os.rename(old_file_storage_dir, new_file_storage_dir)
      except OSError, err:
        _Fail("Cannot rename '%s' to '%s': %s",
              old_file_storage_dir, new_file_storage_dir, err)
    else:
      _Fail("Specified storage dir '%s' is not a directory",
            old_file_storage_dir)
  else:
    if os.path.exists(old_file_storage_dir):
      _Fail("Cannot rename '%s' to '%s': both locations exist",
            old_file_storage_dir, new_file_storage_dir)


def _EnsureJobQueueFile(file_name):
  """Checks whether the given filename is in the queue directory.

  @type file_name: str
  @param file_name: the file name we should check
  @rtype: None
  @raises RPCFail: if the file is not valid

  """
  if not utils.IsBelowDir(pathutils.QUEUE_DIR, file_name):
    _Fail("Passed job queue file '%s' does not belong to"
          " the queue directory '%s'", file_name, pathutils.QUEUE_DIR)


def JobQueueUpdate(file_name, content):
  """Updates a file in the queue directory.

  This is just a wrapper over L{utils.io.WriteFile}, with proper
  checking.

  @type file_name: str
  @param file_name: the job file name
  @type content: str
  @param content: the new job contents
  @rtype: boolean
  @return: the success of the operation

  """
  file_name = vcluster.LocalizeVirtualPath(file_name)

  _EnsureJobQueueFile(file_name)
  getents = runtime.GetEnts()

  # Write and replace the file atomically
  utils.WriteFile(file_name, data=_Decompress(content), uid=getents.masterd_uid,
                  gid=getents.daemons_gid, mode=constants.JOB_QUEUE_FILES_PERMS)


def JobQueueRename(old, new):
  """Renames a job queue file.

  This is just a wrapper over os.rename with proper checking.

  @type old: str
  @param old: the old (actual) file name
  @type new: str
  @param new: the desired file name
  @rtype: tuple
  @return: the success of the operation and payload

  """
  old = vcluster.LocalizeVirtualPath(old)
  new = vcluster.LocalizeVirtualPath(new)

  _EnsureJobQueueFile(old)
  _EnsureJobQueueFile(new)

  getents = runtime.GetEnts()

  utils.RenameFile(old, new, mkdir=True, mkdir_mode=0750,
                   dir_uid=getents.masterd_uid, dir_gid=getents.daemons_gid)


def BlockdevClose(instance_name, disks):
  """Closes the given block devices.

  This means they will be switched to secondary mode (in case of
  DRBD).

  @param instance_name: if the argument is not empty, the symlinks
      of this instance will be removed
  @type disks: list of L{objects.Disk}
  @param disks: the list of disks to be closed
  @rtype: tuple (success, message)
  @return: a tuple of success and message, where success
      indicates the succes of the operation, and message
      which will contain the error details in case we
      failed

  """
  bdevs = []
  for cf in disks:
    rd = _RecursiveFindBD(cf)
    if rd is None:
      _Fail("Can't find device %s", cf)
    bdevs.append(rd)

  msg = []
  for rd in bdevs:
    try:
      rd.Close()
    except errors.BlockDeviceError, err:
      msg.append(str(err))
  if msg:
    _Fail("Can't close devices: %s", ",".join(msg))
  else:
    if instance_name:
      _RemoveBlockDevLinks(instance_name, disks)


def BlockdevOpen(instance_name, disks, exclusive):
  """Opens the given block devices.

  """
  bdevs = []
  for cf in disks:
    rd = _RecursiveFindBD(cf)
    if rd is None:
      _Fail("Can't find device %s", cf)
    bdevs.append(rd)

  msg = []
  for idx, rd in enumerate(bdevs):
    try:
      rd.Open(exclusive=exclusive)
      _SymlinkBlockDev(instance_name, rd.dev_path, idx)
    except errors.BlockDeviceError, err:
      msg.append(str(err))

  if msg:
    _Fail("Can't open devices: %s", ",".join(msg))


def ValidateHVParams(hvname, hvparams):
  """Validates the given hypervisor parameters.

  @type hvname: string
  @param hvname: the hypervisor name
  @type hvparams: dict
  @param hvparams: the hypervisor parameters to be validated
  @rtype: None

  """
  try:
    hv_type = hypervisor.GetHypervisor(hvname)
    hv_type.ValidateParameters(hvparams)
  except errors.HypervisorError, err:
    _Fail(str(err), log=False)


def _CheckOSPList(os_obj, parameters):
  """Check whether a list of parameters is supported by the OS.

  @type os_obj: L{objects.OS}
  @param os_obj: OS object to check
  @type parameters: list
  @param parameters: the list of parameters to check

  """
  supported = [v[0] for v in os_obj.supported_parameters]
  delta = frozenset(parameters).difference(supported)
  if delta:
    _Fail("The following parameters are not supported"
          " by the OS %s: %s" % (os_obj.name, utils.CommaJoin(delta)))


def _CheckOSVariant(os_obj, name):
  """Check whether an OS name conforms to the os variants specification.

  @type os_obj: L{objects.OS}
  @param os_obj: OS object to check

  @type name: string
  @param name: OS name passed by the user, to check for validity

  @rtype: NoneType
  @return: None
  @raise RPCFail: if OS variant is not valid

  """
  variant = objects.OS.GetVariant(name)

  if not os_obj.supported_variants:
    if variant:
      _Fail("OS '%s' does not support variants ('%s' passed)" %
            (os_obj.name, variant))
    else:
      return

  if not variant:
    _Fail("OS name '%s' must include a variant" % name)

  if variant not in os_obj.supported_variants:
    _Fail("OS '%s' does not support variant '%s'" % (os_obj.name, variant))


def ValidateOS(required, osname, checks, osparams, force_variant):
  """Validate the given OS parameters.

  @type required: boolean
  @param required: whether absence of the OS should translate into
      failure or not
  @type osname: string
  @param osname: the OS to be validated
  @type checks: list
  @param checks: list of the checks to run (currently only 'parameters')
  @type osparams: dict
  @param osparams: dictionary with OS parameters, some of which may be
                   private.
  @rtype: boolean
  @return: True if the validation passed, or False if the OS was not
      found and L{required} was false

  """
  if not constants.OS_VALIDATE_CALLS.issuperset(checks):
    _Fail("Unknown checks required for OS %s: %s", osname,
          set(checks).difference(constants.OS_VALIDATE_CALLS))

  name_only = objects.OS.GetName(osname)
  status, tbv = _TryOSFromDisk(name_only, None)

  if not status:
    if required:
      _Fail(tbv)
    else:
      return False

  if not force_variant:
    _CheckOSVariant(tbv, osname)

  if max(tbv.api_versions) < constants.OS_API_V20:
    return True

  if constants.OS_VALIDATE_PARAMETERS in checks:
    _CheckOSPList(tbv, osparams.keys())

  validate_env = OSCoreEnv(osname, tbv, osparams)
  result = utils.RunCmd([tbv.verify_script] + checks, env=validate_env,
                        cwd=tbv.path, reset_env=True)
  if result.failed:
    logging.error("os validate command '%s' returned error: %s output: %s",
                  result.cmd, result.fail_reason, result.output)
    _Fail("OS validation script failed (%s), output: %s",
          result.fail_reason, result.output, log=False)

  return True


def ExportOS(instance, override_env):
  """Creates a GZIPed tarball with an OS definition and environment.

  The archive contains a file with the environment variables needed by
  the OS scripts.

  @type instance: L{objects.Instance}
  @param instance: instance for which the OS definition is exported

  @type override_env: dict of string to string
  @param override_env: if supplied, it overrides the environment on a
                       key-by-key basis that is part of the archive

  @rtype: string
  @return: filepath of the archive

  """
  assert instance
  assert instance.os

  temp_dir = tempfile.mkdtemp()
  inst_os = OSFromDisk(instance.os)

  result = utils.RunCmd(["ln", "-s", inst_os.path,
                         utils.PathJoin(temp_dir, "os")])
  if result.failed:
    _Fail("Failed to copy OS package '%s' to '%s': %s, output '%s'",
          inst_os, temp_dir, result.fail_reason, result.output)

  env = OSEnvironment(instance, inst_os)
  env.update(override_env)

  with open(utils.PathJoin(temp_dir, "environment"), "w") as f:
    for var in env:
      f.write(var + "=" + env[var] + "\n")

  (fd, os_package) = tempfile.mkstemp(suffix=".tgz")
  os.close(fd)

  result = utils.RunCmd(["tar", "--dereference", "-czv",
                         "-f", os_package,
                         "-C", temp_dir,
                         "."])
  if result.failed:
    _Fail("Failed to create OS archive '%s': %s, output '%s'",
          os_package, result.fail_reason, result.output)

  result = utils.RunCmd(["rm", "-rf", temp_dir])
  if result.failed:
    _Fail("Failed to remove copy of OS package '%s' in '%s': %s, output '%s'",
          inst_os, temp_dir, result.fail_reason, result.output)

  return os_package


def DemoteFromMC():
  """Demotes the current node from master candidate role.

  """
  # try to ensure we're not the master by mistake
  master, myself = ssconf.GetMasterAndMyself()
  if master == myself:
    _Fail("ssconf status shows I'm the master node, will not demote")

  result = utils.RunCmd([pathutils.DAEMON_UTIL, "check", constants.MASTERD])
  if not result.failed:
    _Fail("The master daemon is running, will not demote")

  try:
    if os.path.isfile(pathutils.CLUSTER_CONF_FILE):
      utils.CreateBackup(pathutils.CLUSTER_CONF_FILE)
  except EnvironmentError, err:
    if err.errno != errno.ENOENT:
      _Fail("Error while backing up cluster file: %s", err, exc=True)

  utils.RemoveFile(pathutils.CLUSTER_CONF_FILE)


def _GetX509Filenames(cryptodir, name):
  """Returns the full paths for the private key and certificate.

  """
  return (utils.PathJoin(cryptodir, name),
          utils.PathJoin(cryptodir, name, _X509_KEY_FILE),
          utils.PathJoin(cryptodir, name, _X509_CERT_FILE))


def CreateX509Certificate(validity, cryptodir=pathutils.CRYPTO_KEYS_DIR):
  """Creates a new X509 certificate for SSL/TLS.

  @type validity: int
  @param validity: Validity in seconds
  @rtype: tuple; (string, string)
  @return: Certificate name and public part

  """
  serial_no = int(time.time())
  (key_pem, cert_pem) = \
    utils.GenerateSelfSignedX509Cert(netutils.Hostname.GetSysName(),
                                     min(validity, _MAX_SSL_CERT_VALIDITY),
                                     serial_no)

  cert_dir = tempfile.mkdtemp(dir=cryptodir,
                              prefix="x509-%s-" % utils.TimestampForFilename())
  try:
    name = os.path.basename(cert_dir)
    assert len(name) > 5

    (_, key_file, cert_file) = _GetX509Filenames(cryptodir, name)

    utils.WriteFile(key_file, mode=0400, data=key_pem)
    utils.WriteFile(cert_file, mode=0400, data=cert_pem)

    # Never return private key as it shouldn't leave the node
    return (name, cert_pem)
  except Exception:
    shutil.rmtree(cert_dir, ignore_errors=True)
    raise


def RemoveX509Certificate(name, cryptodir=pathutils.CRYPTO_KEYS_DIR):
  """Removes a X509 certificate.

  @type name: string
  @param name: Certificate name

  """
  (cert_dir, key_file, cert_file) = _GetX509Filenames(cryptodir, name)

  utils.RemoveFile(key_file)
  utils.RemoveFile(cert_file)

  try:
    os.rmdir(cert_dir)
  except EnvironmentError, err:
    _Fail("Cannot remove certificate directory '%s': %s",
          cert_dir, err)


def _GetImportExportIoCommand(instance, mode, ieio, ieargs):
  """Returns the command for the requested input/output.

  @type instance: L{objects.Instance}
  @param instance: The instance object
  @param mode: Import/export mode
  @param ieio: Input/output type
  @param ieargs: Input/output arguments

  """
  assert mode in (constants.IEM_IMPORT, constants.IEM_EXPORT)

  env = None
  prefix = None
  suffix = None
  exp_size = None

  if ieio == constants.IEIO_FILE:
    (filename, ) = ieargs

    if not utils.IsNormAbsPath(filename):
      _Fail("Path '%s' is not normalized or absolute", filename)

    real_filename = os.path.realpath(filename)
    directory = os.path.dirname(real_filename)

    if not utils.IsBelowDir(pathutils.EXPORT_DIR, real_filename):
      _Fail("File '%s' is not under exports directory '%s': %s",
            filename, pathutils.EXPORT_DIR, real_filename)

    # Create directory
    utils.Makedirs(directory, mode=0750)

    quoted_filename = utils.ShellQuote(filename)

    if mode == constants.IEM_IMPORT:
      suffix = "> %s" % quoted_filename
    elif mode == constants.IEM_EXPORT:
      suffix = "< %s" % quoted_filename

      # Retrieve file size
      try:
        st = os.stat(filename)
      except EnvironmentError, err:
        logging.error("Can't stat(2) %s: %s", filename, err)
      else:
        exp_size = utils.BytesToMebibyte(st.st_size)

  elif ieio == constants.IEIO_RAW_DISK:
    (disk, ) = ieargs
    real_disk = _OpenRealBD(disk)

    if mode == constants.IEM_IMPORT:
      suffix = "| %s" % utils.ShellQuoteArgs(real_disk.Import())

    elif mode == constants.IEM_EXPORT:
      prefix = "%s |" % utils.ShellQuoteArgs(real_disk.Export())
      exp_size = disk.size

  elif ieio == constants.IEIO_SCRIPT:
    (disk, disk_index, ) = ieargs

    assert isinstance(disk_index, (int, long))

    inst_os = OSFromDisk(instance.os)
    env = OSEnvironment(instance, inst_os)

    if mode == constants.IEM_IMPORT:
      disk_path_var = "DISK_%d_PATH" % disk_index
      if disk_path_var in env:
        env["IMPORT_DEVICE"] = env[disk_path_var]
        env["IMPORT_DISK_PATH"] = env[disk_path_var]

      disk_uri_var = "DISK_%d_URI" % disk_index
      if disk_uri_var in env:
        env["IMPORT_DISK_URI"] = env[disk_uri_var]

      env["IMPORT_INDEX"] = str(disk_index)
      script = inst_os.import_script

    elif mode == constants.IEM_EXPORT:
      disk_path_var = "DISK_%d_PATH" % disk_index
      if disk_path_var in env:
        env["EXPORT_DEVICE"] = env[disk_path_var]
        env["EXPORT_DISK_PATH"] = env[disk_path_var]

      disk_uri_var = "DISK_%d_URI" % disk_index
      if disk_uri_var in env:
        env["EXPORT_DISK_URI"] = env[disk_uri_var]

      env["EXPORT_INDEX"] = str(disk_index)
      script = inst_os.export_script

    # TODO: Pass special environment only to script
    script_cmd = utils.BuildShellCmd("( cd %s && %s; )", inst_os.path, script)

    if mode == constants.IEM_IMPORT:
      suffix = "| %s" % script_cmd

    elif mode == constants.IEM_EXPORT:
      prefix = "%s |" % script_cmd

    # Let script predict size
    exp_size = constants.IE_CUSTOM_SIZE

  else:
    _Fail("Invalid %s I/O mode %r", mode, ieio)

  return (env, prefix, suffix, exp_size)


def _CreateImportExportStatusDir(prefix):
  """Creates status directory for import/export.

  """
  return tempfile.mkdtemp(dir=pathutils.IMPORT_EXPORT_DIR,
                          prefix=("%s-%s-" %
                                  (prefix, utils.TimestampForFilename())))


def StartImportExportDaemon(mode, opts, host, port, instance, component,
                            ieio, ieioargs):
  """Starts an import or export daemon.

  @param mode: Import/output mode
  @type opts: L{objects.ImportExportOptions}
  @param opts: Daemon options
  @type host: string
  @param host: Remote host for export (None for import)
  @type port: int
  @param port: Remote port for export (None for import)
  @type instance: L{objects.Instance}
  @param instance: Instance object
  @type component: string
  @param component: which part of the instance is transferred now,
      e.g. 'disk/0'
  @param ieio: Input/output type
  @param ieioargs: Input/output arguments

  """

  # Use Import/Export over socat.
  #
  #   Export() gives a command that produces a flat stream.
  #   Import() gives a command that reads a flat stream to a disk template.
  if mode == constants.IEM_IMPORT:
    prefix = "import"

    if not (host is None and port is None):
      _Fail("Can not specify host or port on import")

  elif mode == constants.IEM_EXPORT:
    prefix = "export"

    if host is None or port is None:
      _Fail("Host and port must be specified for an export")

  else:
    _Fail("Invalid mode %r", mode)

  if (opts.key_name is None) ^ (opts.ca_pem is None):
    _Fail("Cluster certificate can only be used for both key and CA")

  (cmd_env, cmd_prefix, cmd_suffix, exp_size) = \
    _GetImportExportIoCommand(instance, mode, ieio, ieioargs)

  if opts.key_name is None:
    # Use server.pem
    key_path = pathutils.NODED_CERT_FILE
    cert_path = pathutils.NODED_CERT_FILE
    assert opts.ca_pem is None
  else:
    (_, key_path, cert_path) = _GetX509Filenames(pathutils.CRYPTO_KEYS_DIR,
                                                 opts.key_name)
    assert opts.ca_pem is not None

  for i in [key_path, cert_path]:
    if not os.path.exists(i):
      _Fail("File '%s' does not exist" % i)

  status_dir = _CreateImportExportStatusDir("%s-%s" % (prefix, component))
  try:
    status_file = utils.PathJoin(status_dir, _IES_STATUS_FILE)
    pid_file = utils.PathJoin(status_dir, _IES_PID_FILE)
    ca_file = utils.PathJoin(status_dir, _IES_CA_FILE)

    if opts.ca_pem is None:
      # Use server.pem
      ca = utils.ReadFile(pathutils.NODED_CERT_FILE)
    else:
      ca = opts.ca_pem

    # Write CA file
    utils.WriteFile(ca_file, data=ca, mode=0400)

    cmd = [
      pathutils.IMPORT_EXPORT_DAEMON,
      status_file, mode,
      "--key=%s" % key_path,
      "--cert=%s" % cert_path,
      "--ca=%s" % ca_file,
      ]

    if host:
      cmd.append("--host=%s" % host)

    if port:
      cmd.append("--port=%s" % port)

    if opts.ipv6:
      cmd.append("--ipv6")
    else:
      cmd.append("--ipv4")

    if opts.compress:
      cmd.append("--compress=%s" % opts.compress)

    if opts.magic:
      cmd.append("--magic=%s" % opts.magic)

    if exp_size is not None:
      cmd.append("--expected-size=%s" % exp_size)

    if cmd_prefix:
      cmd.append("--cmd-prefix=%s" % cmd_prefix)

    if cmd_suffix:
      cmd.append("--cmd-suffix=%s" % cmd_suffix)

    if mode == constants.IEM_EXPORT:
      # Retry connection a few times when connecting to remote peer
      cmd.append("--connect-retries=%s" % constants.RIE_CONNECT_RETRIES)
      cmd.append("--connect-timeout=%s" % constants.RIE_CONNECT_ATTEMPT_TIMEOUT)
    elif opts.connect_timeout is not None:
      assert mode == constants.IEM_IMPORT
      # Overall timeout for establishing connection while listening
      cmd.append("--connect-timeout=%s" % opts.connect_timeout)

    logfile = _InstanceLogName(prefix, instance.os, instance.name, component)

    # TODO: Once _InstanceLogName uses tempfile.mkstemp, StartDaemon has
    # support for receiving a file descriptor for output
    utils.StartDaemon(cmd, env=cmd_env, pidfile=pid_file,
                      output=logfile)

    # The import/export name is simply the status directory name
    return os.path.basename(status_dir)

  except Exception:
    shutil.rmtree(status_dir, ignore_errors=True)
    raise


def GetImportExportStatus(names):
  """Returns import/export daemon status.

  @type names: sequence
  @param names: List of names
  @rtype: List of dicts
  @return: Returns a list of the state of each named import/export or None if a
           status couldn't be read

  """
  result = []

  for name in names:
    status_file = utils.PathJoin(pathutils.IMPORT_EXPORT_DIR, name,
                                 _IES_STATUS_FILE)

    try:
      data = utils.ReadFile(status_file)
    except EnvironmentError, err:
      if err.errno != errno.ENOENT:
        raise
      data = None

    if not data:
      result.append(None)
      continue

    result.append(serializer.LoadJson(data))

  return result


def AbortImportExport(name):
  """Sends SIGTERM to a running import/export daemon.

  """
  logging.info("Abort import/export %s", name)

  status_dir = utils.PathJoin(pathutils.IMPORT_EXPORT_DIR, name)
  pid = utils.ReadLockedPidFile(utils.PathJoin(status_dir, _IES_PID_FILE))

  if pid:
    logging.info("Import/export %s is running with PID %s, sending SIGTERM",
                 name, pid)
    utils.IgnoreProcessNotFound(os.kill, pid, signal.SIGTERM)


def CleanupImportExport(name):
  """Cleanup after an import or export.

  If the import/export daemon is still running it's killed. Afterwards the
  whole status directory is removed.

  """
  logging.info("Finalizing import/export %s", name)

  status_dir = utils.PathJoin(pathutils.IMPORT_EXPORT_DIR, name)

  pid = utils.ReadLockedPidFile(utils.PathJoin(status_dir, _IES_PID_FILE))

  if pid:
    logging.info("Import/export %s is still running with PID %s",
                 name, pid)
    utils.KillProcess(pid, waitpid=False)

  shutil.rmtree(status_dir, ignore_errors=True)


def _FindDisks(disks):
  """Finds attached L{BlockDev}s for the given disks.

  @type disks: list of L{objects.Disk}
  @param disks: the disk objects we need to find

  @return: list of L{BlockDev} objects or C{None} if a given disk
           was not found or was no attached.

  """
  bdevs = []

  for disk in disks:
    rd = _RecursiveFindBD(disk)
    if rd is None:
      _Fail("Can't find device %s", disk)
    bdevs.append(rd)
  return bdevs


def DrbdDisconnectNet(disks):
  """Disconnects the network on a list of drbd devices.

  """
  bdevs = _FindDisks(disks)

  # disconnect disks
  for rd in bdevs:
    try:
      rd.DisconnectNet()
    except errors.BlockDeviceError, err:
      _Fail("Can't change network configuration to standalone mode: %s",
            err, exc=True)


def DrbdAttachNet(disks, multimaster):
  """Attaches the network on a list of drbd devices.

  """
  bdevs = _FindDisks(disks)

  # reconnect disks, switch to new master configuration and if
  # needed primary mode
  for rd in bdevs:
    try:
      rd.AttachNet(multimaster)
    except errors.BlockDeviceError, err:
      _Fail("Can't change network configuration: %s", err)

  # wait until the disks are connected; we need to retry the re-attach
  # if the device becomes standalone, as this might happen if the one
  # node disconnects and reconnects in a different mode before the
  # other node reconnects; in this case, one or both of the nodes will
  # decide it has wrong configuration and switch to standalone

  def _Attach():
    all_connected = True

    for rd in bdevs:
      stats = rd.GetProcStatus()

      if multimaster:
        # In the multimaster case we have to wait explicitly until
        # the resource is Connected and UpToDate/UpToDate, because
        # we promote *both nodes* to primary directly afterwards.
        # Being in resync is not enough, since there is a race during which we
        # may promote a node with an Outdated disk to primary, effectively
        # tearing down the connection.
        all_connected = (all_connected and
                         stats.is_connected and
                         stats.is_disk_uptodate and
                         stats.peer_disk_uptodate)
      else:
        all_connected = (all_connected and
                         (stats.is_connected or stats.is_in_resync))

      if stats.is_standalone:
        # peer had different config info and this node became
        # standalone, even though this should not happen with the
        # new staged way of changing disk configs
        try:
          rd.AttachNet(multimaster)
        except errors.BlockDeviceError, err:
          _Fail("Can't change network configuration: %s", err)

    if not all_connected:
      raise utils.RetryAgain()

  try:
    # Start with a delay of 100 miliseconds and go up to 5 seconds
    utils.Retry(_Attach, (0.1, 1.5, 5.0), 2 * 60)
  except utils.RetryTimeout:
    _Fail("Timeout in disk reconnecting")


def DrbdWaitSync(disks):
  """Wait until DRBDs have synchronized.

  """
  def _helper(rd):
    stats = rd.GetProcStatus()
    if not (stats.is_connected or stats.is_in_resync):
      raise utils.RetryAgain()
    return stats

  bdevs = _FindDisks(disks)

  min_resync = 100
  alldone = True
  for rd in bdevs:
    try:
      # poll each second for 15 seconds
      stats = utils.Retry(_helper, 1, 15, args=[rd])
    except utils.RetryTimeout:
      stats = rd.GetProcStatus()
      # last check
      if not (stats.is_connected or stats.is_in_resync):
        _Fail("DRBD device %s is not in sync: stats=%s", rd, stats)
    alldone = alldone and (not stats.is_in_resync)
    if stats.sync_percent is not None:
      min_resync = min(min_resync, stats.sync_percent)

  return (alldone, min_resync)


def DrbdNeedsActivation(disks):
  """Checks which of the passed disks needs activation and returns their UUIDs.

  """
  faulty_disks = []

  for disk in disks:
    rd = _RecursiveFindBD(disk)
    if rd is None:
      faulty_disks.append(disk)
      continue

    stats = rd.GetProcStatus()
    if stats.is_standalone or stats.is_diskless:
      faulty_disks.append(disk)

  return [disk.uuid for disk in faulty_disks]


def GetDrbdUsermodeHelper():
  """Returns DRBD usermode helper currently configured.

  """
  try:
    return drbd.DRBD8.GetUsermodeHelper()
  except errors.BlockDeviceError, err:
    _Fail(str(err))


def PowercycleNode(hypervisor_type, hvparams=None):
  """Hard-powercycle the node.

  Because we need to return first, and schedule the powercycle in the
  background, we won't be able to report failures nicely.

  """
  hyper = hypervisor.GetHypervisor(hypervisor_type)
  try:
    pid = os.fork()
  except OSError:
    # if we can't fork, we'll pretend that we're in the child process
    pid = 0
  if pid > 0:
    return "Reboot scheduled in 5 seconds"
  # ensure the child is running on ram
  try:
    utils.Mlockall()
  except Exception: # pylint: disable=W0703
    pass
  time.sleep(5)
  hyper.PowercycleNode(hvparams=hvparams)


def _VerifyRestrictedCmdName(cmd):
  """Verifies a restricted command name.

  @type cmd: string
  @param cmd: Command name
  @rtype: tuple; (boolean, string or None)
  @return: The tuple's first element is the status; if C{False}, the second
    element is an error message string, otherwise it's C{None}

  """
  if not cmd.strip():
    return (False, "Missing command name")

  if os.path.basename(cmd) != cmd:
    return (False, "Invalid command name")

  if not constants.EXT_PLUGIN_MASK.match(cmd):
    return (False, "Command name contains forbidden characters")

  return (True, None)


def _CommonRestrictedCmdCheck(path, owner):
  """Common checks for restricted command file system directories and files.

  @type path: string
  @param path: Path to check
  @param owner: C{None} or tuple containing UID and GID
  @rtype: tuple; (boolean, string or C{os.stat} result)
  @return: The tuple's first element is the status; if C{False}, the second
    element is an error message string, otherwise it's the result of C{os.stat}

  """
  if owner is None:
    # Default to root as owner
    owner = (0, 0)

  try:
    st = os.stat(path)
  except EnvironmentError, err:
    return (False, "Can't stat(2) '%s': %s" % (path, err))

  if stat.S_IMODE(st.st_mode) & (~_RCMD_MAX_MODE):
    return (False, "Permissions on '%s' are too permissive" % path)

  if (st.st_uid, st.st_gid) != owner:
    (owner_uid, owner_gid) = owner
    return (False, "'%s' is not owned by %s:%s" % (path, owner_uid, owner_gid))

  return (True, st)


def _VerifyRestrictedCmdDirectory(path, _owner=None):
  """Verifies restricted command directory.

  @type path: string
  @param path: Path to check
  @rtype: tuple; (boolean, string or None)
  @return: The tuple's first element is the status; if C{False}, the second
    element is an error message string, otherwise it's C{None}

  """
  (status, value) = _CommonRestrictedCmdCheck(path, _owner)

  if not status:
    return (False, value)

  if not stat.S_ISDIR(value.st_mode):
    return (False, "Path '%s' is not a directory" % path)

  return (True, None)


def _VerifyRestrictedCmd(path, cmd, _owner=None):
  """Verifies a whole restricted command and returns its executable filename.

  @type path: string
  @param path: Directory containing restricted commands
  @type cmd: string
  @param cmd: Command name
  @rtype: tuple; (boolean, string)
  @return: The tuple's first element is the status; if C{False}, the second
    element is an error message string, otherwise the second element is the
    absolute path to the executable

  """
  executable = utils.PathJoin(path, cmd)

  (status, msg) = _CommonRestrictedCmdCheck(executable, _owner)

  if not status:
    return (False, msg)

  if not utils.IsExecutable(executable):
    return (False, "access(2) thinks '%s' can't be executed" % executable)

  return (True, executable)


def _PrepareRestrictedCmd(path, cmd,
                          _verify_dir=_VerifyRestrictedCmdDirectory,
                          _verify_name=_VerifyRestrictedCmdName,
                          _verify_cmd=_VerifyRestrictedCmd):
  """Performs a number of tests on a restricted command.

  @type path: string
  @param path: Directory containing restricted commands
  @type cmd: string
  @param cmd: Command name
  @return: Same as L{_VerifyRestrictedCmd}

  """
  # Verify the directory first
  (status, msg) = _verify_dir(path)
  if status:
    # Check command if everything was alright
    (status, msg) = _verify_name(cmd)

  if not status:
    return (False, msg)

  # Check actual executable
  return _verify_cmd(path, cmd)


def RunConstrainedCmd(cmd,
                      lock_file,
                      path,
                      inp=None,
                      _lock_timeout=_RCMD_LOCK_TIMEOUT,
                      _sleep_fn=time.sleep,
                      _prepare_fn=_PrepareRestrictedCmd,
                      _runcmd_fn=utils.RunCmd,
                      _enabled=constants.ENABLE_RESTRICTED_COMMANDS):
  """Executes a command after performing strict tests.

  @type cmd: string
  @param cmd: Command name
  @type lock_file: string
  @param lock_file: path to the lock file
  @type path: string
  @param path: path to the directory in which the command is present
  @type inp: string
  @param inp: Input to be passed to the command
  @rtype: string
  @return: Command output
  @raise RPCFail: In case of an error

  """
  logging.info("Preparing to run restricted command '%s'", cmd)

  if not _enabled:
    _Fail("Restricted commands disabled at configure time")

  lock = None
  try:
    cmdresult = None
    try:
      lock = utils.FileLock.Open(lock_file)
      lock.Exclusive(blocking=True, timeout=_lock_timeout)

      (status, value) = _prepare_fn(path, cmd)

      if status:
        if inp:
          input_fd = tempfile.TemporaryFile()
          input_fd.write(inp)
          input_fd.flush()
          input_fd.seek(0)
        else:
          input_fd = None
        cmdresult = _runcmd_fn([value], env={}, reset_env=True,
                               postfork_fn=lambda _: lock.Unlock(),
                               input_fd=input_fd)
        if input_fd:
          input_fd.close()
      else:
        logging.error(value)
    except Exception: # pylint: disable=W0703
      # Keep original error in log
      logging.exception("Caught exception")

    if cmdresult is None:
      logging.info("Sleeping for %0.1f seconds before returning",
                   _RCMD_INVALID_DELAY)
      _sleep_fn(_RCMD_INVALID_DELAY)

      # Do not include original error message in returned error
      _Fail("Executing command '%s' failed" % cmd)
    elif cmdresult.failed or cmdresult.fail_reason:
      _Fail("Restricted command '%s' failed: %s; output: %s",
            cmd, cmdresult.fail_reason, cmdresult.output)
    else:
      return cmdresult.output
  finally:
    if lock is not None:
      # Release lock at last
      lock.Close()
      lock = None


def SetWatcherPause(until, _filename=pathutils.WATCHER_PAUSEFILE):
  """Creates or removes the watcher pause file.

  @type until: None or number
  @param until: Unix timestamp saying until when the watcher shouldn't run

  """
  if until is None:
    logging.info("Received request to no longer pause watcher")
    utils.RemoveFile(_filename)
  else:
    logging.info("Received request to pause watcher until %s", until)

    if not ht.TNumber(until):
      _Fail("Duration must be numeric")

    utils.WriteFile(_filename, data="%d\n" % (until, ), mode=0644)


def ConfigureOVS(ovs_name, ovs_link):
  """Creates a OpenvSwitch on the node.

  This function sets up a OpenvSwitch on the node with given name nad
  connects it via a given eth device.

  @type ovs_name: string
  @param ovs_name: Name of the OpenvSwitch to create.
  @type ovs_link: None or string
  @param ovs_link: Ethernet device for outside connection (can be missing)

  """
  # Initialize the OpenvSwitch
  result = utils.RunCmd(["ovs-vsctl", "add-br", ovs_name])
  if result.failed:
    _Fail("Failed to create openvswitch. Script return value: %s, output: '%s'"
          % (result.exit_code, result.output), log=True)

  # And connect it to a physical interface, if given
  if ovs_link:
    result = utils.RunCmd(["ovs-vsctl", "add-port", ovs_name, ovs_link])
    if result.failed:
      _Fail("Failed to connect openvswitch to  interface %s. Script return"
            " value: %s, output: '%s'" % (ovs_link, result.exit_code,
            result.output), log=True)


def GetFileInfo(file_path):
  """ Checks if a file exists and returns information related to it.

  Currently returned information:
    - file size: int, size in bytes

  @type file_path: string
  @param file_path: Name of file to examine.

  @rtype: tuple of bool, dict
  @return: Whether the file exists, and a dictionary of information about the
           file gathered by os.stat.

  """
  try:
    stat_info = os.stat(file_path)
    values_dict = {
      constants.STAT_SIZE: stat_info.st_size,
    }
    return True, values_dict
  except IOError:
    return False, {}


class HooksRunner(object):
  """Hook runner.

  This class is instantiated on the node side (ganeti-noded) and not
  on the master side.

  """
  def __init__(self, hooks_base_dir=None):
    """Constructor for hooks runner.

    @type hooks_base_dir: str or None
    @param hooks_base_dir: if not None, this overrides the
        L{pathutils.HOOKS_BASE_DIR} (useful for unittests)

    """
    if hooks_base_dir is None:
      hooks_base_dir = pathutils.HOOKS_BASE_DIR
    # yeah, _BASE_DIR is not valid for attributes, we use it like a
    # constant
    self._BASE_DIR = hooks_base_dir # pylint: disable=C0103

  def RunLocalHooks(self, node_list, hpath, phase, env):
    """Check that the hooks will be run only locally and then run them.

    """
    assert len(node_list) == 1
    node = node_list[0]
    _, myself = ssconf.GetMasterAndMyself()
    assert node == myself

    results = self.RunHooks(hpath, phase, env)

    # Return values in the form expected by HooksMaster
    return {node: (None, False, results)}

  def RunHooks(self, hpath, phase, env):
    """Run the scripts in the hooks directory.

    @type hpath: str
    @param hpath: the path to the hooks directory which
        holds the scripts
    @type phase: str
    @param phase: either L{constants.HOOKS_PHASE_PRE} or
        L{constants.HOOKS_PHASE_POST}
    @type env: dict
    @param env: dictionary with the environment for the hook
    @rtype: list
    @return: list of 3-element tuples:
      - script path
      - script result, either L{constants.HKR_SUCCESS} or
        L{constants.HKR_FAIL}
      - output of the script

    @raise errors.ProgrammerError: for invalid input
        parameters

    """
    if phase == constants.HOOKS_PHASE_PRE:
      suffix = "pre"
    elif phase == constants.HOOKS_PHASE_POST:
      suffix = "post"
    else:
      _Fail("Unknown hooks phase '%s'", phase)

    subdir = "%s-%s.d" % (hpath, suffix)
    dir_name = utils.PathJoin(self._BASE_DIR, subdir)

    results = []

    if not os.path.isdir(dir_name):
      # for non-existing/non-dirs, we simply exit instead of logging a
      # warning at every operation
      return results

    runparts_results = utils.RunParts(dir_name, env=env, reset_env=True)

    for (relname, relstatus, runresult) in runparts_results:
      if relstatus == constants.RUNPARTS_SKIP:
        rrval = constants.HKR_SKIP
        output = ""
      elif relstatus == constants.RUNPARTS_ERR:
        rrval = constants.HKR_FAIL
        output = "Hook script execution error: %s" % runresult
      elif relstatus == constants.RUNPARTS_RUN:
        if runresult.failed:
          rrval = constants.HKR_FAIL
        else:
          rrval = constants.HKR_SUCCESS
        output = utils.SafeEncode(runresult.output.strip())
      results.append(("%s/%s" % (subdir, relname), rrval, output))

    return results


class IAllocatorRunner(object):
  """IAllocator runner.

  This class is instantiated on the node side (ganeti-noded) and not on
  the master side.

  """
  @staticmethod
  def Run(name, idata, ial_params):
    """Run an iallocator script.

    @type name: str
    @param name: the iallocator script name
    @type idata: str
    @param idata: the allocator input data
    @type ial_params: list
    @param ial_params: the iallocator parameters

    @rtype: tuple
    @return: two element tuple of:
       - status
       - either error message or stdout of allocator (for success)

    """
    alloc_script = utils.FindFile(name, constants.IALLOCATOR_SEARCH_PATH,
                                  os.path.isfile)
    if alloc_script is None:
      _Fail("iallocator module '%s' not found in the search path", name)

    fd, fin_name = tempfile.mkstemp(prefix="ganeti-iallocator.")
    try:
      os.write(fd, idata)
      os.close(fd)
      result = utils.RunCmd([alloc_script, fin_name] + ial_params)
      if result.failed:
        _Fail("iallocator module '%s' failed: %s, output '%s'",
              name, result.fail_reason, result.output)
    finally:
      os.unlink(fin_name)

    return result.stdout


class DevCacheManager(object):
  """Simple class for managing a cache of block device information.

  """
  _DEV_PREFIX = "/dev/"
  _ROOT_DIR = pathutils.BDEV_CACHE_DIR

  @classmethod
  def _ConvertPath(cls, dev_path):
    """Converts a /dev/name path to the cache file name.

    This replaces slashes with underscores and strips the /dev
    prefix. It then returns the full path to the cache file.

    @type dev_path: str
    @param dev_path: the C{/dev/} path name
    @rtype: str
    @return: the converted path name

    """
    if dev_path.startswith(cls._DEV_PREFIX):
      dev_path = dev_path[len(cls._DEV_PREFIX):]
    dev_path = dev_path.replace("/", "_")
    fpath = utils.PathJoin(cls._ROOT_DIR, "bdev_%s" % dev_path)
    return fpath

  @classmethod
  def UpdateCache(cls, dev_path, owner, on_primary, iv_name):
    """Updates the cache information for a given device.

    @type dev_path: str
    @param dev_path: the pathname of the device
    @type owner: str
    @param owner: the owner (instance name) of the device
    @type on_primary: bool
    @param on_primary: whether this is the primary
        node nor not
    @type iv_name: str
    @param iv_name: the instance-visible name of the
        device, as in objects.Disk.iv_name

    @rtype: None

    """
    if dev_path is None:
      logging.error("DevCacheManager.UpdateCache got a None dev_path")
      return
    fpath = cls._ConvertPath(dev_path)
    if on_primary:
      state = "primary"
    else:
      state = "secondary"
    if iv_name is None:
      iv_name = "not_visible"
    fdata = "%s %s %s\n" % (str(owner), state, iv_name)
    try:
      utils.WriteFile(fpath, data=fdata)
    except EnvironmentError, err:
      logging.exception("Can't update bdev cache for %s: %s", dev_path, err)

  @classmethod
  def RemoveCache(cls, dev_path):
    """Remove data for a dev_path.

    This is just a wrapper over L{utils.io.RemoveFile} with a converted
    path name and logging.

    @type dev_path: str
    @param dev_path: the pathname of the device

    @rtype: None

    """
    if dev_path is None:
      logging.error("DevCacheManager.RemoveCache got a None dev_path")
      return
    fpath = cls._ConvertPath(dev_path)
    try:
      utils.RemoveFile(fpath)
    except EnvironmentError, err:
      logging.exception("Can't update bdev cache for %s: %s", dev_path, err)
