Revision a7399f66 lib/opcodes.py
b/lib/opcodes.py | ||
---|---|---|
40 | 40 |
This object serves as a parent class for OpCode without any custom |
41 | 41 |
field handling. |
42 | 42 |
|
43 |
|
|
44 | 43 |
""" |
45 | 44 |
__slots__ = [] |
46 | 45 |
|
47 | 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 |
""" |
|
48 | 55 |
for key in kwargs: |
49 | 56 |
if key not in self.__slots__: |
50 | 57 |
raise TypeError("Object %s doesn't support the parameter '%s'" % |
... | ... | |
52 | 59 |
setattr(self, key, kwargs[key]) |
53 | 60 |
|
54 | 61 |
def __getstate__(self): |
62 |
"""Generic serializer. |
|
63 |
|
|
64 |
This method just returns the contents of the instance as a |
|
65 |
dictionary. |
|
66 |
|
|
67 |
@rtype: C{dict} |
|
68 |
@return: the instance attributes and their values |
|
69 |
|
|
70 |
""" |
|
55 | 71 |
state = {} |
56 | 72 |
for name in self.__slots__: |
57 | 73 |
if hasattr(self, name): |
... | ... | |
59 | 75 |
return state |
60 | 76 |
|
61 | 77 |
def __setstate__(self, state): |
78 |
"""Generic unserializer. |
|
79 |
|
|
80 |
This method just restores from the serialized state the attributes |
|
81 |
of the current instance. |
|
82 |
|
|
83 |
@param state: the serialized opcode data |
|
84 |
@type state: C{dict} |
|
85 |
|
|
86 |
""" |
|
62 | 87 |
if not isinstance(state, dict): |
63 | 88 |
raise ValueError("Invalid data to __setstate__: expected dict, got %s" % |
64 | 89 |
type(state)) |
... | ... | |
72 | 97 |
|
73 | 98 |
|
74 | 99 |
class OpCode(BaseOpCode): |
75 |
"""Abstract OpCode""" |
|
100 |
"""Abstract OpCode. |
|
101 |
|
|
102 |
This is the root of the actual OpCode hierarchy. All clases derived |
|
103 |
from this class should override OP_ID. |
|
104 |
|
|
105 |
@cvar OP_ID: The ID of this opcode. This should be unique amongst all |
|
106 |
childre of this class. |
|
107 |
|
|
108 |
""" |
|
76 | 109 |
OP_ID = "OP_ABSTRACT" |
77 | 110 |
__slots__ = [] |
78 | 111 |
|
79 | 112 |
def __getstate__(self): |
80 | 113 |
"""Specialized getstate for opcodes. |
81 | 114 |
|
115 |
This method adds to the state dictionary the OP_ID of the class, |
|
116 |
so that on unload we can identify the correct class for |
|
117 |
instantiating the opcode. |
|
118 |
|
|
119 |
@rtype: C{dict} |
|
120 |
@return: the state as a dictionary |
|
121 |
|
|
82 | 122 |
""" |
83 | 123 |
data = BaseOpCode.__getstate__(self) |
84 | 124 |
data["OP_ID"] = self.OP_ID |
... | ... | |
88 | 128 |
def LoadOpCode(cls, data): |
89 | 129 |
"""Generic load opcode method. |
90 | 130 |
|
131 |
The method identifies the correct opcode class from the dict-form |
|
132 |
by looking for a OP_ID key, if this is not found, or its value is |
|
133 |
not available in this module as a child of this class, we fail. |
|
134 |
|
|
135 |
@type data: C{dict} |
|
136 |
@param data: the serialized opcode |
|
137 |
|
|
91 | 138 |
""" |
92 | 139 |
if not isinstance(data, dict): |
93 | 140 |
raise ValueError("Invalid data to LoadOpCode (%s)" % type(data)) |
... | ... | |
113 | 160 |
|
114 | 161 |
|
115 | 162 |
class OpDestroyCluster(OpCode): |
116 |
"""Destroy the cluster.""" |
|
163 |
"""Destroy the cluster. |
|
164 |
|
|
165 |
This opcode has no other parameters. All the state is irreversibly |
|
166 |
lost after the execution of this opcode. |
|
167 |
|
|
168 |
""" |
|
117 | 169 |
OP_ID = "OP_CLUSTER_DESTROY" |
118 | 170 |
__slots__ = [] |
119 | 171 |
|
... | ... | |
125 | 177 |
|
126 | 178 |
|
127 | 179 |
class OpVerifyCluster(OpCode): |
128 |
"""Verify the cluster state.""" |
|
180 |
"""Verify the cluster state. |
|
181 |
|
|
182 |
@type skip_checks: C{list} |
|
183 |
@ivar skip_checks: steps to be skipped from the verify process; this |
|
184 |
needs to be a subset of |
|
185 |
L{constants.VERIFY_OPTIONAL_CHECKS}; currently |
|
186 |
only L{constants.VERIFY_NPLUSONE_MEM} can be passed |
|
187 |
|
|
188 |
""" |
|
129 | 189 |
OP_ID = "OP_CLUSTER_VERIFY" |
130 | 190 |
__slots__ = ["skip_checks"] |
131 | 191 |
|
... | ... | |
137 | 197 |
|
138 | 198 |
Result: two lists: |
139 | 199 |
- list of node names with bad data returned (unreachable, etc.) |
140 |
- dist of node names with broken volume groups (values: error msg)
|
|
200 |
- dict of node names with broken volume groups (values: error msg)
|
|
141 | 201 |
- list of instances with degraded disks (that should be activated) |
142 | 202 |
- dict of instances with missing logical volumes (values: (node, vol) |
143 | 203 |
pairs with details about the missing volumes) |
... | ... | |
168 | 228 |
|
169 | 229 |
|
170 | 230 |
class OpRenameCluster(OpCode): |
171 |
"""Rename the cluster.""" |
|
231 |
"""Rename the cluster. |
|
232 |
|
|
233 |
@type name: C{str} |
|
234 |
@ivar name: The new name of the cluster. The name and/or the master IP |
|
235 |
address will be changed to match the new name and its IP |
|
236 |
address. |
|
237 |
|
|
238 |
""" |
|
172 | 239 |
OP_ID = "OP_CLUSTER_RENAME" |
173 | 240 |
__slots__ = ["name"] |
174 | 241 |
|
175 | 242 |
|
176 | 243 |
class OpSetClusterParams(OpCode): |
177 |
"""Change the parameters of the cluster.""" |
|
244 |
"""Change the parameters of the cluster. |
|
245 |
|
|
246 |
@type vg_name: C{str} or C{None} |
|
247 |
@ivar vg_name: The new volume group name or None to disable LVM usage. |
|
248 |
|
|
249 |
""" |
|
178 | 250 |
OP_ID = "OP_CLUSTER_SET_PARAMS" |
179 | 251 |
__slots__ = ["vg_name"] |
180 | 252 |
|
... | ... | |
182 | 254 |
# node opcodes |
183 | 255 |
|
184 | 256 |
class OpRemoveNode(OpCode): |
185 |
"""Remove a node.""" |
|
257 |
"""Remove a node. |
|
258 |
|
|
259 |
@type node_name: C{str} |
|
260 |
@ivar node_name: The name of the node to remove. If the node still has |
|
261 |
instances on it, the operation will fail. |
|
262 |
|
|
263 |
""" |
|
186 | 264 |
OP_ID = "OP_NODE_REMOVE" |
187 | 265 |
__slots__ = ["node_name"] |
188 | 266 |
|
189 | 267 |
|
190 | 268 |
class OpAddNode(OpCode): |
191 |
"""Add a node.""" |
|
269 |
"""Add a node to the cluster. |
|
270 |
|
|
271 |
@type node_name: C{str} |
|
272 |
@ivar node_name: The name of the node to add. This can be a short name, |
|
273 |
but it will be expanded to the FQDN. |
|
274 |
@type primary_ip: IP address |
|
275 |
@ivar primary_ip: The primary IP of the node. This will be ignored when the |
|
276 |
opcode is submitted, but will be filled during the node |
|
277 |
add (so it will be visible in the job query). |
|
278 |
@type secondary_ip: IP address |
|
279 |
@ivar secondary_ip: The secondary IP of the node. This needs to be passed |
|
280 |
if the cluster has been initialized in 'dual-network' |
|
281 |
mode, otherwise it must not be given. |
|
282 |
@type readd: C{bool} |
|
283 |
@ivar readd: Whether to re-add an existing node to the cluster. If |
|
284 |
this is not passed, then the operation will abort if the node |
|
285 |
name is already in the cluster; use this parameter to 'repair' |
|
286 |
a node that had its configuration broken, or was reinstalled |
|
287 |
without removal from the cluster. |
|
288 |
|
|
289 |
""" |
|
192 | 290 |
OP_ID = "OP_NODE_ADD" |
193 | 291 |
__slots__ = ["node_name", "primary_ip", "secondary_ip", "readd"] |
194 | 292 |
|
Also available in: Unified diff