Revision c08fd0d6 lib/rapi/baserlib.py

b/lib/rapi/baserlib.py
33 33
from ganeti import rapi
34 34
from ganeti import http
35 35
from ganeti import errors
36
from ganeti import compat
36 37

  
37 38

  
38 39
# Dummy value to detect unchanged parameters
39 40
_DEFAULT = object()
40 41

  
42
#: Supported HTTP methods
43
_SUPPORTED_METHODS = frozenset([
44
  http.HTTP_DELETE,
45
  http.HTTP_GET,
46
  http.HTTP_POST,
47
  http.HTTP_PUT,
48
  ])
49

  
41 50

  
42 51
def BuildUriList(ids, uri_format, uri_fields=("name", "uri")):
43 52
  """Builds a URI list as used by index resources.
......
391 400
    except luxi.TimeoutError, err:
392 401
      raise http.HttpGatewayTimeout("Timeout while talking to the master"
393 402
                                    " daemon: %s" % err)
403

  
404

  
405
class _MetaOpcodeResource(type):
406
  """Meta class for RAPI resources.
407

  
408
  """
409
  _ATTRS = [(method, "%s_OPCODE" % method, "%s_RENAME" % method,
410
             "Get%sOpInput" % method.capitalize())
411
            for method in _SUPPORTED_METHODS]
412

  
413
  def __call__(mcs, *args, **kwargs):
414
    """Instantiates class and patches it for use by the RAPI daemon.
415

  
416
    """
417
    # Access to private attributes of a client class, pylint: disable=W0212
418
    obj = type.__call__(mcs, *args, **kwargs)
419

  
420
    for (method, op_attr, rename_attr, fn_attr) in mcs._ATTRS:
421
      try:
422
        opcode = getattr(obj, op_attr)
423
      except AttributeError:
424
        # If the "*_OPCODE" attribute isn't set, "*_RENAME" or "Get*OpInput"
425
        # shouldn't either
426
        assert not hasattr(obj, rename_attr)
427
        assert not hasattr(obj, fn_attr)
428
        continue
429

  
430
      assert not hasattr(obj, method)
431

  
432
      # Generate handler method on handler instance
433
      setattr(obj, method,
434
              compat.partial(obj._GenericHandler, opcode,
435
                             getattr(obj, rename_attr, None),
436
                             getattr(obj, fn_attr, obj._GetDefaultData)))
437

  
438
    return obj
439

  
440

  
441
class OpcodeResource(ResourceBase):
442
  """Base class for opcode-based RAPI resources.
443

  
444
  Instances of this class automatically gain handler functions through
445
  L{_MetaOpcodeResource} for any method for which a C{$METHOD$_OPCODE} variable
446
  is defined at class level. Subclasses can define a C{Get$Method$OpInput}
447
  method to do their own opcode input processing (e.g. for static values). The
448
  C{$METHOD$_RENAME} variable defines which values are renamed (see
449
  L{FillOpcode}).
450

  
451
  @cvar GET_OPCODE: Set this to a class derived from L{opcodes.OpCode} to
452
    automatically generate a GET handler submitting the opcode
453
  @cvar GET_RENAME: Set this to rename parameters in the GET handler (see
454
    L{FillOpcode})
455
  @ivar GetGetOpInput: Define this to override the default method for
456
    getting opcode parameters (see L{baserlib.OpcodeResource._GetDefaultData})
457

  
458
  @cvar PUT_OPCODE: Set this to a class derived from L{opcodes.OpCode} to
459
    automatically generate a PUT handler submitting the opcode
460
  @cvar PUT_RENAME: Set this to rename parameters in the PUT handler (see
461
    L{FillOpcode})
462
  @ivar GetPutOpInput: Define this to override the default method for
463
    getting opcode parameters (see L{baserlib.OpcodeResource._GetDefaultData})
464

  
465
  @cvar POST_OPCODE: Set this to a class derived from L{opcodes.OpCode} to
466
    automatically generate a POST handler submitting the opcode
467
  @cvar POST_RENAME: Set this to rename parameters in the DELETE handler (see
468
    L{FillOpcode})
469
  @ivar GetPostOpInput: Define this to override the default method for
470
    getting opcode parameters (see L{baserlib.OpcodeResource._GetDefaultData})
471

  
472
  @cvar DELETE_OPCODE: Set this to a class derived from L{opcodes.OpCode} to
473
    automatically generate a GET handler submitting the opcode
474
  @cvar DELETE_RENAME: Set this to rename parameters in the DELETE handler (see
475
    L{FillOpcode})
476
  @ivar GetDeleteOpInput: Define this to override the default method for
477
    getting opcode parameters (see L{baserlib.OpcodeResource._GetDefaultData})
478

  
479
  """
480
  __metaclass__ = _MetaOpcodeResource
481

  
482
  def _GetDefaultData(self):
483
    return (self.request_body, None)
484

  
485
  def _GenericHandler(self, opcode, rename, fn):
486
    (body, static) = fn()
487
    op = FillOpcode(opcode, body, static, rename=rename)
488
    return self.SubmitJob([op])

Also available in: Unified diff