Statistics
| Branch: | Tag: | Revision:

root / lib / opcodes.py @ 0e46916d

History | View | Annotate | Download (10.6 kB)

1
#
2
#
3

    
4
# Copyright (C) 2006, 2007 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
  """
45
  __slots__ = []
46

    
47
  def __init__(self, **kwargs):
48
    for key in kwargs:
49
      if key not in self.__slots__:
50
        raise TypeError("Object %s doesn't support the parameter '%s'" %
51
                        (self.__class__.__name__, key))
52
      setattr(self, key, kwargs[key])
53

    
54
  def __getstate__(self):
55
    state = {}
56
    for name in self.__slots__:
57
      if hasattr(self, name):
58
        state[name] = getattr(self, name)
59
    return state
60

    
61
  def __setstate__(self, state):
62
    if not isinstance(state, dict):
63
      raise ValueError("Invalid data to __setstate__: expected dict, got %s" %
64
                       type(state))
65

    
66
    for name in self.__slots__:
67
      if name not in state:
68
        delattr(self, name)
69

    
70
    for name in state:
71
      setattr(self, name, state[name])
72

    
73

    
74
class OpCode(BaseOpCode):
75
  """Abstract OpCode"""
76
  OP_ID = "OP_ABSTRACT"
77
  __slots__ = []
78

    
79
  def __getstate__(self):
80
    """Specialized getstate for opcodes.
81

82
    """
83
    data = BaseOpCode.__getstate__(self)
84
    data["OP_ID"] = self.OP_ID
85
    return data
86

    
87
  @classmethod
88
  def LoadOpCode(cls, data):
89
    """Generic load opcode method.
90

91
    """
92
    if not isinstance(data, dict):
93
      raise ValueError("Invalid data to LoadOpCode (%s)" % type(data))
94
    if "OP_ID" not in data:
95
      raise ValueError("Invalid data to LoadOpcode, missing OP_ID")
96
    op_id = data["OP_ID"]
97
    op_class = None
98
    for item in globals().values():
99
      if (isinstance(item, type) and
100
          issubclass(item, cls) and
101
          hasattr(item, "OP_ID") and
102
          getattr(item, "OP_ID") == op_id):
103
        op_class = item
104
        break
105
    if op_class is None:
106
      raise ValueError("Invalid data to LoadOpCode: OP_ID %s unsupported" %
107
                       op_id)
108
    op = op_class()
109
    new_data = data.copy()
110
    del new_data["OP_ID"]
111
    op.__setstate__(new_data)
112
    return op
113

    
114

    
115
class OpDestroyCluster(OpCode):
116
  """Destroy the cluster."""
117
  OP_ID = "OP_CLUSTER_DESTROY"
118
  __slots__ = []
119

    
120

    
121
class OpQueryClusterInfo(OpCode):
122
  """Query cluster information."""
123
  OP_ID = "OP_CLUSTER_QUERY"
124
  __slots__ = []
125

    
126

    
127
class OpVerifyCluster(OpCode):
128
  """Verify the cluster state."""
129
  OP_ID = "OP_CLUSTER_VERIFY"
130
  __slots__ = ["skip_checks"]
131

    
132

    
133
class OpVerifyDisks(OpCode):
134
  """Verify the cluster disks.
135

136
  Parameters: none
137

138
  Result: two lists:
139
    - list of node names with bad data returned (unreachable, etc.)
140
    - dist of node names with broken volume groups (values: error msg)
141
    - list of instances with degraded disks (that should be activated)
142
    - dict of instances with missing logical volumes (values: (node, vol)
143
      pairs with details about the missing volumes)
144

145
  In normal operation, all lists should be empty. A non-empty instance
146
  list (3rd element of the result) is still ok (errors were fixed) but
147
  non-empty node list means some node is down, and probably there are
148
  unfixable drbd errors.
149

150
  Note that only instances that are drbd-based are taken into
151
  consideration. This might need to be revisited in the future.
152

153
  """
154
  OP_ID = "OP_CLUSTER_VERIFY_DISKS"
155
  __slots__ = []
156

    
157

    
158
class OpMasterFailover(OpCode):
159
  """Do a master failover."""
160
  OP_ID = "OP_CLUSTER_MASTERFAILOVER"
161
  __slots__ = []
162

    
163

    
164
class OpDumpClusterConfig(OpCode):
165
  """Dump the cluster configuration."""
166
  OP_ID = "OP_CLUSTER_DUMPCONFIG"
167
  __slots__ = []
168

    
169

    
170
class OpRenameCluster(OpCode):
171
  """Rename the cluster."""
172
  OP_ID = "OP_CLUSTER_RENAME"
173
  __slots__ = ["name"]
174

    
175

    
176
class OpSetClusterParams(OpCode):
177
  """Change the parameters of the cluster."""
178
  OP_ID = "OP_CLUSTER_SET_PARAMS"
179
  __slots__ = ["vg_name"]
180

    
181

    
182
# node opcodes
183

    
184
class OpRemoveNode(OpCode):
185
  """Remove a node."""
186
  OP_ID = "OP_NODE_REMOVE"
187
  __slots__ = ["node_name"]
188

    
189

    
190
class OpAddNode(OpCode):
191
  """Add a node."""
192
  OP_ID = "OP_NODE_ADD"
193
  __slots__ = ["node_name", "primary_ip", "secondary_ip", "readd"]
194

    
195

    
196
class OpQueryNodes(OpCode):
197
  """Compute the list of nodes."""
198
  OP_ID = "OP_NODE_QUERY"
199
  __slots__ = ["output_fields", "names"]
200

    
201

    
202
class OpQueryNodeVolumes(OpCode):
203
  """Get list of volumes on node."""
204
  OP_ID = "OP_NODE_QUERYVOLS"
205
  __slots__ = ["nodes", "output_fields"]
206

    
207

    
208
# instance opcodes
209

    
210
class OpCreateInstance(OpCode):
211
  """Create an instance."""
212
  OP_ID = "OP_INSTANCE_CREATE"
213
  __slots__ = [
214
    "instance_name", "mem_size", "disk_size", "os_type", "pnode",
215
    "disk_template", "snode", "swap_size", "mode",
216
    "vcpus", "ip", "bridge", "src_node", "src_path", "start",
217
    "wait_for_sync", "ip_check", "mac",
218
    "kernel_path", "initrd_path", "hvm_boot_order", "hvm_acpi",
219
    "hvm_pae", "hvm_cdrom_image_path", "vnc_bind_address",
220
    "file_storage_dir", "file_driver",
221
    "iallocator",
222
    ]
223

    
224

    
225
class OpReinstallInstance(OpCode):
226
  """Reinstall an instance's OS."""
227
  OP_ID = "OP_INSTANCE_REINSTALL"
228
  __slots__ = ["instance_name", "os_type"]
229

    
230

    
231
class OpRemoveInstance(OpCode):
232
  """Remove an instance."""
233
  OP_ID = "OP_INSTANCE_REMOVE"
234
  __slots__ = ["instance_name", "ignore_failures"]
235

    
236

    
237
class OpRenameInstance(OpCode):
238
  """Rename an instance."""
239
  OP_ID = "OP_INSTANCE_RENAME"
240
  __slots__ = ["instance_name", "ignore_ip", "new_name"]
241

    
242

    
243
class OpStartupInstance(OpCode):
244
  """Startup an instance."""
245
  OP_ID = "OP_INSTANCE_STARTUP"
246
  __slots__ = ["instance_name", "force", "extra_args"]
247

    
248

    
249
class OpShutdownInstance(OpCode):
250
  """Shutdown an instance."""
251
  OP_ID = "OP_INSTANCE_SHUTDOWN"
252
  __slots__ = ["instance_name"]
253

    
254

    
255
class OpRebootInstance(OpCode):
256
  """Reboot an instance."""
257
  OP_ID = "OP_INSTANCE_REBOOT"
258
  __slots__ = ["instance_name", "reboot_type", "extra_args",
259
               "ignore_secondaries" ]
260

    
261

    
262
class OpReplaceDisks(OpCode):
263
  """Replace the disks of an instance."""
264
  OP_ID = "OP_INSTANCE_REPLACE_DISKS"
265
  __slots__ = ["instance_name", "remote_node", "mode", "disks", "iallocator"]
266

    
267

    
268
class OpFailoverInstance(OpCode):
269
  """Failover an instance."""
270
  OP_ID = "OP_INSTANCE_FAILOVER"
271
  __slots__ = ["instance_name", "ignore_consistency"]
272

    
273

    
274
class OpConnectConsole(OpCode):
275
  """Connect to an instance's console."""
276
  OP_ID = "OP_INSTANCE_CONSOLE"
277
  __slots__ = ["instance_name"]
278

    
279

    
280
class OpActivateInstanceDisks(OpCode):
281
  """Activate an instance's disks."""
282
  OP_ID = "OP_INSTANCE_ACTIVATE_DISKS"
283
  __slots__ = ["instance_name"]
284

    
285

    
286
class OpDeactivateInstanceDisks(OpCode):
287
  """Deactivate an instance's disks."""
288
  OP_ID = "OP_INSTANCE_DEACTIVATE_DISKS"
289
  __slots__ = ["instance_name"]
290

    
291

    
292
class OpQueryInstances(OpCode):
293
  """Compute the list of instances."""
294
  OP_ID = "OP_INSTANCE_QUERY"
295
  __slots__ = ["output_fields", "names"]
296

    
297

    
298
class OpQueryInstanceData(OpCode):
299
  """Compute the run-time status of instances."""
300
  OP_ID = "OP_INSTANCE_QUERY_DATA"
301
  __slots__ = ["instances"]
302

    
303

    
304
class OpSetInstanceParams(OpCode):
305
  """Change the parameters of an instance."""
306
  OP_ID = "OP_INSTANCE_SET_PARAMS"
307
  __slots__ = [
308
    "instance_name", "mem", "vcpus", "ip", "bridge", "mac",
309
    "kernel_path", "initrd_path", "hvm_boot_order", "hvm_acpi",
310
    "hvm_pae", "hvm_cdrom_image_path", "vnc_bind_address"
311
    ]
312

    
313

    
314
class OpGrowDisk(OpCode):
315
  """Grow a disk of an instance."""
316
  OP_ID = "OP_INSTANCE_GROW_DISK"
317
  __slots__ = ["instance_name", "disk", "amount"]
318

    
319

    
320
# OS opcodes
321
class OpDiagnoseOS(OpCode):
322
  """Compute the list of guest operating systems."""
323
  OP_ID = "OP_OS_DIAGNOSE"
324
  __slots__ = ["output_fields", "names"]
325

    
326

    
327
# Exports opcodes
328
class OpQueryExports(OpCode):
329
  """Compute the list of exported images."""
330
  OP_ID = "OP_BACKUP_QUERY"
331
  __slots__ = ["nodes"]
332

    
333

    
334
class OpExportInstance(OpCode):
335
  """Export an instance."""
336
  OP_ID = "OP_BACKUP_EXPORT"
337
  __slots__ = ["instance_name", "target_node", "shutdown"]
338

    
339
class OpRemoveExport(OpCode):
340
  """Remove an instance's export."""
341
  OP_ID = "OP_BACKUP_REMOVE"
342
  __slots__ = ["instance_name"]
343

    
344
# Tags opcodes
345
class OpGetTags(OpCode):
346
  """Returns the tags of the given object."""
347
  OP_ID = "OP_TAGS_GET"
348
  __slots__ = ["kind", "name"]
349

    
350

    
351
class OpSearchTags(OpCode):
352
  """Searches the tags in the cluster for a given pattern."""
353
  OP_ID = "OP_TAGS_SEARCH"
354
  __slots__ = ["pattern"]
355

    
356

    
357
class OpAddTags(OpCode):
358
  """Add a list of tags on a given object."""
359
  OP_ID = "OP_TAGS_SET"
360
  __slots__ = ["kind", "name", "tags"]
361

    
362

    
363
class OpDelTags(OpCode):
364
  """Remove a list of tags from a given object."""
365
  OP_ID = "OP_TAGS_DEL"
366
  __slots__ = ["kind", "name", "tags"]
367

    
368

    
369
# Test opcodes
370
class OpTestDelay(OpCode):
371
  """Sleeps for a configured amount of time.
372

373
  This is used just for debugging and testing.
374

375
  Parameters:
376
    - duration: the time to sleep
377
    - on_master: if true, sleep on the master
378
    - on_nodes: list of nodes in which to sleep
379

380
  If the on_master parameter is true, it will execute a sleep on the
381
  master (before any node sleep).
382

383
  If the on_nodes list is not empty, it will sleep on those nodes
384
  (after the sleep on the master, if that is enabled).
385

386
  As an additional feature, the case of duration < 0 will be reported
387
  as an execution error, so this opcode can be used as a failure
388
  generator. The case of duration == 0 will not be treated specially.
389

390
  """
391
  OP_ID = "OP_TEST_DELAY"
392
  __slots__ = ["duration", "on_master", "on_nodes"]
393

    
394

    
395
class OpTestAllocator(OpCode):
396
  """Allocator framework testing.
397

398
  This opcode has two modes:
399
    - gather and return allocator input for a given mode (allocate new
400
      or replace secondary) and a given instance definition (direction
401
      'in')
402
    - run a selected allocator for a given operation (as above) and
403
      return the allocator output (direction 'out')
404

405
  """
406
  OP_ID = "OP_TEST_ALLOCATOR"
407
  __slots__ = [
408
    "direction", "mode", "allocator", "name",
409
    "mem_size", "disks", "disk_template",
410
    "os", "tags", "nics", "vcpus",
411
    ]