📄 xendapi.py
字号:
@rtype: callable object """ return lambda *args, **kwargs: \ _check_ref(lambda r: XendDomain.instance().is_valid_dev('vif', r), 'VIF_metrics', func, *args, **kwargs)def valid_vdi(func): """Decorator to verify if vdi_ref is valid before calling method. @param func: function with params: (self, session, vdi_ref, ...) @rtype: callable object """ return lambda *args, **kwargs: \ _check_ref(XendNode.instance().is_valid_vdi, 'VDI', func, *args, **kwargs)def valid_vtpm(func): """Decorator to verify if vtpm_ref is valid before calling method. @param func: function with params: (self, session, vtpm_ref, ...) @rtype: callable object """ return lambda *args, **kwargs: \ _check_ref(lambda r: XendDomain.instance().is_valid_dev('vtpm', r), 'VTPM', func, *args, **kwargs)def valid_console(func): """Decorator to verify if console_ref is valid before calling method. @param func: function with params: (self, session, console_ref, ...) @rtype: callable object """ return lambda *args, **kwargs: \ _check_ref(lambda r: XendDomain.instance().is_valid_dev('console', r), 'console', func, *args, **kwargs)def valid_sr(func): """Decorator to verify if sr_ref is valid before calling method. @param func: function with params: (self, session, sr_ref, ...) @rtype: callable object """ return lambda *args, **kwargs: \ _check_ref(lambda r: XendNode.instance().is_valid_sr, 'SR', func, *args, **kwargs)def valid_task(func): """Decorator to verify if task_ref is valid before calling method. @param func: function with params: (self, session, task_ref) @rtype: callable object """ return lambda *args, **kwargs: \ _check_ref(XendTaskManager.get_task, 'task', func, *args, **kwargs)def valid_debug(func): """Decorator to verify if task_ref is valid before calling method. @param func: function with params: (self, session, task_ref) @rtype: callable object """ return lambda *args, **kwargs: \ _check_ref(lambda r: r in XendAPI._debug, 'debug', func, *args, **kwargs)def valid_object(class_name): """Decorator to verify if object is valid before calling method. @param func: function with params: (self, session, pif_ref) @rtype: callable object """ return lambda func: \ lambda *args, **kwargs: \ _check_ref(lambda r: \ XendAPIStore.get(r, class_name) is not None, 'PIF', func, *args, **kwargs)# -----------------------------# Bridge to Legacy XM API calls# -----------------------------def do_vm_func(fn_name, vm_ref, *args, **kwargs): """Helper wrapper func to abstract away from repetitive code. @param fn_name: function name for XendDomain instance @type fn_name: string @param vm_ref: vm_ref @type vm_ref: string @param *args: more arguments @type *args: tuple """ try: xendom = XendDomain.instance() fn = getattr(xendom, fn_name) xendom.do_legacy_api_with_uuid(fn, vm_ref, *args, **kwargs) return xen_api_success_void() except VMBadState, exn: return xen_api_error(['VM_BAD_POWER_STATE', vm_ref, exn.expected, exn.actual])classes = { 'session' : None, 'event' : None, 'host' : valid_host, 'host_cpu' : valid_host_cpu, 'host_metrics' : valid_host_metrics, 'VM' : valid_vm, 'VBD' : valid_vbd, 'VBD_metrics' : valid_vbd_metrics, 'VIF' : valid_vif, 'VIF_metrics' : valid_vif_metrics, 'VDI' : valid_vdi, 'VTPM' : valid_vtpm, 'console' : valid_console, 'SR' : valid_sr, 'task' : valid_task, 'XSPolicy' : valid_object("XSPolicy"), 'ACMPolicy' : valid_object("ACMPolicy"), 'debug' : valid_debug, 'network' : valid_object("network"), 'PIF' : valid_object("PIF"), 'VM_metrics' : valid_object("VM_metrics"), 'PBD' : valid_object("PBD"), 'PIF_metrics' : valid_object("PIF_metrics")}autoplug_classes = { 'network' : XendNetwork, 'PIF' : XendPIF, 'VM_metrics' : XendVMMetrics, 'PBD' : XendPBD, 'PIF_metrics' : XendPIFMetrics, 'XSPolicy' : XendXSPolicy, 'ACMPolicy' : XendACMPolicy,}class XendAPI(object): """Implementation of the Xen-API in Xend. Expects to be used via XMLRPCServer. All methods that need a valid session are marked with a L{session_required} decorator that will transparently perform the required session authentication. We need to support Python <2.4, so we use the old decorator syntax. All XMLRPC accessible methods require an 'api' attribute and is set to the XMLRPC function name which the method implements. """ __decorated__ = False __init_lock__ = threading.Lock() _debug = {} def __new__(cls, *args, **kwds): """ Override __new__ to decorate the class only once. Lock to make sure the classes are not decorated twice. """ cls.__init_lock__.acquire() try: if not cls.__decorated__: cls._decorate() cls.__decorated__ = True return object.__new__(cls, *args, **kwds) finally: cls.__init_lock__.release() def _decorate(cls): """ Decorate all the object methods to have validators and appropriate function attributes. This should only be executed once for the duration of the server. """ global_validators = [session_required, catch_typeerror] # Cheat methods # ------------- # Methods that have a trivial implementation for all classes. # 1. get_by_uuid == getting by ref, so just return uuid for # all get_by_uuid() methods. for api_cls in classes.keys(): # We'll let the autoplug classes implement these functions # themselves - its much cleaner to do it in the base class if api_cls == 'session' or api_cls in autoplug_classes.keys(): continue get_by_uuid = '%s_get_by_uuid' % api_cls get_uuid = '%s_get_uuid' % api_cls get_all_records = '%s_get_all_records' % api_cls def _get_by_uuid(_1, _2, ref): return xen_api_success(ref) def _get_uuid(_1, _2, ref): return xen_api_success(ref) def unpack(v): return v.get('Value') def _get_all_records(_api_cls): return lambda s, session: \ xen_api_success(dict([(ref, unpack(getattr(cls, '%s_get_record' % _api_cls)(s, session, ref)))\ for ref in unpack(getattr(cls, '%s_get_all' % _api_cls)(s, session))])) setattr(cls, get_by_uuid, _get_by_uuid) setattr(cls, get_uuid, _get_uuid) setattr(cls, get_all_records, _get_all_records(api_cls)) # Autoplugging classes # -------------------- # These have all of their methods grabbed out from the implementation # class, and wrapped up to be compatible with the Xen-API. def getter(ref, type): return XendAPIStore.get(ref, type) for api_cls, impl_cls in autoplug_classes.items(): def doit(n): dot_n = '%s.%s' % (api_cls, n) full_n = '%s_%s' % (api_cls, n) if not hasattr(cls, full_n): f = getattr(impl_cls, n) argcounts[dot_n] = f.func_code.co_argcount + 1 g = lambda api_cls: \ setattr(cls, full_n, \ lambda s, session, ref, *args: \ xen_api_success( \ f(getter(ref, api_cls), *args))) g(api_cls) # Force api_cls to be captured def doit_func(n): dot_n = '%s.%s' % (api_cls, n) full_n = '%s_%s' % (api_cls, n) if not hasattr(cls, full_n): f = getattr(impl_cls, n) argcounts[dot_n] = f.func_code.co_argcount setattr(cls, full_n, \ lambda s, session, *args: \ xen_api_success( \ f(*args))) ro_attrs = impl_cls.getAttrRO() rw_attrs = impl_cls.getAttrRW() methods = impl_cls.getMethods() funcs = impl_cls.getFuncs() for attr_name in ro_attrs + rw_attrs: doit('get_%s' % attr_name) for attr_name in rw_attrs: doit('set_%s' % attr_name) for method in methods: doit('%s' % method) for func in funcs: doit_func('%s' % func) def wrap_method(name, new_f): try: f = getattr(cls, name) wrapped_f = (lambda *args: new_f(f, *args)) wrapped_f.api = f.api wrapped_f.async = f.async setattr(cls, name, wrapped_f) except AttributeError: # Logged below (API call: %s not found) pass def setter_event_wrapper(api_cls, attr_name): setter_name = '%s_set_%s' % (api_cls, attr_name) wrap_method( setter_name, lambda setter, s, session, ref, *args: _setter_event_dispatch(s, setter, api_cls, attr_name, session, ref, args)) def ctor_event_wrapper(api_cls): ctor_name = '%s_create' % api_cls wrap_method( ctor_name, lambda ctor, s, session, *args: _ctor_event_dispatch(s, ctor, api_cls, session, args)) def dtor_event_wrapper(api_cls): dtor_name = '%s_destroy' % api_cls wrap_method( dtor_name, lambda dtor, s, session, ref, *args: _dtor_event_dispatch(s, dtor, api_cls, session, ref, args)) # Wrapping validators around XMLRPC calls # --------------------------------------- for api_cls, validator in classes.items(): def doit(n, takes_instance, async_support = False, return_type = None): n_ = n.replace('.', '_') try: f = getattr(cls, n_) if n not in argcounts: 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 f.async = async_support if return_type: f.return_type = return_type setattr(cls, n_, f) except AttributeError: log.warn("API call: %s not found" % n) if api_cls in autoplug_classes.keys(): impl_cls = autoplug_classes[api_cls] ro_attrs = impl_cls.getAttrRO() rw_attrs = impl_cls.getAttrRW() methods = map(lambda x: (x, ""), impl_cls.getMethods()) funcs = map(lambda x: (x, ""), impl_cls.getFuncs()) else: ro_attrs = getattr(cls, '%s_attr_ro' % api_cls, []) \ + cls.Base_attr_ro rw_attrs = getattr(cls, '%s_attr_rw' % api_cls, []) \ + cls.Base_attr_rw methods = getattr(cls, '%s_methods' % api_cls, []) \ + cls.Base_methods funcs = getattr(cls, '%s_funcs' % api_cls, []) \ + cls.Base_funcs
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -