[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] Change the way that MESSAGE_PARAMETER_COUNT_MISMATCH is diagnosed (using a



# HG changeset patch
# User Ewan Mellor <ewan@xxxxxxxxxxxxx>
# Date 1167063623 0
# Node ID bd10d08598b07192e642e8ef8fe9fa76c5117689
# Parent  765ada5f74cc21fffe442b09d675dc0fe5ce4dcf
Change the way that MESSAGE_PARAMETER_COUNT_MISMATCH is diagnosed (using a
separate dictionary to record parameter counts, rather than trying to parse them
out of the exception) and tidy up the validator preprocessing and the
validators themselves.

Signed-off-by: Ewan Mellor <ewan@xxxxxxxxxxxxx>
---
 tools/python/xen/xend/XendAPI.py |  261 ++++++++++++++-------------------------
 1 files changed, 99 insertions(+), 162 deletions(-)

diff -r 765ada5f74cc -r bd10d08598b0 tools/python/xen/xend/XendAPI.py
--- a/tools/python/xen/xend/XendAPI.py  Mon Dec 25 15:04:28 2006 +0000
+++ b/tools/python/xen/xend/XendAPI.py  Mon Dec 25 16:20:23 2006 +0000
@@ -17,7 +17,6 @@
 
 import inspect
 import os
-import re
 import string
 import sys
 import traceback
@@ -35,6 +34,8 @@ from xen.util.xmlrpclib2 import stringif
 
 AUTH_NONE = 'none'
 AUTH_PAM = 'pam'
+
+argcounts = {}
 
 # ------------------------------------------
 # Utility Methods for Xen API Implementation
@@ -84,12 +85,6 @@ def trace(func, api_name = ''):
     return trace_func
 
 
-takesRE = re.compile(r' ([0-9]*) argument')
-def deconstruct_typeerror(exn):
-    m = takesRE.search(exn[0])
-    return m and m.group(1) or None
-
-
 def catch_typeerror(func):
     """Decorator to catch any TypeErrors and translate them into Xen-API
     errors.
@@ -101,23 +96,21 @@ def catch_typeerror(func):
         try:
             return func(self, *args, **kwargs)
         except TypeError, exn:
-            if hasattr(func, 'api'):
-                takes = deconstruct_typeerror(exn)
-                if takes is not None:
-                    # Assume that if the exception was thrown inside this
-                    # file, then it is due to an invalid call from the client,
-                    # but if it was thrown elsewhere, then it's an internal
-                    # error (which will be handled further up).
-                    tb = sys.exc_info()[2]
-                    try:
-                        sourcefile = traceback.extract_tb(tb)[-1][0]
-                        if sourcefile == inspect.getsourcefile(XendAPI):
-                            return xen_api_error(
-                                ['MESSAGE_PARAMETER_COUNT_MISMATCH',
-                                 func.api, int(takes) - 2,
-                                 len(args) + len(kwargs) - 1])
-                    finally:
-                        del tb
+            if hasattr(func, 'api') and func.api in argcounts:
+                # Assume that if the exception was thrown inside this
+                # file, then it is due to an invalid call from the client,
+                # but if it was thrown elsewhere, then it's an internal
+                # error (which will be handled further up).
+                tb = sys.exc_info()[2]
+                try:
+                    sourcefile = traceback.extract_tb(tb)[-1][0]
+                    if sourcefile == inspect.getsourcefile(XendAPI):
+                        return xen_api_error(
+                            ['MESSAGE_PARAMETER_COUNT_MISMATCH',
+                             func.api, argcounts[func.api],
+                             len(args) + len(kwargs)])
+                finally:
+                    del tb
             raise
 
     return f
@@ -138,20 +131,25 @@ def session_required(func):
     return check_session
 
 
+def _is_valid_ref(ref, validator):
+    return type(ref) == str and validator(ref)
+
+def _check_ref(validator, errcode, func, api, session, ref, *args, **kwargs):
+    if _is_valid_ref(ref, validator):
+        return func(api, session, ref, *args, **kwargs)
+    else:
+        return xen_api_error([errcode, ref])
+
+
 def valid_host(func):
     """Decorator to verify if host_ref is valid before calling method.
 
     @param func: function with params: (self, session, host_ref, ...)
     @rtype: callable object
     """
-    def check_host_ref(self, session, host_ref, *args, **kwargs):
-        xennode = XendNode.instance()
-        if type(host_ref) == type(str()) and xennode.is_valid_host(host_ref):
-            return func(self, session, host_ref, *args, **kwargs)
-        else:
-            return xen_api_error(['HOST_HANDLE_INVALID', host_ref])
-
-    return check_host_ref
+    return lambda *args, **kwargs: \
+           _check_ref(XendNode.instance().is_valid_host,
+                      'HOST_HANDLE_INVALID', func, *args, **kwargs)
 
 def valid_host_cpu(func):
     """Decorator to verify if host_cpu_ref is valid before calling method.
@@ -159,15 +157,9 @@ def valid_host_cpu(func):
     @param func: function with params: (self, session, host_cpu_ref, ...)
     @rtype: callable object
     """    
-    def check_host_cpu_ref(self, session, host_cpu_ref, *args, **kwargs):
-        xennode = XendNode.instance()
-        if type(host_cpu_ref) == type(str()) and \
-               xennode.is_valid_cpu(host_cpu_ref):
-            return func(self, session, host_cpu_ref, *args, **kwargs)
-        else:
-            return xen_api_error(['HOST_CPU_HANDLE_INVALID', host_cpu_ref])
-        
-    return check_host_cpu_ref
+    return lambda *args, **kwargs: \
+           _check_ref(XendNode.instance().is_valid_cpu,
+                      'HOST_CPU_HANDLE_INVALID', func, *args, **kwargs)
 
 def valid_vm(func):
     """Decorator to verify if vm_ref is valid before calling method.
@@ -175,15 +167,19 @@ def valid_vm(func):
     @param func: function with params: (self, session, vm_ref, ...)
     @rtype: callable object
     """    
-    def check_vm_ref(self, session, vm_ref, *args, **kwargs):
-        xendom = XendDomain.instance()
-        if type(vm_ref) == type(str()) and \
-               xendom.is_valid_vm(vm_ref):
-            return func(self, session, vm_ref, *args, **kwargs)
-        else:
-            return xen_api_error(['VM_HANDLE_INVALID', vm_ref])
-
-    return check_vm_ref
+    return lambda *args, **kwargs: \
+           _check_ref(XendDomain.instance().is_valid_vm,
+                      'VM_HANDLE_INVALID', func, *args, **kwargs)
+
+def valid_network(func):
+    """Decorator to verify if network_ref is valid before calling method.
+
+    @param func: function with params: (self, session, network_ref, ...)
+    @rtype: callable object
+    """    
+    return lambda *args, **kwargs: \
+           _check_ref(XendNode.instance().is_valid_network,
+                      'NETWORK_HANDLE_INVALID', func, *args, **kwargs)
 
 def valid_vbd(func):
     """Decorator to verify if vbd_ref is valid before calling method.
@@ -191,15 +187,9 @@ def valid_vbd(func):
     @param func: function with params: (self, session, vbd_ref, ...)
     @rtype: callable object
     """    
-    def check_vbd_ref(self, session, vbd_ref, *args, **kwargs):
-        xendom = XendDomain.instance()
-        if type(vbd_ref) == type(str()) and \
-               xendom.is_valid_dev('vbd', vbd_ref):
-            return func(self, session, vbd_ref, *args, **kwargs)
-        else:
-            return xen_api_error(['VBD_HANDLE_INVALID', vbd_ref])
-
-    return check_vbd_ref
+    return lambda *args, **kwargs: \
+           _check_ref(lambda r: XendDomain.instance().is_valid_dev('vbd', r),
+                      'VBD_HANDLE_INVALID', func, *args, **kwargs)
 
 def valid_vif(func):
     """Decorator to verify if vif_ref is valid before calling method.
@@ -207,16 +197,9 @@ def valid_vif(func):
     @param func: function with params: (self, session, vif_ref, ...)
     @rtype: callable object
     """
-    def check_vif_ref(self, session, vif_ref, *args, **kwargs):
-        xendom = XendDomain.instance()
-        if type(vif_ref) == type(str()) and \
-               xendom.is_valid_dev('vif', vif_ref):
-            return func(self, session, vif_ref, *args, **kwargs)
-        else:
-            return xen_api_error(['VIF_HANDLE_INVALID', vif_ref])
-
-    return check_vif_ref
-
+    return lambda *args, **kwargs: \
+           _check_ref(lambda r: XendDomain.instance().is_valid_dev('vif', r),
+                      'VIF_HANDLE_INVALID', func, *args, **kwargs)
 
 def valid_vdi(func):
     """Decorator to verify if vdi_ref is valid before calling method.
@@ -224,15 +207,9 @@ def valid_vdi(func):
     @param func: function with params: (self, session, vdi_ref, ...)
     @rtype: callable object
     """
-    def check_vdi_ref(self, session, vdi_ref, *args, **kwargs):
-        xennode = XendNode.instance()
-        if type(vdi_ref) == type(str()) and \
-               xennode.get_sr().is_valid_vdi(vdi_ref):
-            return func(self, session, vdi_ref, *args, **kwargs)
-        else:
-            return xen_api_error(['VDI_HANDLE_INVALID', vdi_ref])
-
-    return check_vdi_ref
+    return lambda *args, **kwargs: \
+           _check_ref(XendNode.instance().get_sr().is_valid_vdi,
+                      'VDI_HANDLE_INVALID', func, *args, **kwargs)
 
 def valid_vtpm(func):
     """Decorator to verify if vtpm_ref is valid before calling method.
@@ -240,15 +217,9 @@ def valid_vtpm(func):
     @param func: function with params: (self, session, vtpm_ref, ...)
     @rtype: callable object
     """
-    def check_vtpm_ref(self, session, vtpm_ref, *args, **kwargs):
-        xendom = XendDomain.instance()
-        if type(vtpm_ref) == type(str()) and \
-               xendom.is_valid_dev('vtpm', vtpm_ref):
-            return func(self, session, vtpm_ref, *args, **kwargs)
-        else:
-            return xen_api_error(['VTPM_HANDLE_INVALID', vtpm_ref])
-
-    return check_vtpm_ref
+    return lambda *args, **kwargs: \
+           _check_ref(lambda r: XendDomain.instance().is_valid_dev('vtpm', r),
+                      'VTPM_HANDLE_INVALID', func, *args, **kwargs)
 
 def valid_sr(func):
     """Decorator to verify if sr_ref is valid before calling method.
@@ -256,16 +227,9 @@ def valid_sr(func):
     @param func: function with params: (self, session, sr_ref, ...)
     @rtype: callable object
     """
-    def check_sr_ref(self, session, sr_ref, *args, **kwargs):
-        xennode = XendNode.instance()
-        if type(sr_ref) == type(str()) and \
-               xennode.get_sr().uuid == sr_ref:
-            return func(self, session, sr_ref, *args, **kwargs)
-        else:
-            return xen_api_error(['SR_HANDLE_INVALID', sr_ref])
-
-    return check_sr_ref
-
+    return lambda *args, **kwargs: \
+           _check_ref(lambda r: XendNode.instance().get_sr().uuid == r,
+                      'SR_HANDLE_INVALID', func, *args, **kwargs)
 
 def valid_pif(func):
     """Decorator to verify if sr_ref is valid before calling
@@ -274,20 +238,9 @@ def valid_pif(func):
     @param func: function with params: (self, session, sr_ref)
     @rtype: callable object
     """
-    def check_pif_ref(self, session, pif_ref, *args, **kwargs):
-        xennode = XendNode.instance()
-        if type(pif_ref) == type(str()) and pif_ref in xennode.pifs:
-            return func(self, session, pif_ref, *args, **kwargs)
-        else:
-            return xen_api_error(['PIF_HANDLE_INVALID', pif_ref])
-
-    # make sure we keep the 'api' attribute
-    if hasattr(func, 'api'):
-        check_pif_ref.api = func.api
-        
-    return check_pif_ref
-
-
+    return lambda *args, **kwargs: \
+           _check_ref(lambda r: r in XendNode.instance().pifs,
+                      'PIF_HANDLE_INVALID', func, *args, **kwargs)
 
 # -----------------------------
 # Bridge to Legacy XM API calls
@@ -1532,17 +1485,20 @@ def _decorate():
     and L{session_required}.
     """
 
+    global_validators = [session_required, catch_typeerror]
     classes = {
-        'session': (session_required, catch_typeerror),
-        'host': (valid_host, session_required, catch_typeerror),
-        'host_cpu': (valid_host_cpu, session_required, catch_typeerror),
-        'VM': (valid_vm, session_required, catch_typeerror),
-        'VBD': (valid_vbd, session_required, catch_typeerror),
-        'VIF': (valid_vif, session_required, catch_typeerror),
-        'VDI': (valid_vdi, session_required, catch_typeerror),
-        'VTPM':(valid_vtpm, session_required, catch_typeerror),
-        'SR':  (valid_sr, session_required, catch_typeerror),
-        'PIF': (valid_pif, session_required, catch_typeerror)}
+        'session' : None,
+        'host'    : valid_host,
+        'host_cpu': valid_host_cpu,
+        'network' : valid_network,
+        'VM'      : valid_vm,
+        'VBD'     : valid_vbd,
+        'VIF'     : valid_vif,
+        'VDI'     : valid_vdi,
+        'VTPM'    : valid_vtpm,
+        'SR'      : valid_sr,
+        'PIF'     : valid_pif
+        }
 
     # Cheat methods
     # -------------
@@ -1571,7 +1527,24 @@ def _decorate():
     # Wrapping validators around XMLRPC calls
     # ---------------------------------------
 
-    for cls, validators in classes.items():
+    for cls, validator in classes.items():
+        def doit(n, takes_instance):
+            n_ = n.replace('.', '_')
+            try:
+                f = getattr(XendAPI, n_)
+                argcounts[n] = f.func_code.co_argcount - 1
+
+                validators = takes_instance and validator and [validator] \
+                             or []
+                validators += global_validators
+                for v in validators:
+                    f = v(f)
+                    f.api = n
+                setattr(XendAPI, n_, f)
+            except AttributeError:
+                log.warn("API call: %s not found" % n)
+
+
         ro_attrs = getattr(XendAPI, '%s_attr_ro' % cls, [])
         rw_attrs = getattr(XendAPI, '%s_attr_rw' % cls, [])
         methods  = getattr(XendAPI, '%s_methods' % cls, [])
@@ -1579,55 +1552,19 @@ def _decorate():
 
         # wrap validators around readable class attributes
         for attr_name in ro_attrs + rw_attrs + XendAPI.Base_attr_ro:
-            getter_name = '%s_get_%s' % (cls, attr_name)
-            try:
-                getter = getattr(XendAPI, getter_name)
-                for validator in validators:
-                    getter = validator(getter)
-                    getter.api = '%s.get_%s' % (cls, attr_name)
-                setattr(XendAPI, getter_name, getter)
-            except AttributeError:
-                pass
-                #log.warn("API call: %s not found" % getter_name)
+            doit('%s.get_%s' % (cls, attr_name), True)
 
         # wrap validators around writable class attrributes
         for attr_name in rw_attrs + XendAPI.Base_attr_rw:
-            setter_name = '%s_set_%s' % (cls, attr_name)
-            try:
-                setter = getattr(XendAPI, setter_name)
-                for validator in validators:
-                    setter = validator(setter)
-                    setter.api = '%s.set_%s' % (cls, attr_name)
-                setattr(XendAPI, setter_name, setter)
-            except AttributeError:
-                pass
-                #log.warn("API call: %s not found" % setter_name)
+            doit('%s.set_%s' % (cls, attr_name), True)
 
         # wrap validators around methods
         for method_name in methods + XendAPI.Base_methods:
-            method_full_name = '%s_%s' % (cls, method_name)
-            try:
-                method = getattr(XendAPI, method_full_name)
-                for validator in validators:
-                    method = validator(method)
-                    method.api = '%s.%s' % (cls, method_name)
-                setattr(XendAPI, method_full_name, method)
-            except AttributeError:
-                pass
-                #log.warn('API call: %s not found' % method_full_name)
+            doit('%s.%s' % (cls, method_name), True)
 
         # wrap validators around class functions
         for func_name in funcs + XendAPI.Base_funcs:
-            func_full_name = '%s_%s' % (cls, func_name)
-            try:
-                method = getattr(XendAPI, func_full_name)
-                method = session_required(method)
-                method.api = '%s.%s' % (cls, func_name)
-                method = catch_typeerror(method)
-                method.api = '%s.%s' % (cls, func_name)
-                setattr(XendAPI, func_full_name, method)
-            except AttributeError:
-                log.warn('API call: %s not found' % func_full_name)
+            doit('%s.%s' % (cls, func_name), False)
 
 _decorate()
 

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.