ia64/xen-unstable

view tools/python/xen/xend/XendAPI.py @ 15656:e63b331d8698

Fix Xen API console methods that use undefined variables.
Signed-off-by: Jim Fehlig <jfehlig@novell.com>
author kfraser@localhost.localdomain
date Fri Jul 27 09:06:10 2007 +0100 (2007-07-27)
parents f1aed243f3f0
children 2450743f51b2
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, XendAPIStore
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
41 from XendPIF import XendPIF
42 from XendPBD import XendPBD
43 from XendXSPolicy import XendXSPolicy, XendACMPolicy
45 from XendAPIConstants import *
46 from xen.util.xmlrpclib2 import stringify
48 from xen.util.blkif import blkdev_name_to_number
49 from xen.util import xsconstants
52 AUTH_NONE = 'none'
53 AUTH_PAM = 'pam'
55 argcounts = {}
57 # ------------------------------------------
58 # Utility Methods for Xen API Implementation
59 # ------------------------------------------
61 def xen_api_success(value):
62 """Wraps a return value in XenAPI format."""
63 if value is None:
64 s = ''
65 else:
66 s = stringify(value)
67 return {"Status": "Success", "Value": s}
69 def xen_api_success_void():
70 """Return success, but caller expects no return value."""
71 return xen_api_success("")
73 def xen_api_error(error):
74 """Wraps an error value in XenAPI format."""
75 if type(error) == tuple:
76 error = list(error)
77 if type(error) != list:
78 error = [error]
79 if len(error) == 0:
80 error = ['INTERNAL_ERROR', 'Empty list given to xen_api_error']
82 return { "Status": "Failure",
83 "ErrorDescription": [str(x) for x in error] }
86 def xen_api_todo():
87 """Temporary method to make sure we track down all the TODOs"""
88 return {"Status": "Error", "ErrorDescription": XEND_ERROR_TODO}
91 def now():
92 return datetime()
95 def datetime(when = None):
96 """Marshall the given time as a Xen-API DateTime.
98 @param when The time in question, given as seconds since the epoch, UTC.
99 May be None, in which case the current time is used.
100 """
101 if when is None:
102 return xmlrpclib.DateTime(time.gmtime())
103 else:
104 return xmlrpclib.DateTime(time.gmtime(when))
107 # ---------------------------------------------------
108 # Event dispatch
109 # ---------------------------------------------------
111 EVENT_QUEUE_LENGTH = 50
112 event_registrations = {}
114 def event_register(session, reg_classes):
115 if session not in event_registrations:
116 event_registrations[session] = {
117 'classes' : sets.Set(),
118 'queue' : Queue.Queue(EVENT_QUEUE_LENGTH),
119 'next-id' : 1
120 }
121 if not reg_classes:
122 reg_classes = classes
123 event_registrations[session]['classes'].union_update(reg_classes)
126 def event_unregister(session, unreg_classes):
127 if session not in event_registrations:
128 return
130 if unreg_classes:
131 event_registrations[session]['classes'].intersection_update(
132 unreg_classes)
133 if len(event_registrations[session]['classes']) == 0:
134 del event_registrations[session]
135 else:
136 del event_registrations[session]
139 def event_next(session):
140 if session not in event_registrations:
141 return xen_api_error(['SESSION_NOT_REGISTERED', session])
142 queue = event_registrations[session]['queue']
143 events = [queue.get()]
144 try:
145 while True:
146 events.append(queue.get(False))
147 except Queue.Empty:
148 pass
150 return xen_api_success(events)
153 def _ctor_event_dispatch(xenapi, ctor, api_cls, session, args):
154 result = ctor(xenapi, session, *args)
155 if result['Status'] == 'Success':
156 ref = result['Value']
157 event_dispatch('add', api_cls, ref, '')
158 return result
161 def _dtor_event_dispatch(xenapi, dtor, api_cls, session, ref, args):
162 result = dtor(xenapi, session, ref, *args)
163 if result['Status'] == 'Success':
164 event_dispatch('del', api_cls, ref, '')
165 return result
168 def _setter_event_dispatch(xenapi, setter, api_cls, attr_name, session, ref,
169 args):
170 result = setter(xenapi, session, ref, *args)
171 if result['Status'] == 'Success':
172 event_dispatch('mod', api_cls, ref, attr_name)
173 return result
176 def event_dispatch(operation, api_cls, ref, attr_name):
177 assert operation in ['add', 'del', 'mod']
178 event = {
179 'timestamp' : now(),
180 'class' : api_cls,
181 'operation' : operation,
182 'ref' : ref,
183 'obj_uuid' : ref,
184 'field' : attr_name,
185 }
186 for reg in event_registrations.values():
187 if api_cls in reg['classes']:
188 event['id'] = reg['next-id']
189 reg['next-id'] += 1
190 reg['queue'].put(event)
193 # ---------------------------------------------------
194 # Python Method Decorators for input value validation
195 # ---------------------------------------------------
197 def trace(func, api_name = ''):
198 """Decorator to trace XMLRPC Xen API methods.
200 @param func: function with any parameters
201 @param api_name: name of the api call for debugging.
202 """
203 if hasattr(func, 'api'):
204 api_name = func.api
205 def trace_func(self, *args, **kwargs):
206 log.debug('%s: %s' % (api_name, args))
207 return func(self, *args, **kwargs)
208 trace_func.api = api_name
209 return trace_func
212 def catch_typeerror(func):
213 """Decorator to catch any TypeErrors and translate them into Xen-API
214 errors.
216 @param func: function with params: (self, ...)
217 @rtype: callable object
218 """
219 def f(self, *args, **kwargs):
220 try:
221 return func(self, *args, **kwargs)
222 except TypeError, exn:
223 #log.exception('catch_typeerror')
224 if hasattr(func, 'api') and func.api in argcounts:
225 # Assume that if the argument count was wrong and if the
226 # exception was thrown inside this file, then it is due to an
227 # invalid call from the client, otherwise it's an internal
228 # error (which will be handled further up).
229 expected = argcounts[func.api]
230 actual = len(args) + len(kwargs)
231 if expected != actual:
232 tb = sys.exc_info()[2]
233 try:
234 sourcefile = traceback.extract_tb(tb)[-1][0]
235 if sourcefile == inspect.getsourcefile(XendAPI):
236 return xen_api_error(
237 ['MESSAGE_PARAMETER_COUNT_MISMATCH',
238 func.api, expected, actual])
239 finally:
240 del tb
241 raise
242 except XendAPIError, exn:
243 return xen_api_error(exn.get_api_error())
245 return f
248 def session_required(func):
249 """Decorator to verify if session is valid before calling method.
251 @param func: function with params: (self, session, ...)
252 @rtype: callable object
253 """
254 def check_session(self, session, *args, **kwargs):
255 if auth_manager().is_session_valid(session):
256 return func(self, session, *args, **kwargs)
257 else:
258 return xen_api_error(['SESSION_INVALID', session])
260 return check_session
263 def _is_valid_ref(ref, validator):
264 return type(ref) == str and validator(ref)
266 def _check_ref(validator, clas, func, api, session, ref, *args, **kwargs):
267 if _is_valid_ref(ref, validator):
268 return func(api, session, ref, *args, **kwargs)
269 else:
270 return xen_api_error(['HANDLE_INVALID', clas, ref])
273 def valid_host(func):
274 """Decorator to verify if host_ref is valid before calling method.
276 @param func: function with params: (self, session, host_ref, ...)
277 @rtype: callable object
278 """
279 return lambda *args, **kwargs: \
280 _check_ref(XendNode.instance().is_valid_host,
281 'host', func, *args, **kwargs)
283 def valid_host_metrics(func):
284 """Decorator to verify if host_metrics_ref is valid before calling
285 method.
287 @param func: function with params: (self, session, host_metrics_ref)
288 @rtype: callable object
289 """
290 return lambda *args, **kwargs: \
291 _check_ref(lambda r: r == XendNode.instance().host_metrics_uuid,
292 'host_metrics', func, *args, **kwargs)
294 def valid_host_cpu(func):
295 """Decorator to verify if host_cpu_ref is valid before calling method.
297 @param func: function with params: (self, session, host_cpu_ref, ...)
298 @rtype: callable object
299 """
300 return lambda *args, **kwargs: \
301 _check_ref(XendNode.instance().is_valid_cpu,
302 'host_cpu', func, *args, **kwargs)
304 def valid_vm(func):
305 """Decorator to verify if vm_ref is valid before calling method.
307 @param func: function with params: (self, session, vm_ref, ...)
308 @rtype: callable object
309 """
310 return lambda *args, **kwargs: \
311 _check_ref(XendDomain.instance().is_valid_vm,
312 'VM', func, *args, **kwargs)
314 def valid_vbd(func):
315 """Decorator to verify if vbd_ref is valid before calling method.
317 @param func: function with params: (self, session, vbd_ref, ...)
318 @rtype: callable object
319 """
320 return lambda *args, **kwargs: \
321 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vbd', r),
322 'VBD', func, *args, **kwargs)
324 def valid_vbd_metrics(func):
325 """Decorator to verify if ref is valid before calling method.
327 @param func: function with params: (self, session, ref, ...)
328 @rtype: callable object
329 """
330 return lambda *args, **kwargs: \
331 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vbd', r),
332 'VBD_metrics', func, *args, **kwargs)
334 def valid_vif(func):
335 """Decorator to verify if vif_ref is valid before calling method.
337 @param func: function with params: (self, session, vif_ref, ...)
338 @rtype: callable object
339 """
340 return lambda *args, **kwargs: \
341 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vif', r),
342 'VIF', func, *args, **kwargs)
344 def valid_vif_metrics(func):
345 """Decorator to verify if ref is valid before calling method.
347 @param func: function with params: (self, session, ref, ...)
348 @rtype: callable object
349 """
350 return lambda *args, **kwargs: \
351 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vif', r),
352 'VIF_metrics', func, *args, **kwargs)
354 def valid_vdi(func):
355 """Decorator to verify if vdi_ref is valid before calling method.
357 @param func: function with params: (self, session, vdi_ref, ...)
358 @rtype: callable object
359 """
360 return lambda *args, **kwargs: \
361 _check_ref(XendNode.instance().is_valid_vdi,
362 'VDI', func, *args, **kwargs)
364 def valid_vtpm(func):
365 """Decorator to verify if vtpm_ref is valid before calling method.
367 @param func: function with params: (self, session, vtpm_ref, ...)
368 @rtype: callable object
369 """
370 return lambda *args, **kwargs: \
371 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vtpm', r),
372 'VTPM', func, *args, **kwargs)
375 def valid_console(func):
376 """Decorator to verify if console_ref is valid before calling method.
378 @param func: function with params: (self, session, console_ref, ...)
379 @rtype: callable object
380 """
381 return lambda *args, **kwargs: \
382 _check_ref(lambda r: XendDomain.instance().is_valid_dev('console',
383 r),
384 'console', func, *args, **kwargs)
386 def valid_sr(func):
387 """Decorator to verify if sr_ref is valid before calling method.
389 @param func: function with params: (self, session, sr_ref, ...)
390 @rtype: callable object
391 """
392 return lambda *args, **kwargs: \
393 _check_ref(lambda r: XendNode.instance().is_valid_sr,
394 'SR', func, *args, **kwargs)
396 def valid_task(func):
397 """Decorator to verify if task_ref is valid before calling
398 method.
400 @param func: function with params: (self, session, task_ref)
401 @rtype: callable object
402 """
403 return lambda *args, **kwargs: \
404 _check_ref(XendTaskManager.get_task,
405 'task', func, *args, **kwargs)
407 def valid_debug(func):
408 """Decorator to verify if task_ref is valid before calling
409 method.
411 @param func: function with params: (self, session, task_ref)
412 @rtype: callable object
413 """
414 return lambda *args, **kwargs: \
415 _check_ref(lambda r: r in XendAPI._debug,
416 'debug', func, *args, **kwargs)
419 def valid_object(class_name):
420 """Decorator to verify if object is valid before calling
421 method.
423 @param func: function with params: (self, session, pif_ref)
424 @rtype: callable object
425 """
426 return lambda func: \
427 lambda *args, **kwargs: \
428 _check_ref(lambda r: \
429 XendAPIStore.get(r, class_name) is not None,
430 'PIF', func, *args, **kwargs)
432 # -----------------------------
433 # Bridge to Legacy XM API calls
434 # -----------------------------
436 def do_vm_func(fn_name, vm_ref, *args, **kwargs):
437 """Helper wrapper func to abstract away from repetitive code.
439 @param fn_name: function name for XendDomain instance
440 @type fn_name: string
441 @param vm_ref: vm_ref
442 @type vm_ref: string
443 @param *args: more arguments
444 @type *args: tuple
445 """
446 try:
447 xendom = XendDomain.instance()
448 fn = getattr(xendom, fn_name)
449 xendom.do_legacy_api_with_uuid(fn, vm_ref, *args, **kwargs)
450 return xen_api_success_void()
451 except VMBadState, exn:
452 return xen_api_error(['VM_BAD_POWER_STATE', vm_ref, exn.expected,
453 exn.actual])
456 classes = {
457 'session' : None,
458 'event' : None,
459 'host' : valid_host,
460 'host_cpu' : valid_host_cpu,
461 'host_metrics' : valid_host_metrics,
462 'VM' : valid_vm,
463 'VBD' : valid_vbd,
464 'VBD_metrics' : valid_vbd_metrics,
465 'VIF' : valid_vif,
466 'VIF_metrics' : valid_vif_metrics,
467 'VDI' : valid_vdi,
468 'VTPM' : valid_vtpm,
469 'console' : valid_console,
470 'SR' : valid_sr,
471 'task' : valid_task,
472 'XSPolicy' : valid_object("XSPolicy"),
473 'ACMPolicy' : valid_object("ACMPolicy"),
474 'debug' : valid_debug,
475 'network' : valid_object("network"),
476 'PIF' : valid_object("PIF"),
477 'VM_metrics' : valid_object("VM_metrics"),
478 'PBD' : valid_object("PBD"),
479 'PIF_metrics' : valid_object("PIF_metrics")
480 }
482 autoplug_classes = {
483 'network' : XendNetwork,
484 'PIF' : XendPIF,
485 'VM_metrics' : XendVMMetrics,
486 'PBD' : XendPBD,
487 'PIF_metrics' : XendPIFMetrics,
488 'XSPolicy' : XendXSPolicy,
489 'ACMPolicy' : XendACMPolicy,
490 }
492 class XendAPI(object):
493 """Implementation of the Xen-API in Xend. Expects to be
494 used via XMLRPCServer.
496 All methods that need a valid session are marked with
497 a L{session_required} decorator that will
498 transparently perform the required session authentication.
500 We need to support Python <2.4, so we use the old decorator syntax.
502 All XMLRPC accessible methods require an 'api' attribute and
503 is set to the XMLRPC function name which the method implements.
504 """
506 __decorated__ = False
507 __init_lock__ = threading.Lock()
508 _debug = {}
510 def __new__(cls, *args, **kwds):
511 """ Override __new__ to decorate the class only once.
513 Lock to make sure the classes are not decorated twice.
514 """
515 cls.__init_lock__.acquire()
516 try:
517 if not cls.__decorated__:
518 cls._decorate()
519 cls.__decorated__ = True
521 return object.__new__(cls, *args, **kwds)
522 finally:
523 cls.__init_lock__.release()
525 def _decorate(cls):
526 """ Decorate all the object methods to have validators
527 and appropriate function attributes.
529 This should only be executed once for the duration of the
530 server.
531 """
532 global_validators = [session_required, catch_typeerror]
535 # Cheat methods
536 # -------------
537 # Methods that have a trivial implementation for all classes.
538 # 1. get_by_uuid == getting by ref, so just return uuid for
539 # all get_by_uuid() methods.
541 for api_cls in classes.keys():
542 # We'll let the autoplug classes implement these functions
543 # themselves - its much cleaner to do it in the base class
544 if api_cls == 'session' or api_cls in autoplug_classes.keys():
545 continue
547 get_by_uuid = '%s_get_by_uuid' % api_cls
548 get_uuid = '%s_get_uuid' % api_cls
549 get_all_records = '%s_get_all_records' % api_cls
551 def _get_by_uuid(_1, _2, ref):
552 return xen_api_success(ref)
554 def _get_uuid(_1, _2, ref):
555 return xen_api_success(ref)
557 def unpack(v):
558 return v['Value']
560 def _get_all_records(_api_cls):
561 return lambda s, session: \
562 xen_api_success(dict([(ref, unpack(getattr(cls, '%s_get_record' % _api_cls)(s, session, ref)))\
563 for ref in unpack(getattr(cls, '%s_get_all' % _api_cls)(s, session))]))
565 setattr(cls, get_by_uuid, _get_by_uuid)
566 setattr(cls, get_uuid, _get_uuid)
567 setattr(cls, get_all_records, _get_all_records(api_cls))
569 # Autoplugging classes
570 # --------------------
571 # These have all of their methods grabbed out from the implementation
572 # class, and wrapped up to be compatible with the Xen-API.
574 def getter(ref, type):
575 return XendAPIStore.get(ref, type)
577 for api_cls, impl_cls in autoplug_classes.items():
578 def doit(n):
579 dot_n = '%s.%s' % (api_cls, n)
580 full_n = '%s_%s' % (api_cls, n)
581 if not hasattr(cls, full_n):
582 f = getattr(impl_cls, n)
583 argcounts[dot_n] = f.func_code.co_argcount + 1
584 g = lambda api_cls: \
585 setattr(cls, full_n, \
586 lambda s, session, ref, *args: \
587 xen_api_success( \
588 f(getter(ref, api_cls), *args)))
589 g(api_cls) # Force api_cls to be captured
591 def doit_func(n):
592 dot_n = '%s.%s' % (api_cls, n)
593 full_n = '%s_%s' % (api_cls, n)
594 if not hasattr(cls, full_n):
595 f = getattr(impl_cls, n)
596 argcounts[dot_n] = f.func_code.co_argcount
597 setattr(cls, full_n, \
598 lambda s, session, *args: \
599 xen_api_success( \
600 f(*args)))
602 ro_attrs = impl_cls.getAttrRO()
603 rw_attrs = impl_cls.getAttrRW()
604 methods = impl_cls.getMethods()
605 funcs = impl_cls.getFuncs()
607 for attr_name in ro_attrs + rw_attrs:
608 doit('get_%s' % attr_name)
609 for attr_name in rw_attrs:
610 doit('set_%s' % attr_name)
611 for method in methods:
612 doit('%s' % method)
613 for func in funcs:
614 doit_func('%s' % func)
616 def wrap_method(name, new_f):
617 try:
618 f = getattr(cls, name)
619 wrapped_f = (lambda *args: new_f(f, *args))
620 wrapped_f.api = f.api
621 wrapped_f.async = f.async
622 setattr(cls, name, wrapped_f)
623 except AttributeError:
624 # Logged below (API call: %s not found)
625 pass
628 def setter_event_wrapper(api_cls, attr_name):
629 setter_name = '%s_set_%s' % (api_cls, attr_name)
630 wrap_method(
631 setter_name,
632 lambda setter, s, session, ref, *args:
633 _setter_event_dispatch(s, setter, api_cls, attr_name,
634 session, ref, args))
637 def ctor_event_wrapper(api_cls):
638 ctor_name = '%s_create' % api_cls
639 wrap_method(
640 ctor_name,
641 lambda ctor, s, session, *args:
642 _ctor_event_dispatch(s, ctor, api_cls, session, args))
645 def dtor_event_wrapper(api_cls):
646 dtor_name = '%s_destroy' % api_cls
647 wrap_method(
648 dtor_name,
649 lambda dtor, s, session, ref, *args:
650 _dtor_event_dispatch(s, dtor, api_cls, session, ref, args))
653 # Wrapping validators around XMLRPC calls
654 # ---------------------------------------
656 for api_cls, validator in classes.items():
657 def doit(n, takes_instance, async_support = False,
658 return_type = None):
659 n_ = n.replace('.', '_')
660 try:
661 f = getattr(cls, n_)
662 if n not in argcounts:
663 argcounts[n] = f.func_code.co_argcount - 1
665 validators = takes_instance and validator and \
666 [validator] or []
668 validators += global_validators
669 for v in validators:
670 f = v(f)
671 f.api = n
672 f.async = async_support
673 if return_type:
674 f.return_type = return_type
676 setattr(cls, n_, f)
677 except AttributeError:
678 log.warn("API call: %s not found" % n)
680 if api_cls in autoplug_classes.keys():
681 impl_cls = autoplug_classes[api_cls]
682 ro_attrs = impl_cls.getAttrRO()
683 rw_attrs = impl_cls.getAttrRW()
684 methods = map(lambda x: (x, ""), impl_cls.getMethods())
685 funcs = map(lambda x: (x, ""), impl_cls.getFuncs())
686 else:
687 ro_attrs = getattr(cls, '%s_attr_ro' % api_cls, []) \
688 + cls.Base_attr_ro
689 rw_attrs = getattr(cls, '%s_attr_rw' % api_cls, []) \
690 + cls.Base_attr_rw
691 methods = getattr(cls, '%s_methods' % api_cls, []) \
692 + cls.Base_methods
693 funcs = getattr(cls, '%s_funcs' % api_cls, []) \
694 + cls.Base_funcs
696 # wrap validators around readable class attributes
697 for attr_name in ro_attrs + rw_attrs:
698 doit('%s.get_%s' % (api_cls, attr_name), True,
699 async_support = False)
701 # wrap validators around writable class attrributes
702 for attr_name in rw_attrs:
703 doit('%s.set_%s' % (api_cls, attr_name), True,
704 async_support = False)
705 setter_event_wrapper(api_cls, attr_name)
707 # wrap validators around methods
708 for method_name, return_type in methods:
709 doit('%s.%s' % (api_cls, method_name), True,
710 async_support = True)
712 # wrap validators around class functions
713 for func_name, return_type in funcs:
714 doit('%s.%s' % (api_cls, func_name), False,
715 async_support = True,
716 return_type = return_type)
718 ctor_event_wrapper(api_cls)
719 dtor_event_wrapper(api_cls)
722 _decorate = classmethod(_decorate)
724 def __init__(self, auth):
725 self.auth = auth
727 Base_attr_ro = ['uuid']
728 Base_attr_rw = []
729 Base_methods = [('get_record', 'Struct')]
730 Base_funcs = [('get_all', 'Set'), ('get_by_uuid', None), ('get_all_records', 'Set')]
732 # Xen API: Class Session
733 # ----------------------------------------------------------------
734 # NOTE: Left unwrapped by __init__
736 session_attr_ro = ['this_host', 'this_user', 'last_active']
737 session_methods = [('logout', None)]
739 def session_get_all(self, session):
740 return xen_api_success([session])
742 def session_login_with_password(self, *args):
743 if len(args) != 2:
744 return xen_api_error(
745 ['MESSAGE_PARAMETER_COUNT_MISMATCH',
746 'session.login_with_password', 2, len(args)])
747 username = args[0]
748 password = args[1]
749 try:
750 session = ((self.auth == AUTH_NONE and
751 auth_manager().login_unconditionally(username)) or
752 auth_manager().login_with_password(username, password))
753 return xen_api_success(session)
754 except XendError, e:
755 return xen_api_error(['SESSION_AUTHENTICATION_FAILED'])
756 session_login_with_password.api = 'session.login_with_password'
758 # object methods
759 def session_logout(self, session):
760 auth_manager().logout(session)
761 return xen_api_success_void()
763 def session_get_record(self, session, self_session):
764 if self_session != session:
765 return xen_api_error(['PERMISSION_DENIED'])
766 record = {'uuid' : session,
767 'this_host' : XendNode.instance().uuid,
768 'this_user' : auth_manager().get_user(session),
769 'last_active': now()}
770 return xen_api_success(record)
772 def session_get_uuid(self, session, self_session):
773 return xen_api_success(self_session)
775 def session_get_by_uuid(self, session, self_session):
776 return xen_api_success(self_session)
778 # attributes (ro)
779 def session_get_this_host(self, session, self_session):
780 if self_session != session:
781 return xen_api_error(['PERMISSION_DENIED'])
782 return xen_api_success(XendNode.instance().uuid)
784 def session_get_this_user(self, session, self_session):
785 if self_session != session:
786 return xen_api_error(['PERMISSION_DENIED'])
787 user = auth_manager().get_user(session)
788 if user is not None:
789 return xen_api_success(user)
790 return xen_api_error(['SESSION_INVALID', session])
792 def session_get_last_active(self, session, self_session):
793 if self_session != session:
794 return xen_api_error(['PERMISSION_DENIED'])
795 return xen_api_success(now())
798 # Xen API: Class User
799 # ----------------------------------------------------------------
800 # TODO: NOT IMPLEMENTED YET
802 # Xen API: Class Tasks
803 # ----------------------------------------------------------------
805 task_attr_ro = ['name_label',
806 'name_description',
807 'status',
808 'progress',
809 'type',
810 'result',
811 'error_info',
812 'allowed_operations',
813 'session'
814 ]
816 task_attr_rw = []
818 task_funcs = [('get_by_name_label', 'Set(task)'),
819 ('cancel', None)]
821 def task_get_name_label(self, session, task_ref):
822 task = XendTaskManager.get_task(task_ref)
823 return xen_api_success(task.name_label)
825 def task_get_name_description(self, session, task_ref):
826 task = XendTaskManager.get_task(task_ref)
827 return xen_api_success(task.name_description)
829 def task_get_status(self, session, task_ref):
830 task = XendTaskManager.get_task(task_ref)
831 return xen_api_success(task.get_status())
833 def task_get_progress(self, session, task_ref):
834 task = XendTaskManager.get_task(task_ref)
835 return xen_api_success(task.progress)
837 def task_get_type(self, session, task_ref):
838 task = XendTaskManager.get_task(task_ref)
839 return xen_api_success(task.type)
841 def task_get_result(self, session, task_ref):
842 task = XendTaskManager.get_task(task_ref)
843 return xen_api_success(task.result)
845 def task_get_error_info(self, session, task_ref):
846 task = XendTaskManager.get_task(task_ref)
847 return xen_api_success(task.error_info)
849 def task_get_allowed_operations(self, session, task_ref):
850 return xen_api_success({})
852 def task_get_session(self, session, task_ref):
853 task = XendTaskManager.get_task(task_ref)
854 return xen_api_success(task.session)
856 def task_get_all(self, session):
857 tasks = XendTaskManager.get_all_tasks()
858 return xen_api_success(tasks)
860 def task_get_record(self, session, task_ref):
861 task = XendTaskManager.get_task(task_ref)
862 return xen_api_success(task.get_record())
864 def task_cancel(self, session, task_ref):
865 return xen_api_error('OPERATION_NOT_ALLOWED')
867 def task_get_by_name_label(self, session, name):
868 return xen_api_success(XendTaskManager.get_task_by_name(name))
870 # Xen API: Class host
871 # ----------------------------------------------------------------
873 host_attr_ro = ['software_version',
874 'resident_VMs',
875 'PBDs',
876 'PIFs',
877 'host_CPUs',
878 'cpu_configuration',
879 'metrics',
880 'capabilities',
881 'supported_bootloaders',
882 'sched_policy',
883 'API_version_major',
884 'API_version_minor',
885 'API_version_vendor',
886 'API_version_vendor_implementation',
887 'enabled']
889 host_attr_rw = ['name_label',
890 'name_description',
891 'other_config',
892 'logging']
894 host_methods = [('disable', None),
895 ('enable', None),
896 ('reboot', None),
897 ('shutdown', None),
898 ('add_to_other_config', None),
899 ('remove_from_other_config', None),
900 ('dmesg', 'String'),
901 ('dmesg_clear', 'String'),
902 ('get_log', 'String'),
903 ('send_debug_keys', None)]
905 host_funcs = [('get_by_name_label', None),
906 ('list_methods', None)]
908 # attributes
909 def host_get_name_label(self, session, host_ref):
910 return xen_api_success(XendNode.instance().name)
911 def host_set_name_label(self, session, host_ref, new_name):
912 XendNode.instance().set_name(new_name)
913 return xen_api_success_void()
914 def host_get_name_description(self, session, host_ref):
915 return xen_api_success(XendNode.instance().get_description())
916 def host_set_name_description(self, session, host_ref, new_desc):
917 XendNode.instance().set_description(new_desc)
918 return xen_api_success_void()
919 def host_get_other_config(self, session, host_ref):
920 return xen_api_success(XendNode.instance().other_config)
921 def host_set_other_config(self, session, host_ref, other_config):
922 node = XendNode.instance()
923 node.other_config = dict(other_config)
924 node.save()
925 return xen_api_success_void()
926 def host_add_to_other_config(self, session, host_ref, key, value):
927 node = XendNode.instance()
928 node.other_config[key] = value
929 node.save()
930 return xen_api_success_void()
931 def host_remove_from_other_config(self, session, host_ref, key):
932 node = XendNode.instance()
933 if key in node.other_config:
934 del node.other_config[key]
935 node.save()
936 return xen_api_success_void()
937 def host_get_API_version_major(self, _, ref):
938 return xen_api_success(XEN_API_VERSION_MAJOR)
939 def host_get_API_version_minor(self, _, ref):
940 return xen_api_success(XEN_API_VERSION_MINOR)
941 def host_get_API_version_vendor(self, _, ref):
942 return xen_api_success(XEN_API_VERSION_VENDOR)
943 def host_get_API_version_vendor_implementation(self, _, ref):
944 return xen_api_success(XEN_API_VERSION_VENDOR_IMPLEMENTATION)
945 def host_get_software_version(self, session, host_ref):
946 return xen_api_success(XendNode.instance().xen_version())
947 def host_get_enabled(self, _1, _2):
948 return xen_api_success(XendDomain.instance().allow_new_domains())
949 def host_get_resident_VMs(self, session, host_ref):
950 return xen_api_success(XendDomain.instance().get_domain_refs())
951 def host_get_PBDs(self, _, ref):
952 return xen_api_success(XendPBD.get_all())
953 def host_get_PIFs(self, session, ref):
954 return xen_api_success(XendNode.instance().get_PIF_refs())
955 def host_get_host_CPUs(self, session, host_ref):
956 return xen_api_success(XendNode.instance().get_host_cpu_refs())
957 def host_get_metrics(self, _, ref):
958 return xen_api_success(XendNode.instance().host_metrics_uuid)
959 def host_get_capabilities(self, session, host_ref):
960 return xen_api_success(XendNode.instance().get_capabilities())
961 def host_get_supported_bootloaders(self, session, host_ref):
962 return xen_api_success(['pygrub'])
963 def host_get_sched_policy(self, _, host_ref):
964 return xen_api_success(XendNode.instance().get_vcpus_policy())
965 def host_get_cpu_configuration(self, _, host_ref):
966 return xen_api_success(XendNode.instance().get_cpu_configuration())
967 def host_set_logging(self, _, host_ref, logging):
968 return xen_api_todo()
969 def host_get_logging(self, _, host_ref):
970 return xen_api_todo()
972 # object methods
973 def host_disable(self, session, host_ref):
974 XendDomain.instance().set_allow_new_domains(False)
975 return xen_api_success_void()
976 def host_enable(self, session, host_ref):
977 XendDomain.instance().set_allow_new_domains(True)
978 return xen_api_success_void()
979 def host_reboot(self, session, host_ref):
980 if not XendDomain.instance().allow_new_domains():
981 return xen_api_error(XEND_ERROR_HOST_RUNNING)
982 return xen_api_error(XEND_ERROR_UNSUPPORTED)
983 def host_shutdown(self, session, host_ref):
984 if not XendDomain.instance().allow_new_domains():
985 return xen_api_error(XEND_ERROR_HOST_RUNNING)
986 return xen_api_error(XEND_ERROR_UNSUPPORTED)
988 def host_dmesg(self, session, host_ref):
989 return xen_api_success(XendDmesg.instance().info())
991 def host_dmesg_clear(self, session, host_ref):
992 return xen_api_success(XendDmesg.instance().clear())
994 def host_get_log(self, session, host_ref):
995 log_file = open(XendLogging.getLogFilename())
996 log_buffer = log_file.read()
997 return xen_api_success(log_buffer)
999 def host_send_debug_keys(self, _, host_ref, keys):
1000 node = XendNode.instance()
1001 node.send_debug_keys(keys)
1002 return xen_api_success_void()
1004 def host_get_record(self, session, host_ref):
1005 node = XendNode.instance()
1006 dom = XendDomain.instance()
1007 record = {'uuid': node.uuid,
1008 'name_label': node.name,
1009 'name_description': '',
1010 'API_version_major': XEN_API_VERSION_MAJOR,
1011 'API_version_minor': XEN_API_VERSION_MINOR,
1012 'API_version_vendor': XEN_API_VERSION_VENDOR,
1013 'API_version_vendor_implementation':
1014 XEN_API_VERSION_VENDOR_IMPLEMENTATION,
1015 'software_version': node.xen_version(),
1016 'enabled': XendDomain.instance().allow_new_domains(),
1017 'other_config': node.other_config,
1018 'resident_VMs': dom.get_domain_refs(),
1019 'host_CPUs': node.get_host_cpu_refs(),
1020 'cpu_configuration': node.get_cpu_configuration(),
1021 'metrics': node.host_metrics_uuid,
1022 'capabilities': node.get_capabilities(),
1023 'supported_bootloaders': ['pygrub'],
1024 'sched_policy': node.get_vcpus_policy(),
1025 'logging': {},
1026 'PIFs': XendPIF.get_all(),
1027 'PBDs': XendPBD.get_all()}
1028 return xen_api_success(record)
1030 # class methods
1031 def host_get_all(self, session):
1032 return xen_api_success((XendNode.instance().uuid,))
1033 def host_get_by_name_label(self, session, name):
1034 if XendNode.instance().name == name:
1035 return xen_api_success((XendNode.instance().uuid,))
1036 return xen_api_success([])
1038 def host_list_methods(self, _):
1039 def _funcs():
1040 return [getattr(XendAPI, x) for x in XendAPI.__dict__]
1042 return xen_api_success([x.api for x in _funcs()
1043 if hasattr(x, 'api')])
1045 # Xen API: Class host_CPU
1046 # ----------------------------------------------------------------
1048 host_cpu_attr_ro = ['host',
1049 'number',
1050 'vendor',
1051 'speed',
1052 'modelname',
1053 'stepping',
1054 'flags',
1055 'utilisation',
1056 'features']
1058 # attributes
1059 def _host_cpu_get(self, ref, field):
1060 return xen_api_success(
1061 XendNode.instance().get_host_cpu_field(ref, field))
1063 def host_cpu_get_host(self, _, ref):
1064 return xen_api_success(XendNode.instance().uuid)
1065 def host_cpu_get_features(self, _, ref):
1066 return self._host_cpu_get(ref, 'features')
1067 def host_cpu_get_number(self, _, ref):
1068 return self._host_cpu_get(ref, 'number')
1069 def host_cpu_get_vendor(self, _, ref):
1070 return self._host_cpu_get(ref, 'vendor')
1071 def host_cpu_get_speed(self, _, ref):
1072 return self._host_cpu_get(ref, 'speed')
1073 def host_cpu_get_modelname(self, _, ref):
1074 return self._host_cpu_get(ref, 'modelname')
1075 def host_cpu_get_stepping(self, _, ref):
1076 return self._host_cpu_get(ref, 'stepping')
1077 def host_cpu_get_flags(self, _, ref):
1078 return self._host_cpu_get(ref, 'flags')
1079 def host_cpu_get_utilisation(self, _, ref):
1080 return xen_api_success(XendNode.instance().get_host_cpu_load(ref))
1082 # object methods
1083 def host_cpu_get_record(self, _, ref):
1084 node = XendNode.instance()
1085 record = dict([(f, node.get_host_cpu_field(ref, f))
1086 for f in self.host_cpu_attr_ro
1087 if f not in ['uuid', 'host', 'utilisation']])
1088 record['uuid'] = ref
1089 record['host'] = node.uuid
1090 record['utilisation'] = node.get_host_cpu_load(ref)
1091 return xen_api_success(record)
1093 # class methods
1094 def host_cpu_get_all(self, session):
1095 return xen_api_success(XendNode.instance().get_host_cpu_refs())
1098 # Xen API: Class host_metrics
1099 # ----------------------------------------------------------------
1101 host_metrics_attr_ro = ['memory_total',
1102 'memory_free',
1103 'last_updated']
1104 host_metrics_attr_rw = []
1105 host_metrics_methods = []
1107 def host_metrics_get_all(self, _):
1108 return xen_api_success([XendNode.instance().host_metrics_uuid])
1110 def _host_metrics_get(self, ref, f):
1111 return xen_api_success(getattr(node, f)())
1113 def host_metrics_get_record(self, _, ref):
1114 return xen_api_success({
1115 'uuid' : ref,
1116 'memory_total' : self._host_metrics_get_memory_total(),
1117 'memory_free' : self._host_metrics_get_memory_free(),
1118 'last_updated' : now(),
1119 })
1121 def host_metrics_get_memory_total(self, _1, _2):
1122 return xen_api_success(self._host_metrics_get_memory_total())
1124 def host_metrics_get_memory_free(self, _1, _2):
1125 return xen_api_success(self._host_metrics_get_memory_free())
1127 def host_metrics_get_last_updated(self, _1, _2):
1128 return xen_api_success(now())
1130 def _host_metrics_get_memory_total(self):
1131 node = XendNode.instance()
1132 return node.xc.physinfo()['total_memory'] * 1024
1134 def _host_metrics_get_memory_free(self):
1135 node = XendNode.instance()
1136 return node.xc.physinfo()['free_memory'] * 1024
1138 # Xen API: Class VM
1139 # ----------------------------------------------------------------
1141 VM_attr_ro = ['power_state',
1142 'resident_on',
1143 'consoles',
1144 'VIFs',
1145 'VBDs',
1146 'VTPMs',
1147 'tools_version',
1148 'domid',
1149 'is_control_domain',
1150 'metrics',
1151 'crash_dumps',
1154 VM_attr_rw = ['name_label',
1155 'name_description',
1156 'user_version',
1157 'is_a_template',
1158 'auto_power_on',
1159 'memory_dynamic_max',
1160 'memory_dynamic_min',
1161 'memory_static_max',
1162 'memory_static_min',
1163 'VCPUs_max',
1164 'VCPUs_at_startup',
1165 'VCPUs_params',
1166 'actions_after_shutdown',
1167 'actions_after_reboot',
1168 'actions_after_suspend',
1169 'actions_after_crash',
1170 'PV_bootloader',
1171 'PV_kernel',
1172 'PV_ramdisk',
1173 'PV_args',
1174 'PV_bootloader_args',
1175 'HVM_boot_policy',
1176 'HVM_boot_params',
1177 'platform',
1178 'PCI_bus',
1179 'other_config',
1180 'security_label']
1182 VM_methods = [('clone', 'VM'),
1183 ('start', None),
1184 ('pause', None),
1185 ('unpause', None),
1186 ('clean_shutdown', None),
1187 ('clean_reboot', None),
1188 ('hard_shutdown', None),
1189 ('hard_reboot', None),
1190 ('suspend', None),
1191 ('resume', None),
1192 ('send_sysrq', None),
1193 ('set_VCPUs_number_live', None),
1194 ('add_to_HVM_boot_params', None),
1195 ('remove_from_HVM_boot_params', None),
1196 ('add_to_VCPUs_params', None),
1197 ('add_to_VCPUs_params_live', None),
1198 ('remove_from_VCPUs_params', None),
1199 ('add_to_platform', None),
1200 ('remove_from_platform', None),
1201 ('add_to_other_config', None),
1202 ('remove_from_other_config', None),
1203 ('save', None),
1204 ('set_memory_dynamic_max_live', None),
1205 ('set_memory_dynamic_min_live', None),
1206 ('send_trigger', None),
1207 ('migrate', None),
1208 ('destroy', None)]
1210 VM_funcs = [('create', 'VM'),
1211 ('restore', None),
1212 ('get_by_name_label', 'Set(VM)')]
1214 # parameters required for _create()
1215 VM_attr_inst = [
1216 'name_label',
1217 'name_description',
1218 'user_version',
1219 'is_a_template',
1220 'memory_static_max',
1221 'memory_dynamic_max',
1222 'memory_dynamic_min',
1223 'memory_static_min',
1224 'VCPUs_max',
1225 'VCPUs_at_startup',
1226 'VCPUs_params',
1227 'actions_after_shutdown',
1228 'actions_after_reboot',
1229 'actions_after_suspend',
1230 'actions_after_crash',
1231 'PV_bootloader',
1232 'PV_kernel',
1233 'PV_ramdisk',
1234 'PV_args',
1235 'PV_bootloader_args',
1236 'HVM_boot_policy',
1237 'HVM_boot_params',
1238 'platform',
1239 'PCI_bus',
1240 'other_config',
1241 'security_label']
1243 def VM_get(self, name, session, vm_ref):
1244 return xen_api_success(
1245 XendDomain.instance().get_vm_by_uuid(vm_ref).info[name])
1247 def VM_set(self, name, session, vm_ref, value):
1248 xd = XendDomain.instance()
1249 dominfo = xd.get_vm_by_uuid(vm_ref)
1250 dominfo.info[name] = value
1251 return self._VM_save(dominfo)
1253 def _VM_save(self, dominfo):
1254 XendDomain.instance().managed_config_save(dominfo)
1255 return xen_api_success_void()
1257 # attributes (ro)
1258 def VM_get_power_state(self, session, vm_ref):
1259 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1260 return xen_api_success(dom.get_power_state())
1262 def VM_get_resident_on(self, session, vm_ref):
1263 return xen_api_success(XendNode.instance().uuid)
1265 def VM_get_memory_static_max(self, session, vm_ref):
1266 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1267 return xen_api_success(dom.get_memory_static_max())
1269 def VM_get_memory_static_min(self, session, vm_ref):
1270 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1271 return xen_api_success(dom.get_memory_static_min())
1273 def VM_get_VIFs(self, session, vm_ref):
1274 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1275 return xen_api_success(dom.get_vifs())
1277 def VM_get_VBDs(self, session, vm_ref):
1278 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1279 return xen_api_success(dom.get_vbds())
1281 def VM_get_VTPMs(self, session, vm_ref):
1282 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1283 return xen_api_success(dom.get_vtpms())
1285 def VM_get_consoles(self, session, vm_ref):
1286 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1287 return xen_api_success(dom.get_consoles())
1289 def VM_get_tools_version(self, session, vm_ref):
1290 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1291 return dom.get_tools_version()
1293 def VM_get_metrics(self, _, vm_ref):
1294 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1295 return xen_api_success(dom.get_metrics())
1297 def VM_get_VCPUs_max(self, _, vm_ref):
1298 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1299 return xen_api_todo()
1301 def VM_get_VCPUs_at_startup(self, _, vm_ref):
1302 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1303 return xen_api_todo()
1305 # attributes (rw)
1306 def VM_get_name_label(self, session, vm_ref):
1307 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1308 return xen_api_success(dom.getName())
1310 def VM_get_name_description(self, session, vm_ref):
1311 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1312 return xen_api_todo()
1314 def VM_get_user_version(self, session, vm_ref):
1315 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1316 return xen_api_todo()
1318 def VM_get_is_a_template(self, session, ref):
1319 return self.VM_get('is_a_template', session, ref)
1321 def VM_get_memory_dynamic_max(self, session, vm_ref):
1322 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1323 return xen_api_success(dom.get_memory_dynamic_max())
1325 def VM_get_memory_dynamic_min(self, session, vm_ref):
1326 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1327 return xen_api_success(dom.get_memory_dynamic_min())
1329 def VM_get_VCPUs_params(self, session, vm_ref):
1330 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1331 return xen_api_success(dom.get_vcpus_params())
1333 def VM_get_actions_after_shutdown(self, session, vm_ref):
1334 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1335 return xen_api_success(dom.get_on_shutdown())
1337 def VM_get_actions_after_reboot(self, session, vm_ref):
1338 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1339 return xen_api_success(dom.get_on_reboot())
1341 def VM_get_actions_after_suspend(self, session, vm_ref):
1342 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1343 return xen_api_success(dom.get_on_suspend())
1345 def VM_get_actions_after_crash(self, session, vm_ref):
1346 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1347 return xen_api_success(dom.get_on_crash())
1349 def VM_get_PV_bootloader(self, session, vm_ref):
1350 return self.VM_get('PV_bootloader', session, vm_ref)
1352 def VM_get_PV_kernel(self, session, vm_ref):
1353 return self.VM_get('PV_kernel', session, vm_ref)
1355 def VM_get_PV_ramdisk(self, session, vm_ref):
1356 return self.VM_get('PV_ramdisk', session, vm_ref)
1358 def VM_get_PV_args(self, session, vm_ref):
1359 return self.VM_get('PV_args', session, vm_ref)
1361 def VM_get_PV_bootloader_args(self, session, vm_ref):
1362 return self.VM_get('PV_bootloader_args', session, vm_ref)
1364 def VM_get_HVM_boot_policy(self, session, vm_ref):
1365 return self.VM_get('HVM_boot_policy', session, vm_ref)
1367 def VM_get_HVM_boot_params(self, session, vm_ref):
1368 return self.VM_get('HVM_boot_params', session, vm_ref)
1370 def VM_get_platform(self, session, vm_ref):
1371 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1372 return xen_api_success(dom.get_platform())
1374 def VM_get_PCI_bus(self, session, vm_ref):
1375 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1376 return dom.get_pci_bus()
1378 def VM_set_PCI_bus(self, session, vm_ref, val):
1379 return self.VM_set('PCI_bus', session, vm_ref, val)
1381 def VM_get_other_config(self, session, vm_ref):
1382 return self.VM_get('other_config', session, vm_ref)
1384 def VM_get_domid(self, _, ref):
1385 domid = XendDomain.instance().get_vm_by_uuid(ref).getDomid()
1386 return xen_api_success(domid is None and -1 or domid)
1388 def VM_get_is_control_domain(self, session, vm_ref):
1389 xd = XendDomain.instance()
1390 return xen_api_success(
1391 xd.get_vm_by_uuid(vm_ref) == xd.privilegedDomain())
1393 def VM_set_name_label(self, session, vm_ref, label):
1394 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1395 dom.setName(label)
1396 return self._VM_save(dom)
1398 def VM_set_name_description(self, session, vm_ref, desc):
1399 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1400 return xen_api_todo()
1402 def VM_set_user_version(self, session, vm_ref, ver):
1403 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1404 return xen_api_todo()
1406 def VM_set_is_a_template(self, session, vm_ref, is_template):
1407 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1408 return xen_api_todo()
1410 def VM_set_memory_dynamic_max(self, session, vm_ref, mem):
1411 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1412 dom.set_memory_dynamic_max(int(mem))
1413 return self._VM_save(dom)
1415 def VM_set_memory_dynamic_min(self, session, vm_ref, mem):
1416 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1417 dom.set_memory_dynamic_min(int(mem))
1418 return self._VM_save(dom)
1420 def VM_set_memory_static_max(self, session, vm_ref, mem):
1421 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1422 dom.set_memory_static_max(int(mem))
1423 return self._VM_save(dom)
1425 def VM_set_memory_static_min(self, session, vm_ref, mem):
1426 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1427 dom.set_memory_static_min(int(mem))
1428 return self._VM_save(dom)
1430 def VM_set_memory_dynamic_max_live(self, session, vm_ref, mem):
1431 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1432 dom.set_memory_dynamic_max(int(mem))
1433 # need to pass target as MiB
1434 dom.setMemoryTarget(int(mem)/1024/1024)
1435 return xen_api_success_void()
1437 def VM_set_memory_dynamic_min_live(self, session, vm_ref, mem):
1438 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1439 dom.set_memory_dynamic_min(int(mem))
1440 # need to pass target as MiB
1441 dom.setMemoryTarget(int(mem)/1024/1024)
1442 return xen_api_success_void()
1444 def VM_set_VCPUs_params(self, session, vm_ref, value):
1445 return self.VM_set('vcpus_params', session, vm_ref, value)
1447 def VM_add_to_VCPUs_params(self, session, vm_ref, key, value):
1448 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1449 if 'vcpus_params' not in dom.info:
1450 dom.info['vcpus_params'] = {}
1451 dom.info['vcpus_params'][key] = value
1452 return self._VM_save(dom)
1454 def VM_add_to_VCPUs_params_live(self, session, vm_ref, key, value):
1455 self.VM_add_to_VCPUs_params(session, vm_ref, key, value)
1456 self._VM_VCPUs_params_refresh(vm_ref)
1457 return xen_api_success_void()
1459 def _VM_VCPUs_params_refresh(self, vm_ref):
1460 xendom = XendDomain.instance()
1461 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1463 #update the cpumaps
1464 for key, value in xeninfo.info['vcpus_params'].items():
1465 if key.startswith("cpumap"):
1466 vcpu = int(key[6:])
1467 try:
1468 cpus = map(int, value.split(","))
1469 xendom.domain_pincpu(xeninfo.getDomid(), vcpu, cpus)
1470 except Exception, ex:
1471 log.exception(ex)
1473 #need to update sched params aswell
1474 if 'weight' in xeninfo.info['vcpus_params'] \
1475 and 'cap' in xeninfo.info['vcpus_params']:
1476 weight = xeninfo.info['vcpus_params']['weight']
1477 cap = xeninfo.info['vcpus_params']['cap']
1478 xendom.domain_sched_credit_set(xeninfo.getDomid(), weight, cap)
1480 def VM_set_VCPUs_number_live(self, _, vm_ref, num):
1481 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1482 dom.setVCpuCount(int(num))
1483 return xen_api_success_void()
1485 def VM_remove_from_VCPUs_params(self, session, vm_ref, key):
1486 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1487 if 'vcpus_params' in dom.info \
1488 and key in dom.info['vcpus_params']:
1489 del dom.info['vcpus_params'][key]
1490 return self._VM_save(dom)
1491 else:
1492 return xen_api_success_void()
1494 def VM_set_VCPUs_at_startup(self, session, vm_ref, num):
1495 return self.VM_set('VCPUs_at_startup', session, vm_ref, num)
1497 def VM_set_VCPUs_max(self, session, vm_ref, num):
1498 return self.VM_set('VCPUs_max', session, vm_ref, num)
1500 def VM_set_actions_after_shutdown(self, session, vm_ref, action):
1501 if action not in XEN_API_ON_NORMAL_EXIT:
1502 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1503 return self.VM_set('actions_after_shutdown', session, vm_ref, action)
1505 def VM_set_actions_after_reboot(self, session, vm_ref, action):
1506 if action not in XEN_API_ON_NORMAL_EXIT:
1507 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1508 return self.VM_set('actions_after_reboot', session, vm_ref, action)
1510 def VM_set_actions_after_suspend(self, session, vm_ref, action):
1511 if action not in XEN_API_ON_NORMAL_EXIT:
1512 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1513 return self.VM_set('actions_after_suspend', session, vm_ref, action)
1515 def VM_set_actions_after_crash(self, session, vm_ref, action):
1516 if action not in XEN_API_ON_CRASH_BEHAVIOUR:
1517 return xen_api_error(['VM_ON_CRASH_BEHAVIOUR_INVALID', vm_ref])
1518 return self.VM_set('actions_after_crash', session, vm_ref, action)
1520 def VM_set_HVM_boot_policy(self, session, vm_ref, value):
1521 if value != "" and value != "BIOS order":
1522 return xen_api_error(
1523 ['VALUE_NOT_SUPPORTED', 'VM.HVM_boot_policy', value,
1524 'Xend supports only the "BIOS order" boot policy.'])
1525 else:
1526 return self.VM_set('HVM_boot_policy', session, vm_ref, value)
1528 def VM_set_HVM_boot_params(self, session, vm_ref, value):
1529 return self.VM_set('HVM_boot_params', session, vm_ref, value)
1531 def VM_add_to_HVM_boot_params(self, session, vm_ref, key, value):
1532 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1533 if 'HVM_boot_params' not in dom.info:
1534 dom.info['HVM_boot_params'] = {}
1535 dom.info['HVM_boot_params'][key] = value
1536 return self._VM_save(dom)
1538 def VM_remove_from_HVM_boot_params(self, session, vm_ref, key):
1539 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1540 if 'HVM_boot_params' in dom.info \
1541 and key in dom.info['HVM_boot_params']:
1542 del dom.info['HVM_boot_params'][key]
1543 return self._VM_save(dom)
1544 else:
1545 return xen_api_success_void()
1547 def VM_set_PV_bootloader(self, session, vm_ref, value):
1548 return self.VM_set('PV_bootloader', session, vm_ref, value)
1550 def VM_set_PV_kernel(self, session, vm_ref, value):
1551 return self.VM_set('PV_kernel', session, vm_ref, value)
1553 def VM_set_PV_ramdisk(self, session, vm_ref, value):
1554 return self.VM_set('PV_ramdisk', session, vm_ref, value)
1556 def VM_set_PV_args(self, session, vm_ref, value):
1557 return self.VM_set('PV_args', session, vm_ref, value)
1559 def VM_set_PV_bootloader_args(self, session, vm_ref, value):
1560 return self.VM_set('PV_bootloader_args', session, vm_ref, value)
1562 def VM_set_platform(self, session, vm_ref, value):
1563 return self.VM_set('platform', session, vm_ref, value)
1565 def VM_add_to_platform(self, session, vm_ref, key, value):
1566 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1567 plat = dom.get_platform()
1568 plat[key] = value
1569 return self.VM_set_platform(session, vm_ref, plat)
1571 def VM_remove_from_platform(self, session, vm_ref, key):
1572 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1573 plat = dom.get_platform()
1574 if key in plat:
1575 del plat[key]
1576 return self.VM_set_platform(session, vm_ref, plat)
1577 else:
1578 return xen_api_success_void()
1580 def VM_set_other_config(self, session, vm_ref, value):
1581 return self.VM_set('other_config', session, vm_ref, value)
1583 def VM_add_to_other_config(self, session, vm_ref, key, value):
1584 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1585 if dom and 'other_config' in dom.info:
1586 dom.info['other_config'][key] = value
1587 return self._VM_save(dom)
1589 def VM_remove_from_other_config(self, session, vm_ref, key):
1590 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1591 if dom and 'other_config' in dom.info \
1592 and key in dom.info['other_config']:
1593 del dom.info['other_config'][key]
1594 return self._VM_save(dom)
1595 else:
1596 return xen_api_success_void()
1598 def VM_get_crash_dumps(self, _, vm_ref):
1599 return xen_api_todo()
1601 # class methods
1602 def VM_get_all(self, session):
1603 refs = [d.get_uuid() for d in XendDomain.instance().list('all')]
1604 return xen_api_success(refs)
1606 def VM_get_by_name_label(self, session, label):
1607 xendom = XendDomain.instance()
1608 dom = xendom.domain_lookup_nr(label)
1609 if dom:
1610 return xen_api_success([dom.get_uuid()])
1611 return xen_api_success([])
1613 def VM_get_security_label(self, session, vm_ref):
1614 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1615 label = dom.get_security_label()
1616 return xen_api_success(label)
1618 def VM_set_security_label(self, session, vm_ref, sec_label, old_label):
1619 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1620 (rc, errors, oldlabel, new_ssidref) = \
1621 dom.set_security_label(sec_label, old_label)
1622 if rc != xsconstants.XSERR_SUCCESS:
1623 return xen_api_error(['SECURITY_ERROR', rc,
1624 xsconstants.xserr2string(-rc)])
1625 if rc == 0:
1626 rc = new_ssidref
1627 return xen_api_success(rc)
1629 def VM_create(self, session, vm_struct):
1630 xendom = XendDomain.instance()
1631 domuuid = XendTask.log_progress(0, 100,
1632 xendom.create_domain, vm_struct)
1633 return xen_api_success(domuuid)
1635 # object methods
1636 def VM_get_record(self, session, vm_ref):
1637 xendom = XendDomain.instance()
1638 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1639 if not xeninfo:
1640 return xen_api_error(['HANDLE_INVALID', 'VM', vm_ref])
1642 domid = xeninfo.getDomid()
1644 record = {
1645 'uuid': xeninfo.get_uuid(),
1646 'power_state': xeninfo.get_power_state(),
1647 'name_label': xeninfo.getName(),
1648 'name_description': xeninfo.getName(),
1649 'user_version': 1,
1650 'is_a_template': xeninfo.info['is_a_template'],
1651 'auto_power_on': False,
1652 'resident_on': XendNode.instance().uuid,
1653 'memory_static_min': xeninfo.get_memory_static_min(),
1654 'memory_static_max': xeninfo.get_memory_static_max(),
1655 'memory_dynamic_min': xeninfo.get_memory_dynamic_min(),
1656 'memory_dynamic_max': xeninfo.get_memory_dynamic_max(),
1657 'VCPUs_params': xeninfo.get_vcpus_params(),
1658 'VCPUs_at_startup': xeninfo.getVCpuCount(),
1659 'VCPUs_max': xeninfo.getVCpuCount(),
1660 'actions_after_shutdown': xeninfo.get_on_shutdown(),
1661 'actions_after_reboot': xeninfo.get_on_reboot(),
1662 'actions_after_suspend': xeninfo.get_on_suspend(),
1663 'actions_after_crash': xeninfo.get_on_crash(),
1664 'consoles': xeninfo.get_consoles(),
1665 'VIFs': xeninfo.get_vifs(),
1666 'VBDs': xeninfo.get_vbds(),
1667 'VTPMs': xeninfo.get_vtpms(),
1668 'PV_bootloader': xeninfo.info.get('PV_bootloader'),
1669 'PV_kernel': xeninfo.info.get('PV_kernel'),
1670 'PV_ramdisk': xeninfo.info.get('PV_ramdisk'),
1671 'PV_args': xeninfo.info.get('PV_args'),
1672 'PV_bootloader_args': xeninfo.info.get('PV_bootloader_args'),
1673 'HVM_boot_policy': xeninfo.info.get('HVM_boot_policy'),
1674 'HVM_boot_params': xeninfo.info.get('HVM_boot_params'),
1675 'platform': xeninfo.get_platform(),
1676 'PCI_bus': xeninfo.get_pci_bus(),
1677 'tools_version': xeninfo.get_tools_version(),
1678 'other_config': xeninfo.info.get('other_config', {}),
1679 'domid': domid is None and -1 or domid,
1680 'is_control_domain': xeninfo.info['is_control_domain'],
1681 'metrics': xeninfo.get_metrics(),
1682 'security_label': xeninfo.get_security_label(),
1683 'crash_dumps': []
1685 return xen_api_success(record)
1687 def VM_clean_reboot(self, session, vm_ref):
1688 xendom = XendDomain.instance()
1689 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1690 XendTask.log_progress(0, 100, xeninfo.shutdown, "reboot")
1691 return xen_api_success_void()
1693 def VM_clean_shutdown(self, session, vm_ref):
1694 xendom = XendDomain.instance()
1695 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1696 XendTask.log_progress(0, 100, xeninfo.shutdown, "poweroff")
1697 return xen_api_success_void()
1699 def VM_clone(self, session, vm_ref):
1700 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1702 def VM_destroy(self, session, vm_ref):
1703 return XendTask.log_progress(0, 100, do_vm_func,
1704 "domain_delete", vm_ref)
1706 def VM_hard_reboot(self, session, vm_ref):
1707 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1709 def VM_hard_shutdown(self, session, vm_ref):
1710 return XendTask.log_progress(0, 100, do_vm_func,
1711 "domain_destroy", vm_ref)
1712 def VM_pause(self, session, vm_ref):
1713 return XendTask.log_progress(0, 100, do_vm_func,
1714 "domain_pause", vm_ref)
1716 def VM_resume(self, session, vm_ref, start_paused):
1717 return XendTask.log_progress(0, 100, do_vm_func,
1718 "domain_resume", vm_ref,
1719 start_paused = start_paused)
1721 def VM_start(self, session, vm_ref, start_paused):
1722 try:
1723 return XendTask.log_progress(0, 100, do_vm_func,
1724 "domain_start", vm_ref,
1725 start_paused = start_paused)
1726 except HVMRequired, exn:
1727 return xen_api_error(['VM_HVM_REQUIRED', vm_ref])
1729 def VM_suspend(self, session, vm_ref):
1730 return XendTask.log_progress(0, 100, do_vm_func,
1731 "domain_suspend", vm_ref)
1733 def VM_unpause(self, session, vm_ref):
1734 return XendTask.log_progress(0, 100, do_vm_func,
1735 "domain_unpause", vm_ref)
1737 def VM_send_sysrq(self, _, vm_ref, req):
1738 xeninfo = XendDomain.instance().get_vm_by_uuid(vm_ref)
1739 if xeninfo.state == XEN_API_VM_POWER_STATE_RUNNING \
1740 or xeninfo.state == XEN_API_VM_POWER_STATE_PAUSED:
1741 xeninfo.send_sysrq(req)
1742 return xen_api_success_void()
1743 else:
1744 return xen_api_error(
1745 ['VM_BAD_POWER_STATE', vm_ref,
1746 XendDomain.POWER_STATE_NAMES[XEN_API_VM_POWER_STATE_RUNNING],
1747 XendDomain.POWER_STATE_NAMES[xeninfo.state]])
1749 def VM_send_trigger(self, _, vm_ref, trigger, vcpu):
1750 xendom = XendDomain.instance()
1751 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1752 xendom.domain_send_trigger(xeninfo.getDomid(), trigger, vcpu)
1753 return xen_api_success_void()
1755 def VM_migrate(self, _, vm_ref, destination_url, live, other_config):
1756 xendom = XendDomain.instance()
1757 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1759 resource = other_config.get("resource", 0)
1760 port = other_config.get("port", 0)
1762 xendom.domain_migrate(xeninfo.getDomid(), destination_url,
1763 bool(live), resource, port)
1764 return xen_api_success_void()
1766 def VM_save(self, _, vm_ref, dest, checkpoint):
1767 xendom = XendDomain.instance()
1768 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1769 xendom.domain_save(xeninfo.getDomid(), dest, checkpoint)
1770 return xen_api_success_void()
1772 def VM_restore(self, _, src, paused):
1773 xendom = XendDomain.instance()
1774 xendom.domain_restore(src, bool(paused))
1775 return xen_api_success_void()
1778 # Xen API: Class VBD
1779 # ----------------------------------------------------------------
1781 VBD_attr_ro = ['VM',
1782 'VDI',
1783 'metrics',
1784 'runtime_properties']
1785 VBD_attr_rw = ['device',
1786 'bootable',
1787 'mode',
1788 'type']
1790 VBD_attr_inst = VBD_attr_rw
1792 VBD_methods = [('media_change', None), ('destroy', None)]
1793 VBD_funcs = [('create', 'VBD')]
1795 # object methods
1796 def VBD_get_record(self, session, vbd_ref):
1797 xendom = XendDomain.instance()
1798 vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1799 if not vm:
1800 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1801 cfg = vm.get_dev_xenapi_config('vbd', vbd_ref)
1802 if not cfg:
1803 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1805 valid_vbd_keys = self.VBD_attr_ro + self.VBD_attr_rw + \
1806 self.Base_attr_ro + self.Base_attr_rw
1808 return_cfg = {}
1809 for k in cfg.keys():
1810 if k in valid_vbd_keys:
1811 return_cfg[k] = cfg[k]
1813 return_cfg['metrics'] = vbd_ref
1814 return_cfg['runtime_properties'] = {} #todo
1816 return xen_api_success(return_cfg)
1818 def VBD_media_change(self, session, vbd_ref, vdi_ref):
1819 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1821 # class methods
1822 def VBD_create(self, session, vbd_struct):
1823 xendom = XendDomain.instance()
1824 xennode = XendNode.instance()
1826 if not xendom.is_valid_vm(vbd_struct['VM']):
1827 return xen_api_error(['HANDLE_INVALID', 'VM', vbd_struct['VM']])
1829 dom = xendom.get_vm_by_uuid(vbd_struct['VM'])
1830 vdi = xennode.get_vdi_by_uuid(vbd_struct['VDI'])
1831 if not vdi:
1832 return xen_api_error(['HANDLE_INVALID', 'VDI', vdi_ref])
1834 # new VBD via VDI/SR
1835 vdi_image = vdi.get_location()
1837 try:
1838 vbd_ref = XendTask.log_progress(0, 100,
1839 dom.create_vbd,
1840 vbd_struct, vdi_image)
1841 except XendError, e:
1842 log.exception("Error in VBD_create")
1843 return xen_api_error(['INTERNAL_ERROR', str(e)])
1845 vdi.addVBD(vbd_ref)
1847 xendom.managed_config_save(dom)
1848 return xen_api_success(vbd_ref)
1851 def VBD_destroy(self, session, vbd_ref):
1852 xendom = XendDomain.instance()
1853 vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1854 if not vm:
1855 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1857 vdi_ref = XendDomain.instance()\
1858 .get_dev_property_by_uuid('vbd', vbd_ref, "VDI")
1859 vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
1861 XendTask.log_progress(0, 100, vm.destroy_vbd, vbd_ref)
1863 vdi.removeVBD(vbd_ref)
1865 return xen_api_success_void()
1867 def _VBD_get(self, vbd_ref, prop):
1868 return xen_api_success(
1869 XendDomain.instance().get_dev_property_by_uuid(
1870 'vbd', vbd_ref, prop))
1872 # attributes (ro)
1873 def VBD_get_metrics(self, _, vbd_ref):
1874 return xen_api_success(vbd_ref)
1876 def VBD_get_runtime_properties(self, _, vbd_ref):
1877 xendom = XendDomain.instance()
1878 dominfo = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1879 device = dominfo.get_dev_config_by_uuid('vbd', vbd_ref)
1881 try:
1882 devid = int(device['id'])
1883 device_sxps = dominfo.getDeviceSxprs('vbd')
1884 device_dicts = [dict(device_sxp[1][0:]) for device_sxp in device_sxps]
1885 device_dict = [device_dict
1886 for device_dict in device_dicts
1887 if int(device_dict['virtual-device']) == devid][0]
1889 return xen_api_success(device_dict)
1890 except Exception, exn:
1891 log.exception(exn)
1892 return xen_api_success({})
1894 # attributes (rw)
1895 def VBD_get_VM(self, session, vbd_ref):
1896 return self._VBD_get(vbd_ref, 'VM')
1898 def VBD_get_VDI(self, session, vbd_ref):
1899 return self._VBD_get(vbd_ref, 'VDI')
1901 def VBD_get_device(self, session, vbd_ref):
1902 return self._VBD_get(vbd_ref, 'device')
1904 def VBD_get_bootable(self, session, vbd_ref):
1905 return self._VBD_get(vbd_ref, 'bootable')
1907 def VBD_get_mode(self, session, vbd_ref):
1908 return self._VBD_get(vbd_ref, 'mode')
1910 def VBD_get_type(self, session, vbd_ref):
1911 return self._VBD_get(vbd_ref, 'type')
1913 def VBD_set_bootable(self, session, vbd_ref, bootable):
1914 bootable = bool(bootable)
1915 xd = XendDomain.instance()
1916 vm = xd.get_vm_with_dev_uuid('vbd', vbd_ref)
1917 vm.set_dev_property('vbd', vbd_ref, 'bootable', bootable)
1918 xd.managed_config_save(vm)
1919 return xen_api_success_void()
1921 def VBD_set_mode(self, session, vbd_ref, mode):
1922 if mode == 'RW':
1923 mode = 'w'
1924 else:
1925 mode = 'r'
1926 xd = XendDomain.instance()
1927 vm = xd.get_vm_with_dev_uuid('vbd', vbd_ref)
1928 vm.set_dev_property('vbd', vbd_ref, 'mode', mode)
1929 xd.managed_config_save(vm)
1930 return xen_api_success_void()
1932 def VBD_get_all(self, session):
1933 xendom = XendDomain.instance()
1934 vbds = [d.get_vbds() for d in XendDomain.instance().list('all')]
1935 vbds = reduce(lambda x, y: x + y, vbds)
1936 return xen_api_success(vbds)
1939 # Xen API: Class VBD_metrics
1940 # ----------------------------------------------------------------
1942 VBD_metrics_attr_ro = ['io_read_kbs',
1943 'io_write_kbs',
1944 'last_updated']
1945 VBD_metrics_attr_rw = []
1946 VBD_metrics_methods = []
1948 def VBD_metrics_get_all(self, session):
1949 return self.VBD_get_all(session)
1951 def VBD_metrics_get_record(self, _, ref):
1952 vm = XendDomain.instance().get_vm_with_dev_uuid('vbd', ref)
1953 if not vm:
1954 return xen_api_error(['HANDLE_INVALID', 'VBD_metrics', ref])
1955 return xen_api_success(
1956 { 'io_read_kbs' : vm.get_dev_property('vbd', ref, 'io_read_kbs'),
1957 'io_write_kbs' : vm.get_dev_property('vbd', ref, 'io_write_kbs'),
1958 'last_updated' : now()
1959 })
1961 def VBD_metrics_get_io_read_kbs(self, _, ref):
1962 return self._VBD_get(ref, 'io_read_kbs')
1964 def VBD_metrics_get_io_write_kbs(self, session, ref):
1965 return self._VBD_get(ref, 'io_write_kbs')
1967 def VBD_metrics_get_last_updated(self, _1, _2):
1968 return xen_api_success(now())
1971 # Xen API: Class VIF
1972 # ----------------------------------------------------------------
1974 VIF_attr_ro = ['network',
1975 'VM',
1976 'metrics',
1977 'runtime_properties']
1978 VIF_attr_rw = ['device',
1979 'MAC',
1980 'MTU',
1981 'security_label']
1983 VIF_attr_inst = VIF_attr_rw
1985 VIF_methods = [('destroy', None)]
1986 VIF_funcs = [('create', 'VIF')]
1989 # object methods
1990 def VIF_get_record(self, session, vif_ref):
1991 xendom = XendDomain.instance()
1992 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
1993 if not vm:
1994 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
1995 cfg = vm.get_dev_xenapi_config('vif', vif_ref)
1996 if not cfg:
1997 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
1999 valid_vif_keys = self.VIF_attr_ro + self.VIF_attr_rw + \
2000 self.Base_attr_ro + self.Base_attr_rw
2002 return_cfg = {}
2003 for k in cfg.keys():
2004 if k in valid_vif_keys:
2005 return_cfg[k] = cfg[k]
2007 return_cfg['metrics'] = vif_ref
2009 return xen_api_success(return_cfg)
2011 # class methods
2012 def VIF_create(self, session, vif_struct):
2013 xendom = XendDomain.instance()
2014 if not xendom.is_valid_vm(vif_struct['VM']):
2015 return xen_api_error(['HANDLE_INVALID', 'VM', vif_struct['VM']])
2017 dom = xendom.get_vm_by_uuid(vif_struct['VM'])
2018 try:
2019 vif_ref = dom.create_vif(vif_struct)
2020 xendom.managed_config_save(dom)
2021 return xen_api_success(vif_ref)
2022 except XendError, exn:
2023 return xen_api_error(['INTERNAL_ERROR', str(exn)])
2025 def VIF_destroy(self, session, vif_ref):
2026 xendom = XendDomain.instance()
2027 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
2028 if not vm:
2029 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
2031 vm.destroy_vif(vif_ref)
2032 return xen_api_success_void()
2034 def _VIF_get(self, ref, prop):
2035 return xen_api_success(
2036 XendDomain.instance().get_dev_property_by_uuid('vif', ref, prop))
2038 # getters/setters
2039 def VIF_get_metrics(self, _, vif_ref):
2040 return xen_api_success(vif_ref)
2042 def VIF_get_VM(self, session, vif_ref):
2043 xendom = XendDomain.instance()
2044 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
2045 return xen_api_success(vm.get_uuid())
2047 def VIF_get_MTU(self, session, vif_ref):
2048 return self._VIF_get(vif_ref, 'MTU')
2050 def VIF_get_MAC(self, session, vif_ref):
2051 return self._VIF_get(vif_ref, 'MAC')
2053 def VIF_get_device(self, session, vif_ref):
2054 return self._VIF_get(vif_ref, 'device')
2056 def VIF_get_all(self, session):
2057 xendom = XendDomain.instance()
2058 vifs = [d.get_vifs() for d in XendDomain.instance().list('all')]
2059 vifs = reduce(lambda x, y: x + y, vifs)
2060 return xen_api_success(vifs)
2062 def VIF_get_runtime_properties(self, _, vif_ref):
2063 xendom = XendDomain.instance()
2064 dominfo = xendom.get_vm_with_dev_uuid('vif', vif_ref)
2065 device = dominfo.get_dev_config_by_uuid('vif', vif_ref)
2067 try:
2068 devid = int(device['id'])
2070 device_sxps = dominfo.getDeviceSxprs('vif')
2071 device_dicts = [dict(device_sxp[1][1:])
2072 for device_sxp in device_sxps]
2074 device_dict = [device_dict
2075 for device_dict in device_dicts
2076 if int(device_dict['handle']) == devid][0]
2078 return xen_api_success(device_dict)
2080 except Exception, exn:
2081 log.exception(exn)
2082 return xen_api_success({})
2084 def VIF_get_security_label(self, session, vif_ref):
2085 return self._VIF_get(vif_ref, 'security_label')
2087 def _VIF_set(self, ref, prop, val, old_val):
2088 return XendDomain.instance().set_dev_property_by_uuid(
2089 'vif', ref, prop, val, old_val)
2091 def VIF_set_security_label(self, session, vif_ref, sec_lab, old_lab):
2092 xendom = XendDomain.instance()
2093 dom = xendom.get_vm_with_dev_uuid('vif', vif_ref)
2094 if not dom:
2095 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
2097 if dom._stateGet() == XEN_API_VM_POWER_STATE_RUNNING:
2098 raise SecurityError(-xsconstants.XSERR_RESOURCE_IN_USE)
2100 rc = self._VIF_set(vif_ref, 'security_label', sec_lab, old_lab)
2101 if rc == False:
2102 raise SecurityError(-xsconstants.XSERR_BAD_LABEL)
2103 return xen_api_success(xsconstants.XSERR_SUCCESS)
2106 # Xen API: Class VIF_metrics
2107 # ----------------------------------------------------------------
2109 VIF_metrics_attr_ro = ['io_read_kbs',
2110 'io_write_kbs',
2111 'last_updated']
2112 VIF_metrics_attr_rw = []
2113 VIF_metrics_methods = []
2115 def VIF_metrics_get_all(self, session):
2116 return self.VIF_get_all(session)
2118 def VIF_metrics_get_record(self, _, ref):
2119 vm = XendDomain.instance().get_vm_with_dev_uuid('vif', ref)
2120 if not vm:
2121 return xen_api_error(['HANDLE_INVALID', 'VIF_metrics', ref])
2122 return xen_api_success(
2123 { 'io_read_kbs' : vm.get_dev_property('vif', ref, 'io_read_kbs'),
2124 'io_write_kbs' : vm.get_dev_property('vif', ref, 'io_write_kbs'),
2125 'last_updated' : now()
2126 })
2128 def VIF_metrics_get_io_read_kbs(self, _, ref):
2129 return self._VIF_get(ref, 'io_read_kbs')
2131 def VIF_metrics_get_io_write_kbs(self, session, ref):
2132 return self._VIF_get(ref, 'io_write_kbs')
2134 def VIF_metrics_get_last_updated(self, _1, _2):
2135 return xen_api_success(now())
2138 # Xen API: Class VDI
2139 # ----------------------------------------------------------------
2140 VDI_attr_ro = ['SR',
2141 'VBDs',
2142 'physical_utilisation',
2143 'type']
2144 VDI_attr_rw = ['name_label',
2145 'name_description',
2146 'virtual_size',
2147 'sharable',
2148 'read_only',
2149 'other_config',
2150 'security_label']
2151 VDI_attr_inst = VDI_attr_ro + VDI_attr_rw
2153 VDI_methods = [('destroy', None)]
2154 VDI_funcs = [('create', 'VDI'),
2155 ('get_by_name_label', 'Set(VDI)')]
2157 def _get_VDI(self, ref):
2158 return XendNode.instance().get_vdi_by_uuid(ref)
2160 def VDI_get_VBDs(self, session, vdi_ref):
2161 vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
2162 return xen_api_success(vdi.getVBDs())
2164 def VDI_get_physical_utilisation(self, session, vdi_ref):
2165 return xen_api_success(self._get_VDI(vdi_ref).
2166 get_physical_utilisation())
2168 def VDI_get_type(self, session, vdi_ref):
2169 return xen_api_success(self._get_VDI(vdi_ref).type)
2171 def VDI_get_name_label(self, session, vdi_ref):
2172 return xen_api_success(self._get_VDI(vdi_ref).name_label)
2174 def VDI_get_name_description(self, session, vdi_ref):
2175 return xen_api_success(self._get_VDI(vdi_ref).name_description)
2177 def VDI_get_SR(self, session, vdi_ref):
2178 return xen_api_success(self._get_VDI(vdi_ref).sr_uuid)
2180 def VDI_get_virtual_size(self, session, vdi_ref):
2181 return xen_api_success(self._get_VDI(vdi_ref).virtual_size)
2183 def VDI_get_sharable(self, session, vdi_ref):
2184 return xen_api_success(self._get_VDI(vdi_ref).sharable)
2186 def VDI_get_read_only(self, session, vdi_ref):
2187 return xen_api_success(self._get_VDI(vdi_ref).read_only)
2189 def VDI_set_name_label(self, session, vdi_ref, value):
2190 self._get_VDI(vdi_ref).name_label = value
2191 return xen_api_success_void()
2193 def VDI_set_name_description(self, session, vdi_ref, value):
2194 self._get_VDI(vdi_ref).name_description = value
2195 return xen_api_success_void()
2197 def VDI_set_virtual_size(self, session, vdi_ref, value):
2198 return xen_api_error(XEND_ERROR_UNSUPPORTED)
2200 def VDI_set_sharable(self, session, vdi_ref, value):
2201 self._get_VDI(vdi_ref).sharable = bool(value)
2202 return xen_api_success_void()
2204 def VDI_set_read_only(self, session, vdi_ref, value):
2205 self._get_VDI(vdi_ref).read_only = bool(value)
2206 return xen_api_success_void()
2208 def VDI_get_other_config(self, session, vdi_ref):
2209 return xen_api_success(
2210 self._get_VDI(vdi_ref).other_config)
2212 def VDI_set_other_config(self, session, vdi_ref, other_config):
2213 self._get_VDI(vdi_ref).other_config = other_config
2214 return xen_api_success_void()
2216 # Object Methods
2218 def VDI_destroy(self, session, vdi_ref):
2219 sr = XendNode.instance().get_sr_containing_vdi(vdi_ref)
2220 sr.destroy_vdi(vdi_ref)
2221 return xen_api_success_void()
2223 def VDI_get_record(self, session, vdi_ref):
2224 image = XendNode.instance().get_vdi_by_uuid(vdi_ref)
2225 return xen_api_success({
2226 'uuid': vdi_ref,
2227 'name_label': image.name_label,
2228 'name_description': image.name_description,
2229 'SR': image.sr_uuid,
2230 'VBDs': image.getVBDs(),
2231 'virtual_size': image.virtual_size,
2232 'physical_utilisation': image.physical_utilisation,
2233 'type': image.type,
2234 'sharable': image.sharable,
2235 'read_only': image.read_only,
2236 'other_config': image.other_config
2237 })
2239 # Class Functions
2240 def VDI_create(self, session, vdi_struct):
2241 sr_ref = vdi_struct.get('SR')
2242 xennode = XendNode.instance()
2243 if not xennode.is_valid_sr(sr_ref):
2244 return xen_api_error(['HANDLE_INVALID', 'SR', sr_ref])
2246 vdi_uuid = xennode.srs[sr_ref].create_vdi(vdi_struct)
2247 return xen_api_success(vdi_uuid)
2249 def VDI_get_all(self, session):
2250 xennode = XendNode.instance()
2251 vdis = [sr.get_vdis() for sr in xennode.srs.values()]
2252 return xen_api_success(reduce(lambda x, y: x + y, vdis))
2254 def VDI_get_by_name_label(self, session, name):
2255 xennode = XendNode.instance()
2256 return xen_api_success(xennode.get_vdi_by_name_label(name))
2258 def VDI_set_security_label(self, session, vdi_ref, sec_lab, old_lab):
2259 vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
2260 rc = vdi.set_security_label(sec_lab, old_lab)
2261 if rc < 0:
2262 return xen_api_error(['SECURITY_ERROR', rc,
2263 xsconstants.xserr2string(-rc)])
2264 return xen_api_success(rc)
2266 def VDI_get_security_label(self, session, vdi_ref):
2267 vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
2268 return xen_api_success(vdi.get_security_label())
2270 # Xen API: Class VTPM
2271 # ----------------------------------------------------------------
2273 VTPM_attr_rw = [ ]
2274 VTPM_attr_ro = ['VM',
2275 'backend',
2276 'runtime_properties' ]
2278 VTPM_attr_inst = VTPM_attr_rw
2280 VTPM_methods = [('destroy', None)]
2281 VTPM_funcs = [('create', 'VTPM')]
2283 # object methods
2284 def VTPM_get_record(self, session, vtpm_ref):
2285 xendom = XendDomain.instance()
2286 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
2287 if not vm:
2288 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
2289 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
2290 if not cfg:
2291 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
2292 valid_vtpm_keys = self.VTPM_attr_ro + self.VTPM_attr_rw + \
2293 self.Base_attr_ro + self.Base_attr_rw
2294 return_cfg = {}
2295 for k in cfg.keys():
2296 if k in valid_vtpm_keys:
2297 return_cfg[k] = cfg[k]
2299 return xen_api_success(return_cfg)
2301 # Class Functions
2302 def VTPM_get_backend(self, session, vtpm_ref):
2303 xendom = XendDomain.instance()
2304 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
2305 if not vm:
2306 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
2307 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
2308 if not cfg:
2309 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
2310 if not cfg.has_key('backend'):
2311 return xen_api_error(['INTERNAL_ERROR', 'VTPM backend not set'])
2312 return xen_api_success(cfg['backend'])
2314 def VTPM_get_VM(self, session, vtpm_ref):
2315 xendom = XendDomain.instance()
2316 return xen_api_success(xendom.get_dev_property_by_uuid('vtpm',
2317 vtpm_ref, 'VM'))
2319 def VTPM_destroy(self, session, vtpm_ref):
2320 xendom = XendDomain.instance()
2321 dom = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
2322 if dom:
2323 if dom.state != XEN_API_VM_POWER_STATE_HALTED:
2324 vm_ref = dom.get_dev_property('vtpm', vtpm_ref, 'VM')
2325 return xen_api_error(['VM_BAD_POWER_STATE', vm_ref,
2326 XendDomain.POWER_STATE_NAMES[XEN_API_VM_POWER_STATE_HALTED],
2327 XendDomain.POWER_STATE_NAMES[dom.state]])
2328 from xen.xend.server import tpmif
2329 tpmif.destroy_vtpmstate(dom.getName())
2330 return xen_api_success_void()
2331 else:
2332 return xen_api_error(['HANDLE_INVALID', 'VM', vtpm_struct['VM']])
2334 # class methods
2335 def VTPM_create(self, session, vtpm_struct):
2336 xendom = XendDomain.instance()
2337 if xendom.is_valid_vm(vtpm_struct['VM']):
2338 dom = xendom.get_vm_by_uuid(vtpm_struct['VM'])
2339 try:
2340 vtpm_ref = dom.create_vtpm(vtpm_struct)
2341 xendom.managed_config_save(dom)
2342 return xen_api_success(vtpm_ref)
2343 except XendError, exn:
2344 return xen_api_error(['INTERNAL_ERROR', str(exn)])
2345 else:
2346 return xen_api_error(['HANDLE_INVALID', 'VM', vtpm_struct['VM']])
2348 def VTPM_get_all(self, session):
2349 xendom = XendDomain.instance()
2350 vtpms = [d.get_vtpms() for d in XendDomain.instance().list('all')]
2351 vtpms = reduce(lambda x, y: x + y, vtpms)
2352 return xen_api_success(vtpms)
2354 def VTPM_get_runtime_properties(self, _, vtpm_ref):
2355 xendom = XendDomain.instance()
2356 dominfo = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
2357 device = dominfo.get_dev_config_by_uuid('vtpm', vtpm_ref)
2359 try:
2360 device_sxps = dominfo.getDeviceSxprs('vtpm')
2361 device_dict = dict(device_sxps[0][1])
2362 return xen_api_success(device_dict)
2363 except:
2364 return xen_api_success({})
2366 # Xen API: Class console
2367 # ----------------------------------------------------------------
2370 console_attr_ro = ['location', 'protocol', 'VM']
2371 console_attr_rw = ['other_config']
2372 console_funcs = [('create', 'console')]
2374 def console_get_all(self, session):
2375 xendom = XendDomain.instance()
2376 cons = [d.get_consoles() for d in XendDomain.instance().list('all')]
2377 cons = reduce(lambda x, y: x + y, cons)
2378 return xen_api_success(cons)
2380 def console_get_location(self, session, console_ref):
2381 xendom = XendDomain.instance()
2382 return xen_api_success(xendom.get_dev_property_by_uuid('console',
2383 console_ref,
2384 'location'))
2386 def console_get_protocol(self, session, console_ref):
2387 xendom = XendDomain.instance()
2388 return xen_api_success(xendom.get_dev_property_by_uuid('console',
2389 console_ref,
2390 'protocol'))
2392 def console_get_VM(self, session, console_ref):
2393 xendom = XendDomain.instance()
2394 vm = xendom.get_vm_with_dev_uuid('console', console_ref)
2395 return xen_api_success(vm.get_uuid())
2397 # object methods
2398 def console_get_record(self, session, console_ref):
2399 xendom = XendDomain.instance()
2400 vm = xendom.get_vm_with_dev_uuid('console', console_ref)
2401 if not vm:
2402 return xen_api_error(['HANDLE_INVALID', 'console', console_ref])
2403 cfg = vm.get_dev_xenapi_config('console', console_ref)
2404 if not cfg:
2405 return xen_api_error(['HANDLE_INVALID', 'console', console_ref])
2407 valid_console_keys = self.console_attr_ro + self.console_attr_rw + \
2408 self.Base_attr_ro + self.Base_attr_rw
2410 return_cfg = {}
2411 for k in cfg.keys():
2412 if k in valid_console_keys:
2413 return_cfg[k] = cfg[k]
2415 return xen_api_success(return_cfg)
2417 def console_create(self, session, console_struct):
2418 xendom = XendDomain.instance()
2419 if not xendom.is_valid_vm(console_struct['VM']):
2420 return xen_api_error(['HANDLE_INVALID', 'VM',
2421 console_struct['VM']])
2423 dom = xendom.get_vm_by_uuid(console_struct['VM'])
2424 try:
2425 if 'protocol' not in console_struct:
2426 return xen_api_error(['CONSOLE_PROTOCOL_INVALID',
2427 'No protocol specified'])
2429 console_ref = dom.create_console(console_struct)
2430 xendom.managed_config_save(dom)
2431 return xen_api_success(console_ref)
2432 except XendError, exn:
2433 return xen_api_error(['INTERNAL_ERROR', str(exn)])
2435 # Xen API: Class SR
2436 # ----------------------------------------------------------------
2437 SR_attr_ro = ['VDIs',
2438 'virtual_allocation',
2439 'physical_utilisation',
2440 'physical_size',
2441 'type',
2442 'content_type']
2444 SR_attr_rw = ['name_label',
2445 'name_description']
2447 SR_attr_inst = ['physical_size',
2448 'type',
2449 'name_label',
2450 'name_description']
2452 SR_methods = []
2453 SR_funcs = [('get_by_name_label', 'Set(SR)'),
2454 ('get_by_uuid', 'SR')]
2456 # Class Functions
2457 def SR_get_all(self, session):
2458 return xen_api_success(XendNode.instance().get_all_sr_uuid())
2460 def SR_get_by_name_label(self, session, label):
2461 return xen_api_success(XendNode.instance().get_sr_by_name(label))
2463 def SR_get_supported_types(self, _):
2464 return xen_api_success(['local', 'qcow_file'])
2466 # Class Methods
2468 def SR_get_record(self, session, sr_ref):
2469 sr = XendNode.instance().get_sr(sr_ref)
2470 if sr:
2471 return xen_api_success(sr.get_record())
2472 return xen_api_error(['HANDLE_INVALID', 'SR', sr_ref])
2474 # Attribute acceess
2476 def _get_SR_func(self, sr_ref, func):
2477 return xen_api_success(getattr(XendNode.instance().get_sr(sr_ref),
2478 func)())
2480 def _get_SR_attr(self, sr_ref, attr):
2481 return xen_api_success(getattr(XendNode.instance().get_sr(sr_ref),
2482 attr))
2484 def SR_get_VDIs(self, _, ref):
2485 return self._get_SR_func(ref, 'list_images')
2487 def SR_get_virtual_allocation(self, _, ref):
2488 return self._get_SR_func(ref, 'virtual_allocation')
2490 def SR_get_physical_utilisation(self, _, ref):
2491 return self._get_SR_func(ref, 'physical_utilisation')
2493 def SR_get_physical_size(self, _, ref):
2494 return self._get_SR_func(ref, 'physical_size')
2496 def SR_get_type(self, _, ref):
2497 return self._get_SR_attr(ref, 'type')
2499 def SR_get_content_type(self, _, ref):
2500 return self._get_SR_attr(ref, 'content_type')
2502 def SR_get_name_label(self, _, ref):
2503 return self._get_SR_attr(ref, 'name_label')
2505 def SR_get_name_description(self, _, ref):
2506 return self._get_SR_attr(ref, 'name_description')
2508 def SR_set_name_label(self, session, sr_ref, value):
2509 sr = XendNode.instance.get_sr(sr_ref)
2510 if sr:
2511 sr.name_label = value
2512 XendNode.instance().save()
2513 return xen_api_success_void()
2515 def SR_set_name_description(self, session, sr_ref, value):
2516 sr = XendNode.instance.get_sr(sr_ref)
2517 if sr:
2518 sr.name_description = value
2519 XendNode.instance().save()
2520 return xen_api_success_void()
2523 # Xen API: Class event
2524 # ----------------------------------------------------------------
2526 event_attr_ro = []
2527 event_attr_rw = []
2528 event_funcs = [('register', None),
2529 ('unregister', None),
2530 ('next', None)]
2532 def event_register(self, session, reg_classes):
2533 event_register(session, reg_classes)
2534 return xen_api_success_void()
2536 def event_unregister(self, session, unreg_classes):
2537 event_unregister(session, reg_classes)
2538 return xen_api_success_void()
2540 def event_next(self, session):
2541 return event_next(session)
2543 # Xen API: Class debug
2544 # ----------------------------------------------------------------
2546 debug_methods = [('destroy', None),
2547 ('get_record', 'debug')]
2548 debug_funcs = [('wait', None),
2549 ('return_failure', None)]
2551 def debug_wait(self, session, wait_secs):
2552 import time
2553 prog_units = 100/float(wait_secs)
2554 for i in range(int(wait_secs)):
2555 XendTask.log_progress(prog_units * i, prog_units * (i + 1),
2556 time.sleep, 1)
2557 return xen_api_success_void()
2560 def debug_return_failure(self, session):
2561 return xen_api_error(['DEBUG_FAIL', session])
2563 def debug_create(self, session):
2564 debug_uuid = uuid.createString()
2565 self._debug[debug_uuid] = None
2566 return xen_api_success(debug_uuid)
2568 def debug_destroy(self, session, debug_ref):
2569 del self._debug[debug_ref]
2570 return xen_api_success_void()
2572 def debug_get_record(self, session, debug_ref):
2573 return xen_api_success({'uuid': debug_ref})
2576 class XendAPIAsyncProxy:
2577 """ A redirector for Async.Class.function calls to XendAPI
2578 but wraps the call for use with the XendTaskManager.
2580 @ivar xenapi: Xen API instance
2581 @ivar method_map: Mapping from XMLRPC method name to callable objects.
2582 """
2584 method_prefix = 'Async.'
2586 def __init__(self, xenapi):
2587 """Initialises the Async Proxy by making a map of all
2588 implemented Xen API methods for use with XendTaskManager.
2590 @param xenapi: XendAPI instance
2591 """
2592 self.xenapi = xenapi
2593 self.method_map = {}
2594 for method_name in dir(self.xenapi):
2595 method = getattr(self.xenapi, method_name)
2596 if method_name[0] != '_' and hasattr(method, 'async') \
2597 and method.async == True:
2598 self.method_map[method.api] = method
2600 def _dispatch(self, method, args):
2601 """Overridden method so that SimpleXMLRPCServer will
2602 resolve methods through this method rather than through
2603 inspection.
2605 @param method: marshalled method name from XMLRPC.
2606 @param args: marshalled arguments from XMLRPC.
2607 """
2609 # Only deal with method names that start with "Async."
2610 if not method.startswith(self.method_prefix):
2611 return xen_api_error(['MESSAGE_METHOD_UNKNOWN', method])
2613 # Lookup synchronous version of the method
2614 synchronous_method_name = method[len(self.method_prefix):]
2615 if synchronous_method_name not in self.method_map:
2616 return xen_api_error(['MESSAGE_METHOD_UNKNOWN', method])
2618 method = self.method_map[synchronous_method_name]
2620 # Check that we've got enough arguments before issuing a task ID.
2621 needed = argcounts[method.api]
2622 if len(args) != needed:
2623 return xen_api_error(['MESSAGE_PARAMETER_COUNT_MISMATCH',
2624 self.method_prefix + method.api, needed,
2625 len(args)])
2627 # Validate the session before proceeding
2628 session = args[0]
2629 if not auth_manager().is_session_valid(session):
2630 return xen_api_error(['SESSION_INVALID', session])
2632 # create and execute the task, and return task_uuid
2633 return_type = getattr(method, 'return_type', None)
2634 task_uuid = XendTaskManager.create_task(method, args,
2635 synchronous_method_name,
2636 return_type,
2637 synchronous_method_name,
2638 session)
2639 return xen_api_success(task_uuid)