Statistics
| Branch: | Tag: | Revision:

root / lib / opcodes.py.in_before @ 355d1f32

History | View | Annotate | Download (6.9 kB)

1
#
2
#
3

    
4
# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 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
Note that this file is autogenerated using @src/hs2py@ with a header
25
from @lib/opcodes.py.in_before@ and a footer from @lib/opcodes.py.in_after@.
26

    
27
This module implements part of the data structures which define the
28
cluster operations - the so-called opcodes.
29

    
30
Every operation which modifies the cluster state is expressed via
31
opcodes.
32

    
33
"""
34

    
35
# this are practically structures, so disable the message about too
36
# few public methods:
37
# pylint: disable=R0903
38
# pylint: disable=C0301
39

    
40
from ganeti import constants
41
from ganeti import ht
42

    
43
from ganeti import opcodes_base
44

    
45

    
46
class OpCode(opcodes_base.BaseOpCode):
47
  """Abstract OpCode.
48

    
49
  This is the root of the actual OpCode hierarchy. All clases derived
50
  from this class should override OP_ID.
51

    
52
  @cvar OP_ID: The ID of this opcode. This should be unique amongst all
53
               children of this class.
54
  @cvar OP_DSC_FIELD: The name of a field whose value will be included in the
55
                      string returned by Summary(); see the docstring of that
56
                      method for details).
57
  @cvar OP_DSC_FORMATTER: A callable that should format the OP_DSC_FIELD; if
58
                          not present, then the field will be simply converted
59
                          to string
60
  @cvar OP_PARAMS: List of opcode attributes, the default values they should
61
                   get if not already defined, and types they must match.
62
  @cvar OP_RESULT: Callable to verify opcode result
63
  @cvar WITH_LU: Boolean that specifies whether this should be included in
64
      mcpu's dispatch table
65
  @ivar dry_run: Whether the LU should be run in dry-run mode, i.e. just
66
                 the check steps
67
  @ivar priority: Opcode priority for queue
68

    
69
  """
70
  # pylint: disable=E1101
71
  # as OP_ID is dynamically defined
72
  WITH_LU = True
73
  OP_PARAMS = [
74
    ("dry_run", None, ht.TMaybe(ht.TBool), "Run checks only, don't execute"),
75
    ("debug_level", None, ht.TMaybe(ht.TNonNegative(ht.TInt)), "Debug level"),
76
    ("priority", constants.OP_PRIO_DEFAULT,
77
     ht.TElemOf(constants.OP_PRIO_SUBMIT_VALID), "Opcode priority"),
78
    (opcodes_base.DEPEND_ATTR, None, opcodes_base.BuildJobDepCheck(True),
79
     "Job dependencies; if used through ``SubmitManyJobs`` relative (negative)"
80
     " job IDs can be used; see :doc:`design document <design-chained-jobs>`"
81
     " for details"),
82
    (opcodes_base.COMMENT_ATTR, None, ht.TMaybe(ht.TString),
83
     "Comment describing the purpose of the opcode"),
84
    (constants.OPCODE_REASON, None, ht.TMaybe(ht.TListOf(ht.TAny)),
85
     "The reason trail, describing why the OpCode is executed"),
86
    ]
87
  OP_RESULT = None
88

    
89
  def __getstate__(self):
90
    """Specialized getstate for opcodes.
91

    
92
    This method adds to the state dictionary the OP_ID of the class,
93
    so that on unload we can identify the correct class for
94
    instantiating the opcode.
95

    
96
    @rtype:   C{dict}
97
    @return:  the state as a dictionary
98

    
99
    """
100
    data = opcodes_base.BaseOpCode.__getstate__(self)
101
    data["OP_ID"] = self.OP_ID
102
    return data
103

    
104
  @classmethod
105
  def LoadOpCode(cls, data):
106
    """Generic load opcode method.
107

    
108
    The method identifies the correct opcode class from the dict-form
109
    by looking for a OP_ID key, if this is not found, or its value is
110
    not available in this module as a child of this class, we fail.
111

    
112
    @type data:  C{dict}
113
    @param data: the serialized opcode
114

    
115
    """
116
    if not isinstance(data, dict):
117
      raise ValueError("Invalid data to LoadOpCode (%s)" % type(data))
118
    if "OP_ID" not in data:
119
      raise ValueError("Invalid data to LoadOpcode, missing OP_ID")
120
    op_id = data["OP_ID"]
121
    op_class = None
122
    if op_id in OP_MAPPING:
123
      op_class = OP_MAPPING[op_id]
124
    else:
125
      raise ValueError("Invalid data to LoadOpCode: OP_ID %s unsupported" %
126
                       op_id)
127
    op = op_class()
128
    new_data = data.copy()
129
    del new_data["OP_ID"]
130
    op.__setstate__(new_data)
131
    return op
132

    
133
  def Summary(self):
134
    """Generates a summary description of this opcode.
135

    
136
    The summary is the value of the OP_ID attribute (without the "OP_"
137
    prefix), plus the value of the OP_DSC_FIELD attribute, if one was
138
    defined; this field should allow to easily identify the operation
139
    (for an instance creation job, e.g., it would be the instance
140
    name).
141

    
142
    """
143
    assert self.OP_ID is not None and len(self.OP_ID) > 3
144
    # all OP_ID start with OP_, we remove that
145
    txt = self.OP_ID[3:]
146
    field_name = getattr(self, "OP_DSC_FIELD", None)
147
    if field_name:
148
      field_value = getattr(self, field_name, None)
149
      field_formatter = getattr(self, "OP_DSC_FORMATTER", None)
150
      if callable(field_formatter):
151
        field_value = field_formatter(field_value)
152
      elif isinstance(field_value, (list, tuple)):
153
        field_value = ",".join(str(i) for i in field_value)
154
      txt = "%s(%s)" % (txt, field_value)
155
    return txt
156

    
157
  def TinySummary(self):
158
    """Generates a compact summary description of the opcode.
159

    
160
    """
161
    assert self.OP_ID.startswith("OP_")
162

    
163
    text = self.OP_ID[3:]
164

    
165
    for (prefix, supplement) in opcodes_base.SUMMARY_PREFIX.items():
166
      if text.startswith(prefix):
167
        return supplement + text[len(prefix):]
168

    
169
    return text
170

    
171

    
172
class OpInstanceMultiAllocBase(OpCode):
173
  """Allocates multiple instances.
174

    
175
  """
176
  def __getstate__(self):
177
    """Generic serializer.
178

    
179
    """
180
    state = OpCode.__getstate__(self)
181
    if hasattr(self, "instances"):
182
      # pylint: disable=E1101
183
      state["instances"] = [inst.__getstate__() for inst in self.instances]
184
    return state
185

    
186
  def __setstate__(self, state):
187
    """Generic unserializer.
188

    
189
    This method just restores from the serialized state the attributes
190
    of the current instance.
191

    
192
    @param state: the serialized opcode data
193
    @type state: C{dict}
194

    
195
    """
196
    if not isinstance(state, dict):
197
      raise ValueError("Invalid data to __setstate__: expected dict, got %s" %
198
                       type(state))
199

    
200
    if "instances" in state:
201
      state["instances"] = map(OpCode.LoadOpCode, state["instances"])
202

    
203
    return OpCode.__setstate__(self, state)
204

    
205
  def Validate(self, set_defaults):
206
    """Validates this opcode.
207

    
208
    We do this recursively.
209

    
210
    """
211
    OpCode.Validate(self, set_defaults)
212

    
213
    for inst in self.instances: # pylint: disable=E1101
214
      inst.Validate(set_defaults)