ia64/xen-unstable

view tools/python/xen/xend/XendAPI.py @ 14738:610dcfb3c164

Send INTERNAL_ERROR rather than ERROR_TODO if device creation fails.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author Ewan Mellor <ewan@xensource.com>
date Wed Apr 04 14:53:52 2007 +0100 (2007-04-04)
parents e5931b5e6cc5
children 4de1e743a5a8
line source
1 #============================================================================
2 # This library is free software; you can redistribute it and/or
3 # modify it under the terms of version 2.1 of the GNU Lesser General Public
4 # License as published by the Free Software Foundation.
5 #
6 # This library is distributed in the hope that it will be useful,
7 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 # Lesser General Public License for more details.
10 #
11 # You should have received a copy of the GNU Lesser General Public
12 # License along with this library; if not, write to the Free Software
13 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14 #============================================================================
15 # Copyright (C) 2006-2007 XenSource Ltd.
16 #============================================================================
18 import inspect
19 import os
20 import Queue
21 import sets
22 import string
23 import sys
24 import traceback
25 import threading
26 import time
27 import xmlrpclib
29 import XendDomain, XendDomainInfo, XendNode, XendDmesg
30 import XendLogging, XendTaskManager
32 from XendAPIVersion import *
33 from XendAuthSessions import instance as auth_manager
34 from XendError import *
35 from XendClient import ERROR_INVALID_DOMAIN
36 from XendLogging import log
37 from XendNetwork import XendNetwork
38 from XendTask import XendTask
39 from XendPIFMetrics import XendPIFMetrics
40 from XendVMMetrics import XendVMMetrics
42 import XendPBD
44 from XendAPIConstants import *
45 from xen.util.xmlrpclib2 import stringify
47 from xen.util.blkif import blkdev_name_to_number
50 AUTH_NONE = 'none'
51 AUTH_PAM = 'pam'
53 argcounts = {}
55 # ------------------------------------------
56 # Utility Methods for Xen API Implementation
57 # ------------------------------------------
59 def xen_api_success(value):
60 """Wraps a return value in XenAPI format."""
61 if value is None:
62 s = ''
63 else:
64 s = stringify(value)
65 return {"Status": "Success", "Value": s}
67 def xen_api_success_void():
68 """Return success, but caller expects no return value."""
69 return xen_api_success("")
71 def xen_api_error(error):
72 """Wraps an error value in XenAPI format."""
73 if type(error) == tuple:
74 error = list(error)
75 if type(error) != list:
76 error = [error]
77 if len(error) == 0:
78 error = ['INTERNAL_ERROR', 'Empty list given to xen_api_error']
80 return { "Status": "Failure",
81 "ErrorDescription": [str(x) for x in error] }
84 def xen_api_todo():
85 """Temporary method to make sure we track down all the TODOs"""
86 return {"Status": "Error", "ErrorDescription": XEND_ERROR_TODO}
89 def now():
90 return xmlrpclib.DateTime(time.strftime("%Y%m%dT%H:%M:%S", time.gmtime()))
93 # ---------------------------------------------------
94 # Event dispatch
95 # ---------------------------------------------------
97 EVENT_QUEUE_LENGTH = 50
98 event_registrations = {}
100 def event_register(session, reg_classes):
101 if session not in event_registrations:
102 event_registrations[session] = {
103 'classes' : sets.Set(),
104 'queue' : Queue.Queue(EVENT_QUEUE_LENGTH),
105 'next-id' : 1
106 }
107 if not reg_classes:
108 reg_classes = classes
109 event_registrations[session]['classes'].union_update(reg_classes)
112 def event_unregister(session, unreg_classes):
113 if session not in event_registrations:
114 return
116 if unreg_classes:
117 event_registrations[session]['classes'].intersection_update(
118 unreg_classes)
119 if len(event_registrations[session]['classes']) == 0:
120 del event_registrations[session]
121 else:
122 del event_registrations[session]
125 def event_next(session):
126 if session not in event_registrations:
127 return xen_api_error(['SESSION_NOT_REGISTERED', session])
128 queue = event_registrations[session]['queue']
129 events = [queue.get()]
130 try:
131 while True:
132 events.append(queue.get(False))
133 except Queue.Empty:
134 pass
136 return xen_api_success(events)
139 def _ctor_event_dispatch(xenapi, ctor, api_cls, session, args):
140 result = ctor(xenapi, session, *args)
141 if result['Status'] == 'Success':
142 ref = result['Value']
143 _event_dispatch('add', api_cls, ref, '')
144 return result
147 def _dtor_event_dispatch(xenapi, dtor, api_cls, session, ref, args):
148 result = dtor(xenapi, session, ref, *args)
149 if result['Status'] == 'Success':
150 _event_dispatch('del', api_cls, ref, '')
151 return result
154 def _setter_event_dispatch(xenapi, setter, api_cls, attr_name, session, ref,
155 args):
156 result = setter(xenapi, session, ref, *args)
157 if result['Status'] == 'Success':
158 _event_dispatch('mod', api_cls, ref, attr_name)
159 return result
162 def _event_dispatch(operation, api_cls, ref, attr_name):
163 event = {
164 'timestamp' : now(),
165 'class' : api_cls,
166 'operation' : operation,
167 'ref' : ref,
168 'obj_uuid' : ref,
169 'field' : attr_name,
170 }
171 for reg in event_registrations.values():
172 if api_cls in reg['classes']:
173 event['id'] = reg['next-id']
174 reg['next-id'] += 1
175 reg['queue'].put(event)
178 # ---------------------------------------------------
179 # Python Method Decorators for input value validation
180 # ---------------------------------------------------
182 def trace(func, api_name = ''):
183 """Decorator to trace XMLRPC Xen API methods.
185 @param func: function with any parameters
186 @param api_name: name of the api call for debugging.
187 """
188 if hasattr(func, 'api'):
189 api_name = func.api
190 def trace_func(self, *args, **kwargs):
191 log.debug('%s: %s' % (api_name, args))
192 return func(self, *args, **kwargs)
193 trace_func.api = api_name
194 return trace_func
197 def catch_typeerror(func):
198 """Decorator to catch any TypeErrors and translate them into Xen-API
199 errors.
201 @param func: function with params: (self, ...)
202 @rtype: callable object
203 """
204 def f(self, *args, **kwargs):
205 try:
206 return func(self, *args, **kwargs)
207 except TypeError, exn:
208 #log.exception('catch_typeerror')
209 if hasattr(func, 'api') and func.api in argcounts:
210 # Assume that if the argument count was wrong and if the
211 # exception was thrown inside this file, then it is due to an
212 # invalid call from the client, otherwise it's an internal
213 # error (which will be handled further up).
214 expected = argcounts[func.api]
215 actual = len(args) + len(kwargs)
216 if expected != actual:
217 tb = sys.exc_info()[2]
218 try:
219 sourcefile = traceback.extract_tb(tb)[-1][0]
220 if sourcefile == inspect.getsourcefile(XendAPI):
221 return xen_api_error(
222 ['MESSAGE_PARAMETER_COUNT_MISMATCH',
223 func.api, expected, actual])
224 finally:
225 del tb
226 raise
228 return f
231 def session_required(func):
232 """Decorator to verify if session is valid before calling method.
234 @param func: function with params: (self, session, ...)
235 @rtype: callable object
236 """
237 def check_session(self, session, *args, **kwargs):
238 if auth_manager().is_session_valid(session):
239 return func(self, session, *args, **kwargs)
240 else:
241 return xen_api_error(['SESSION_INVALID', session])
243 return check_session
246 def _is_valid_ref(ref, validator):
247 return type(ref) == str and validator(ref)
249 def _check_ref(validator, clas, func, api, session, ref, *args, **kwargs):
250 if _is_valid_ref(ref, validator):
251 return func(api, session, ref, *args, **kwargs)
252 else:
253 return xen_api_error(['HANDLE_INVALID', clas, ref])
256 def valid_host(func):
257 """Decorator to verify if host_ref is valid before calling method.
259 @param func: function with params: (self, session, host_ref, ...)
260 @rtype: callable object
261 """
262 return lambda *args, **kwargs: \
263 _check_ref(XendNode.instance().is_valid_host,
264 'host', func, *args, **kwargs)
266 def valid_host_metrics(func):
267 """Decorator to verify if host_metrics_ref is valid before calling
268 method.
270 @param func: function with params: (self, session, host_metrics_ref)
271 @rtype: callable object
272 """
273 return lambda *args, **kwargs: \
274 _check_ref(lambda r: r == XendNode.instance().host_metrics_uuid,
275 'host_metrics', func, *args, **kwargs)
277 def valid_host_cpu(func):
278 """Decorator to verify if host_cpu_ref is valid before calling method.
280 @param func: function with params: (self, session, host_cpu_ref, ...)
281 @rtype: callable object
282 """
283 return lambda *args, **kwargs: \
284 _check_ref(XendNode.instance().is_valid_cpu,
285 'host_cpu', func, *args, **kwargs)
287 def valid_vm(func):
288 """Decorator to verify if vm_ref is valid before calling method.
290 @param func: function with params: (self, session, vm_ref, ...)
291 @rtype: callable object
292 """
293 return lambda *args, **kwargs: \
294 _check_ref(XendDomain.instance().is_valid_vm,
295 'VM', func, *args, **kwargs)
297 def valid_vm_metrics(func):
298 """Decorator to verify if vm_metrics_ref is valid before calling method.
300 @param func: function with params: (self, session, vm_metrics_ref, ...)
301 @rtype: callable object
302 """
303 return lambda *args, **kwargs: \
304 _check_ref(XendVMMetrics.is_valid_vm_metrics,
305 'VM_metrics', func, *args, **kwargs)
307 def valid_network(func):
308 """Decorator to verify if network_ref is valid before calling method.
310 @param func: function with params: (self, session, network_ref, ...)
311 @rtype: callable object
312 """
313 return lambda *args, **kwargs: \
314 _check_ref(XendNode.instance().is_valid_network,
315 'network', func, *args, **kwargs)
317 def valid_vbd(func):
318 """Decorator to verify if vbd_ref is valid before calling method.
320 @param func: function with params: (self, session, vbd_ref, ...)
321 @rtype: callable object
322 """
323 return lambda *args, **kwargs: \
324 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vbd', r),
325 'VBD', func, *args, **kwargs)
327 def valid_vbd_metrics(func):
328 """Decorator to verify if ref is valid before calling method.
330 @param func: function with params: (self, session, ref, ...)
331 @rtype: callable object
332 """
333 return lambda *args, **kwargs: \
334 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vbd', r),
335 'VBD_metrics', func, *args, **kwargs)
337 def valid_vif(func):
338 """Decorator to verify if vif_ref is valid before calling method.
340 @param func: function with params: (self, session, vif_ref, ...)
341 @rtype: callable object
342 """
343 return lambda *args, **kwargs: \
344 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vif', r),
345 'VIF', func, *args, **kwargs)
347 def valid_vif_metrics(func):
348 """Decorator to verify if ref is valid before calling method.
350 @param func: function with params: (self, session, ref, ...)
351 @rtype: callable object
352 """
353 return lambda *args, **kwargs: \
354 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vif', r),
355 'VIF_metrics', func, *args, **kwargs)
357 def valid_vdi(func):
358 """Decorator to verify if vdi_ref is valid before calling method.
360 @param func: function with params: (self, session, vdi_ref, ...)
361 @rtype: callable object
362 """
363 return lambda *args, **kwargs: \
364 _check_ref(XendNode.instance().is_valid_vdi,
365 'VDI', func, *args, **kwargs)
367 def valid_vtpm(func):
368 """Decorator to verify if vtpm_ref is valid before calling method.
370 @param func: function with params: (self, session, vtpm_ref, ...)
371 @rtype: callable object
372 """
373 return lambda *args, **kwargs: \
374 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vtpm', r),
375 'VTPM', func, *args, **kwargs)
378 def valid_console(func):
379 """Decorator to verify if console_ref is valid before calling method.
381 @param func: function with params: (self, session, console_ref, ...)
382 @rtype: callable object
383 """
384 return lambda *args, **kwargs: \
385 _check_ref(lambda r: XendDomain.instance().is_valid_dev('console',
386 r),
387 'console', func, *args, **kwargs)
389 def valid_sr(func):
390 """Decorator to verify if sr_ref is valid before calling method.
392 @param func: function with params: (self, session, sr_ref, ...)
393 @rtype: callable object
394 """
395 return lambda *args, **kwargs: \
396 _check_ref(lambda r: XendNode.instance().is_valid_sr,
397 'SR', func, *args, **kwargs)
399 def valid_pbd(func):
400 """Decorator to verify if pbd_ref is valid before calling
401 method.
403 @param func: function with params: (self, session, pbd_ref)
404 @rtype: callable object
405 """
406 return lambda *args, **kwargs: \
407 _check_ref(lambda r: r in XendPBD.get_all_refs(),
408 'PBD', func, *args, **kwargs)
410 def valid_pif(func):
411 """Decorator to verify if pif_ref is valid before calling
412 method.
414 @param func: function with params: (self, session, pif_ref)
415 @rtype: callable object
416 """
417 return lambda *args, **kwargs: \
418 _check_ref(lambda r: r in XendNode.instance().pifs,
419 'PIF', func, *args, **kwargs)
421 def valid_pif_metrics(func):
422 """Decorator to verify if pif_metrics_ref is valid before calling
423 method.
425 @param func: function with params: (self, session, pif_metrics_ref)
426 @rtype: callable object
427 """
428 return lambda *args, **kwargs: \
429 _check_ref(lambda r: r in XendNode.instance().pif_metrics,
430 'PIF_metrics', func, *args, **kwargs)
432 def valid_task(func):
433 """Decorator to verify if task_ref is valid before calling
434 method.
436 @param func: function with params: (self, session, task_ref)
437 @rtype: callable object
438 """
439 return lambda *args, **kwargs: \
440 _check_ref(XendTaskManager.get_task,
441 'task', func, *args, **kwargs)
443 def valid_debug(func):
444 """Decorator to verify if task_ref is valid before calling
445 method.
447 @param func: function with params: (self, session, task_ref)
448 @rtype: callable object
449 """
450 return lambda *args, **kwargs: \
451 _check_ref(lambda r: r in XendAPI._debug,
452 'debug', func, *args, **kwargs)
454 # -----------------------------
455 # Bridge to Legacy XM API calls
456 # -----------------------------
458 def do_vm_func(fn_name, vm_ref, *args, **kwargs):
459 """Helper wrapper func to abstract away from repetitive code.
461 @param fn_name: function name for XendDomain instance
462 @type fn_name: string
463 @param vm_ref: vm_ref
464 @type vm_ref: string
465 @param *args: more arguments
466 @type *args: tuple
467 """
468 try:
469 xendom = XendDomain.instance()
470 fn = getattr(xendom, fn_name)
471 xendom.do_legacy_api_with_uuid(fn, vm_ref, *args, **kwargs)
472 return xen_api_success_void()
473 except VMBadState, exn:
474 return xen_api_error(['VM_BAD_POWER_STATE', vm_ref, exn.expected,
475 exn.actual])
478 classes = {
479 'session' : None,
480 'event' : None,
481 'host' : valid_host,
482 'host_cpu' : valid_host_cpu,
483 'host_metrics' : valid_host_metrics,
484 'network' : valid_network,
485 'VM' : valid_vm,
486 'VM_metrics' : valid_vm_metrics,
487 'VBD' : valid_vbd,
488 'VBD_metrics' : valid_vbd_metrics,
489 'VIF' : valid_vif,
490 'VIF_metrics' : valid_vif_metrics,
491 'VDI' : valid_vdi,
492 'VTPM' : valid_vtpm,
493 'console' : valid_console,
494 'SR' : valid_sr,
495 'PBD' : valid_pbd,
496 'PIF' : valid_pif,
497 'PIF_metrics' : valid_pif_metrics,
498 'task' : valid_task,
499 'debug' : valid_debug,
500 }
502 autoplug_classes = {
503 'network' : XendNetwork,
504 'VM_metrics' : XendVMMetrics,
505 'PBD' : XendPBD.XendPBD,
506 'PIF_metrics' : XendPIFMetrics,
507 }
510 class XendAPI(object):
511 """Implementation of the Xen-API in Xend. Expects to be
512 used via XMLRPCServer.
514 All methods that need a valid session are marked with
515 a L{session_required} decorator that will
516 transparently perform the required session authentication.
518 We need to support Python <2.4, so we use the old decorator syntax.
520 All XMLRPC accessible methods require an 'api' attribute and
521 is set to the XMLRPC function name which the method implements.
522 """
524 __decorated__ = False
525 __init_lock__ = threading.Lock()
526 _debug = {}
528 def __new__(cls, *args, **kwds):
529 """ Override __new__ to decorate the class only once.
531 Lock to make sure the classes are not decorated twice.
532 """
533 cls.__init_lock__.acquire()
534 try:
535 if not cls.__decorated__:
536 cls._decorate()
537 cls.__decorated__ = True
539 return object.__new__(cls, *args, **kwds)
540 finally:
541 cls.__init_lock__.release()
543 def _decorate(cls):
544 """ Decorate all the object methods to have validators
545 and appropriate function attributes.
547 This should only be executed once for the duration of the
548 server.
549 """
550 global_validators = [session_required, catch_typeerror]
553 # Cheat methods
554 # -------------
555 # Methods that have a trivial implementation for all classes.
556 # 1. get_by_uuid == getting by ref, so just return uuid for
557 # all get_by_uuid() methods.
559 for api_cls in classes.keys():
560 if api_cls == 'session':
561 continue
563 get_by_uuid = '%s_get_by_uuid' % api_cls
564 get_uuid = '%s_get_uuid' % api_cls
565 def _get_by_uuid(_1, _2, ref):
566 return xen_api_success(ref)
568 def _get_uuid(_1, _2, ref):
569 return xen_api_success(ref)
571 setattr(cls, get_by_uuid, _get_by_uuid)
572 setattr(cls, get_uuid, _get_uuid)
575 # Autoplugging classes
576 # --------------------
577 # These have all of their methods grabbed out from the implementation
578 # class, and wrapped up to be compatible with the Xen-API.
580 for api_cls, impl_cls in autoplug_classes.items():
581 def doit(n):
582 getter = getattr(cls, '_%s_get' % api_cls)
583 dot_n = '%s.%s' % (api_cls, n)
584 full_n = '%s_%s' % (api_cls, n)
585 if not hasattr(cls, full_n):
586 f = getattr(impl_cls, n)
587 argcounts[dot_n] = f.func_code.co_argcount + 1
588 setattr(cls, full_n,
589 lambda s, session, ref, *args: \
590 xen_api_success( \
591 f(getter(s, session, ref), *args)))
593 ro_attrs = getattr(cls, '%s_attr_ro' % api_cls, [])
594 rw_attrs = getattr(cls, '%s_attr_rw' % api_cls, [])
595 methods = getattr(cls, '%s_methods' % api_cls, [])
596 funcs = getattr(cls, '%s_funcs' % api_cls, [])
598 for attr_name in ro_attrs + rw_attrs:
599 doit('get_%s' % attr_name)
600 for attr_name in rw_attrs + cls.Base_attr_rw:
601 doit('set_%s' % attr_name)
602 for method_name, return_type in methods + cls.Base_methods:
603 doit('%s' % method_name)
604 for func_name, return_type in funcs + cls.Base_funcs:
605 doit('%s' % func_name)
608 def wrap_method(name, new_f):
609 try:
610 f = getattr(cls, name)
611 wrapped_f = (lambda *args: new_f(f, *args))
612 wrapped_f.api = f.api
613 wrapped_f.async = f.async
614 setattr(cls, name, wrapped_f)
615 except AttributeError:
616 # Logged below (API call: %s not found)
617 pass
620 def setter_event_wrapper(api_cls, attr_name):
621 setter_name = '%s_set_%s' % (api_cls, attr_name)
622 wrap_method(
623 setter_name,
624 lambda setter, s, session, ref, *args:
625 _setter_event_dispatch(s, setter, api_cls, attr_name,
626 session, ref, args))
629 def ctor_event_wrapper(api_cls):
630 ctor_name = '%s_create' % api_cls
631 wrap_method(
632 ctor_name,
633 lambda ctor, s, session, *args:
634 _ctor_event_dispatch(s, ctor, api_cls, session, args))
637 def dtor_event_wrapper(api_cls):
638 dtor_name = '%s_destroy' % api_cls
639 wrap_method(
640 dtor_name,
641 lambda dtor, s, session, ref, *args:
642 _dtor_event_dispatch(s, dtor, api_cls, session, ref, args))
645 # Wrapping validators around XMLRPC calls
646 # ---------------------------------------
648 for api_cls, validator in classes.items():
649 def doit(n, takes_instance, async_support = False,
650 return_type = None):
651 n_ = n.replace('.', '_')
652 try:
653 f = getattr(cls, n_)
654 if n not in argcounts:
655 argcounts[n] = f.func_code.co_argcount - 1
657 validators = takes_instance and validator and \
658 [validator] or []
660 validators += global_validators
661 for v in validators:
662 f = v(f)
663 f.api = n
664 f.async = async_support
665 if return_type:
666 f.return_type = return_type
668 setattr(cls, n_, f)
669 except AttributeError:
670 log.warn("API call: %s not found" % n)
673 ro_attrs = getattr(cls, '%s_attr_ro' % api_cls, [])
674 rw_attrs = getattr(cls, '%s_attr_rw' % api_cls, [])
675 methods = getattr(cls, '%s_methods' % api_cls, [])
676 funcs = getattr(cls, '%s_funcs' % api_cls, [])
678 # wrap validators around readable class attributes
679 for attr_name in ro_attrs + rw_attrs + cls.Base_attr_ro:
680 doit('%s.get_%s' % (api_cls, attr_name), True,
681 async_support = False)
683 # wrap validators around writable class attrributes
684 for attr_name in rw_attrs + cls.Base_attr_rw:
685 doit('%s.set_%s' % (api_cls, attr_name), True,
686 async_support = False)
687 setter_event_wrapper(api_cls, attr_name)
689 # wrap validators around methods
690 for method_name, return_type in methods + cls.Base_methods:
691 doit('%s.%s' % (api_cls, method_name), True,
692 async_support = True)
694 # wrap validators around class functions
695 for func_name, return_type in funcs + cls.Base_funcs:
696 doit('%s.%s' % (api_cls, func_name), False, async_support = True,
697 return_type = return_type)
699 ctor_event_wrapper(api_cls)
700 dtor_event_wrapper(api_cls)
703 _decorate = classmethod(_decorate)
705 def __init__(self, auth):
706 self.auth = auth
708 Base_attr_ro = ['uuid']
709 Base_attr_rw = []
710 Base_methods = [('get_record', 'Struct')]
711 Base_funcs = [('get_all', 'Set'), ('get_by_uuid', None)]
713 # Xen API: Class Session
714 # ----------------------------------------------------------------
715 # NOTE: Left unwrapped by __init__
717 session_attr_ro = ['this_host', 'this_user', 'last_active']
718 session_methods = [('logout', None)]
720 def session_get_all(self, session):
721 return xen_api_success([session])
723 def session_login_with_password(self, *args):
724 if len(args) != 2:
725 return xen_api_error(
726 ['MESSAGE_PARAMETER_COUNT_MISMATCH',
727 'session.login_with_password', 2, len(args)])
728 username = args[0]
729 password = args[1]
730 try:
731 session = ((self.auth == AUTH_NONE and
732 auth_manager().login_unconditionally(username)) or
733 auth_manager().login_with_password(username, password))
734 return xen_api_success(session)
735 except XendError, e:
736 return xen_api_error(['SESSION_AUTHENTICATION_FAILED'])
737 session_login_with_password.api = 'session.login_with_password'
739 # object methods
740 def session_logout(self, session):
741 auth_manager().logout(session)
742 return xen_api_success_void()
744 def session_get_record(self, session, self_session):
745 if self_session != session:
746 return xen_api_error(['PERMISSION_DENIED'])
747 record = {'uuid' : session,
748 'this_host' : XendNode.instance().uuid,
749 'this_user' : auth_manager().get_user(session),
750 'last_active': now()}
751 return xen_api_success(record)
753 def session_get_uuid(self, session, self_session):
754 return xen_api_success(self_session)
756 def session_get_by_uuid(self, session, self_session):
757 return xen_api_success(self_session)
759 # attributes (ro)
760 def session_get_this_host(self, session, self_session):
761 if self_session != session:
762 return xen_api_error(['PERMISSION_DENIED'])
763 return xen_api_success(XendNode.instance().uuid)
765 def session_get_this_user(self, session, self_session):
766 if self_session != session:
767 return xen_api_error(['PERMISSION_DENIED'])
768 user = auth_manager().get_user(session)
769 if user is not None:
770 return xen_api_success(user)
771 return xen_api_error(['SESSION_INVALID', session])
773 def session_get_last_active(self, session, self_session):
774 if self_session != session:
775 return xen_api_error(['PERMISSION_DENIED'])
776 return xen_api_success(now())
779 # Xen API: Class User
780 # ----------------------------------------------------------------
781 # TODO: NOT IMPLEMENTED YET
783 # Xen API: Class Tasks
784 # ----------------------------------------------------------------
786 task_attr_ro = ['name_label',
787 'name_description',
788 'status',
789 'progress',
790 'type',
791 'result',
792 'error_code',
793 'error_info',
794 'allowed_operations',
795 'session'
796 ]
798 task_attr_rw = []
800 task_funcs = [('get_by_name_label', 'Set(task)'),
801 ('cancel', None)]
803 def task_get_name_label(self, session, task_ref):
804 task = XendTaskManager.get_task(task_ref)
805 return xen_api_success(task.name_label)
807 def task_get_name_description(self, session, task_ref):
808 task = XendTaskManager.get_task(task_ref)
809 return xen_api_success(task.name_description)
811 def task_get_status(self, session, task_ref):
812 task = XendTaskManager.get_task(task_ref)
813 return xen_api_success(task.get_status())
815 def task_get_progress(self, session, task_ref):
816 task = XendTaskManager.get_task(task_ref)
817 return xen_api_success(task.progress)
819 def task_get_type(self, session, task_ref):
820 task = XendTaskManager.get_task(task_ref)
821 return xen_api_success(task.type)
823 def task_get_result(self, session, task_ref):
824 task = XendTaskManager.get_task(task_ref)
825 return xen_api_success(task.result)
827 def task_get_error_code(self, session, task_ref):
828 task = XendTaskManager.get_task(task_ref)
829 return xen_api_success(task.error_code)
831 def task_get_error_info(self, session, task_ref):
832 task = XendTaskManager.get_task(task_ref)
833 return xen_api_success(task.error_info)
835 def task_get_allowed_operations(self, session, task_ref):
836 return xen_api_success({})
838 def task_get_session(self, session, task_ref):
839 task = XendTaskManager.get_task(task_ref)
840 return xen_api_success(task.session)
842 def task_get_all(self, session):
843 tasks = XendTaskManager.get_all_tasks()
844 return xen_api_success(tasks)
846 def task_get_record(self, session, task_ref):
847 task = XendTaskManager.get_task(task_ref)
848 return xen_api_success(task.get_record())
850 def task_cancel(self, session, task_ref):
851 return xen_api_error('OPERATION_NOT_ALLOWED')
853 def task_get_by_name_label(self, session, name):
854 return xen_api_success(XendTaskManager.get_task_by_name(name))
856 # Xen API: Class host
857 # ----------------------------------------------------------------
859 host_attr_ro = ['software_version',
860 'resident_VMs',
861 'PBDs',
862 'PIFs',
863 'host_CPUs',
864 'cpu_configuration',
865 'metrics',
866 'capabilities',
867 'supported_bootloaders',
868 'API_version_major',
869 'API_version_minor',
870 'API_version_vendor',
871 'API_version_vendor_implementation']
873 host_attr_rw = ['name_label',
874 'sched_policy',
875 'name_description',
876 'other_config']
878 host_methods = [('disable', None),
879 ('enable', None),
880 ('reboot', None),
881 ('shutdown', None),
882 ('add_to_other_config', None),
883 ('remove_from_other_config', None),
884 ('dmesg', 'String'),
885 ('dmesg_clear', 'String'),
886 ('get_log', 'String'),
887 ('send_debug_keys', None)]
889 host_funcs = [('get_by_name_label', 'Set(host)')]
891 # attributes
892 def host_get_name_label(self, session, host_ref):
893 return xen_api_success(XendNode.instance().name)
894 def host_set_name_label(self, session, host_ref, new_name):
895 XendNode.instance().set_name(new_name)
896 return xen_api_success_void()
897 def host_get_name_description(self, session, host_ref):
898 return xen_api_success(XendNode.instance().description)
899 def host_set_name_description(self, session, host_ref, new_desc):
900 XendNode.instance().set_description(new_desc)
901 return xen_api_success_void()
902 def host_get_other_config(self, session, host_ref):
903 return xen_api_success(XendNode.instance().other_config)
904 def host_set_other_config(self, session, host_ref, other_config):
905 node = XendNode.instance()
906 node.other_config = dict(other_config)
907 node.save()
908 return xen_api_success_void()
909 def host_add_to_other_config(self, session, host_ref, key, value):
910 node = XendNode.instance()
911 node.other_config[key] = value
912 node.save()
913 return xen_api_success_void()
914 def host_remove_from_other_config(self, session, host_ref, key):
915 node = XendNode.instance()
916 if key in node.other_config:
917 del node.other_config[key]
918 node.save()
919 return xen_api_success_void()
920 def host_get_API_version_major(self, _, ref):
921 return xen_api_success(XEN_API_VERSION_MAJOR)
922 def host_get_API_version_minor(self, _, ref):
923 return xen_api_success(XEN_API_VERSION_MINOR)
924 def host_get_API_version_vendor(self, _, ref):
925 return xen_api_success(XEN_API_VERSION_VENDOR)
926 def host_get_API_version_vendor_implementation(self, _, ref):
927 return xen_api_success(XEN_API_VERSION_VENDOR_IMPLEMENTATION)
928 def host_get_software_version(self, session, host_ref):
929 return xen_api_success(XendNode.instance().xen_version())
930 def host_get_resident_VMs(self, session, host_ref):
931 return xen_api_success(XendDomain.instance().get_domain_refs())
932 def host_get_PBDs(self, _, ref):
933 return xen_api_success(XendPBD.get_all_refs())
934 def host_get_PIFs(self, session, ref):
935 return xen_api_success(XendNode.instance().get_PIF_refs())
936 def host_get_host_CPUs(self, session, host_ref):
937 return xen_api_success(XendNode.instance().get_host_cpu_refs())
938 def host_get_metrics(self, _, ref):
939 return xen_api_success(XendNode.instance().host_metrics_uuid)
940 def host_get_capabilities(self, session, host_ref):
941 return xen_api_success(XendNode.instance().get_capabilities())
942 def host_get_supported_bootloaders(self, session, host_ref):
943 return xen_api_success(['pygrub'])
944 def host_get_sched_policy(self, _, host_ref):
945 return xen_api_success(XendNode.instance().get_vcpus_policy())
946 def host_set_sched_policy(self, _, host_ref, policy):
947 return xen_api_todo()
948 def host_get_cpu_configuration(self, _, host_ref):
949 return xen_api_success(XendNode.instance().get_cpu_configuration())
951 # object methods
952 def host_disable(self, session, host_ref):
953 XendDomain.instance().set_allow_new_domains(False)
954 return xen_api_success_void()
955 def host_enable(self, session, host_ref):
956 XendDomain.instance().set_allow_new_domains(True)
957 return xen_api_success_void()
958 def host_reboot(self, session, host_ref):
959 if not XendDomain.instance().allow_new_domains():
960 return xen_api_error(XEND_ERROR_HOST_RUNNING)
961 return xen_api_error(XEND_ERROR_UNSUPPORTED)
962 def host_shutdown(self, session, host_ref):
963 if not XendDomain.instance().allow_new_domains():
964 return xen_api_error(XEND_ERROR_HOST_RUNNING)
965 return xen_api_error(XEND_ERROR_UNSUPPORTED)
967 def host_dmesg(self, session, host_ref):
968 return xen_api_success(XendDmesg.instance().info())
970 def host_dmesg_clear(self, session, host_ref):
971 return xen_api_success(XendDmesg.instance().clear())
973 def host_get_log(self, session, host_ref):
974 log_file = open(XendLogging.getLogFilename())
975 log_buffer = log_file.read()
976 return xen_api_success(log_buffer)
978 def host_send_debug_keys(self, _, host_ref, keys):
979 node = XendNode.instance()
980 node.send_debug_keys(keys)
981 return xen_api_success_void()
983 def host_get_record(self, session, host_ref):
984 node = XendNode.instance()
985 dom = XendDomain.instance()
986 record = {'uuid': node.uuid,
987 'name_label': node.name,
988 'name_description': '',
989 'API_version_major': XEN_API_VERSION_MAJOR,
990 'API_version_minor': XEN_API_VERSION_MINOR,
991 'API_version_vendor': XEN_API_VERSION_VENDOR,
992 'API_version_vendor_implementation':
993 XEN_API_VERSION_VENDOR_IMPLEMENTATION,
994 'software_version': node.xen_version(),
995 'other_config': node.other_config,
996 'resident_VMs': dom.get_domain_refs(),
997 'host_CPUs': node.get_host_cpu_refs(),
998 'cpu_configuration': node.get_cpu_configuration(),
999 'metrics': node.host_metrics_uuid,
1000 'capabilities': node.get_capabilities(),
1001 'supported_bootloaders': 'pygrub',
1002 'sched_policy': node.get_vcpus_policy()}
1003 return xen_api_success(record)
1005 # class methods
1006 def host_get_all(self, session):
1007 return xen_api_success((XendNode.instance().uuid,))
1008 def host_get_by_name_label(self, session, name):
1009 if XendNode.instance().name == name:
1010 return xen_api_success((XendNode.instance().uuid,))
1011 return xen_api_success([])
1014 # Xen API: Class host_CPU
1015 # ----------------------------------------------------------------
1017 host_cpu_attr_ro = ['host',
1018 'number',
1019 'vendor',
1020 'speed',
1021 'modelname',
1022 'stepping',
1023 'flags',
1024 'utilisation',
1025 'features']
1027 # attributes
1028 def _host_cpu_get(self, ref, field):
1029 return xen_api_success(
1030 XendNode.instance().get_host_cpu_field(ref, field))
1032 def host_cpu_get_host(self, _, ref):
1033 return xen_api_success(XendNode.instance().uuid)
1034 def host_cpu_get_features(self, _, ref):
1035 return self._host_cpu_get(ref, 'features')
1036 def host_cpu_get_number(self, _, ref):
1037 return self._host_cpu_get(ref, 'number')
1038 def host_cpu_get_vendor(self, _, ref):
1039 return self._host_cpu_get(ref, 'vendor')
1040 def host_cpu_get_speed(self, _, ref):
1041 return self._host_cpu_get(ref, 'speed')
1042 def host_cpu_get_modelname(self, _, ref):
1043 return self._host_cpu_get(ref, 'modelname')
1044 def host_cpu_get_stepping(self, _, ref):
1045 return self._host_cpu_get(ref, 'stepping')
1046 def host_cpu_get_flags(self, _, ref):
1047 return self._host_cpu_get(ref, 'flags')
1048 def host_cpu_get_utilisation(self, _, ref):
1049 return xen_api_success(XendNode.instance().get_host_cpu_load(ref))
1051 # object methods
1052 def host_cpu_get_record(self, _, ref):
1053 node = XendNode.instance()
1054 record = dict([(f, node.get_host_cpu_field(ref, f))
1055 for f in self.host_cpu_attr_ro
1056 if f not in ['uuid', 'host', 'utilisation']])
1057 record['uuid'] = ref
1058 record['host'] = node.uuid
1059 record['utilisation'] = node.get_host_cpu_load(ref)
1060 return xen_api_success(record)
1062 # class methods
1063 def host_cpu_get_all(self, session):
1064 return xen_api_success(XendNode.instance().get_host_cpu_refs())
1067 # Xen API: Class host_metrics
1068 # ----------------------------------------------------------------
1070 host_metrics_attr_ro = ['memory_total',
1071 'memory_free',
1072 'last_updated']
1073 host_metrics_attr_rw = []
1074 host_metrics_methods = []
1076 def host_metrics_get_all(self, _):
1077 return xen_api_success([XendNode.instance().host_metrics_uuid])
1079 def _host_metrics_get(self, ref, f):
1080 return xen_api_success(getattr(node, f)())
1082 def host_metrics_get_record(self, _, ref):
1083 return xen_api_success({
1084 'uuid' : ref,
1085 'memory_total' : self._host_metrics_get_memory_total(),
1086 'memory_free' : self._host_metrics_get_memory_free(),
1087 'last_updated' : now(),
1088 })
1090 def host_metrics_get_memory_total(self, _1, _2):
1091 return xen_api_success(self._host_metrics_get_memory_total())
1093 def host_metrics_get_memory_free(self, _1, _2):
1094 return xen_api_success(self._host_metrics_get_memory_free())
1096 def host_metrics_get_last_updated(self, _1, _2):
1097 return xen_api_success(now())
1099 def _host_metrics_get_memory_total(self):
1100 node = XendNode.instance()
1101 return node.xc.physinfo()['total_memory'] * 1024
1103 def _host_metrics_get_memory_free(self):
1104 node = XendNode.instance()
1105 return node.xc.physinfo()['free_memory'] * 1024
1108 # Xen API: Class network
1109 # ----------------------------------------------------------------
1111 network_attr_ro = ['VIFs', 'PIFs']
1112 network_attr_rw = ['name_label',
1113 'name_description',
1114 'other_config']
1115 network_methods = [('add_to_other_config', None),
1116 ('remove_from_other_config', None),
1117 ('destroy', None)]
1118 network_funcs = [('create', None)]
1120 def _network_get(self, _, ref):
1121 return XendNode.instance().get_network(ref)
1123 def network_get_all(self, _):
1124 return xen_api_success(XendNode.instance().get_network_refs())
1126 def network_create(self, _, record):
1127 return xen_api_success(XendNode.instance().network_create(record))
1129 def network_destroy(self, _, ref):
1130 return xen_api_success(XendNode.instance().network_destroy(ref))
1133 # Xen API: Class PIF
1134 # ----------------------------------------------------------------
1136 PIF_attr_ro = ['network',
1137 'host',
1138 'metrics']
1139 PIF_attr_rw = ['device',
1140 'MAC',
1141 'MTU',
1142 'VLAN']
1144 PIF_attr_inst = PIF_attr_rw
1146 PIF_methods = [('create_VLAN', 'int'), ('destroy', None)]
1148 def _get_PIF(self, ref):
1149 return XendNode.instance().pifs[ref]
1151 def PIF_destroy(self, _, ref):
1152 try:
1153 return xen_api_success(XendNode.instance().PIF_destroy(ref))
1154 except PIFIsPhysical, exn:
1155 return xen_api_error(['PIF_IS_PHYSICAL', ref])
1157 # object methods
1158 def PIF_get_record(self, _, ref):
1159 return xen_api_success(self._get_PIF(ref).get_record())
1161 def PIF_get_all(self, _):
1162 return xen_api_success(XendNode.instance().pifs.keys())
1164 def PIF_get_metrics(self, _, ref):
1165 return xen_api_success(self._get_PIF(ref).metrics.uuid)
1167 def PIF_get_device(self, _, ref):
1168 return xen_api_success(self._get_PIF(ref).device)
1170 def PIF_get_network(self, _, ref):
1171 return xen_api_success(self._get_PIF(ref).network.uuid)
1173 def PIF_get_host(self, _, ref):
1174 return xen_api_success(self._get_PIF(ref).host.uuid)
1176 def PIF_get_MAC(self, _, ref):
1177 return xen_api_success(self._get_PIF(ref).mac)
1179 def PIF_get_MTU(self, _, ref):
1180 return xen_api_success(self._get_PIF(ref).mtu)
1182 def PIF_get_VLAN(self, _, ref):
1183 return xen_api_success(self._get_PIF(ref).vlan)
1185 def PIF_set_device(self, _, ref, device):
1186 return xen_api_success(self._get_PIF(ref).set_device(device))
1188 def PIF_set_MAC(self, _, ref, mac):
1189 return xen_api_success(self._get_PIF(ref).set_mac(mac))
1191 def PIF_set_MTU(self, _, ref, mtu):
1192 return xen_api_success(self._get_PIF(ref).set_mtu(mtu))
1194 def PIF_create_VLAN(self, _, ref, network, vlan):
1195 try:
1196 vlan = int(vlan)
1197 except:
1198 return xen_api_error(['VLAN_TAG_INVALID', vlan])
1200 try:
1201 node = XendNode.instance()
1203 if _is_valid_ref(network, node.is_valid_network):
1204 return xen_api_success(
1205 node.PIF_create_VLAN(ref, network, vlan))
1206 else:
1207 return xen_api_error(['HANDLE_INVALID', 'network', network])
1208 except NetworkAlreadyConnected, exn:
1209 return xen_api_error(['NETWORK_ALREADY_CONNECTED',
1210 network, exn.pif_uuid])
1211 except VLANTagInvalid:
1212 return xen_api_error(['VLAN_TAG_INVALID', vlan])
1215 # Xen API: Class PIF_metrics
1216 # ----------------------------------------------------------------
1218 PIF_metrics_attr_ro = ['io_read_kbs',
1219 'io_write_kbs',
1220 'last_updated']
1221 PIF_metrics_attr_rw = []
1222 PIF_metrics_methods = []
1224 def PIF_metrics_get_all(self, _):
1225 return xen_api_success(XendNode.instance().pif_metrics.keys())
1227 def _PIF_metrics_get(self, _, ref):
1228 return XendNode.instance().pif_metrics[ref]
1231 # Xen API: Class VM
1232 # ----------------------------------------------------------------
1234 VM_attr_ro = ['power_state',
1235 'resident_on',
1236 'consoles',
1237 'VIFs',
1238 'VBDs',
1239 'VTPMs',
1240 'tools_version',
1241 'domid',
1242 'is_control_domain',
1243 'metrics'
1246 VM_attr_rw = ['name_label',
1247 'name_description',
1248 'user_version',
1249 'is_a_template',
1250 'auto_power_on',
1251 'memory_dynamic_max',
1252 'memory_dynamic_min',
1253 'memory_static_max',
1254 'memory_static_min',
1255 'VCPUs_max',
1256 'VCPUs_at_startup',
1257 'VCPUs_params',
1258 'actions_after_shutdown',
1259 'actions_after_reboot',
1260 'actions_after_suspend',
1261 'actions_after_crash',
1262 'PV_bootloader',
1263 'PV_kernel',
1264 'PV_ramdisk',
1265 'PV_args',
1266 'PV_bootloader_args',
1267 'HVM_boot_policy',
1268 'HVM_boot_params',
1269 'platform',
1270 'PCI_bus',
1271 'other_config']
1273 VM_methods = [('clone', 'VM'),
1274 ('start', None),
1275 ('pause', None),
1276 ('unpause', None),
1277 ('clean_shutdown', None),
1278 ('clean_reboot', None),
1279 ('hard_shutdown', None),
1280 ('hard_reboot', None),
1281 ('suspend', None),
1282 ('resume', None),
1283 ('send_sysrq', None),
1284 ('set_VCPUs_number_live', None),
1285 ('add_to_HVM_boot_params', None),
1286 ('remove_from_HVM_boot_params', None),
1287 ('add_to_VCPUs_params', None),
1288 ('add_to_VCPUs_params_live', None),
1289 ('remove_from_VCPUs_params', None),
1290 ('add_to_platform', None),
1291 ('remove_from_platform', None),
1292 ('add_to_other_config', None),
1293 ('remove_from_other_config', None),
1294 ('save', None),
1295 ('set_memory_dynamic_max_live', None),
1296 ('set_memory_dynamic_min_live', None),
1297 ('send_trigger', None),
1298 ('destroy', None)]
1300 VM_funcs = [('create', 'VM'),
1301 ('restore', None),
1302 ('get_by_name_label', 'Set(VM)')]
1304 # parameters required for _create()
1305 VM_attr_inst = [
1306 'name_label',
1307 'name_description',
1308 'user_version',
1309 'is_a_template',
1310 'memory_static_max',
1311 'memory_dynamic_max',
1312 'memory_dynamic_min',
1313 'memory_static_min',
1314 'VCPUs_max',
1315 'VCPUs_at_startup',
1316 'VCPUs_params',
1317 'actions_after_shutdown',
1318 'actions_after_reboot',
1319 'actions_after_suspend',
1320 'actions_after_crash',
1321 'PV_bootloader',
1322 'PV_kernel',
1323 'PV_ramdisk',
1324 'PV_args',
1325 'PV_bootloader_args',
1326 'HVM_boot_policy',
1327 'HVM_boot_params',
1328 'platform',
1329 'PCI_bus',
1330 'other_config']
1332 def VM_get(self, name, session, vm_ref):
1333 return xen_api_success(
1334 XendDomain.instance().get_vm_by_uuid(vm_ref).info[name])
1336 def VM_set(self, name, session, vm_ref, value):
1337 xd = XendDomain.instance()
1338 dominfo = xd.get_vm_by_uuid(vm_ref)
1339 dominfo.info[name] = value
1340 return self._VM_save(dominfo)
1342 def _VM_save(self, dominfo):
1343 XendDomain.instance().managed_config_save(dominfo)
1344 return xen_api_success_void()
1346 # attributes (ro)
1347 def VM_get_power_state(self, session, vm_ref):
1348 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1349 return xen_api_success(dom.get_power_state())
1351 def VM_get_resident_on(self, session, vm_ref):
1352 return xen_api_success(XendNode.instance().uuid)
1354 def VM_get_memory_static_max(self, session, vm_ref):
1355 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1356 return xen_api_success(dom.get_memory_static_max())
1358 def VM_get_memory_static_min(self, session, vm_ref):
1359 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1360 return xen_api_success(dom.get_memory_static_min())
1362 def VM_get_VIFs(self, session, vm_ref):
1363 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1364 return xen_api_success(dom.get_vifs())
1366 def VM_get_VBDs(self, session, vm_ref):
1367 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1368 return xen_api_success(dom.get_vbds())
1370 def VM_get_VTPMs(self, session, vm_ref):
1371 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1372 return xen_api_success(dom.get_vtpms())
1374 def VM_get_consoles(self, session, vm_ref):
1375 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1376 return xen_api_success(dom.get_consoles())
1378 def VM_get_tools_version(self, session, vm_ref):
1379 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1380 return dom.get_tools_version()
1382 def VM_get_metrics(self, _, vm_ref):
1383 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1384 return xen_api_success(dom.get_metrics())
1386 def VM_get_VCPUs_max(self, _, vm_ref):
1387 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1388 return xen_api_todo()
1390 def VM_get_VCPUs_at_startup(self, _, vm_ref):
1391 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1392 return xen_api_todo()
1394 # attributes (rw)
1395 def VM_get_name_label(self, session, vm_ref):
1396 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1397 return xen_api_success(dom.getName())
1399 def VM_get_name_description(self, session, vm_ref):
1400 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1401 return xen_api_todo()
1403 def VM_get_user_version(self, session, vm_ref):
1404 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1405 return xen_api_todo()
1407 def VM_get_is_a_template(self, session, ref):
1408 return self.VM_get('is_a_template', session, ref)
1410 def VM_get_memory_dynamic_max(self, session, vm_ref):
1411 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1412 return xen_api_success(dom.get_memory_dynamic_max())
1414 def VM_get_memory_dynamic_min(self, session, vm_ref):
1415 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1416 return xen_api_success(dom.get_memory_dynamic_min())
1418 def VM_get_VCPUs_params(self, session, vm_ref):
1419 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1420 return xen_api_success(dom.get_vcpus_params())
1422 def VM_get_actions_after_shutdown(self, session, vm_ref):
1423 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1424 return xen_api_success(dom.get_on_shutdown())
1426 def VM_get_actions_after_reboot(self, session, vm_ref):
1427 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1428 return xen_api_success(dom.get_on_reboot())
1430 def VM_get_actions_after_suspend(self, session, vm_ref):
1431 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1432 return xen_api_success(dom.get_on_suspend())
1434 def VM_get_actions_after_crash(self, session, vm_ref):
1435 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1436 return xen_api_success(dom.get_on_crash())
1438 def VM_get_PV_bootloader(self, session, vm_ref):
1439 return self.VM_get('PV_bootloader', session, vm_ref)
1441 def VM_get_PV_kernel(self, session, vm_ref):
1442 return self.VM_get('PV_kernel', session, vm_ref)
1444 def VM_get_PV_ramdisk(self, session, vm_ref):
1445 return self.VM_get('PV_ramdisk', session, vm_ref)
1447 def VM_get_PV_args(self, session, vm_ref):
1448 return self.VM_get('PV_args', session, vm_ref)
1450 def VM_get_PV_bootloader_args(self, session, vm_ref):
1451 return self.VM_get('PV_bootloader_args', session, vm_ref)
1453 def VM_get_HVM_boot_policy(self, session, vm_ref):
1454 return self.VM_get('HVM_boot_policy', session, vm_ref)
1456 def VM_get_HVM_boot_params(self, session, vm_ref):
1457 return self.VM_get('HVM_boot_params', session, vm_ref)
1459 def VM_get_platform(self, session, vm_ref):
1460 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1461 return xen_api_success(dom.get_platform())
1463 def VM_get_PCI_bus(self, session, vm_ref):
1464 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1465 return dom.get_pci_bus()
1467 def VM_set_PCI_bus(self, session, vm_ref, val):
1468 return self.VM_set('PCI_bus', session, vm_ref, val)
1470 def VM_get_other_config(self, session, vm_ref):
1471 return self.VM_get('other_config', session, vm_ref)
1473 def VM_get_domid(self, _, ref):
1474 domid = XendDomain.instance().get_vm_by_uuid(ref).getDomid()
1475 return xen_api_success(domid is None and -1 or domid)
1477 def VM_get_is_control_domain(self, session, vm_ref):
1478 xd = XendDomain.instance()
1479 return xen_api_success(
1480 xd.get_vm_by_uuid(vm_ref) == xd.privilegedDomain())
1482 def VM_set_name_label(self, session, vm_ref, label):
1483 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1484 dom.setName(label)
1485 return self._VM_save(dom)
1487 def VM_set_name_description(self, session, vm_ref, desc):
1488 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1489 return xen_api_todo()
1491 def VM_set_user_version(self, session, vm_ref, ver):
1492 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1493 return xen_api_todo()
1495 def VM_set_is_a_template(self, session, vm_ref, is_template):
1496 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1497 return xen_api_todo()
1499 def VM_set_memory_dynamic_max(self, session, vm_ref, mem):
1500 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1501 dom.set_memory_dynamic_max(int(mem))
1502 return xen_api_success_void()
1504 def VM_set_memory_dynamic_min(self, session, vm_ref, mem):
1505 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1506 dom.set_memory_dynamic_min(int(mem))
1507 return xen_api_success_void()
1509 def VM_set_memory_static_max(self, session, vm_ref, mem):
1510 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1511 dom.set_memory_static_max(int(mem))
1512 return xen_api_success_void()
1514 def VM_set_memory_static_min(self, session, vm_ref, mem):
1515 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1516 dom.set_memory_static_min(int(mem))
1517 return xen_api_success_void()
1519 def VM_set_memory_dynamic_max_live(self, session, vm_ref, mem):
1520 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1521 dom.set_memory_dynamic_max(int(mem))
1522 # need to pass target as MiB
1523 dom.setMemoryTarget(int(mem)/1024/1024)
1524 return xen_api_success_void()
1526 def VM_set_memory_dynamic_min_live(self, session, vm_ref, mem):
1527 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1528 dom.set_memory_dynamic_min(int(mem))
1529 # need to pass target as MiB
1530 dom.setMemoryTarget(int(mem)/1024/1024)
1531 return xen_api_success_void()
1533 def VM_set_VCPUs_params(self, session, vm_ref, value):
1534 return self.VM_set('vcpus_params', session, vm_ref, value)
1536 def VM_add_to_VCPUs_params(self, session, vm_ref, key, value):
1537 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1538 if 'vcpus_params' not in dom.info:
1539 dom.info['vcpus_params'] = {}
1540 dom.info['vcpus_params'][key] = value
1541 return self._VM_save(dom)
1543 def VM_add_to_VCPUs_params_live(self, session, vm_ref, key, value):
1544 self.VM_add_to_VCPUs_params(session, vm_ref, key, value)
1545 self._VM_VCPUs_params_refresh(vm_ref)
1546 return xen_api_success_void()
1548 def _VM_VCPUs_params_refresh(self, vm_ref):
1549 xendom = XendDomain.instance()
1550 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1552 #update the cpumaps
1553 for key, value in xeninfo.info['vcpus_params'].items():
1554 if key.startswith("cpumap"):
1555 vcpu = int(key[6:])
1556 try:
1557 cpus = map(int, value.split(","))
1558 xendom.domain_pincpu(xeninfo.getDomid(), vcpu, cpus)
1559 except Exception, ex:
1560 log.exception(ex)
1562 #need to update sched params aswell
1563 if 'weight' in xeninfo.info['vcpus_params'] \
1564 and 'cap' in xeninfo.info['vcpus_params']:
1565 weight = xeninfo.info['vcpus_params']['weight']
1566 cap = xeninfo.info['vcpus_params']['cap']
1567 xendom.domain_sched_credit_set(xeninfo.getDomid(), weight, cap)
1569 def VM_set_VCPUs_number_live(self, _, vm_ref, num):
1570 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1571 dom.setVCpuCount(int(num))
1572 return xen_api_success_void()
1574 def VM_remove_from_VCPUs_params(self, session, vm_ref, key):
1575 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1576 if 'vcpus_params' in dom.info \
1577 and key in dom.info['vcpus_params']:
1578 del dom.info['vcpus_params'][key]
1579 return self._VM_save(dom)
1580 else:
1581 return xen_api_success_void()
1583 def VM_set_actions_after_shutdown(self, session, vm_ref, action):
1584 if action not in XEN_API_ON_NORMAL_EXIT:
1585 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1586 return self.VM_set('actions_after_shutdown', session, vm_ref, action)
1588 def VM_set_actions_after_reboot(self, session, vm_ref, action):
1589 if action not in XEN_API_ON_NORMAL_EXIT:
1590 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1591 return self.VM_set('actions_after_reboot', session, vm_ref, action)
1593 def VM_set_actions_after_suspend(self, session, vm_ref, action):
1594 if action not in XEN_API_ON_NORMAL_EXIT:
1595 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1596 return self.VM_set('actions_after_suspend', session, vm_ref, action)
1598 def VM_set_actions_after_crash(self, session, vm_ref, action):
1599 if action not in XEN_API_ON_CRASH_BEHAVIOUR:
1600 return xen_api_error(['VM_ON_CRASH_BEHAVIOUR_INVALID', vm_ref])
1601 return self.VM_set('actions_after_crash', session, vm_ref, action)
1603 def VM_set_HVM_boot_policy(self, session, vm_ref, value):
1604 if value != "" and value != "BIOS order":
1605 return xen_api_error(
1606 ['VALUE_NOT_SUPPORTED', 'VM.HVM_boot_policy', value,
1607 'Xend supports only the "BIOS order" boot policy.'])
1608 else:
1609 return self.VM_set('HVM_boot_policy', session, vm_ref, value)
1611 def VM_set_HVM_boot_params(self, session, vm_ref, value):
1612 return self.VM_set('HVM_boot_params', session, vm_ref, value)
1614 def VM_add_to_HVM_boot_params(self, session, vm_ref, key, value):
1615 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1616 if 'HVM_boot_params' not in dom.info:
1617 dom.info['HVM_boot_params'] = {}
1618 dom.info['HVM_boot_params'][key] = value
1619 return self._VM_save(dom)
1621 def VM_remove_from_HVM_boot_params(self, session, vm_ref, key):
1622 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1623 if 'HVM_boot_params' in dom.info \
1624 and key in dom.info['HVM_boot_params']:
1625 del dom.info['HVM_boot_params'][key]
1626 return self._VM_save(dom)
1627 else:
1628 return xen_api_success_void()
1630 def VM_set_PV_bootloader(self, session, vm_ref, value):
1631 return self.VM_set('PV_bootloader', session, vm_ref, value)
1633 def VM_set_PV_kernel(self, session, vm_ref, value):
1634 return self.VM_set('PV_kernel', session, vm_ref, value)
1636 def VM_set_PV_ramdisk(self, session, vm_ref, value):
1637 return self.VM_set('PV_ramdisk', session, vm_ref, value)
1639 def VM_set_PV_args(self, session, vm_ref, value):
1640 return self.VM_set('PV_args', session, vm_ref, value)
1642 def VM_set_PV_bootloader_args(self, session, vm_ref, value):
1643 return self.VM_set('PV_bootloader_args', session, vm_ref, value)
1645 def VM_set_platform(self, session, vm_ref, value):
1646 return self.VM_set('platform', session, vm_ref, value)
1648 def VM_add_to_platform(self, session, vm_ref, key, value):
1649 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1650 plat = dom.get_platform()
1651 plat[key] = value
1652 return self.VM_set_platform(session, vm_ref, plat)
1654 def VM_remove_from_platform(self, session, vm_ref, key):
1655 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1656 plat = dom.get_platform()
1657 if key in plat:
1658 del plat[key]
1659 return self.VM_set_platform(session, vm_ref, plat)
1660 else:
1661 return xen_api_success_void()
1663 def VM_set_other_config(self, session, vm_ref, value):
1664 return self.VM_set('other_config', session, vm_ref, value)
1666 def VM_add_to_other_config(self, session, vm_ref, key, value):
1667 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1668 if dom and 'other_config' in dom.info:
1669 dom.info['other_config'][key] = value
1670 return self._VM_save(dom)
1672 def VM_remove_from_other_config(self, session, vm_ref, key):
1673 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1674 if dom and 'other_config' in dom.info \
1675 and key in dom.info['other_config']:
1676 del dom.info['other_config'][key]
1677 return self._VM_save(dom)
1678 else:
1679 return xen_api_success_void()
1681 # class methods
1682 def VM_get_all(self, session):
1683 refs = [d.get_uuid() for d in XendDomain.instance().list('all')]
1684 return xen_api_success(refs)
1686 def VM_get_by_name_label(self, session, label):
1687 xendom = XendDomain.instance()
1688 dom = xendom.domain_lookup_nr(label)
1689 if dom:
1690 return xen_api_success([dom.get_uuid()])
1691 return xen_api_success([])
1693 def VM_create(self, session, vm_struct):
1694 xendom = XendDomain.instance()
1695 domuuid = XendTask.log_progress(0, 100,
1696 xendom.create_domain, vm_struct)
1697 return xen_api_success(domuuid)
1699 # object methods
1700 def VM_get_record(self, session, vm_ref):
1701 xendom = XendDomain.instance()
1702 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1703 if not xeninfo:
1704 return xen_api_error(['HANDLE_INVALID', 'VM', vm_ref])
1706 domid = xeninfo.getDomid()
1708 record = {
1709 'uuid': xeninfo.get_uuid(),
1710 'power_state': xeninfo.get_power_state(),
1711 'name_label': xeninfo.getName(),
1712 'name_description': xeninfo.getName(),
1713 'user_version': 1,
1714 'is_a_template': xeninfo.info['is_a_template'],
1715 'auto_power_on': False,
1716 'resident_on': XendNode.instance().uuid,
1717 'memory_static_min': xeninfo.get_memory_static_min(),
1718 'memory_static_max': xeninfo.get_memory_static_max(),
1719 'memory_dynamic_min': xeninfo.get_memory_dynamic_min(),
1720 'memory_dynamic_max': xeninfo.get_memory_dynamic_max(),
1721 'VCPUs_params': xeninfo.get_vcpus_params(),
1722 'VCPUs_at_startup': xeninfo.getVCpuCount(),
1723 'VCPUs_max': xeninfo.getVCpuCount(),
1724 'actions_after_shutdown': xeninfo.get_on_shutdown(),
1725 'actions_after_reboot': xeninfo.get_on_reboot(),
1726 'actions_after_suspend': xeninfo.get_on_suspend(),
1727 'actions_after_crash': xeninfo.get_on_crash(),
1728 'consoles': xeninfo.get_consoles(),
1729 'VIFs': xeninfo.get_vifs(),
1730 'VBDs': xeninfo.get_vbds(),
1731 'VTPMs': xeninfo.get_vtpms(),
1732 'PV_bootloader': xeninfo.info.get('PV_bootloader'),
1733 'PV_kernel': xeninfo.info.get('PV_kernel'),
1734 'PV_ramdisk': xeninfo.info.get('PV_ramdisk'),
1735 'PV_args': xeninfo.info.get('PV_args'),
1736 'PV_bootloader_args': xeninfo.info.get('PV_bootloader_args'),
1737 'HVM_boot_policy': xeninfo.info.get('HVM_boot_policy'),
1738 'HVM_boot_params': xeninfo.info.get('HVM_boot_params'),
1739 'platform': xeninfo.get_platform(),
1740 'PCI_bus': xeninfo.get_pci_bus(),
1741 'tools_version': xeninfo.get_tools_version(),
1742 'other_config': xeninfo.info.get('other_config', {}),
1743 'domid': domid is None and -1 or domid,
1744 'is_control_domain': xeninfo.info['is_control_domain'],
1745 'metrics': xeninfo.get_metrics()
1747 return xen_api_success(record)
1749 def VM_clean_reboot(self, session, vm_ref):
1750 xendom = XendDomain.instance()
1751 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1752 XendTask.log_progress(0, 100, xeninfo.shutdown, "reboot")
1753 return xen_api_success_void()
1755 def VM_clean_shutdown(self, session, vm_ref):
1756 xendom = XendDomain.instance()
1757 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1758 XendTask.log_progress(0, 100, xeninfo.shutdown, "poweroff")
1759 return xen_api_success_void()
1761 def VM_clone(self, session, vm_ref):
1762 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1764 def VM_destroy(self, session, vm_ref):
1765 return XendTask.log_progress(0, 100, do_vm_func,
1766 "domain_delete", vm_ref)
1768 def VM_hard_reboot(self, session, vm_ref):
1769 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1771 def VM_hard_shutdown(self, session, vm_ref):
1772 return XendTask.log_progress(0, 100, do_vm_func,
1773 "domain_destroy", vm_ref)
1774 def VM_pause(self, session, vm_ref):
1775 return XendTask.log_progress(0, 100, do_vm_func,
1776 "domain_pause", vm_ref)
1778 def VM_resume(self, session, vm_ref, start_paused):
1779 return XendTask.log_progress(0, 100, do_vm_func,
1780 "domain_resume", vm_ref,
1781 start_paused = start_paused)
1783 def VM_start(self, session, vm_ref, start_paused):
1784 try:
1785 return XendTask.log_progress(0, 100, do_vm_func,
1786 "domain_start", vm_ref,
1787 start_paused = start_paused)
1788 except HVMRequired, exn:
1789 return xen_api_error(['VM_HVM_REQUIRED', vm_ref])
1791 def VM_suspend(self, session, vm_ref):
1792 return XendTask.log_progress(0, 100, do_vm_func,
1793 "domain_suspend", vm_ref)
1795 def VM_unpause(self, session, vm_ref):
1796 return XendTask.log_progress(0, 100, do_vm_func,
1797 "domain_unpause", vm_ref)
1799 def VM_send_sysrq(self, _, vm_ref, req):
1800 xeninfo = XendDomain.instance().get_vm_by_uuid(vm_ref)
1801 if xeninfo.state == XEN_API_VM_POWER_STATE_RUNNING \
1802 or xeninfo.state == XEN_API_VM_POWER_STATE_PAUSED:
1803 xeninfo.send_sysrq(req)
1804 return xen_api_success_void()
1805 else:
1806 return xen_api_error(
1807 ['VM_BAD_POWER_STATE', vm_ref,
1808 XendDomain.POWER_STATE_NAMES[XEN_API_VM_POWER_STATE_RUNNING],
1809 XendDomain.POWER_STATE_NAMES[xeninfo.state]])
1811 def VM_send_trigger(self, _, vm_ref, trigger, vcpu):
1812 xendom = XendDomain.instance()
1813 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1814 xendom.domain_send_trigger(xeninfo.getDomid(), trigger, vcpu)
1815 return xen_api_success_void()
1817 def VM_save(self, _, vm_ref, dest, checkpoint):
1818 xendom = XendDomain.instance()
1819 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1820 xendom.domain_save(xeninfo.getDomid(), dest, checkpoint)
1821 return xen_api_success_void()
1823 def VM_restore(self, _, src, paused):
1824 xendom = XendDomain.instance()
1825 xendom.domain_restore(src, bool(paused))
1826 return xen_api_success_void()
1829 # Xen API: Class VM_metrics
1830 # ----------------------------------------------------------------
1832 VM_metrics_attr_ro = ['memory_actual',
1833 'VCPUs_number',
1834 'VCPUs_utilisation',
1835 'VCPUs_CPU',
1836 'VCPUs_flags',
1837 'VCPUs_params',
1838 'state',
1839 'start_time',
1840 'last_updated']
1841 VM_metrics_attr_rw = []
1842 VM_metrics_methods = []
1844 def _VM_metrics_get(self, _, ref):
1845 return XendVMMetrics.get_by_uuid(ref)
1847 def VM_metrics_get_all(self, _):
1848 return xen_api_success(XendVMMetrics.get_all())
1851 # Xen API: Class VBD
1852 # ----------------------------------------------------------------
1854 VBD_attr_ro = ['VM',
1855 'VDI',
1856 'metrics',
1857 'runtime_properties']
1858 VBD_attr_rw = ['device',
1859 'bootable',
1860 'mode',
1861 'type']
1863 VBD_attr_inst = VBD_attr_rw
1865 VBD_methods = [('media_change', None), ('destroy', None)]
1866 VBD_funcs = [('create', 'VBD')]
1868 # object methods
1869 def VBD_get_record(self, session, vbd_ref):
1870 xendom = XendDomain.instance()
1871 vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1872 if not vm:
1873 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1874 cfg = vm.get_dev_xenapi_config('vbd', vbd_ref)
1875 if not cfg:
1876 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1878 valid_vbd_keys = self.VBD_attr_ro + self.VBD_attr_rw + \
1879 self.Base_attr_ro + self.Base_attr_rw
1881 return_cfg = {}
1882 for k in cfg.keys():
1883 if k in valid_vbd_keys:
1884 return_cfg[k] = cfg[k]
1886 return_cfg['metrics'] = vbd_ref
1888 return xen_api_success(return_cfg)
1890 def VBD_media_change(self, session, vbd_ref, vdi_ref):
1891 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1893 # class methods
1894 def VBD_create(self, session, vbd_struct):
1895 xendom = XendDomain.instance()
1896 xennode = XendNode.instance()
1898 if not xendom.is_valid_vm(vbd_struct['VM']):
1899 return xen_api_error(['HANDLE_INVALID', 'VM', vbd_struct['VM']])
1901 dom = xendom.get_vm_by_uuid(vbd_struct['VM'])
1902 vdi = xennode.get_vdi_by_uuid(vbd_struct['VDI'])
1903 if not vdi:
1904 return xen_api_error(['HANDLE_INVALID', 'VDI', vdi_ref])
1906 # new VBD via VDI/SR
1907 vdi_image = vdi.get_location()
1909 try:
1910 vbd_ref = XendTask.log_progress(0, 100,
1911 dom.create_vbd,
1912 vbd_struct, vdi_image)
1913 except XendError, e:
1914 log.exception("Error in VBD_create")
1915 return xen_api_error(['INTERNAL_ERROR', str(e)])
1917 vdi.addVBD(vbd_ref)
1919 xendom.managed_config_save(dom)
1920 return xen_api_success(vbd_ref)
1923 def VBD_destroy(self, session, vbd_ref):
1924 xendom = XendDomain.instance()
1925 vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1926 if not vm:
1927 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1929 vdi_ref = XendDomain.instance()\
1930 .get_dev_property_by_uuid('vbd', vbd_ref, "VDI")
1931 vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
1933 XendTask.log_progress(0, 100, vm.destroy_vbd, vbd_ref)
1935 vdi.removeVBD(vbd_ref)
1937 return xen_api_success_void()
1939 def _VBD_get(self, vbd_ref, prop):
1940 return xen_api_success(
1941 XendDomain.instance().get_dev_property_by_uuid(
1942 'vbd', vbd_ref, prop))
1944 # attributes (ro)
1945 def VBD_get_metrics(self, _, vbd_ref):
1946 return xen_api_success(vbd_ref)
1948 def VBD_get_runtime_properties(self, _, vbd_ref):
1949 xendom = XendDomain.instance()
1950 dominfo = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1951 device = dominfo.get_dev_config_by_uuid('vbd', vbd_ref)
1953 try:
1954 devid = int(device['id'])
1955 device_sxps = dominfo.getDeviceSxprs('vbd')
1956 device_dicts = [dict(device_sxp[1][1:]) for device_sxp in device_sxps]
1957 device_dict = [device_dict
1958 for device_dict in device_dicts
1959 if int(device_dict['virtual-device']) == devid][0]
1961 return xen_api_success(device_dict)
1962 except Exception, exn:
1963 log.exception(exn)
1964 return xen_api_success({})
1966 # attributes (rw)
1967 def VBD_get_VM(self, session, vbd_ref):
1968 return self._VBD_get(vbd_ref, 'VM')
1970 def VBD_get_VDI(self, session, vbd_ref):
1971 return self._VBD_get(vbd_ref, 'VDI')
1973 def VBD_get_device(self, session, vbd_ref):
1974 return self._VBD_get(vbd_ref, 'device')
1976 def VBD_get_bootable(self, session, vbd_ref):
1977 return self._VBD_get(vbd_ref, 'bootable')
1979 def VBD_get_mode(self, session, vbd_ref):
1980 return self._VBD_get(vbd_ref, 'mode')
1982 def VBD_get_type(self, session, vbd_ref):
1983 return self._VBD_get(vbd_ref, 'type')
1985 def VBD_set_bootable(self, session, vbd_ref, bootable):
1986 bootable = bool(bootable)
1987 xd = XendDomain.instance()
1988 vm = xd.get_vm_with_dev_uuid('vbd', vbd_ref)
1989 vm.set_dev_property('vbd', vbd_ref, 'bootable', bootable)
1990 xd.managed_config_save(vm)
1991 return xen_api_success_void()
1993 def VBD_get_all(self, session):
1994 xendom = XendDomain.instance()
1995 vbds = [d.get_vbds() for d in XendDomain.instance().list('all')]
1996 vbds = reduce(lambda x, y: x + y, vbds)
1997 return xen_api_success(vbds)
2000 # Xen API: Class VBD_metrics
2001 # ----------------------------------------------------------------
2003 VBD_metrics_attr_ro = ['io_read_kbs',
2004 'io_write_kbs',
2005 'last_updated']
2006 VBD_metrics_attr_rw = []
2007 VBD_metrics_methods = []
2009 def VBD_metrics_get_all(self, session):
2010 return self.VBD_get_all(session)
2012 def VBD_metrics_get_record(self, _, ref):
2013 vm = XendDomain.instance().get_vm_with_dev_uuid('vbd', ref)
2014 if not vm:
2015 return xen_api_error(['HANDLE_INVALID', 'VBD_metrics', ref])
2016 return xen_api_success(
2017 { 'io_read_kbs' : vm.get_dev_property('vbd', ref, 'io_read_kbs'),
2018 'io_write_kbs' : vm.get_dev_property('vbd', ref, 'io_write_kbs'),
2019 'last_updated' : now()
2020 })
2022 def VBD_metrics_get_io_read_kbs(self, _, ref):
2023 return self._VBD_get(ref, 'io_read_kbs')
2025 def VBD_metrics_get_io_write_kbs(self, session, ref):
2026 return self._VBD_get(ref, 'io_write_kbs')
2028 def VBD_metrics_get_last_updated(self, _1, _2):
2029 return xen_api_success(now())
2032 # Xen API: Class VIF
2033 # ----------------------------------------------------------------
2035 VIF_attr_ro = ['network',
2036 'VM',
2037 'metrics',
2038 'runtime_properties']
2039 VIF_attr_rw = ['device',
2040 'MAC',
2041 'MTU']
2043 VIF_attr_inst = VIF_attr_rw
2045 VIF_methods = [('destroy', None)]
2046 VIF_funcs = [('create', 'VIF')]
2049 # object methods
2050 def VIF_get_record(self, session, vif_ref):
2051 xendom = XendDomain.instance()
2052 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
2053 if not vm:
2054 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
2055 cfg = vm.get_dev_xenapi_config('vif', vif_ref)
2056 if not cfg:
2057 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
2059 valid_vif_keys = self.VIF_attr_ro + self.VIF_attr_rw + \
2060 self.Base_attr_ro + self.Base_attr_rw
2062 return_cfg = {}
2063 for k in cfg.keys():
2064 if k in valid_vif_keys:
2065 return_cfg[k] = cfg[k]
2067 return_cfg['metrics'] = vif_ref
2069 return xen_api_success(return_cfg)
2071 # class methods
2072 def VIF_create(self, session, vif_struct):
2073 xendom = XendDomain.instance()
2074 if not xendom.is_valid_vm(vif_struct['VM']):
2075 return xen_api_error(['HANDLE_INVALID', 'VM', vif_struct['VM']])
2077 dom = xendom.get_vm_by_uuid(vif_struct['VM'])
2078 try:
2079 vif_ref = dom.create_vif(vif_struct)
2080 xendom.managed_config_save(dom)
2081 return xen_api_success(vif_ref)
2082 except XendError, exn:
2083 return xen_api_error(['INTERNAL_ERROR', str(exn)])
2085 def VIF_destroy(self, session, vif_ref):
2086 xendom = XendDomain.instance()
2087 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
2088 if not vm:
2089 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
2091 vm.destroy_vif(vif_ref)
2092 return xen_api_success_void()
2094 def _VIF_get(self, ref, prop):
2095 return xen_api_success(
2096 XendDomain.instance().get_dev_property_by_uuid('vif', ref, prop))
2098 # getters/setters
2099 def VIF_get_metrics(self, _, vif_ref):
2100 return xen_api_success(vif_ref)
2102 def VIF_get_VM(self, session, vif_ref):
2103 xendom = XendDomain.instance()
2104 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
2105 return xen_api_success(vm.get_uuid())
2107 def VIF_get_MTU(self, session, vif_ref):
2108 return self._VIF_get(vif_ref, 'MTU')
2110 def VIF_get_MAC(self, session, vif_ref):
2111 return self._VIF_get(vif_ref, 'MAC')
2113 def VIF_get_device(self, session, vif_ref):
2114 return self._VIF_get(vif_ref, 'device')
2116 def VIF_get_all(self, session):
2117 xendom = XendDomain.instance()
2118 vifs = [d.get_vifs() for d in XendDomain.instance().list('all')]
2119 vifs = reduce(lambda x, y: x + y, vifs)
2120 return xen_api_success(vifs)
2122 def VIF_get_runtime_properties(self, _, vif_ref):
2123 xendom = XendDomain.instance()
2124 dominfo = xendom.get_vm_with_dev_uuid('vif', vif_ref)
2125 device = dominfo.get_dev_config_by_uuid('vif', vif_ref)
2127 try:
2128 devid = int(device['id'])
2130 device_sxps = dominfo.getDeviceSxprs('vif')
2131 device_dicts = [dict(device_sxp[1][1:])
2132 for device_sxp in device_sxps]
2134 device_dict = [device_dict
2135 for device_dict in device_dicts
2136 if int(device_dict['handle']) == devid][0]
2138 return xen_api_success(device_dict)
2140 except Exception, exn:
2141 log.exception(exn)
2142 return xen_api_success({})
2144 # Xen API: Class VIF_metrics
2145 # ----------------------------------------------------------------
2147 VIF_metrics_attr_ro = ['io_read_kbs',
2148 'io_write_kbs',
2149 'last_updated']
2150 VIF_metrics_attr_rw = []
2151 VIF_metrics_methods = []
2153 def VIF_metrics_get_all(self, session):
2154 return self.VIF_get_all(session)
2156 def VIF_metrics_get_record(self, _, ref):
2157 vm = XendDomain.instance().get_vm_with_dev_uuid('vif', ref)
2158 if not vm:
2159 return xen_api_error(['HANDLE_INVALID', 'VIF_metrics', ref])
2160 return xen_api_success(
2161 { 'io_read_kbs' : vm.get_dev_property('vif', ref, 'io_read_kbs'),
2162 'io_write_kbs' : vm.get_dev_property('vif', ref, 'io_write_kbs'),
2163 'last_updated' : now()
2164 })
2166 def VIF_metrics_get_io_read_kbs(self, _, ref):
2167 return self._VIF_get(ref, 'io_read_kbs')
2169 def VIF_metrics_get_io_write_kbs(self, session, ref):
2170 return self._VIF_get(ref, 'io_write_kbs')
2172 def VIF_metrics_get_last_updated(self, _1, _2):
2173 return xen_api_success(now())
2176 # Xen API: Class VDI
2177 # ----------------------------------------------------------------
2178 VDI_attr_ro = ['SR',
2179 'VBDs',
2180 'physical_utilisation',
2181 'type']
2182 VDI_attr_rw = ['name_label',
2183 'name_description',
2184 'virtual_size',
2185 'sharable',
2186 'read_only',
2187 'other_config']
2188 VDI_attr_inst = VDI_attr_ro + VDI_attr_rw
2190 VDI_methods = [('snapshot', 'VDI'), ('destroy', None)]
2191 VDI_funcs = [('create', 'VDI'),
2192 ('get_by_name_label', 'Set(VDI)')]
2194 def _get_VDI(self, ref):
2195 return XendNode.instance().get_vdi_by_uuid(ref)
2197 def VDI_get_VBDs(self, session, vdi_ref):
2198 vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
2199 return xen_api_success(vdi.getVBDs())
2201 def VDI_get_physical_utilisation(self, session, vdi_ref):
2202 return xen_api_success(self._get_VDI(vdi_ref).
2203 get_physical_utilisation())
2205 def VDI_get_type(self, session, vdi_ref):
2206 return xen_api_success(self._get_VDI(vdi_ref).type)
2208 def VDI_get_name_label(self, session, vdi_ref):
2209 return xen_api_success(self._get_VDI(vdi_ref).name_label)
2211 def VDI_get_name_description(self, session, vdi_ref):
2212 return xen_api_success(self._get_VDI(vdi_ref).name_description)
2214 def VDI_get_SR(self, session, vdi_ref):
2215 return xen_api_success(self._get_VDI(vdi_ref).sr_uuid)
2217 def VDI_get_virtual_size(self, session, vdi_ref):
2218 return xen_api_success(self._get_VDI(vdi_ref).virtual_size)
2220 def VDI_get_sharable(self, session, vdi_ref):
2221 return xen_api_success(self._get_VDI(vdi_ref).sharable)
2223 def VDI_get_read_only(self, session, vdi_ref):
2224 return xen_api_success(self._get_VDI(vdi_ref).read_only)
2226 def VDI_set_name_label(self, session, vdi_ref, value):
2227 self._get_VDI(vdi_ref).name_label = value
2228 return xen_api_success_void()
2230 def VDI_set_name_description(self, session, vdi_ref, value):
2231 self._get_VDI(vdi_ref).name_description = value
2232 return xen_api_success_void()
2234 def VDI_set_virtual_size(self, session, vdi_ref, value):
2235 return xen_api_error(XEND_ERROR_UNSUPPORTED)
2237 def VDI_set_sharable(self, session, vdi_ref, value):
2238 self._get_VDI(vdi_ref).sharable = bool(value)
2239 return xen_api_success_void()
2241 def VDI_set_read_only(self, session, vdi_ref, value):
2242 self._get_VDI(vdi_ref).read_only = bool(value)
2243 return xen_api_success_void()
2245 def VDI_get_other_config(self, session, vdi_ref):
2246 return xen_api_success(
2247 self._get_VDI(vdi_ref).other_config)
2249 def VDI_set_other_config(self, session, vdi_ref, other_config):
2250 self._get_VDI(vdi_ref).other_config = other_config
2251 return xen_api_success_void()
2253 # Object Methods
2254 def VDI_snapshot(self, session, vdi_ref):
2255 return xen_api_todo()
2257 def VDI_destroy(self, session, vdi_ref):
2258 sr = XendNode.instance().get_sr_containing_vdi(vdi_ref)
2259 sr.destroy_vdi(vdi_ref)
2260 return xen_api_success_void()
2262 def VDI_get_record(self, session, vdi_ref):
2263 image = XendNode.instance().get_vdi_by_uuid(vdi_ref)
2264 return xen_api_success({
2265 'uuid': vdi_ref,
2266 'name_label': image.name_label,
2267 'name_description': image.name_description,
2268 'SR': image.sr_uuid,
2269 'VBDs': image.getVBDs(),
2270 'virtual_size': image.virtual_size,
2271 'physical_utilisation': image.physical_utilisation,
2272 'type': image.type,
2273 'sharable': image.sharable,
2274 'read_only': image.read_only,
2275 'other_config': image.other_config
2276 })
2278 # Class Functions
2279 def VDI_create(self, session, vdi_struct):
2280 sr_ref = vdi_struct.get('SR')
2281 xennode = XendNode.instance()
2282 if not xennode.is_valid_sr(sr_ref):
2283 return xen_api_error(['HANDLE_INVALID', 'SR', sr_ref])
2285 vdi_uuid = xennode.srs[sr_ref].create_vdi(vdi_struct)
2286 return xen_api_success(vdi_uuid)
2288 def VDI_get_all(self, session):
2289 xennode = XendNode.instance()
2290 vdis = [sr.get_vdis() for sr in xennode.srs.values()]
2291 return xen_api_success(reduce(lambda x, y: x + y, vdis))
2293 def VDI_get_by_name_label(self, session, name):
2294 xennode = XendNode.instance()
2295 return xen_api_success(xennode.get_vdi_by_name_label(name))
2298 # Xen API: Class VTPM
2299 # ----------------------------------------------------------------
2301 VTPM_attr_rw = [ ]
2302 VTPM_attr_ro = ['VM',
2303 'backend']
2305 VTPM_attr_inst = VTPM_attr_rw
2307 VTPM_methods = [('destroy', None)]
2308 VTPM_funcs = [('create', 'VTPM')]
2310 # object methods
2311 def VTPM_get_record(self, session, vtpm_ref):
2312 xendom = XendDomain.instance()
2313 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
2314 if not vm:
2315 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
2316 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
2317 if not cfg:
2318 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
2319 valid_vtpm_keys = self.VTPM_attr_ro + self.VTPM_attr_rw + \
2320 self.Base_attr_ro + self.Base_attr_rw
2321 return_cfg = {}
2322 for k in cfg.keys():
2323 if k in valid_vtpm_keys:
2324 return_cfg[k] = cfg[k]
2326 return xen_api_success(return_cfg)
2328 # Class Functions
2329 def VTPM_get_backend(self, session, vtpm_ref):
2330 xendom = XendDomain.instance()
2331 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
2332 if not vm:
2333 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
2334 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
2335 if not cfg:
2336 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
2337 if not cfg.has_key('backend'):
2338 return xen_api_error(['VTPM backend not set'])
2339 return xen_api_success(cfg['backend'])
2341 def VTPM_get_VM(self, session, vtpm_ref):
2342 xendom = XendDomain.instance()
2343 return xen_api_success(xendom.get_dev_property_by_uuid('vtpm',
2344 vtpm_ref, 'VM'))
2346 def VTPM_destroy(self, session, vtpm_ref):
2347 xendom = XendDomain.instance()
2348 dom = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
2349 if dom:
2350 if dom.state != XEN_API_VM_POWER_STATE_HALTED:
2351 vm_ref = dom.get_dev_property('vtpm', vtpm_ref, 'VM')
2352 return xen_api_error(['VM_BAD_POWER_STATE', vm_ref,
2353 XendDomain.POWER_STATE_NAMES[XEN_API_VM_POWER_STATE_HALTED],
2354 XendDomain.POWER_STATE_NAMES[dom.state]])
2355 from xen.xend.server import tpmif
2356 tpmif.destroy_vtpmstate(dom.getName())
2357 return xen_api_success_void()
2358 else:
2359 return xen_api_error(['HANDLE_INVALID', 'VM', vtpm_struct['VM']])
2361 # class methods
2362 def VTPM_create(self, session, vtpm_struct):
2363 xendom = XendDomain.instance()
2364 if xendom.is_valid_vm(vtpm_struct['VM']):
2365 dom = xendom.get_vm_by_uuid(vtpm_struct['VM'])
2366 try:
2367 vtpm_ref = dom.create_vtpm(vtpm_struct)
2368 xendom.managed_config_save(dom)
2369 return xen_api_success(vtpm_ref)
2370 except XendError, exn:
2371 return xen_api_error(['INTERNAL_ERROR', str(exn)])
2372 else:
2373 return xen_api_error(['HANDLE_INVALID', 'VM', vtpm_struct['VM']])
2375 def VTPM_get_all(self, session):
2376 xendom = XendDomain.instance()
2377 vtpms = [d.get_vtpms() for d in XendDomain.instance().list('all')]
2378 vtpms = reduce(lambda x, y: x + y, vtpms)
2379 return xen_api_success(vtpms)
2381 # Xen API: Class console
2382 # ----------------------------------------------------------------
2385 console_attr_ro = ['location', 'protocol', 'VM']
2386 console_attr_rw = ['other_config']
2387 console_funcs = [('create', 'console')]
2389 def console_get_all(self, session):
2390 xendom = XendDomain.instance()
2391 cons = [d.get_consoles() for d in XendDomain.instance().list('all')]
2392 cons = reduce(lambda x, y: x + y, cons)
2393 return xen_api_success(cons)
2395 def console_get_location(self, session, console_ref):
2396 return xen_api_success(xendom.get_dev_property_by_uuid('console',
2397 console_ref,
2398 'location'))
2400 def console_get_protocol(self, session, console_ref):
2401 return xen_api_success(xendom.get_dev_property_by_uuid('console',
2402 console_ref,
2403 'protocol'))
2405 def console_get_VM(self, session, console_ref):
2406 xendom = XendDomain.instance()
2407 vm = xendom.get_vm_with_dev_uuid('console', console_ref)
2408 return xen_api_success(vm.get_uuid())
2410 # object methods
2411 def console_get_record(self, session, console_ref):
2412 xendom = XendDomain.instance()
2413 vm = xendom.get_vm_with_dev_uuid('console', console_ref)
2414 if not vm:
2415 return xen_api_error(['HANDLE_INVALID', 'console', console_ref])
2416 cfg = vm.get_dev_xenapi_config('console', console_ref)
2417 if not cfg:
2418 return xen_api_error(['HANDLE_INVALID', 'console', console_ref])
2420 valid_console_keys = self.console_attr_ro + self.console_attr_rw + \
2421 self.Base_attr_ro + self.Base_attr_rw
2423 return_cfg = {}
2424 for k in cfg.keys():
2425 if k in valid_console_keys:
2426 return_cfg[k] = cfg[k]
2428 return xen_api_success(return_cfg)
2430 def console_create(self, session, console_struct):
2431 xendom = XendDomain.instance()
2432 if not xendom.is_valid_vm(console_struct['VM']):
2433 return xen_api_error(['HANDLE_INVALID', 'VM',
2434 console_struct['VM']])
2436 dom = xendom.get_vm_by_uuid(console_struct['VM'])
2437 try:
2438 if 'protocol' not in console_struct:
2439 return xen_api_error(['CONSOLE_PROTOCOL_INVALID',
2440 'No protocol specified'])
2442 console_ref = dom.create_console(console_struct)
2443 xendom.managed_config_save(dom)
2444 return xen_api_success(console_ref)
2445 except XendError, exn:
2446 return xen_api_error(['INTERNAL_ERROR', str(exn)])
2448 # Xen API: Class SR
2449 # ----------------------------------------------------------------
2450 SR_attr_ro = ['VDIs',
2451 'virtual_allocation',
2452 'physical_utilisation',
2453 'physical_size',
2454 'type',
2455 'content_type']
2457 SR_attr_rw = ['name_label',
2458 'name_description']
2460 SR_attr_inst = ['physical_size',
2461 'type',
2462 'name_label',
2463 'name_description']
2465 SR_methods = []
2466 SR_funcs = [('get_by_name_label', 'Set(SR)'),
2467 ('get_by_uuid', 'SR')]
2469 # Class Functions
2470 def SR_get_all(self, session):
2471 return xen_api_success(XendNode.instance().get_all_sr_uuid())
2473 def SR_get_by_name_label(self, session, label):
2474 return xen_api_success(XendNode.instance().get_sr_by_name(label))
2476 def SR_get_supported_types(self, _):
2477 return xen_api_success(['local', 'qcow_file'])
2479 # Class Methods
2481 def SR_get_record(self, session, sr_ref):
2482 sr = XendNode.instance().get_sr(sr_ref)
2483 if sr:
2484 return xen_api_success(sr.get_record())
2485 return xen_api_error(['HANDLE_INVALID', 'SR', sr_ref])
2487 # Attribute acceess
2489 def _get_SR_func(self, sr_ref, func):
2490 return xen_api_success(getattr(XendNode.instance().get_sr(sr_ref),
2491 func)())
2493 def _get_SR_attr(self, sr_ref, attr):
2494 return xen_api_success(getattr(XendNode.instance().get_sr(sr_ref),
2495 attr))
2497 def SR_get_VDIs(self, _, ref):
2498 return self._get_SR_func(ref, 'list_images')
2500 def SR_get_virtual_allocation(self, _, ref):
2501 return self._get_SR_func(ref, 'virtual_allocation')
2503 def SR_get_physical_utilisation(self, _, ref):
2504 return self._get_SR_func(ref, 'physical_utilisation')
2506 def SR_get_physical_size(self, _, ref):
2507 return self._get_SR_func(ref, 'physical_size')
2509 def SR_get_type(self, _, ref):
2510 return self._get_SR_attr(ref, 'type')
2512 def SR_get_content_type(self, _, ref):
2513 return self._get_SR_attr(ref, 'content_type')
2515 def SR_get_name_label(self, _, ref):
2516 return self._get_SR_attr(ref, 'name_label')
2518 def SR_get_name_description(self, _, ref):
2519 return self._get_SR_attr(ref, 'name_description')
2521 def SR_set_name_label(self, session, sr_ref, value):
2522 sr = XendNode.instance.get_sr(sr_ref)
2523 if sr:
2524 sr.name_label = value
2525 XendNode.instance().save()
2526 return xen_api_success_void()
2528 def SR_set_name_description(self, session, sr_ref, value):
2529 sr = XendNode.instance.get_sr(sr_ref)
2530 if sr:
2531 sr.name_description = value
2532 XendNode.instance().save()
2533 return xen_api_success_void()
2536 # Xen API: Class PBD
2537 # ----------------------------------------------------------------
2539 PBD_attr_ro = ['host',
2540 'SR',
2541 'device_config',
2542 'currently_attached']
2543 PBD_attr_rw = []
2544 PBD_methods = [('destroy', None)]
2545 PBD_funcs = [('create', None)]
2547 def PBD_get_all(self, _):
2548 return xen_api_success(XendPBD.get_all_refs())
2550 def _PBD_get(self, _, ref):
2551 return XendPBD.get(ref)
2553 def PBD_create(self, _, record):
2554 if 'uuid' in record:
2555 return xen_api_error(['VALUE_NOT_SUPPORTED',
2556 'uuid', record['uuid'],
2557 'You may not specify a UUID on creation'])
2558 new_uuid = XendPBD.XendPBD(record).get_uuid()
2559 XendNode.instance().save()
2560 return xen_api_success(new_uuid)
2563 # Xen API: Class event
2564 # ----------------------------------------------------------------
2566 event_attr_ro = []
2567 event_attr_rw = []
2568 event_funcs = [('register', None),
2569 ('unregister', None),
2570 ('next', None)]
2572 def event_register(self, session, reg_classes):
2573 event_register(session, reg_classes)
2574 return xen_api_success_void()
2576 def event_unregister(self, session, unreg_classes):
2577 event_unregister(session, reg_classes)
2578 return xen_api_success_void()
2580 def event_next(self, session):
2581 return event_next(session)
2583 # Xen API: Class debug
2584 # ----------------------------------------------------------------
2586 debug_methods = [('destroy', None),
2587 ('get_record', 'debug')]
2588 debug_funcs = [('wait', None),
2589 ('return_failure', None)]
2591 def debug_wait(self, session, wait_secs):
2592 import time
2593 prog_units = 100/float(wait_secs)
2594 for i in range(int(wait_secs)):
2595 XendTask.log_progress(prog_units * i, prog_units * (i + 1),
2596 time.sleep, 1)
2597 return xen_api_success_void()
2600 def debug_return_failure(self, session):
2601 return xen_api_error(['DEBUG_FAIL', session])
2603 def debug_create(self, session):
2604 debug_uuid = uuid.createString()
2605 self._debug[debug_uuid] = None
2606 return xen_api_success(debug_uuid)
2608 def debug_destroy(self, session, debug_ref):
2609 del self._debug[debug_ref]
2610 return xen_api_success_void()
2612 def debug_get_record(self, session, debug_ref):
2613 return xen_api_success({'uuid': debug_ref})
2616 def list_all_methods(self, _):
2617 def _funcs():
2618 return [getattr(XendAPI, x) for x in XendAPI.__dict__]
2620 return xen_api_success([x.api for x in _funcs()
2621 if hasattr(x, 'api')])
2622 list_all_methods.api = '_UNSUPPORTED_list_all_methods'
2625 class XendAPIAsyncProxy:
2626 """ A redirector for Async.Class.function calls to XendAPI
2627 but wraps the call for use with the XendTaskManager.
2629 @ivar xenapi: Xen API instance
2630 @ivar method_map: Mapping from XMLRPC method name to callable objects.
2631 """
2633 method_prefix = 'Async.'
2635 def __init__(self, xenapi):
2636 """Initialises the Async Proxy by making a map of all
2637 implemented Xen API methods for use with XendTaskManager.
2639 @param xenapi: XendAPI instance
2640 """
2641 self.xenapi = xenapi
2642 self.method_map = {}
2643 for method_name in dir(self.xenapi):
2644 method = getattr(self.xenapi, method_name)
2645 if method_name[0] != '_' and hasattr(method, 'async') \
2646 and method.async == True:
2647 self.method_map[method.api] = method
2649 def _dispatch(self, method, args):
2650 """Overridden method so that SimpleXMLRPCServer will
2651 resolve methods through this method rather than through
2652 inspection.
2654 @param method: marshalled method name from XMLRPC.
2655 @param args: marshalled arguments from XMLRPC.
2656 """
2658 # Only deal with method names that start with "Async."
2659 if not method.startswith(self.method_prefix):
2660 return xen_api_error(['MESSAGE_METHOD_UNKNOWN', method])
2662 # Lookup synchronous version of the method
2663 synchronous_method_name = method[len(self.method_prefix):]
2664 if synchronous_method_name not in self.method_map:
2665 return xen_api_error(['MESSAGE_METHOD_UNKNOWN', method])
2667 method = self.method_map[synchronous_method_name]
2669 # Check that we've got enough arguments before issuing a task ID.
2670 needed = argcounts[method.api]
2671 if len(args) != needed:
2672 return xen_api_error(['MESSAGE_PARAMETER_COUNT_MISMATCH',
2673 self.method_prefix + method.api, needed,
2674 len(args)])
2676 # Validate the session before proceeding
2677 session = args[0]
2678 if not auth_manager().is_session_valid(session):
2679 return xen_api_error(['SESSION_INVALID', session])
2681 # create and execute the task, and return task_uuid
2682 return_type = getattr(method, 'return_type', None)
2683 task_uuid = XendTaskManager.create_task(method, args,
2684 synchronous_method_name,
2685 return_type,
2686 synchronous_method_name,
2687 session)
2688 return xen_api_success(task_uuid)