ia64/xen-unstable

changeset 14939:31f6f85778e5

[XEND] Remove autoplug class signatures, have it all handled in the class now

signed-off-by: Tom Wilkie <tom.wilkie@gmail.com>
author Tom Wilkie <tom.wilkie@gmail.com>
date Wed Apr 25 16:16:21 2007 +0100 (2007-04-25)
parents 7317e701f3e7
children 0bbc44c0b6e3
files tools/python/xen/xend/XendAPI.py
line diff
     1.1 --- a/tools/python/xen/xend/XendAPI.py	Wed Apr 25 16:14:20 2007 +0100
     1.2 +++ b/tools/python/xen/xend/XendAPI.py	Wed Apr 25 16:16:21 2007 +0100
     1.3 @@ -27,7 +27,7 @@ import time
     1.4  import xmlrpclib
     1.5  
     1.6  import XendDomain, XendDomainInfo, XendNode, XendDmesg
     1.7 -import XendLogging, XendTaskManager
     1.8 +import XendLogging, XendTaskManager, XendAPIStore
     1.9  
    1.10  from XendAPIVersion import *
    1.11  from XendAuthSessions import instance as auth_manager
    1.12 @@ -38,8 +38,8 @@ from XendNetwork import XendNetwork
    1.13  from XendTask import XendTask
    1.14  from XendPIFMetrics import XendPIFMetrics
    1.15  from XendVMMetrics import XendVMMetrics
    1.16 -
    1.17 -import XendPBD
    1.18 +from XendPIF import XendPIF
    1.19 +from XendPBD import XendPBD
    1.20  
    1.21  from XendAPIConstants import *
    1.22  from xen.util.xmlrpclib2 import stringify
    1.23 @@ -237,6 +237,8 @@ def catch_typeerror(func):
    1.24                      finally:
    1.25                          del tb
    1.26              raise
    1.27 +        except XendAPIError, exn:
    1.28 +            return xen_api_error(exn.get_api_error())
    1.29  
    1.30      return f
    1.31  
    1.32 @@ -307,26 +309,6 @@ def valid_vm(func):
    1.33             _check_ref(XendDomain.instance().is_valid_vm,
    1.34                        'VM', func, *args, **kwargs)
    1.35  
    1.36 -def valid_vm_metrics(func):
    1.37 -    """Decorator to verify if vm_metrics_ref is valid before calling method.
    1.38 -
    1.39 -    @param func: function with params: (self, session, vm_metrics_ref, ...)
    1.40 -    @rtype: callable object
    1.41 -    """    
    1.42 -    return lambda *args, **kwargs: \
    1.43 -           _check_ref(XendVMMetrics.is_valid_vm_metrics,
    1.44 -                      'VM_metrics', func, *args, **kwargs)
    1.45 -
    1.46 -def valid_network(func):
    1.47 -    """Decorator to verify if network_ref is valid before calling method.
    1.48 -
    1.49 -    @param func: function with params: (self, session, network_ref, ...)
    1.50 -    @rtype: callable object
    1.51 -    """    
    1.52 -    return lambda *args, **kwargs: \
    1.53 -           _check_ref(XendNode.instance().is_valid_network,
    1.54 -                      'network', func, *args, **kwargs)
    1.55 -
    1.56  def valid_vbd(func):
    1.57      """Decorator to verify if vbd_ref is valid before calling method.
    1.58  
    1.59 @@ -409,39 +391,6 @@ def valid_sr(func):
    1.60             _check_ref(lambda r: XendNode.instance().is_valid_sr,
    1.61                        'SR', func, *args, **kwargs)
    1.62  
    1.63 -def valid_pbd(func):
    1.64 -    """Decorator to verify if pbd_ref is valid before calling
    1.65 -    method.
    1.66 -
    1.67 -    @param func: function with params: (self, session, pbd_ref)
    1.68 -    @rtype: callable object
    1.69 -    """
    1.70 -    return lambda *args, **kwargs: \
    1.71 -           _check_ref(lambda r: r in XendPBD.get_all_refs(),
    1.72 -                      'PBD', func, *args, **kwargs)
    1.73 -
    1.74 -def valid_pif(func):
    1.75 -    """Decorator to verify if pif_ref is valid before calling
    1.76 -    method.
    1.77 -
    1.78 -    @param func: function with params: (self, session, pif_ref)
    1.79 -    @rtype: callable object
    1.80 -    """
    1.81 -    return lambda *args, **kwargs: \
    1.82 -           _check_ref(lambda r: r in XendNode.instance().pifs,
    1.83 -                      'PIF', func, *args, **kwargs)
    1.84 -
    1.85 -def valid_pif_metrics(func):
    1.86 -    """Decorator to verify if pif_metrics_ref is valid before calling
    1.87 -    method.
    1.88 -
    1.89 -    @param func: function with params: (self, session, pif_metrics_ref)
    1.90 -    @rtype: callable object
    1.91 -    """
    1.92 -    return lambda *args, **kwargs: \
    1.93 -           _check_ref(lambda r: r in XendNode.instance().pif_metrics,
    1.94 -                      'PIF_metrics', func, *args, **kwargs)
    1.95 -
    1.96  def valid_task(func):
    1.97      """Decorator to verify if task_ref is valid before calling
    1.98      method.
    1.99 @@ -464,6 +413,20 @@ def valid_debug(func):
   1.100             _check_ref(lambda r: r in XendAPI._debug,
   1.101                        'debug', func, *args, **kwargs)
   1.102  
   1.103 +
   1.104 +def valid_object(class_name):
   1.105 +    """Decorator to verify if object is valid before calling
   1.106 +    method.
   1.107 +
   1.108 +    @param func: function with params: (self, session, pif_ref)
   1.109 +    @rtype: callable object
   1.110 +    """
   1.111 +    return lambda func: \
   1.112 +           lambda *args, **kwargs: \
   1.113 +           _check_ref(lambda r: \
   1.114 +                          XendAPIStore.get(r, class_name) is not None,
   1.115 +                      'PIF', func, *args, **kwargs)
   1.116 +
   1.117  # -----------------------------
   1.118  # Bridge to Legacy XM API calls
   1.119  # -----------------------------
   1.120 @@ -494,9 +457,7 @@ classes = {
   1.121      'host'         : valid_host,
   1.122      'host_cpu'     : valid_host_cpu,
   1.123      'host_metrics' : valid_host_metrics,
   1.124 -    'network'      : valid_network,
   1.125      'VM'           : valid_vm,
   1.126 -    'VM_metrics'   : valid_vm_metrics,
   1.127      'VBD'          : valid_vbd,
   1.128      'VBD_metrics'  : valid_vbd_metrics,
   1.129      'VIF'          : valid_vif,
   1.130 @@ -505,21 +466,23 @@ classes = {
   1.131      'VTPM'         : valid_vtpm,
   1.132      'console'      : valid_console,
   1.133      'SR'           : valid_sr,
   1.134 -    'PBD'          : valid_pbd,
   1.135 -    'PIF'          : valid_pif,
   1.136 -    'PIF_metrics'  : valid_pif_metrics,
   1.137      'task'         : valid_task,
   1.138      'debug'        : valid_debug,
   1.139 +    'network'      : valid_object("network"),
   1.140 +    'PIF'          : valid_object("PIF"),
   1.141 +    'VM_metrics'   : valid_object("VM_metrics"),
   1.142 +    'PBD'          : valid_object("PBD"),
   1.143 +    'PIF_metrics'  : valid_object("PIF_metrics")
   1.144  }
   1.145  
   1.146  autoplug_classes = {
   1.147      'network'     : XendNetwork,
   1.148 +    'PIF'         : XendPIF,
   1.149      'VM_metrics'  : XendVMMetrics,
   1.150 -    'PBD'         : XendPBD.XendPBD,
   1.151 +    'PBD'         : XendPBD,
   1.152      'PIF_metrics' : XendPIFMetrics,
   1.153  }
   1.154  
   1.155 -
   1.156  class XendAPI(object):
   1.157      """Implementation of the Xen-API in Xend. Expects to be
   1.158      used via XMLRPCServer.
   1.159 @@ -570,7 +533,9 @@ class XendAPI(object):
   1.160          #    all get_by_uuid() methods.
   1.161          
   1.162          for api_cls in classes.keys():
   1.163 -            if api_cls == 'session':
   1.164 +            # We'll let the autoplug classes implement these functions
   1.165 +            # themselves - its much cleaner to do it in the base class
   1.166 +            if api_cls == 'session' or api_cls in autoplug_classes.keys():
   1.167                  continue
   1.168              
   1.169              get_by_uuid = '%s_get_by_uuid' % api_cls
   1.170 @@ -599,34 +564,48 @@ class XendAPI(object):
   1.171          # --------------------
   1.172          # These have all of their methods grabbed out from the implementation
   1.173          # class, and wrapped up to be compatible with the Xen-API.
   1.174 +
   1.175 +        def getter(ref, type):
   1.176 +            return XendAPIStore.get(ref, type)
   1.177          
   1.178          for api_cls, impl_cls in autoplug_classes.items():
   1.179 -            def doit(n):
   1.180 -                getter = getattr(cls, '_%s_get' % api_cls)
   1.181 +            def doit(n):           
   1.182                  dot_n = '%s.%s' % (api_cls, n)
   1.183                  full_n = '%s_%s' % (api_cls, n)
   1.184                  if not hasattr(cls, full_n):
   1.185                      f = getattr(impl_cls, n)
   1.186                      argcounts[dot_n] = f.func_code.co_argcount + 1
   1.187 -                    setattr(cls, full_n,
   1.188 +                    g = lambda api_cls: \
   1.189 +                    setattr(cls, full_n, \
   1.190                              lambda s, session, ref, *args: \
   1.191                                 xen_api_success( \
   1.192 -                                   f(getter(s, session, ref), *args)))
   1.193 +                                   f(getter(ref, api_cls), *args)))
   1.194 +                    g(api_cls) # Force api_cls to be captured
   1.195 +                    
   1.196 +            def doit_func(n):           
   1.197 +                dot_n = '%s.%s' % (api_cls, n)
   1.198 +                full_n = '%s_%s' % (api_cls, n)
   1.199 +                if not hasattr(cls, full_n):
   1.200 +                    f = getattr(impl_cls, n)
   1.201 +                    argcounts[dot_n] = f.func_code.co_argcount
   1.202 +                    setattr(cls, full_n, \
   1.203 +                            lambda s, session, *args: \
   1.204 +                               xen_api_success( \
   1.205 +                                   f(*args)))
   1.206  
   1.207 -            ro_attrs = getattr(cls, '%s_attr_ro' % api_cls, [])
   1.208 -            rw_attrs = getattr(cls, '%s_attr_rw' % api_cls, [])
   1.209 -            methods  = getattr(cls, '%s_methods' % api_cls, [])
   1.210 -            funcs    = getattr(cls, '%s_funcs'   % api_cls, [])
   1.211 +            ro_attrs = impl_cls.getAttrRO()
   1.212 +            rw_attrs = impl_cls.getAttrRW()
   1.213 +            methods  = impl_cls.getMethods()
   1.214 +            funcs    = impl_cls.getFuncs()
   1.215              
   1.216              for attr_name in ro_attrs + rw_attrs:
   1.217                  doit('get_%s' % attr_name)
   1.218 -            for attr_name in rw_attrs + cls.Base_attr_rw:
   1.219 +            for attr_name in rw_attrs:
   1.220                  doit('set_%s' % attr_name)
   1.221 -            for method_name, return_type in methods + cls.Base_methods:
   1.222 -                doit('%s' % method_name)
   1.223 -            for func_name, return_type in funcs + cls.Base_funcs:
   1.224 -                doit('%s' % func_name)
   1.225 -
   1.226 +            for method in methods:
   1.227 +                doit('%s' % method)
   1.228 +            for func in funcs:
   1.229 +                doit_func('%s' % func)
   1.230  
   1.231          def wrap_method(name, new_f):
   1.232              try:
   1.233 @@ -692,31 +671,42 @@ class XendAPI(object):
   1.234                  except AttributeError:
   1.235                      log.warn("API call: %s not found" % n)
   1.236  
   1.237 -
   1.238 -            ro_attrs = getattr(cls, '%s_attr_ro' % api_cls, [])
   1.239 -            rw_attrs = getattr(cls, '%s_attr_rw' % api_cls, [])
   1.240 -            methods  = getattr(cls, '%s_methods' % api_cls, [])
   1.241 -            funcs    = getattr(cls, '%s_funcs'   % api_cls, [])
   1.242 +            if api_cls in autoplug_classes.keys():
   1.243 +                impl_cls = autoplug_classes[api_cls]
   1.244 +                ro_attrs = impl_cls.getAttrRO()
   1.245 +                rw_attrs = impl_cls.getAttrRW()
   1.246 +                methods  = map(lambda x: (x, ""), impl_cls.getMethods())
   1.247 +                funcs    = map(lambda x: (x, ""), impl_cls.getFuncs())
   1.248 +            else:
   1.249 +                ro_attrs = getattr(cls, '%s_attr_ro' % api_cls, []) \
   1.250 +                           + cls.Base_attr_ro
   1.251 +                rw_attrs = getattr(cls, '%s_attr_rw' % api_cls, []) \
   1.252 +                           + cls.Base_attr_rw
   1.253 +                methods  = getattr(cls, '%s_methods' % api_cls, []) \
   1.254 +                           + cls.Base_methods
   1.255 +                funcs    = getattr(cls, '%s_funcs'   % api_cls, []) \
   1.256 +                           + cls.Base_funcs
   1.257  
   1.258              # wrap validators around readable class attributes
   1.259 -            for attr_name in ro_attrs + rw_attrs + cls.Base_attr_ro:
   1.260 +            for attr_name in ro_attrs + rw_attrs:
   1.261                  doit('%s.get_%s' % (api_cls, attr_name), True,
   1.262                       async_support = False)
   1.263  
   1.264              # wrap validators around writable class attrributes
   1.265 -            for attr_name in rw_attrs + cls.Base_attr_rw:
   1.266 +            for attr_name in rw_attrs:
   1.267                  doit('%s.set_%s' % (api_cls, attr_name), True,
   1.268                       async_support = False)
   1.269                  setter_event_wrapper(api_cls, attr_name)
   1.270  
   1.271              # wrap validators around methods
   1.272 -            for method_name, return_type in methods + cls.Base_methods:
   1.273 +            for method_name, return_type in methods:
   1.274                  doit('%s.%s' % (api_cls, method_name), True,
   1.275                       async_support = True)
   1.276  
   1.277              # wrap validators around class functions
   1.278 -            for func_name, return_type in funcs + cls.Base_funcs:
   1.279 -                doit('%s.%s' % (api_cls, func_name), False, async_support = True,
   1.280 +            for func_name, return_type in funcs:
   1.281 +                doit('%s.%s' % (api_cls, func_name), False,
   1.282 +                     async_support = True,
   1.283                       return_type = return_type)
   1.284  
   1.285              ctor_event_wrapper(api_cls)
   1.286 @@ -952,7 +942,7 @@ class XendAPI(object):
   1.287      def host_get_resident_VMs(self, session, host_ref):
   1.288          return xen_api_success(XendDomain.instance().get_domain_refs())
   1.289      def host_get_PBDs(self, _, ref):
   1.290 -        return xen_api_success(XendPBD.get_all_refs())
   1.291 +        return xen_api_success(XendPBD.get_all())
   1.292      def host_get_PIFs(self, session, ref):
   1.293          return xen_api_success(XendNode.instance().get_PIF_refs())
   1.294      def host_get_host_CPUs(self, session, host_ref):
   1.295 @@ -1131,130 +1121,6 @@ class XendAPI(object):
   1.296          node = XendNode.instance()
   1.297          return node.xc.physinfo()['free_memory'] * 1024
   1.298  
   1.299 -
   1.300 -    # Xen API: Class network
   1.301 -    # ----------------------------------------------------------------
   1.302 -
   1.303 -    network_attr_ro = ['VIFs', 'PIFs']
   1.304 -    network_attr_rw = ['name_label',
   1.305 -                       'name_description',
   1.306 -                       'other_config']
   1.307 -    network_methods = [('add_to_other_config', None),
   1.308 -                       ('remove_from_other_config', None),
   1.309 -                       ('destroy', None)]
   1.310 -    network_funcs = [('create', None)]
   1.311 -    
   1.312 -    def _network_get(self, _, ref):
   1.313 -        return XendNode.instance().get_network(ref)
   1.314 -
   1.315 -    def network_get_all(self, _):
   1.316 -        return xen_api_success(XendNode.instance().get_network_refs())
   1.317 -
   1.318 -    def network_create(self, _, record):
   1.319 -        return xen_api_success(XendNode.instance().network_create(record))
   1.320 -
   1.321 -    def network_destroy(self, _, ref):
   1.322 -        return xen_api_success(XendNode.instance().network_destroy(ref))
   1.323 -
   1.324 -
   1.325 -    # Xen API: Class PIF
   1.326 -    # ----------------------------------------------------------------
   1.327 -
   1.328 -    PIF_attr_ro = ['network',
   1.329 -                   'host',
   1.330 -                   'metrics']
   1.331 -    PIF_attr_rw = ['device',
   1.332 -                   'MAC',
   1.333 -                   'MTU',
   1.334 -                   'VLAN']
   1.335 -
   1.336 -    PIF_attr_inst = PIF_attr_rw
   1.337 -
   1.338 -    PIF_methods = [('create_VLAN', 'int'), ('destroy', None)]
   1.339 -
   1.340 -    def _get_PIF(self, ref):
   1.341 -        return XendNode.instance().pifs[ref]
   1.342 -
   1.343 -    def PIF_destroy(self, _, ref):
   1.344 -        try:
   1.345 -            return xen_api_success(XendNode.instance().PIF_destroy(ref))
   1.346 -        except PIFIsPhysical, exn:
   1.347 -            return xen_api_error(['PIF_IS_PHYSICAL', ref])
   1.348 -
   1.349 -    # object methods
   1.350 -    def PIF_get_record(self, _, ref):
   1.351 -        return xen_api_success(self._get_PIF(ref).get_record())
   1.352 -
   1.353 -    def PIF_get_all(self, _):
   1.354 -        return xen_api_success(XendNode.instance().pifs.keys())
   1.355 -
   1.356 -    def PIF_get_metrics(self, _, ref):
   1.357 -        return xen_api_success(self._get_PIF(ref).metrics.uuid)
   1.358 -
   1.359 -    def PIF_get_device(self, _, ref):
   1.360 -        return xen_api_success(self._get_PIF(ref).device)
   1.361 -
   1.362 -    def PIF_get_network(self, _, ref):
   1.363 -        return xen_api_success(self._get_PIF(ref).network.uuid)
   1.364 -
   1.365 -    def PIF_get_host(self, _, ref):
   1.366 -        return xen_api_success(self._get_PIF(ref).host.uuid)
   1.367 -
   1.368 -    def PIF_get_MAC(self, _, ref):
   1.369 -        return xen_api_success(self._get_PIF(ref).mac)
   1.370 -
   1.371 -    def PIF_get_MTU(self, _, ref):
   1.372 -        return xen_api_success(self._get_PIF(ref).mtu)
   1.373 -
   1.374 -    def PIF_get_VLAN(self, _, ref):
   1.375 -        return xen_api_success(self._get_PIF(ref).vlan)
   1.376 -
   1.377 -    def PIF_set_device(self, _, ref, device):
   1.378 -        return xen_api_success(self._get_PIF(ref).set_device(device))
   1.379 -
   1.380 -    def PIF_set_MAC(self, _, ref, mac):
   1.381 -        return xen_api_success(self._get_PIF(ref).set_mac(mac))
   1.382 -
   1.383 -    def PIF_set_MTU(self, _, ref, mtu):
   1.384 -        return xen_api_success(self._get_PIF(ref).set_mtu(mtu))
   1.385 -
   1.386 -    def PIF_create_VLAN(self, _, ref, network, vlan):
   1.387 -        try:
   1.388 -            vlan = int(vlan)
   1.389 -        except:
   1.390 -            return xen_api_error(['VLAN_TAG_INVALID', vlan])
   1.391 -
   1.392 -        try:
   1.393 -            node = XendNode.instance()
   1.394 -            
   1.395 -            if _is_valid_ref(network, node.is_valid_network):
   1.396 -                return xen_api_success(
   1.397 -                    node.PIF_create_VLAN(ref, network, vlan))
   1.398 -            else:
   1.399 -                return xen_api_error(['HANDLE_INVALID', 'network', network])
   1.400 -        except NetworkAlreadyConnected, exn:
   1.401 -            return xen_api_error(['NETWORK_ALREADY_CONNECTED',
   1.402 -                                  network, exn.pif_uuid])
   1.403 -        except VLANTagInvalid:
   1.404 -            return xen_api_error(['VLAN_TAG_INVALID', vlan])
   1.405 -
   1.406 -
   1.407 -    # Xen API: Class PIF_metrics
   1.408 -    # ----------------------------------------------------------------
   1.409 -
   1.410 -    PIF_metrics_attr_ro = ['io_read_kbs',
   1.411 -                           'io_write_kbs',
   1.412 -                           'last_updated']
   1.413 -    PIF_metrics_attr_rw = []
   1.414 -    PIF_metrics_methods = []
   1.415 -
   1.416 -    def PIF_metrics_get_all(self, _):
   1.417 -        return xen_api_success(XendNode.instance().pif_metrics.keys())
   1.418 -
   1.419 -    def _PIF_metrics_get(self, _, ref):
   1.420 -        return XendNode.instance().pif_metrics[ref]
   1.421 -
   1.422 -
   1.423      # Xen API: Class VM
   1.424      # ----------------------------------------------------------------        
   1.425  
   1.426 @@ -1865,28 +1731,6 @@ class XendAPI(object):
   1.427          return xen_api_success_void()
   1.428  
   1.429  
   1.430 -    # Xen API: Class VM_metrics
   1.431 -    # ----------------------------------------------------------------
   1.432 -
   1.433 -    VM_metrics_attr_ro = ['memory_actual',
   1.434 -                          'VCPUs_number',
   1.435 -                          'VCPUs_utilisation',
   1.436 -                          'VCPUs_CPU',
   1.437 -                          'VCPUs_flags',
   1.438 -                          'VCPUs_params',
   1.439 -                          'state',
   1.440 -                          'start_time',
   1.441 -                          'last_updated']
   1.442 -    VM_metrics_attr_rw = []
   1.443 -    VM_metrics_methods = []
   1.444 -
   1.445 -    def _VM_metrics_get(self, _, ref):
   1.446 -        return XendVMMetrics.get_by_uuid(ref)
   1.447 -
   1.448 -    def VM_metrics_get_all(self, _):
   1.449 -        return xen_api_success(XendVMMetrics.get_all())
   1.450 -
   1.451 -
   1.452      # Xen API: Class VBD
   1.453      # ----------------------------------------------------------------
   1.454  
   1.455 @@ -2570,33 +2414,6 @@ class XendAPI(object):
   1.456          return xen_api_success_void()
   1.457  
   1.458  
   1.459 -    # Xen API: Class PBD
   1.460 -    # ----------------------------------------------------------------
   1.461 -
   1.462 -    PBD_attr_ro = ['host',
   1.463 -                   'SR',
   1.464 -                   'device_config',
   1.465 -                   'currently_attached']
   1.466 -    PBD_attr_rw = []
   1.467 -    PBD_methods = [('destroy', None)]
   1.468 -    PBD_funcs   = [('create', None)]
   1.469 -
   1.470 -    def PBD_get_all(self, _):
   1.471 -        return xen_api_success(XendPBD.get_all_refs())
   1.472 -
   1.473 -    def _PBD_get(self, _, ref):
   1.474 -        return XendPBD.get(ref)
   1.475 -
   1.476 -    def PBD_create(self, _, record):
   1.477 -        if 'uuid' in record:
   1.478 -            return xen_api_error(['VALUE_NOT_SUPPORTED',
   1.479 -                                  'uuid', record['uuid'],
   1.480 -                                  'You may not specify a UUID on creation'])
   1.481 -        new_uuid = XendPBD.XendPBD(record).get_uuid()
   1.482 -        XendNode.instance().save()
   1.483 -        return xen_api_success(new_uuid)
   1.484 -
   1.485 -
   1.486      # Xen API: Class event
   1.487      # ----------------------------------------------------------------
   1.488