Merge branch 'stable-2.8' into stable-2.9
[ganeti-local] / lib / constants.py
index cedb125..0e721ba 100644 (file)
@@ -1,7 +1,7 @@
 #
 #
 
-# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Google Inc.
+# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Google Inc.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -26,6 +26,7 @@ import socket
 
 from ganeti import _autoconf
 from ganeti import _vcsversion
+from ganeti import compat
 from ganeti import pathutils
 
 
@@ -34,7 +35,11 @@ RELEASE_VERSION = _autoconf.PACKAGE_VERSION
 OS_API_V10 = 10
 OS_API_V15 = 15
 OS_API_V20 = 20
-OS_API_VERSIONS = frozenset([OS_API_V10, OS_API_V15, OS_API_V20])
+OS_API_VERSIONS = compat.UniqueFrozenset([
+  OS_API_V10,
+  OS_API_V15,
+  OS_API_V20,
+  ])
 VCS_VERSION = _vcsversion.VCS_VERSION
 EXPORT_VERSION = 0
 RAPI_VERSION = 2
@@ -99,8 +104,12 @@ RAPI_USER = _autoconf.RAPI_USER
 RAPI_GROUP = _autoconf.RAPI_GROUP
 CONFD_USER = _autoconf.CONFD_USER
 CONFD_GROUP = _autoconf.CONFD_GROUP
+LUXID_USER = _autoconf.LUXID_USER
+LUXID_GROUP = _autoconf.LUXID_GROUP
 NODED_USER = _autoconf.NODED_USER
 NODED_GROUP = _autoconf.NODED_GROUP
+MOND_USER = _autoconf.MOND_USER
+MOND_GROUP = _autoconf.MOND_GROUP
 SSH_LOGIN_USER = _autoconf.SSH_LOGIN_USER
 SSH_CONSOLE_USER = _autoconf.SSH_CONSOLE_USER
 
@@ -136,44 +145,89 @@ RUN_DIRS_MODE = 0775
 SECURE_DIR_MODE = 0700
 SECURE_FILE_MODE = 0600
 ADOPTABLE_BLOCKDEV_ROOT = "/dev/disk/"
-ENABLE_FILE_STORAGE = _autoconf.ENABLE_FILE_STORAGE
 ENABLE_SHARED_FILE_STORAGE = _autoconf.ENABLE_SHARED_FILE_STORAGE
 ENABLE_CONFD = _autoconf.ENABLE_CONFD
+ENABLE_MOND = _autoconf.ENABLE_MOND
 ENABLE_SPLIT_QUERY = _autoconf.ENABLE_SPLIT_QUERY
 ENABLE_RESTRICTED_COMMANDS = _autoconf.ENABLE_RESTRICTED_COMMANDS
 
+# SSH constants
+SSH = "ssh"
+SCP = "scp"
+
 NODED = "ganeti-noded"
 CONFD = "ganeti-confd"
+LUXID = "ganeti-luxid"
 RAPI = "ganeti-rapi"
 MASTERD = "ganeti-masterd"
-# used in the ganeti-nbma project
-NLD = "ganeti-nld"
+MOND = "ganeti-mond"
+
+DAEMONS = compat.UniqueFrozenset([
+  NODED,
+  CONFD,
+  LUXID,
+  RAPI,
+  MASTERD,
+  MOND,
+  ])
 
 DAEMONS_PORTS = {
   # daemon-name: ("proto", "default-port")
   NODED: ("tcp", 1811),
   CONFD: ("udp", 1814),
+  MOND: ("tcp", 1815),
   RAPI: ("tcp", 5080),
-  "ssh": ("tcp", 22),
-  # used in the ganeti-nbma project
-  NLD: ("udp", 1816),
+  SSH: ("tcp", 22),
 }
+
 DEFAULT_NODED_PORT = DAEMONS_PORTS[NODED][1]
 DEFAULT_CONFD_PORT = DAEMONS_PORTS[CONFD][1]
+DEFAULT_MOND_PORT = DAEMONS_PORTS[MOND][1]
 DEFAULT_RAPI_PORT = DAEMONS_PORTS[RAPI][1]
-# used in the ganeti-nbma project
-DEFAULT_NLD_PORT = DAEMONS_PORTS[NLD][1]
 
 FIRST_DRBD_PORT = 11000
 LAST_DRBD_PORT = 14999
 
-DAEMONS_LOGFILES = {
-  NODED: pathutils.GetLogFilename("node-daemon"),
-  CONFD: pathutils.GetLogFilename("conf-daemon"),
-  RAPI: pathutils.GetLogFilename("rapi-daemon"),
-  MASTERD: pathutils.GetLogFilename("master-daemon"),
+DAEMONS_LOGBASE = {
+  NODED: "node-daemon",
+  CONFD: "conf-daemon",
+  LUXID: "luxi-daemon",
+  RAPI: "rapi-daemon",
+  MASTERD: "master-daemon",
+  MOND: "monitoring-daemon",
   }
 
+DAEMONS_LOGFILES = \
+    dict((daemon, pathutils.GetLogFilename(DAEMONS_LOGBASE[daemon]))
+         for daemon in DAEMONS_LOGBASE)
+
+# Some daemons might require more than one logfile.
+# Specifically, right now only the Haskell http library "snap", used by the
+# monitoring daemon, requires multiple log files.
+
+# These are the only valid reasons for having an extra logfile
+EXTRA_LOGREASON_ACCESS = "access"
+EXTRA_LOGREASON_ERROR = "error"
+
+VALID_EXTRA_LOGREASONS = compat.UniqueFrozenset([
+  EXTRA_LOGREASON_ACCESS,
+  EXTRA_LOGREASON_ERROR,
+  ])
+
+# These are the extra logfiles, grouped by daemon
+DAEMONS_EXTRA_LOGBASE = {
+  MOND: {
+    EXTRA_LOGREASON_ACCESS: "monitoring-daemon-access",
+    EXTRA_LOGREASON_ERROR: "monitoring-daemon-error",
+    }
+  }
+
+DAEMONS_EXTRA_LOGFILES = \
+  dict((daemon, dict((extra,
+       pathutils.GetLogFilename(DAEMONS_EXTRA_LOGBASE[daemon][extra]))
+       for extra in DAEMONS_EXTRA_LOGBASE[daemon]))
+         for daemon in DAEMONS_EXTRA_LOGBASE)
+
 DEV_CONSOLE = "/dev/console"
 
 PROC_MOUNTS = "/proc/mounts"
@@ -181,6 +235,10 @@ PROC_MOUNTS = "/proc/mounts"
 # Local UniX Interface related constants
 LUXI_EOM = "\3"
 LUXI_VERSION = CONFIG_VERSION
+#: Environment variable for the luxi override socket
+LUXI_OVERRIDE = "FORCE_LUXI_SOCKET"
+LUXI_OVERRIDE_MASTER = "master"
+LUXI_OVERRIDE_QUERY = "query"
 
 # one of "no", "yes", "only"
 SYSLOG_USAGE = _autoconf.SYSLOG_USAGE
@@ -196,8 +254,12 @@ XEN_KERNEL = _autoconf.XEN_KERNEL
 XEN_INITRD = _autoconf.XEN_INITRD
 XEN_CMD_XM = "xm"
 XEN_CMD_XL = "xl"
-# FIXME: This will be made configurable using hvparams in Ganeti 2.7
-XEN_CMD = _autoconf.XEN_CMD
+
+KNOWN_XEN_COMMANDS = compat.UniqueFrozenset([
+  XEN_CMD_XM,
+  XEN_CMD_XL,
+  ])
+
 # When the Xen toolstack used is "xl", live migration requires the source host
 # to connect to the target host via ssh (xl runs this command). We need to pass
 # the command xl runs some extra info so that it can use Ganeti's key
@@ -229,7 +291,12 @@ CONS_SPICE = "spice"
 CONS_MESSAGE = "msg"
 
 #: All console types
-CONS_ALL = frozenset([CONS_SSH, CONS_VNC, CONS_SPICE, CONS_MESSAGE])
+CONS_ALL = compat.UniqueFrozenset([
+  CONS_SSH,
+  CONS_VNC,
+  CONS_SPICE,
+  CONS_MESSAGE,
+  ])
 
 # For RSA keys more bits are better, but they also make operations more
 # expensive. NIST SP 800-131 recommends a minimum of 2048 bits from the year
@@ -262,7 +329,7 @@ IEM_EXPORT = "export"
 # Import/export transport compression
 IEC_NONE = "none"
 IEC_GZIP = "gzip"
-IEC_ALL = frozenset([
+IEC_ALL = compat.UniqueFrozenset([
   IEC_NONE,
   IEC_GZIP,
   ])
@@ -309,9 +376,27 @@ HKR_FAIL = 1
 HKR_SUCCESS = 2
 
 # Storage types
+ST_BLOCK = "blockdev"
+ST_DISKLESS = "diskless"
+ST_EXT = "ext"
 ST_FILE = "file"
 ST_LVM_PV = "lvm-pv"
 ST_LVM_VG = "lvm-vg"
+ST_RADOS = "rados"
+
+STORAGE_TYPES = compat.UniqueFrozenset([
+  ST_BLOCK,
+  ST_DISKLESS,
+  ST_EXT,
+  ST_FILE,
+  ST_LVM_PV,
+  ST_LVM_VG,
+  ST_RADOS,
+  ])
+
+# the set of storage types for which storage reporting is available
+# FIXME: Remove this, once storage reporting is available for all types.
+STS_REPORT = compat.UniqueFrozenset([ST_FILE, ST_LVM_PV, ST_LVM_VG])
 
 # Storage fields
 # first two are valid in LU context only, not passed to backend
@@ -328,7 +413,7 @@ SF_ALLOCATABLE = "allocatable"
 SO_FIX_CONSISTENCY = "fix-consistency"
 
 # Available fields per storage type
-VALID_STORAGE_FIELDS = frozenset([
+VALID_STORAGE_FIELDS = compat.UniqueFrozenset([
   SF_NAME,
   SF_TYPE,
   SF_SIZE,
@@ -337,8 +422,6 @@ VALID_STORAGE_FIELDS = frozenset([
   SF_ALLOCATABLE,
   ])
 
-VALID_STORAGE_TYPES = frozenset([ST_FILE, ST_LVM_PV, ST_LVM_VG])
-
 MODIFIABLE_STORAGE_FIELDS = {
   ST_LVM_PV: frozenset([SF_ALLOCATABLE]),
   }
@@ -353,39 +436,134 @@ VALID_STORAGE_OPERATIONS = {
  LDS_UNKNOWN,
  LDS_FAULTY) = range(1, 4)
 
+LDS_NAMES = {
+  LDS_OKAY: "ok",
+  LDS_UNKNOWN: "unknown",
+  LDS_FAULTY: "faulty",
+}
+
 # disk template types
+DT_BLOCK = "blockdev"
 DT_DISKLESS = "diskless"
-DT_PLAIN = "plain"
 DT_DRBD8 = "drbd"
+DT_EXT = "ext"
 DT_FILE = "file"
-DT_SHARED_FILE = "sharedfile"
-DT_BLOCK = "blockdev"
+DT_PLAIN = "plain"
 DT_RBD = "rbd"
+DT_SHARED_FILE = "sharedfile"
+
+# This is used to order determine the default disk template when the list
+# of enabled disk templates is inferred from the current state of the cluster.
+# This only happens on an upgrade from a version of Ganeti that did not
+# support the 'enabled_disk_templates' so far.
+DISK_TEMPLATE_PREFERENCE = [
+  DT_BLOCK,
+  DT_DISKLESS,
+  DT_DRBD8,
+  DT_EXT,
+  DT_FILE,
+  DT_PLAIN,
+  DT_RBD,
+  DT_SHARED_FILE,
+  ]
+
+DISK_TEMPLATES = compat.UniqueFrozenset([
+  DT_DISKLESS,
+  DT_PLAIN,
+  DT_DRBD8,
+  DT_FILE,
+  DT_SHARED_FILE,
+  DT_BLOCK,
+  DT_RBD,
+  DT_EXT
+  ])
+
+# disk templates that are enabled by default
+DEFAULT_ENABLED_DISK_TEMPLATES = [
+  DT_DRBD8,
+  DT_PLAIN,
+  ]
+
+# mapping of disk templates to storage types
+MAP_DISK_TEMPLATE_STORAGE_TYPE = {
+  DT_BLOCK: ST_BLOCK,
+  DT_DISKLESS: ST_DISKLESS,
+  DT_DRBD8: ST_LVM_VG,
+  DT_EXT: ST_EXT,
+  DT_FILE: ST_FILE,
+  DT_PLAIN: ST_LVM_VG,
+  DT_RBD: ST_RADOS,
+  DT_SHARED_FILE: ST_FILE,
+  }
 
 # the set of network-mirrored disk templates
-DTS_INT_MIRROR = frozenset([DT_DRBD8])
+DTS_INT_MIRROR = compat.UniqueFrozenset([DT_DRBD8])
 
 # the set of externally-mirrored disk templates (e.g. SAN, NAS)
-DTS_EXT_MIRROR = frozenset([DT_SHARED_FILE, DT_BLOCK, DT_RBD])
+DTS_EXT_MIRROR = compat.UniqueFrozenset([
+  DT_DISKLESS, # 'trivially' externally mirrored
+  DT_SHARED_FILE,
+  DT_BLOCK,
+  DT_RBD,
+  DT_EXT,
+  ])
 
 # the set of non-lvm-based disk templates
-DTS_NOT_LVM = frozenset([DT_DISKLESS, DT_FILE, DT_SHARED_FILE,
-                         DT_BLOCK, DT_RBD])
+DTS_NOT_LVM = compat.UniqueFrozenset([
+  DT_DISKLESS,
+  DT_FILE,
+  DT_SHARED_FILE,
+  DT_BLOCK,
+  DT_RBD,
+  DT_EXT,
+  ])
 
 # the set of disk templates which can be grown
-DTS_GROWABLE = frozenset([DT_PLAIN, DT_DRBD8, DT_FILE, DT_SHARED_FILE, DT_RBD])
+DTS_GROWABLE = compat.UniqueFrozenset([
+  DT_PLAIN,
+  DT_DRBD8,
+  DT_FILE,
+  DT_SHARED_FILE,
+  DT_RBD,
+  DT_EXT,
+  ])
 
 # the set of disk templates that allow adoption
-DTS_MAY_ADOPT = frozenset([DT_PLAIN, DT_BLOCK])
+DTS_MAY_ADOPT = compat.UniqueFrozenset([
+  DT_PLAIN,
+  DT_BLOCK,
+  ])
 
 # the set of disk templates that *must* use adoption
-DTS_MUST_ADOPT = frozenset([DT_BLOCK])
+DTS_MUST_ADOPT = compat.UniqueFrozenset([DT_BLOCK])
 
 # the set of disk templates that allow migrations
 DTS_MIRRORED = frozenset.union(DTS_INT_MIRROR, DTS_EXT_MIRROR)
 
 # the set of file based disk templates
-DTS_FILEBASED = frozenset([DT_FILE, DT_SHARED_FILE])
+DTS_FILEBASED = compat.UniqueFrozenset([
+  DT_FILE,
+  DT_SHARED_FILE,
+  ])
+
+# the set of disk templates that can be moved by copying
+# Note: a requirement is that they're not accessed externally or shared between
+# nodes; in particular, sharedfile is not suitable.
+DTS_COPYABLE = compat.UniqueFrozenset([
+  DT_FILE,
+  DT_PLAIN,
+  ])
+
+# the set of disk templates that are supported by exclusive_storage
+DTS_EXCL_STORAGE = compat.UniqueFrozenset([DT_PLAIN])
+
+# templates for which we don't perform checks on free space
+DTS_NO_FREE_SPACE_CHECK = compat.UniqueFrozenset([
+  DT_FILE,
+  DT_SHARED_FILE,
+  DT_RBD,
+  DT_EXT,
+  ])
 
 # logical disk types
 LD_LV = "lvm"
@@ -393,19 +571,28 @@ LD_DRBD8 = "drbd8"
 LD_FILE = "file"
 LD_BLOCKDEV = "blockdev"
 LD_RBD = "rbd"
-LOGICAL_DISK_TYPES = frozenset([
+LD_EXT = "ext"
+LOGICAL_DISK_TYPES = compat.UniqueFrozenset([
   LD_LV,
   LD_DRBD8,
   LD_FILE,
   LD_BLOCKDEV,
   LD_RBD,
+  LD_EXT,
   ])
 
-LDS_BLOCK = frozenset([LD_LV, LD_DRBD8, LD_BLOCKDEV, LD_RBD])
+LDS_BLOCK = compat.UniqueFrozenset([
+  LD_LV,
+  LD_DRBD8,
+  LD_BLOCKDEV,
+  LD_RBD,
+  LD_EXT,
+  ])
 
 # drbd constants
 DRBD_HMAC_ALG = "md5"
-DRBD_NET_PROTOCOL = "C"
+DRBD_DEFAULT_NET_PROTOCOL = "C"
+DRBD_MIGRATION_NET_PROTOCOL = "C"
 DRBD_STATUS_FILE = "/proc/drbd"
 
 #: Size of DRBD meta block device
@@ -418,7 +605,7 @@ DRBD_B_DISK_DRAIN = "d"
 DRBD_B_DISK_FLUSH = "f"
 
 # Valid barrier combinations: "n" or any non-null subset of "bfd"
-DRBD_VALID_BARRIER_OPT = frozenset([
+DRBD_VALID_BARRIER_OPT = compat.UniqueFrozenset([
   frozenset([DRBD_B_NONE]),
   frozenset([DRBD_B_DISK_BARRIERS]),
   frozenset([DRBD_B_DISK_DRAIN]),
@@ -437,19 +624,19 @@ FD_LOOP = "loop"
 FD_BLKTAP = "blktap"
 
 # the set of drbd-like disk types
-LDS_DRBD = frozenset([LD_DRBD8])
+LDS_DRBD = compat.UniqueFrozenset([LD_DRBD8])
 
 # disk access mode
 DISK_RDONLY = "ro"
 DISK_RDWR = "rw"
-DISK_ACCESS_SET = frozenset([DISK_RDONLY, DISK_RDWR])
+DISK_ACCESS_SET = compat.UniqueFrozenset([DISK_RDONLY, DISK_RDWR])
 
 # disk replacement mode
 REPLACE_DISK_PRI = "replace_on_primary"    # replace disks on primary
 REPLACE_DISK_SEC = "replace_on_secondary"  # replace disks on secondary
 REPLACE_DISK_CHG = "replace_new_secondary" # change secondary node
 REPLACE_DISK_AUTO = "replace_auto"
-REPLACE_MODES = frozenset([
+REPLACE_MODES = compat.UniqueFrozenset([
   REPLACE_DISK_PRI,
   REPLACE_DISK_SEC,
   REPLACE_DISK_CHG,
@@ -459,7 +646,7 @@ REPLACE_MODES = frozenset([
 # Instance export mode
 EXPORT_MODE_LOCAL = "local"
 EXPORT_MODE_REMOTE = "remote"
-EXPORT_MODES = frozenset([
+EXPORT_MODES = compat.UniqueFrozenset([
   EXPORT_MODE_LOCAL,
   EXPORT_MODE_REMOTE,
   ])
@@ -468,7 +655,7 @@ EXPORT_MODES = frozenset([
 INSTANCE_CREATE = "create"
 INSTANCE_IMPORT = "import"
 INSTANCE_REMOTE_IMPORT = "remote-import"
-INSTANCE_CREATE_MODES = frozenset([
+INSTANCE_CREATE_MODES = compat.UniqueFrozenset([
   INSTANCE_CREATE,
   INSTANCE_IMPORT,
   INSTANCE_REMOTE_IMPORT,
@@ -493,17 +680,7 @@ RIE_CONNECT_RETRIES = 10
 #: Give child process up to 5 seconds to exit after sending a signal
 CHILD_LINGER_TIMEOUT = 5.0
 
-DISK_TEMPLATES = frozenset([
-  DT_DISKLESS,
-  DT_PLAIN,
-  DT_DRBD8,
-  DT_FILE,
-  DT_SHARED_FILE,
-  DT_BLOCK,
-  DT_RBD,
-  ])
-
-FILE_DRIVER = frozenset([FD_LOOP, FD_BLKTAP])
+FILE_DRIVER = compat.UniqueFrozenset([FD_LOOP, FD_BLKTAP])
 
 # import/export config options
 INISECT_EXP = "export"
@@ -516,7 +693,7 @@ INISECT_OSP = "os"
 DDM_ADD = "add"
 DDM_MODIFY = "modify"
 DDM_REMOVE = "remove"
-DDMS_VALUES = frozenset([DDM_ADD, DDM_REMOVE])
+DDMS_VALUES = compat.UniqueFrozenset([DDM_ADD, DDM_REMOVE])
 DDMS_VALUES_WITH_MODIFY = (DDMS_VALUES | frozenset([
   DDM_MODIFY,
   ]))
@@ -539,7 +716,7 @@ TAG_NODEGROUP = "nodegroup"
 TAG_NODE = "node"
 TAG_INSTANCE = "instance"
 TAG_NETWORK = "network"
-VALID_TAG_TYPES = frozenset([
+VALID_TAG_TYPES = compat.UniqueFrozenset([
   TAG_CLUSTER,
   TAG_NODEGROUP,
   TAG_NODE,
@@ -558,7 +735,7 @@ IP6_ADDRESS_LOCALHOST = "::1"
 IP6_ADDRESS_ANY = "::"
 IP4_VERSION = 4
 IP6_VERSION = 6
-VALID_IP_VERSIONS = frozenset([IP4_VERSION, IP6_VERSION])
+VALID_IP_VERSIONS = compat.UniqueFrozenset([IP4_VERSION, IP6_VERSION])
 # for export to htools
 IP4_FAMILY = socket.AF_INET
 IP6_FAMILY = socket.AF_INET6
@@ -585,7 +762,11 @@ JOB_IDS_KEY = "jobs"
  RUNPARTS_RUN,
  RUNPARTS_ERR) = range(3)
 
-RUNPARTS_STATUS = frozenset([RUNPARTS_SKIP, RUNPARTS_RUN, RUNPARTS_ERR])
+RUNPARTS_STATUS = compat.UniqueFrozenset([
+  RUNPARTS_SKIP,
+  RUNPARTS_RUN,
+  RUNPARTS_ERR,
+  ])
 
 # RPC constants
 (RPC_ENCODING_NONE,
@@ -608,7 +789,7 @@ OS_SCRIPT_IMPORT = "import"
 OS_SCRIPT_EXPORT = "export"
 OS_SCRIPT_RENAME = "rename"
 OS_SCRIPT_VERIFY = "verify"
-OS_SCRIPTS = frozenset([
+OS_SCRIPTS = compat.UniqueFrozenset([
   OS_SCRIPT_CREATE,
   OS_SCRIPT_IMPORT,
   OS_SCRIPT_EXPORT,
@@ -621,18 +802,42 @@ OS_VARIANTS_FILE = "variants.list"
 OS_PARAMETERS_FILE = "parameters.list"
 
 OS_VALIDATE_PARAMETERS = "parameters"
-OS_VALIDATE_CALLS = frozenset([OS_VALIDATE_PARAMETERS])
+OS_VALIDATE_CALLS = compat.UniqueFrozenset([OS_VALIDATE_PARAMETERS])
+
+# External Storage (ES) related constants
+ES_ACTION_CREATE = "create"
+ES_ACTION_REMOVE = "remove"
+ES_ACTION_GROW = "grow"
+ES_ACTION_ATTACH = "attach"
+ES_ACTION_DETACH = "detach"
+ES_ACTION_SETINFO = "setinfo"
+ES_ACTION_VERIFY = "verify"
+
+ES_SCRIPT_CREATE = ES_ACTION_CREATE
+ES_SCRIPT_REMOVE = ES_ACTION_REMOVE
+ES_SCRIPT_GROW = ES_ACTION_GROW
+ES_SCRIPT_ATTACH = ES_ACTION_ATTACH
+ES_SCRIPT_DETACH = ES_ACTION_DETACH
+ES_SCRIPT_SETINFO = ES_ACTION_SETINFO
+ES_SCRIPT_VERIFY = ES_ACTION_VERIFY
+ES_SCRIPTS = frozenset([
+  ES_SCRIPT_CREATE,
+  ES_SCRIPT_REMOVE,
+  ES_SCRIPT_GROW,
+  ES_SCRIPT_ATTACH,
+  ES_SCRIPT_DETACH,
+  ES_SCRIPT_SETINFO,
+  ES_SCRIPT_VERIFY
+  ])
 
-# ssh constants
-SSH = "ssh"
-SCP = "scp"
+ES_PARAMETERS_FILE = "parameters.list"
 
 # reboot types
 INSTANCE_REBOOT_SOFT = "soft"
 INSTANCE_REBOOT_HARD = "hard"
 INSTANCE_REBOOT_FULL = "full"
 
-REBOOT_TYPES = frozenset([
+REBOOT_TYPES = compat.UniqueFrozenset([
   INSTANCE_REBOOT_SOFT,
   INSTANCE_REBOOT_HARD,
   INSTANCE_REBOOT_FULL,
@@ -642,7 +847,7 @@ REBOOT_TYPES = frozenset([
 INSTANCE_REBOOT_ALLOWED = "reboot"
 INSTANCE_REBOOT_EXIT = "exit"
 
-REBOOT_BEHAVIORS = frozenset([
+REBOOT_BEHAVIORS = compat.UniqueFrozenset([
   INSTANCE_REBOOT_ALLOWED,
   INSTANCE_REBOOT_EXIT,
   ])
@@ -652,7 +857,7 @@ VTYPE_MAYBE_STRING = "maybe-string"
 VTYPE_BOOL = "bool"
 VTYPE_SIZE = "size" # size, in MiBs
 VTYPE_INT = "int"
-ENFORCEABLE_TYPES = frozenset([
+ENFORCEABLE_TYPES = compat.UniqueFrozenset([
   VTYPE_STRING,
   VTYPE_MAYBE_STRING,
   VTYPE_BOOL,
@@ -663,6 +868,27 @@ ENFORCEABLE_TYPES = frozenset([
 # Constant representing that the user does not specify any IP version
 IFACE_NO_IP_VERSION_SPECIFIED = 0
 
+VALID_SERIAL_SPEEDS = compat.UniqueFrozenset([
+  75,
+  110,
+  300,
+  600,
+  1200,
+  1800,
+  2400,
+  4800,
+  9600,
+  14400,
+  19200,
+  28800,
+  38400,
+  57600,
+  115200,
+  230400,
+  345600,
+  460800,
+  ])
+
 # HV parameter names (global namespace)
 HV_BOOT_ORDER = "boot_order"
 HV_CDROM_IMAGE_PATH = "cdrom_image_path"
@@ -697,6 +923,7 @@ HV_KERNEL_PATH = "kernel_path"
 HV_INITRD_PATH = "initrd_path"
 HV_ROOT_PATH = "root_path"
 HV_SERIAL_CONSOLE = "serial_console"
+HV_SERIAL_SPEED = "serial_speed"
 HV_USB_MOUSE = "usb_mouse"
 HV_KEYMAP = "keymap"
 HV_DEVICE_MODEL = "device_model"
@@ -720,9 +947,23 @@ HV_REBOOT_BEHAVIOR = "reboot_behavior"
 HV_CPU_TYPE = "cpu_type"
 HV_CPU_CAP = "cpu_cap"
 HV_CPU_WEIGHT = "cpu_weight"
+HV_CPU_CORES = "cpu_cores"
+HV_CPU_THREADS = "cpu_threads"
+HV_CPU_SOCKETS = "cpu_sockets"
+HV_SOUNDHW = "soundhw"
+HV_USB_DEVICES = "usb_devices"
+HV_VGA = "vga"
+HV_KVM_EXTRA = "kvm_extra"
+HV_KVM_MACHINE_VERSION = "machine_version"
+HV_KVM_PATH = "kvm_path"
+HV_VIF_TYPE = "vif_type"
+HV_VIF_SCRIPT = "vif_script"
+HV_XEN_CMD = "xen_cmd"
+HV_VNET_HDR = "vnet_hdr"
 
 
 HVS_PARAMETER_TYPES = {
+  HV_KVM_PATH: VTYPE_STRING,
   HV_BOOT_ORDER: VTYPE_STRING,
   HV_KVM_FLOPPY_IMAGE_PATH: VTYPE_STRING,
   HV_CDROM_IMAGE_PATH: VTYPE_STRING,
@@ -756,6 +997,7 @@ HVS_PARAMETER_TYPES = {
   HV_INITRD_PATH: VTYPE_STRING,
   HV_ROOT_PATH: VTYPE_MAYBE_STRING,
   HV_SERIAL_CONSOLE: VTYPE_BOOL,
+  HV_SERIAL_SPEED: VTYPE_INT,
   HV_USB_MOUSE: VTYPE_STRING,
   HV_KEYMAP: VTYPE_STRING,
   HV_DEVICE_MODEL: VTYPE_STRING,
@@ -779,6 +1021,18 @@ HVS_PARAMETER_TYPES = {
   HV_CPU_TYPE: VTYPE_STRING,
   HV_CPU_CAP: VTYPE_INT,
   HV_CPU_WEIGHT: VTYPE_INT,
+  HV_CPU_CORES: VTYPE_INT,
+  HV_CPU_THREADS: VTYPE_INT,
+  HV_CPU_SOCKETS: VTYPE_INT,
+  HV_SOUNDHW: VTYPE_STRING,
+  HV_USB_DEVICES: VTYPE_STRING,
+  HV_VGA: VTYPE_STRING,
+  HV_KVM_EXTRA: VTYPE_STRING,
+  HV_KVM_MACHINE_VERSION: VTYPE_STRING,
+  HV_VIF_TYPE: VTYPE_STRING,
+  HV_VIF_SCRIPT: VTYPE_STRING,
+  HV_XEN_CMD: VTYPE_STRING,
+  HV_VNET_HDR: VTYPE_BOOL,
   }
 
 HVS_PARAMETERS = frozenset(HVS_PARAMETER_TYPES.keys())
@@ -803,14 +1057,14 @@ HV_MIGRATION_ACTIVE = "active"
 HV_MIGRATION_FAILED = "failed"
 HV_MIGRATION_CANCELLED = "cancelled"
 
-HV_MIGRATION_VALID_STATUSES = frozenset([
+HV_MIGRATION_VALID_STATUSES = compat.UniqueFrozenset([
   HV_MIGRATION_COMPLETED,
   HV_MIGRATION_ACTIVE,
   HV_MIGRATION_FAILED,
   HV_MIGRATION_CANCELLED,
   ])
 
-HV_MIGRATION_FAILED_STATUSES = frozenset([
+HV_MIGRATION_FAILED_STATUSES = compat.UniqueFrozenset([
   HV_MIGRATION_FAILED,
   HV_MIGRATION_CANCELLED,
   ])
@@ -864,7 +1118,7 @@ DSS_PARAMETER_TYPES = {
   }
 
 DSS_PARAMETERS = frozenset(DSS_PARAMETER_TYPES.keys())
-DS_VALID_TYPES = frozenset([LD_LV])
+DS_VALID_TYPES = compat.UniqueFrozenset([LD_LV])
 
 # Backend parameter names
 BE_MEMORY = "memory" # deprecated and replaced by max and min mem
@@ -917,6 +1171,7 @@ ISPECS_PARAMETER_TYPES = {
 
 ISPECS_PARAMETERS = frozenset(ISPECS_PARAMETER_TYPES.keys())
 
+ISPECS_MINMAX = "minmax"
 ISPECS_MIN = "min"
 ISPECS_MAX = "max"
 ISPECS_STD = "std"
@@ -924,28 +1179,28 @@ IPOLICY_DTS = "disk-templates"
 IPOLICY_VCPU_RATIO = "vcpu-ratio"
 IPOLICY_SPINDLE_RATIO = "spindle-ratio"
 
-IPOLICY_ISPECS = frozenset([
+ISPECS_MINMAX_KEYS = compat.UniqueFrozenset([
   ISPECS_MIN,
   ISPECS_MAX,
-  ISPECS_STD,
   ])
 
-IPOLICY_PARAMETERS = frozenset([
+IPOLICY_PARAMETERS = compat.UniqueFrozenset([
   IPOLICY_VCPU_RATIO,
   IPOLICY_SPINDLE_RATIO,
   ])
 
-IPOLICY_ALL_KEYS = (IPOLICY_ISPECS |
-                    IPOLICY_PARAMETERS |
-                    frozenset([IPOLICY_DTS]))
+IPOLICY_ALL_KEYS = (IPOLICY_PARAMETERS |
+                    frozenset([ISPECS_MINMAX, ISPECS_STD, IPOLICY_DTS]))
 
 # Node parameter names
 ND_OOB_PROGRAM = "oob_program"
 ND_SPINDLE_COUNT = "spindle_count"
+ND_EXCLUSIVE_STORAGE = "exclusive_storage"
 
 NDS_PARAMETER_TYPES = {
   ND_OOB_PROGRAM: VTYPE_STRING,
   ND_SPINDLE_COUNT: VTYPE_INT,
+  ND_EXCLUSIVE_STORAGE: VTYPE_BOOL,
   }
 
 NDS_PARAMETERS = frozenset(NDS_PARAMETER_TYPES.keys())
@@ -953,6 +1208,7 @@ NDS_PARAMETERS = frozenset(NDS_PARAMETER_TYPES.keys())
 NDS_PARAMETER_TITLES = {
   ND_OOB_PROGRAM: "OutOfBandProgram",
   ND_SPINDLE_COUNT: "SpindleCount",
+  ND_EXCLUSIVE_STORAGE: "ExclusiveStorage",
   }
 
 # Logical Disks parameters
@@ -963,6 +1219,7 @@ LDP_NO_META_FLUSH = "disable-meta-flush"
 LDP_DEFAULT_METAVG = "default-metavg"
 LDP_DISK_CUSTOM = "disk-custom"
 LDP_NET_CUSTOM = "net-custom"
+LDP_PROTOCOL = "protocol"
 LDP_DYNAMIC_RESYNC = "dynamic-resync"
 LDP_PLAN_AHEAD = "c-plan-ahead"
 LDP_FILL_TARGET = "c-fill-target"
@@ -978,6 +1235,7 @@ DISK_LD_TYPES = {
   LDP_DEFAULT_METAVG: VTYPE_STRING,
   LDP_DISK_CUSTOM: VTYPE_STRING,
   LDP_NET_CUSTOM: VTYPE_STRING,
+  LDP_PROTOCOL: VTYPE_STRING,
   LDP_DYNAMIC_RESYNC: VTYPE_BOOL,
   LDP_PLAN_AHEAD: VTYPE_INT,
   LDP_FILL_TARGET: VTYPE_INT,
@@ -998,6 +1256,7 @@ DRBD_META_BARRIERS = "meta-barriers"
 DRBD_DEFAULT_METAVG = "metavg"
 DRBD_DISK_CUSTOM = "disk-custom"
 DRBD_NET_CUSTOM = "net-custom"
+DRBD_PROTOCOL = "protocol"
 DRBD_DYNAMIC_RESYNC = "dynamic-resync"
 DRBD_PLAN_AHEAD = "c-plan-ahead"
 DRBD_FILL_TARGET = "c-fill-target"
@@ -1015,6 +1274,7 @@ DISK_DT_TYPES = {
   DRBD_DEFAULT_METAVG: VTYPE_STRING,
   DRBD_DISK_CUSTOM: VTYPE_STRING,
   DRBD_NET_CUSTOM: VTYPE_STRING,
+  DRBD_PROTOCOL: VTYPE_STRING,
   DRBD_DYNAMIC_RESYNC: VTYPE_BOOL,
   DRBD_PLAN_AHEAD: VTYPE_INT,
   DRBD_FILL_TARGET: VTYPE_INT,
@@ -1034,7 +1294,7 @@ OOB_POWER_CYCLE = "power-cycle"
 OOB_POWER_STATUS = "power-status"
 OOB_HEALTH = "health"
 
-OOB_COMMANDS = frozenset([
+OOB_COMMANDS = compat.UniqueFrozenset([
   OOB_POWER_ON,
   OOB_POWER_OFF,
   OOB_POWER_CYCLE,
@@ -1052,7 +1312,7 @@ OOB_STATUS_WARNING = "WARNING"
 OOB_STATUS_CRITICAL = "CRITICAL"
 OOB_STATUS_UNKNOWN = "UNKNOWN"
 
-OOB_STATUSES = frozenset([
+OOB_STATUSES = compat.UniqueFrozenset([
   OOB_STATUS_OK,
   OOB_STATUS_WARNING,
   OOB_STATUS_CRITICAL,
@@ -1071,18 +1331,15 @@ NIC_MODE_ROUTED = "routed"
 NIC_MODE_OVS = "openvswitch"
 NIC_IP_POOL = "pool"
 
-NIC_VALID_MODES = frozenset([NIC_MODE_BRIDGED, NIC_MODE_ROUTED, NIC_MODE_OVS])
+NIC_VALID_MODES = compat.UniqueFrozenset([
+  NIC_MODE_BRIDGED,
+  NIC_MODE_ROUTED,
+  NIC_MODE_OVS,
+  ])
 
 RESERVE_ACTION = "reserve"
 RELEASE_ACTION = "release"
 
-# An extra description of the network.
-# Can be used by hooks/kvm-vif-bridge to apply different rules
-NETWORK_TYPE_PRIVATE = "private"
-NETWORK_TYPE_PUBLIC = "public"
-
-NETWORK_VALID_TYPES = frozenset([NETWORK_TYPE_PRIVATE, NETWORK_TYPE_PUBLIC])
-
 NICS_PARAMETER_TYPES = {
   NIC_MODE: VTYPE_STRING,
   NIC_LINK: VTYPE_STRING,
@@ -1092,16 +1349,22 @@ NICS_PARAMETERS = frozenset(NICS_PARAMETER_TYPES.keys())
 
 # IDISK_* constants are used in opcodes, to create/change disks
 IDISK_SIZE = "size"
+IDISK_SPINDLES = "spindles"
 IDISK_MODE = "mode"
 IDISK_ADOPT = "adopt"
 IDISK_VG = "vg"
 IDISK_METAVG = "metavg"
+IDISK_PROVIDER = "provider"
+IDISK_NAME = "name"
 IDISK_PARAMS_TYPES = {
   IDISK_SIZE: VTYPE_SIZE,
+  IDISK_SPINDLES: VTYPE_INT,
   IDISK_MODE: VTYPE_STRING,
   IDISK_ADOPT: VTYPE_STRING,
   IDISK_VG: VTYPE_STRING,
   IDISK_METAVG: VTYPE_STRING,
+  IDISK_PROVIDER: VTYPE_STRING,
+  IDISK_NAME: VTYPE_MAYBE_STRING,
   }
 IDISK_PARAMS = frozenset(IDISK_PARAMS_TYPES.keys())
 
@@ -1111,12 +1374,14 @@ INIC_IP = "ip"
 INIC_MODE = "mode"
 INIC_LINK = "link"
 INIC_NETWORK = "network"
+INIC_NAME = "name"
 INIC_PARAMS_TYPES = {
   INIC_IP: VTYPE_MAYBE_STRING,
   INIC_LINK: VTYPE_STRING,
   INIC_MAC: VTYPE_STRING,
   INIC_MODE: VTYPE_STRING,
   INIC_NETWORK: VTYPE_MAYBE_STRING,
+  INIC_NAME: VTYPE_MAYBE_STRING,
   }
 INIC_PARAMS = frozenset(INIC_PARAMS_TYPES.keys())
 
@@ -1127,7 +1392,7 @@ HT_XEN_HVM = "xen-hvm"
 HT_KVM = "kvm"
 HT_CHROOT = "chroot"
 HT_LXC = "lxc"
-HYPER_TYPES = frozenset([
+HYPER_TYPES = compat.UniqueFrozenset([
   HT_XEN_PVM,
   HT_FAKE,
   HT_XEN_HVM,
@@ -1135,7 +1400,7 @@ HYPER_TYPES = frozenset([
   HT_CHROOT,
   HT_LXC,
   ])
-HTS_REQ_PORT = frozenset([HT_XEN_HVM, HT_KVM])
+HTS_REQ_PORT = compat.UniqueFrozenset([HT_XEN_HVM, HT_KVM])
 
 VNC_BASE_PORT = 5900
 VNC_DEFAULT_BIND_ADDRESS = IP4_ADDRESS_ANY
@@ -1151,14 +1416,14 @@ HT_NIC_PCNET = "pcnet"
 HT_NIC_E1000 = "e1000"
 HT_NIC_PARAVIRTUAL = HT_DISK_PARAVIRTUAL = "paravirtual"
 
-HT_HVM_VALID_NIC_TYPES = frozenset([
+HT_HVM_VALID_NIC_TYPES = compat.UniqueFrozenset([
   HT_NIC_RTL8139,
   HT_NIC_NE2K_PCI,
   HT_NIC_E1000,
   HT_NIC_NE2K_ISA,
   HT_NIC_PARAVIRTUAL,
   ])
-HT_KVM_VALID_NIC_TYPES = frozenset([
+HT_KVM_VALID_NIC_TYPES = compat.UniqueFrozenset([
   HT_NIC_RTL8139,
   HT_NIC_NE2K_PCI,
   HT_NIC_NE2K_ISA,
@@ -1170,6 +1435,15 @@ HT_KVM_VALID_NIC_TYPES = frozenset([
   HT_NIC_PARAVIRTUAL,
   ])
 
+# Vif types
+# default vif type in xen-hvm
+HT_HVM_VIF_IOEMU = "ioemu"
+HT_HVM_VIF_VIF = "vif"
+HT_HVM_VALID_VIF_TYPES = compat.UniqueFrozenset([
+  HT_HVM_VIF_IOEMU,
+  HT_HVM_VIF_VIF,
+  ])
+
 # Disk types
 HT_DISK_IOEMU = "ioemu"
 HT_DISK_IDE = "ide"
@@ -1182,15 +1456,18 @@ HT_CACHE_DEFAULT = "default"
 HT_CACHE_NONE = "none"
 HT_CACHE_WTHROUGH = "writethrough"
 HT_CACHE_WBACK = "writeback"
-HT_VALID_CACHE_TYPES = frozenset([
+HT_VALID_CACHE_TYPES = compat.UniqueFrozenset([
   HT_CACHE_DEFAULT,
   HT_CACHE_NONE,
   HT_CACHE_WTHROUGH,
   HT_CACHE_WBACK,
   ])
 
-HT_HVM_VALID_DISK_TYPES = frozenset([HT_DISK_PARAVIRTUAL, HT_DISK_IOEMU])
-HT_KVM_VALID_DISK_TYPES = frozenset([
+HT_HVM_VALID_DISK_TYPES = compat.UniqueFrozenset([
+  HT_DISK_PARAVIRTUAL,
+  HT_DISK_IOEMU,
+  ])
+HT_KVM_VALID_DISK_TYPES = compat.UniqueFrozenset([
   HT_DISK_PARAVIRTUAL,
   HT_DISK_IDE,
   HT_DISK_SCSI,
@@ -1203,7 +1480,10 @@ HT_KVM_VALID_DISK_TYPES = frozenset([
 HT_MOUSE_MOUSE = "mouse"
 HT_MOUSE_TABLET = "tablet"
 
-HT_KVM_VALID_MOUSE_TYPES = frozenset([HT_MOUSE_MOUSE, HT_MOUSE_TABLET])
+HT_KVM_VALID_MOUSE_TYPES = compat.UniqueFrozenset([
+  HT_MOUSE_MOUSE,
+  HT_MOUSE_TABLET,
+  ])
 
 # Boot order
 HT_BO_FLOPPY = "floppy"
@@ -1211,7 +1491,7 @@ HT_BO_CDROM = "cdrom"
 HT_BO_DISK = "disk"
 HT_BO_NETWORK = "network"
 
-HT_KVM_VALID_BO_TYPES = frozenset([
+HT_KVM_VALID_BO_TYPES = compat.UniqueFrozenset([
   HT_BO_FLOPPY,
   HT_BO_CDROM,
   HT_BO_DISK,
@@ -1226,7 +1506,7 @@ HT_KVM_SPICE_LOSSLESS_IMG_COMPR_GLZ = "glz"
 HT_KVM_SPICE_LOSSLESS_IMG_COMPR_LZ = "lz"
 HT_KVM_SPICE_LOSSLESS_IMG_COMPR_OFF = "off"
 
-HT_KVM_SPICE_VALID_LOSSLESS_IMG_COMPR_OPTIONS = frozenset([
+HT_KVM_SPICE_VALID_LOSSLESS_IMG_COMPR_OPTIONS = compat.UniqueFrozenset([
   HT_KVM_SPICE_LOSSLESS_IMG_COMPR_AUTO_GLZ,
   HT_KVM_SPICE_LOSSLESS_IMG_COMPR_AUTO_LZ,
   HT_KVM_SPICE_LOSSLESS_IMG_COMPR_QUIC,
@@ -1240,7 +1520,7 @@ HT_KVM_SPICE_LOSSY_IMG_COMPR_AUTO = "auto"
 HT_KVM_SPICE_LOSSY_IMG_COMPR_NEVER = "never"
 HT_KVM_SPICE_LOSSY_IMG_COMPR_ALWAYS = "always"
 
-HT_KVM_SPICE_VALID_LOSSY_IMG_COMPR_OPTIONS = frozenset([
+HT_KVM_SPICE_VALID_LOSSY_IMG_COMPR_OPTIONS = compat.UniqueFrozenset([
   HT_KVM_SPICE_LOSSY_IMG_COMPR_AUTO,
   HT_KVM_SPICE_LOSSY_IMG_COMPR_NEVER,
   HT_KVM_SPICE_LOSSY_IMG_COMPR_ALWAYS,
@@ -1251,7 +1531,7 @@ HT_KVM_SPICE_VIDEO_STREAM_DETECTION_OFF = "off"
 HT_KVM_SPICE_VIDEO_STREAM_DETECTION_ALL = "all"
 HT_KVM_SPICE_VIDEO_STREAM_DETECTION_FILTER = "filter"
 
-HT_KVM_SPICE_VALID_VIDEO_STREAM_DETECTION_OPTIONS = frozenset([
+HT_KVM_SPICE_VALID_VIDEO_STREAM_DETECTION_OPTIONS = compat.UniqueFrozenset([
   HT_KVM_SPICE_VIDEO_STREAM_DETECTION_OFF,
   HT_KVM_SPICE_VIDEO_STREAM_DETECTION_ALL,
   HT_KVM_SPICE_VIDEO_STREAM_DETECTION_FILTER,
@@ -1262,25 +1542,33 @@ HT_SM_NONE = "none"
 HT_SM_USER = "user"
 HT_SM_POOL = "pool"
 
-HT_KVM_VALID_SM_TYPES = frozenset([HT_SM_NONE, HT_SM_USER, HT_SM_POOL])
+HT_KVM_VALID_SM_TYPES = compat.UniqueFrozenset([
+  HT_SM_NONE,
+  HT_SM_USER,
+  HT_SM_POOL,
+  ])
 
 # Kvm flag values
 HT_KVM_ENABLED = "enabled"
 HT_KVM_DISABLED = "disabled"
 
-HT_KVM_FLAG_VALUES = frozenset([HT_KVM_ENABLED, HT_KVM_DISABLED])
+HT_KVM_FLAG_VALUES = compat.UniqueFrozenset([HT_KVM_ENABLED, HT_KVM_DISABLED])
 
 # Migration type
 HT_MIGRATION_LIVE = "live"
 HT_MIGRATION_NONLIVE = "non-live"
-HT_MIGRATION_MODES = frozenset([HT_MIGRATION_LIVE, HT_MIGRATION_NONLIVE])
+HT_MIGRATION_MODES = compat.UniqueFrozenset([
+  HT_MIGRATION_LIVE,
+  HT_MIGRATION_NONLIVE,
+  ])
 
 # Cluster Verify steps
 VERIFY_NPLUSONE_MEM = "nplusone_mem"
-VERIFY_OPTIONAL_CHECKS = frozenset([VERIFY_NPLUSONE_MEM])
+VERIFY_OPTIONAL_CHECKS = compat.UniqueFrozenset([VERIFY_NPLUSONE_MEM])
 
 # Cluster Verify error classes
 CV_TCLUSTER = "cluster"
+CV_TGROUP = "group"
 CV_TNODE = "node"
 CV_TINSTANCE = "instance"
 
@@ -1299,6 +1587,8 @@ CV_ECLUSTERDANGLINGNODES = \
 CV_ECLUSTERDANGLINGINST = \
   (CV_TNODE, "ECLUSTERDANGLINGINST",
    "Some instances have a non-existing primary node")
+CV_EGROUPDIFFERENTPVSIZE = \
+  (CV_TGROUP, "EGROUPDIFFERENTPVSIZE", "PVs in the group have different sizes")
 CV_EINSTANCEBADNODE = \
   (CV_TINSTANCE, "EINSTANCEBADNODE",
    "Instance marked as running lives on an offline node")
@@ -1319,8 +1609,16 @@ CV_EINSTANCESPLITGROUPS = \
 CV_EINSTANCEPOLICY = \
   (CV_TINSTANCE, "EINSTANCEPOLICY",
    "Instance does not meet policy")
+CV_EINSTANCEUNSUITABLENODE = \
+  (CV_TINSTANCE, "EINSTANCEUNSUITABLENODE",
+   "Instance running on nodes that are not suitable for it")
+CV_EINSTANCEMISSINGCFGPARAMETER = \
+  (CV_TINSTANCE, "EINSTANCEMISSINGCFGPARAMETER",
+   "A configuration parameter for an instance is missing")
 CV_ENODEDRBD = \
   (CV_TNODE, "ENODEDRBD", "Error parsing the DRBD status file")
+CV_ENODEDRBDVERSION = \
+  (CV_TNODE, "ENODEDRBDVERSION", "DRBD version mismatch within a node group")
 CV_ENODEDRBDHELPER = \
   (CV_TNODE, "ENODEDRBDHELPER", "Error caused by the DRBD helper")
 CV_ENODEFILECHECK = \
@@ -1360,8 +1658,10 @@ CV_ENODEUSERSCRIPTS = \
   (CV_TNODE, "ENODEUSERSCRIPTS", "User scripts not present or not executable")
 CV_ENODEFILESTORAGEPATHS = \
   (CV_TNODE, "ENODEFILESTORAGEPATHS", "Detected bad file storage paths")
+CV_ENODEFILESTORAGEPATHUNUSABLE = \
+  (CV_TNODE, "ENODEFILESTORAGEPATHUNUSABLE", "File storage path unusable")
 
-CV_ALL_ECODES = frozenset([
+CV_ALL_ECODES = compat.UniqueFrozenset([
   CV_ECLUSTERCFG,
   CV_ECLUSTERCERT,
   CV_ECLUSTERFILECHECK,
@@ -1394,33 +1694,39 @@ CV_ALL_ECODES = frozenset([
   CV_ENODEOOBPATH,
   CV_ENODEUSERSCRIPTS,
   CV_ENODEFILESTORAGEPATHS,
+  CV_ENODEFILESTORAGEPATHUNUSABLE,
   ])
 
-CV_ALL_ECODES_STRINGS = frozenset(estr for (_, estr, _) in CV_ALL_ECODES)
+CV_ALL_ECODES_STRINGS = \
+  compat.UniqueFrozenset(estr for (_, estr, _) in CV_ALL_ECODES)
 
 # Node verify constants
+NV_BRIDGES = "bridges"
 NV_DRBDHELPER = "drbd-helper"
+NV_DRBDVERSION = "drbd-version"
 NV_DRBDLIST = "drbd-list"
+NV_EXCLUSIVEPVS = "exclusive-pvs"
 NV_FILELIST = "filelist"
+NV_ACCEPTED_STORAGE_PATHS = "allowed-file-storage-paths"
+NV_FILE_STORAGE_PATH = "file-storage-path"
+NV_SHARED_FILE_STORAGE_PATH = "shared-file-storage-path"
 NV_HVINFO = "hvinfo"
-NV_HYPERVISOR = "hypervisor"
 NV_HVPARAMS = "hvparms"
+NV_HYPERVISOR = "hypervisor"
 NV_INSTANCELIST = "instancelist"
 NV_LVLIST = "lvlist"
 NV_MASTERIP = "master-ip"
 NV_NODELIST = "nodelist"
 NV_NODENETTEST = "node-net-test"
 NV_NODESETUP = "nodesetup"
+NV_OOB_PATHS = "oob-paths"
 NV_OSLIST = "oslist"
 NV_PVLIST = "pvlist"
 NV_TIME = "time"
+NV_USERSCRIPTS = "user-scripts"
 NV_VERSION = "version"
 NV_VGLIST = "vglist"
 NV_VMNODES = "vmnodes"
-NV_OOB_PATHS = "oob-paths"
-NV_BRIDGES = "bridges"
-NV_USERSCRIPTS = "user-scripts"
-NV_FILE_STORAGE_PATHS = "file-storage-paths"
 
 # Instance status
 INSTST_RUNNING = "running"
@@ -1431,7 +1737,7 @@ INSTST_NODEDOWN = "ERROR_nodedown"
 INSTST_WRONGNODE = "ERROR_wrongnode"
 INSTST_ERRORUP = "ERROR_up"
 INSTST_ERRORDOWN = "ERROR_down"
-INSTST_ALL = frozenset([
+INSTST_ALL = compat.UniqueFrozenset([
   INSTST_RUNNING,
   INSTST_ADMINDOWN,
   INSTST_ADMINOFFLINE,
@@ -1446,7 +1752,7 @@ INSTST_ALL = frozenset([
 ADMINST_UP = "up"
 ADMINST_DOWN = "down"
 ADMINST_OFFLINE = "offline"
-ADMINST_ALL = frozenset([
+ADMINST_ALL = compat.UniqueFrozenset([
   ADMINST_UP,
   ADMINST_DOWN,
   ADMINST_OFFLINE,
@@ -1458,7 +1764,7 @@ NR_MASTER = "M"
 NR_MCANDIDATE = "C"
 NR_DRAINED = "D"
 NR_OFFLINE = "O"
-NR_ALL = frozenset([
+NR_ALL = compat.UniqueFrozenset([
   NR_REGULAR,
   NR_MASTER,
   NR_MCANDIDATE,
@@ -1474,7 +1780,7 @@ SSL_CERT_EXPIRATION_ERROR = 7
 IALLOCATOR_VERSION = 2
 IALLOCATOR_DIR_IN = "in"
 IALLOCATOR_DIR_OUT = "out"
-VALID_IALLOCATOR_DIRECTIONS = frozenset([
+VALID_IALLOCATOR_DIRECTIONS = compat.UniqueFrozenset([
   IALLOCATOR_DIR_IN,
   IALLOCATOR_DIR_OUT,
   ])
@@ -1483,7 +1789,7 @@ IALLOCATOR_MODE_RELOC = "relocate"
 IALLOCATOR_MODE_CHG_GROUP = "change-group"
 IALLOCATOR_MODE_NODE_EVAC = "node-evacuate"
 IALLOCATOR_MODE_MULTI_ALLOC = "multi-allocate"
-VALID_IALLOCATOR_MODES = frozenset([
+VALID_IALLOCATOR_MODES = compat.UniqueFrozenset([
   IALLOCATOR_MODE_ALLOC,
   IALLOCATOR_MODE_RELOC,
   IALLOCATOR_MODE_CHG_GROUP,
@@ -1496,7 +1802,7 @@ DEFAULT_IALLOCATOR_SHORTCUT = "."
 IALLOCATOR_NEVAC_PRI = "primary-only"
 IALLOCATOR_NEVAC_SEC = "secondary-only"
 IALLOCATOR_NEVAC_ALL = "all"
-IALLOCATOR_NEVAC_MODES = frozenset([
+IALLOCATOR_NEVAC_MODES = compat.UniqueFrozenset([
   IALLOCATOR_NEVAC_PRI,
   IALLOCATOR_NEVAC_SEC,
   IALLOCATOR_NEVAC_ALL,
@@ -1506,7 +1812,7 @@ IALLOCATOR_NEVAC_MODES = frozenset([
 NODE_EVAC_PRI = "primary-only"
 NODE_EVAC_SEC = "secondary-only"
 NODE_EVAC_ALL = "all"
-NODE_EVAC_MODES = frozenset([
+NODE_EVAC_MODES = compat.UniqueFrozenset([
   NODE_EVAC_PRI,
   NODE_EVAC_SEC,
   NODE_EVAC_ALL,
@@ -1515,6 +1821,7 @@ NODE_EVAC_MODES = frozenset([
 # Job queue
 JOB_QUEUE_VERSION = 1
 JOB_QUEUE_SIZE_HARD_LIMIT = 5000
+JOB_QUEUE_FILES_PERMS = 0640
 
 JOB_ID_TEMPLATE = r"\d+"
 JOB_FILE_RE = re.compile(r"^job-(%s)$" % JOB_ID_TEMPLATE)
@@ -1530,17 +1837,17 @@ JOB_STATUS_RUNNING = "running"
 JOB_STATUS_CANCELED = "canceled"
 JOB_STATUS_SUCCESS = "success"
 JOB_STATUS_ERROR = "error"
-JOBS_PENDING = frozenset([
+JOBS_PENDING = compat.UniqueFrozenset([
   JOB_STATUS_QUEUED,
   JOB_STATUS_WAITING,
   JOB_STATUS_CANCELING,
   ])
-JOBS_FINALIZED = frozenset([
+JOBS_FINALIZED = compat.UniqueFrozenset([
   JOB_STATUS_CANCELED,
   JOB_STATUS_SUCCESS,
   JOB_STATUS_ERROR,
   ])
-JOB_STATUS_ALL = frozenset([
+JOB_STATUS_ALL = compat.UniqueFrozenset([
   JOB_STATUS_RUNNING,
   ]) | JOBS_PENDING | JOBS_FINALIZED
 
@@ -1554,7 +1861,7 @@ OP_STATUS_RUNNING = "running"
 OP_STATUS_CANCELED = "canceled"
 OP_STATUS_SUCCESS = "success"
 OP_STATUS_ERROR = "error"
-OPS_FINALIZED = frozenset([
+OPS_FINALIZED = compat.UniqueFrozenset([
   OP_STATUS_CANCELED,
   OP_STATUS_SUCCESS,
   OP_STATUS_ERROR,
@@ -1568,7 +1875,7 @@ OP_PRIO_LOW = +10
 OP_PRIO_NORMAL = 0
 OP_PRIO_HIGH = -10
 
-OP_PRIO_SUBMIT_VALID = frozenset([
+OP_PRIO_SUBMIT_VALID = compat.UniqueFrozenset([
   OP_PRIO_LOW,
   OP_PRIO_NORMAL,
   OP_PRIO_HIGH,
@@ -1604,7 +1911,7 @@ JQT_EXPANDNAMES = "expandnames"
 JQT_EXEC = "exec"
 JQT_LOGMSG = "logmsg"
 JQT_STARTMSG = "startmsg"
-JQT_ALL = frozenset([
+JQT_ALL = compat.UniqueFrozenset([
   JQT_EXPANDNAMES,
   JQT_EXEC,
   JQT_LOGMSG,
@@ -1621,9 +1928,10 @@ QR_OS = "os"
 QR_JOB = "job"
 QR_EXPORT = "export"
 QR_NETWORK = "network"
+QR_EXTSTORAGE = "extstorage"
 
 #: List of resources which can be queried using L{opcodes.OpQuery}
-QR_VIA_OP = frozenset([
+QR_VIA_OP = compat.UniqueFrozenset([
   QR_CLUSTER,
   QR_INSTANCE,
   QR_NODE,
@@ -1631,6 +1939,7 @@ QR_VIA_OP = frozenset([
   QR_OS,
   QR_EXPORT,
   QR_NETWORK,
+  QR_EXTSTORAGE,
   ])
 
 #: List of resources which can be queried using Local UniX Interface
@@ -1652,7 +1961,7 @@ QFT_TIMESTAMP = "timestamp"
 QFT_OTHER = "other"
 
 #: All query field types
-QFT_ALL = frozenset([
+QFT_ALL = compat.UniqueFrozenset([
   QFT_UNKNOWN,
   QFT_TEXT,
   QFT_BOOL,
@@ -1677,7 +1986,7 @@ RS_UNAVAIL = 3
 #: Resource marked offline
 RS_OFFLINE = 4
 
-RS_ALL = frozenset([
+RS_ALL = compat.UniqueFrozenset([
   RS_NORMAL,
   RS_UNKNOWN,
   RS_NODATA,
@@ -1724,6 +2033,26 @@ SS_UID_POOL = "uid_pool"
 SS_NODEGROUPS = "nodegroups"
 SS_NETWORKS = "networks"
 
+# This is not a complete SSCONF key, but the prefix for the hypervisor keys
+SS_HVPARAMS_PREF = "hvparams_"
+
+# Hvparams keys:
+SS_HVPARAMS_XEN_PVM = SS_HVPARAMS_PREF + HT_XEN_PVM
+SS_HVPARAMS_XEN_FAKE = SS_HVPARAMS_PREF + HT_FAKE
+SS_HVPARAMS_XEN_HVM = SS_HVPARAMS_PREF + HT_XEN_HVM
+SS_HVPARAMS_XEN_KVM = SS_HVPARAMS_PREF + HT_KVM
+SS_HVPARAMS_XEN_CHROOT = SS_HVPARAMS_PREF + HT_CHROOT
+SS_HVPARAMS_XEN_LXC = SS_HVPARAMS_PREF + HT_LXC
+
+VALID_SS_HVPARAMS_KEYS = compat.UniqueFrozenset([
+  SS_HVPARAMS_XEN_PVM,
+  SS_HVPARAMS_XEN_FAKE,
+  SS_HVPARAMS_XEN_HVM,
+  SS_HVPARAMS_XEN_KVM,
+  SS_HVPARAMS_XEN_CHROOT,
+  SS_HVPARAMS_XEN_LXC,
+  ])
+
 SS_FILE_PERMS = 0444
 
 # cluster wide default parameters
@@ -1736,7 +2065,7 @@ HVC_DEFAULTS = {
     HV_BOOTLOADER_ARGS: "",
     HV_KERNEL_PATH: XEN_KERNEL,
     HV_INITRD_PATH: "",
-    HV_ROOT_PATH: "/dev/sda1",
+    HV_ROOT_PATH: "/dev/xvda1",
     HV_KERNEL_ARGS: "ro",
     HV_MIGRATION_PORT: 8002,
     HV_MIGRATION_MODE: HT_MIGRATION_LIVE,
@@ -1745,6 +2074,8 @@ HVC_DEFAULTS = {
     HV_CPU_MASK: CPU_PINNING_ALL,
     HV_CPU_CAP: 0,
     HV_CPU_WEIGHT: 256,
+    HV_VIF_SCRIPT: "",
+    HV_XEN_CMD: XEN_CMD_XM,
     },
   HT_XEN_HVM: {
     HV_BOOT_ORDER: "cd",
@@ -1766,14 +2097,19 @@ HVC_DEFAULTS = {
     HV_CPU_MASK: CPU_PINNING_ALL,
     HV_CPU_CAP: 0,
     HV_CPU_WEIGHT: 256,
+    HV_VIF_TYPE: HT_HVM_VIF_IOEMU,
+    HV_VIF_SCRIPT: "",
+    HV_XEN_CMD: XEN_CMD_XM,
     },
   HT_KVM: {
+    HV_KVM_PATH: KVM_PATH,
     HV_KERNEL_PATH: KVM_KERNEL,
     HV_INITRD_PATH: "",
     HV_KERNEL_ARGS: "ro",
     HV_ROOT_PATH: "/dev/vda1",
     HV_ACPI: True,
     HV_SERIAL_CONSOLE: True,
+    HV_SERIAL_SPEED: 38400,
     HV_VNC_BIND_ADDRESS: "",
     HV_VNC_TLS: False,
     HV_VNC_X509: "",
@@ -1814,8 +2150,19 @@ HVC_DEFAULTS = {
     HV_REBOOT_BEHAVIOR: INSTANCE_REBOOT_ALLOWED,
     HV_CPU_MASK: CPU_PINNING_ALL,
     HV_CPU_TYPE: "",
+    HV_CPU_CORES: 0,
+    HV_CPU_THREADS: 0,
+    HV_CPU_SOCKETS: 0,
+    HV_SOUNDHW: "",
+    HV_USB_DEVICES: "",
+    HV_VGA: "",
+    HV_KVM_EXTRA: "",
+    HV_KVM_MACHINE_VERSION: "",
+    HV_VNET_HDR: True,
     },
-  HT_FAKE: {},
+  HT_FAKE: {
+    HV_MIGRATION_MODE: HT_MIGRATION_LIVE,
+  },
   HT_CHROOT: {
     HV_INIT_SCRIPT: "/ganeti-chroot",
     },
@@ -1824,10 +2171,11 @@ HVC_DEFAULTS = {
     },
   }
 
-HVC_GLOBALS = frozenset([
+HVC_GLOBALS = compat.UniqueFrozenset([
   HV_MIGRATION_PORT,
   HV_MIGRATION_BANDWIDTH,
   HV_MIGRATION_MODE,
+  HV_XEN_CMD,
   ])
 
 BEC_DEFAULTS = {
@@ -1842,8 +2190,13 @@ BEC_DEFAULTS = {
 NDC_DEFAULTS = {
   ND_OOB_PROGRAM: "",
   ND_SPINDLE_COUNT: 1,
+  ND_EXCLUSIVE_STORAGE: False,
   }
 
+NDC_GLOBALS = compat.UniqueFrozenset([
+  ND_EXCLUSIVE_STORAGE,
+  ])
+
 DISK_LD_DEFAULTS = {
   LD_DRBD8: {
     LDP_RESYNC_RATE: CLASSIC_DRBD_SYNC_SPEED,
@@ -1852,13 +2205,14 @@ DISK_LD_DEFAULTS = {
     LDP_DEFAULT_METAVG: DEFAULT_VG,
     LDP_DISK_CUSTOM: "",
     LDP_NET_CUSTOM: "",
+    LDP_PROTOCOL: DRBD_DEFAULT_NET_PROTOCOL,
     LDP_DYNAMIC_RESYNC: False,
 
-    # The default values for the DRBD dynamic resync speed algorithm are taken
-    # from the drbsetup 8.3.11 man page, except for c-plan-ahead (that we
-    # don't need to set to 0, because we have a separate option to enable it)
-    # and for c-max-rate, that we cap to the default value for the static resync
-    # rate.
+    # The default values for the DRBD dynamic resync speed algorithm
+    # are taken from the drbsetup 8.3.11 man page, except for
+    # c-plan-ahead (that we don't need to set to 0, because we have a
+    # separate option to enable it) and for c-max-rate, that we cap to
+    # the default value for the static resync rate.
     LDP_PLAN_AHEAD: 20, # ds
     LDP_FILL_TARGET: 0, # sectors
     LDP_DELAY_TARGET: 1, # ds
@@ -1873,6 +2227,7 @@ DISK_LD_DEFAULTS = {
   LD_RBD: {
     LDP_POOL: "rbd"
     },
+  LD_EXT: {},
   }
 
 # readability shortcuts
@@ -1892,6 +2247,7 @@ DISK_DT_DEFAULTS = {
     DRBD_DEFAULT_METAVG: _DRBD_DEFAULTS[LDP_DEFAULT_METAVG],
     DRBD_DISK_CUSTOM: _DRBD_DEFAULTS[LDP_DISK_CUSTOM],
     DRBD_NET_CUSTOM: _DRBD_DEFAULTS[LDP_NET_CUSTOM],
+    DRBD_PROTOCOL: _DRBD_DEFAULTS[LDP_PROTOCOL],
     DRBD_DYNAMIC_RESYNC: _DRBD_DEFAULTS[LDP_DYNAMIC_RESYNC],
     DRBD_PLAN_AHEAD: _DRBD_DEFAULTS[LDP_PLAN_AHEAD],
     DRBD_FILL_TARGET: _DRBD_DEFAULTS[LDP_FILL_TARGET],
@@ -1906,6 +2262,7 @@ DISK_DT_DEFAULTS = {
   DT_RBD: {
     RBD_POOL: DISK_LD_DEFAULTS[LD_RBD][LDP_POOL]
     },
+  DT_EXT: {},
   }
 
 # we don't want to export the shortcuts
@@ -1918,7 +2275,7 @@ NICC_DEFAULTS = {
 
 # All of the following values are quite arbitrarily - there are no
 # "good" defaults, these must be customised per-site
-IPOLICY_DEFAULTS = {
+ISPECS_MINMAX_DEFAULTS = {
   ISPECS_MIN: {
     ISPEC_MEM_SIZE: 128,
     ISPEC_CPU_COUNT: 1,
@@ -1935,6 +2292,9 @@ IPOLICY_DEFAULTS = {
     ISPEC_NIC_COUNT: MAX_NICS,
     ISPEC_SPINDLE_USE: 12,
     },
+  }
+IPOLICY_DEFAULTS = {
+  ISPECS_MINMAX: [ISPECS_MINMAX_DEFAULTS],
   ISPECS_STD: {
     ISPEC_MEM_SIZE: 128,
     ISPEC_CPU_COUNT: 1,
@@ -1943,13 +2303,19 @@ IPOLICY_DEFAULTS = {
     ISPEC_NIC_COUNT: 1,
     ISPEC_SPINDLE_USE: 1,
     },
-  IPOLICY_DTS: DISK_TEMPLATES,
+  IPOLICY_DTS: list(DISK_TEMPLATES),
   IPOLICY_VCPU_RATIO: 4.0,
   IPOLICY_SPINDLE_RATIO: 32.0,
   }
 
 MASTER_POOL_SIZE_DEFAULT = 10
 
+# Exclusive storage:
+# Error margin used to compare physical disks
+PART_MARGIN = .01
+# Space reserved when creating instance disks
+PART_RESERVED = .02
+
 CONFD_PROTOCOL_VERSION = 1
 
 CONFD_REQ_PING = 0
@@ -1960,6 +2326,7 @@ CONFD_REQ_NODE_PIP_LIST = 4
 CONFD_REQ_MC_PIP_LIST = 5
 CONFD_REQ_INSTANCES_IPS_LIST = 6
 CONFD_REQ_NODE_DRBD = 7
+CONFD_REQ_NODE_INSTANCES = 8
 
 # Confd request query fields. These are used to narrow down queries.
 # These must be strings rather than integers, because json-encoding
@@ -1973,7 +2340,7 @@ CONFD_REQFIELD_NAME = "0"
 CONFD_REQFIELD_IP = "1"
 CONFD_REQFIELD_MNODE_PIP = "2"
 
-CONFD_REQS = frozenset([
+CONFD_REQS = compat.UniqueFrozenset([
   CONFD_REQ_PING,
   CONFD_REQ_NODE_ROLE_BYNAME,
   CONFD_REQ_NODE_PIP_BY_INSTANCE_IP,
@@ -1988,7 +2355,7 @@ CONFD_REPL_STATUS_OK = 0
 CONFD_REPL_STATUS_ERROR = 1
 CONFD_REPL_STATUS_NOTIMPLEMENTED = 2
 
-CONFD_REPL_STATUSES = frozenset([
+CONFD_REPL_STATUSES = compat.UniqueFrozenset([
   CONFD_REPL_STATUS_OK,
   CONFD_REPL_STATUS_ERROR,
   CONFD_REPL_STATUS_NOTIMPLEMENTED,
@@ -2011,14 +2378,16 @@ CONFD_ERROR_ARGUMENT = 3
 # TODO: make this a default and allow the value to be more configurable
 CONFD_MAX_CLOCK_SKEW = 2 * NODE_MAX_CLOCK_SKEW
 
-# When we haven't reloaded the config for more than this amount of seconds, we
-# force a test to see if inotify is betraying us.
-CONFD_CONFIG_RELOAD_TIMEOUT = 60
+# When we haven't reloaded the config for more than this amount of
+# seconds, we force a test to see if inotify is betraying us. Using a
+# prime number to ensure we get less chance of 'same wakeup' with
+# other processes.
+CONFD_CONFIG_RELOAD_TIMEOUT = 17
 
-# If we receive more than one update in this amount of seconds, we move to
-# polling every RATELIMIT seconds, rather than relying on inotify, to be able
-# to serve more requests.
-CONFD_CONFIG_RELOAD_RATELIMIT = 2
+# If we receive more than one update in this amount of microseconds,
+# we move to polling every RATELIMIT seconds, rather than relying on
+# inotify, to be able to serve more requests.
+CONFD_CONFIG_RELOAD_RATELIMIT = 250000
 
 # Magic number prepended to all confd queries.
 # This allows us to distinguish different types of confd protocols and handle
@@ -2082,12 +2451,12 @@ FAKE_OP_MASTER_TURNDOWN = "OP_CLUSTER_IP_TURNDOWN"
 # SSH key types
 SSHK_RSA = "rsa"
 SSHK_DSA = "dsa"
-SSHK_ALL = frozenset([SSHK_RSA, SSHK_DSA])
+SSHK_ALL = compat.UniqueFrozenset([SSHK_RSA, SSHK_DSA])
 
 # SSH authorized key types
 SSHAK_RSA = "ssh-rsa"
 SSHAK_DSS = "ssh-dss"
-SSHAK_ALL = frozenset([SSHAK_RSA, SSHAK_DSS])
+SSHAK_ALL = compat.UniqueFrozenset([SSHAK_RSA, SSHAK_DSS])
 
 # SSH setup
 SSHS_CLUSTER_NAME = "cluster_name"
@@ -2107,5 +2476,63 @@ NDS_NODE_DAEMON_CERTIFICATE = "node_daemon_certificate"
 NDS_SSCONF = "ssconf"
 NDS_START_NODE_DAEMON = "start_node_daemon"
 
+# Path generating random UUID
+RANDOM_UUID_FILE = "/proc/sys/kernel/random/uuid"
+
+# Regex string for verifying a UUID
+UUID_REGEX = "^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$"
+
+# Auto-repair tag prefixes
+AUTO_REPAIR_TAG_PREFIX = "ganeti:watcher:autorepair:"
+AUTO_REPAIR_TAG_ENABLED = AUTO_REPAIR_TAG_PREFIX
+AUTO_REPAIR_TAG_SUSPENDED = AUTO_REPAIR_TAG_ENABLED + "suspend:"
+AUTO_REPAIR_TAG_PENDING = AUTO_REPAIR_TAG_PREFIX + "pending:"
+AUTO_REPAIR_TAG_RESULT = AUTO_REPAIR_TAG_PREFIX + "result:"
+
+# Auto-repair levels
+AUTO_REPAIR_FIX_STORAGE = "fix-storage"
+AUTO_REPAIR_MIGRATE = "migrate"
+AUTO_REPAIR_FAILOVER = "failover"
+AUTO_REPAIR_REINSTALL = "reinstall"
+AUTO_REPAIR_ALL_TYPES = [
+  AUTO_REPAIR_FIX_STORAGE,
+  AUTO_REPAIR_MIGRATE,
+  AUTO_REPAIR_FAILOVER,
+  AUTO_REPAIR_REINSTALL,
+]
+
+# Auto-repair results
+AUTO_REPAIR_SUCCESS = "success"
+AUTO_REPAIR_FAILURE = "failure"
+AUTO_REPAIR_ENOPERM = "enoperm"
+AUTO_REPAIR_ALL_RESULTS = frozenset([
+    AUTO_REPAIR_SUCCESS,
+    AUTO_REPAIR_FAILURE,
+    AUTO_REPAIR_ENOPERM,
+])
+
+# The version identifier for builtin data collectors
+BUILTIN_DATA_COLLECTOR_VERSION = "B"
+
+# The reason trail opcode parameter name
+OPCODE_REASON = "reason"
+
+# The source reasons for the execution of an OpCode
+OPCODE_REASON_SRC_CLIENT = "gnt:client"
+OPCODE_REASON_SRC_NODED = "gnt:daemon:noded"
+OPCODE_REASON_SRC_OPCODE = "gnt:opcode"
+OPCODE_REASON_SRC_RLIB2 = "gnt:library:rlib2"
+OPCODE_REASON_SRC_USER = "gnt:user"
+
+OPCODE_REASON_SOURCES = compat.UniqueFrozenset([
+  OPCODE_REASON_SRC_CLIENT,
+  OPCODE_REASON_SRC_NODED,
+  OPCODE_REASON_SRC_OPCODE,
+  OPCODE_REASON_SRC_RLIB2,
+  OPCODE_REASON_SRC_USER,
+  ])
+
+DISKSTATS_FILE = "/proc/diskstats"
+
 # Do not re-export imported modules
-del re, _vcsversion, _autoconf, socket, pathutils
+del re, _vcsversion, _autoconf, socket, pathutils, compat