4 # Copyright (C) 2006, 2007 Google Inc.
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 This module implements the data structures which define the cluster
25 operations - the so-called opcodes.
28 This module implements the logic for doing operations in the cluster. There
29 are two kinds of classes defined:
30 - opcodes, which are small classes only holding data for the task at hand
31 - logical units, which know how to deal with their specific opcode only
35 # this are practically structures, so disable the message about too
37 # pylint: disable-msg=R0903
41 """A simple serializable object.
43 This object serves as a parent class for both OpCode and Job since
44 they are serialized in the same way.
49 def __init__(self, **kwargs):
51 if key not in self.__slots__:
52 raise TypeError("Object %s doesn't support the parameter '%s'" %
53 (self.__class__.__name__, key))
54 setattr(self, key, kwargs[key])
56 def __getstate__(self):
58 for name in self.__slots__:
59 if hasattr(self, name):
60 state[name] = getattr(self, name)
63 def __setstate__(self, state):
64 if not isinstance(state, dict):
65 raise ValueError("Invalid data to __setstate__: expected dict, got %s" %
68 for name in self.__slots__:
73 setattr(self, name, state[name])
81 def __getstate__(self):
82 """Specialized getstate for opcodes.
85 data = BaseJO.__getstate__(self)
86 data["OP_ID"] = self.OP_ID
90 def LoadOpCode(cls, data):
91 """Generic load opcode method.
94 if not isinstance(data, dict):
95 raise ValueError("Invalid data to LoadOpCode (%s)" % type(data))
96 if "OP_ID" not in data:
97 raise ValueError("Invalid data to LoadOpcode, missing OP_ID")
100 for item in globals().values():
101 if (isinstance(item, type) and
102 issubclass(item, cls) and
103 hasattr(item, "OP_ID") and
104 getattr(item, "OP_ID") == op_id):
108 raise ValueError("Invalid data to LoadOpCode: OP_ID %s unsupported" %
111 new_data = data.copy()
112 del new_data["OP_ID"]
113 op.__setstate__(new_data)
117 class OpDestroyCluster(OpCode):
118 """Destroy the cluster."""
119 OP_ID = "OP_CLUSTER_DESTROY"
123 class OpQueryClusterInfo(OpCode):
124 """Query cluster information."""
125 OP_ID = "OP_CLUSTER_QUERY"
129 class OpVerifyCluster(OpCode):
130 """Verify the cluster state."""
131 OP_ID = "OP_CLUSTER_VERIFY"
132 __slots__ = ["skip_checks"]
135 class OpVerifyDisks(OpCode):
136 """Verify the cluster disks.
141 - list of node names with bad data returned (unreachable, etc.)
142 - dist of node names with broken volume groups (values: error msg)
143 - list of instances with degraded disks (that should be activated)
144 - dict of instances with missing logical volumes (values: (node, vol)
145 pairs with details about the missing volumes)
147 In normal operation, all lists should be empty. A non-empty instance
148 list (3rd element of the result) is still ok (errors were fixed) but
149 non-empty node list means some node is down, and probably there are
150 unfixable drbd errors.
152 Note that only instances that are drbd-based are taken into
153 consideration. This might need to be revisited in the future.
156 OP_ID = "OP_CLUSTER_VERIFY_DISKS"
160 class OpMasterFailover(OpCode):
161 """Do a master failover."""
162 OP_ID = "OP_CLUSTER_MASTERFAILOVER"
166 class OpDumpClusterConfig(OpCode):
167 """Dump the cluster configuration."""
168 OP_ID = "OP_CLUSTER_DUMPCONFIG"
172 class OpRenameCluster(OpCode):
173 """Rename the cluster."""
174 OP_ID = "OP_CLUSTER_RENAME"
178 class OpSetClusterParams(OpCode):
179 """Change the parameters of the cluster."""
180 OP_ID = "OP_CLUSTER_SET_PARAMS"
181 __slots__ = ["vg_name"]
186 class OpRemoveNode(OpCode):
188 OP_ID = "OP_NODE_REMOVE"
189 __slots__ = ["node_name"]
192 class OpAddNode(OpCode):
194 OP_ID = "OP_NODE_ADD"
195 __slots__ = ["node_name", "primary_ip", "secondary_ip", "readd"]
198 class OpQueryNodes(OpCode):
199 """Compute the list of nodes."""
200 OP_ID = "OP_NODE_QUERY"
201 __slots__ = ["output_fields", "names"]
204 class OpQueryNodeVolumes(OpCode):
205 """Get list of volumes on node."""
206 OP_ID = "OP_NODE_QUERYVOLS"
207 __slots__ = ["nodes", "output_fields"]
212 class OpCreateInstance(OpCode):
213 """Create an instance."""
214 OP_ID = "OP_INSTANCE_CREATE"
216 "instance_name", "mem_size", "disk_size", "os_type", "pnode",
217 "disk_template", "snode", "swap_size", "mode",
218 "vcpus", "ip", "bridge", "src_node", "src_path", "start",
219 "wait_for_sync", "ip_check", "mac",
220 "kernel_path", "initrd_path", "hvm_boot_order", "hvm_acpi",
221 "hvm_pae", "hvm_cdrom_image_path", "vnc_bind_address",
222 "file_storage_dir", "file_driver",
227 class OpReinstallInstance(OpCode):
228 """Reinstall an instance's OS."""
229 OP_ID = "OP_INSTANCE_REINSTALL"
230 __slots__ = ["instance_name", "os_type"]
233 class OpRemoveInstance(OpCode):
234 """Remove an instance."""
235 OP_ID = "OP_INSTANCE_REMOVE"
236 __slots__ = ["instance_name", "ignore_failures"]
239 class OpRenameInstance(OpCode):
240 """Rename an instance."""
241 OP_ID = "OP_INSTANCE_RENAME"
242 __slots__ = ["instance_name", "ignore_ip", "new_name"]
245 class OpStartupInstance(OpCode):
246 """Startup an instance."""
247 OP_ID = "OP_INSTANCE_STARTUP"
248 __slots__ = ["instance_name", "force", "extra_args"]
251 class OpShutdownInstance(OpCode):
252 """Shutdown an instance."""
253 OP_ID = "OP_INSTANCE_SHUTDOWN"
254 __slots__ = ["instance_name"]
257 class OpRebootInstance(OpCode):
258 """Reboot an instance."""
259 OP_ID = "OP_INSTANCE_REBOOT"
260 __slots__ = ["instance_name", "reboot_type", "extra_args",
261 "ignore_secondaries" ]
264 class OpReplaceDisks(OpCode):
265 """Replace the disks of an instance."""
266 OP_ID = "OP_INSTANCE_REPLACE_DISKS"
267 __slots__ = ["instance_name", "remote_node", "mode", "disks", "iallocator"]
270 class OpFailoverInstance(OpCode):
271 """Failover an instance."""
272 OP_ID = "OP_INSTANCE_FAILOVER"
273 __slots__ = ["instance_name", "ignore_consistency"]
276 class OpConnectConsole(OpCode):
277 """Connect to an instance's console."""
278 OP_ID = "OP_INSTANCE_CONSOLE"
279 __slots__ = ["instance_name"]
282 class OpActivateInstanceDisks(OpCode):
283 """Activate an instance's disks."""
284 OP_ID = "OP_INSTANCE_ACTIVATE_DISKS"
285 __slots__ = ["instance_name"]
288 class OpDeactivateInstanceDisks(OpCode):
289 """Deactivate an instance's disks."""
290 OP_ID = "OP_INSTANCE_DEACTIVATE_DISKS"
291 __slots__ = ["instance_name"]
294 class OpQueryInstances(OpCode):
295 """Compute the list of instances."""
296 OP_ID = "OP_INSTANCE_QUERY"
297 __slots__ = ["output_fields", "names"]
300 class OpQueryInstanceData(OpCode):
301 """Compute the run-time status of instances."""
302 OP_ID = "OP_INSTANCE_QUERY_DATA"
303 __slots__ = ["instances"]
306 class OpSetInstanceParams(OpCode):
307 """Change the parameters of an instance."""
308 OP_ID = "OP_INSTANCE_SET_PARAMS"
310 "instance_name", "mem", "vcpus", "ip", "bridge", "mac",
311 "kernel_path", "initrd_path", "hvm_boot_order", "hvm_acpi",
312 "hvm_pae", "hvm_cdrom_image_path", "vnc_bind_address"
316 class OpGrowDisk(OpCode):
317 """Grow a disk of an instance."""
318 OP_ID = "OP_INSTANCE_GROW_DISK"
319 __slots__ = ["instance_name", "disk", "amount"]
323 class OpDiagnoseOS(OpCode):
324 """Compute the list of guest operating systems."""
325 OP_ID = "OP_OS_DIAGNOSE"
326 __slots__ = ["output_fields", "names"]
330 class OpQueryExports(OpCode):
331 """Compute the list of exported images."""
332 OP_ID = "OP_BACKUP_QUERY"
333 __slots__ = ["nodes"]
336 class OpExportInstance(OpCode):
337 """Export an instance."""
338 OP_ID = "OP_BACKUP_EXPORT"
339 __slots__ = ["instance_name", "target_node", "shutdown"]
341 class OpRemoveExport(OpCode):
342 """Remove an instance's export."""
343 OP_ID = "OP_BACKUP_REMOVE"
344 __slots__ = ["instance_name"]
347 class OpGetTags(OpCode):
348 """Returns the tags of the given object."""
349 OP_ID = "OP_TAGS_GET"
350 __slots__ = ["kind", "name"]
353 class OpSearchTags(OpCode):
354 """Searches the tags in the cluster for a given pattern."""
355 OP_ID = "OP_TAGS_SEARCH"
356 __slots__ = ["pattern"]
359 class OpAddTags(OpCode):
360 """Add a list of tags on a given object."""
361 OP_ID = "OP_TAGS_SET"
362 __slots__ = ["kind", "name", "tags"]
365 class OpDelTags(OpCode):
366 """Remove a list of tags from a given object."""
367 OP_ID = "OP_TAGS_DEL"
368 __slots__ = ["kind", "name", "tags"]
372 class OpTestDelay(OpCode):
373 """Sleeps for a configured amount of time.
375 This is used just for debugging and testing.
378 - duration: the time to sleep
379 - on_master: if true, sleep on the master
380 - on_nodes: list of nodes in which to sleep
382 If the on_master parameter is true, it will execute a sleep on the
383 master (before any node sleep).
385 If the on_nodes list is not empty, it will sleep on those nodes
386 (after the sleep on the master, if that is enabled).
388 As an additional feature, the case of duration < 0 will be reported
389 as an execution error, so this opcode can be used as a failure
390 generator. The case of duration == 0 will not be treated specially.
393 OP_ID = "OP_TEST_DELAY"
394 __slots__ = ["duration", "on_master", "on_nodes"]
397 class OpTestAllocator(OpCode):
398 """Allocator framework testing.
400 This opcode has two modes:
401 - gather and return allocator input for a given mode (allocate new
402 or replace secondary) and a given instance definition (direction
404 - run a selected allocator for a given operation (as above) and
405 return the allocator output (direction 'out')
408 OP_ID = "OP_TEST_ALLOCATOR"
410 "direction", "mode", "allocator", "name",
411 "mem_size", "disks", "disk_template",
412 "os", "tags", "nics", "vcpus",