[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |