Revision 32683096 lib/opcodes.py
b/lib/opcodes.py | ||
---|---|---|
40 | 40 |
from ganeti import errors |
41 | 41 |
from ganeti import ht |
42 | 42 |
from ganeti import objects |
43 |
from ganeti import objectutils |
|
43 | 44 |
|
44 | 45 |
|
45 | 46 |
# Common opcode attributes |
... | ... | |
342 | 343 |
"Storage type") |
343 | 344 |
|
344 | 345 |
|
345 |
class _AutoOpParamSlots(type):
|
|
346 |
class _AutoOpParamSlots(objectutils.AutoSlots):
|
|
346 | 347 |
"""Meta class for opcode definitions. |
347 | 348 |
|
348 | 349 |
""" |
... | ... | |
356 | 357 |
@param attrs: Class attributes |
357 | 358 |
|
358 | 359 |
""" |
359 |
assert "__slots__" not in attrs, \ |
|
360 |
"Class '%s' defines __slots__ when it should use OP_PARAMS" % name |
|
361 | 360 |
assert "OP_ID" not in attrs, "Class '%s' defining OP_ID" % name |
362 | 361 |
|
362 |
slots = mcs._GetSlots(attrs) |
|
363 |
assert "OP_DSC_FIELD" not in attrs or attrs["OP_DSC_FIELD"] in slots, \ |
|
364 |
"Class '%s' uses unknown field in OP_DSC_FIELD" % name |
|
365 |
|
|
363 | 366 |
attrs["OP_ID"] = _NameToId(name) |
364 | 367 |
|
368 |
return objectutils.AutoSlots.__new__(mcs, name, bases, attrs) |
|
369 |
|
|
370 |
@classmethod |
|
371 |
def _GetSlots(mcs, attrs): |
|
372 |
"""Build the slots out of OP_PARAMS. |
|
373 |
|
|
374 |
""" |
|
365 | 375 |
# Always set OP_PARAMS to avoid duplicates in BaseOpCode.GetAllParams |
366 | 376 |
params = attrs.setdefault("OP_PARAMS", []) |
367 | 377 |
|
368 | 378 |
# Use parameter names as slots |
369 |
slots = [pname for (pname, _, _, _) in params] |
|
370 |
|
|
371 |
assert "OP_DSC_FIELD" not in attrs or attrs["OP_DSC_FIELD"] in slots, \ |
|
372 |
"Class '%s' uses unknown field in OP_DSC_FIELD" % name |
|
373 |
|
|
374 |
attrs["__slots__"] = slots |
|
375 |
|
|
376 |
return type.__new__(mcs, name, bases, attrs) |
|
379 |
return [pname for (pname, _, _, _) in params] |
|
377 | 380 |
|
378 | 381 |
|
379 |
class BaseOpCode(object): |
|
382 |
class BaseOpCode(objectutils.ValidatedSlots):
|
|
380 | 383 |
"""A simple serializable object. |
381 | 384 |
|
382 | 385 |
This object serves as a parent class for OpCode without any custom |
... | ... | |
387 | 390 |
# as OP_ID is dynamically defined |
388 | 391 |
__metaclass__ = _AutoOpParamSlots |
389 | 392 |
|
390 |
def __init__(self, **kwargs): |
|
391 |
"""Constructor for BaseOpCode. |
|
392 |
|
|
393 |
The constructor takes only keyword arguments and will set |
|
394 |
attributes on this object based on the passed arguments. As such, |
|
395 |
it means that you should not pass arguments which are not in the |
|
396 |
__slots__ attribute for this class. |
|
397 |
|
|
398 |
""" |
|
399 |
slots = self._all_slots() |
|
400 |
for key in kwargs: |
|
401 |
if key not in slots: |
|
402 |
raise TypeError("Object %s doesn't support the parameter '%s'" % |
|
403 |
(self.__class__.__name__, key)) |
|
404 |
setattr(self, key, kwargs[key]) |
|
405 |
|
|
406 | 393 |
def __getstate__(self): |
407 | 394 |
"""Generic serializer. |
408 | 395 |
|
... | ... | |
414 | 401 |
|
415 | 402 |
""" |
416 | 403 |
state = {} |
417 |
for name in self._all_slots():
|
|
404 |
for name in self.GetAllSlots():
|
|
418 | 405 |
if hasattr(self, name): |
419 | 406 |
state[name] = getattr(self, name) |
420 | 407 |
return state |
... | ... | |
433 | 420 |
raise ValueError("Invalid data to __setstate__: expected dict, got %s" % |
434 | 421 |
type(state)) |
435 | 422 |
|
436 |
for name in self._all_slots():
|
|
423 |
for name in self.GetAllSlots():
|
|
437 | 424 |
if name not in state and hasattr(self, name): |
438 | 425 |
delattr(self, name) |
439 | 426 |
|
... | ... | |
441 | 428 |
setattr(self, name, state[name]) |
442 | 429 |
|
443 | 430 |
@classmethod |
444 |
def _all_slots(cls): |
|
445 |
"""Compute the list of all declared slots for a class. |
|
446 |
|
|
447 |
""" |
|
448 |
slots = [] |
|
449 |
for parent in cls.__mro__: |
|
450 |
slots.extend(getattr(parent, "__slots__", [])) |
|
451 |
return slots |
|
452 |
|
|
453 |
@classmethod |
|
454 | 431 |
def GetAllParams(cls): |
455 | 432 |
"""Compute list of all parameters for an opcode. |
456 | 433 |
|
... | ... | |
460 | 437 |
slots.extend(getattr(parent, "OP_PARAMS", [])) |
461 | 438 |
return slots |
462 | 439 |
|
463 |
def Validate(self, set_defaults): |
|
440 |
def Validate(self, set_defaults): # pylint: disable=W0221
|
|
464 | 441 |
"""Validate opcode parameters, optionally setting default values. |
465 | 442 |
|
466 | 443 |
@type set_defaults: bool |
Also available in: Unified diff