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
39 from ganeti import constants
40 from ganeti import errors
41 from ganeti import ht
42
43
44
45
46
47 _POutputFields = ("output_fields", ht.NoDefault, ht.TListOf(ht.TNonEmptyString))
48
49
50 _PShutdownTimeout = ("shutdown_timeout", constants.DEFAULT_SHUTDOWN_TIMEOUT,
51 ht.TPositiveInt)
52
53
54 _PForce = ("force", False, ht.TBool)
55
56
57 _PInstanceName = ("instance_name", ht.NoDefault, ht.TNonEmptyString)
58
59
60 _PIgnoreOfflineNodes = ("ignore_offline_nodes", False, ht.TBool)
61
62
63 _PNodeName = ("node_name", ht.NoDefault, ht.TNonEmptyString)
64
65
66 _PGroupName = ("group_name", ht.NoDefault, ht.TNonEmptyString)
67
68
69 _PMigrationMode = ("mode", None,
70 ht.TOr(ht.TNone, ht.TElemOf(constants.HT_MIGRATION_MODES)))
71
72
73 _PMigrationLive = ("live", None, ht.TMaybeBool)
74
75
76 _PTagKind = ("kind", ht.NoDefault, ht.TElemOf(constants.VALID_TAG_TYPES))
77
78
79 _PTags = ("tags", ht.NoDefault, ht.TListOf(ht.TNonEmptyString))
80
81
82 _PIgnoreConsistency = ("ignore_consistency", False, ht.TBool)
83
84
85 _PNoRemember = ("no_remember", False, ht.TBool)
86
87
88 _OPID_RE = re.compile("([a-z])([A-Z])")
92 """Convert an opcode class name to an OP_ID.
93
94 @type name: string
95 @param name: the class name, as OpXxxYyy
96 @rtype: string
97 @return: the name in the OP_XXXX_YYYY format
98
99 """
100 if not name.startswith("Op"):
101 return None
102
103
104
105
106
107 name = _OPID_RE.sub(r"\1,\2", name)
108 elems = name.split(",")
109 return "_".join(n.upper() for n in elems)
110
113 """Checks that file storage is enabled.
114
115 While it doesn't really fit into this module, L{utils} was deemed too large
116 of a dependency to be imported for just one or two functions.
117
118 @raise errors.OpPrereqError: when file storage is disabled
119
120 """
121 if not constants.ENABLE_FILE_STORAGE:
122 raise errors.OpPrereqError("File storage disabled at configure time",
123 errors.ECODE_INVAL)
124
138
150
151
152
153 _PStorageType = ("storage_type", ht.NoDefault, _CheckStorageType)
157 """Meta class for opcode definitions.
158
159 """
160 - def __new__(mcs, name, bases, attrs):
161 """Called when a class should be created.
162
163 @param mcs: The meta class
164 @param name: Name of created class
165 @param bases: Base classes
166 @type attrs: dict
167 @param attrs: Class attributes
168
169 """
170 assert "__slots__" not in attrs, \
171 "Class '%s' defines __slots__ when it should use OP_PARAMS" % name
172 assert "OP_ID" not in attrs, "Class '%s' defining OP_ID" % name
173
174 attrs["OP_ID"] = _NameToId(name)
175
176
177 params = attrs.setdefault("OP_PARAMS", [])
178
179
180 slots = [pname for (pname, _, _) in params]
181
182 assert "OP_DSC_FIELD" not in attrs or attrs["OP_DSC_FIELD"] in slots, \
183 "Class '%s' uses unknown field in OP_DSC_FIELD" % name
184
185 attrs["__slots__"] = slots
186
187 return type.__new__(mcs, name, bases, attrs)
188
191 """A simple serializable object.
192
193 This object serves as a parent class for OpCode without any custom
194 field handling.
195
196 """
197
198
199 __metaclass__ = _AutoOpParamSlots
200
202 """Constructor for BaseOpCode.
203
204 The constructor takes only keyword arguments and will set
205 attributes on this object based on the passed arguments. As such,
206 it means that you should not pass arguments which are not in the
207 __slots__ attribute for this class.
208
209 """
210 slots = self._all_slots()
211 for key in kwargs:
212 if key not in slots:
213 raise TypeError("Object %s doesn't support the parameter '%s'" %
214 (self.__class__.__name__, key))
215 setattr(self, key, kwargs[key])
216
218 """Generic serializer.
219
220 This method just returns the contents of the instance as a
221 dictionary.
222
223 @rtype: C{dict}
224 @return: the instance attributes and their values
225
226 """
227 state = {}
228 for name in self._all_slots():
229 if hasattr(self, name):
230 state[name] = getattr(self, name)
231 return state
232
234 """Generic unserializer.
235
236 This method just restores from the serialized state the attributes
237 of the current instance.
238
239 @param state: the serialized opcode data
240 @type state: C{dict}
241
242 """
243 if not isinstance(state, dict):
244 raise ValueError("Invalid data to __setstate__: expected dict, got %s" %
245 type(state))
246
247 for name in self._all_slots():
248 if name not in state and hasattr(self, name):
249 delattr(self, name)
250
251 for name in state:
252 setattr(self, name, state[name])
253
254 @classmethod
256 """Compute the list of all declared slots for a class.
257
258 """
259 slots = []
260 for parent in cls.__mro__:
261 slots.extend(getattr(parent, "__slots__", []))
262 return slots
263
264 @classmethod
266 """Compute list of all parameters for an opcode.
267
268 """
269 slots = []
270 for parent in cls.__mro__:
271 slots.extend(getattr(parent, "OP_PARAMS", []))
272 return slots
273
275 """Validate opcode parameters, optionally setting default values.
276
277 @type set_defaults: bool
278 @param set_defaults: Whether to set default values
279 @raise errors.OpPrereqError: When a parameter value doesn't match
280 requirements
281
282 """
283 for (attr_name, default, test) in self.GetAllParams():
284 assert test == ht.NoType or callable(test)
285
286 if not hasattr(self, attr_name):
287 if default == ht.NoDefault:
288 raise errors.OpPrereqError("Required parameter '%s.%s' missing" %
289 (self.OP_ID, attr_name),
290 errors.ECODE_INVAL)
291 elif set_defaults:
292 if callable(default):
293 dval = default()
294 else:
295 dval = default
296 setattr(self, attr_name, dval)
297
298 if test == ht.NoType:
299
300 continue
301
302 if set_defaults or hasattr(self, attr_name):
303 attr_val = getattr(self, attr_name)
304 if not test(attr_val):
305 logging.error("OpCode %s, parameter %s, has invalid type %s/value %s",
306 self.OP_ID, attr_name, type(attr_val), attr_val)
307 raise errors.OpPrereqError("Parameter '%s.%s' fails validation" %
308 (self.OP_ID, attr_name),
309 errors.ECODE_INVAL)
310
313 """Abstract OpCode.
314
315 This is the root of the actual OpCode hierarchy. All clases derived
316 from this class should override OP_ID.
317
318 @cvar OP_ID: The ID of this opcode. This should be unique amongst all
319 children of this class.
320 @cvar OP_DSC_FIELD: The name of a field whose value will be included in the
321 string returned by Summary(); see the docstring of that
322 method for details).
323 @cvar OP_PARAMS: List of opcode attributes, the default values they should
324 get if not already defined, and types they must match.
325 @cvar WITH_LU: Boolean that specifies whether this should be included in
326 mcpu's dispatch table
327 @ivar dry_run: Whether the LU should be run in dry-run mode, i.e. just
328 the check steps
329 @ivar priority: Opcode priority for queue
330
331 """
332
333
334 WITH_LU = True
335 OP_PARAMS = [
336 ("dry_run", None, ht.TMaybeBool),
337 ("debug_level", None, ht.TOr(ht.TNone, ht.TPositiveInt)),
338 ("priority", constants.OP_PRIO_DEFAULT,
339 ht.TElemOf(constants.OP_PRIO_SUBMIT_VALID)),
340 ]
341
343 """Specialized getstate for opcodes.
344
345 This method adds to the state dictionary the OP_ID of the class,
346 so that on unload we can identify the correct class for
347 instantiating the opcode.
348
349 @rtype: C{dict}
350 @return: the state as a dictionary
351
352 """
353 data = BaseOpCode.__getstate__(self)
354 data["OP_ID"] = self.OP_ID
355 return data
356
357 @classmethod
359 """Generic load opcode method.
360
361 The method identifies the correct opcode class from the dict-form
362 by looking for a OP_ID key, if this is not found, or its value is
363 not available in this module as a child of this class, we fail.
364
365 @type data: C{dict}
366 @param data: the serialized opcode
367
368 """
369 if not isinstance(data, dict):
370 raise ValueError("Invalid data to LoadOpCode (%s)" % type(data))
371 if "OP_ID" not in data:
372 raise ValueError("Invalid data to LoadOpcode, missing OP_ID")
373 op_id = data["OP_ID"]
374 op_class = None
375 if op_id in OP_MAPPING:
376 op_class = OP_MAPPING[op_id]
377 else:
378 raise ValueError("Invalid data to LoadOpCode: OP_ID %s unsupported" %
379 op_id)
380 op = op_class()
381 new_data = data.copy()
382 del new_data["OP_ID"]
383 op.__setstate__(new_data)
384 return op
385
387 """Generates a summary description of this opcode.
388
389 The summary is the value of the OP_ID attribute (without the "OP_"
390 prefix), plus the value of the OP_DSC_FIELD attribute, if one was
391 defined; this field should allow to easily identify the operation
392 (for an instance creation job, e.g., it would be the instance
393 name).
394
395 """
396 assert self.OP_ID is not None and len(self.OP_ID) > 3
397
398 txt = self.OP_ID[3:]
399 field_name = getattr(self, "OP_DSC_FIELD", None)
400 if field_name:
401 field_value = getattr(self, field_name, None)
402 if isinstance(field_value, (list, tuple)):
403 field_value = ",".join(str(i) for i in field_value)
404 txt = "%s(%s)" % (txt, field_value)
405 return txt
406
407
408
409
410 -class OpClusterPostInit(OpCode):
411 """Post cluster initialization.
412
413 This opcode does not touch the cluster at all. Its purpose is to run hooks
414 after the cluster has been initialized.
415
416 """
417
420 """Destroy the cluster.
421
422 This opcode has no other parameters. All the state is irreversibly
423 lost after the execution of this opcode.
424
425 """
426
429 """Query cluster information."""
430
433 """Verify the cluster state.
434
435 @type skip_checks: C{list}
436 @ivar skip_checks: steps to be skipped from the verify process; this
437 needs to be a subset of
438 L{constants.VERIFY_OPTIONAL_CHECKS}; currently
439 only L{constants.VERIFY_NPLUSONE_MEM} can be passed
440
441 """
442 OP_PARAMS = [
443 ("skip_checks", ht.EmptyList,
444 ht.TListOf(ht.TElemOf(constants.VERIFY_OPTIONAL_CHECKS))),
445 ("verbose", False, ht.TBool),
446 ("error_codes", False, ht.TBool),
447 ("debug_simulate_errors", False, ht.TBool),
448 ]
449
452 """Verify the cluster disks.
453
454 Parameters: none
455
456 Result: a tuple of four elements:
457 - list of node names with bad data returned (unreachable, etc.)
458 - dict of node names with broken volume groups (values: error msg)
459 - list of instances with degraded disks (that should be activated)
460 - dict of instances with missing logical volumes (values: (node, vol)
461 pairs with details about the missing volumes)
462
463 In normal operation, all lists should be empty. A non-empty instance
464 list (3rd element of the result) is still ok (errors were fixed) but
465 non-empty node list means some node is down, and probably there are
466 unfixable drbd errors.
467
468 Note that only instances that are drbd-based are taken into
469 consideration. This might need to be revisited in the future.
470
471 """
472
475 """Verify the disk sizes of the instances and fixes configuration
476 mimatches.
477
478 Parameters: optional instances list, in case we want to restrict the
479 checks to only a subset of the instances.
480
481 Result: a list of tuples, (instance, disk, new-size) for changed
482 configurations.
483
484 In normal operation, the list should be empty.
485
486 @type instances: list
487 @ivar instances: the list of instances to check, or empty for all instances
488
489 """
490 OP_PARAMS = [
491 ("instances", ht.EmptyList, ht.TListOf(ht.TNonEmptyString)),
492 ]
493
500
503 """Rename the cluster.
504
505 @type name: C{str}
506 @ivar name: The new name of the cluster. The name and/or the master IP
507 address will be changed to match the new name and its IP
508 address.
509
510 """
511 OP_DSC_FIELD = "name"
512 OP_PARAMS = [
513 ("name", ht.NoDefault, ht.TNonEmptyString),
514 ]
515
518 """Change the parameters of the cluster.
519
520 @type vg_name: C{str} or C{None}
521 @ivar vg_name: The new volume group name or None to disable LVM usage.
522
523 """
524 OP_PARAMS = [
525 ("vg_name", None, ht.TMaybeString),
526 ("enabled_hypervisors", None,
527 ht.TOr(ht.TAnd(ht.TListOf(ht.TElemOf(constants.HYPER_TYPES)), ht.TTrue),
528 ht.TNone)),
529 ("hvparams", None, ht.TOr(ht.TDictOf(ht.TNonEmptyString, ht.TDict),
530 ht.TNone)),
531 ("beparams", None, ht.TOr(ht.TDict, ht.TNone)),
532 ("os_hvp", None, ht.TOr(ht.TDictOf(ht.TNonEmptyString, ht.TDict),
533 ht.TNone)),
534 ("osparams", None, ht.TOr(ht.TDictOf(ht.TNonEmptyString, ht.TDict),
535 ht.TNone)),
536 ("candidate_pool_size", None, ht.TOr(ht.TStrictPositiveInt, ht.TNone)),
537 ("uid_pool", None, ht.NoType),
538 ("add_uids", None, ht.NoType),
539 ("remove_uids", None, ht.NoType),
540 ("maintain_node_health", None, ht.TMaybeBool),
541 ("prealloc_wipe_disks", None, ht.TMaybeBool),
542 ("nicparams", None, ht.TMaybeDict),
543 ("ndparams", None, ht.TMaybeDict),
544 ("drbd_helper", None, ht.TOr(ht.TString, ht.TNone)),
545 ("default_iallocator", None, ht.TOr(ht.TString, ht.TNone)),
546 ("master_netdev", None, ht.TOr(ht.TString, ht.TNone)),
547 ("reserved_lvs", None, ht.TOr(ht.TListOf(ht.TNonEmptyString), ht.TNone)),
548 ("hidden_os", None, ht.TOr(ht.TListOf(
549 ht.TAnd(ht.TList,
550 ht.TIsLength(2),
551 ht.TMap(lambda v: v[0], ht.TElemOf(constants.DDMS_VALUES)))),
552 ht.TNone)),
553 ("blacklisted_os", None, ht.TOr(ht.TListOf(
554 ht.TAnd(ht.TList,
555 ht.TIsLength(2),
556 ht.TMap(lambda v: v[0], ht.TElemOf(constants.DDMS_VALUES)))),
557 ht.TNone)),
558 ]
559
562 """Force a full push of the cluster configuration.
563
564 """
565
568 """Query for resources/items.
569
570 @ivar what: Resources to query for, must be one of L{constants.QR_OP_QUERY}
571 @ivar fields: List of fields to retrieve
572 @ivar filter: Query filter
573
574 """
575 OP_PARAMS = [
576 ("what", ht.NoDefault, ht.TElemOf(constants.QR_OP_QUERY)),
577 ("fields", ht.NoDefault, ht.TListOf(ht.TNonEmptyString)),
578 ("filter", None, ht.TOr(ht.TNone,
579 ht.TListOf(ht.TOr(ht.TNonEmptyString, ht.TList)))),
580 ]
581
594
603
608 """Remove a node.
609
610 @type node_name: C{str}
611 @ivar node_name: The name of the node to remove. If the node still has
612 instances on it, the operation will fail.
613
614 """
615 OP_DSC_FIELD = "node_name"
616 OP_PARAMS = [
617 _PNodeName,
618 ]
619
622 """Add a node to the cluster.
623
624 @type node_name: C{str}
625 @ivar node_name: The name of the node to add. This can be a short name,
626 but it will be expanded to the FQDN.
627 @type primary_ip: IP address
628 @ivar primary_ip: The primary IP of the node. This will be ignored when the
629 opcode is submitted, but will be filled during the node
630 add (so it will be visible in the job query).
631 @type secondary_ip: IP address
632 @ivar secondary_ip: The secondary IP of the node. This needs to be passed
633 if the cluster has been initialized in 'dual-network'
634 mode, otherwise it must not be given.
635 @type readd: C{bool}
636 @ivar readd: Whether to re-add an existing node to the cluster. If
637 this is not passed, then the operation will abort if the node
638 name is already in the cluster; use this parameter to 'repair'
639 a node that had its configuration broken, or was reinstalled
640 without removal from the cluster.
641 @type group: C{str}
642 @ivar group: The node group to which this node will belong.
643 @type vm_capable: C{bool}
644 @ivar vm_capable: The vm_capable node attribute
645 @type master_capable: C{bool}
646 @ivar master_capable: The master_capable node attribute
647
648 """
649 OP_DSC_FIELD = "node_name"
650 OP_PARAMS = [
651 _PNodeName,
652 ("primary_ip", None, ht.NoType),
653 ("secondary_ip", None, ht.TMaybeString),
654 ("readd", False, ht.TBool),
655 ("group", None, ht.TMaybeString),
656 ("master_capable", None, ht.TMaybeBool),
657 ("vm_capable", None, ht.TMaybeBool),
658 ("ndparams", None, ht.TMaybeDict),
659 ]
660
669
677
687
697
708
711 """Change the parameters of a node."""
712 OP_DSC_FIELD = "node_name"
713 OP_PARAMS = [
714 _PNodeName,
715 _PForce,
716 ("master_candidate", None, ht.TMaybeBool),
717 ("offline", None, ht.TMaybeBool),
718 ("drained", None, ht.TMaybeBool),
719 ("auto_promote", False, ht.TBool),
720 ("master_capable", None, ht.TMaybeBool),
721 ("vm_capable", None, ht.TMaybeBool),
722 ("secondary_ip", None, ht.TMaybeString),
723 ("ndparams", None, ht.TMaybeDict),
724 ("powered", None, ht.TMaybeBool),
725 ]
726
735
745
755
760 """Create an instance.
761
762 @ivar instance_name: Instance name
763 @ivar mode: Instance creation mode (one of L{constants.INSTANCE_CREATE_MODES})
764 @ivar source_handshake: Signed handshake from source (remote import only)
765 @ivar source_x509_ca: Source X509 CA in PEM format (remote import only)
766 @ivar source_instance_name: Previous name of instance (remote import only)
767 @ivar source_shutdown_timeout: Shutdown timeout used for source instance
768 (remote import only)
769
770 """
771 OP_DSC_FIELD = "instance_name"
772 OP_PARAMS = [
773 _PInstanceName,
774 ("beparams", ht.EmptyDict, ht.TDict),
775 ("disks", ht.NoDefault, ht.TListOf(ht.TDict)),
776 ("disk_template", ht.NoDefault, _CheckDiskTemplate),
777 ("file_driver", None, ht.TOr(ht.TNone, ht.TElemOf(constants.FILE_DRIVER))),
778 ("file_storage_dir", None, ht.TMaybeString),
779 ("force_variant", False, ht.TBool),
780 ("hvparams", ht.EmptyDict, ht.TDict),
781 ("hypervisor", None, ht.TMaybeString),
782 ("iallocator", None, ht.TMaybeString),
783 ("identify_defaults", False, ht.TBool),
784 ("ip_check", True, ht.TBool),
785 ("mode", ht.NoDefault, ht.TElemOf(constants.INSTANCE_CREATE_MODES)),
786 ("name_check", True, ht.TBool),
787 ("nics", ht.NoDefault, ht.TListOf(ht.TDict)),
788 ("no_install", None, ht.TMaybeBool),
789 ("osparams", ht.EmptyDict, ht.TDict),
790 ("os_type", None, ht.TMaybeString),
791 ("pnode", None, ht.TMaybeString),
792 ("snode", None, ht.TMaybeString),
793 ("source_handshake", None, ht.TOr(ht.TList, ht.TNone)),
794 ("source_instance_name", None, ht.TMaybeString),
795 ("source_shutdown_timeout", constants.DEFAULT_SHUTDOWN_TIMEOUT,
796 ht.TPositiveInt),
797 ("source_x509_ca", None, ht.TMaybeString),
798 ("src_node", None, ht.TMaybeString),
799 ("src_path", None, ht.TMaybeString),
800 ("start", True, ht.TBool),
801 ("wait_for_sync", True, ht.TBool),
802 ]
803
806 """Reinstall an instance's OS."""
807 OP_DSC_FIELD = "instance_name"
808 OP_PARAMS = [
809 _PInstanceName,
810 ("os_type", None, ht.TMaybeString),
811 ("force_variant", False, ht.TBool),
812 ("osparams", None, ht.TMaybeDict),
813 ]
814
824
827 """Rename an instance."""
828 OP_PARAMS = [
829 _PInstanceName,
830 ("new_name", ht.NoDefault, ht.TNonEmptyString),
831 ("ip_check", False, ht.TBool),
832 ("name_check", True, ht.TBool),
833 ]
834
837 """Startup an instance."""
838 OP_DSC_FIELD = "instance_name"
839 OP_PARAMS = [
840 _PInstanceName,
841 _PForce,
842 _PIgnoreOfflineNodes,
843 _PNoRemember,
844 ("hvparams", ht.EmptyDict, ht.TDict),
845 ("beparams", ht.EmptyDict, ht.TDict),
846 ]
847
858
869
872 """Replace the disks of an instance."""
873 OP_DSC_FIELD = "instance_name"
874 OP_PARAMS = [
875 _PInstanceName,
876 ("mode", ht.NoDefault, ht.TElemOf(constants.REPLACE_MODES)),
877 ("disks", ht.EmptyList, ht.TListOf(ht.TPositiveInt)),
878 ("remote_node", None, ht.TMaybeString),
879 ("iallocator", None, ht.TMaybeString),
880 ("early_release", False, ht.TBool),
881 ]
882
892
895 """Migrate an instance.
896
897 This migrates (without shutting down an instance) to its secondary
898 node.
899
900 @ivar instance_name: the name of the instance
901 @ivar mode: the migration mode (live, non-live or None for auto)
902
903 """
904 OP_DSC_FIELD = "instance_name"
905 OP_PARAMS = [
906 _PInstanceName,
907 _PMigrationMode,
908 _PMigrationLive,
909 ("cleanup", False, ht.TBool),
910 ]
911
930
938
947
956
966
975
984
987 """Change the parameters of an instance."""
988 OP_DSC_FIELD = "instance_name"
989 OP_PARAMS = [
990 _PInstanceName,
991 _PForce,
992 ("nics", ht.EmptyList, ht.TList),
993 ("disks", ht.EmptyList, ht.TList),
994 ("beparams", ht.EmptyDict, ht.TDict),
995 ("hvparams", ht.EmptyDict, ht.TDict),
996 ("disk_template", None, ht.TOr(ht.TNone, _CheckDiskTemplate)),
997 ("remote_node", None, ht.TMaybeString),
998 ("os_name", None, ht.TMaybeString),
999 ("force_variant", False, ht.TBool),
1000 ("osparams", None, ht.TMaybeDict),
1001 ("wait_for_sync", True, ht.TBool),
1002 ]
1003
1006 """Grow a disk of an instance."""
1007 OP_DSC_FIELD = "instance_name"
1008 OP_PARAMS = [
1009 _PInstanceName,
1010 ("disk", ht.NoDefault, ht.TInt),
1011 ("amount", ht.NoDefault, ht.TInt),
1012 ("wait_for_sync", True, ht.TBool),
1013 ]
1014
1027
1037
1045
1056
1064
1073
1082
1091
1105
1108 """Export an instance.
1109
1110 For local exports, the export destination is the node name. For remote
1111 exports, the export destination is a list of tuples, each consisting of
1112 hostname/IP address, port, HMAC and HMAC salt. The HMAC is calculated using
1113 the cluster domain secret over the value "${index}:${hostname}:${port}". The
1114 destination X509 CA must be a signed certificate.
1115
1116 @ivar mode: Export mode (one of L{constants.EXPORT_MODES})
1117 @ivar target_node: Export destination
1118 @ivar x509_key_name: X509 key to use (remote export only)
1119 @ivar destination_x509_ca: Destination X509 CA in PEM format (remote export
1120 only)
1121
1122 """
1123 OP_DSC_FIELD = "instance_name"
1124 OP_PARAMS = [
1125 _PInstanceName,
1126 _PShutdownTimeout,
1127
1128
1129 ("target_node", ht.NoDefault, ht.TOr(ht.TNonEmptyString, ht.TList)),
1130 ("shutdown", True, ht.TBool),
1131 ("remove_instance", False, ht.TBool),
1132 ("ignore_remove_failures", False, ht.TBool),
1133 ("mode", constants.EXPORT_MODE_LOCAL, ht.TElemOf(constants.EXPORT_MODES)),
1134 ("x509_key_name", None, ht.TOr(ht.TList, ht.TNone)),
1135 ("destination_x509_ca", None, ht.TMaybeString),
1136 ]
1137
1145
1156
1164
1174
1184
1187 """Sleeps for a configured amount of time.
1188
1189 This is used just for debugging and testing.
1190
1191 Parameters:
1192 - duration: the time to sleep
1193 - on_master: if true, sleep on the master
1194 - on_nodes: list of nodes in which to sleep
1195
1196 If the on_master parameter is true, it will execute a sleep on the
1197 master (before any node sleep).
1198
1199 If the on_nodes list is not empty, it will sleep on those nodes
1200 (after the sleep on the master, if that is enabled).
1201
1202 As an additional feature, the case of duration < 0 will be reported
1203 as an execution error, so this opcode can be used as a failure
1204 generator. The case of duration == 0 will not be treated specially.
1205
1206 """
1207 OP_DSC_FIELD = "duration"
1208 OP_PARAMS = [
1209 ("duration", ht.NoDefault, ht.TNumber),
1210 ("on_master", True, ht.TBool),
1211 ("on_nodes", ht.EmptyList, ht.TListOf(ht.TNonEmptyString)),
1212 ("repeat", 0, ht.TPositiveInt)
1213 ]
1214
1217 """Allocator framework testing.
1218
1219 This opcode has two modes:
1220 - gather and return allocator input for a given mode (allocate new
1221 or replace secondary) and a given instance definition (direction
1222 'in')
1223 - run a selected allocator for a given operation (as above) and
1224 return the allocator output (direction 'out')
1225
1226 """
1227 OP_DSC_FIELD = "allocator"
1228 OP_PARAMS = [
1229 ("direction", ht.NoDefault,
1230 ht.TElemOf(constants.VALID_IALLOCATOR_DIRECTIONS)),
1231 ("mode", ht.NoDefault, ht.TElemOf(constants.VALID_IALLOCATOR_MODES)),
1232 ("name", ht.NoDefault, ht.TNonEmptyString),
1233 ("nics", ht.NoDefault, ht.TOr(ht.TNone, ht.TListOf(
1234 ht.TDictOf(ht.TElemOf(["mac", "ip", "bridge"]),
1235 ht.TOr(ht.TNone, ht.TNonEmptyString))))),
1236 ("disks", ht.NoDefault, ht.TOr(ht.TNone, ht.TList)),
1237 ("hypervisor", None, ht.TMaybeString),
1238 ("allocator", None, ht.TMaybeString),
1239 ("tags", ht.EmptyList, ht.TListOf(ht.TNonEmptyString)),
1240 ("mem_size", None, ht.TOr(ht.TNone, ht.TPositiveInt)),
1241 ("vcpus", None, ht.TOr(ht.TNone, ht.TPositiveInt)),
1242 ("os", None, ht.TMaybeString),
1243 ("disk_template", None, ht.TMaybeString),
1244 ("evac_nodes", None, ht.TOr(ht.TNone, ht.TListOf(ht.TNonEmptyString))),
1245 ]
1246
1249 """Utility opcode to test some aspects of the job queue.
1250
1251 """
1252 OP_PARAMS = [
1253 ("notify_waitlock", False, ht.TBool),
1254 ("notify_exec", False, ht.TBool),
1255 ("log_messages", ht.EmptyList, ht.TListOf(ht.TString)),
1256 ("fail", False, ht.TBool),
1257 ]
1258
1270
1273 """Returns list of all defined opcodes.
1274
1275 Does not eliminate duplicates by C{OP_ID}.
1276
1277 """
1278 return [v for v in globals().values()
1279 if (isinstance(v, type) and issubclass(v, OpCode) and
1280 hasattr(v, "OP_ID") and v is not OpCode)]
1281
1282
1283 OP_MAPPING = dict((v.OP_ID, v) for v in _GetOpList())
1284