Package ganeti :: Module opcodes
[hide private]
[frames] | no frames]

Source Code for Module ganeti.opcodes

  1  # 
  2  # 
  3   
  4  # Copyright (C) 2006, 2007, 2008, 2009, 2010 Google Inc. 
  5  # 
  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. 
 10  # 
 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. 
 15  # 
 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 
 19  # 02110-1301, USA. 
 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 # this are practically structures, so disable the message about too 33 # few public methods: 34 # pylint: disable-msg=R0903 35 36 37 -class BaseOpCode(object):
38 """A simple serializable object. 39 40 This object serves as a parent class for OpCode without any custom 41 field handling. 42 43 """ 44 __slots__ = [] 45
46 - def __init__(self, **kwargs):
47 """Constructor for BaseOpCode. 48 49 The constructor takes only keyword arguments and will set 50 attributes on this object based on the passed arguments. As such, 51 it means that you should not pass arguments which are not in the 52 __slots__ attribute for this class. 53 54 """ 55 slots = self._all_slots() 56 for key in kwargs: 57 if key not in slots: 58 raise TypeError("Object %s doesn't support the parameter '%s'" % 59 (self.__class__.__name__, key)) 60 setattr(self, key, kwargs[key])
61
62 - def __getstate__(self):
63 """Generic serializer. 64 65 This method just returns the contents of the instance as a 66 dictionary. 67 68 @rtype: C{dict} 69 @return: the instance attributes and their values 70 71 """ 72 state = {} 73 for name in self._all_slots(): 74 if hasattr(self, name): 75 state[name] = getattr(self, name) 76 return state
77
78 - def __setstate__(self, state):
79 """Generic unserializer. 80 81 This method just restores from the serialized state the attributes 82 of the current instance. 83 84 @param state: the serialized opcode data 85 @type state: C{dict} 86 87 """ 88 if not isinstance(state, dict): 89 raise ValueError("Invalid data to __setstate__: expected dict, got %s" % 90 type(state)) 91 92 for name in self._all_slots(): 93 if name not in state and hasattr(self, name): 94 delattr(self, name) 95 96 for name in state: 97 setattr(self, name, state[name])
98 99 @classmethod
100 - def _all_slots(cls):
101 """Compute the list of all declared slots for a class. 102 103 """ 104 slots = [] 105 for parent in cls.__mro__: 106 slots.extend(getattr(parent, "__slots__", [])) 107 return slots
108
109 110 -class OpCode(BaseOpCode):
111 """Abstract OpCode. 112 113 This is the root of the actual OpCode hierarchy. All clases derived 114 from this class should override OP_ID. 115 116 @cvar OP_ID: The ID of this opcode. This should be unique amongst all 117 children of this class. 118 @ivar dry_run: Whether the LU should be run in dry-run mode, i.e. just 119 the check steps 120 121 """ 122 OP_ID = "OP_ABSTRACT" 123 __slots__ = ["dry_run", "debug_level"] 124
125 - def __getstate__(self):
126 """Specialized getstate for opcodes. 127 128 This method adds to the state dictionary the OP_ID of the class, 129 so that on unload we can identify the correct class for 130 instantiating the opcode. 131 132 @rtype: C{dict} 133 @return: the state as a dictionary 134 135 """ 136 data = BaseOpCode.__getstate__(self) 137 data["OP_ID"] = self.OP_ID 138 return data
139 140 @classmethod
141 - def LoadOpCode(cls, data):
142 """Generic load opcode method. 143 144 The method identifies the correct opcode class from the dict-form 145 by looking for a OP_ID key, if this is not found, or its value is 146 not available in this module as a child of this class, we fail. 147 148 @type data: C{dict} 149 @param data: the serialized opcode 150 151 """ 152 if not isinstance(data, dict): 153 raise ValueError("Invalid data to LoadOpCode (%s)" % type(data)) 154 if "OP_ID" not in data: 155 raise ValueError("Invalid data to LoadOpcode, missing OP_ID") 156 op_id = data["OP_ID"] 157 op_class = None 158 if op_id in OP_MAPPING: 159 op_class = OP_MAPPING[op_id] 160 else: 161 raise ValueError("Invalid data to LoadOpCode: OP_ID %s unsupported" % 162 op_id) 163 op = op_class() 164 new_data = data.copy() 165 del new_data["OP_ID"] 166 op.__setstate__(new_data) 167 return op
168
169 - def Summary(self):
170 """Generates a summary description of this opcode. 171 172 """ 173 # all OP_ID start with OP_, we remove that 174 txt = self.OP_ID[3:] 175 field_name = getattr(self, "OP_DSC_FIELD", None) 176 if field_name: 177 field_value = getattr(self, field_name, None) 178 if isinstance(field_value, (list, tuple)): 179 field_value = ",".join(str(i) for i in field_value) 180 txt = "%s(%s)" % (txt, field_value) 181 return txt
182
183 184 # cluster opcodes 185 186 -class OpPostInitCluster(OpCode):
187 """Post cluster initialization. 188 189 This opcode does not touch the cluster at all. Its purpose is to run hooks 190 after the cluster has been initialized. 191 192 """ 193 OP_ID = "OP_CLUSTER_POST_INIT" 194 __slots__ = []
195
196 197 -class OpDestroyCluster(OpCode):
198 """Destroy the cluster. 199 200 This opcode has no other parameters. All the state is irreversibly 201 lost after the execution of this opcode. 202 203 """ 204 OP_ID = "OP_CLUSTER_DESTROY" 205 __slots__ = []
206
207 208 -class OpQueryClusterInfo(OpCode):
209 """Query cluster information.""" 210 OP_ID = "OP_CLUSTER_QUERY" 211 __slots__ = []
212
213 214 -class OpVerifyCluster(OpCode):
215 """Verify the cluster state. 216 217 @type skip_checks: C{list} 218 @ivar skip_checks: steps to be skipped from the verify process; this 219 needs to be a subset of 220 L{constants.VERIFY_OPTIONAL_CHECKS}; currently 221 only L{constants.VERIFY_NPLUSONE_MEM} can be passed 222 223 """ 224 OP_ID = "OP_CLUSTER_VERIFY" 225 __slots__ = ["skip_checks", "verbose", "error_codes", 226 "debug_simulate_errors"]
227
228 229 -class OpVerifyDisks(OpCode):
230 """Verify the cluster disks. 231 232 Parameters: none 233 234 Result: a tuple of four elements: 235 - list of node names with bad data returned (unreachable, etc.) 236 - dict of node names with broken volume groups (values: error msg) 237 - list of instances with degraded disks (that should be activated) 238 - dict of instances with missing logical volumes (values: (node, vol) 239 pairs with details about the missing volumes) 240 241 In normal operation, all lists should be empty. A non-empty instance 242 list (3rd element of the result) is still ok (errors were fixed) but 243 non-empty node list means some node is down, and probably there are 244 unfixable drbd errors. 245 246 Note that only instances that are drbd-based are taken into 247 consideration. This might need to be revisited in the future. 248 249 """ 250 OP_ID = "OP_CLUSTER_VERIFY_DISKS" 251 __slots__ = []
252
253 254 -class OpRepairDiskSizes(OpCode):
255 """Verify the disk sizes of the instances and fixes configuration 256 mimatches. 257 258 Parameters: optional instances list, in case we want to restrict the 259 checks to only a subset of the instances. 260 261 Result: a list of tuples, (instance, disk, new-size) for changed 262 configurations. 263 264 In normal operation, the list should be empty. 265 266 @type instances: list 267 @ivar instances: the list of instances to check, or empty for all instances 268 269 """ 270 OP_ID = "OP_CLUSTER_REPAIR_DISK_SIZES" 271 __slots__ = ["instances"]
272
273 274 -class OpQueryConfigValues(OpCode):
275 """Query cluster configuration values.""" 276 OP_ID = "OP_CLUSTER_CONFIG_QUERY" 277 __slots__ = ["output_fields"]
278
279 280 -class OpRenameCluster(OpCode):
281 """Rename the cluster. 282 283 @type name: C{str} 284 @ivar name: The new name of the cluster. The name and/or the master IP 285 address will be changed to match the new name and its IP 286 address. 287 288 """ 289 OP_ID = "OP_CLUSTER_RENAME" 290 OP_DSC_FIELD = "name" 291 __slots__ = ["name"]
292
293 294 -class OpSetClusterParams(OpCode):
295 """Change the parameters of the cluster. 296 297 @type vg_name: C{str} or C{None} 298 @ivar vg_name: The new volume group name or None to disable LVM usage. 299 300 """ 301 OP_ID = "OP_CLUSTER_SET_PARAMS" 302 __slots__ = [ 303 "vg_name", 304 "drbd_helper", 305 "enabled_hypervisors", 306 "hvparams", 307 "os_hvp", 308 "beparams", 309 "osparams", 310 "nicparams", 311 "candidate_pool_size", 312 "maintain_node_health", 313 "uid_pool", 314 "add_uids", 315 "remove_uids", 316 "default_iallocator", 317 "reserved_lvs", 318 "hidden_os", 319 "blacklisted_os", 320 ]
321
322 323 -class OpRedistributeConfig(OpCode):
324 """Force a full push of the cluster configuration. 325 326 """ 327 OP_ID = "OP_CLUSTER_REDIST_CONF" 328 __slots__ = []
329
330 # node opcodes 331 332 -class OpRemoveNode(OpCode):
333 """Remove a node. 334 335 @type node_name: C{str} 336 @ivar node_name: The name of the node to remove. If the node still has 337 instances on it, the operation will fail. 338 339 """ 340 OP_ID = "OP_NODE_REMOVE" 341 OP_DSC_FIELD = "node_name" 342 __slots__ = ["node_name"]
343
344 345 -class OpAddNode(OpCode):
346 """Add a node to the cluster. 347 348 @type node_name: C{str} 349 @ivar node_name: The name of the node to add. This can be a short name, 350 but it will be expanded to the FQDN. 351 @type primary_ip: IP address 352 @ivar primary_ip: The primary IP of the node. This will be ignored when the 353 opcode is submitted, but will be filled during the node 354 add (so it will be visible in the job query). 355 @type secondary_ip: IP address 356 @ivar secondary_ip: The secondary IP of the node. This needs to be passed 357 if the cluster has been initialized in 'dual-network' 358 mode, otherwise it must not be given. 359 @type readd: C{bool} 360 @ivar readd: Whether to re-add an existing node to the cluster. If 361 this is not passed, then the operation will abort if the node 362 name is already in the cluster; use this parameter to 'repair' 363 a node that had its configuration broken, or was reinstalled 364 without removal from the cluster. 365 366 """ 367 OP_ID = "OP_NODE_ADD" 368 OP_DSC_FIELD = "node_name" 369 __slots__ = ["node_name", "primary_ip", "secondary_ip", "readd"]
370
371 372 -class OpQueryNodes(OpCode):
373 """Compute the list of nodes.""" 374 OP_ID = "OP_NODE_QUERY" 375 __slots__ = ["output_fields", "names", "use_locking"]
376
377 378 -class OpQueryNodeVolumes(OpCode):
379 """Get list of volumes on node.""" 380 OP_ID = "OP_NODE_QUERYVOLS" 381 __slots__ = ["nodes", "output_fields"]
382
383 384 -class OpQueryNodeStorage(OpCode):
385 """Get information on storage for node(s).""" 386 OP_ID = "OP_NODE_QUERY_STORAGE" 387 __slots__ = [ 388 "nodes", 389 "storage_type", 390 "name", 391 "output_fields", 392 ]
393
394 395 -class OpModifyNodeStorage(OpCode):
396 """Modifies the properies of a storage unit""" 397 OP_ID = "OP_NODE_MODIFY_STORAGE" 398 __slots__ = [ 399 "node_name", 400 "storage_type", 401 "name", 402 "changes", 403 ]
404
405 406 -class OpRepairNodeStorage(OpCode):
407 """Repairs the volume group on a node.""" 408 OP_ID = "OP_REPAIR_NODE_STORAGE" 409 OP_DSC_FIELD = "node_name" 410 __slots__ = [ 411 "node_name", 412 "storage_type", 413 "name", 414 "ignore_consistency", 415 ]
416
417 418 -class OpSetNodeParams(OpCode):
419 """Change the parameters of a node.""" 420 OP_ID = "OP_NODE_SET_PARAMS" 421 OP_DSC_FIELD = "node_name" 422 __slots__ = [ 423 "node_name", 424 "force", 425 "master_candidate", 426 "offline", 427 "drained", 428 "auto_promote", 429 ]
430
431 432 -class OpPowercycleNode(OpCode):
433 """Tries to powercycle a node.""" 434 OP_ID = "OP_NODE_POWERCYCLE" 435 OP_DSC_FIELD = "node_name" 436 __slots__ = [ 437 "node_name", 438 "force", 439 ]
440
441 442 -class OpMigrateNode(OpCode):
443 """Migrate all instances from a node.""" 444 OP_ID = "OP_NODE_MIGRATE" 445 OP_DSC_FIELD = "node_name" 446 __slots__ = [ 447 "node_name", 448 "mode", 449 "live", 450 ]
451
452 453 -class OpNodeEvacuationStrategy(OpCode):
454 """Compute the evacuation strategy for a list of nodes.""" 455 OP_ID = "OP_NODE_EVAC_STRATEGY" 456 OP_DSC_FIELD = "nodes" 457 __slots__ = ["nodes", "iallocator", "remote_node"]
458
459 460 # instance opcodes 461 462 -class OpCreateInstance(OpCode):
463 """Create an instance. 464 465 @ivar instance_name: Instance name 466 @ivar mode: Instance creation mode (one of L{constants.INSTANCE_CREATE_MODES}) 467 @ivar source_handshake: Signed handshake from source (remote import only) 468 @ivar source_x509_ca: Source X509 CA in PEM format (remote import only) 469 @ivar source_instance_name: Previous name of instance (remote import only) 470 471 """ 472 OP_ID = "OP_INSTANCE_CREATE" 473 OP_DSC_FIELD = "instance_name" 474 __slots__ = [ 475 "instance_name", 476 "os_type", "force_variant", "no_install", 477 "pnode", "disk_template", "snode", "mode", 478 "disks", "nics", 479 "src_node", "src_path", "start", "identify_defaults", 480 "wait_for_sync", "ip_check", "name_check", 481 "file_storage_dir", "file_driver", 482 "iallocator", 483 "hypervisor", "hvparams", "beparams", "osparams", 484 "source_handshake", 485 "source_x509_ca", 486 "source_instance_name", 487 ]
488
489 490 -class OpReinstallInstance(OpCode):
491 """Reinstall an instance's OS.""" 492 OP_ID = "OP_INSTANCE_REINSTALL" 493 OP_DSC_FIELD = "instance_name" 494 __slots__ = ["instance_name", "os_type", "force_variant"]
495
496 497 -class OpRemoveInstance(OpCode):
498 """Remove an instance.""" 499 OP_ID = "OP_INSTANCE_REMOVE" 500 OP_DSC_FIELD = "instance_name" 501 __slots__ = [ 502 "instance_name", 503 "ignore_failures", 504 "shutdown_timeout", 505 ]
506
507 508 -class OpRenameInstance(OpCode):
509 """Rename an instance.""" 510 OP_ID = "OP_INSTANCE_RENAME" 511 __slots__ = [ 512 "instance_name", "ip_check", "new_name", "name_check", 513 ]
514
515 516 -class OpStartupInstance(OpCode):
517 """Startup an instance.""" 518 OP_ID = "OP_INSTANCE_STARTUP" 519 OP_DSC_FIELD = "instance_name" 520 __slots__ = [ 521 "instance_name", "force", "hvparams", "beparams", 522 ]
523
524 525 -class OpShutdownInstance(OpCode):
526 """Shutdown an instance.""" 527 OP_ID = "OP_INSTANCE_SHUTDOWN" 528 OP_DSC_FIELD = "instance_name" 529 __slots__ = ["instance_name", "timeout"]
530
531 532 -class OpRebootInstance(OpCode):
533 """Reboot an instance.""" 534 OP_ID = "OP_INSTANCE_REBOOT" 535 OP_DSC_FIELD = "instance_name" 536 __slots__ = [ 537 "instance_name", "reboot_type", "ignore_secondaries", "shutdown_timeout", 538 ]
539
540 541 -class OpReplaceDisks(OpCode):
542 """Replace the disks of an instance.""" 543 OP_ID = "OP_INSTANCE_REPLACE_DISKS" 544 OP_DSC_FIELD = "instance_name" 545 __slots__ = [ 546 "instance_name", "remote_node", "mode", "disks", "iallocator", 547 "early_release", 548 ]
549
550 551 -class OpFailoverInstance(OpCode):
552 """Failover an instance.""" 553 OP_ID = "OP_INSTANCE_FAILOVER" 554 OP_DSC_FIELD = "instance_name" 555 __slots__ = [ 556 "instance_name", "ignore_consistency", "shutdown_timeout", 557 ]
558
559 560 -class OpMigrateInstance(OpCode):
561 """Migrate an instance. 562 563 This migrates (without shutting down an instance) to its secondary 564 node. 565 566 @ivar instance_name: the name of the instance 567 @ivar mode: the migration mode (live, non-live or None for auto) 568 569 """ 570 OP_ID = "OP_INSTANCE_MIGRATE" 571 OP_DSC_FIELD = "instance_name" 572 __slots__ = ["instance_name", "mode", "cleanup", "live"]
573
574 575 -class OpMoveInstance(OpCode):
576 """Move an instance. 577 578 This move (with shutting down an instance and data copying) to an 579 arbitrary node. 580 581 @ivar instance_name: the name of the instance 582 @ivar target_node: the destination node 583 584 """ 585 OP_ID = "OP_INSTANCE_MOVE" 586 OP_DSC_FIELD = "instance_name" 587 __slots__ = [ 588 "instance_name", "target_node", "shutdown_timeout", 589 ]
590
591 592 -class OpConnectConsole(OpCode):
593 """Connect to an instance's console.""" 594 OP_ID = "OP_INSTANCE_CONSOLE" 595 OP_DSC_FIELD = "instance_name" 596 __slots__ = ["instance_name"]
597
598 599 -class OpActivateInstanceDisks(OpCode):
600 """Activate an instance's disks.""" 601 OP_ID = "OP_INSTANCE_ACTIVATE_DISKS" 602 OP_DSC_FIELD = "instance_name" 603 __slots__ = ["instance_name", "ignore_size"]
604
605 606 -class OpDeactivateInstanceDisks(OpCode):
607 """Deactivate an instance's disks.""" 608 OP_ID = "OP_INSTANCE_DEACTIVATE_DISKS" 609 OP_DSC_FIELD = "instance_name" 610 __slots__ = ["instance_name"]
611
612 613 -class OpRecreateInstanceDisks(OpCode):
614 """Deactivate an instance's disks.""" 615 OP_ID = "OP_INSTANCE_RECREATE_DISKS" 616 OP_DSC_FIELD = "instance_name" 617 __slots__ = ["instance_name", "disks"]
618
619 620 -class OpQueryInstances(OpCode):
621 """Compute the list of instances.""" 622 OP_ID = "OP_INSTANCE_QUERY" 623 __slots__ = ["output_fields", "names", "use_locking"]
624
625 626 -class OpQueryInstanceData(OpCode):
627 """Compute the run-time status of instances.""" 628 OP_ID = "OP_INSTANCE_QUERY_DATA" 629 __slots__ = ["instances", "static"]
630
631 632 -class OpSetInstanceParams(OpCode):
633 """Change the parameters of an instance.""" 634 OP_ID = "OP_INSTANCE_SET_PARAMS" 635 OP_DSC_FIELD = "instance_name" 636 __slots__ = [ 637 "instance_name", 638 "hvparams", "beparams", "osparams", "force", 639 "nics", "disks", "disk_template", 640 "remote_node", "os_name", "force_variant", 641 ]
642
643 644 -class OpGrowDisk(OpCode):
645 """Grow a disk of an instance.""" 646 OP_ID = "OP_INSTANCE_GROW_DISK" 647 OP_DSC_FIELD = "instance_name" 648 __slots__ = [ 649 "instance_name", "disk", "amount", "wait_for_sync", 650 ]
651
652 653 # OS opcodes 654 -class OpDiagnoseOS(OpCode):
655 """Compute the list of guest operating systems.""" 656 OP_ID = "OP_OS_DIAGNOSE" 657 __slots__ = ["output_fields", "names"]
658
659 660 # Exports opcodes 661 -class OpQueryExports(OpCode):
662 """Compute the list of exported images.""" 663 OP_ID = "OP_BACKUP_QUERY" 664 __slots__ = ["nodes", "use_locking"]
665
666 667 -class OpPrepareExport(OpCode):
668 """Prepares an instance export. 669 670 @ivar instance_name: Instance name 671 @ivar mode: Export mode (one of L{constants.EXPORT_MODES}) 672 673 """ 674 OP_ID = "OP_BACKUP_PREPARE" 675 OP_DSC_FIELD = "instance_name" 676 __slots__ = [ 677 "instance_name", "mode", 678 ]
679
680 681 -class OpExportInstance(OpCode):
682 """Export an instance. 683 684 For local exports, the export destination is the node name. For remote 685 exports, the export destination is a list of tuples, each consisting of 686 hostname/IP address, port, HMAC and HMAC salt. The HMAC is calculated using 687 the cluster domain secret over the value "${index}:${hostname}:${port}". The 688 destination X509 CA must be a signed certificate. 689 690 @ivar mode: Export mode (one of L{constants.EXPORT_MODES}) 691 @ivar target_node: Export destination 692 @ivar x509_key_name: X509 key to use (remote export only) 693 @ivar destination_x509_ca: Destination X509 CA in PEM format (remote export 694 only) 695 696 """ 697 OP_ID = "OP_BACKUP_EXPORT" 698 OP_DSC_FIELD = "instance_name" 699 __slots__ = [ 700 # TODO: Rename target_node as it changes meaning for different export modes 701 # (e.g. "destination") 702 "instance_name", "target_node", "shutdown", "shutdown_timeout", 703 "remove_instance", 704 "ignore_remove_failures", 705 "mode", 706 "x509_key_name", 707 "destination_x509_ca", 708 ]
709
710 711 -class OpRemoveExport(OpCode):
712 """Remove an instance's export.""" 713 OP_ID = "OP_BACKUP_REMOVE" 714 OP_DSC_FIELD = "instance_name" 715 __slots__ = ["instance_name"]
716
717 718 # Tags opcodes 719 -class OpGetTags(OpCode):
720 """Returns the tags of the given object.""" 721 OP_ID = "OP_TAGS_GET" 722 OP_DSC_FIELD = "name" 723 __slots__ = ["kind", "name"]
724
725 726 -class OpSearchTags(OpCode):
727 """Searches the tags in the cluster for a given pattern.""" 728 OP_ID = "OP_TAGS_SEARCH" 729 OP_DSC_FIELD = "pattern" 730 __slots__ = ["pattern"]
731
732 733 -class OpAddTags(OpCode):
734 """Add a list of tags on a given object.""" 735 OP_ID = "OP_TAGS_SET" 736 __slots__ = ["kind", "name", "tags"]
737
738 739 -class OpDelTags(OpCode):
740 """Remove a list of tags from a given object.""" 741 OP_ID = "OP_TAGS_DEL" 742 __slots__ = ["kind", "name", "tags"]
743
744 745 # Test opcodes 746 -class OpTestDelay(OpCode):
747 """Sleeps for a configured amount of time. 748 749 This is used just for debugging and testing. 750 751 Parameters: 752 - duration: the time to sleep 753 - on_master: if true, sleep on the master 754 - on_nodes: list of nodes in which to sleep 755 756 If the on_master parameter is true, it will execute a sleep on the 757 master (before any node sleep). 758 759 If the on_nodes list is not empty, it will sleep on those nodes 760 (after the sleep on the master, if that is enabled). 761 762 As an additional feature, the case of duration < 0 will be reported 763 as an execution error, so this opcode can be used as a failure 764 generator. The case of duration == 0 will not be treated specially. 765 766 """ 767 OP_ID = "OP_TEST_DELAY" 768 OP_DSC_FIELD = "duration" 769 __slots__ = ["duration", "on_master", "on_nodes", "repeat"]
770
771 772 -class OpTestAllocator(OpCode):
773 """Allocator framework testing. 774 775 This opcode has two modes: 776 - gather and return allocator input for a given mode (allocate new 777 or replace secondary) and a given instance definition (direction 778 'in') 779 - run a selected allocator for a given operation (as above) and 780 return the allocator output (direction 'out') 781 782 """ 783 OP_ID = "OP_TEST_ALLOCATOR" 784 OP_DSC_FIELD = "allocator" 785 __slots__ = [ 786 "direction", "mode", "allocator", "name", 787 "mem_size", "disks", "disk_template", 788 "os", "tags", "nics", "vcpus", "hypervisor", 789 "evac_nodes", 790 ]
791
792 793 -class OpTestJobqueue(OpCode):
794 """Utility opcode to test some aspects of the job queue. 795 796 """ 797 OP_ID = "OP_TEST_JQUEUE" 798 __slots__ = [ 799 "notify_waitlock", 800 "notify_exec", 801 "log_messages", 802 "fail", 803 ]
804 805 806 OP_MAPPING = dict([(v.OP_ID, v) for v in globals().values() 807 if (isinstance(v, type) and issubclass(v, OpCode) and 808 hasattr(v, "OP_ID"))]) 809