WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] Change the way that MESSAGE_PARAMETER_COU

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] Change the way that MESSAGE_PARAMETER_COUNT_MISMATCH is diagnosed (using a
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Mon, 25 Dec 2006 10:55:10 -0800
Delivery-date: Mon, 25 Dec 2006 10:56:24 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# 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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] Change the way that MESSAGE_PARAMETER_COUNT_MISMATCH is diagnosed (using a, Xen patchbot-unstable <=