ia64/xen-unstable

changeset 13606:da23e1b616b0

[XEND] Move decorate() to XendAPI.__new__ and have a static flag to
ensure it only runs at instantiation time, and only once per Xend
instance. Otherwise, decorate() runs on every invocation of
/usr/sbin/xend, even if it is xend stop.

Signed-off-by: Alastair Tse <atse@xensource.com>
author Alastair Tse <atse@xensource.com>
date Wed Jan 24 15:57:10 2007 +0000 (2007-01-24)
parents f9eceb9c52d7
children a94363b85e19
files tools/python/xen/xend/XendAPI.py
line diff
     1.1 --- a/tools/python/xen/xend/XendAPI.py	Wed Jan 24 15:52:26 2007 +0000
     1.2 +++ b/tools/python/xen/xend/XendAPI.py	Wed Jan 24 15:57:10 2007 +0000
     1.3 @@ -20,6 +20,7 @@ import os
     1.4  import string
     1.5  import sys
     1.6  import traceback
     1.7 +import threading
     1.8  
     1.9  from xen.xend import XendDomain, XendDomainInfo, XendNode
    1.10  from xen.xend import XendLogging, XendTaskManager
    1.11 @@ -283,7 +284,7 @@ def do_vm_func(fn_name, vm_ref, *args, *
    1.12                                exn.actual])
    1.13  
    1.14  
    1.15 -class XendAPI:
    1.16 +class XendAPI(object):
    1.17      """Implementation of the Xen-API in Xend. Expects to be
    1.18      used via XMLRPCServer.
    1.19  
    1.20 @@ -297,6 +298,119 @@ class XendAPI:
    1.21      is set to the XMLRPC function name which the method implements.
    1.22      """
    1.23  
    1.24 +    __decorated__ = False
    1.25 +    __init_lock__ = threading.Lock()
    1.26 +    
    1.27 +    def __new__(cls, *args, **kwds):
    1.28 +        """ Override __new__ to decorate the class only once.
    1.29 +
    1.30 +        Lock to make sure the classes are not decorated twice.
    1.31 +        """
    1.32 +        cls.__init_lock__.acquire()
    1.33 +        try:
    1.34 +            if not cls.__decorated__:
    1.35 +                cls._decorate()
    1.36 +                cls.__decorated__ = True
    1.37 +                
    1.38 +            return object.__new__(cls, *args, **kwds)
    1.39 +        finally:
    1.40 +            cls.__init_lock__.release()
    1.41 +            
    1.42 +    def _decorate(cls):
    1.43 +        """ Decorate all the object methods to have validators
    1.44 +        and appropriate function attributes.
    1.45 +
    1.46 +        This should only be executed once for the duration of the
    1.47 +        server.
    1.48 +        """
    1.49 +        global_validators = [session_required, catch_typeerror]
    1.50 +        classes = {
    1.51 +            'session' : None,
    1.52 +            'host'    : valid_host,
    1.53 +            'host_cpu': valid_host_cpu,
    1.54 +            'network' : valid_network,
    1.55 +            'VM'      : valid_vm,
    1.56 +            'VBD'     : valid_vbd,
    1.57 +            'VIF'     : valid_vif,
    1.58 +            'VDI'     : valid_vdi,
    1.59 +            'VTPM'    : valid_vtpm,
    1.60 +            'SR'      : valid_sr,
    1.61 +            'PIF'     : valid_pif,
    1.62 +            'task'    : valid_task,
    1.63 +        }
    1.64 +
    1.65 +        # Cheat methods
    1.66 +        # -------------
    1.67 +        # Methods that have a trivial implementation for all classes.
    1.68 +        # 1. get_by_uuid == getting by ref, so just return uuid for
    1.69 +        #    all get_by_uuid() methods.
    1.70 +        
    1.71 +        for api_cls in classes.keys():
    1.72 +            get_by_uuid = '%s_get_by_uuid' % api_cls
    1.73 +            get_uuid = '%s_get_uuid' % api_cls
    1.74 +            def _get_by_uuid(_1, _2, ref):
    1.75 +                return xen_api_success(ref)
    1.76 +
    1.77 +            def _get_uuid(_1, _2, ref):
    1.78 +                return xen_api_success(ref)
    1.79 +
    1.80 +            setattr(cls, get_by_uuid, _get_by_uuid)
    1.81 +            setattr(cls, get_uuid,    _get_uuid)
    1.82 +
    1.83 +        # Wrapping validators around XMLRPC calls
    1.84 +        # ---------------------------------------
    1.85 +
    1.86 +        for api_cls, validator in classes.items():
    1.87 +            def doit(n, takes_instance, async_support = False,
    1.88 +                     return_type = None):
    1.89 +                n_ = n.replace('.', '_')
    1.90 +                try:
    1.91 +                    f = getattr(cls, n_)
    1.92 +                    argcounts[n] = f.func_code.co_argcount - 1
    1.93 +                    
    1.94 +                    validators = takes_instance and validator and \
    1.95 +                                 [validator] or []
    1.96 +
    1.97 +                    validators += global_validators
    1.98 +                    for v in validators:
    1.99 +                        f = v(f)
   1.100 +                        f.api = n
   1.101 +                        f.async = async_support
   1.102 +                        if return_type:
   1.103 +                            f.return_type = return_type
   1.104 +                    
   1.105 +                    setattr(cls, n_, f)
   1.106 +                except AttributeError:
   1.107 +                    log.warn("API call: %s not found" % n)
   1.108 +
   1.109 +
   1.110 +            ro_attrs = getattr(cls, '%s_attr_ro' % api_cls, [])
   1.111 +            rw_attrs = getattr(cls, '%s_attr_rw' % api_cls, [])
   1.112 +            methods  = getattr(cls, '%s_methods' % api_cls, [])
   1.113 +            funcs    = getattr(cls, '%s_funcs'   % api_cls, [])
   1.114 +
   1.115 +            # wrap validators around readable class attributes
   1.116 +            for attr_name in ro_attrs + rw_attrs + cls.Base_attr_ro:
   1.117 +                doit('%s.get_%s' % (api_cls, attr_name), True,
   1.118 +                     async_support = False)
   1.119 +
   1.120 +            # wrap validators around writable class attrributes
   1.121 +            for attr_name in rw_attrs + cls.Base_attr_rw:
   1.122 +                doit('%s.set_%s' % (api_cls, attr_name), True,
   1.123 +                     async_support = False)
   1.124 +
   1.125 +            # wrap validators around methods
   1.126 +            for method_name, return_type in methods + cls.Base_methods:
   1.127 +                doit('%s.%s' % (api_cls, method_name), True,
   1.128 +                     async_support = True)
   1.129 +
   1.130 +            # wrap validators around class functions
   1.131 +            for func_name, return_type in funcs + cls.Base_funcs:
   1.132 +                doit('%s.%s' % (api_cls, func_name), False, async_support = True,
   1.133 +                     return_type = return_type)
   1.134 +
   1.135 +    _decorate = classmethod(_decorate)
   1.136 +
   1.137      def __init__(self, auth):
   1.138          self.auth = auth
   1.139  
   1.140 @@ -1813,97 +1927,6 @@ class XendAPIAsyncProxy:
   1.141                                                  synchronous_method_name)
   1.142          return xen_api_success(task_uuid)
   1.143  
   1.144 -def _decorate():
   1.145 -    """Initialise Xen API wrapper by making sure all functions
   1.146 -    have the correct validation decorators such as L{valid_host}
   1.147 -    and L{session_required}.
   1.148 -    """
   1.149 -
   1.150 -    global_validators = [session_required, catch_typeerror]
   1.151 -    classes = {
   1.152 -        'session' : None,
   1.153 -        'host'    : valid_host,
   1.154 -        'host_cpu': valid_host_cpu,
   1.155 -        'network' : valid_network,
   1.156 -        'VM'      : valid_vm,
   1.157 -        'VBD'     : valid_vbd,
   1.158 -        'VIF'     : valid_vif,
   1.159 -        'VDI'     : valid_vdi,
   1.160 -        'VTPM'    : valid_vtpm,
   1.161 -        'SR'      : valid_sr,
   1.162 -        'PIF'     : valid_pif,
   1.163 -        'task'    : valid_task,
   1.164 -        }
   1.165 -
   1.166 -    # Cheat methods
   1.167 -    # -------------
   1.168 -    # Methods that have a trivial implementation for all classes.
   1.169 -    # 1. get_by_uuid == getting by ref, so just return uuid for
   1.170 -    #    all get_by_uuid() methods.
   1.171 -
   1.172 -    for cls in classes.keys():
   1.173 -        get_by_uuid = '%s_get_by_uuid' % cls
   1.174 -        get_uuid = '%s_get_uuid' % cls
   1.175 -        def _get_by_uuid(_1, _2, ref):
   1.176 -            return xen_api_success(ref)
   1.177 -
   1.178 -        def _get_uuid(_1, _2, ref):
   1.179 -            return xen_api_success(ref)
   1.180 -
   1.181 -        setattr(XendAPI, get_by_uuid, _get_by_uuid)
   1.182 -        setattr(XendAPI, get_uuid,    _get_uuid)
   1.183 -
   1.184 -    # Wrapping validators around XMLRPC calls
   1.185 -    # ---------------------------------------
   1.186 -
   1.187 -    for cls, validator in classes.items():
   1.188 -        def doit(n, takes_instance, async_support = False, return_type = None):
   1.189 -            n_ = n.replace('.', '_')
   1.190 -            try:
   1.191 -                f = getattr(XendAPI, n_)
   1.192 -                argcounts[n] = f.func_code.co_argcount - 1
   1.193 -
   1.194 -                validators = takes_instance and validator and [validator] \
   1.195 -                             or []
   1.196 -                validators += global_validators
   1.197 -                for v in validators:
   1.198 -                    f = v(f)
   1.199 -                    f.api = n
   1.200 -                    f.async = async_support
   1.201 -                    if return_type:
   1.202 -                        f.return_type = return_type
   1.203 -                    
   1.204 -                setattr(XendAPI, n_, f)
   1.205 -            except AttributeError:
   1.206 -                log.warn("API call: %s not found" % n)
   1.207 -
   1.208 -
   1.209 -        ro_attrs = getattr(XendAPI, '%s_attr_ro' % cls, [])
   1.210 -        rw_attrs = getattr(XendAPI, '%s_attr_rw' % cls, [])
   1.211 -        methods  = getattr(XendAPI, '%s_methods' % cls, [])
   1.212 -        funcs    = getattr(XendAPI, '%s_funcs'   % cls, [])
   1.213 -
   1.214 -        # wrap validators around readable class attributes
   1.215 -        for attr_name in ro_attrs + rw_attrs + XendAPI.Base_attr_ro:
   1.216 -            doit('%s.get_%s' % (cls, attr_name), True, async_support = False)
   1.217 -
   1.218 -        # wrap validators around writable class attrributes
   1.219 -        for attr_name in rw_attrs + XendAPI.Base_attr_rw:
   1.220 -            doit('%s.set_%s' % (cls, attr_name), True, async_support = False)
   1.221 -
   1.222 -        # wrap validators around methods
   1.223 -        for method_name, return_type in methods + XendAPI.Base_methods:
   1.224 -            doit('%s.%s' % (cls, method_name), True, async_support = True)
   1.225 -
   1.226 -        # wrap validators around class functions
   1.227 -        for func_name, return_type in funcs + XendAPI.Base_funcs:
   1.228 -            doit('%s.%s' % (cls, func_name), False, async_support = True,
   1.229 -                 return_type = return_type)
   1.230 -
   1.231 -
   1.232 -_decorate()
   1.233 -
   1.234 -
   1.235  #   
   1.236  # Auto generate some stubs based on XendAPI introspection
   1.237  #