4 # Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Google Inc.
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 This module implements the data structures which define the cluster
25 operations - the so-called opcodes.
27 Every operation which modifies the cluster state is expressed via
32 # this are practically structures, so disable the message about too
34 # pylint: disable=R0903
39 from ganeti import compat
40 from ganeti import constants
41 from ganeti import errors
45 # Common opcode attributes
47 #: output fields for a query operation
48 _POutputFields = ("output_fields", ht.NoDefault, ht.TListOf(ht.TNonEmptyString),
49 "Selected output fields")
51 #: the shutdown timeout
53 ("shutdown_timeout", constants.DEFAULT_SHUTDOWN_TIMEOUT, ht.TPositiveInt,
54 "How long to wait for instance to shut down")
56 #: the force parameter
57 _PForce = ("force", False, ht.TBool, "Whether to force the operation")
59 #: a required instance name (for single-instance LUs)
60 _PInstanceName = ("instance_name", ht.NoDefault, ht.TNonEmptyString,
63 #: Whether to ignore offline nodes
64 _PIgnoreOfflineNodes = ("ignore_offline_nodes", False, ht.TBool,
65 "Whether to ignore offline nodes")
67 #: a required node name (for single-node LUs)
68 _PNodeName = ("node_name", ht.NoDefault, ht.TNonEmptyString, "Node name")
70 #: a required node group name (for single-group LUs)
71 _PGroupName = ("group_name", ht.NoDefault, ht.TNonEmptyString, "Group name")
73 #: Migration type (live/non-live)
74 _PMigrationMode = ("mode", None,
75 ht.TOr(ht.TNone, ht.TElemOf(constants.HT_MIGRATION_MODES)),
78 #: Obsolete 'live' migration mode (boolean)
79 _PMigrationLive = ("live", None, ht.TMaybeBool,
80 "Legacy setting for live migration, do not use")
83 _PTagKind = ("kind", ht.NoDefault, ht.TElemOf(constants.VALID_TAG_TYPES), None)
85 #: List of tag strings
86 _PTags = ("tags", ht.NoDefault, ht.TListOf(ht.TNonEmptyString), None)
88 _PForceVariant = ("force_variant", False, ht.TBool,
89 "Whether to force an unknown OS variant")
91 _PWaitForSync = ("wait_for_sync", True, ht.TBool,
92 "Whether to wait for the disk to synchronize")
94 _PIgnoreConsistency = ("ignore_consistency", False, ht.TBool,
95 "Whether to ignore disk consistency")
97 _PStorageName = ("name", ht.NoDefault, ht.TMaybeString, "Storage name")
99 _PUseLocking = ("use_locking", False, ht.TBool,
100 "Whether to use synchronization")
102 _PNameCheck = ("name_check", True, ht.TBool, "Whether to check name")
104 _PNodeGroupAllocPolicy = \
105 ("alloc_policy", None,
106 ht.TOr(ht.TNone, ht.TElemOf(constants.VALID_ALLOC_POLICIES)),
107 "Instance allocation policy")
109 _PGroupNodeParams = ("ndparams", None, ht.TMaybeDict,
110 "Default node parameters for group")
112 _PQueryWhat = ("what", ht.NoDefault, ht.TElemOf(constants.QR_VIA_OP),
113 "Resource(s) to query for")
115 _PEarlyRelease = ("early_release", False, ht.TBool,
116 "Whether to release locks as soon as possible")
118 _PIpCheckDoc = "Whether to ensure instance's IP address is inactive"
120 #: Do not remember instance state changes
121 _PNoRemember = ("no_remember", False, ht.TBool,
122 "Do not remember the state change")
124 #: Target node for instance migration/failover
125 _PMigrationTargetNode = ("target_node", None, ht.TMaybeString,
126 "Target node for shared-storage instances")
128 _PStartupPaused = ("startup_paused", False, ht.TBool,
129 "Pause instance at startup")
131 _PVerbose = ("verbose", False, ht.TBool, "Verbose mode")
133 # Parameters for cluster verification
134 _PDebugSimulateErrors = ("debug_simulate_errors", False, ht.TBool,
135 "Whether to simulate errors (useful for debugging)")
136 _PErrorCodes = ("error_codes", False, ht.TBool, "Error codes")
137 _PSkipChecks = ("skip_checks", ht.EmptyList,
138 ht.TListOf(ht.TElemOf(constants.VERIFY_OPTIONAL_CHECKS)),
139 "Which checks to skip")
140 _PIgnoreErrors = ("ignore_errors", ht.EmptyList,
141 ht.TListOf(ht.TElemOf(constants.CV_ALL_ECODES_STRINGS)),
142 "List of error codes that should be treated as warnings")
145 _PDiskParams = ("diskparams", None,
147 ht.TDictOf(ht.TElemOf(constants.DISK_TEMPLATES), ht.TDict),
149 "Disk templates' parameter defaults")
151 # Parameters for node resource model
152 _PHvState = ("hv_state", None, ht.TMaybeDict, "Set hypervisor states")
153 _PDiskState = ("disk_state", None, ht.TMaybeDict, "Set disk states")
156 _PIgnoreIpolicy = ("ignore_ipolicy", False, ht.TBool,
157 "Whether to ignore ipolicy violations")
159 #: OP_ID conversion regular expression
160 _OPID_RE = re.compile("([a-z])([A-Z])")
162 #: Utility function for L{OpClusterSetParams}
163 _TestClusterOsList = ht.TOr(ht.TNone,
164 ht.TListOf(ht.TAnd(ht.TList, ht.TIsLength(2),
165 ht.TMap(ht.WithDesc("GetFirstItem")(compat.fst),
166 ht.TElemOf(constants.DDMS_VALUES)))))
169 # TODO: Generate check from constants.INIC_PARAMS_TYPES
170 #: Utility function for testing NIC definitions
171 _TestNicDef = ht.TDictOf(ht.TElemOf(constants.INIC_PARAMS),
172 ht.TOr(ht.TNone, ht.TNonEmptyString))
174 _TSetParamsResultItemItems = [
175 ht.Comment("name of changed parameter")(ht.TNonEmptyString),
176 ht.Comment("new value")(ht.TAny),
179 _TSetParamsResult = \
180 ht.TListOf(ht.TAnd(ht.TIsLength(len(_TSetParamsResultItemItems)),
181 ht.TItems(_TSetParamsResultItemItems)))
183 # TODO: Generate check from constants.IDISK_PARAMS_TYPES (however, not all users
184 # of this check support all parameters)
185 _TDiskParams = ht.TDictOf(ht.TElemOf(constants.IDISK_PARAMS),
186 ht.TOr(ht.TNonEmptyString, ht.TInt))
195 #: Attribute name for dependencies
196 DEPEND_ATTR = "depends"
198 #: Attribute name for comment
199 COMMENT_ATTR = "comment"
203 """Convert an opcode class name to an OP_ID.
206 @param name: the class name, as OpXxxYyy
208 @return: the name in the OP_XXXX_YYYY format
211 if not name.startswith("Op"):
213 # Note: (?<=[a-z])(?=[A-Z]) would be ideal, since it wouldn't
214 # consume any input, and hence we would just have all the elements
215 # in the list, one by one; but it seems that split doesn't work on
216 # non-consuming input, hence we have to process the input string a
218 name = _OPID_RE.sub(r"\1,\2", name)
219 elems = name.split(",")
220 return "_".join(n.upper() for n in elems)
223 def RequireFileStorage():
224 """Checks that file storage is enabled.
226 While it doesn't really fit into this module, L{utils} was deemed too large
227 of a dependency to be imported for just one or two functions.
229 @raise errors.OpPrereqError: when file storage is disabled
232 if not constants.ENABLE_FILE_STORAGE:
233 raise errors.OpPrereqError("File storage disabled at configure time",
237 def RequireSharedFileStorage():
238 """Checks that shared file storage is enabled.
240 While it doesn't really fit into this module, L{utils} was deemed too large
241 of a dependency to be imported for just one or two functions.
243 @raise errors.OpPrereqError: when shared file storage is disabled
246 if not constants.ENABLE_SHARED_FILE_STORAGE:
247 raise errors.OpPrereqError("Shared file storage disabled at"
248 " configure time", errors.ECODE_INVAL)
251 @ht.WithDesc("CheckFileStorage")
252 def _CheckFileStorage(value):
253 """Ensures file storage is enabled if used.
256 if value == constants.DT_FILE:
258 elif value == constants.DT_SHARED_FILE:
259 RequireSharedFileStorage()
263 def _BuildDiskTemplateCheck(accept_none):
264 """Builds check for disk template.
266 @type accept_none: bool
267 @param accept_none: whether to accept None as a correct value
271 template_check = ht.TElemOf(constants.DISK_TEMPLATES)
274 template_check = ht.TOr(template_check, ht.TNone)
276 return ht.TAnd(template_check, _CheckFileStorage)
279 def _CheckStorageType(storage_type):
280 """Ensure a given storage type is valid.
283 if storage_type not in constants.VALID_STORAGE_TYPES:
284 raise errors.OpPrereqError("Unknown storage type: %s" % storage_type,
286 if storage_type == constants.ST_FILE:
291 #: Storage type parameter
292 _PStorageType = ("storage_type", ht.NoDefault, _CheckStorageType,
296 class _AutoOpParamSlots(type):
297 """Meta class for opcode definitions.
300 def __new__(mcs, name, bases, attrs):
301 """Called when a class should be created.
303 @param mcs: The meta class
304 @param name: Name of created class
305 @param bases: Base classes
307 @param attrs: Class attributes
310 assert "__slots__" not in attrs, \
311 "Class '%s' defines __slots__ when it should use OP_PARAMS" % name
312 assert "OP_ID" not in attrs, "Class '%s' defining OP_ID" % name
314 attrs["OP_ID"] = _NameToId(name)
316 # Always set OP_PARAMS to avoid duplicates in BaseOpCode.GetAllParams
317 params = attrs.setdefault("OP_PARAMS", [])
319 # Use parameter names as slots
320 slots = [pname for (pname, _, _, _) in params]
322 assert "OP_DSC_FIELD" not in attrs or attrs["OP_DSC_FIELD"] in slots, \
323 "Class '%s' uses unknown field in OP_DSC_FIELD" % name
325 attrs["__slots__"] = slots
327 return type.__new__(mcs, name, bases, attrs)
330 class BaseOpCode(object):
331 """A simple serializable object.
333 This object serves as a parent class for OpCode without any custom
337 # pylint: disable=E1101
338 # as OP_ID is dynamically defined
339 __metaclass__ = _AutoOpParamSlots
341 def __init__(self, **kwargs):
342 """Constructor for BaseOpCode.
344 The constructor takes only keyword arguments and will set
345 attributes on this object based on the passed arguments. As such,
346 it means that you should not pass arguments which are not in the
347 __slots__ attribute for this class.
350 slots = self._all_slots()
353 raise TypeError("Object %s doesn't support the parameter '%s'" %
354 (self.__class__.__name__, key))
355 setattr(self, key, kwargs[key])
357 def __getstate__(self):
358 """Generic serializer.
360 This method just returns the contents of the instance as a
364 @return: the instance attributes and their values
368 for name in self._all_slots():
369 if hasattr(self, name):
370 state[name] = getattr(self, name)
373 def __setstate__(self, state):
374 """Generic unserializer.
376 This method just restores from the serialized state the attributes
377 of the current instance.
379 @param state: the serialized opcode data
383 if not isinstance(state, dict):
384 raise ValueError("Invalid data to __setstate__: expected dict, got %s" %
387 for name in self._all_slots():
388 if name not in state and hasattr(self, name):
392 setattr(self, name, state[name])
396 """Compute the list of all declared slots for a class.
400 for parent in cls.__mro__:
401 slots.extend(getattr(parent, "__slots__", []))
405 def GetAllParams(cls):
406 """Compute list of all parameters for an opcode.
410 for parent in cls.__mro__:
411 slots.extend(getattr(parent, "OP_PARAMS", []))
414 def Validate(self, set_defaults):
415 """Validate opcode parameters, optionally setting default values.
417 @type set_defaults: bool
418 @param set_defaults: Whether to set default values
419 @raise errors.OpPrereqError: When a parameter value doesn't match
423 for (attr_name, default, test, _) in self.GetAllParams():
424 assert test == ht.NoType or callable(test)
426 if not hasattr(self, attr_name):
427 if default == ht.NoDefault:
428 raise errors.OpPrereqError("Required parameter '%s.%s' missing" %
429 (self.OP_ID, attr_name),
432 if callable(default):
436 setattr(self, attr_name, dval)
438 if test == ht.NoType:
442 if set_defaults or hasattr(self, attr_name):
443 attr_val = getattr(self, attr_name)
444 if not test(attr_val):
445 logging.error("OpCode %s, parameter %s, has invalid type %s/value %s",
446 self.OP_ID, attr_name, type(attr_val), attr_val)
447 raise errors.OpPrereqError("Parameter '%s.%s' fails validation" %
448 (self.OP_ID, attr_name),
452 def _BuildJobDepCheck(relative):
453 """Builds check for job dependencies (L{DEPEND_ATTR}).
456 @param relative: Whether to accept relative job IDs (negative)
461 job_id = ht.TOr(ht.TJobId, ht.TRelativeJobId)
466 ht.TAnd(ht.TIsLength(2),
468 ht.TListOf(ht.TElemOf(constants.JOBS_FINALIZED))]))
470 return ht.TOr(ht.TNone, ht.TListOf(job_dep))
473 TNoRelativeJobDependencies = _BuildJobDepCheck(False)
475 #: List of submission status and job ID as returned by C{SubmitManyJobs}
477 ht.TAnd(ht.TIsLength(2),
478 ht.TItems([ht.Comment("success")(ht.TBool),
479 ht.Comment("Job ID if successful, error message"
480 " otherwise")(ht.TOr(ht.TString,
482 TJobIdList = ht.TListOf(_TJobIdListItem)
484 #: Result containing only list of submitted jobs
485 TJobIdListOnly = ht.TStrictDict(True, True, {
486 constants.JOB_IDS_KEY: ht.Comment("List of submitted jobs")(TJobIdList),
490 class OpCode(BaseOpCode):
493 This is the root of the actual OpCode hierarchy. All clases derived
494 from this class should override OP_ID.
496 @cvar OP_ID: The ID of this opcode. This should be unique amongst all
497 children of this class.
498 @cvar OP_DSC_FIELD: The name of a field whose value will be included in the
499 string returned by Summary(); see the docstring of that
501 @cvar OP_PARAMS: List of opcode attributes, the default values they should
502 get if not already defined, and types they must match.
503 @cvar OP_RESULT: Callable to verify opcode result
504 @cvar WITH_LU: Boolean that specifies whether this should be included in
505 mcpu's dispatch table
506 @ivar dry_run: Whether the LU should be run in dry-run mode, i.e. just
508 @ivar priority: Opcode priority for queue
511 # pylint: disable=E1101
512 # as OP_ID is dynamically defined
515 ("dry_run", None, ht.TMaybeBool, "Run checks only, don't execute"),
516 ("debug_level", None, ht.TOr(ht.TNone, ht.TPositiveInt), "Debug level"),
517 ("priority", constants.OP_PRIO_DEFAULT,
518 ht.TElemOf(constants.OP_PRIO_SUBMIT_VALID), "Opcode priority"),
519 (DEPEND_ATTR, None, _BuildJobDepCheck(True),
520 "Job dependencies; if used through ``SubmitManyJobs`` relative (negative)"
521 " job IDs can be used; see :doc:`design document <design-chained-jobs>`"
523 (COMMENT_ATTR, None, ht.TMaybeString,
524 "Comment describing the purpose of the opcode"),
528 def __getstate__(self):
529 """Specialized getstate for opcodes.
531 This method adds to the state dictionary the OP_ID of the class,
532 so that on unload we can identify the correct class for
533 instantiating the opcode.
536 @return: the state as a dictionary
539 data = BaseOpCode.__getstate__(self)
540 data["OP_ID"] = self.OP_ID
544 def LoadOpCode(cls, data):
545 """Generic load opcode method.
547 The method identifies the correct opcode class from the dict-form
548 by looking for a OP_ID key, if this is not found, or its value is
549 not available in this module as a child of this class, we fail.
552 @param data: the serialized opcode
555 if not isinstance(data, dict):
556 raise ValueError("Invalid data to LoadOpCode (%s)" % type(data))
557 if "OP_ID" not in data:
558 raise ValueError("Invalid data to LoadOpcode, missing OP_ID")
559 op_id = data["OP_ID"]
561 if op_id in OP_MAPPING:
562 op_class = OP_MAPPING[op_id]
564 raise ValueError("Invalid data to LoadOpCode: OP_ID %s unsupported" %
567 new_data = data.copy()
568 del new_data["OP_ID"]
569 op.__setstate__(new_data)
573 """Generates a summary description of this opcode.
575 The summary is the value of the OP_ID attribute (without the "OP_"
576 prefix), plus the value of the OP_DSC_FIELD attribute, if one was
577 defined; this field should allow to easily identify the operation
578 (for an instance creation job, e.g., it would be the instance
582 assert self.OP_ID is not None and len(self.OP_ID) > 3
583 # all OP_ID start with OP_, we remove that
585 field_name = getattr(self, "OP_DSC_FIELD", None)
587 field_value = getattr(self, field_name, None)
588 if isinstance(field_value, (list, tuple)):
589 field_value = ",".join(str(i) for i in field_value)
590 txt = "%s(%s)" % (txt, field_value)
593 def TinySummary(self):
594 """Generates a compact summary description of the opcode.
597 assert self.OP_ID.startswith("OP_")
599 text = self.OP_ID[3:]
601 for (prefix, supplement) in _SUMMARY_PREFIX.items():
602 if text.startswith(prefix):
603 return supplement + text[len(prefix):]
610 class OpClusterPostInit(OpCode):
611 """Post cluster initialization.
613 This opcode does not touch the cluster at all. Its purpose is to run hooks
614 after the cluster has been initialized.
619 class OpClusterDestroy(OpCode):
620 """Destroy the cluster.
622 This opcode has no other parameters. All the state is irreversibly
623 lost after the execution of this opcode.
628 class OpClusterQuery(OpCode):
629 """Query cluster information."""
632 class OpClusterVerify(OpCode):
633 """Submits all jobs necessary to verify the cluster.
637 _PDebugSimulateErrors,
642 ("group_name", None, ht.TMaybeString, "Group to verify")
644 OP_RESULT = TJobIdListOnly
647 class OpClusterVerifyConfig(OpCode):
648 """Verify the cluster config.
652 _PDebugSimulateErrors,
660 class OpClusterVerifyGroup(OpCode):
661 """Run verify on a node group from the cluster.
663 @type skip_checks: C{list}
664 @ivar skip_checks: steps to be skipped from the verify process; this
665 needs to be a subset of
666 L{constants.VERIFY_OPTIONAL_CHECKS}; currently
667 only L{constants.VERIFY_NPLUSONE_MEM} can be passed
670 OP_DSC_FIELD = "group_name"
673 _PDebugSimulateErrors,
682 class OpClusterVerifyDisks(OpCode):
683 """Verify the cluster disks.
686 OP_RESULT = TJobIdListOnly
689 class OpGroupVerifyDisks(OpCode):
690 """Verifies the status of all disks in a node group.
692 Result: a tuple of three elements:
693 - dict of node names with issues (values: error msg)
694 - list of instances with degraded disks (that should be activated)
695 - dict of instances with missing logical volumes (values: (node, vol)
696 pairs with details about the missing volumes)
698 In normal operation, all lists should be empty. A non-empty instance
699 list (3rd element of the result) is still ok (errors were fixed) but
700 non-empty node list means some node is down, and probably there are
701 unfixable drbd errors.
703 Note that only instances that are drbd-based are taken into
704 consideration. This might need to be revisited in the future.
707 OP_DSC_FIELD = "group_name"
712 ht.TAnd(ht.TIsLength(3),
713 ht.TItems([ht.TDictOf(ht.TString, ht.TString),
714 ht.TListOf(ht.TString),
715 ht.TDictOf(ht.TString,
716 ht.TListOf(ht.TListOf(ht.TString)))]))
719 class OpClusterRepairDiskSizes(OpCode):
720 """Verify the disk sizes of the instances and fixes configuration
723 Parameters: optional instances list, in case we want to restrict the
724 checks to only a subset of the instances.
726 Result: a list of tuples, (instance, disk, new-size) for changed
729 In normal operation, the list should be empty.
731 @type instances: list
732 @ivar instances: the list of instances to check, or empty for all instances
736 ("instances", ht.EmptyList, ht.TListOf(ht.TNonEmptyString), None),
740 class OpClusterConfigQuery(OpCode):
741 """Query cluster configuration values."""
747 class OpClusterRename(OpCode):
748 """Rename the cluster.
751 @ivar name: The new name of the cluster. The name and/or the master IP
752 address will be changed to match the new name and its IP
756 OP_DSC_FIELD = "name"
758 ("name", ht.NoDefault, ht.TNonEmptyString, None),
762 class OpClusterSetParams(OpCode):
763 """Change the parameters of the cluster.
765 @type vg_name: C{str} or C{None}
766 @ivar vg_name: The new volume group name or None to disable LVM usage.
772 ("vg_name", None, ht.TMaybeString, "Volume group name"),
773 ("enabled_hypervisors", None,
774 ht.TOr(ht.TAnd(ht.TListOf(ht.TElemOf(constants.HYPER_TYPES)), ht.TTrue),
776 "List of enabled hypervisors"),
777 ("hvparams", None, ht.TOr(ht.TDictOf(ht.TNonEmptyString, ht.TDict),
779 "Cluster-wide hypervisor parameter defaults, hypervisor-dependent"),
780 ("beparams", None, ht.TOr(ht.TDict, ht.TNone),
781 "Cluster-wide backend parameter defaults"),
782 ("os_hvp", None, ht.TOr(ht.TDictOf(ht.TNonEmptyString, ht.TDict),
784 "Cluster-wide per-OS hypervisor parameter defaults"),
785 ("osparams", None, ht.TOr(ht.TDictOf(ht.TNonEmptyString, ht.TDict),
787 "Cluster-wide OS parameter defaults"),
789 ("candidate_pool_size", None, ht.TOr(ht.TStrictPositiveInt, ht.TNone),
790 "Master candidate pool size"),
791 ("uid_pool", None, ht.NoType,
792 "Set UID pool, must be list of lists describing UID ranges (two items,"
793 " start and end inclusive)"),
794 ("add_uids", None, ht.NoType,
795 "Extend UID pool, must be list of lists describing UID ranges (two"
796 " items, start and end inclusive) to be added"),
797 ("remove_uids", None, ht.NoType,
798 "Shrink UID pool, must be list of lists describing UID ranges (two"
799 " items, start and end inclusive) to be removed"),
800 ("maintain_node_health", None, ht.TMaybeBool,
801 "Whether to automatically maintain node health"),
802 ("prealloc_wipe_disks", None, ht.TMaybeBool,
803 "Whether to wipe disks before allocating them to instances"),
804 ("nicparams", None, ht.TMaybeDict, "Cluster-wide NIC parameter defaults"),
805 ("ndparams", None, ht.TMaybeDict, "Cluster-wide node parameter defaults"),
806 ("ipolicy", None, ht.TMaybeDict,
807 "Cluster-wide :ref:`instance policy <rapi-ipolicy>` specs"),
808 ("drbd_helper", None, ht.TOr(ht.TString, ht.TNone), "DRBD helper program"),
809 ("default_iallocator", None, ht.TOr(ht.TString, ht.TNone),
810 "Default iallocator for cluster"),
811 ("master_netdev", None, ht.TOr(ht.TString, ht.TNone),
812 "Master network device"),
813 ("master_netmask", None, ht.TOr(ht.TInt, ht.TNone),
814 "Netmask of the master IP"),
815 ("reserved_lvs", None, ht.TOr(ht.TListOf(ht.TNonEmptyString), ht.TNone),
816 "List of reserved LVs"),
817 ("hidden_os", None, _TestClusterOsList,
818 "Modify list of hidden operating systems. Each modification must have"
819 " two items, the operation and the OS name. The operation can be"
820 " ``%s`` or ``%s``." % (constants.DDM_ADD, constants.DDM_REMOVE)),
821 ("blacklisted_os", None, _TestClusterOsList,
822 "Modify list of blacklisted operating systems. Each modification must have"
823 " two items, the operation and the OS name. The operation can be"
824 " ``%s`` or ``%s``." % (constants.DDM_ADD, constants.DDM_REMOVE)),
825 ("use_external_mip_script", None, ht.TMaybeBool,
826 "Whether to use an external master IP address setup script"),
830 class OpClusterRedistConf(OpCode):
831 """Force a full push of the cluster configuration.
836 class OpClusterActivateMasterIp(OpCode):
837 """Activate the master IP on the master node.
842 class OpClusterDeactivateMasterIp(OpCode):
843 """Deactivate the master IP on the master node.
848 class OpQuery(OpCode):
849 """Query for resources/items.
851 @ivar what: Resources to query for, must be one of L{constants.QR_VIA_OP}
852 @ivar fields: List of fields to retrieve
853 @ivar qfilter: Query filter
856 OP_DSC_FIELD = "what"
860 ("fields", ht.NoDefault, ht.TListOf(ht.TNonEmptyString),
862 ("qfilter", None, ht.TOr(ht.TNone, ht.TListOf),
867 class OpQueryFields(OpCode):
868 """Query for available resource/item fields.
870 @ivar what: Resources to query for, must be one of L{constants.QR_VIA_OP}
871 @ivar fields: List of fields to retrieve
874 OP_DSC_FIELD = "what"
877 ("fields", None, ht.TOr(ht.TNone, ht.TListOf(ht.TNonEmptyString)),
878 "Requested fields; if not given, all are returned"),
882 class OpOobCommand(OpCode):
883 """Interact with OOB."""
885 ("node_names", ht.EmptyList, ht.TListOf(ht.TNonEmptyString),
886 "List of nodes to run the OOB command against"),
887 ("command", None, ht.TElemOf(constants.OOB_COMMANDS),
888 "OOB command to be run"),
889 ("timeout", constants.OOB_TIMEOUT, ht.TInt,
890 "Timeout before the OOB helper will be terminated"),
891 ("ignore_status", False, ht.TBool,
892 "Ignores the node offline status for power off"),
893 ("power_delay", constants.OOB_POWER_DELAY, ht.TPositiveFloat,
894 "Time in seconds to wait between powering on nodes"),
900 class OpNodeRemove(OpCode):
903 @type node_name: C{str}
904 @ivar node_name: The name of the node to remove. If the node still has
905 instances on it, the operation will fail.
908 OP_DSC_FIELD = "node_name"
914 class OpNodeAdd(OpCode):
915 """Add a node to the cluster.
917 @type node_name: C{str}
918 @ivar node_name: The name of the node to add. This can be a short name,
919 but it will be expanded to the FQDN.
920 @type primary_ip: IP address
921 @ivar primary_ip: The primary IP of the node. This will be ignored when the
922 opcode is submitted, but will be filled during the node
923 add (so it will be visible in the job query).
924 @type secondary_ip: IP address
925 @ivar secondary_ip: The secondary IP of the node. This needs to be passed
926 if the cluster has been initialized in 'dual-network'
927 mode, otherwise it must not be given.
929 @ivar readd: Whether to re-add an existing node to the cluster. If
930 this is not passed, then the operation will abort if the node
931 name is already in the cluster; use this parameter to 'repair'
932 a node that had its configuration broken, or was reinstalled
933 without removal from the cluster.
935 @ivar group: The node group to which this node will belong.
936 @type vm_capable: C{bool}
937 @ivar vm_capable: The vm_capable node attribute
938 @type master_capable: C{bool}
939 @ivar master_capable: The master_capable node attribute
942 OP_DSC_FIELD = "node_name"
947 ("primary_ip", None, ht.NoType, "Primary IP address"),
948 ("secondary_ip", None, ht.TMaybeString, "Secondary IP address"),
949 ("readd", False, ht.TBool, "Whether node is re-added to cluster"),
950 ("group", None, ht.TMaybeString, "Initial node group"),
951 ("master_capable", None, ht.TMaybeBool,
952 "Whether node can become master or master candidate"),
953 ("vm_capable", None, ht.TMaybeBool,
954 "Whether node can host instances"),
955 ("ndparams", None, ht.TMaybeDict, "Node parameters"),
959 class OpNodeQuery(OpCode):
960 """Compute the list of nodes."""
964 ("names", ht.EmptyList, ht.TListOf(ht.TNonEmptyString),
965 "Empty list to query all nodes, node names otherwise"),
969 class OpNodeQueryvols(OpCode):
970 """Get list of volumes on node."""
973 ("nodes", ht.EmptyList, ht.TListOf(ht.TNonEmptyString),
974 "Empty list to query all nodes, node names otherwise"),
978 class OpNodeQueryStorage(OpCode):
979 """Get information on storage for node(s)."""
983 ("nodes", ht.EmptyList, ht.TListOf(ht.TNonEmptyString), "List of nodes"),
984 ("name", None, ht.TMaybeString, "Storage name"),
988 class OpNodeModifyStorage(OpCode):
989 """Modifies the properies of a storage unit"""
994 ("changes", ht.NoDefault, ht.TDict, "Requested changes"),
998 class OpRepairNodeStorage(OpCode):
999 """Repairs the volume group on a node."""
1000 OP_DSC_FIELD = "node_name"
1005 _PIgnoreConsistency,
1009 class OpNodeSetParams(OpCode):
1010 """Change the parameters of a node."""
1011 OP_DSC_FIELD = "node_name"
1017 ("master_candidate", None, ht.TMaybeBool,
1018 "Whether the node should become a master candidate"),
1019 ("offline", None, ht.TMaybeBool,
1020 "Whether the node should be marked as offline"),
1021 ("drained", None, ht.TMaybeBool,
1022 "Whether the node should be marked as drained"),
1023 ("auto_promote", False, ht.TBool,
1024 "Whether node(s) should be promoted to master candidate if necessary"),
1025 ("master_capable", None, ht.TMaybeBool,
1026 "Denote whether node can become master or master candidate"),
1027 ("vm_capable", None, ht.TMaybeBool,
1028 "Denote whether node can host instances"),
1029 ("secondary_ip", None, ht.TMaybeString,
1030 "Change node's secondary IP address"),
1031 ("ndparams", None, ht.TMaybeDict, "Set node parameters"),
1032 ("powered", None, ht.TMaybeBool,
1033 "Whether the node should be marked as powered"),
1035 OP_RESULT = _TSetParamsResult
1038 class OpNodePowercycle(OpCode):
1039 """Tries to powercycle a node."""
1040 OP_DSC_FIELD = "node_name"
1047 class OpNodeMigrate(OpCode):
1048 """Migrate all instances from a node."""
1049 OP_DSC_FIELD = "node_name"
1054 _PMigrationTargetNode,
1056 ("iallocator", None, ht.TMaybeString,
1057 "Iallocator for deciding the target node for shared-storage instances"),
1059 OP_RESULT = TJobIdListOnly
1062 class OpNodeEvacuate(OpCode):
1063 """Evacuate instances off a number of nodes."""
1064 OP_DSC_FIELD = "node_name"
1068 ("remote_node", None, ht.TMaybeString, "New secondary node"),
1069 ("iallocator", None, ht.TMaybeString, "Iallocator for computing solution"),
1070 ("mode", ht.NoDefault, ht.TElemOf(constants.NODE_EVAC_MODES),
1071 "Node evacuation mode"),
1073 OP_RESULT = TJobIdListOnly
1078 class OpInstanceCreate(OpCode):
1079 """Create an instance.
1081 @ivar instance_name: Instance name
1082 @ivar mode: Instance creation mode (one of L{constants.INSTANCE_CREATE_MODES})
1083 @ivar source_handshake: Signed handshake from source (remote import only)
1084 @ivar source_x509_ca: Source X509 CA in PEM format (remote import only)
1085 @ivar source_instance_name: Previous name of instance (remote import only)
1086 @ivar source_shutdown_timeout: Shutdown timeout used for source instance
1087 (remote import only)
1090 OP_DSC_FIELD = "instance_name"
1097 ("beparams", ht.EmptyDict, ht.TDict, "Backend parameters for instance"),
1098 ("disks", ht.NoDefault, ht.TListOf(_TDiskParams),
1099 "Disk descriptions, for example ``[{\"%s\": 100}, {\"%s\": 5}]``;"
1100 " each disk definition must contain a ``%s`` value and"
1101 " can contain an optional ``%s`` value denoting the disk access mode"
1103 (constants.IDISK_SIZE, constants.IDISK_SIZE, constants.IDISK_SIZE,
1104 constants.IDISK_MODE,
1105 " or ".join("``%s``" % i for i in sorted(constants.DISK_ACCESS_SET)))),
1106 ("disk_template", ht.NoDefault, _BuildDiskTemplateCheck(True),
1108 ("file_driver", None, ht.TOr(ht.TNone, ht.TElemOf(constants.FILE_DRIVER)),
1109 "Driver for file-backed disks"),
1110 ("file_storage_dir", None, ht.TMaybeString,
1111 "Directory for storing file-backed disks"),
1112 ("hvparams", ht.EmptyDict, ht.TDict,
1113 "Hypervisor parameters for instance, hypervisor-dependent"),
1114 ("hypervisor", None, ht.TMaybeString, "Hypervisor"),
1115 ("iallocator", None, ht.TMaybeString,
1116 "Iallocator for deciding which node(s) to use"),
1117 ("identify_defaults", False, ht.TBool,
1118 "Reset instance parameters to default if equal"),
1119 ("ip_check", True, ht.TBool, _PIpCheckDoc),
1120 ("mode", ht.NoDefault, ht.TElemOf(constants.INSTANCE_CREATE_MODES),
1121 "Instance creation mode"),
1122 ("nics", ht.NoDefault, ht.TListOf(_TestNicDef),
1123 "List of NIC (network interface) definitions, for example"
1124 " ``[{}, {}, {\"%s\": \"198.51.100.4\"}]``; each NIC definition can"
1125 " contain the optional values %s" %
1127 ", ".join("``%s``" % i for i in sorted(constants.INIC_PARAMS)))),
1128 ("no_install", None, ht.TMaybeBool,
1129 "Do not install the OS (will disable automatic start)"),
1130 ("osparams", ht.EmptyDict, ht.TDict, "OS parameters for instance"),
1131 ("os_type", None, ht.TMaybeString, "Operating system"),
1132 ("pnode", None, ht.TMaybeString, "Primary node"),
1133 ("snode", None, ht.TMaybeString, "Secondary node"),
1134 ("source_handshake", None, ht.TOr(ht.TList, ht.TNone),
1135 "Signed handshake from source (remote import only)"),
1136 ("source_instance_name", None, ht.TMaybeString,
1137 "Source instance name (remote import only)"),
1138 ("source_shutdown_timeout", constants.DEFAULT_SHUTDOWN_TIMEOUT,
1140 "How long source instance was given to shut down (remote import only)"),
1141 ("source_x509_ca", None, ht.TMaybeString,
1142 "Source X509 CA in PEM format (remote import only)"),
1143 ("src_node", None, ht.TMaybeString, "Source node for import"),
1144 ("src_path", None, ht.TMaybeString, "Source directory for import"),
1145 ("start", True, ht.TBool, "Whether to start instance after creation"),
1146 ("tags", ht.EmptyList, ht.TListOf(ht.TNonEmptyString), "Instance tags"),
1148 OP_RESULT = ht.Comment("instance nodes")(ht.TListOf(ht.TNonEmptyString))
1151 class OpInstanceReinstall(OpCode):
1152 """Reinstall an instance's OS."""
1153 OP_DSC_FIELD = "instance_name"
1157 ("os_type", None, ht.TMaybeString, "Instance operating system"),
1158 ("osparams", None, ht.TMaybeDict, "Temporary OS parameters"),
1162 class OpInstanceRemove(OpCode):
1163 """Remove an instance."""
1164 OP_DSC_FIELD = "instance_name"
1168 ("ignore_failures", False, ht.TBool,
1169 "Whether to ignore failures during removal"),
1173 class OpInstanceRename(OpCode):
1174 """Rename an instance."""
1178 ("new_name", ht.NoDefault, ht.TNonEmptyString, "New instance name"),
1179 ("ip_check", False, ht.TBool, _PIpCheckDoc),
1181 OP_RESULT = ht.Comment("New instance name")(ht.TNonEmptyString)
1184 class OpInstanceStartup(OpCode):
1185 """Startup an instance."""
1186 OP_DSC_FIELD = "instance_name"
1190 _PIgnoreOfflineNodes,
1191 ("hvparams", ht.EmptyDict, ht.TDict,
1192 "Temporary hypervisor parameters, hypervisor-dependent"),
1193 ("beparams", ht.EmptyDict, ht.TDict, "Temporary backend parameters"),
1199 class OpInstanceShutdown(OpCode):
1200 """Shutdown an instance."""
1201 OP_DSC_FIELD = "instance_name"
1204 _PIgnoreOfflineNodes,
1205 ("timeout", constants.DEFAULT_SHUTDOWN_TIMEOUT, ht.TPositiveInt,
1206 "How long to wait for instance to shut down"),
1211 class OpInstanceReboot(OpCode):
1212 """Reboot an instance."""
1213 OP_DSC_FIELD = "instance_name"
1217 ("ignore_secondaries", False, ht.TBool,
1218 "Whether to start the instance even if secondary disks are failing"),
1219 ("reboot_type", ht.NoDefault, ht.TElemOf(constants.REBOOT_TYPES),
1220 "How to reboot instance"),
1224 class OpInstanceReplaceDisks(OpCode):
1225 """Replace the disks of an instance."""
1226 OP_DSC_FIELD = "instance_name"
1231 ("mode", ht.NoDefault, ht.TElemOf(constants.REPLACE_MODES),
1232 "Replacement mode"),
1233 ("disks", ht.EmptyList, ht.TListOf(ht.TPositiveInt),
1235 ("remote_node", None, ht.TMaybeString, "New secondary node"),
1236 ("iallocator", None, ht.TMaybeString,
1237 "Iallocator for deciding new secondary node"),
1241 class OpInstanceFailover(OpCode):
1242 """Failover an instance."""
1243 OP_DSC_FIELD = "instance_name"
1247 _PIgnoreConsistency,
1248 _PMigrationTargetNode,
1250 ("iallocator", None, ht.TMaybeString,
1251 "Iallocator for deciding the target node for shared-storage instances"),
1255 class OpInstanceMigrate(OpCode):
1256 """Migrate an instance.
1258 This migrates (without shutting down an instance) to its secondary
1261 @ivar instance_name: the name of the instance
1262 @ivar mode: the migration mode (live, non-live or None for auto)
1265 OP_DSC_FIELD = "instance_name"
1270 _PMigrationTargetNode,
1272 ("cleanup", False, ht.TBool,
1273 "Whether a previously failed migration should be cleaned up"),
1274 ("iallocator", None, ht.TMaybeString,
1275 "Iallocator for deciding the target node for shared-storage instances"),
1276 ("allow_failover", False, ht.TBool,
1277 "Whether we can fallback to failover if migration is not possible"),
1281 class OpInstanceMove(OpCode):
1282 """Move an instance.
1284 This move (with shutting down an instance and data copying) to an
1287 @ivar instance_name: the name of the instance
1288 @ivar target_node: the destination node
1291 OP_DSC_FIELD = "instance_name"
1296 ("target_node", ht.NoDefault, ht.TNonEmptyString, "Target node"),
1297 _PIgnoreConsistency,
1301 class OpInstanceConsole(OpCode):
1302 """Connect to an instance's console."""
1303 OP_DSC_FIELD = "instance_name"
1309 class OpInstanceActivateDisks(OpCode):
1310 """Activate an instance's disks."""
1311 OP_DSC_FIELD = "instance_name"
1314 ("ignore_size", False, ht.TBool, "Whether to ignore recorded size"),
1318 class OpInstanceDeactivateDisks(OpCode):
1319 """Deactivate an instance's disks."""
1320 OP_DSC_FIELD = "instance_name"
1327 class OpInstanceRecreateDisks(OpCode):
1328 """Recreate an instance's disks."""
1330 ht.TAnd(ht.TIsLength(2),
1331 ht.TItems([ht.Comment("Disk index")(ht.TPositiveInt),
1332 ht.Comment("Parameters")(_TDiskParams)]))
1334 OP_DSC_FIELD = "instance_name"
1337 ("disks", ht.EmptyList,
1338 ht.TOr(ht.TListOf(ht.TPositiveInt), ht.TListOf(_TDiskChanges)),
1339 "List of disk indexes (deprecated) or a list of tuples containing a disk"
1340 " index and a possibly empty dictionary with disk parameter changes"),
1341 ("nodes", ht.EmptyList, ht.TListOf(ht.TNonEmptyString),
1342 "New instance nodes, if relocation is desired"),
1346 class OpInstanceQuery(OpCode):
1347 """Compute the list of instances."""
1351 ("names", ht.EmptyList, ht.TListOf(ht.TNonEmptyString),
1352 "Empty list to query all instances, instance names otherwise"),
1356 class OpInstanceQueryData(OpCode):
1357 """Compute the run-time status of instances."""
1360 ("instances", ht.EmptyList, ht.TListOf(ht.TNonEmptyString),
1362 ("static", False, ht.TBool,
1363 "Whether to only return configuration data without querying"
1368 class OpInstanceSetParams(OpCode):
1369 """Change the parameters of an instance."""
1370 OP_DSC_FIELD = "instance_name"
1376 # TODO: Use _TestNicDef
1377 ("nics", ht.EmptyList, ht.TList,
1378 "List of NIC changes. Each item is of the form ``(op, settings)``."
1379 " ``op`` can be ``%s`` to add a new NIC with the specified settings,"
1380 " ``%s`` to remove the last NIC or a number to modify the settings"
1381 " of the NIC with that index." %
1382 (constants.DDM_ADD, constants.DDM_REMOVE)),
1383 ("disks", ht.EmptyList, ht.TList, "List of disk changes. See ``nics``."),
1384 ("beparams", ht.EmptyDict, ht.TDict, "Per-instance backend parameters"),
1385 ("runtime_mem", None, ht.TMaybeStrictPositiveInt, "New runtime memory"),
1386 ("hvparams", ht.EmptyDict, ht.TDict,
1387 "Per-instance hypervisor parameters, hypervisor-dependent"),
1388 ("disk_template", None, ht.TOr(ht.TNone, _BuildDiskTemplateCheck(False)),
1389 "Disk template for instance"),
1390 ("remote_node", None, ht.TMaybeString,
1391 "Secondary node (used when changing disk template)"),
1392 ("os_name", None, ht.TMaybeString,
1393 "Change instance's OS name. Does not reinstall the instance."),
1394 ("osparams", None, ht.TMaybeDict, "Per-instance OS parameters"),
1395 ("wait_for_sync", True, ht.TBool,
1396 "Whether to wait for the disk to synchronize, when changing template"),
1397 ("offline_inst", False, ht.TBool,
1398 "Whether to turn off the down instance completely"),
1399 ("online_inst", False, ht.TBool,
1400 "Whether to enable the offline instance"),
1402 OP_RESULT = _TSetParamsResult
1405 class OpInstanceGrowDisk(OpCode):
1406 """Grow a disk of an instance."""
1407 OP_DSC_FIELD = "instance_name"
1411 ("disk", ht.NoDefault, ht.TInt, "Disk index"),
1412 ("amount", ht.NoDefault, ht.TInt,
1413 "Amount of disk space to add (megabytes)"),
1417 class OpInstanceChangeGroup(OpCode):
1418 """Moves an instance to another node group."""
1419 OP_DSC_FIELD = "instance_name"
1423 ("iallocator", None, ht.TMaybeString, "Iallocator for computing solution"),
1424 ("target_groups", None, ht.TOr(ht.TNone, ht.TListOf(ht.TNonEmptyString)),
1425 "Destination group names or UUIDs (defaults to \"all but current group\""),
1427 OP_RESULT = TJobIdListOnly
1430 # Node group opcodes
1432 class OpGroupAdd(OpCode):
1433 """Add a node group to the cluster."""
1434 OP_DSC_FIELD = "group_name"
1437 _PNodeGroupAllocPolicy,
1442 ("ipolicy", None, ht.TMaybeDict,
1443 "Group-wide :ref:`instance policy <rapi-ipolicy>` specs"),
1447 class OpGroupAssignNodes(OpCode):
1448 """Assign nodes to a node group."""
1449 OP_DSC_FIELD = "group_name"
1453 ("nodes", ht.NoDefault, ht.TListOf(ht.TNonEmptyString),
1454 "List of nodes to assign"),
1458 class OpGroupQuery(OpCode):
1459 """Compute the list of node groups."""
1462 ("names", ht.EmptyList, ht.TListOf(ht.TNonEmptyString),
1463 "Empty list to query all groups, group names otherwise"),
1467 class OpGroupSetParams(OpCode):
1468 """Change the parameters of a node group."""
1469 OP_DSC_FIELD = "group_name"
1472 _PNodeGroupAllocPolicy,
1477 ("ipolicy", None, ht.TMaybeDict, "Group-wide instance policy specs"),
1479 OP_RESULT = _TSetParamsResult
1482 class OpGroupRemove(OpCode):
1483 """Remove a node group from the cluster."""
1484 OP_DSC_FIELD = "group_name"
1490 class OpGroupRename(OpCode):
1491 """Rename a node group in the cluster."""
1494 ("new_name", ht.NoDefault, ht.TNonEmptyString, "New group name"),
1496 OP_RESULT = ht.Comment("New group name")(ht.TNonEmptyString)
1499 class OpGroupEvacuate(OpCode):
1500 """Evacuate a node group in the cluster."""
1501 OP_DSC_FIELD = "group_name"
1505 ("iallocator", None, ht.TMaybeString, "Iallocator for computing solution"),
1506 ("target_groups", None, ht.TOr(ht.TNone, ht.TListOf(ht.TNonEmptyString)),
1507 "Destination group names or UUIDs"),
1509 OP_RESULT = TJobIdListOnly
1513 class OpOsDiagnose(OpCode):
1514 """Compute the list of guest operating systems."""
1517 ("names", ht.EmptyList, ht.TListOf(ht.TNonEmptyString),
1518 "Which operating systems to diagnose"),
1523 class OpBackupQuery(OpCode):
1524 """Compute the list of exported images."""
1527 ("nodes", ht.EmptyList, ht.TListOf(ht.TNonEmptyString),
1528 "Empty list to query all nodes, node names otherwise"),
1532 class OpBackupPrepare(OpCode):
1533 """Prepares an instance export.
1535 @ivar instance_name: Instance name
1536 @ivar mode: Export mode (one of L{constants.EXPORT_MODES})
1539 OP_DSC_FIELD = "instance_name"
1542 ("mode", ht.NoDefault, ht.TElemOf(constants.EXPORT_MODES),
1547 class OpBackupExport(OpCode):
1548 """Export an instance.
1550 For local exports, the export destination is the node name. For remote
1551 exports, the export destination is a list of tuples, each consisting of
1552 hostname/IP address, port, HMAC and HMAC salt. The HMAC is calculated using
1553 the cluster domain secret over the value "${index}:${hostname}:${port}". The
1554 destination X509 CA must be a signed certificate.
1556 @ivar mode: Export mode (one of L{constants.EXPORT_MODES})
1557 @ivar target_node: Export destination
1558 @ivar x509_key_name: X509 key to use (remote export only)
1559 @ivar destination_x509_ca: Destination X509 CA in PEM format (remote export
1563 OP_DSC_FIELD = "instance_name"
1567 # TODO: Rename target_node as it changes meaning for different export modes
1568 # (e.g. "destination")
1569 ("target_node", ht.NoDefault, ht.TOr(ht.TNonEmptyString, ht.TList),
1570 "Destination information, depends on export mode"),
1571 ("shutdown", True, ht.TBool, "Whether to shutdown instance before export"),
1572 ("remove_instance", False, ht.TBool,
1573 "Whether to remove instance after export"),
1574 ("ignore_remove_failures", False, ht.TBool,
1575 "Whether to ignore failures while removing instances"),
1576 ("mode", constants.EXPORT_MODE_LOCAL, ht.TElemOf(constants.EXPORT_MODES),
1578 ("x509_key_name", None, ht.TOr(ht.TList, ht.TNone),
1579 "Name of X509 key (remote export only)"),
1580 ("destination_x509_ca", None, ht.TMaybeString,
1581 "Destination X509 CA (remote export only)"),
1585 class OpBackupRemove(OpCode):
1586 """Remove an instance's export."""
1587 OP_DSC_FIELD = "instance_name"
1594 class OpTagsGet(OpCode):
1595 """Returns the tags of the given object."""
1596 OP_DSC_FIELD = "name"
1599 # Name is only meaningful for nodes and instances
1600 ("name", ht.NoDefault, ht.TMaybeString, None),
1604 class OpTagsSearch(OpCode):
1605 """Searches the tags in the cluster for a given pattern."""
1606 OP_DSC_FIELD = "pattern"
1608 ("pattern", ht.NoDefault, ht.TNonEmptyString, None),
1612 class OpTagsSet(OpCode):
1613 """Add a list of tags on a given object."""
1617 # Name is only meaningful for nodes and instances
1618 ("name", ht.NoDefault, ht.TMaybeString, None),
1622 class OpTagsDel(OpCode):
1623 """Remove a list of tags from a given object."""
1627 # Name is only meaningful for nodes and instances
1628 ("name", ht.NoDefault, ht.TMaybeString, None),
1633 class OpTestDelay(OpCode):
1634 """Sleeps for a configured amount of time.
1636 This is used just for debugging and testing.
1639 - duration: the time to sleep
1640 - on_master: if true, sleep on the master
1641 - on_nodes: list of nodes in which to sleep
1643 If the on_master parameter is true, it will execute a sleep on the
1644 master (before any node sleep).
1646 If the on_nodes list is not empty, it will sleep on those nodes
1647 (after the sleep on the master, if that is enabled).
1649 As an additional feature, the case of duration < 0 will be reported
1650 as an execution error, so this opcode can be used as a failure
1651 generator. The case of duration == 0 will not be treated specially.
1654 OP_DSC_FIELD = "duration"
1656 ("duration", ht.NoDefault, ht.TNumber, None),
1657 ("on_master", True, ht.TBool, None),
1658 ("on_nodes", ht.EmptyList, ht.TListOf(ht.TNonEmptyString), None),
1659 ("repeat", 0, ht.TPositiveInt, None),
1663 class OpTestAllocator(OpCode):
1664 """Allocator framework testing.
1666 This opcode has two modes:
1667 - gather and return allocator input for a given mode (allocate new
1668 or replace secondary) and a given instance definition (direction
1670 - run a selected allocator for a given operation (as above) and
1671 return the allocator output (direction 'out')
1674 OP_DSC_FIELD = "allocator"
1676 ("direction", ht.NoDefault,
1677 ht.TElemOf(constants.VALID_IALLOCATOR_DIRECTIONS), None),
1678 ("mode", ht.NoDefault, ht.TElemOf(constants.VALID_IALLOCATOR_MODES), None),
1679 ("name", ht.NoDefault, ht.TNonEmptyString, None),
1680 ("nics", ht.NoDefault, ht.TOr(ht.TNone, ht.TListOf(
1681 ht.TDictOf(ht.TElemOf([constants.INIC_MAC, constants.INIC_IP, "bridge"]),
1682 ht.TOr(ht.TNone, ht.TNonEmptyString)))), None),
1683 ("disks", ht.NoDefault, ht.TOr(ht.TNone, ht.TList), None),
1684 ("hypervisor", None, ht.TMaybeString, None),
1685 ("allocator", None, ht.TMaybeString, None),
1686 ("tags", ht.EmptyList, ht.TListOf(ht.TNonEmptyString), None),
1687 ("memory", None, ht.TOr(ht.TNone, ht.TPositiveInt), None),
1688 ("vcpus", None, ht.TOr(ht.TNone, ht.TPositiveInt), None),
1689 ("os", None, ht.TMaybeString, None),
1690 ("disk_template", None, ht.TMaybeString, None),
1691 ("instances", None, ht.TOr(ht.TNone, ht.TListOf(ht.TNonEmptyString)),
1694 ht.TOr(ht.TNone, ht.TElemOf(constants.IALLOCATOR_NEVAC_MODES)), None),
1695 ("target_groups", None, ht.TOr(ht.TNone, ht.TListOf(ht.TNonEmptyString)),
1700 class OpTestJqueue(OpCode):
1701 """Utility opcode to test some aspects of the job queue.
1705 ("notify_waitlock", False, ht.TBool, None),
1706 ("notify_exec", False, ht.TBool, None),
1707 ("log_messages", ht.EmptyList, ht.TListOf(ht.TString), None),
1708 ("fail", False, ht.TBool, None),
1712 class OpTestDummy(OpCode):
1713 """Utility opcode used by unittests.
1717 ("result", ht.NoDefault, ht.NoType, None),
1718 ("messages", ht.NoDefault, ht.NoType, None),
1719 ("fail", ht.NoDefault, ht.NoType, None),
1720 ("submit_jobs", None, ht.NoType, None),
1726 """Returns list of all defined opcodes.
1728 Does not eliminate duplicates by C{OP_ID}.
1731 return [v for v in globals().values()
1732 if (isinstance(v, type) and issubclass(v, OpCode) and
1733 hasattr(v, "OP_ID") and v is not OpCode)]
1736 OP_MAPPING = dict((v.OP_ID, v) for v in _GetOpList())