X-Git-Url: https://code.grnet.gr/git/ganeti-local/blobdiff_plain/47804ec9441f89433e3abd117dd578622981dfc4..df5758b1f2312bcb9024f1a2cb3be835c973f8ee:/lib/opcodes.py diff --git a/lib/opcodes.py b/lib/opcodes.py index 929c62f..d314fc8 100644 --- a/lib/opcodes.py +++ b/lib/opcodes.py @@ -1,7 +1,7 @@ # # -# Copyright (C) 2006, 2007 Google Inc. +# Copyright (C) 2006, 2007, 2008, 2009, 2010 Google Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -52,8 +52,9 @@ class BaseOpCode(object): __slots__ attribute for this class. """ + slots = self._all_slots() for key in kwargs: - if key not in self.__slots__: + if key not in slots: raise TypeError("Object %s doesn't support the parameter '%s'" % (self.__class__.__name__, key)) setattr(self, key, kwargs[key]) @@ -69,7 +70,7 @@ class BaseOpCode(object): """ state = {} - for name in self.__slots__: + for name in self._all_slots(): if hasattr(self, name): state[name] = getattr(self, name) return state @@ -88,13 +89,23 @@ class BaseOpCode(object): raise ValueError("Invalid data to __setstate__: expected dict, got %s" % type(state)) - for name in self.__slots__: - if name not in state: + for name in self._all_slots(): + if name not in state and hasattr(self, name): delattr(self, name) for name in state: setattr(self, name, state[name]) + @classmethod + def _all_slots(cls): + """Compute the list of all declared slots for a class. + + """ + slots = [] + for parent in cls.__mro__: + slots.extend(getattr(parent, "__slots__", [])) + return slots + class OpCode(BaseOpCode): """Abstract OpCode. @@ -106,10 +117,11 @@ class OpCode(BaseOpCode): children of this class. @ivar dry_run: Whether the LU should be run in dry-run mode, i.e. just the check steps + @ivar priority: Opcode priority for queue """ OP_ID = "OP_ABSTRACT" - __slots__ = BaseOpCode.__slots__ + ["dry_run"] + __slots__ = ["dry_run", "debug_level", "priority"] def __getstate__(self): """Specialized getstate for opcodes. @@ -164,6 +176,8 @@ class OpCode(BaseOpCode): field_name = getattr(self, "OP_DSC_FIELD", None) if field_name: field_value = getattr(self, field_name, None) + if isinstance(field_value, (list, tuple)): + field_value = ",".join(str(i) for i in field_value) txt = "%s(%s)" % (txt, field_value) return txt @@ -178,7 +192,7 @@ class OpPostInitCluster(OpCode): """ OP_ID = "OP_CLUSTER_POST_INIT" - __slots__ = OpCode.__slots__ + [] + __slots__ = [] class OpDestroyCluster(OpCode): @@ -189,13 +203,13 @@ class OpDestroyCluster(OpCode): """ OP_ID = "OP_CLUSTER_DESTROY" - __slots__ = OpCode.__slots__ + [] + __slots__ = [] class OpQueryClusterInfo(OpCode): """Query cluster information.""" OP_ID = "OP_CLUSTER_QUERY" - __slots__ = OpCode.__slots__ + [] + __slots__ = [] class OpVerifyCluster(OpCode): @@ -209,8 +223,8 @@ class OpVerifyCluster(OpCode): """ OP_ID = "OP_CLUSTER_VERIFY" - __slots__ = OpCode.__slots__ + ["skip_checks", "verbose", "error_codes", - "debug_simulate_errors"] + __slots__ = ["skip_checks", "verbose", "error_codes", + "debug_simulate_errors"] class OpVerifyDisks(OpCode): @@ -235,7 +249,7 @@ class OpVerifyDisks(OpCode): """ OP_ID = "OP_CLUSTER_VERIFY_DISKS" - __slots__ = OpCode.__slots__ + [] + __slots__ = [] class OpRepairDiskSizes(OpCode): @@ -261,7 +275,7 @@ class OpRepairDiskSizes(OpCode): class OpQueryConfigValues(OpCode): """Query cluster configuration values.""" OP_ID = "OP_CLUSTER_CONFIG_QUERY" - __slots__ = OpCode.__slots__ + ["output_fields"] + __slots__ = ["output_fields"] class OpRenameCluster(OpCode): @@ -275,7 +289,7 @@ class OpRenameCluster(OpCode): """ OP_ID = "OP_CLUSTER_RENAME" OP_DSC_FIELD = "name" - __slots__ = OpCode.__slots__ + ["name"] + __slots__ = ["name"] class OpSetClusterParams(OpCode): @@ -286,13 +300,24 @@ class OpSetClusterParams(OpCode): """ OP_ID = "OP_CLUSTER_SET_PARAMS" - __slots__ = OpCode.__slots__ + [ + __slots__ = [ "vg_name", + "drbd_helper", "enabled_hypervisors", "hvparams", + "os_hvp", "beparams", + "osparams", "nicparams", "candidate_pool_size", + "maintain_node_health", + "uid_pool", + "add_uids", + "remove_uids", + "default_iallocator", + "reserved_lvs", + "hidden_oss", + "blacklisted_oss", ] @@ -301,8 +326,7 @@ class OpRedistributeConfig(OpCode): """ OP_ID = "OP_CLUSTER_REDIST_CONF" - __slots__ = OpCode.__slots__ + [ - ] + __slots__ = [] # node opcodes @@ -316,7 +340,7 @@ class OpRemoveNode(OpCode): """ OP_ID = "OP_NODE_REMOVE" OP_DSC_FIELD = "node_name" - __slots__ = OpCode.__slots__ + ["node_name"] + __slots__ = ["node_name"] class OpAddNode(OpCode): @@ -343,27 +367,25 @@ class OpAddNode(OpCode): """ OP_ID = "OP_NODE_ADD" OP_DSC_FIELD = "node_name" - __slots__ = OpCode.__slots__ + [ - "node_name", "primary_ip", "secondary_ip", "readd", - ] + __slots__ = ["node_name", "primary_ip", "secondary_ip", "readd", "nodegroup"] class OpQueryNodes(OpCode): """Compute the list of nodes.""" OP_ID = "OP_NODE_QUERY" - __slots__ = OpCode.__slots__ + ["output_fields", "names", "use_locking"] + __slots__ = ["output_fields", "names", "use_locking"] class OpQueryNodeVolumes(OpCode): """Get list of volumes on node.""" OP_ID = "OP_NODE_QUERYVOLS" - __slots__ = OpCode.__slots__ + ["nodes", "output_fields"] + __slots__ = ["nodes", "output_fields"] class OpQueryNodeStorage(OpCode): """Get information on storage for node(s).""" OP_ID = "OP_NODE_QUERY_STORAGE" - __slots__ = OpCode.__slots__ + [ + __slots__ = [ "nodes", "storage_type", "name", @@ -372,9 +394,9 @@ class OpQueryNodeStorage(OpCode): class OpModifyNodeStorage(OpCode): - """""" + """Modifies the properies of a storage unit""" OP_ID = "OP_NODE_MODIFY_STORAGE" - __slots__ = OpCode.__slots__ + [ + __slots__ = [ "node_name", "storage_type", "name", @@ -386,10 +408,11 @@ class OpRepairNodeStorage(OpCode): """Repairs the volume group on a node.""" OP_ID = "OP_REPAIR_NODE_STORAGE" OP_DSC_FIELD = "node_name" - __slots__ = OpCode.__slots__ + [ + __slots__ = [ "node_name", "storage_type", "name", + "ignore_consistency", ] @@ -397,12 +420,13 @@ class OpSetNodeParams(OpCode): """Change the parameters of a node.""" OP_ID = "OP_NODE_SET_PARAMS" OP_DSC_FIELD = "node_name" - __slots__ = OpCode.__slots__ + [ + __slots__ = [ "node_name", "force", "master_candidate", "offline", "drained", + "auto_promote", ] @@ -410,47 +434,57 @@ class OpPowercycleNode(OpCode): """Tries to powercycle a node.""" OP_ID = "OP_NODE_POWERCYCLE" OP_DSC_FIELD = "node_name" - __slots__ = OpCode.__slots__ + [ + __slots__ = [ "node_name", "force", ] -class OpEvacuateNode(OpCode): - """Relocate secondary instances from a node.""" - OP_ID = "OP_NODE_EVACUATE" - OP_DSC_FIELD = "node_name" - __slots__ = OpCode.__slots__ + [ - "node_name", "remote_node", "iallocator", - ] - - class OpMigrateNode(OpCode): """Migrate all instances from a node.""" OP_ID = "OP_NODE_MIGRATE" OP_DSC_FIELD = "node_name" - __slots__ = OpCode.__slots__ + [ + __slots__ = [ "node_name", + "mode", "live", ] +class OpNodeEvacuationStrategy(OpCode): + """Compute the evacuation strategy for a list of nodes.""" + OP_ID = "OP_NODE_EVAC_STRATEGY" + OP_DSC_FIELD = "nodes" + __slots__ = ["nodes", "iallocator", "remote_node"] + + # instance opcodes class OpCreateInstance(OpCode): - """Create an instance.""" + """Create an instance. + + @ivar instance_name: Instance name + @ivar mode: Instance creation mode (one of L{constants.INSTANCE_CREATE_MODES}) + @ivar source_handshake: Signed handshake from source (remote import only) + @ivar source_x509_ca: Source X509 CA in PEM format (remote import only) + @ivar source_instance_name: Previous name of instance (remote import only) + + """ OP_ID = "OP_INSTANCE_CREATE" OP_DSC_FIELD = "instance_name" - __slots__ = OpCode.__slots__ + [ - "instance_name", "os_type", "force_variant", + __slots__ = [ + "instance_name", + "os_type", "force_variant", "no_install", "pnode", "disk_template", "snode", "mode", "disks", "nics", - "src_node", "src_path", "start", - "wait_for_sync", "ip_check", + "src_node", "src_path", "start", "identify_defaults", + "wait_for_sync", "ip_check", "name_check", "file_storage_dir", "file_driver", "iallocator", - "hypervisor", "hvparams", "beparams", - "dry_run", + "hypervisor", "hvparams", "beparams", "osparams", + "source_handshake", + "source_x509_ca", + "source_instance_name", ] @@ -458,21 +492,25 @@ class OpReinstallInstance(OpCode): """Reinstall an instance's OS.""" OP_ID = "OP_INSTANCE_REINSTALL" OP_DSC_FIELD = "instance_name" - __slots__ = OpCode.__slots__ + ["instance_name", "os_type", "force_variant"] + __slots__ = ["instance_name", "os_type", "force_variant"] class OpRemoveInstance(OpCode): """Remove an instance.""" OP_ID = "OP_INSTANCE_REMOVE" OP_DSC_FIELD = "instance_name" - __slots__ = OpCode.__slots__ + ["instance_name", "ignore_failures"] + __slots__ = [ + "instance_name", + "ignore_failures", + "shutdown_timeout", + ] class OpRenameInstance(OpCode): """Rename an instance.""" OP_ID = "OP_INSTANCE_RENAME" - __slots__ = OpCode.__slots__ + [ - "instance_name", "ignore_ip", "new_name", + __slots__ = [ + "instance_name", "ip_check", "new_name", "name_check", ] @@ -480,7 +518,7 @@ class OpStartupInstance(OpCode): """Startup an instance.""" OP_ID = "OP_INSTANCE_STARTUP" OP_DSC_FIELD = "instance_name" - __slots__ = OpCode.__slots__ + [ + __slots__ = [ "instance_name", "force", "hvparams", "beparams", ] @@ -489,15 +527,15 @@ class OpShutdownInstance(OpCode): """Shutdown an instance.""" OP_ID = "OP_INSTANCE_SHUTDOWN" OP_DSC_FIELD = "instance_name" - __slots__ = OpCode.__slots__ + ["instance_name"] + __slots__ = ["instance_name", "timeout"] class OpRebootInstance(OpCode): """Reboot an instance.""" OP_ID = "OP_INSTANCE_REBOOT" OP_DSC_FIELD = "instance_name" - __slots__ = OpCode.__slots__ + [ - "instance_name", "reboot_type", "ignore_secondaries", + __slots__ = [ + "instance_name", "reboot_type", "ignore_secondaries", "shutdown_timeout", ] @@ -505,8 +543,9 @@ class OpReplaceDisks(OpCode): """Replace the disks of an instance.""" OP_ID = "OP_INSTANCE_REPLACE_DISKS" OP_DSC_FIELD = "instance_name" - __slots__ = OpCode.__slots__ + [ + __slots__ = [ "instance_name", "remote_node", "mode", "disks", "iallocator", + "early_release", ] @@ -514,7 +553,9 @@ class OpFailoverInstance(OpCode): """Failover an instance.""" OP_ID = "OP_INSTANCE_FAILOVER" OP_DSC_FIELD = "instance_name" - __slots__ = OpCode.__slots__ + ["instance_name", "ignore_consistency"] + __slots__ = [ + "instance_name", "ignore_consistency", "shutdown_timeout", + ] class OpMigrateInstance(OpCode): @@ -524,11 +565,12 @@ class OpMigrateInstance(OpCode): node. @ivar instance_name: the name of the instance + @ivar mode: the migration mode (live, non-live or None for auto) """ OP_ID = "OP_INSTANCE_MIGRATE" OP_DSC_FIELD = "instance_name" - __slots__ = OpCode.__slots__ + ["instance_name", "live", "cleanup"] + __slots__ = ["instance_name", "mode", "cleanup", "live"] class OpMoveInstance(OpCode): @@ -543,57 +585,60 @@ class OpMoveInstance(OpCode): """ OP_ID = "OP_INSTANCE_MOVE" OP_DSC_FIELD = "instance_name" - __slots__ = OpCode.__slots__ + ["instance_name", "target_node"] + __slots__ = [ + "instance_name", "target_node", "shutdown_timeout", + ] class OpConnectConsole(OpCode): """Connect to an instance's console.""" OP_ID = "OP_INSTANCE_CONSOLE" OP_DSC_FIELD = "instance_name" - __slots__ = OpCode.__slots__ + ["instance_name"] + __slots__ = ["instance_name"] class OpActivateInstanceDisks(OpCode): """Activate an instance's disks.""" OP_ID = "OP_INSTANCE_ACTIVATE_DISKS" OP_DSC_FIELD = "instance_name" - __slots__ = OpCode.__slots__ + ["instance_name", "ignore_size"] + __slots__ = ["instance_name", "ignore_size"] class OpDeactivateInstanceDisks(OpCode): """Deactivate an instance's disks.""" OP_ID = "OP_INSTANCE_DEACTIVATE_DISKS" OP_DSC_FIELD = "instance_name" - __slots__ = OpCode.__slots__ + ["instance_name"] + __slots__ = ["instance_name"] class OpRecreateInstanceDisks(OpCode): """Deactivate an instance's disks.""" OP_ID = "OP_INSTANCE_RECREATE_DISKS" OP_DSC_FIELD = "instance_name" - __slots__ = OpCode.__slots__ + ["instance_name", "disks"] + __slots__ = ["instance_name", "disks"] class OpQueryInstances(OpCode): """Compute the list of instances.""" OP_ID = "OP_INSTANCE_QUERY" - __slots__ = OpCode.__slots__ + ["output_fields", "names", "use_locking"] + __slots__ = ["output_fields", "names", "use_locking"] class OpQueryInstanceData(OpCode): """Compute the run-time status of instances.""" OP_ID = "OP_INSTANCE_QUERY_DATA" - __slots__ = OpCode.__slots__ + ["instances", "static"] + __slots__ = ["instances", "static"] class OpSetInstanceParams(OpCode): """Change the parameters of an instance.""" OP_ID = "OP_INSTANCE_SET_PARAMS" OP_DSC_FIELD = "instance_name" - __slots__ = OpCode.__slots__ + [ + __slots__ = [ "instance_name", - "hvparams", "beparams", "force", - "nics", "disks", + "hvparams", "beparams", "osparams", "force", + "nics", "disks", "disk_template", + "remote_node", "os_name", "force_variant", ] @@ -601,7 +646,7 @@ class OpGrowDisk(OpCode): """Grow a disk of an instance.""" OP_ID = "OP_INSTANCE_GROW_DISK" OP_DSC_FIELD = "instance_name" - __slots__ = OpCode.__slots__ + [ + __slots__ = [ "instance_name", "disk", "amount", "wait_for_sync", ] @@ -610,28 +655,65 @@ class OpGrowDisk(OpCode): class OpDiagnoseOS(OpCode): """Compute the list of guest operating systems.""" OP_ID = "OP_OS_DIAGNOSE" - __slots__ = OpCode.__slots__ + ["output_fields", "names"] + __slots__ = ["output_fields", "names"] # Exports opcodes class OpQueryExports(OpCode): """Compute the list of exported images.""" OP_ID = "OP_BACKUP_QUERY" - __slots__ = OpCode.__slots__ + ["nodes", "use_locking"] + __slots__ = ["nodes", "use_locking"] + + +class OpPrepareExport(OpCode): + """Prepares an instance export. + + @ivar instance_name: Instance name + @ivar mode: Export mode (one of L{constants.EXPORT_MODES}) + + """ + OP_ID = "OP_BACKUP_PREPARE" + OP_DSC_FIELD = "instance_name" + __slots__ = [ + "instance_name", "mode", + ] class OpExportInstance(OpCode): - """Export an instance.""" + """Export an instance. + + For local exports, the export destination is the node name. For remote + exports, the export destination is a list of tuples, each consisting of + hostname/IP address, port, HMAC and HMAC salt. The HMAC is calculated using + the cluster domain secret over the value "${index}:${hostname}:${port}". The + destination X509 CA must be a signed certificate. + + @ivar mode: Export mode (one of L{constants.EXPORT_MODES}) + @ivar target_node: Export destination + @ivar x509_key_name: X509 key to use (remote export only) + @ivar destination_x509_ca: Destination X509 CA in PEM format (remote export + only) + + """ OP_ID = "OP_BACKUP_EXPORT" OP_DSC_FIELD = "instance_name" - __slots__ = OpCode.__slots__ + ["instance_name", "target_node", "shutdown"] + __slots__ = [ + # TODO: Rename target_node as it changes meaning for different export modes + # (e.g. "destination") + "instance_name", "target_node", "shutdown", "shutdown_timeout", + "remove_instance", + "ignore_remove_failures", + "mode", + "x509_key_name", + "destination_x509_ca", + ] class OpRemoveExport(OpCode): """Remove an instance's export.""" OP_ID = "OP_BACKUP_REMOVE" OP_DSC_FIELD = "instance_name" - __slots__ = OpCode.__slots__ + ["instance_name"] + __slots__ = ["instance_name"] # Tags opcodes @@ -639,26 +721,26 @@ class OpGetTags(OpCode): """Returns the tags of the given object.""" OP_ID = "OP_TAGS_GET" OP_DSC_FIELD = "name" - __slots__ = OpCode.__slots__ + ["kind", "name"] + __slots__ = ["kind", "name"] class OpSearchTags(OpCode): """Searches the tags in the cluster for a given pattern.""" OP_ID = "OP_TAGS_SEARCH" OP_DSC_FIELD = "pattern" - __slots__ = OpCode.__slots__ + ["pattern"] + __slots__ = ["pattern"] class OpAddTags(OpCode): """Add a list of tags on a given object.""" OP_ID = "OP_TAGS_SET" - __slots__ = OpCode.__slots__ + ["kind", "name", "tags"] + __slots__ = ["kind", "name", "tags"] class OpDelTags(OpCode): """Remove a list of tags from a given object.""" OP_ID = "OP_TAGS_DEL" - __slots__ = OpCode.__slots__ + ["kind", "name", "tags"] + __slots__ = ["kind", "name", "tags"] # Test opcodes @@ -685,7 +767,7 @@ class OpTestDelay(OpCode): """ OP_ID = "OP_TEST_DELAY" OP_DSC_FIELD = "duration" - __slots__ = OpCode.__slots__ + ["duration", "on_master", "on_nodes"] + __slots__ = ["duration", "on_master", "on_nodes", "repeat"] class OpTestAllocator(OpCode): @@ -701,10 +783,36 @@ class OpTestAllocator(OpCode): """ OP_ID = "OP_TEST_ALLOCATOR" OP_DSC_FIELD = "allocator" - __slots__ = OpCode.__slots__ + [ + __slots__ = [ "direction", "mode", "allocator", "name", "mem_size", "disks", "disk_template", "os", "tags", "nics", "vcpus", "hypervisor", + "evac_nodes", + ] + + +class OpTestJobqueue(OpCode): + """Utility opcode to test some aspects of the job queue. + + """ + OP_ID = "OP_TEST_JQUEUE" + __slots__ = [ + "notify_waitlock", + "notify_exec", + "log_messages", + "fail", + ] + + +class OpTestDummy(OpCode): + """Utility opcode used by unittests. + + """ + OP_ID = "OP_TEST_DUMMY" + __slots__ = [ + "result", + "messages", + "fail", ]