1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 """OpCodes module
23
24 This module implements the data structures which define the cluster
25 operations - the so-called opcodes.
26
27 Every operation which modifies the cluster state is expressed via
28 opcodes.
29
30 """
31
32
33
34
35
36 import logging
37 import re
38 import ipaddr
39
40 from ganeti import constants
41 from ganeti import errors
42 from ganeti import ht
43 from ganeti import objects
44 from ganeti import outils
45
46
47
48
49
50 _POutputFields = ("output_fields", ht.NoDefault, ht.TListOf(ht.TNonEmptyString),
51 "Selected output fields")
52
53
54 _PShutdownTimeout = \
55 ("shutdown_timeout", constants.DEFAULT_SHUTDOWN_TIMEOUT, ht.TNonNegativeInt,
56 "How long to wait for instance to shut down")
57
58
59 _PForce = ("force", False, ht.TBool, "Whether to force the operation")
60
61
62 _PInstanceName = ("instance_name", ht.NoDefault, ht.TNonEmptyString,
63 "Instance name")
64
65
66 _PIgnoreOfflineNodes = ("ignore_offline_nodes", False, ht.TBool,
67 "Whether to ignore offline nodes")
68
69
70 _PNodeName = ("node_name", ht.NoDefault, ht.TNonEmptyString, "Node name")
71
72
73 _PGroupName = ("group_name", ht.NoDefault, ht.TNonEmptyString, "Group name")
74
75
76 _PMigrationMode = ("mode", None,
77 ht.TMaybe(ht.TElemOf(constants.HT_MIGRATION_MODES)),
78 "Migration mode")
79
80
81 _PMigrationLive = ("live", None, ht.TMaybeBool,
82 "Legacy setting for live migration, do not use")
83
84
85 _PTagKind = ("kind", ht.NoDefault, ht.TElemOf(constants.VALID_TAG_TYPES),
86 "Tag kind")
87
88
89 _PTags = ("tags", ht.NoDefault, ht.TListOf(ht.TNonEmptyString),
90 "List of tag names")
91
92 _PForceVariant = ("force_variant", False, ht.TBool,
93 "Whether to force an unknown OS variant")
94
95 _PWaitForSync = ("wait_for_sync", True, ht.TBool,
96 "Whether to wait for the disk to synchronize")
97
98 _PWaitForSyncFalse = ("wait_for_sync", False, ht.TBool,
99 "Whether to wait for the disk to synchronize"
100 " (defaults to false)")
101
102 _PIgnoreConsistency = ("ignore_consistency", False, ht.TBool,
103 "Whether to ignore disk consistency")
104
105 _PStorageName = ("name", ht.NoDefault, ht.TMaybeString, "Storage name")
106
107 _PUseLocking = ("use_locking", False, ht.TBool,
108 "Whether to use synchronization")
109
110 _PNameCheck = ("name_check", True, ht.TBool, "Whether to check name")
111
112 _PNodeGroupAllocPolicy = \
113 ("alloc_policy", None,
114 ht.TMaybe(ht.TElemOf(constants.VALID_ALLOC_POLICIES)),
115 "Instance allocation policy")
116
117 _PGroupNodeParams = ("ndparams", None, ht.TMaybeDict,
118 "Default node parameters for group")
119
120 _PQueryWhat = ("what", ht.NoDefault, ht.TElemOf(constants.QR_VIA_OP),
121 "Resource(s) to query for")
122
123 _PEarlyRelease = ("early_release", False, ht.TBool,
124 "Whether to release locks as soon as possible")
125
126 _PIpCheckDoc = "Whether to ensure instance's IP address is inactive"
127
128
129 _PNoRemember = ("no_remember", False, ht.TBool,
130 "Do not remember the state change")
131
132
133 _PMigrationTargetNode = ("target_node", None, ht.TMaybeString,
134 "Target node for shared-storage instances")
135
136 _PStartupPaused = ("startup_paused", False, ht.TBool,
137 "Pause instance at startup")
138
139 _PVerbose = ("verbose", False, ht.TBool, "Verbose mode")
140
141
142 _PDebugSimulateErrors = ("debug_simulate_errors", False, ht.TBool,
143 "Whether to simulate errors (useful for debugging)")
144 _PErrorCodes = ("error_codes", False, ht.TBool, "Error codes")
145 _PSkipChecks = ("skip_checks", ht.EmptyList,
146 ht.TListOf(ht.TElemOf(constants.VERIFY_OPTIONAL_CHECKS)),
147 "Which checks to skip")
148 _PIgnoreErrors = ("ignore_errors", ht.EmptyList,
149 ht.TListOf(ht.TElemOf(constants.CV_ALL_ECODES_STRINGS)),
150 "List of error codes that should be treated as warnings")
151
152
153 _PDiskParams = \
154 ("diskparams", None,
155 ht.TMaybe(ht.TDictOf(ht.TElemOf(constants.DISK_TEMPLATES), ht.TDict)),
156 "Disk templates' parameter defaults")
157
158
159 _PHvState = ("hv_state", None, ht.TMaybeDict, "Set hypervisor states")
160 _PDiskState = ("disk_state", None, ht.TMaybeDict, "Set disk states")
161
162
163 _POpportunisticLocking = \
164 ("opportunistic_locking", False, ht.TBool,
165 ("Whether to employ opportunistic locking for nodes, meaning nodes"
166 " already locked by another opcode won't be considered for instance"
167 " allocation (only when an iallocator is used)"))
168
169 _PIgnoreIpolicy = ("ignore_ipolicy", False, ht.TBool,
170 "Whether to ignore ipolicy violations")
171
172
173 _PAllowRuntimeChgs = ("allow_runtime_changes", True, ht.TBool,
174 "Allow runtime changes (eg. memory ballooning)")
175
176
177 _PIAllocFromDesc = lambda desc: ("iallocator", None, ht.TMaybeString, desc)
178
179
180 _PNetworkName = ("network_name", ht.NoDefault, ht.TNonEmptyString,
181 "Set network name")
182
183 _PTargetGroups = \
184 ("target_groups", None, ht.TMaybeListOf(ht.TNonEmptyString),
185 "Destination group names or UUIDs (defaults to \"all but current group\")")
186
187
188 _OPID_RE = re.compile("([a-z])([A-Z])")
189
190
191 _TestClusterOsListItem = \
192 ht.TAnd(ht.TIsLength(2), ht.TItems([
193 ht.TElemOf(constants.DDMS_VALUES),
194 ht.TNonEmptyString,
195 ]))
196
197 _TestClusterOsList = ht.TMaybeListOf(_TestClusterOsListItem)
198
199
200
201 _TestNicDef = \
202 ht.Comment("NIC parameters")(ht.TDictOf(ht.TElemOf(constants.INIC_PARAMS),
203 ht.TMaybeString))
204
205 _TSetParamsResultItemItems = [
206 ht.Comment("name of changed parameter")(ht.TNonEmptyString),
207 ht.Comment("new value")(ht.TAny),
208 ]
209
210 _TSetParamsResult = \
211 ht.TListOf(ht.TAnd(ht.TIsLength(len(_TSetParamsResultItemItems)),
212 ht.TItems(_TSetParamsResultItemItems)))
213
214
215
216
217
218 _TDiskParams = \
219 ht.Comment("Disk parameters")(ht.TDictOf(ht.TNonEmptyString,
220 ht.TOr(ht.TNonEmptyString, ht.TInt)))
221
222 _TQueryRow = \
223 ht.TListOf(ht.TAnd(ht.TIsLength(2),
224 ht.TItems([ht.TElemOf(constants.RS_ALL),
225 ht.TAny])))
226
227 _TQueryResult = ht.TListOf(_TQueryRow)
228
229 _TOldQueryRow = ht.TListOf(ht.TAny)
230
231 _TOldQueryResult = ht.TListOf(_TOldQueryRow)
232
233
234 _SUMMARY_PREFIX = {
235 "CLUSTER_": "C_",
236 "GROUP_": "G_",
237 "NODE_": "N_",
238 "INSTANCE_": "I_",
239 }
240
241
242 DEPEND_ATTR = "depends"
243
244
245 COMMENT_ATTR = "comment"
249 """Convert an opcode class name to an OP_ID.
250
251 @type name: string
252 @param name: the class name, as OpXxxYyy
253 @rtype: string
254 @return: the name in the OP_XXXX_YYYY format
255
256 """
257 if not name.startswith("Op"):
258 return None
259
260
261
262
263
264 name = _OPID_RE.sub(r"\1,\2", name)
265 elems = name.split(",")
266 return "_".join(n.upper() for n in elems)
267
270 """Helper to generate type checks for objects.
271
272 @param obj: The object to generate type checks
273 @param fields_types: The fields and their types as a dict
274 @return: A ht type check function
275
276 """
277 assert set(obj.GetAllSlots()) == set(fields_types.keys()), \
278 "%s != %s" % (set(obj.GetAllSlots()), set(fields_types.keys()))
279 return ht.TStrictDict(True, True, fields_types)
280
281
282 _TQueryFieldDef = \
283 _GenerateObjectTypeCheck(objects.QueryFieldDefinition, {
284 "name": ht.TNonEmptyString,
285 "title": ht.TNonEmptyString,
286 "kind": ht.TElemOf(constants.QFT_ALL),
287 "doc": ht.TNonEmptyString,
288 })
292 """Checks that file storage is enabled.
293
294 While it doesn't really fit into this module, L{utils} was deemed too large
295 of a dependency to be imported for just one or two functions.
296
297 @raise errors.OpPrereqError: when file storage is disabled
298
299 """
300 if not constants.ENABLE_FILE_STORAGE:
301 raise errors.OpPrereqError("File storage disabled at configure time",
302 errors.ECODE_INVAL)
303
306 """Checks that shared file storage is enabled.
307
308 While it doesn't really fit into this module, L{utils} was deemed too large
309 of a dependency to be imported for just one or two functions.
310
311 @raise errors.OpPrereqError: when shared file storage is disabled
312
313 """
314 if not constants.ENABLE_SHARED_FILE_STORAGE:
315 raise errors.OpPrereqError("Shared file storage disabled at"
316 " configure time", errors.ECODE_INVAL)
317
329
332 """Builds check for disk template.
333
334 @type accept_none: bool
335 @param accept_none: whether to accept None as a correct value
336 @rtype: callable
337
338 """
339 template_check = ht.TElemOf(constants.DISK_TEMPLATES)
340
341 if accept_none:
342 template_check = ht.TMaybe(template_check)
343
344 return ht.TAnd(template_check, _CheckFileStorage)
345
358
359
360
361 _PStorageType = ("storage_type", ht.NoDefault, _CheckStorageType,
362 "Storage type")
367 """Ensure a given CIDR notation type is valid.
368
369 """
370 try:
371 ipaddr.IPv4Network(value)
372 except ipaddr.AddressValueError:
373 return False
374 return True
375
379 """Ensure a given CIDR notation type is valid.
380
381 """
382 try:
383 ipaddr.IPv4Address(value)
384 except ipaddr.AddressValueError:
385 return False
386 return True
387
391 """Ensure a given CIDR notation type is valid.
392
393 """
394 try:
395 ipaddr.IPv6Address(value)
396 except ipaddr.AddressValueError:
397 return False
398 return True
399
403 """Ensure a given CIDR notation type is valid.
404
405 """
406 try:
407 ipaddr.IPv6Network(value)
408 except ipaddr.AddressValueError:
409 return False
410 return True
411
412
413 _TIpAddress4 = ht.TAnd(ht.TString, _CheckCIDRAddrNotation)
414 _TIpAddress6 = ht.TAnd(ht.TString, _CheckCIDR6AddrNotation)
415 _TIpNetwork4 = ht.TAnd(ht.TString, _CheckCIDRNetNotation)
416 _TIpNetwork6 = ht.TAnd(ht.TString, _CheckCIDR6NetNotation)
417 _TMaybeAddr4List = ht.TMaybe(ht.TListOf(_TIpAddress4))
421 """Meta class for opcode definitions.
422
423 """
424 - def __new__(mcs, name, bases, attrs):
425 """Called when a class should be created.
426
427 @param mcs: The meta class
428 @param name: Name of created class
429 @param bases: Base classes
430 @type attrs: dict
431 @param attrs: Class attributes
432
433 """
434 assert "OP_ID" not in attrs, "Class '%s' defining OP_ID" % name
435
436 slots = mcs._GetSlots(attrs)
437 assert "OP_DSC_FIELD" not in attrs or attrs["OP_DSC_FIELD"] in slots, \
438 "Class '%s' uses unknown field in OP_DSC_FIELD" % name
439 assert ("OP_DSC_FORMATTER" not in attrs or
440 callable(attrs["OP_DSC_FORMATTER"])), \
441 ("Class '%s' uses non-callable in OP_DSC_FORMATTER (%s)" %
442 (name, type(attrs["OP_DSC_FORMATTER"])))
443
444 attrs["OP_ID"] = _NameToId(name)
445
446 return outils.AutoSlots.__new__(mcs, name, bases, attrs)
447
448 @classmethod
450 """Build the slots out of OP_PARAMS.
451
452 """
453
454 params = attrs.setdefault("OP_PARAMS", [])
455
456
457 return [pname for (pname, _, _, _) in params]
458
461 """A simple serializable object.
462
463 This object serves as a parent class for OpCode without any custom
464 field handling.
465
466 """
467
468
469 __metaclass__ = _AutoOpParamSlots
470
472 """Generic serializer.
473
474 This method just returns the contents of the instance as a
475 dictionary.
476
477 @rtype: C{dict}
478 @return: the instance attributes and their values
479
480 """
481 state = {}
482 for name in self.GetAllSlots():
483 if hasattr(self, name):
484 state[name] = getattr(self, name)
485 return state
486
488 """Generic unserializer.
489
490 This method just restores from the serialized state the attributes
491 of the current instance.
492
493 @param state: the serialized opcode data
494 @type state: C{dict}
495
496 """
497 if not isinstance(state, dict):
498 raise ValueError("Invalid data to __setstate__: expected dict, got %s" %
499 type(state))
500
501 for name in self.GetAllSlots():
502 if name not in state and hasattr(self, name):
503 delattr(self, name)
504
505 for name in state:
506 setattr(self, name, state[name])
507
508 @classmethod
510 """Compute list of all parameters for an opcode.
511
512 """
513 slots = []
514 for parent in cls.__mro__:
515 slots.extend(getattr(parent, "OP_PARAMS", []))
516 return slots
517
519 """Validate opcode parameters, optionally setting default values.
520
521 @type set_defaults: bool
522 @param set_defaults: Whether to set default values
523 @raise errors.OpPrereqError: When a parameter value doesn't match
524 requirements
525
526 """
527 for (attr_name, default, test, _) in self.GetAllParams():
528 assert test == ht.NoType or callable(test)
529
530 if not hasattr(self, attr_name):
531 if default == ht.NoDefault:
532 raise errors.OpPrereqError("Required parameter '%s.%s' missing" %
533 (self.OP_ID, attr_name),
534 errors.ECODE_INVAL)
535 elif set_defaults:
536 if callable(default):
537 dval = default()
538 else:
539 dval = default
540 setattr(self, attr_name, dval)
541
542 if test == ht.NoType:
543
544 continue
545
546 if set_defaults or hasattr(self, attr_name):
547 attr_val = getattr(self, attr_name)
548 if not test(attr_val):
549 logging.error("OpCode %s, parameter %s, has invalid type %s/value"
550 " '%s' expecting type %s",
551 self.OP_ID, attr_name, type(attr_val), attr_val, test)
552 raise errors.OpPrereqError("Parameter '%s.%s' fails validation" %
553 (self.OP_ID, attr_name),
554 errors.ECODE_INVAL)
555
577
578
579 TNoRelativeJobDependencies = _BuildJobDepCheck(False)
580
581
582 _TJobIdListItem = \
583 ht.TAnd(ht.TIsLength(2),
584 ht.TItems([ht.Comment("success")(ht.TBool),
585 ht.Comment("Job ID if successful, error message"
586 " otherwise")(ht.TOr(ht.TString,
587 ht.TJobId))]))
588 TJobIdList = ht.TListOf(_TJobIdListItem)
589
590
591 TJobIdListOnly = ht.TStrictDict(True, True, {
592 constants.JOB_IDS_KEY: ht.Comment("List of submitted jobs")(TJobIdList),
593 })
594
595
596 -class OpCode(BaseOpCode):
597 """Abstract OpCode.
598
599 This is the root of the actual OpCode hierarchy. All clases derived
600 from this class should override OP_ID.
601
602 @cvar OP_ID: The ID of this opcode. This should be unique amongst all
603 children of this class.
604 @cvar OP_DSC_FIELD: The name of a field whose value will be included in the
605 string returned by Summary(); see the docstring of that
606 method for details).
607 @cvar OP_DSC_FORMATTER: A callable that should format the OP_DSC_FIELD; if
608 not present, then the field will be simply converted
609 to string
610 @cvar OP_PARAMS: List of opcode attributes, the default values they should
611 get if not already defined, and types they must match.
612 @cvar OP_RESULT: Callable to verify opcode result
613 @cvar WITH_LU: Boolean that specifies whether this should be included in
614 mcpu's dispatch table
615 @ivar dry_run: Whether the LU should be run in dry-run mode, i.e. just
616 the check steps
617 @ivar priority: Opcode priority for queue
618
619 """
620
621
622 WITH_LU = True
623 OP_PARAMS = [
624 ("dry_run", None, ht.TMaybeBool, "Run checks only, don't execute"),
625 ("debug_level", None, ht.TMaybe(ht.TNonNegativeInt), "Debug level"),
626 ("priority", constants.OP_PRIO_DEFAULT,
627 ht.TElemOf(constants.OP_PRIO_SUBMIT_VALID), "Opcode priority"),
628 (DEPEND_ATTR, None, _BuildJobDepCheck(True),
629 "Job dependencies; if used through ``SubmitManyJobs`` relative (negative)"
630 " job IDs can be used; see :doc:`design document <design-chained-jobs>`"
631 " for details"),
632 (COMMENT_ATTR, None, ht.TMaybeString,
633 "Comment describing the purpose of the opcode"),
634 ]
635 OP_RESULT = None
636
638 """Specialized getstate for opcodes.
639
640 This method adds to the state dictionary the OP_ID of the class,
641 so that on unload we can identify the correct class for
642 instantiating the opcode.
643
644 @rtype: C{dict}
645 @return: the state as a dictionary
646
647 """
648 data = BaseOpCode.__getstate__(self)
649 data["OP_ID"] = self.OP_ID
650 return data
651
652 @classmethod
654 """Generic load opcode method.
655
656 The method identifies the correct opcode class from the dict-form
657 by looking for a OP_ID key, if this is not found, or its value is
658 not available in this module as a child of this class, we fail.
659
660 @type data: C{dict}
661 @param data: the serialized opcode
662
663 """
664 if not isinstance(data, dict):
665 raise ValueError("Invalid data to LoadOpCode (%s)" % type(data))
666 if "OP_ID" not in data:
667 raise ValueError("Invalid data to LoadOpcode, missing OP_ID")
668 op_id = data["OP_ID"]
669 op_class = None
670 if op_id in OP_MAPPING:
671 op_class = OP_MAPPING[op_id]
672 else:
673 raise ValueError("Invalid data to LoadOpCode: OP_ID %s unsupported" %
674 op_id)
675 op = op_class()
676 new_data = data.copy()
677 del new_data["OP_ID"]
678 op.__setstate__(new_data)
679 return op
680
682 """Generates a summary description of this opcode.
683
684 The summary is the value of the OP_ID attribute (without the "OP_"
685 prefix), plus the value of the OP_DSC_FIELD attribute, if one was
686 defined; this field should allow to easily identify the operation
687 (for an instance creation job, e.g., it would be the instance
688 name).
689
690 """
691 assert self.OP_ID is not None and len(self.OP_ID) > 3
692
693 txt = self.OP_ID[3:]
694 field_name = getattr(self, "OP_DSC_FIELD", None)
695 if field_name:
696 field_value = getattr(self, field_name, None)
697 field_formatter = getattr(self, "OP_DSC_FORMATTER", None)
698 if callable(field_formatter):
699 field_value = field_formatter(field_value)
700 elif isinstance(field_value, (list, tuple)):
701 field_value = ",".join(str(i) for i in field_value)
702 txt = "%s(%s)" % (txt, field_value)
703 return txt
704
706 """Generates a compact summary description of the opcode.
707
708 """
709 assert self.OP_ID.startswith("OP_")
710
711 text = self.OP_ID[3:]
712
713 for (prefix, supplement) in _SUMMARY_PREFIX.items():
714 if text.startswith(prefix):
715 return supplement + text[len(prefix):]
716
717 return text
718
719
720
721
722 -class OpClusterPostInit(OpCode):
723 """Post cluster initialization.
724
725 This opcode does not touch the cluster at all. Its purpose is to run hooks
726 after the cluster has been initialized.
727
728 """
729 OP_RESULT = ht.TBool
730
733 """Destroy the cluster.
734
735 This opcode has no other parameters. All the state is irreversibly
736 lost after the execution of this opcode.
737
738 """
739 OP_RESULT = ht.TNonEmptyString
740
745
760
773
795
802
805 """Verifies the status of all disks in a node group.
806
807 Result: a tuple of three elements:
808 - dict of node names with issues (values: error msg)
809 - list of instances with degraded disks (that should be activated)
810 - dict of instances with missing logical volumes (values: (node, vol)
811 pairs with details about the missing volumes)
812
813 In normal operation, all lists should be empty. A non-empty instance
814 list (3rd element of the result) is still ok (errors were fixed) but
815 non-empty node list means some node is down, and probably there are
816 unfixable drbd errors.
817
818 Note that only instances that are drbd-based are taken into
819 consideration. This might need to be revisited in the future.
820
821 """
822 OP_DSC_FIELD = "group_name"
823 OP_PARAMS = [
824 _PGroupName,
825 ]
826 OP_RESULT = \
827 ht.TAnd(ht.TIsLength(3),
828 ht.TItems([ht.TDictOf(ht.TString, ht.TString),
829 ht.TListOf(ht.TString),
830 ht.TDictOf(ht.TString,
831 ht.TListOf(ht.TListOf(ht.TString)))]))
832
835 """Verify the disk sizes of the instances and fixes configuration
836 mimatches.
837
838 Parameters: optional instances list, in case we want to restrict the
839 checks to only a subset of the instances.
840
841 Result: a list of tuples, (instance, disk, new-size) for changed
842 configurations.
843
844 In normal operation, the list should be empty.
845
846 @type instances: list
847 @ivar instances: the list of instances to check, or empty for all instances
848
849 """
850 OP_PARAMS = [
851 ("instances", ht.EmptyList, ht.TListOf(ht.TNonEmptyString), None),
852 ]
853 OP_RESULT = ht.TListOf(ht.TAnd(ht.TIsLength(3),
854 ht.TItems([ht.TNonEmptyString,
855 ht.TNonNegativeInt,
856 ht.TNonNegativeInt])))
857
865
881
884 """Change the parameters of the cluster.
885
886 @type vg_name: C{str} or C{None}
887 @ivar vg_name: The new volume group name or None to disable LVM usage.
888
889 """
890 OP_PARAMS = [
891 _PHvState,
892 _PDiskState,
893 ("vg_name", None, ht.TMaybe(ht.TString), "Volume group name"),
894 ("enabled_hypervisors", None,
895 ht.TMaybe(ht.TAnd(ht.TListOf(ht.TElemOf(constants.HYPER_TYPES)),
896 ht.TTrue)),
897 "List of enabled hypervisors"),
898 ("hvparams", None,
899 ht.TMaybe(ht.TDictOf(ht.TNonEmptyString, ht.TDict)),
900 "Cluster-wide hypervisor parameter defaults, hypervisor-dependent"),
901 ("beparams", None, ht.TMaybeDict,
902 "Cluster-wide backend parameter defaults"),
903 ("os_hvp", None, ht.TMaybe(ht.TDictOf(ht.TNonEmptyString, ht.TDict)),
904 "Cluster-wide per-OS hypervisor parameter defaults"),
905 ("osparams", None,
906 ht.TMaybe(ht.TDictOf(ht.TNonEmptyString, ht.TDict)),
907 "Cluster-wide OS parameter defaults"),
908 _PDiskParams,
909 ("candidate_pool_size", None, ht.TMaybe(ht.TPositiveInt),
910 "Master candidate pool size"),
911 ("uid_pool", None, ht.NoType,
912 "Set UID pool, must be list of lists describing UID ranges (two items,"
913 " start and end inclusive)"),
914 ("add_uids", None, ht.NoType,
915 "Extend UID pool, must be list of lists describing UID ranges (two"
916 " items, start and end inclusive) to be added"),
917 ("remove_uids", None, ht.NoType,
918 "Shrink UID pool, must be list of lists describing UID ranges (two"
919 " items, start and end inclusive) to be removed"),
920 ("maintain_node_health", None, ht.TMaybeBool,
921 "Whether to automatically maintain node health"),
922 ("prealloc_wipe_disks", None, ht.TMaybeBool,
923 "Whether to wipe disks before allocating them to instances"),
924 ("nicparams", None, ht.TMaybeDict, "Cluster-wide NIC parameter defaults"),
925 ("ndparams", None, ht.TMaybeDict, "Cluster-wide node parameter defaults"),
926 ("ipolicy", None, ht.TMaybeDict,
927 "Cluster-wide :ref:`instance policy <rapi-ipolicy>` specs"),
928 ("drbd_helper", None, ht.TMaybe(ht.TString), "DRBD helper program"),
929 ("default_iallocator", None, ht.TMaybe(ht.TString),
930 "Default iallocator for cluster"),
931 ("master_netdev", None, ht.TMaybe(ht.TString),
932 "Master network device"),
933 ("master_netmask", None, ht.TMaybe(ht.TNonNegativeInt),
934 "Netmask of the master IP"),
935 ("reserved_lvs", None, ht.TMaybeListOf(ht.TNonEmptyString),
936 "List of reserved LVs"),
937 ("hidden_os", None, _TestClusterOsList,
938 "Modify list of hidden operating systems: each modification must have"
939 " two items, the operation and the OS name; the operation can be"
940 " ``%s`` or ``%s``" % (constants.DDM_ADD, constants.DDM_REMOVE)),
941 ("blacklisted_os", None, _TestClusterOsList,
942 "Modify list of blacklisted operating systems: each modification must"
943 " have two items, the operation and the OS name; the operation can be"
944 " ``%s`` or ``%s``" % (constants.DDM_ADD, constants.DDM_REMOVE)),
945 ("use_external_mip_script", None, ht.TMaybeBool,
946 "Whether to use an external master IP address setup script"),
947 ]
948 OP_RESULT = ht.TNone
949
952 """Force a full push of the cluster configuration.
953
954 """
955 OP_RESULT = ht.TNone
956
959 """Activate the master IP on the master node.
960
961 """
962 OP_RESULT = ht.TNone
963
966 """Deactivate the master IP on the master node.
967
968 """
969 OP_RESULT = ht.TNone
970
973 """Query for resources/items.
974
975 @ivar what: Resources to query for, must be one of L{constants.QR_VIA_OP}
976 @ivar fields: List of fields to retrieve
977 @ivar qfilter: Query filter
978
979 """
980 OP_DSC_FIELD = "what"
981 OP_PARAMS = [
982 _PQueryWhat,
983 _PUseLocking,
984 ("fields", ht.NoDefault, ht.TListOf(ht.TNonEmptyString),
985 "Requested fields"),
986 ("qfilter", None, ht.TMaybe(ht.TList),
987 "Query filter"),
988 ]
989 OP_RESULT = \
990 _GenerateObjectTypeCheck(objects.QueryResponse, {
991 "fields": ht.TListOf(_TQueryFieldDef),
992 "data": _TQueryResult,
993 })
994
1013
1016 """Interact with OOB."""
1017 OP_PARAMS = [
1018 ("node_names", ht.EmptyList, ht.TListOf(ht.TNonEmptyString),
1019 "List of nodes to run the OOB command against"),
1020 ("command", ht.NoDefault, ht.TElemOf(constants.OOB_COMMANDS),
1021 "OOB command to be run"),
1022 ("timeout", constants.OOB_TIMEOUT, ht.TInt,
1023 "Timeout before the OOB helper will be terminated"),
1024 ("ignore_status", False, ht.TBool,
1025 "Ignores the node offline status for power off"),
1026 ("power_delay", constants.OOB_POWER_DELAY, ht.TNonNegativeFloat,
1027 "Time in seconds to wait between powering on nodes"),
1028 ]
1029
1030 OP_RESULT = _TQueryResult
1031
1034 """Runs a restricted command on node(s).
1035
1036 """
1037 OP_PARAMS = [
1038 _PUseLocking,
1039 ("nodes", ht.NoDefault, ht.TListOf(ht.TNonEmptyString),
1040 "Nodes on which the command should be run (at least one)"),
1041 ("command", ht.NoDefault, ht.TNonEmptyString,
1042 "Command name (no parameters)"),
1043 ]
1044
1045 _RESULT_ITEMS = [
1046 ht.Comment("success")(ht.TBool),
1047 ht.Comment("output or error message")(ht.TString),
1048 ]
1049
1050 OP_RESULT = \
1051 ht.TListOf(ht.TAnd(ht.TIsLength(len(_RESULT_ITEMS)),
1052 ht.TItems(_RESULT_ITEMS)))
1053
1058 """Remove a node.
1059
1060 @type node_name: C{str}
1061 @ivar node_name: The name of the node to remove. If the node still has
1062 instances on it, the operation will fail.
1063
1064 """
1065 OP_DSC_FIELD = "node_name"
1066 OP_PARAMS = [
1067 _PNodeName,
1068 ]
1069 OP_RESULT = ht.TNone
1070
1073 """Add a node to the cluster.
1074
1075 @type node_name: C{str}
1076 @ivar node_name: The name of the node to add. This can be a short name,
1077 but it will be expanded to the FQDN.
1078 @type primary_ip: IP address
1079 @ivar primary_ip: The primary IP of the node. This will be ignored when the
1080 opcode is submitted, but will be filled during the node
1081 add (so it will be visible in the job query).
1082 @type secondary_ip: IP address
1083 @ivar secondary_ip: The secondary IP of the node. This needs to be passed
1084 if the cluster has been initialized in 'dual-network'
1085 mode, otherwise it must not be given.
1086 @type readd: C{bool}
1087 @ivar readd: Whether to re-add an existing node to the cluster. If
1088 this is not passed, then the operation will abort if the node
1089 name is already in the cluster; use this parameter to 'repair'
1090 a node that had its configuration broken, or was reinstalled
1091 without removal from the cluster.
1092 @type group: C{str}
1093 @ivar group: The node group to which this node will belong.
1094 @type vm_capable: C{bool}
1095 @ivar vm_capable: The vm_capable node attribute
1096 @type master_capable: C{bool}
1097 @ivar master_capable: The master_capable node attribute
1098
1099 """
1100 OP_DSC_FIELD = "node_name"
1101 OP_PARAMS = [
1102 _PNodeName,
1103 _PHvState,
1104 _PDiskState,
1105 ("primary_ip", None, ht.NoType, "Primary IP address"),
1106 ("secondary_ip", None, ht.TMaybeString, "Secondary IP address"),
1107 ("readd", False, ht.TBool, "Whether node is re-added to cluster"),
1108 ("group", None, ht.TMaybeString, "Initial node group"),
1109 ("master_capable", None, ht.TMaybeBool,
1110 "Whether node can become master or master candidate"),
1111 ("vm_capable", None, ht.TMaybeBool,
1112 "Whether node can host instances"),
1113 ("ndparams", None, ht.TMaybeDict, "Node parameters"),
1114 ]
1115 OP_RESULT = ht.TNone
1116
1127
1137
1140 """Get information on storage for node(s)."""
1141 OP_PARAMS = [
1142 _POutputFields,
1143 _PStorageType,
1144 ("nodes", ht.EmptyList, ht.TListOf(ht.TNonEmptyString), "List of nodes"),
1145 ("name", None, ht.TMaybeString, "Storage name"),
1146 ]
1147 OP_RESULT = _TOldQueryResult
1148
1160
1172
1175 """Change the parameters of a node."""
1176 OP_DSC_FIELD = "node_name"
1177 OP_PARAMS = [
1178 _PNodeName,
1179 _PForce,
1180 _PHvState,
1181 _PDiskState,
1182 ("master_candidate", None, ht.TMaybeBool,
1183 "Whether the node should become a master candidate"),
1184 ("offline", None, ht.TMaybeBool,
1185 "Whether the node should be marked as offline"),
1186 ("drained", None, ht.TMaybeBool,
1187 "Whether the node should be marked as drained"),
1188 ("auto_promote", False, ht.TBool,
1189 "Whether node(s) should be promoted to master candidate if necessary"),
1190 ("master_capable", None, ht.TMaybeBool,
1191 "Denote whether node can become master or master candidate"),
1192 ("vm_capable", None, ht.TMaybeBool,
1193 "Denote whether node can host instances"),
1194 ("secondary_ip", None, ht.TMaybeString,
1195 "Change node's secondary IP address"),
1196 ("ndparams", None, ht.TMaybeDict, "Set node parameters"),
1197 ("powered", None, ht.TMaybeBool,
1198 "Whether the node should be marked as powered"),
1199 ]
1200 OP_RESULT = _TSetParamsResult
1201
1211
1227
1230 """Evacuate instances off a number of nodes."""
1231 OP_DSC_FIELD = "node_name"
1232 OP_PARAMS = [
1233 _PEarlyRelease,
1234 _PNodeName,
1235 ("remote_node", None, ht.TMaybeString, "New secondary node"),
1236 _PIAllocFromDesc("Iallocator for computing solution"),
1237 ("mode", ht.NoDefault, ht.TElemOf(constants.NODE_EVAC_MODES),
1238 "Node evacuation mode"),
1239 ]
1240 OP_RESULT = TJobIdListOnly
1241
1246 """Create an instance.
1247
1248 @ivar instance_name: Instance name
1249 @ivar mode: Instance creation mode (one of L{constants.INSTANCE_CREATE_MODES})
1250 @ivar source_handshake: Signed handshake from source (remote import only)
1251 @ivar source_x509_ca: Source X509 CA in PEM format (remote import only)
1252 @ivar source_instance_name: Previous name of instance (remote import only)
1253 @ivar source_shutdown_timeout: Shutdown timeout used for source instance
1254 (remote import only)
1255
1256 """
1257 OP_DSC_FIELD = "instance_name"
1258 OP_PARAMS = [
1259 _PInstanceName,
1260 _PForceVariant,
1261 _PWaitForSync,
1262 _PNameCheck,
1263 _PIgnoreIpolicy,
1264 _POpportunisticLocking,
1265 ("beparams", ht.EmptyDict, ht.TDict, "Backend parameters for instance"),
1266 ("disks", ht.NoDefault, ht.TListOf(_TDiskParams),
1267 "Disk descriptions, for example ``[{\"%s\": 100}, {\"%s\": 5}]``;"
1268 " each disk definition must contain a ``%s`` value and"
1269 " can contain an optional ``%s`` value denoting the disk access mode"
1270 " (%s)" %
1271 (constants.IDISK_SIZE, constants.IDISK_SIZE, constants.IDISK_SIZE,
1272 constants.IDISK_MODE,
1273 " or ".join("``%s``" % i for i in sorted(constants.DISK_ACCESS_SET)))),
1274 ("disk_template", ht.NoDefault, _BuildDiskTemplateCheck(True),
1275 "Disk template"),
1276 ("file_driver", None, ht.TMaybe(ht.TElemOf(constants.FILE_DRIVER)),
1277 "Driver for file-backed disks"),
1278 ("file_storage_dir", None, ht.TMaybeString,
1279 "Directory for storing file-backed disks"),
1280 ("hvparams", ht.EmptyDict, ht.TDict,
1281 "Hypervisor parameters for instance, hypervisor-dependent"),
1282 ("hypervisor", None, ht.TMaybeString, "Hypervisor"),
1283 _PIAllocFromDesc("Iallocator for deciding which node(s) to use"),
1284 ("identify_defaults", False, ht.TBool,
1285 "Reset instance parameters to default if equal"),
1286 ("ip_check", True, ht.TBool, _PIpCheckDoc),
1287 ("conflicts_check", True, ht.TBool, "Check for conflicting IPs"),
1288 ("mode", ht.NoDefault, ht.TElemOf(constants.INSTANCE_CREATE_MODES),
1289 "Instance creation mode"),
1290 ("nics", ht.NoDefault, ht.TListOf(_TestNicDef),
1291 "List of NIC (network interface) definitions, for example"
1292 " ``[{}, {}, {\"%s\": \"198.51.100.4\"}]``; each NIC definition can"
1293 " contain the optional values %s" %
1294 (constants.INIC_IP,
1295 ", ".join("``%s``" % i for i in sorted(constants.INIC_PARAMS)))),
1296 ("no_install", None, ht.TMaybeBool,
1297 "Do not install the OS (will disable automatic start)"),
1298 ("osparams", ht.EmptyDict, ht.TDict, "OS parameters for instance"),
1299 ("os_type", None, ht.TMaybeString, "Operating system"),
1300 ("pnode", None, ht.TMaybeString, "Primary node"),
1301 ("snode", None, ht.TMaybeString, "Secondary node"),
1302 ("source_handshake", None, ht.TMaybe(ht.TList),
1303 "Signed handshake from source (remote import only)"),
1304 ("source_instance_name", None, ht.TMaybeString,
1305 "Source instance name (remote import only)"),
1306 ("source_shutdown_timeout", constants.DEFAULT_SHUTDOWN_TIMEOUT,
1307 ht.TNonNegativeInt,
1308 "How long source instance was given to shut down (remote import only)"),
1309 ("source_x509_ca", None, ht.TMaybeString,
1310 "Source X509 CA in PEM format (remote import only)"),
1311 ("src_node", None, ht.TMaybeString, "Source node for import"),
1312 ("src_path", None, ht.TMaybeString, "Source directory for import"),
1313 ("start", True, ht.TBool, "Whether to start instance after creation"),
1314 ("tags", ht.EmptyList, ht.TListOf(ht.TNonEmptyString), "Instance tags"),
1315 ]
1316 OP_RESULT = ht.Comment("instance nodes")(ht.TListOf(ht.TNonEmptyString))
1317
1320 """Allocates multiple instances.
1321
1322 """
1323 OP_PARAMS = [
1324 _POpportunisticLocking,
1325 _PIAllocFromDesc("Iallocator used to allocate all the instances"),
1326 ("instances", ht.EmptyList, ht.TListOf(ht.TInstanceOf(OpInstanceCreate)),
1327 "List of instance create opcodes describing the instances to allocate"),
1328 ]
1329 _JOB_LIST = ht.Comment("List of submitted jobs")(TJobIdList)
1330 ALLOCATABLE_KEY = "allocatable"
1331 FAILED_KEY = "allocatable"
1332 OP_RESULT = ht.TStrictDict(True, True, {
1333 constants.JOB_IDS_KEY: _JOB_LIST,
1334 ALLOCATABLE_KEY: ht.TListOf(ht.TNonEmptyString),
1335 FAILED_KEY: ht.TListOf(ht.TNonEmptyString),
1336 })
1337
1347
1349 """Generic unserializer.
1350
1351 This method just restores from the serialized state the attributes
1352 of the current instance.
1353
1354 @param state: the serialized opcode data
1355 @type state: C{dict}
1356
1357 """
1358 if not isinstance(state, dict):
1359 raise ValueError("Invalid data to __setstate__: expected dict, got %s" %
1360 type(state))
1361
1362 if "instances" in state:
1363 state["instances"] = map(OpCode.LoadOpCode, state["instances"])
1364
1365 return OpCode.__setstate__(self, state)
1366
1368 """Validates this opcode.
1369
1370 We do this recursively.
1371
1372 """
1373 OpCode.Validate(self, set_defaults)
1374
1375 for inst in self.instances:
1376 inst.Validate(set_defaults)
1377
1380 """Reinstall an instance's OS."""
1381 OP_DSC_FIELD = "instance_name"
1382 OP_PARAMS = [
1383 _PInstanceName,
1384 _PForceVariant,
1385 ("os_type", None, ht.TMaybeString, "Instance operating system"),
1386 ("osparams", None, ht.TMaybeDict, "Temporary OS parameters"),
1387 ]
1388 OP_RESULT = ht.TNone
1389
1401
1404 """Rename an instance."""
1405 OP_PARAMS = [
1406 _PInstanceName,
1407 _PNameCheck,
1408 ("new_name", ht.NoDefault, ht.TNonEmptyString, "New instance name"),
1409 ("ip_check", False, ht.TBool, _PIpCheckDoc),
1410 ]
1411 OP_RESULT = ht.Comment("New instance name")(ht.TNonEmptyString)
1412
1415 """Startup an instance."""
1416 OP_DSC_FIELD = "instance_name"
1417 OP_PARAMS = [
1418 _PInstanceName,
1419 _PForce,
1420 _PIgnoreOfflineNodes,
1421 ("hvparams", ht.EmptyDict, ht.TDict,
1422 "Temporary hypervisor parameters, hypervisor-dependent"),
1423 ("beparams", ht.EmptyDict, ht.TDict, "Temporary backend parameters"),
1424 _PNoRemember,
1425 _PStartupPaused,
1426 ]
1427 OP_RESULT = ht.TNone
1428
1442
1445 """Reboot an instance."""
1446 OP_DSC_FIELD = "instance_name"
1447 OP_PARAMS = [
1448 _PInstanceName,
1449 _PShutdownTimeout,
1450 ("ignore_secondaries", False, ht.TBool,
1451 "Whether to start the instance even if secondary disks are failing"),
1452 ("reboot_type", ht.NoDefault, ht.TElemOf(constants.REBOOT_TYPES),
1453 "How to reboot instance"),
1454 ]
1455 OP_RESULT = ht.TNone
1456
1459 """Replace the disks of an instance."""
1460 OP_DSC_FIELD = "instance_name"
1461 OP_PARAMS = [
1462 _PInstanceName,
1463 _PEarlyRelease,
1464 _PIgnoreIpolicy,
1465 ("mode", ht.NoDefault, ht.TElemOf(constants.REPLACE_MODES),
1466 "Replacement mode"),
1467 ("disks", ht.EmptyList, ht.TListOf(ht.TNonNegativeInt),
1468 "Disk indexes"),
1469 ("remote_node", None, ht.TMaybeString, "New secondary node"),
1470 _PIAllocFromDesc("Iallocator for deciding new secondary node"),
1471 ]
1472 OP_RESULT = ht.TNone
1473
1488
1491 """Migrate an instance.
1492
1493 This migrates (without shutting down an instance) to its secondary
1494 node.
1495
1496 @ivar instance_name: the name of the instance
1497 @ivar mode: the migration mode (live, non-live or None for auto)
1498
1499 """
1500 OP_DSC_FIELD = "instance_name"
1501 OP_PARAMS = [
1502 _PInstanceName,
1503 _PMigrationMode,
1504 _PMigrationLive,
1505 _PMigrationTargetNode,
1506 _PAllowRuntimeChgs,
1507 _PIgnoreIpolicy,
1508 ("cleanup", False, ht.TBool,
1509 "Whether a previously failed migration should be cleaned up"),
1510 _PIAllocFromDesc("Iallocator for deciding the target node for"
1511 " shared-storage instances"),
1512 ("allow_failover", False, ht.TBool,
1513 "Whether we can fallback to failover if migration is not possible"),
1514 ]
1515 OP_RESULT = ht.TNone
1516
1537
1546
1560
1570
1573 """Recreate an instance's disks."""
1574 _TDiskChanges = \
1575 ht.TAnd(ht.TIsLength(2),
1576 ht.TItems([ht.Comment("Disk index")(ht.TNonNegativeInt),
1577 ht.Comment("Parameters")(_TDiskParams)]))
1578
1579 OP_DSC_FIELD = "instance_name"
1580 OP_PARAMS = [
1581 _PInstanceName,
1582 ("disks", ht.EmptyList,
1583 ht.TOr(ht.TListOf(ht.TNonNegativeInt), ht.TListOf(_TDiskChanges)),
1584 "List of disk indexes (deprecated) or a list of tuples containing a disk"
1585 " index and a possibly empty dictionary with disk parameter changes"),
1586 ("nodes", ht.EmptyList, ht.TListOf(ht.TNonEmptyString),
1587 "New instance nodes, if relocation is desired"),
1588 _PIAllocFromDesc("Iallocator for deciding new nodes"),
1589 ]
1590 OP_RESULT = ht.TNone
1591
1602
1605 """Compute the run-time status of instances."""
1606 OP_PARAMS = [
1607 _PUseLocking,
1608 ("instances", ht.EmptyList, ht.TListOf(ht.TNonEmptyString),
1609 "Instance names"),
1610 ("static", False, ht.TBool,
1611 "Whether to only return configuration data without querying"
1612 " nodes"),
1613 ]
1614 OP_RESULT = ht.TDictOf(ht.TNonEmptyString, ht.TDict)
1615
1618 """Generates a check for modification lists.
1619
1620 """
1621
1622
1623 old_mod_item_fn = \
1624 ht.TAnd(ht.TIsLength(2), ht.TItems([
1625 ht.TOr(ht.TElemOf(constants.DDMS_VALUES), ht.TNonNegativeInt),
1626 fn,
1627 ]))
1628
1629
1630 mod_item_fn = \
1631 ht.TAnd(ht.TIsLength(3), ht.TItems([
1632 ht.TElemOf(constants.DDMS_VALUES_WITH_MODIFY),
1633 ht.Comment("Disk index, can be negative, e.g. -1 for last disk")(ht.TInt),
1634 fn,
1635 ]))
1636
1637 return ht.TOr(ht.Comment("Recommended")(ht.TListOf(mod_item_fn)),
1638 ht.Comment("Deprecated")(ht.TListOf(old_mod_item_fn)))
1639
1642 """Change the parameters of an instance.
1643
1644 """
1645 TestNicModifications = _TestInstSetParamsModList(_TestNicDef)
1646 TestDiskModifications = _TestInstSetParamsModList(_TDiskParams)
1647
1648 OP_DSC_FIELD = "instance_name"
1649 OP_PARAMS = [
1650 _PInstanceName,
1651 _PForce,
1652 _PForceVariant,
1653 _PIgnoreIpolicy,
1654 ("nics", ht.EmptyList, TestNicModifications,
1655 "List of NIC changes: each item is of the form ``(op, index, settings)``,"
1656 " ``op`` is one of ``%s``, ``%s`` or ``%s``, ``index`` can be either -1"
1657 " to refer to the last position, or a zero-based index number; a"
1658 " deprecated version of this parameter used the form ``(op, settings)``,"
1659 " where ``op`` can be ``%s`` to add a new NIC with the specified"
1660 " settings, ``%s`` to remove the last NIC or a number to modify the"
1661 " settings of the NIC with that index" %
1662 (constants.DDM_ADD, constants.DDM_MODIFY, constants.DDM_REMOVE,
1663 constants.DDM_ADD, constants.DDM_REMOVE)),
1664 ("disks", ht.EmptyList, TestDiskModifications,
1665 "List of disk changes; see ``nics``"),
1666 ("beparams", ht.EmptyDict, ht.TDict, "Per-instance backend parameters"),
1667 ("runtime_mem", None, ht.TMaybePositiveInt, "New runtime memory"),
1668 ("hvparams", ht.EmptyDict, ht.TDict,
1669 "Per-instance hypervisor parameters, hypervisor-dependent"),
1670 ("disk_template", None, ht.TMaybe(_BuildDiskTemplateCheck(False)),
1671 "Disk template for instance"),
1672 ("remote_node", None, ht.TMaybeString,
1673 "Secondary node (used when changing disk template)"),
1674 ("os_name", None, ht.TMaybeString,
1675 "Change the instance's OS without reinstalling the instance"),
1676 ("osparams", None, ht.TMaybeDict, "Per-instance OS parameters"),
1677 ("wait_for_sync", True, ht.TBool,
1678 "Whether to wait for the disk to synchronize, when changing template"),
1679 ("offline", None, ht.TMaybeBool, "Whether to mark instance as offline"),
1680 ("conflicts_check", True, ht.TBool, "Check for conflicting IPs"),
1681 ]
1682 OP_RESULT = _TSetParamsResult
1683
1686 """Grow a disk of an instance."""
1687 OP_DSC_FIELD = "instance_name"
1688 OP_PARAMS = [
1689 _PInstanceName,
1690 _PWaitForSync,
1691 ("disk", ht.NoDefault, ht.TInt, "Disk index"),
1692 ("amount", ht.NoDefault, ht.TNonNegativeInt,
1693 "Amount of disk space to add (megabytes)"),
1694 ("absolute", False, ht.TBool,
1695 "Whether the amount parameter is an absolute target or a relative one"),
1696 ]
1697 OP_RESULT = ht.TNone
1698
1710
1715 """Add a node group to the cluster."""
1716 OP_DSC_FIELD = "group_name"
1717 OP_PARAMS = [
1718 _PGroupName,
1719 _PNodeGroupAllocPolicy,
1720 _PGroupNodeParams,
1721 _PDiskParams,
1722 _PHvState,
1723 _PDiskState,
1724 ("ipolicy", None, ht.TMaybeDict,
1725 "Group-wide :ref:`instance policy <rapi-ipolicy>` specs"),
1726 ]
1727 OP_RESULT = ht.TNone
1728
1740
1750
1753 """Change the parameters of a node group."""
1754 OP_DSC_FIELD = "group_name"
1755 OP_PARAMS = [
1756 _PGroupName,
1757 _PNodeGroupAllocPolicy,
1758 _PGroupNodeParams,
1759 _PDiskParams,
1760 _PHvState,
1761 _PDiskState,
1762 ("ipolicy", None, ht.TMaybeDict, "Group-wide instance policy specs"),
1763 ]
1764 OP_RESULT = _TSetParamsResult
1765
1774
1783
1795
1806
1817
1830
1846
1849 """Export an instance.
1850
1851 For local exports, the export destination is the node name. For
1852 remote exports, the export destination is a list of tuples, each
1853 consisting of hostname/IP address, port, magic, HMAC and HMAC
1854 salt. The HMAC is calculated using the cluster domain secret over
1855 the value "${index}:${hostname}:${port}". The destination X509 CA
1856 must be a signed certificate.
1857
1858 @ivar mode: Export mode (one of L{constants.EXPORT_MODES})
1859 @ivar target_node: Export destination
1860 @ivar x509_key_name: X509 key to use (remote export only)
1861 @ivar destination_x509_ca: Destination X509 CA in PEM format (remote export
1862 only)
1863
1864 """
1865 OP_DSC_FIELD = "instance_name"
1866 OP_PARAMS = [
1867 _PInstanceName,
1868 _PShutdownTimeout,
1869
1870
1871 ("target_node", ht.NoDefault, ht.TOr(ht.TNonEmptyString, ht.TList),
1872 "Destination information, depends on export mode"),
1873 ("shutdown", True, ht.TBool, "Whether to shutdown instance before export"),
1874 ("remove_instance", False, ht.TBool,
1875 "Whether to remove instance after export"),
1876 ("ignore_remove_failures", False, ht.TBool,
1877 "Whether to ignore failures while removing instances"),
1878 ("mode", constants.EXPORT_MODE_LOCAL, ht.TElemOf(constants.EXPORT_MODES),
1879 "Export mode"),
1880 ("x509_key_name", None, ht.TMaybe(ht.TList),
1881 "Name of X509 key (remote export only)"),
1882 ("destination_x509_ca", None, ht.TMaybeString,
1883 "Destination X509 CA (remote export only)"),
1884 ]
1885 OP_RESULT = \
1886 ht.TAnd(ht.TIsLength(2), ht.TItems([
1887 ht.Comment("Finalizing status")(ht.TBool),
1888 ht.Comment("Status for every exported disk")(ht.TListOf(ht.TBool)),
1889 ]))
1890
1899
1914
1927
1939
1951
1955 """Sleeps for a configured amount of time.
1956
1957 This is used just for debugging and testing.
1958
1959 Parameters:
1960 - duration: the time to sleep
1961 - on_master: if true, sleep on the master
1962 - on_nodes: list of nodes in which to sleep
1963
1964 If the on_master parameter is true, it will execute a sleep on the
1965 master (before any node sleep).
1966
1967 If the on_nodes list is not empty, it will sleep on those nodes
1968 (after the sleep on the master, if that is enabled).
1969
1970 As an additional feature, the case of duration < 0 will be reported
1971 as an execution error, so this opcode can be used as a failure
1972 generator. The case of duration == 0 will not be treated specially.
1973
1974 """
1975 OP_DSC_FIELD = "duration"
1976 OP_PARAMS = [
1977 ("duration", ht.NoDefault, ht.TNumber, None),
1978 ("on_master", True, ht.TBool, None),
1979 ("on_nodes", ht.EmptyList, ht.TListOf(ht.TNonEmptyString), None),
1980 ("repeat", 0, ht.TNonNegativeInt, None),
1981 ]
1982
1984 """Custom formatter for duration.
1985
1986 """
1987 try:
1988 v = float(value)
1989 except TypeError:
1990 v = value
1991 return str(v)
1992
1995 """Allocator framework testing.
1996
1997 This opcode has two modes:
1998 - gather and return allocator input for a given mode (allocate new
1999 or replace secondary) and a given instance definition (direction
2000 'in')
2001 - run a selected allocator for a given operation (as above) and
2002 return the allocator output (direction 'out')
2003
2004 """
2005 OP_DSC_FIELD = "iallocator"
2006 OP_PARAMS = [
2007 ("direction", ht.NoDefault,
2008 ht.TElemOf(constants.VALID_IALLOCATOR_DIRECTIONS), None),
2009 ("mode", ht.NoDefault, ht.TElemOf(constants.VALID_IALLOCATOR_MODES), None),
2010 ("name", ht.NoDefault, ht.TNonEmptyString, None),
2011 ("nics", ht.NoDefault,
2012 ht.TMaybeListOf(ht.TDictOf(ht.TElemOf([constants.INIC_MAC,
2013 constants.INIC_IP,
2014 "bridge"]),
2015 ht.TMaybeString)),
2016 None),
2017 ("disks", ht.NoDefault, ht.TMaybe(ht.TList), None),
2018 ("hypervisor", None, ht.TMaybeString, None),
2019 _PIAllocFromDesc(None),
2020 ("tags", ht.EmptyList, ht.TListOf(ht.TNonEmptyString), None),
2021 ("memory", None, ht.TMaybe(ht.TNonNegativeInt), None),
2022 ("vcpus", None, ht.TMaybe(ht.TNonNegativeInt), None),
2023 ("os", None, ht.TMaybeString, None),
2024 ("disk_template", None, ht.TMaybeString, None),
2025 ("instances", None, ht.TMaybeListOf(ht.TNonEmptyString), None),
2026 ("evac_mode", None,
2027 ht.TMaybe(ht.TElemOf(constants.IALLOCATOR_NEVAC_MODES)), None),
2028 ("target_groups", None, ht.TMaybeListOf(ht.TNonEmptyString), None),
2029 ("spindle_use", 1, ht.TNonNegativeInt, None),
2030 ("count", 1, ht.TNonNegativeInt, None),
2031 ]
2032
2035 """Utility opcode to test some aspects of the job queue.
2036
2037 """
2038 OP_PARAMS = [
2039 ("notify_waitlock", False, ht.TBool, None),
2040 ("notify_exec", False, ht.TBool, None),
2041 ("log_messages", ht.EmptyList, ht.TListOf(ht.TString), None),
2042 ("fail", False, ht.TBool, None),
2043 ]
2044
2047 """Utility opcode used by unittests.
2048
2049 """
2050 OP_PARAMS = [
2051 ("result", ht.NoDefault, ht.NoType, None),
2052 ("messages", ht.NoDefault, ht.NoType, None),
2053 ("fail", ht.NoDefault, ht.NoType, None),
2054 ("submit_jobs", None, ht.NoType, None),
2055 ]
2056 WITH_LU = False
2057
2062 """Add an IP network to the cluster."""
2063 OP_DSC_FIELD = "network_name"
2064 OP_PARAMS = [
2065 _PNetworkName,
2066 ("network", ht.NoDefault, _TIpNetwork4, "IPv4 subnet"),
2067 ("gateway", None, ht.TMaybe(_TIpAddress4), "IPv4 gateway"),
2068 ("network6", None, ht.TMaybe(_TIpNetwork6), "IPv6 subnet"),
2069 ("gateway6", None, ht.TMaybe(_TIpAddress6), "IPv6 gateway"),
2070 ("mac_prefix", None, ht.TMaybeString,
2071 "MAC address prefix that overrides cluster one"),
2072 ("add_reserved_ips", None, _TMaybeAddr4List,
2073 "Which IP addresses to reserve"),
2074 ("conflicts_check", True, ht.TBool,
2075 "Whether to check for conflicting IP addresses"),
2076 ("tags", ht.EmptyList, ht.TListOf(ht.TNonEmptyString), "Network tags"),
2077 ]
2078 OP_RESULT = ht.TNone
2079
2092
2095 """Modify Network's parameters except for IPv4 subnet"""
2096 OP_DSC_FIELD = "network_name"
2097 OP_PARAMS = [
2098 _PNetworkName,
2099 ("gateway", None, ht.TMaybeValueNone(_TIpAddress4), "IPv4 gateway"),
2100 ("network6", None, ht.TMaybeValueNone(_TIpNetwork6), "IPv6 subnet"),
2101 ("gateway6", None, ht.TMaybeValueNone(_TIpAddress6), "IPv6 gateway"),
2102 ("mac_prefix", None, ht.TMaybeValueNone(ht.TString),
2103 "MAC address prefix that overrides cluster one"),
2104 ("add_reserved_ips", None, _TMaybeAddr4List,
2105 "Which external IP addresses to reserve"),
2106 ("remove_reserved_ips", None, _TMaybeAddr4List,
2107 "Which external IP addresses to release"),
2108 ]
2109 OP_RESULT = ht.TNone
2110
2113 """Connect a Network to a specific Nodegroup with the defined netparams
2114 (mode, link). Nics in this Network will inherit those params.
2115 Produce errors if a NIC (that its not already assigned to a network)
2116 has an IP that is contained in the Network this will produce error unless
2117 --no-conflicts-check is passed.
2118
2119 """
2120 OP_DSC_FIELD = "network_name"
2121 OP_PARAMS = [
2122 _PGroupName,
2123 _PNetworkName,
2124 ("network_mode", ht.NoDefault, ht.TElemOf(constants.NIC_VALID_MODES),
2125 "Connectivity mode"),
2126 ("network_link", ht.NoDefault, ht.TString, "Connectivity link"),
2127 ("conflicts_check", True, ht.TBool, "Whether to check for conflicting IPs"),
2128 ]
2129 OP_RESULT = ht.TNone
2130
2143
2154
2157 """Returns list of all defined opcodes.
2158
2159 Does not eliminate duplicates by C{OP_ID}.
2160
2161 """
2162 return [v for v in globals().values()
2163 if (isinstance(v, type) and issubclass(v, OpCode) and
2164 hasattr(v, "OP_ID") and v is not OpCode)]
2165
2166
2167 OP_MAPPING = dict((v.OP_ID, v) for v in _GetOpList())
2168