Add stricter checks for OpInstanceSetParams.{nics,disks}
[ganeti-local] / lib / opcodes.py
index eb6a4de..9f4ab41 100644 (file)
@@ -36,7 +36,6 @@ opcodes.
 import logging
 import re
 
-from ganeti import compat
 from ganeti import constants
 from ganeti import errors
 from ganeti import ht
@@ -156,15 +155,22 @@ _PDiskState = ("disk_state", None, ht.TMaybeDict, "Set disk states")
 _PIgnoreIpolicy = ("ignore_ipolicy", False, ht.TBool,
                    "Whether to ignore ipolicy violations")
 
+# Allow runtime changes while migrating
+_PAllowRuntimeChgs = ("allow_runtime_changes", True, ht.TBool,
+                      "Allow runtime changes (eg. memory ballooning)")
+
+
 #: OP_ID conversion regular expression
 _OPID_RE = re.compile("([a-z])([A-Z])")
 
 #: Utility function for L{OpClusterSetParams}
-_TestClusterOsList = ht.TOr(ht.TNone,
-  ht.TListOf(ht.TAnd(ht.TList, ht.TIsLength(2),
-    ht.TMap(ht.WithDesc("GetFirstItem")(compat.fst),
-            ht.TElemOf(constants.DDMS_VALUES)))))
+_TestClusterOsListItem = \
+  ht.TAnd(ht.TIsLength(2), ht.TItems([
+    ht.TElemOf(constants.DDMS_VALUES),
+    ht.TNonEmptyString,
+    ]))
 
+_TestClusterOsList = ht.TMaybeListOf(_TestClusterOsListItem)
 
 # TODO: Generate check from constants.INIC_PARAMS_TYPES
 #: Utility function for testing NIC definitions
@@ -180,6 +186,11 @@ _TSetParamsResult = \
   ht.TListOf(ht.TAnd(ht.TIsLength(len(_TSetParamsResultItemItems)),
                      ht.TItems(_TSetParamsResultItemItems)))
 
+# TODO: Generate check from constants.IDISK_PARAMS_TYPES (however, not all users
+# of this check support all parameters)
+_TDiskParams = ht.TDictOf(ht.TElemOf(constants.IDISK_PARAMS),
+                          ht.TOr(ht.TNonEmptyString, ht.TInt))
+
 _SUMMARY_PREFIX = {
   "CLUSTER_": "C_",
   "GROUP_": "G_",
@@ -462,7 +473,7 @@ def _BuildJobDepCheck(relative):
             ht.TItems([job_id,
                        ht.TListOf(ht.TElemOf(constants.JOBS_FINALIZED))]))
 
-  return ht.TOr(ht.TNone, ht.TListOf(job_dep))
+  return ht.TMaybeListOf(job_dep)
 
 
 TNoRelativeJobDependencies = _BuildJobDepCheck(False)
@@ -798,7 +809,8 @@ class OpClusterSetParams(OpCode):
      "Whether to wipe disks before allocating them to instances"),
     ("nicparams", None, ht.TMaybeDict, "Cluster-wide NIC parameter defaults"),
     ("ndparams", None, ht.TMaybeDict, "Cluster-wide node parameter defaults"),
-    ("ipolicy", None, ht.TMaybeDict, "Cluster-wide instance policy specs"),
+    ("ipolicy", None, ht.TMaybeDict,
+     "Cluster-wide :ref:`instance policy <rapi-ipolicy>` specs"),
     ("drbd_helper", None, ht.TOr(ht.TString, ht.TNone), "DRBD helper program"),
     ("default_iallocator", None, ht.TOr(ht.TString, ht.TNone),
      "Default iallocator for cluster"),
@@ -806,7 +818,7 @@ class OpClusterSetParams(OpCode):
      "Master network device"),
     ("master_netmask", None, ht.TOr(ht.TInt, ht.TNone),
      "Netmask of the master IP"),
-    ("reserved_lvs", None, ht.TOr(ht.TListOf(ht.TNonEmptyString), ht.TNone),
+    ("reserved_lvs", None, ht.TMaybeListOf(ht.TNonEmptyString),
      "List of reserved LVs"),
     ("hidden_os", None, _TestClusterOsList,
      "Modify list of hidden operating systems. Each modification must have"
@@ -868,7 +880,7 @@ class OpQueryFields(OpCode):
   OP_DSC_FIELD = "what"
   OP_PARAMS = [
     _PQueryWhat,
-    ("fields", None, ht.TOr(ht.TNone, ht.TListOf(ht.TNonEmptyString)),
+    ("fields", None, ht.TMaybeListOf(ht.TNonEmptyString),
      "Requested fields; if not given, all are returned"),
     ]
 
@@ -1046,6 +1058,7 @@ class OpNodeMigrate(OpCode):
     _PMigrationMode,
     _PMigrationLive,
     _PMigrationTargetNode,
+    _PAllowRuntimeChgs,
     _PIgnoreIpolicy,
     ("iallocator", None, ht.TMaybeString,
      "Iallocator for deciding the target node for shared-storage instances"),
@@ -1089,10 +1102,7 @@ class OpInstanceCreate(OpCode):
     _PNameCheck,
     _PIgnoreIpolicy,
     ("beparams", ht.EmptyDict, ht.TDict, "Backend parameters for instance"),
-    ("disks", ht.NoDefault,
-     # TODO: Generate check from constants.IDISK_PARAMS_TYPES
-     ht.TListOf(ht.TDictOf(ht.TElemOf(constants.IDISK_PARAMS),
-                           ht.TOr(ht.TNonEmptyString, ht.TInt))),
+    ("disks", ht.NoDefault, ht.TListOf(_TDiskParams),
      "Disk descriptions, for example ``[{\"%s\": 100}, {\"%s\": 5}]``;"
      " each disk definition must contain a ``%s`` value and"
      " can contain an optional ``%s`` value denoting the disk access mode"
@@ -1224,6 +1234,7 @@ class OpInstanceReplaceDisks(OpCode):
   OP_PARAMS = [
     _PInstanceName,
     _PEarlyRelease,
+    _PIgnoreIpolicy,
     ("mode", ht.NoDefault, ht.TElemOf(constants.REPLACE_MODES),
      "Replacement mode"),
     ("disks", ht.EmptyList, ht.TListOf(ht.TPositiveInt),
@@ -1264,6 +1275,7 @@ class OpInstanceMigrate(OpCode):
     _PMigrationMode,
     _PMigrationLive,
     _PMigrationTargetNode,
+    _PAllowRuntimeChgs,
     _PIgnoreIpolicy,
     ("cleanup", False, ht.TBool,
      "Whether a previously failed migration should be cleaned up"),
@@ -1322,11 +1334,18 @@ class OpInstanceDeactivateDisks(OpCode):
 
 class OpInstanceRecreateDisks(OpCode):
   """Recreate an instance's disks."""
+  _TDiskChanges = \
+    ht.TAnd(ht.TIsLength(2),
+            ht.TItems([ht.Comment("Disk index")(ht.TPositiveInt),
+                       ht.Comment("Parameters")(_TDiskParams)]))
+
   OP_DSC_FIELD = "instance_name"
   OP_PARAMS = [
     _PInstanceName,
-    ("disks", ht.EmptyList, ht.TListOf(ht.TPositiveInt),
-     "List of disk indexes"),
+    ("disks", ht.EmptyList,
+     ht.TOr(ht.TListOf(ht.TPositiveInt), ht.TListOf(_TDiskChanges)),
+     "List of disk indexes (deprecated) or a list of tuples containing a disk"
+     " index and a possibly empty dictionary with disk parameter changes"),
     ("nodes", ht.EmptyList, ht.TListOf(ht.TNonEmptyString),
      "New instance nodes, if relocation is desired"),
     ]
@@ -1354,23 +1373,42 @@ class OpInstanceQueryData(OpCode):
     ]
 
 
+def _TestInstSetParamsModList(fn):
+  """Generates a check for modification lists.
+
+  """
+  mod_item_fn = \
+    ht.TAnd(ht.TIsLength(2), ht.TItems([
+      ht.TOr(ht.TElemOf(constants.DDMS_VALUES), ht.TPositiveInt),
+      fn,
+      ]))
+
+  return ht.TListOf(mod_item_fn)
+
+
 class OpInstanceSetParams(OpCode):
-  """Change the parameters of an instance."""
+  """Change the parameters of an instance.
+
+  """
+  _TestNicModifications = _TestInstSetParamsModList(_TestNicDef)
+  _TestDiskModifications = _TestInstSetParamsModList(_TDiskParams)
+
   OP_DSC_FIELD = "instance_name"
   OP_PARAMS = [
     _PInstanceName,
     _PForce,
     _PForceVariant,
     _PIgnoreIpolicy,
-    # TODO: Use _TestNicDef
-    ("nics", ht.EmptyList, ht.TList,
+    ("nics", ht.EmptyList, _TestNicModifications,
      "List of NIC changes. Each item is of the form ``(op, settings)``."
      " ``op`` can be ``%s`` to add a new NIC with the specified settings,"
      " ``%s`` to remove the last NIC or a number to modify the settings"
      " of the NIC with that index." %
      (constants.DDM_ADD, constants.DDM_REMOVE)),
-    ("disks", ht.EmptyList, ht.TList, "List of disk changes. See ``nics``."),
+    ("disks", ht.EmptyList, _TestDiskModifications,
+     "List of disk changes. See ``nics``."),
     ("beparams", ht.EmptyDict, ht.TDict, "Per-instance backend parameters"),
+    ("runtime_mem", None, ht.TMaybeStrictPositiveInt, "New runtime memory"),
     ("hvparams", ht.EmptyDict, ht.TDict,
      "Per-instance hypervisor parameters, hypervisor-dependent"),
     ("disk_template", None, ht.TOr(ht.TNone, _BuildDiskTemplateCheck(False)),
@@ -1382,10 +1420,7 @@ class OpInstanceSetParams(OpCode):
     ("osparams", None, ht.TMaybeDict, "Per-instance OS parameters"),
     ("wait_for_sync", True, ht.TBool,
      "Whether to wait for the disk to synchronize, when changing template"),
-    ("offline_inst", False, ht.TBool,
-     "Whether to turn off the down instance completely"),
-    ("online_inst", False, ht.TBool,
-     "Whether to enable the offline instance"),
+    ("offline", None, ht.TMaybeBool, "Whether to mark instance as offline"),
     ]
   OP_RESULT = _TSetParamsResult
 
@@ -1409,7 +1444,7 @@ class OpInstanceChangeGroup(OpCode):
     _PInstanceName,
     _PEarlyRelease,
     ("iallocator", None, ht.TMaybeString, "Iallocator for computing solution"),
-    ("target_groups", None, ht.TOr(ht.TNone, ht.TListOf(ht.TNonEmptyString)),
+    ("target_groups", None, ht.TMaybeListOf(ht.TNonEmptyString),
      "Destination group names or UUIDs (defaults to \"all but current group\""),
     ]
   OP_RESULT = TJobIdListOnly
@@ -1427,7 +1462,8 @@ class OpGroupAdd(OpCode):
     _PDiskParams,
     _PHvState,
     _PDiskState,
-    ("ipolicy", None, ht.TMaybeDict, "Group-wide instance policy specs"),
+    ("ipolicy", None, ht.TMaybeDict,
+     "Group-wide :ref:`instance policy <rapi-ipolicy>` specs"),
     ]
 
 
@@ -1490,7 +1526,7 @@ class OpGroupEvacuate(OpCode):
     _PGroupName,
     _PEarlyRelease,
     ("iallocator", None, ht.TMaybeString, "Iallocator for computing solution"),
-    ("target_groups", None, ht.TOr(ht.TNone, ht.TListOf(ht.TNonEmptyString)),
+    ("target_groups", None, ht.TMaybeListOf(ht.TNonEmptyString),
      "Destination group names or UUIDs"),
     ]
   OP_RESULT = TJobIdListOnly
@@ -1664,9 +1700,12 @@ class OpTestAllocator(OpCode):
      ht.TElemOf(constants.VALID_IALLOCATOR_DIRECTIONS), None),
     ("mode", ht.NoDefault, ht.TElemOf(constants.VALID_IALLOCATOR_MODES), None),
     ("name", ht.NoDefault, ht.TNonEmptyString, None),
-    ("nics", ht.NoDefault, ht.TOr(ht.TNone, ht.TListOf(
-     ht.TDictOf(ht.TElemOf([constants.INIC_MAC, constants.INIC_IP, "bridge"]),
-                ht.TOr(ht.TNone, ht.TNonEmptyString)))), None),
+    ("nics", ht.NoDefault,
+     ht.TMaybeListOf(ht.TDictOf(ht.TElemOf([constants.INIC_MAC,
+                                            constants.INIC_IP,
+                                            "bridge"]),
+                                ht.TOr(ht.TNone, ht.TNonEmptyString))),
+     None),
     ("disks", ht.NoDefault, ht.TOr(ht.TNone, ht.TList), None),
     ("hypervisor", None, ht.TMaybeString, None),
     ("allocator", None, ht.TMaybeString, None),
@@ -1675,12 +1714,10 @@ class OpTestAllocator(OpCode):
     ("vcpus", None, ht.TOr(ht.TNone, ht.TPositiveInt), None),
     ("os", None, ht.TMaybeString, None),
     ("disk_template", None, ht.TMaybeString, None),
-    ("instances", None, ht.TOr(ht.TNone, ht.TListOf(ht.TNonEmptyString)),
-     None),
+    ("instances", None, ht.TMaybeListOf(ht.TNonEmptyString), None),
     ("evac_mode", None,
      ht.TOr(ht.TNone, ht.TElemOf(constants.IALLOCATOR_NEVAC_MODES)), None),
-    ("target_groups", None, ht.TOr(ht.TNone, ht.TListOf(ht.TNonEmptyString)),
-     None),
+    ("target_groups", None, ht.TMaybeListOf(ht.TNonEmptyString), None),
     ]