ia64/xen-unstable

view tools/python/xen/xend/XendAPI.py @ 18816:368e072feb29

xenapi: fix valid_object typo

Signed-off-by: Zhigang Wang <zhigang.x.wang@oracle.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Nov 20 14:14:20 2008 +0000 (2008-11-20)
parents 9404bcb6d32e
children 5ae8ed54e2cd
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 XendPPCI import XendPPCI
44 from XendDPCI import XendDPCI
45 from XendPSCSI import XendPSCSI
46 from XendDSCSI import XendDSCSI
47 from XendXSPolicy import XendXSPolicy, XendACMPolicy
49 from XendAPIConstants import *
50 from xen.util.xmlrpclib2 import stringify
52 from xen.util.blkif import blkdev_name_to_number
53 from xen.util import xsconstants
56 AUTH_NONE = 'none'
57 AUTH_PAM = 'pam'
59 argcounts = {}
61 # ------------------------------------------
62 # Utility Methods for Xen API Implementation
63 # ------------------------------------------
65 def xen_api_success(value):
66 """Wraps a return value in XenAPI format."""
67 if value is None:
68 s = ''
69 else:
70 s = stringify(value)
71 return {"Status": "Success", "Value": s}
73 def xen_api_success_void():
74 """Return success, but caller expects no return value."""
75 return xen_api_success("")
77 def xen_api_error(error):
78 """Wraps an error value in XenAPI format."""
79 if type(error) == tuple:
80 error = list(error)
81 if type(error) != list:
82 error = [error]
83 if len(error) == 0:
84 error = ['INTERNAL_ERROR', 'Empty list given to xen_api_error']
86 return { "Status": "Failure",
87 "ErrorDescription": [str(x) for x in error] }
90 def xen_api_todo():
91 """Temporary method to make sure we track down all the TODOs"""
92 return {"Status": "Error", "ErrorDescription": XEND_ERROR_TODO}
95 def now():
96 return datetime()
99 def datetime(when = None):
100 """Marshall the given time as a Xen-API DateTime.
102 @param when The time in question, given as seconds since the epoch, UTC.
103 May be None, in which case the current time is used.
104 """
105 if when is None:
106 return xmlrpclib.DateTime(time.gmtime())
107 else:
108 return xmlrpclib.DateTime(time.gmtime(when))
111 # ---------------------------------------------------
112 # Event dispatch
113 # ---------------------------------------------------
115 EVENT_QUEUE_LENGTH = 50
116 event_registrations = {}
118 def event_register(session, reg_classes):
119 if session not in event_registrations:
120 event_registrations[session] = {
121 'classes' : sets.Set(),
122 'queue' : Queue.Queue(EVENT_QUEUE_LENGTH),
123 'next-id' : 1
124 }
125 if not reg_classes:
126 reg_classes = classes
127 event_registrations[session]['classes'].union_update(reg_classes)
130 def event_unregister(session, unreg_classes):
131 if session not in event_registrations:
132 return
134 if unreg_classes:
135 event_registrations[session]['classes'].intersection_update(
136 unreg_classes)
137 if len(event_registrations[session]['classes']) == 0:
138 del event_registrations[session]
139 else:
140 del event_registrations[session]
143 def event_next(session):
144 if session not in event_registrations:
145 return xen_api_error(['SESSION_NOT_REGISTERED', session])
146 queue = event_registrations[session]['queue']
147 events = [queue.get()]
148 try:
149 while True:
150 events.append(queue.get(False))
151 except Queue.Empty:
152 pass
154 return xen_api_success(events)
157 def _ctor_event_dispatch(xenapi, ctor, api_cls, session, args):
158 result = ctor(xenapi, session, *args)
159 if result['Status'] == 'Success':
160 ref = result['Value']
161 event_dispatch('add', api_cls, ref, '')
162 return result
165 def _dtor_event_dispatch(xenapi, dtor, api_cls, session, ref, args):
166 result = dtor(xenapi, session, ref, *args)
167 if result['Status'] == 'Success':
168 event_dispatch('del', api_cls, ref, '')
169 return result
172 def _setter_event_dispatch(xenapi, setter, api_cls, attr_name, session, ref,
173 args):
174 result = setter(xenapi, session, ref, *args)
175 if result['Status'] == 'Success':
176 event_dispatch('mod', api_cls, ref, attr_name)
177 return result
180 def event_dispatch(operation, api_cls, ref, attr_name):
181 assert operation in ['add', 'del', 'mod']
182 event = {
183 'timestamp' : now(),
184 'class' : api_cls,
185 'operation' : operation,
186 'ref' : ref,
187 'obj_uuid' : ref,
188 'field' : attr_name,
189 }
190 for reg in event_registrations.values():
191 if api_cls in reg['classes']:
192 event['id'] = reg['next-id']
193 reg['next-id'] += 1
194 reg['queue'].put(event)
197 # ---------------------------------------------------
198 # Python Method Decorators for input value validation
199 # ---------------------------------------------------
201 def trace(func, api_name = ''):
202 """Decorator to trace XMLRPC Xen API methods.
204 @param func: function with any parameters
205 @param api_name: name of the api call for debugging.
206 """
207 if hasattr(func, 'api'):
208 api_name = func.api
209 def trace_func(self, *args, **kwargs):
210 log.debug('%s: %s' % (api_name, args))
211 return func(self, *args, **kwargs)
212 trace_func.api = api_name
213 return trace_func
216 def catch_typeerror(func):
217 """Decorator to catch any TypeErrors and translate them into Xen-API
218 errors.
220 @param func: function with params: (self, ...)
221 @rtype: callable object
222 """
223 def f(self, *args, **kwargs):
224 try:
225 return func(self, *args, **kwargs)
226 except TypeError, exn:
227 #log.exception('catch_typeerror')
228 if hasattr(func, 'api') and func.api in argcounts:
229 # Assume that if the argument count was wrong and if the
230 # exception was thrown inside this file, then it is due to an
231 # invalid call from the client, otherwise it's an internal
232 # error (which will be handled further up).
233 expected = argcounts[func.api]
234 actual = len(args) + len(kwargs)
235 if expected != actual:
236 tb = sys.exc_info()[2]
237 try:
238 sourcefile = traceback.extract_tb(tb)[-1][0]
239 if sourcefile == inspect.getsourcefile(XendAPI):
240 return xen_api_error(
241 ['MESSAGE_PARAMETER_COUNT_MISMATCH',
242 func.api, expected, actual])
243 finally:
244 del tb
245 raise
246 except XendAPIError, exn:
247 return xen_api_error(exn.get_api_error())
249 return f
252 def session_required(func):
253 """Decorator to verify if session is valid before calling method.
255 @param func: function with params: (self, session, ...)
256 @rtype: callable object
257 """
258 def check_session(self, session, *args, **kwargs):
259 if auth_manager().is_session_valid(session):
260 return func(self, session, *args, **kwargs)
261 else:
262 return xen_api_error(['SESSION_INVALID', session])
264 return check_session
267 def _is_valid_ref(ref, validator):
268 return type(ref) == str and validator(ref)
270 def _check_ref(validator, clas, func, api, session, ref, *args, **kwargs):
271 if _is_valid_ref(ref, validator):
272 return func(api, session, ref, *args, **kwargs)
273 else:
274 return xen_api_error(['HANDLE_INVALID', clas, ref])
277 def valid_host(func):
278 """Decorator to verify if host_ref is valid before calling method.
280 @param func: function with params: (self, session, host_ref, ...)
281 @rtype: callable object
282 """
283 return lambda *args, **kwargs: \
284 _check_ref(XendNode.instance().is_valid_host,
285 'host', func, *args, **kwargs)
287 def valid_host_metrics(func):
288 """Decorator to verify if host_metrics_ref is valid before calling
289 method.
291 @param func: function with params: (self, session, host_metrics_ref)
292 @rtype: callable object
293 """
294 return lambda *args, **kwargs: \
295 _check_ref(lambda r: r == XendNode.instance().host_metrics_uuid,
296 'host_metrics', func, *args, **kwargs)
298 def valid_host_cpu(func):
299 """Decorator to verify if host_cpu_ref is valid before calling method.
301 @param func: function with params: (self, session, host_cpu_ref, ...)
302 @rtype: callable object
303 """
304 return lambda *args, **kwargs: \
305 _check_ref(XendNode.instance().is_valid_cpu,
306 'host_cpu', func, *args, **kwargs)
308 def valid_vm(func):
309 """Decorator to verify if vm_ref is valid before calling method.
311 @param func: function with params: (self, session, vm_ref, ...)
312 @rtype: callable object
313 """
314 return lambda *args, **kwargs: \
315 _check_ref(XendDomain.instance().is_valid_vm,
316 'VM', func, *args, **kwargs)
318 def valid_vbd(func):
319 """Decorator to verify if vbd_ref is valid before calling method.
321 @param func: function with params: (self, session, vbd_ref, ...)
322 @rtype: callable object
323 """
324 return lambda *args, **kwargs: \
325 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vbd', r),
326 'VBD', func, *args, **kwargs)
328 def valid_vbd_metrics(func):
329 """Decorator to verify if ref is valid before calling method.
331 @param func: function with params: (self, session, ref, ...)
332 @rtype: callable object
333 """
334 return lambda *args, **kwargs: \
335 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vbd', r),
336 'VBD_metrics', func, *args, **kwargs)
338 def valid_vif(func):
339 """Decorator to verify if vif_ref is valid before calling method.
341 @param func: function with params: (self, session, vif_ref, ...)
342 @rtype: callable object
343 """
344 return lambda *args, **kwargs: \
345 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vif', r),
346 'VIF', func, *args, **kwargs)
348 def valid_vif_metrics(func):
349 """Decorator to verify if ref is valid before calling method.
351 @param func: function with params: (self, session, ref, ...)
352 @rtype: callable object
353 """
354 return lambda *args, **kwargs: \
355 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vif', r),
356 'VIF_metrics', func, *args, **kwargs)
358 def valid_vdi(func):
359 """Decorator to verify if vdi_ref is valid before calling method.
361 @param func: function with params: (self, session, vdi_ref, ...)
362 @rtype: callable object
363 """
364 return lambda *args, **kwargs: \
365 _check_ref(XendNode.instance().is_valid_vdi,
366 'VDI', func, *args, **kwargs)
368 def valid_vtpm(func):
369 """Decorator to verify if vtpm_ref is valid before calling method.
371 @param func: function with params: (self, session, vtpm_ref, ...)
372 @rtype: callable object
373 """
374 return lambda *args, **kwargs: \
375 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vtpm', r),
376 'VTPM', func, *args, **kwargs)
379 def valid_console(func):
380 """Decorator to verify if console_ref is valid before calling method.
382 @param func: function with params: (self, session, console_ref, ...)
383 @rtype: callable object
384 """
385 return lambda *args, **kwargs: \
386 _check_ref(lambda r: XendDomain.instance().is_valid_dev('console',
387 r),
388 'console', func, *args, **kwargs)
390 def valid_sr(func):
391 """Decorator to verify if sr_ref is valid before calling method.
393 @param func: function with params: (self, session, sr_ref, ...)
394 @rtype: callable object
395 """
396 return lambda *args, **kwargs: \
397 _check_ref(lambda r: XendNode.instance().is_valid_sr,
398 'SR', func, *args, **kwargs)
400 def valid_task(func):
401 """Decorator to verify if task_ref is valid before calling
402 method.
404 @param func: function with params: (self, session, task_ref)
405 @rtype: callable object
406 """
407 return lambda *args, **kwargs: \
408 _check_ref(XendTaskManager.get_task,
409 'task', func, *args, **kwargs)
411 def valid_debug(func):
412 """Decorator to verify if task_ref is valid before calling
413 method.
415 @param func: function with params: (self, session, task_ref)
416 @rtype: callable object
417 """
418 return lambda *args, **kwargs: \
419 _check_ref(lambda r: r in XendAPI._debug,
420 'debug', func, *args, **kwargs)
423 def valid_object(class_name):
424 """Decorator to verify if object is valid before calling
425 method.
427 @param func: function with params: (self, session, pif_ref)
428 @rtype: callable object
429 """
430 return lambda func: \
431 lambda *args, **kwargs: \
432 _check_ref(lambda r: \
433 XendAPIStore.get(r, class_name) is not None,
434 class_name, func, *args, **kwargs)
436 # -----------------------------
437 # Bridge to Legacy XM API calls
438 # -----------------------------
440 def do_vm_func(fn_name, vm_ref, *args, **kwargs):
441 """Helper wrapper func to abstract away from repetitive code.
443 @param fn_name: function name for XendDomain instance
444 @type fn_name: string
445 @param vm_ref: vm_ref
446 @type vm_ref: string
447 @param *args: more arguments
448 @type *args: tuple
449 """
450 try:
451 xendom = XendDomain.instance()
452 fn = getattr(xendom, fn_name)
453 xendom.do_legacy_api_with_uuid(fn, vm_ref, *args, **kwargs)
454 return xen_api_success_void()
455 except VMBadState, exn:
456 return xen_api_error(['VM_BAD_POWER_STATE', vm_ref, exn.expected,
457 exn.actual])
460 classes = {
461 'session' : None,
462 'event' : None,
463 'host' : valid_host,
464 'host_cpu' : valid_host_cpu,
465 'host_metrics' : valid_host_metrics,
466 'VM' : valid_vm,
467 'VBD' : valid_vbd,
468 'VBD_metrics' : valid_vbd_metrics,
469 'VIF' : valid_vif,
470 'VIF_metrics' : valid_vif_metrics,
471 'VDI' : valid_vdi,
472 'VTPM' : valid_vtpm,
473 'console' : valid_console,
474 'SR' : valid_sr,
475 'task' : valid_task,
476 'XSPolicy' : valid_object("XSPolicy"),
477 'ACMPolicy' : valid_object("ACMPolicy"),
478 'debug' : valid_debug,
479 'network' : valid_object("network"),
480 'PIF' : valid_object("PIF"),
481 'VM_metrics' : valid_object("VM_metrics"),
482 'PBD' : valid_object("PBD"),
483 'PIF_metrics' : valid_object("PIF_metrics"),
484 'PPCI' : valid_object("PPCI"),
485 'DPCI' : valid_object("DPCI"),
486 'PSCSI' : valid_object("PSCSI"),
487 'DSCSI' : valid_object("DSCSI")
488 }
490 autoplug_classes = {
491 'network' : XendNetwork,
492 'PIF' : XendPIF,
493 'VM_metrics' : XendVMMetrics,
494 'PBD' : XendPBD,
495 'PIF_metrics' : XendPIFMetrics,
496 'PPCI' : XendPPCI,
497 'DPCI' : XendDPCI,
498 'PSCSI' : XendPSCSI,
499 'DSCSI' : XendDSCSI,
500 'XSPolicy' : XendXSPolicy,
501 'ACMPolicy' : XendACMPolicy,
502 }
504 class XendAPI(object):
505 """Implementation of the Xen-API in Xend. Expects to be
506 used via XMLRPCServer.
508 All methods that need a valid session are marked with
509 a L{session_required} decorator that will
510 transparently perform the required session authentication.
512 We need to support Python <2.4, so we use the old decorator syntax.
514 All XMLRPC accessible methods require an 'api' attribute and
515 is set to the XMLRPC function name which the method implements.
516 """
518 __decorated__ = False
519 __init_lock__ = threading.Lock()
520 _debug = {}
522 def __new__(cls, *args, **kwds):
523 """ Override __new__ to decorate the class only once.
525 Lock to make sure the classes are not decorated twice.
526 """
527 cls.__init_lock__.acquire()
528 try:
529 if not cls.__decorated__:
530 cls._decorate()
531 cls.__decorated__ = True
533 return object.__new__(cls, *args, **kwds)
534 finally:
535 cls.__init_lock__.release()
537 def _decorate(cls):
538 """ Decorate all the object methods to have validators
539 and appropriate function attributes.
541 This should only be executed once for the duration of the
542 server.
543 """
544 global_validators = [session_required, catch_typeerror]
547 # Cheat methods
548 # -------------
549 # Methods that have a trivial implementation for all classes.
550 # 1. get_by_uuid == getting by ref, so just return uuid for
551 # all get_by_uuid() methods.
553 for api_cls in classes.keys():
554 # We'll let the autoplug classes implement these functions
555 # themselves - its much cleaner to do it in the base class
556 if api_cls == 'session' or api_cls in autoplug_classes.keys():
557 continue
559 get_by_uuid = '%s_get_by_uuid' % api_cls
560 get_uuid = '%s_get_uuid' % api_cls
561 get_all_records = '%s_get_all_records' % api_cls
563 def _get_by_uuid(_1, _2, ref):
564 return xen_api_success(ref)
566 def _get_uuid(_1, _2, ref):
567 return xen_api_success(ref)
569 def unpack(v):
570 return v.get('Value')
572 def _get_all_records(_api_cls):
573 return lambda s, session: \
574 xen_api_success(dict([(ref, unpack(getattr(cls, '%s_get_record' % _api_cls)(s, session, ref)))\
575 for ref in unpack(getattr(cls, '%s_get_all' % _api_cls)(s, session))]))
577 setattr(cls, get_by_uuid, _get_by_uuid)
578 setattr(cls, get_uuid, _get_uuid)
579 setattr(cls, get_all_records, _get_all_records(api_cls))
581 # Autoplugging classes
582 # --------------------
583 # These have all of their methods grabbed out from the implementation
584 # class, and wrapped up to be compatible with the Xen-API.
586 def getter(ref, type):
587 return XendAPIStore.get(ref, type)
589 for api_cls, impl_cls in autoplug_classes.items():
590 def doit(n):
591 dot_n = '%s.%s' % (api_cls, n)
592 full_n = '%s_%s' % (api_cls, n)
593 if not hasattr(cls, full_n):
594 f = getattr(impl_cls, n)
595 argcounts[dot_n] = f.func_code.co_argcount + 1
596 g = lambda api_cls: \
597 setattr(cls, full_n, \
598 lambda s, session, ref, *args: \
599 xen_api_success( \
600 f(getter(ref, api_cls), *args)))
601 g(api_cls) # Force api_cls to be captured
603 def doit_func(n):
604 dot_n = '%s.%s' % (api_cls, n)
605 full_n = '%s_%s' % (api_cls, n)
606 if not hasattr(cls, full_n):
607 f = getattr(impl_cls, n)
608 argcounts[dot_n] = f.func_code.co_argcount
609 setattr(cls, full_n, \
610 lambda s, session, *args: \
611 xen_api_success( \
612 f(*args)))
614 ro_attrs = impl_cls.getAttrRO()
615 rw_attrs = impl_cls.getAttrRW()
616 methods = impl_cls.getMethods()
617 funcs = impl_cls.getFuncs()
619 for attr_name in ro_attrs + rw_attrs:
620 doit('get_%s' % attr_name)
621 for attr_name in rw_attrs:
622 doit('set_%s' % attr_name)
623 for method in methods:
624 doit('%s' % method)
625 for func in funcs:
626 doit_func('%s' % func)
628 def wrap_method(name, new_f):
629 try:
630 f = getattr(cls, name)
631 wrapped_f = (lambda *args: new_f(f, *args))
632 wrapped_f.api = f.api
633 wrapped_f.async = f.async
634 setattr(cls, name, wrapped_f)
635 except AttributeError:
636 # Logged below (API call: %s not found)
637 pass
640 def setter_event_wrapper(api_cls, attr_name):
641 setter_name = '%s_set_%s' % (api_cls, attr_name)
642 wrap_method(
643 setter_name,
644 lambda setter, s, session, ref, *args:
645 _setter_event_dispatch(s, setter, api_cls, attr_name,
646 session, ref, args))
649 def ctor_event_wrapper(api_cls):
650 ctor_name = '%s_create' % api_cls
651 wrap_method(
652 ctor_name,
653 lambda ctor, s, session, *args:
654 _ctor_event_dispatch(s, ctor, api_cls, session, args))
657 def dtor_event_wrapper(api_cls):
658 dtor_name = '%s_destroy' % api_cls
659 wrap_method(
660 dtor_name,
661 lambda dtor, s, session, ref, *args:
662 _dtor_event_dispatch(s, dtor, api_cls, session, ref, args))
665 # Wrapping validators around XMLRPC calls
666 # ---------------------------------------
668 for api_cls, validator in classes.items():
669 def doit(n, takes_instance, async_support = False,
670 return_type = None):
671 n_ = n.replace('.', '_')
672 try:
673 f = getattr(cls, n_)
674 if n not in argcounts:
675 argcounts[n] = f.func_code.co_argcount - 1
677 validators = takes_instance and validator and \
678 [validator] or []
680 validators += global_validators
681 for v in validators:
682 f = v(f)
683 f.api = n
684 f.async = async_support
685 if return_type:
686 f.return_type = return_type
688 setattr(cls, n_, f)
689 except AttributeError:
690 log.warn("API call: %s not found" % n)
692 if api_cls in autoplug_classes.keys():
693 impl_cls = autoplug_classes[api_cls]
694 ro_attrs = impl_cls.getAttrRO()
695 rw_attrs = impl_cls.getAttrRW()
696 methods = map(lambda x: (x, ""), impl_cls.getMethods())
697 funcs = map(lambda x: (x, ""), impl_cls.getFuncs())
698 else:
699 ro_attrs = getattr(cls, '%s_attr_ro' % api_cls, []) \
700 + cls.Base_attr_ro
701 rw_attrs = getattr(cls, '%s_attr_rw' % api_cls, []) \
702 + cls.Base_attr_rw
703 methods = getattr(cls, '%s_methods' % api_cls, []) \
704 + cls.Base_methods
705 funcs = getattr(cls, '%s_funcs' % api_cls, []) \
706 + cls.Base_funcs
708 # wrap validators around readable class attributes
709 for attr_name in ro_attrs + rw_attrs:
710 doit('%s.get_%s' % (api_cls, attr_name), True,
711 async_support = False)
713 # wrap validators around writable class attrributes
714 for attr_name in rw_attrs:
715 doit('%s.set_%s' % (api_cls, attr_name), True,
716 async_support = False)
717 setter_event_wrapper(api_cls, attr_name)
719 # wrap validators around methods
720 for method_name, return_type in methods:
721 doit('%s.%s' % (api_cls, method_name), True,
722 async_support = True)
724 # wrap validators around class functions
725 for func_name, return_type in funcs:
726 doit('%s.%s' % (api_cls, func_name), False,
727 async_support = True,
728 return_type = return_type)
730 ctor_event_wrapper(api_cls)
731 dtor_event_wrapper(api_cls)
734 _decorate = classmethod(_decorate)
736 def __init__(self, auth):
737 self.auth = auth
739 Base_attr_ro = ['uuid']
740 Base_attr_rw = []
741 Base_methods = [('get_record', 'Struct')]
742 Base_funcs = [('get_all', 'Set'), ('get_by_uuid', None), ('get_all_records', 'Set')]
744 # Xen API: Class Session
745 # ----------------------------------------------------------------
746 # NOTE: Left unwrapped by __init__
748 session_attr_ro = ['this_host', 'this_user', 'last_active']
749 session_methods = [('logout', None)]
751 def session_get_all(self, session):
752 return xen_api_success([session])
754 def session_login_with_password(self, *args):
755 if len(args) != 2:
756 return xen_api_error(
757 ['MESSAGE_PARAMETER_COUNT_MISMATCH',
758 'session.login_with_password', 2, len(args)])
759 username = args[0]
760 password = args[1]
761 try:
762 session = ((self.auth == AUTH_NONE and
763 auth_manager().login_unconditionally(username)) or
764 auth_manager().login_with_password(username, password))
765 return xen_api_success(session)
766 except XendError, e:
767 return xen_api_error(['SESSION_AUTHENTICATION_FAILED'])
768 session_login_with_password.api = 'session.login_with_password'
770 # object methods
771 def session_logout(self, session):
772 auth_manager().logout(session)
773 return xen_api_success_void()
775 def session_get_record(self, session, self_session):
776 if self_session != session:
777 return xen_api_error(['PERMISSION_DENIED'])
778 record = {'uuid' : session,
779 'this_host' : XendNode.instance().uuid,
780 'this_user' : auth_manager().get_user(session),
781 'last_active': now()}
782 return xen_api_success(record)
784 def session_get_uuid(self, session, self_session):
785 return xen_api_success(self_session)
787 def session_get_by_uuid(self, session, self_session):
788 return xen_api_success(self_session)
790 # attributes (ro)
791 def session_get_this_host(self, session, self_session):
792 if self_session != session:
793 return xen_api_error(['PERMISSION_DENIED'])
794 return xen_api_success(XendNode.instance().uuid)
796 def session_get_this_user(self, session, self_session):
797 if self_session != session:
798 return xen_api_error(['PERMISSION_DENIED'])
799 user = auth_manager().get_user(session)
800 if user is not None:
801 return xen_api_success(user)
802 return xen_api_error(['SESSION_INVALID', session])
804 def session_get_last_active(self, session, self_session):
805 if self_session != session:
806 return xen_api_error(['PERMISSION_DENIED'])
807 return xen_api_success(now())
810 # Xen API: Class User
811 # ----------------------------------------------------------------
812 # TODO: NOT IMPLEMENTED YET
814 # Xen API: Class Tasks
815 # ----------------------------------------------------------------
817 task_attr_ro = ['name_label',
818 'name_description',
819 'status',
820 'progress',
821 'type',
822 'result',
823 'error_info',
824 'allowed_operations',
825 'session'
826 ]
828 task_attr_rw = []
830 task_funcs = [('get_by_name_label', 'Set(task)'),
831 ('cancel', None)]
833 def task_get_name_label(self, session, task_ref):
834 task = XendTaskManager.get_task(task_ref)
835 return xen_api_success(task.name_label)
837 def task_get_name_description(self, session, task_ref):
838 task = XendTaskManager.get_task(task_ref)
839 return xen_api_success(task.name_description)
841 def task_get_status(self, session, task_ref):
842 task = XendTaskManager.get_task(task_ref)
843 return xen_api_success(task.get_status())
845 def task_get_progress(self, session, task_ref):
846 task = XendTaskManager.get_task(task_ref)
847 return xen_api_success(task.progress)
849 def task_get_type(self, session, task_ref):
850 task = XendTaskManager.get_task(task_ref)
851 return xen_api_success(task.type)
853 def task_get_result(self, session, task_ref):
854 task = XendTaskManager.get_task(task_ref)
855 return xen_api_success(task.result)
857 def task_get_error_info(self, session, task_ref):
858 task = XendTaskManager.get_task(task_ref)
859 return xen_api_success(task.error_info)
861 def task_get_allowed_operations(self, session, task_ref):
862 return xen_api_success({})
864 def task_get_session(self, session, task_ref):
865 task = XendTaskManager.get_task(task_ref)
866 return xen_api_success(task.session)
868 def task_get_all(self, session):
869 tasks = XendTaskManager.get_all_tasks()
870 return xen_api_success(tasks)
872 def task_get_record(self, session, task_ref):
873 task = XendTaskManager.get_task(task_ref)
874 return xen_api_success(task.get_record())
876 def task_cancel(self, session, task_ref):
877 return xen_api_error('OPERATION_NOT_ALLOWED')
879 def task_get_by_name_label(self, session, name):
880 return xen_api_success(XendTaskManager.get_task_by_name(name))
882 # Xen API: Class host
883 # ----------------------------------------------------------------
885 host_attr_ro = ['software_version',
886 'resident_VMs',
887 'PBDs',
888 'PIFs',
889 'PPCIs',
890 'PSCSIs',
891 'host_CPUs',
892 'cpu_configuration',
893 'metrics',
894 'capabilities',
895 'supported_bootloaders',
896 'sched_policy',
897 'API_version_major',
898 'API_version_minor',
899 'API_version_vendor',
900 'API_version_vendor_implementation',
901 'enabled']
903 host_attr_rw = ['name_label',
904 'name_description',
905 'other_config',
906 'logging']
908 host_methods = [('disable', None),
909 ('enable', None),
910 ('reboot', None),
911 ('shutdown', None),
912 ('add_to_other_config', None),
913 ('remove_from_other_config', None),
914 ('dmesg', 'String'),
915 ('dmesg_clear', 'String'),
916 ('get_log', 'String'),
917 ('send_debug_keys', None)]
919 host_funcs = [('get_by_name_label', None),
920 ('list_methods', None)]
922 # attributes
923 def host_get_name_label(self, session, host_ref):
924 return xen_api_success(XendNode.instance().name)
925 def host_set_name_label(self, session, host_ref, new_name):
926 XendNode.instance().set_name(new_name)
927 return xen_api_success_void()
928 def host_get_name_description(self, session, host_ref):
929 return xen_api_success(XendNode.instance().get_description())
930 def host_set_name_description(self, session, host_ref, new_desc):
931 XendNode.instance().set_description(new_desc)
932 return xen_api_success_void()
933 def host_get_other_config(self, session, host_ref):
934 return xen_api_success(XendNode.instance().other_config)
935 def host_set_other_config(self, session, host_ref, other_config):
936 node = XendNode.instance()
937 node.other_config = dict(other_config)
938 node.save()
939 return xen_api_success_void()
940 def host_add_to_other_config(self, session, host_ref, key, value):
941 node = XendNode.instance()
942 node.other_config[key] = value
943 node.save()
944 return xen_api_success_void()
945 def host_remove_from_other_config(self, session, host_ref, key):
946 node = XendNode.instance()
947 if key in node.other_config:
948 del node.other_config[key]
949 node.save()
950 return xen_api_success_void()
951 def host_get_API_version_major(self, _, ref):
952 return xen_api_success(XEN_API_VERSION_MAJOR)
953 def host_get_API_version_minor(self, _, ref):
954 return xen_api_success(XEN_API_VERSION_MINOR)
955 def host_get_API_version_vendor(self, _, ref):
956 return xen_api_success(XEN_API_VERSION_VENDOR)
957 def host_get_API_version_vendor_implementation(self, _, ref):
958 return xen_api_success(XEN_API_VERSION_VENDOR_IMPLEMENTATION)
959 def host_get_software_version(self, session, host_ref):
960 return xen_api_success(XendNode.instance().xen_version())
961 def host_get_enabled(self, _1, _2):
962 return xen_api_success(XendDomain.instance().allow_new_domains())
963 def host_get_resident_VMs(self, session, host_ref):
964 return xen_api_success(XendDomain.instance().get_domain_refs())
965 def host_get_PBDs(self, _, ref):
966 return xen_api_success(XendPBD.get_all())
967 def host_get_PIFs(self, session, ref):
968 return xen_api_success(XendNode.instance().get_PIF_refs())
969 def host_get_PPCIs(self, session, ref):
970 return xen_api_success(XendNode.instance().get_PPCI_refs())
971 def host_get_PSCSIs(self, session, ref):
972 return xen_api_success(XendNode.instance().get_PSCSI_refs())
973 def host_get_host_CPUs(self, session, host_ref):
974 return xen_api_success(XendNode.instance().get_host_cpu_refs())
975 def host_get_metrics(self, _, ref):
976 return xen_api_success(XendNode.instance().host_metrics_uuid)
977 def host_get_capabilities(self, session, host_ref):
978 return xen_api_success(XendNode.instance().get_capabilities())
979 def host_get_supported_bootloaders(self, session, host_ref):
980 return xen_api_success(['pygrub'])
981 def host_get_sched_policy(self, _, host_ref):
982 return xen_api_success(XendNode.instance().get_vcpus_policy())
983 def host_get_cpu_configuration(self, _, host_ref):
984 return xen_api_success(XendNode.instance().get_cpu_configuration())
985 def host_set_logging(self, _, host_ref, logging):
986 return xen_api_todo()
987 def host_get_logging(self, _, host_ref):
988 return xen_api_todo()
990 # object methods
991 def host_disable(self, session, host_ref):
992 XendDomain.instance().set_allow_new_domains(False)
993 return xen_api_success_void()
994 def host_enable(self, session, host_ref):
995 XendDomain.instance().set_allow_new_domains(True)
996 return xen_api_success_void()
997 def host_reboot(self, session, host_ref):
998 if not XendDomain.instance().allow_new_domains():
999 return xen_api_error(XEND_ERROR_HOST_RUNNING)
1000 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1001 def host_shutdown(self, session, host_ref):
1002 if not XendDomain.instance().allow_new_domains():
1003 return xen_api_error(XEND_ERROR_HOST_RUNNING)
1004 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1006 def host_dmesg(self, session, host_ref):
1007 return xen_api_success(XendDmesg.instance().info())
1009 def host_dmesg_clear(self, session, host_ref):
1010 return xen_api_success(XendDmesg.instance().clear())
1012 def host_get_log(self, session, host_ref):
1013 log_file = open(XendLogging.getLogFilename())
1014 log_buffer = log_file.read()
1015 log_buffer = log_buffer.replace('\b', ' ')
1016 log_buffer = log_buffer.replace('\f', '\n')
1017 log_file.close()
1018 return xen_api_success(log_buffer)
1020 def host_send_debug_keys(self, _, host_ref, keys):
1021 node = XendNode.instance()
1022 node.send_debug_keys(keys)
1023 return xen_api_success_void()
1025 def host_get_record(self, session, host_ref):
1026 node = XendNode.instance()
1027 dom = XendDomain.instance()
1028 record = {'uuid': node.uuid,
1029 'name_label': node.name,
1030 'name_description': '',
1031 'API_version_major': XEN_API_VERSION_MAJOR,
1032 'API_version_minor': XEN_API_VERSION_MINOR,
1033 'API_version_vendor': XEN_API_VERSION_VENDOR,
1034 'API_version_vendor_implementation':
1035 XEN_API_VERSION_VENDOR_IMPLEMENTATION,
1036 'software_version': node.xen_version(),
1037 'enabled': XendDomain.instance().allow_new_domains(),
1038 'other_config': node.other_config,
1039 'resident_VMs': dom.get_domain_refs(),
1040 'host_CPUs': node.get_host_cpu_refs(),
1041 'cpu_configuration': node.get_cpu_configuration(),
1042 'metrics': node.host_metrics_uuid,
1043 'capabilities': node.get_capabilities(),
1044 'supported_bootloaders': ['pygrub'],
1045 'sched_policy': node.get_vcpus_policy(),
1046 'logging': {},
1047 'PIFs': XendPIF.get_all(),
1048 'PBDs': XendPBD.get_all(),
1049 'PPCIs': XendPPCI.get_all(),
1050 'PSCSIs': XendPSCSI.get_all()}
1051 return xen_api_success(record)
1053 # class methods
1054 def host_get_all(self, session):
1055 return xen_api_success((XendNode.instance().uuid,))
1056 def host_get_by_name_label(self, session, name):
1057 if XendNode.instance().name == name:
1058 return xen_api_success((XendNode.instance().uuid,))
1059 return xen_api_success([])
1061 def host_list_methods(self, _):
1062 def _funcs():
1063 return [getattr(XendAPI, x) for x in XendAPI.__dict__]
1065 return xen_api_success([x.api for x in _funcs()
1066 if hasattr(x, 'api')])
1068 # Xen API: Class host_CPU
1069 # ----------------------------------------------------------------
1071 host_cpu_attr_ro = ['host',
1072 'number',
1073 'vendor',
1074 'speed',
1075 'modelname',
1076 'stepping',
1077 'flags',
1078 'utilisation',
1079 'features']
1081 # attributes
1082 def _host_cpu_get(self, ref, field):
1083 return xen_api_success(
1084 XendNode.instance().get_host_cpu_field(ref, field))
1086 def host_cpu_get_host(self, _, ref):
1087 return xen_api_success(XendNode.instance().uuid)
1088 def host_cpu_get_features(self, _, ref):
1089 return self._host_cpu_get(ref, 'features')
1090 def host_cpu_get_number(self, _, ref):
1091 return self._host_cpu_get(ref, 'number')
1092 def host_cpu_get_vendor(self, _, ref):
1093 return self._host_cpu_get(ref, 'vendor')
1094 def host_cpu_get_speed(self, _, ref):
1095 return self._host_cpu_get(ref, 'speed')
1096 def host_cpu_get_modelname(self, _, ref):
1097 return self._host_cpu_get(ref, 'modelname')
1098 def host_cpu_get_stepping(self, _, ref):
1099 return self._host_cpu_get(ref, 'stepping')
1100 def host_cpu_get_flags(self, _, ref):
1101 return self._host_cpu_get(ref, 'flags')
1102 def host_cpu_get_utilisation(self, _, ref):
1103 return xen_api_success(XendNode.instance().get_host_cpu_load(ref))
1105 # object methods
1106 def host_cpu_get_record(self, _, ref):
1107 node = XendNode.instance()
1108 record = dict([(f, node.get_host_cpu_field(ref, f))
1109 for f in self.host_cpu_attr_ro
1110 if f not in ['uuid', 'host', 'utilisation']])
1111 record['uuid'] = ref
1112 record['host'] = node.uuid
1113 record['utilisation'] = node.get_host_cpu_load(ref)
1114 return xen_api_success(record)
1116 # class methods
1117 def host_cpu_get_all(self, session):
1118 return xen_api_success(XendNode.instance().get_host_cpu_refs())
1121 # Xen API: Class host_metrics
1122 # ----------------------------------------------------------------
1124 host_metrics_attr_ro = ['memory_total',
1125 'memory_free',
1126 'last_updated']
1127 host_metrics_attr_rw = []
1128 host_metrics_methods = []
1130 def host_metrics_get_all(self, _):
1131 return xen_api_success([XendNode.instance().host_metrics_uuid])
1133 def _host_metrics_get(self, ref, f):
1134 return xen_api_success(getattr(node, f)())
1136 def host_metrics_get_record(self, _, ref):
1137 return xen_api_success({
1138 'uuid' : ref,
1139 'memory_total' : self._host_metrics_get_memory_total(),
1140 'memory_free' : self._host_metrics_get_memory_free(),
1141 'last_updated' : now(),
1142 })
1144 def host_metrics_get_memory_total(self, _1, _2):
1145 return xen_api_success(self._host_metrics_get_memory_total())
1147 def host_metrics_get_memory_free(self, _1, _2):
1148 return xen_api_success(self._host_metrics_get_memory_free())
1150 def host_metrics_get_last_updated(self, _1, _2):
1151 return xen_api_success(now())
1153 def _host_metrics_get_memory_total(self):
1154 node = XendNode.instance()
1155 return node.xc.physinfo()['total_memory'] * 1024
1157 def _host_metrics_get_memory_free(self):
1158 node = XendNode.instance()
1159 return node.xc.physinfo()['free_memory'] * 1024
1161 # Xen API: Class VM
1162 # ----------------------------------------------------------------
1164 VM_attr_ro = ['power_state',
1165 'resident_on',
1166 'consoles',
1167 'VIFs',
1168 'VBDs',
1169 'VTPMs',
1170 'DPCIs',
1171 'DSCSIs',
1172 'tools_version',
1173 'domid',
1174 'is_control_domain',
1175 'metrics',
1176 'crash_dumps',
1179 VM_attr_rw = ['name_label',
1180 'name_description',
1181 'user_version',
1182 'is_a_template',
1183 'auto_power_on',
1184 'memory_dynamic_max',
1185 'memory_dynamic_min',
1186 'memory_static_max',
1187 'memory_static_min',
1188 'VCPUs_max',
1189 'VCPUs_at_startup',
1190 'VCPUs_params',
1191 'actions_after_shutdown',
1192 'actions_after_reboot',
1193 'actions_after_suspend',
1194 'actions_after_crash',
1195 'PV_bootloader',
1196 'PV_kernel',
1197 'PV_ramdisk',
1198 'PV_args',
1199 'PV_bootloader_args',
1200 'HVM_boot_policy',
1201 'HVM_boot_params',
1202 'platform',
1203 'PCI_bus',
1204 'other_config',
1205 'security_label']
1207 VM_methods = [('clone', 'VM'),
1208 ('start', None),
1209 ('pause', None),
1210 ('unpause', None),
1211 ('clean_shutdown', None),
1212 ('clean_reboot', None),
1213 ('hard_shutdown', None),
1214 ('hard_reboot', None),
1215 ('suspend', None),
1216 ('resume', None),
1217 ('send_sysrq', None),
1218 ('set_VCPUs_number_live', None),
1219 ('add_to_HVM_boot_params', None),
1220 ('remove_from_HVM_boot_params', None),
1221 ('add_to_VCPUs_params', None),
1222 ('add_to_VCPUs_params_live', None),
1223 ('remove_from_VCPUs_params', None),
1224 ('add_to_platform', None),
1225 ('remove_from_platform', None),
1226 ('add_to_other_config', None),
1227 ('remove_from_other_config', None),
1228 ('save', None),
1229 ('set_memory_dynamic_max_live', None),
1230 ('set_memory_dynamic_min_live', None),
1231 ('send_trigger', None),
1232 ('migrate', None),
1233 ('destroy', None)]
1235 VM_funcs = [('create', 'VM'),
1236 ('restore', None),
1237 ('get_by_name_label', 'Set(VM)')]
1239 # parameters required for _create()
1240 VM_attr_inst = [
1241 'name_label',
1242 'name_description',
1243 'user_version',
1244 'is_a_template',
1245 'memory_static_max',
1246 'memory_dynamic_max',
1247 'memory_dynamic_min',
1248 'memory_static_min',
1249 'VCPUs_max',
1250 'VCPUs_at_startup',
1251 'VCPUs_params',
1252 'actions_after_shutdown',
1253 'actions_after_reboot',
1254 'actions_after_suspend',
1255 'actions_after_crash',
1256 'PV_bootloader',
1257 'PV_kernel',
1258 'PV_ramdisk',
1259 'PV_args',
1260 'PV_bootloader_args',
1261 'HVM_boot_policy',
1262 'HVM_boot_params',
1263 'platform',
1264 'PCI_bus',
1265 'other_config',
1266 'security_label']
1268 def VM_get(self, name, session, vm_ref):
1269 return xen_api_success(
1270 XendDomain.instance().get_vm_by_uuid(vm_ref).info[name])
1272 def VM_set(self, name, session, vm_ref, value):
1273 xd = XendDomain.instance()
1274 dominfo = xd.get_vm_by_uuid(vm_ref)
1275 dominfo.info[name] = value
1276 return self._VM_save(dominfo)
1278 def _VM_save(self, dominfo):
1279 XendDomain.instance().managed_config_save(dominfo)
1280 return xen_api_success_void()
1282 # attributes (ro)
1283 def VM_get_power_state(self, session, vm_ref):
1284 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1285 return xen_api_success(dom.get_power_state())
1287 def VM_get_resident_on(self, session, vm_ref):
1288 return xen_api_success(XendNode.instance().uuid)
1290 def VM_get_memory_static_max(self, session, vm_ref):
1291 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1292 return xen_api_success(dom.get_memory_static_max())
1294 def VM_get_memory_static_min(self, session, vm_ref):
1295 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1296 return xen_api_success(dom.get_memory_static_min())
1298 def VM_get_VIFs(self, session, vm_ref):
1299 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1300 return xen_api_success(dom.get_vifs())
1302 def VM_get_VBDs(self, session, vm_ref):
1303 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1304 return xen_api_success(dom.get_vbds())
1306 def VM_get_VTPMs(self, session, vm_ref):
1307 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1308 return xen_api_success(dom.get_vtpms())
1310 def VM_get_consoles(self, session, vm_ref):
1311 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1312 return xen_api_success(dom.get_consoles())
1314 def VM_get_DPCIs(self, session, vm_ref):
1315 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1316 return xen_api_success(dom.get_dpcis())
1318 def VM_get_DSCSIs(self, session, vm_ref):
1319 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1320 return xen_api_success(dom.get_dscsis())
1322 def VM_get_tools_version(self, session, vm_ref):
1323 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1324 return dom.get_tools_version()
1326 def VM_get_metrics(self, _, vm_ref):
1327 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1328 return xen_api_success(dom.get_metrics())
1330 def VM_get_VCPUs_max(self, _, vm_ref):
1331 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1332 return xen_api_todo()
1334 def VM_get_VCPUs_at_startup(self, _, vm_ref):
1335 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1336 return xen_api_todo()
1338 # attributes (rw)
1339 def VM_get_name_label(self, session, vm_ref):
1340 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1341 return xen_api_success(dom.getName())
1343 def VM_get_name_description(self, session, vm_ref):
1344 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1345 return xen_api_todo()
1347 def VM_get_user_version(self, session, vm_ref):
1348 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1349 return xen_api_todo()
1351 def VM_get_is_a_template(self, session, ref):
1352 return self.VM_get('is_a_template', session, ref)
1354 def VM_get_memory_dynamic_max(self, session, vm_ref):
1355 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1356 return xen_api_success(dom.get_memory_dynamic_max())
1358 def VM_get_memory_dynamic_min(self, session, vm_ref):
1359 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1360 return xen_api_success(dom.get_memory_dynamic_min())
1362 def VM_get_VCPUs_params(self, session, vm_ref):
1363 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1364 return xen_api_success(dom.get_vcpus_params())
1366 def VM_get_actions_after_shutdown(self, session, vm_ref):
1367 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1368 return xen_api_success(dom.get_on_shutdown())
1370 def VM_get_actions_after_reboot(self, session, vm_ref):
1371 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1372 return xen_api_success(dom.get_on_reboot())
1374 def VM_get_actions_after_suspend(self, session, vm_ref):
1375 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1376 return xen_api_success(dom.get_on_suspend())
1378 def VM_get_actions_after_crash(self, session, vm_ref):
1379 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1380 return xen_api_success(dom.get_on_crash())
1382 def VM_get_PV_bootloader(self, session, vm_ref):
1383 return self.VM_get('PV_bootloader', session, vm_ref)
1385 def VM_get_PV_kernel(self, session, vm_ref):
1386 return self.VM_get('PV_kernel', session, vm_ref)
1388 def VM_get_PV_ramdisk(self, session, vm_ref):
1389 return self.VM_get('PV_ramdisk', session, vm_ref)
1391 def VM_get_PV_args(self, session, vm_ref):
1392 return self.VM_get('PV_args', session, vm_ref)
1394 def VM_get_PV_bootloader_args(self, session, vm_ref):
1395 return self.VM_get('PV_bootloader_args', session, vm_ref)
1397 def VM_get_HVM_boot_policy(self, session, vm_ref):
1398 return self.VM_get('HVM_boot_policy', session, vm_ref)
1400 def VM_get_HVM_boot_params(self, session, vm_ref):
1401 return self.VM_get('HVM_boot_params', session, vm_ref)
1403 def VM_get_platform(self, session, vm_ref):
1404 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1405 return xen_api_success(dom.get_platform())
1407 def VM_get_PCI_bus(self, session, vm_ref):
1408 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1409 return dom.get_pci_bus()
1411 def VM_set_PCI_bus(self, session, vm_ref, val):
1412 return self.VM_set('PCI_bus', session, vm_ref, val)
1414 def VM_get_other_config(self, session, vm_ref):
1415 return self.VM_get('other_config', session, vm_ref)
1417 def VM_get_domid(self, _, ref):
1418 domid = XendDomain.instance().get_vm_by_uuid(ref).getDomid()
1419 return xen_api_success(domid is None and -1 or domid)
1421 def VM_get_is_control_domain(self, session, vm_ref):
1422 xd = XendDomain.instance()
1423 return xen_api_success(
1424 xd.get_vm_by_uuid(vm_ref) == xd.privilegedDomain())
1426 def VM_set_name_label(self, session, vm_ref, label):
1427 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1428 dom.setName(label)
1429 return self._VM_save(dom)
1431 def VM_set_name_description(self, session, vm_ref, desc):
1432 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1433 return xen_api_todo()
1435 def VM_set_user_version(self, session, vm_ref, ver):
1436 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1437 return xen_api_todo()
1439 def VM_set_is_a_template(self, session, vm_ref, is_template):
1440 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1441 return xen_api_todo()
1443 def VM_set_memory_dynamic_max(self, session, vm_ref, mem):
1444 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1445 dom.set_memory_dynamic_max(int(mem))
1446 return self._VM_save(dom)
1448 def VM_set_memory_dynamic_min(self, session, vm_ref, mem):
1449 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1450 dom.set_memory_dynamic_min(int(mem))
1451 return self._VM_save(dom)
1453 def VM_set_memory_static_max(self, session, vm_ref, mem):
1454 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1455 dom.set_memory_static_max(int(mem))
1456 return self._VM_save(dom)
1458 def VM_set_memory_static_min(self, session, vm_ref, mem):
1459 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1460 dom.set_memory_static_min(int(mem))
1461 return self._VM_save(dom)
1463 def VM_set_memory_dynamic_max_live(self, session, vm_ref, mem):
1464 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1465 dom.set_memory_dynamic_max(int(mem))
1466 # need to pass target as MiB
1467 dom.setMemoryTarget(int(mem)/1024/1024)
1468 return xen_api_success_void()
1470 def VM_set_memory_dynamic_min_live(self, session, vm_ref, mem):
1471 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1472 dom.set_memory_dynamic_min(int(mem))
1473 # need to pass target as MiB
1474 dom.setMemoryTarget(int(mem)/1024/1024)
1475 return xen_api_success_void()
1477 def VM_set_VCPUs_params(self, session, vm_ref, value):
1478 return self.VM_set('vcpus_params', session, vm_ref, value)
1480 def VM_add_to_VCPUs_params(self, session, vm_ref, key, value):
1481 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1482 if 'vcpus_params' not in dom.info:
1483 dom.info['vcpus_params'] = {}
1484 dom.info['vcpus_params'][key] = value
1485 return self._VM_save(dom)
1487 def VM_add_to_VCPUs_params_live(self, session, vm_ref, key, value):
1488 self.VM_add_to_VCPUs_params(session, vm_ref, key, value)
1489 self._VM_VCPUs_params_refresh(vm_ref)
1490 return xen_api_success_void()
1492 def _VM_VCPUs_params_refresh(self, vm_ref):
1493 xendom = XendDomain.instance()
1494 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1496 #update the cpumaps
1497 for key, value in xeninfo.info['vcpus_params'].items():
1498 if key.startswith("cpumap"):
1499 vcpu = int(key[6:])
1500 try:
1501 cpus = map(int, value.split(","))
1502 xendom.domain_pincpu(xeninfo.getDomid(), vcpu, cpus)
1503 except Exception, ex:
1504 log.exception(ex)
1506 #need to update sched params aswell
1507 if 'weight' in xeninfo.info['vcpus_params'] \
1508 and 'cap' in xeninfo.info['vcpus_params']:
1509 weight = xeninfo.info['vcpus_params']['weight']
1510 cap = xeninfo.info['vcpus_params']['cap']
1511 xendom.domain_sched_credit_set(xeninfo.getDomid(), weight, cap)
1513 def VM_set_VCPUs_number_live(self, _, vm_ref, num):
1514 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1515 dom.setVCpuCount(int(num))
1516 return xen_api_success_void()
1518 def VM_remove_from_VCPUs_params(self, session, vm_ref, key):
1519 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1520 if 'vcpus_params' in dom.info \
1521 and key in dom.info['vcpus_params']:
1522 del dom.info['vcpus_params'][key]
1523 return self._VM_save(dom)
1524 else:
1525 return xen_api_success_void()
1527 def VM_set_VCPUs_at_startup(self, session, vm_ref, num):
1528 return self.VM_set('VCPUs_at_startup', session, vm_ref, num)
1530 def VM_set_VCPUs_max(self, session, vm_ref, num):
1531 return self.VM_set('VCPUs_max', session, vm_ref, num)
1533 def VM_set_actions_after_shutdown(self, session, vm_ref, action):
1534 if action not in XEN_API_ON_NORMAL_EXIT:
1535 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1536 return self.VM_set('actions_after_shutdown', session, vm_ref, action)
1538 def VM_set_actions_after_reboot(self, session, vm_ref, action):
1539 if action not in XEN_API_ON_NORMAL_EXIT:
1540 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1541 return self.VM_set('actions_after_reboot', session, vm_ref, action)
1543 def VM_set_actions_after_suspend(self, session, vm_ref, action):
1544 if action not in XEN_API_ON_NORMAL_EXIT:
1545 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1546 return self.VM_set('actions_after_suspend', session, vm_ref, action)
1548 def VM_set_actions_after_crash(self, session, vm_ref, action):
1549 if action not in XEN_API_ON_CRASH_BEHAVIOUR:
1550 return xen_api_error(['VM_ON_CRASH_BEHAVIOUR_INVALID', vm_ref])
1551 return self.VM_set('actions_after_crash', session, vm_ref, action)
1553 def VM_set_HVM_boot_policy(self, session, vm_ref, value):
1554 if value != "" and value != "BIOS order":
1555 return xen_api_error(
1556 ['VALUE_NOT_SUPPORTED', 'VM.HVM_boot_policy', value,
1557 'Xend supports only the "BIOS order" boot policy.'])
1558 else:
1559 return self.VM_set('HVM_boot_policy', session, vm_ref, value)
1561 def VM_set_HVM_boot_params(self, session, vm_ref, value):
1562 return self.VM_set('HVM_boot_params', session, vm_ref, value)
1564 def VM_add_to_HVM_boot_params(self, session, vm_ref, key, value):
1565 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1566 if 'HVM_boot_params' not in dom.info:
1567 dom.info['HVM_boot_params'] = {}
1568 dom.info['HVM_boot_params'][key] = value
1569 return self._VM_save(dom)
1571 def VM_remove_from_HVM_boot_params(self, session, vm_ref, key):
1572 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1573 if 'HVM_boot_params' in dom.info \
1574 and key in dom.info['HVM_boot_params']:
1575 del dom.info['HVM_boot_params'][key]
1576 return self._VM_save(dom)
1577 else:
1578 return xen_api_success_void()
1580 def VM_set_PV_bootloader(self, session, vm_ref, value):
1581 return self.VM_set('PV_bootloader', session, vm_ref, value)
1583 def VM_set_PV_kernel(self, session, vm_ref, value):
1584 return self.VM_set('PV_kernel', session, vm_ref, value)
1586 def VM_set_PV_ramdisk(self, session, vm_ref, value):
1587 return self.VM_set('PV_ramdisk', session, vm_ref, value)
1589 def VM_set_PV_args(self, session, vm_ref, value):
1590 return self.VM_set('PV_args', session, vm_ref, value)
1592 def VM_set_PV_bootloader_args(self, session, vm_ref, value):
1593 return self.VM_set('PV_bootloader_args', session, vm_ref, value)
1595 def VM_set_platform(self, session, vm_ref, value):
1596 return self.VM_set('platform', session, vm_ref, value)
1598 def VM_add_to_platform(self, session, vm_ref, key, value):
1599 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1600 plat = dom.get_platform()
1601 plat[key] = value
1602 return self.VM_set_platform(session, vm_ref, plat)
1604 def VM_remove_from_platform(self, session, vm_ref, key):
1605 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1606 plat = dom.get_platform()
1607 if key in plat:
1608 del plat[key]
1609 return self.VM_set_platform(session, vm_ref, plat)
1610 else:
1611 return xen_api_success_void()
1613 def VM_set_other_config(self, session, vm_ref, value):
1614 return self.VM_set('other_config', session, vm_ref, value)
1616 def VM_add_to_other_config(self, session, vm_ref, key, value):
1617 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1618 if dom and 'other_config' in dom.info:
1619 dom.info['other_config'][key] = value
1620 return self._VM_save(dom)
1622 def VM_remove_from_other_config(self, session, vm_ref, key):
1623 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1624 if dom and 'other_config' in dom.info \
1625 and key in dom.info['other_config']:
1626 del dom.info['other_config'][key]
1627 return self._VM_save(dom)
1628 else:
1629 return xen_api_success_void()
1631 def VM_get_crash_dumps(self, _, vm_ref):
1632 return xen_api_todo()
1634 # class methods
1635 def VM_get_all(self, session):
1636 refs = [d.get_uuid() for d in XendDomain.instance().list('all')]
1637 return xen_api_success(refs)
1639 def VM_get_by_name_label(self, session, label):
1640 xendom = XendDomain.instance()
1641 dom = xendom.domain_lookup_nr(label)
1642 if dom:
1643 return xen_api_success([dom.get_uuid()])
1644 return xen_api_success([])
1646 def VM_get_security_label(self, session, vm_ref):
1647 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1648 label = dom.get_security_label()
1649 return xen_api_success(label)
1651 def VM_set_security_label(self, session, vm_ref, sec_label, old_label):
1652 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1653 (rc, errors, oldlabel, new_ssidref) = \
1654 dom.set_security_label(sec_label, old_label)
1655 if rc != xsconstants.XSERR_SUCCESS:
1656 return xen_api_error(['SECURITY_ERROR', rc,
1657 xsconstants.xserr2string(-rc)])
1658 if rc == 0:
1659 rc = new_ssidref
1660 return xen_api_success(rc)
1662 def VM_create(self, session, vm_struct):
1663 xendom = XendDomain.instance()
1664 domuuid = XendTask.log_progress(0, 100,
1665 xendom.create_domain, vm_struct)
1666 return xen_api_success(domuuid)
1668 # object methods
1669 def VM_get_record(self, session, vm_ref):
1670 xendom = XendDomain.instance()
1671 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1672 if not xeninfo:
1673 return xen_api_error(['HANDLE_INVALID', 'VM', vm_ref])
1675 domid = xeninfo.getDomid()
1677 record = {
1678 'uuid': xeninfo.get_uuid(),
1679 'power_state': xeninfo.get_power_state(),
1680 'name_label': xeninfo.getName(),
1681 'name_description': xeninfo.getName(),
1682 'user_version': 1,
1683 'is_a_template': xeninfo.info['is_a_template'],
1684 'auto_power_on': False,
1685 'resident_on': XendNode.instance().uuid,
1686 'memory_static_min': xeninfo.get_memory_static_min(),
1687 'memory_static_max': xeninfo.get_memory_static_max(),
1688 'memory_dynamic_min': xeninfo.get_memory_dynamic_min(),
1689 'memory_dynamic_max': xeninfo.get_memory_dynamic_max(),
1690 'VCPUs_params': xeninfo.get_vcpus_params(),
1691 'VCPUs_at_startup': xeninfo.getVCpuCount(),
1692 'VCPUs_max': xeninfo.getVCpuCount(),
1693 'actions_after_shutdown': xeninfo.get_on_shutdown(),
1694 'actions_after_reboot': xeninfo.get_on_reboot(),
1695 'actions_after_suspend': xeninfo.get_on_suspend(),
1696 'actions_after_crash': xeninfo.get_on_crash(),
1697 'consoles': xeninfo.get_consoles(),
1698 'VIFs': xeninfo.get_vifs(),
1699 'VBDs': xeninfo.get_vbds(),
1700 'VTPMs': xeninfo.get_vtpms(),
1701 'DPCIs': xeninfo.get_dpcis(),
1702 'DSCSIs': xeninfo.get_dscsis(),
1703 'PV_bootloader': xeninfo.info.get('PV_bootloader'),
1704 'PV_kernel': xeninfo.info.get('PV_kernel'),
1705 'PV_ramdisk': xeninfo.info.get('PV_ramdisk'),
1706 'PV_args': xeninfo.info.get('PV_args'),
1707 'PV_bootloader_args': xeninfo.info.get('PV_bootloader_args'),
1708 'HVM_boot_policy': xeninfo.info.get('HVM_boot_policy'),
1709 'HVM_boot_params': xeninfo.info.get('HVM_boot_params'),
1710 'platform': xeninfo.get_platform(),
1711 'PCI_bus': xeninfo.get_pci_bus(),
1712 'tools_version': xeninfo.get_tools_version(),
1713 'other_config': xeninfo.info.get('other_config', {}),
1714 'domid': domid is None and -1 or domid,
1715 'is_control_domain': xeninfo.info['is_control_domain'],
1716 'metrics': xeninfo.get_metrics(),
1717 'security_label': xeninfo.get_security_label(),
1718 'crash_dumps': []
1720 return xen_api_success(record)
1722 def VM_clean_reboot(self, session, vm_ref):
1723 xendom = XendDomain.instance()
1724 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1725 XendTask.log_progress(0, 100, xeninfo.shutdown, "reboot")
1726 return xen_api_success_void()
1728 def VM_clean_shutdown(self, session, vm_ref):
1729 xendom = XendDomain.instance()
1730 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1731 XendTask.log_progress(0, 100, xeninfo.shutdown, "poweroff")
1732 return xen_api_success_void()
1734 def VM_clone(self, session, vm_ref):
1735 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1737 def VM_destroy(self, session, vm_ref):
1738 return XendTask.log_progress(0, 100, do_vm_func,
1739 "domain_delete", vm_ref)
1741 def VM_hard_reboot(self, session, vm_ref):
1742 return XendTask.log_progress(0, 100, do_vm_func,
1743 "domain_reset", vm_ref)
1745 def VM_hard_shutdown(self, session, vm_ref):
1746 return XendTask.log_progress(0, 100, do_vm_func,
1747 "domain_destroy", vm_ref)
1749 def VM_pause(self, session, vm_ref):
1750 return XendTask.log_progress(0, 100, do_vm_func,
1751 "domain_pause", vm_ref)
1753 def VM_resume(self, session, vm_ref, start_paused):
1754 return XendTask.log_progress(0, 100, do_vm_func,
1755 "domain_resume", vm_ref,
1756 start_paused = start_paused)
1758 def VM_start(self, session, vm_ref, start_paused):
1759 try:
1760 return XendTask.log_progress(0, 100, do_vm_func,
1761 "domain_start", vm_ref,
1762 start_paused = start_paused)
1763 except HVMRequired, exn:
1764 return xen_api_error(['VM_HVM_REQUIRED', vm_ref])
1766 def VM_suspend(self, session, vm_ref):
1767 return XendTask.log_progress(0, 100, do_vm_func,
1768 "domain_suspend", vm_ref)
1770 def VM_unpause(self, session, vm_ref):
1771 return XendTask.log_progress(0, 100, do_vm_func,
1772 "domain_unpause", vm_ref)
1774 def VM_send_sysrq(self, _, vm_ref, req):
1775 xeninfo = XendDomain.instance().get_vm_by_uuid(vm_ref)
1776 if xeninfo.state == XEN_API_VM_POWER_STATE_RUNNING \
1777 or xeninfo.state == XEN_API_VM_POWER_STATE_PAUSED:
1778 xeninfo.send_sysrq(req)
1779 return xen_api_success_void()
1780 else:
1781 return xen_api_error(
1782 ['VM_BAD_POWER_STATE', vm_ref,
1783 XendDomain.POWER_STATE_NAMES[XEN_API_VM_POWER_STATE_RUNNING],
1784 XendDomain.POWER_STATE_NAMES[xeninfo.state]])
1786 def VM_send_trigger(self, _, vm_ref, trigger, vcpu):
1787 xendom = XendDomain.instance()
1788 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1789 xendom.domain_send_trigger(xeninfo.getDomid(), trigger, vcpu)
1790 return xen_api_success_void()
1792 def VM_migrate(self, _, vm_ref, destination_url, live, other_config):
1793 xendom = XendDomain.instance()
1794 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1796 port = other_config.get("port", 0)
1797 node = other_config.get("node", -1)
1798 ssl = other_config.get("ssl", None)
1800 xendom.domain_migrate(xeninfo.getDomid(), destination_url,
1801 bool(live), port, node, ssl)
1802 return xen_api_success_void()
1804 def VM_save(self, _, vm_ref, dest, checkpoint):
1805 xendom = XendDomain.instance()
1806 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1807 xendom.domain_save(xeninfo.getDomid(), dest, checkpoint)
1808 return xen_api_success_void()
1810 def VM_restore(self, _, src, paused):
1811 xendom = XendDomain.instance()
1812 xendom.domain_restore(src, bool(paused))
1813 return xen_api_success_void()
1816 # Xen API: Class VBD
1817 # ----------------------------------------------------------------
1819 VBD_attr_ro = ['VM',
1820 'VDI',
1821 'metrics',
1822 'runtime_properties']
1823 VBD_attr_rw = ['device',
1824 'bootable',
1825 'mode',
1826 'type']
1828 VBD_attr_inst = VBD_attr_rw
1830 VBD_methods = [('media_change', None), ('destroy', None)]
1831 VBD_funcs = [('create', 'VBD')]
1833 # object methods
1834 def VBD_get_record(self, session, vbd_ref):
1835 xendom = XendDomain.instance()
1836 vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1837 if not vm:
1838 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1839 cfg = vm.get_dev_xenapi_config('vbd', vbd_ref)
1840 if not cfg:
1841 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1843 valid_vbd_keys = self.VBD_attr_ro + self.VBD_attr_rw + \
1844 self.Base_attr_ro + self.Base_attr_rw
1846 return_cfg = {}
1847 for k in cfg.keys():
1848 if k in valid_vbd_keys:
1849 return_cfg[k] = cfg[k]
1851 return_cfg['metrics'] = vbd_ref
1852 return_cfg['runtime_properties'] = {} #todo
1854 return xen_api_success(return_cfg)
1856 def VBD_media_change(self, session, vbd_ref, vdi_ref):
1857 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1859 # class methods
1860 def VBD_create(self, session, vbd_struct):
1861 xendom = XendDomain.instance()
1862 xennode = XendNode.instance()
1864 if not xendom.is_valid_vm(vbd_struct['VM']):
1865 return xen_api_error(['HANDLE_INVALID', 'VM', vbd_struct['VM']])
1867 dom = xendom.get_vm_by_uuid(vbd_struct['VM'])
1868 vdi = xennode.get_vdi_by_uuid(vbd_struct['VDI'])
1869 if not vdi:
1870 return xen_api_error(['HANDLE_INVALID', 'VDI', vdi_ref])
1872 # new VBD via VDI/SR
1873 vdi_image = vdi.get_location()
1875 try:
1876 vbd_ref = XendTask.log_progress(0, 100,
1877 dom.create_vbd,
1878 vbd_struct, vdi_image)
1879 except XendError, e:
1880 log.exception("Error in VBD_create")
1881 return xen_api_error(['INTERNAL_ERROR', str(e)])
1883 vdi.addVBD(vbd_ref)
1885 xendom.managed_config_save(dom)
1886 return xen_api_success(vbd_ref)
1889 def VBD_destroy(self, session, vbd_ref):
1890 xendom = XendDomain.instance()
1891 vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1892 if not vm:
1893 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1895 vdi_ref = XendDomain.instance()\
1896 .get_dev_property_by_uuid('vbd', vbd_ref, "VDI")
1897 vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
1899 XendTask.log_progress(0, 100, vm.destroy_vbd, vbd_ref)
1901 vdi.removeVBD(vbd_ref)
1903 return xen_api_success_void()
1905 def _VBD_get(self, vbd_ref, prop):
1906 return xen_api_success(
1907 XendDomain.instance().get_dev_property_by_uuid(
1908 'vbd', vbd_ref, prop))
1910 # attributes (ro)
1911 def VBD_get_metrics(self, _, vbd_ref):
1912 return xen_api_success(vbd_ref)
1914 def VBD_get_runtime_properties(self, _, vbd_ref):
1915 xendom = XendDomain.instance()
1916 dominfo = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1917 device = dominfo.get_dev_config_by_uuid('vbd', vbd_ref)
1919 try:
1920 devid = int(device['id'])
1921 device_sxps = dominfo.getDeviceSxprs('vbd')
1922 device_dicts = [dict(device_sxp[1][0:]) for device_sxp in device_sxps]
1923 device_dict = [device_dict
1924 for device_dict in device_dicts
1925 if int(device_dict['virtual-device']) == devid][0]
1927 return xen_api_success(device_dict)
1928 except Exception, exn:
1929 log.exception(exn)
1930 return xen_api_success({})
1932 # attributes (rw)
1933 def VBD_get_VM(self, session, vbd_ref):
1934 return self._VBD_get(vbd_ref, 'VM')
1936 def VBD_get_VDI(self, session, vbd_ref):
1937 return self._VBD_get(vbd_ref, 'VDI')
1939 def VBD_get_device(self, session, vbd_ref):
1940 return self._VBD_get(vbd_ref, 'device')
1942 def VBD_get_bootable(self, session, vbd_ref):
1943 return self._VBD_get(vbd_ref, 'bootable')
1945 def VBD_get_mode(self, session, vbd_ref):
1946 return self._VBD_get(vbd_ref, 'mode')
1948 def VBD_get_type(self, session, vbd_ref):
1949 return self._VBD_get(vbd_ref, 'type')
1951 def VBD_set_bootable(self, session, vbd_ref, bootable):
1952 bootable = bool(bootable)
1953 xd = XendDomain.instance()
1954 vm = xd.get_vm_with_dev_uuid('vbd', vbd_ref)
1955 vm.set_dev_property('vbd', vbd_ref, 'bootable', bootable)
1956 xd.managed_config_save(vm)
1957 return xen_api_success_void()
1959 def VBD_set_mode(self, session, vbd_ref, mode):
1960 if mode == 'RW':
1961 mode = 'w'
1962 else:
1963 mode = 'r'
1964 xd = XendDomain.instance()
1965 vm = xd.get_vm_with_dev_uuid('vbd', vbd_ref)
1966 vm.set_dev_property('vbd', vbd_ref, 'mode', mode)
1967 xd.managed_config_save(vm)
1968 return xen_api_success_void()
1970 def VBD_get_all(self, session):
1971 xendom = XendDomain.instance()
1972 vbds = [d.get_vbds() for d in XendDomain.instance().list('all')]
1973 vbds = reduce(lambda x, y: x + y, vbds)
1974 return xen_api_success(vbds)
1977 # Xen API: Class VBD_metrics
1978 # ----------------------------------------------------------------
1980 VBD_metrics_attr_ro = ['io_read_kbs',
1981 'io_write_kbs',
1982 'last_updated']
1983 VBD_metrics_attr_rw = []
1984 VBD_metrics_methods = []
1986 def VBD_metrics_get_all(self, session):
1987 return self.VBD_get_all(session)
1989 def VBD_metrics_get_record(self, _, ref):
1990 vm = XendDomain.instance().get_vm_with_dev_uuid('vbd', ref)
1991 if not vm:
1992 return xen_api_error(['HANDLE_INVALID', 'VBD_metrics', ref])
1993 return xen_api_success(
1994 { 'io_read_kbs' : vm.get_dev_property('vbd', ref, 'io_read_kbs'),
1995 'io_write_kbs' : vm.get_dev_property('vbd', ref, 'io_write_kbs'),
1996 'last_updated' : now()
1997 })
1999 def VBD_metrics_get_io_read_kbs(self, _, ref):
2000 return self._VBD_get(ref, 'io_read_kbs')
2002 def VBD_metrics_get_io_write_kbs(self, session, ref):
2003 return self._VBD_get(ref, 'io_write_kbs')
2005 def VBD_metrics_get_last_updated(self, _1, _2):
2006 return xen_api_success(now())
2009 # Xen API: Class VIF
2010 # ----------------------------------------------------------------
2012 VIF_attr_ro = ['network',
2013 'VM',
2014 'metrics',
2015 'runtime_properties']
2016 VIF_attr_rw = ['device',
2017 'MAC',
2018 'MTU',
2019 'security_label']
2021 VIF_attr_inst = VIF_attr_rw
2023 VIF_methods = [('destroy', None)]
2024 VIF_funcs = [('create', 'VIF')]
2027 # object methods
2028 def VIF_get_record(self, session, vif_ref):
2029 xendom = XendDomain.instance()
2030 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
2031 if not vm:
2032 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
2033 cfg = vm.get_dev_xenapi_config('vif', vif_ref)
2034 if not cfg:
2035 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
2037 valid_vif_keys = self.VIF_attr_ro + self.VIF_attr_rw + \
2038 self.Base_attr_ro + self.Base_attr_rw
2040 return_cfg = {}
2041 for k in cfg.keys():
2042 if k in valid_vif_keys:
2043 return_cfg[k] = cfg[k]
2045 return_cfg['metrics'] = vif_ref
2047 return xen_api_success(return_cfg)
2049 # class methods
2050 def VIF_create(self, session, vif_struct):
2051 xendom = XendDomain.instance()
2052 if not xendom.is_valid_vm(vif_struct['VM']):
2053 return xen_api_error(['HANDLE_INVALID', 'VM', vif_struct['VM']])
2055 dom = xendom.get_vm_by_uuid(vif_struct['VM'])
2056 try:
2057 vif_ref = dom.create_vif(vif_struct)
2058 xendom.managed_config_save(dom)
2059 return xen_api_success(vif_ref)
2060 except XendError, exn:
2061 return xen_api_error(['INTERNAL_ERROR', str(exn)])
2063 def VIF_destroy(self, session, vif_ref):
2064 xendom = XendDomain.instance()
2065 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
2066 if not vm:
2067 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
2069 vm.destroy_vif(vif_ref)
2070 return xen_api_success_void()
2072 def _VIF_get(self, ref, prop):
2073 return xen_api_success(
2074 XendDomain.instance().get_dev_property_by_uuid('vif', ref, prop))
2076 # getters/setters
2077 def VIF_get_metrics(self, _, vif_ref):
2078 return xen_api_success(vif_ref)
2080 def VIF_get_VM(self, session, vif_ref):
2081 xendom = XendDomain.instance()
2082 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
2083 return xen_api_success(vm.get_uuid())
2085 def VIF_get_MTU(self, session, vif_ref):
2086 return self._VIF_get(vif_ref, 'MTU')
2088 def VIF_get_MAC(self, session, vif_ref):
2089 return self._VIF_get(vif_ref, 'MAC')
2091 def VIF_get_device(self, session, vif_ref):
2092 return self._VIF_get(vif_ref, 'device')
2094 def VIF_get_all(self, session):
2095 xendom = XendDomain.instance()
2096 vifs = [d.get_vifs() for d in XendDomain.instance().list('all')]
2097 vifs = reduce(lambda x, y: x + y, vifs)
2098 return xen_api_success(vifs)
2100 def VIF_get_runtime_properties(self, _, vif_ref):
2101 xendom = XendDomain.instance()
2102 dominfo = xendom.get_vm_with_dev_uuid('vif', vif_ref)
2103 device = dominfo.get_dev_config_by_uuid('vif', vif_ref)
2105 try:
2106 devid = int(device['id'])
2108 device_sxps = dominfo.getDeviceSxprs('vif')
2109 device_dicts = [dict(device_sxp[1][1:])
2110 for device_sxp in device_sxps]
2112 device_dict = [device_dict
2113 for device_dict in device_dicts
2114 if int(device_dict['handle']) == devid][0]
2116 return xen_api_success(device_dict)
2118 except Exception, exn:
2119 log.exception(exn)
2120 return xen_api_success({})
2122 def VIF_get_security_label(self, session, vif_ref):
2123 return self._VIF_get(vif_ref, 'security_label')
2125 def _VIF_set(self, ref, prop, val, old_val):
2126 return XendDomain.instance().set_dev_property_by_uuid(
2127 'vif', ref, prop, val, old_val)
2129 def VIF_set_security_label(self, session, vif_ref, sec_lab, old_lab):
2130 xendom = XendDomain.instance()
2131 dom = xendom.get_vm_with_dev_uuid('vif', vif_ref)
2132 if not dom:
2133 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
2135 if dom._stateGet() == XEN_API_VM_POWER_STATE_RUNNING:
2136 raise SecurityError(-xsconstants.XSERR_RESOURCE_IN_USE)
2138 rc = self._VIF_set(vif_ref, 'security_label', sec_lab, old_lab)
2139 if rc == False:
2140 raise SecurityError(-xsconstants.XSERR_BAD_LABEL)
2141 return xen_api_success(xsconstants.XSERR_SUCCESS)
2144 # Xen API: Class VIF_metrics
2145 # ----------------------------------------------------------------
2147 VIF_metrics_attr_ro = ['io_read_kbs',
2148 'io_write_kbs',
2149 'io_total_read_kbs',
2150 'io_total_write_kbs',
2151 'last_updated']
2152 VIF_metrics_attr_rw = []
2153 VIF_metrics_methods = []
2155 def VIF_metrics_get_all(self, session):
2156 return self.VIF_get_all(session)
2158 def VIF_metrics_get_record(self, _, ref):
2159 vm = XendDomain.instance().get_vm_with_dev_uuid('vif', ref)
2160 if not vm:
2161 return xen_api_error(['HANDLE_INVALID', 'VIF_metrics', ref])
2162 return xen_api_success(
2163 { 'io_read_kbs' : vm.get_dev_property('vif', ref, 'io_read_kbs'),
2164 'io_write_kbs' : vm.get_dev_property('vif', ref, 'io_write_kbs'),
2165 'io_total_read_kbs' : vm.get_dev_property('vif', ref, 'io_total_read_kbs'),
2166 'io_total_write_kbs' : vm.get_dev_property('vif', ref, 'io_total_write_kbs'),
2167 'last_updated' : now()
2168 })
2170 def VIF_metrics_get_io_read_kbs(self, _, ref):
2171 return self._VIF_get(ref, 'io_read_kbs')
2173 def VIF_metrics_get_io_write_kbs(self, session, ref):
2174 return self._VIF_get(ref, 'io_write_kbs')
2176 def VIF_metrics_get_io_total_read_kbs(self, _, ref):
2177 return self._VIF_get(ref, 'io_total_read_kbs')
2179 def VIF_metrics_get_io_total_write_kbs(self, session, ref):
2180 return self._VIF_get(ref, 'io_total_write_kbs')
2182 def VIF_metrics_get_last_updated(self, _1, _2):
2183 return xen_api_success(now())
2186 # Xen API: Class VDI
2187 # ----------------------------------------------------------------
2188 VDI_attr_ro = ['SR',
2189 'VBDs',
2190 'physical_utilisation',
2191 'type']
2192 VDI_attr_rw = ['name_label',
2193 'name_description',
2194 'virtual_size',
2195 'sharable',
2196 'read_only',
2197 'other_config',
2198 'security_label']
2199 VDI_attr_inst = VDI_attr_ro + VDI_attr_rw
2201 VDI_methods = [('destroy', None)]
2202 VDI_funcs = [('create', 'VDI'),
2203 ('get_by_name_label', 'Set(VDI)')]
2205 def _get_VDI(self, ref):
2206 return XendNode.instance().get_vdi_by_uuid(ref)
2208 def VDI_get_VBDs(self, session, vdi_ref):
2209 vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
2210 return xen_api_success(vdi.getVBDs())
2212 def VDI_get_physical_utilisation(self, session, vdi_ref):
2213 return xen_api_success(self._get_VDI(vdi_ref).
2214 get_physical_utilisation())
2216 def VDI_get_type(self, session, vdi_ref):
2217 return xen_api_success(self._get_VDI(vdi_ref).type)
2219 def VDI_get_name_label(self, session, vdi_ref):
2220 return xen_api_success(self._get_VDI(vdi_ref).name_label)
2222 def VDI_get_name_description(self, session, vdi_ref):
2223 return xen_api_success(self._get_VDI(vdi_ref).name_description)
2225 def VDI_get_SR(self, session, vdi_ref):
2226 return xen_api_success(self._get_VDI(vdi_ref).sr_uuid)
2228 def VDI_get_virtual_size(self, session, vdi_ref):
2229 return xen_api_success(self._get_VDI(vdi_ref).virtual_size)
2231 def VDI_get_sharable(self, session, vdi_ref):
2232 return xen_api_success(self._get_VDI(vdi_ref).sharable)
2234 def VDI_get_read_only(self, session, vdi_ref):
2235 return xen_api_success(self._get_VDI(vdi_ref).read_only)
2237 def VDI_set_name_label(self, session, vdi_ref, value):
2238 self._get_VDI(vdi_ref).name_label = value
2239 return xen_api_success_void()
2241 def VDI_set_name_description(self, session, vdi_ref, value):
2242 self._get_VDI(vdi_ref).name_description = value
2243 return xen_api_success_void()
2245 def VDI_set_virtual_size(self, session, vdi_ref, value):
2246 return xen_api_error(XEND_ERROR_UNSUPPORTED)
2248 def VDI_set_sharable(self, session, vdi_ref, value):
2249 self._get_VDI(vdi_ref).sharable = bool(value)
2250 return xen_api_success_void()
2252 def VDI_set_read_only(self, session, vdi_ref, value):
2253 self._get_VDI(vdi_ref).read_only = bool(value)
2254 return xen_api_success_void()
2256 def VDI_get_other_config(self, session, vdi_ref):
2257 return xen_api_success(
2258 self._get_VDI(vdi_ref).other_config)
2260 def VDI_set_other_config(self, session, vdi_ref, other_config):
2261 self._get_VDI(vdi_ref).other_config = other_config
2262 return xen_api_success_void()
2264 # Object Methods
2266 def VDI_destroy(self, session, vdi_ref):
2267 sr = XendNode.instance().get_sr_containing_vdi(vdi_ref)
2268 sr.destroy_vdi(vdi_ref)
2269 return xen_api_success_void()
2271 def VDI_get_record(self, session, vdi_ref):
2272 image = XendNode.instance().get_vdi_by_uuid(vdi_ref)
2273 return xen_api_success({
2274 'uuid': vdi_ref,
2275 'name_label': image.name_label,
2276 'name_description': image.name_description,
2277 'SR': image.sr_uuid,
2278 'VBDs': image.getVBDs(),
2279 'virtual_size': image.virtual_size,
2280 'physical_utilisation': image.physical_utilisation,
2281 'type': image.type,
2282 'sharable': image.sharable,
2283 'read_only': image.read_only,
2284 'other_config': image.other_config,
2285 'security_label' : image.get_security_label()
2286 })
2288 # Class Functions
2289 def VDI_create(self, session, vdi_struct):
2290 sr_ref = vdi_struct.get('SR')
2291 xennode = XendNode.instance()
2292 if not xennode.is_valid_sr(sr_ref):
2293 return xen_api_error(['HANDLE_INVALID', 'SR', sr_ref])
2295 vdi_uuid = xennode.srs[sr_ref].create_vdi(vdi_struct)
2296 return xen_api_success(vdi_uuid)
2298 def VDI_get_all(self, session):
2299 xennode = XendNode.instance()
2300 vdis = [sr.get_vdis() for sr in xennode.srs.values()]
2301 return xen_api_success(reduce(lambda x, y: x + y, vdis))
2303 def VDI_get_by_name_label(self, session, name):
2304 xennode = XendNode.instance()
2305 return xen_api_success(xennode.get_vdi_by_name_label(name))
2307 def VDI_set_security_label(self, session, vdi_ref, sec_lab, old_lab):
2308 vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
2309 rc = vdi.set_security_label(sec_lab, old_lab)
2310 if rc < 0:
2311 return xen_api_error(['SECURITY_ERROR', rc,
2312 xsconstants.xserr2string(-rc)])
2313 return xen_api_success(rc)
2315 def VDI_get_security_label(self, session, vdi_ref):
2316 vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
2317 return xen_api_success(vdi.get_security_label())
2319 # Xen API: Class VTPM
2320 # ----------------------------------------------------------------
2322 VTPM_attr_rw = ['other_config']
2323 VTPM_attr_ro = ['VM',
2324 'backend',
2325 'runtime_properties' ]
2327 VTPM_attr_inst = VTPM_attr_rw
2329 VTPM_methods = [('destroy', None)]
2330 VTPM_funcs = [('create', 'VTPM')]
2332 def VTPM_get_other_config(self, session, vtpm_ref):
2333 xendom = XendDomain.instance()
2334 return xen_api_success(xendom.get_dev_property_by_uuid('vtpm',
2335 vtpm_ref,
2336 'other_config'))
2338 def VTPM_set_other_config(self, session, vtpm_ref, other_config):
2339 xendom = XendDomain.instance()
2340 xendom.set_dev_property_by_uuid('vtpm',
2341 vtpm_ref,
2342 'other_config',
2343 other_config)
2344 return xen_api_success_void()
2346 # object methods
2347 def VTPM_get_record(self, session, vtpm_ref):
2348 xendom = XendDomain.instance()
2349 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
2350 if not vm:
2351 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
2352 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
2353 if not cfg:
2354 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
2355 valid_vtpm_keys = self.VTPM_attr_ro + self.VTPM_attr_rw + \
2356 self.Base_attr_ro + self.Base_attr_rw
2357 return_cfg = {}
2358 for k in cfg.keys():
2359 if k in valid_vtpm_keys:
2360 return_cfg[k] = cfg[k]
2362 return xen_api_success(return_cfg)
2364 # Class Functions
2365 def VTPM_get_backend(self, session, vtpm_ref):
2366 xendom = XendDomain.instance()
2367 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
2368 if not vm:
2369 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
2370 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
2371 if not cfg:
2372 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
2373 if not cfg.has_key('backend'):
2374 return xen_api_error(['INTERNAL_ERROR', 'VTPM backend not set'])
2375 return xen_api_success(cfg['backend'])
2377 def VTPM_get_VM(self, session, vtpm_ref):
2378 xendom = XendDomain.instance()
2379 return xen_api_success(xendom.get_dev_property_by_uuid('vtpm',
2380 vtpm_ref, 'VM'))
2382 def VTPM_destroy(self, session, vtpm_ref):
2383 xendom = XendDomain.instance()
2384 dom = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
2385 if dom:
2386 if dom.state != XEN_API_VM_POWER_STATE_HALTED:
2387 vm_ref = dom.get_dev_property('vtpm', vtpm_ref, 'VM')
2388 return xen_api_error(['VM_BAD_POWER_STATE', vm_ref,
2389 XendDomain.POWER_STATE_NAMES[XEN_API_VM_POWER_STATE_HALTED],
2390 XendDomain.POWER_STATE_NAMES[dom.state]])
2391 from xen.xend.server import tpmif
2392 tpmif.destroy_vtpmstate(dom.getName())
2393 return xen_api_success_void()
2394 else:
2395 return xen_api_error(['HANDLE_INVALID', 'VM', vtpm_struct['VM']])
2397 # class methods
2398 def VTPM_create(self, session, vtpm_struct):
2399 xendom = XendDomain.instance()
2400 if xendom.is_valid_vm(vtpm_struct['VM']):
2401 dom = xendom.get_vm_by_uuid(vtpm_struct['VM'])
2402 try:
2403 vtpm_ref = dom.create_vtpm(vtpm_struct)
2404 xendom.managed_config_save(dom)
2405 return xen_api_success(vtpm_ref)
2406 except XendError, exn:
2407 return xen_api_error(['INTERNAL_ERROR', str(exn)])
2408 else:
2409 return xen_api_error(['HANDLE_INVALID', 'VM', vtpm_struct['VM']])
2411 def VTPM_get_all(self, session):
2412 xendom = XendDomain.instance()
2413 vtpms = [d.get_vtpms() for d in XendDomain.instance().list('all')]
2414 vtpms = reduce(lambda x, y: x + y, vtpms)
2415 return xen_api_success(vtpms)
2417 def VTPM_get_runtime_properties(self, _, vtpm_ref):
2418 xendom = XendDomain.instance()
2419 dominfo = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
2420 device = dominfo.get_dev_config_by_uuid('vtpm', vtpm_ref)
2422 try:
2423 device_sxps = dominfo.getDeviceSxprs('vtpm')
2424 device_dict = dict(device_sxps[0][1])
2425 return xen_api_success(device_dict)
2426 except:
2427 return xen_api_success({})
2429 # Xen API: Class console
2430 # ----------------------------------------------------------------
2433 console_attr_ro = ['location', 'protocol', 'VM']
2434 console_attr_rw = ['other_config']
2435 console_funcs = [('create', 'console')]
2437 def console_get_all(self, session):
2438 xendom = XendDomain.instance()
2439 cons = [d.get_consoles() for d in XendDomain.instance().list('all')]
2440 cons = reduce(lambda x, y: x + y, cons)
2441 return xen_api_success(cons)
2443 def console_get_location(self, session, console_ref):
2444 xendom = XendDomain.instance()
2445 return xen_api_success(xendom.get_dev_property_by_uuid('console',
2446 console_ref,
2447 'location'))
2449 def console_get_protocol(self, session, console_ref):
2450 xendom = XendDomain.instance()
2451 return xen_api_success(xendom.get_dev_property_by_uuid('console',
2452 console_ref,
2453 'protocol'))
2455 def console_get_VM(self, session, console_ref):
2456 xendom = XendDomain.instance()
2457 vm = xendom.get_vm_with_dev_uuid('console', console_ref)
2458 return xen_api_success(vm.get_uuid())
2460 def console_get_other_config(self, session, console_ref):
2461 xendom = XendDomain.instance()
2462 return xen_api_success(xendom.get_dev_property_by_uuid('console',
2463 console_ref,
2464 'other_config'))
2466 # object methods
2467 def console_get_record(self, session, console_ref):
2468 xendom = XendDomain.instance()
2469 vm = xendom.get_vm_with_dev_uuid('console', console_ref)
2470 if not vm:
2471 return xen_api_error(['HANDLE_INVALID', 'console', console_ref])
2472 cfg = vm.get_dev_xenapi_config('console', console_ref)
2473 if not cfg:
2474 return xen_api_error(['HANDLE_INVALID', 'console', console_ref])
2476 valid_console_keys = self.console_attr_ro + self.console_attr_rw + \
2477 self.Base_attr_ro + self.Base_attr_rw
2479 return_cfg = {}
2480 for k in cfg.keys():
2481 if k in valid_console_keys:
2482 return_cfg[k] = cfg[k]
2484 return xen_api_success(return_cfg)
2486 def console_create(self, session, console_struct):
2487 xendom = XendDomain.instance()
2488 if not xendom.is_valid_vm(console_struct['VM']):
2489 return xen_api_error(['HANDLE_INVALID', 'VM',
2490 console_struct['VM']])
2492 dom = xendom.get_vm_by_uuid(console_struct['VM'])
2493 try:
2494 if 'protocol' not in console_struct:
2495 return xen_api_error(['CONSOLE_PROTOCOL_INVALID',
2496 'No protocol specified'])
2498 console_ref = dom.create_console(console_struct)
2499 xendom.managed_config_save(dom)
2500 return xen_api_success(console_ref)
2501 except XendError, exn:
2502 return xen_api_error(['INTERNAL_ERROR', str(exn)])
2504 def console_set_other_config(self, session, console_ref, other_config):
2505 xd = XendDomain.instance()
2506 vm = xd.get_vm_with_dev_uuid('console', console_ref)
2507 vm.set_console_other_config(console_ref, other_config)
2508 xd.managed_config_save(vm)
2509 return xen_api_success_void()
2511 # Xen API: Class SR
2512 # ----------------------------------------------------------------
2513 SR_attr_ro = ['VDIs',
2514 'PBDs',
2515 'virtual_allocation',
2516 'physical_utilisation',
2517 'physical_size',
2518 'type',
2519 'content_type']
2521 SR_attr_rw = ['name_label',
2522 'name_description']
2524 SR_attr_inst = ['physical_size',
2525 'type',
2526 'name_label',
2527 'name_description']
2529 SR_methods = []
2530 SR_funcs = [('get_by_name_label', 'Set(SR)'),
2531 ('get_by_uuid', 'SR')]
2533 # Class Functions
2534 def SR_get_all(self, session):
2535 return xen_api_success(XendNode.instance().get_all_sr_uuid())
2537 def SR_get_by_name_label(self, session, label):
2538 return xen_api_success(XendNode.instance().get_sr_by_name(label))
2540 def SR_get_supported_types(self, _):
2541 return xen_api_success(['local', 'qcow_file'])
2543 # Class Methods
2545 def SR_get_record(self, session, sr_ref):
2546 sr = XendNode.instance().get_sr(sr_ref)
2547 if sr:
2548 return xen_api_success(sr.get_record())
2549 return xen_api_error(['HANDLE_INVALID', 'SR', sr_ref])
2551 # Attribute acceess
2553 def _get_SR_func(self, sr_ref, func):
2554 return xen_api_success(getattr(XendNode.instance().get_sr(sr_ref),
2555 func)())
2557 def _get_SR_attr(self, sr_ref, attr):
2558 return xen_api_success(getattr(XendNode.instance().get_sr(sr_ref),
2559 attr))
2561 def SR_get_VDIs(self, _, ref):
2562 return self._get_SR_func(ref, 'list_images')
2564 def SR_get_PBDs(self, _, ref):
2565 return xen_api_success(XendPBD.get_by_SR(ref))
2567 def SR_get_virtual_allocation(self, _, ref):
2568 return self._get_SR_func(ref, 'virtual_allocation')
2570 def SR_get_physical_utilisation(self, _, ref):
2571 return self._get_SR_func(ref, 'physical_utilisation')
2573 def SR_get_physical_size(self, _, ref):
2574 return self._get_SR_attr(ref, 'physical_size')
2576 def SR_get_type(self, _, ref):
2577 return self._get_SR_attr(ref, 'type')
2579 def SR_get_content_type(self, _, ref):
2580 return self._get_SR_attr(ref, 'content_type')
2582 def SR_get_name_label(self, _, ref):
2583 return self._get_SR_attr(ref, 'name_label')
2585 def SR_get_name_description(self, _, ref):
2586 return self._get_SR_attr(ref, 'name_description')
2588 def SR_set_name_label(self, session, sr_ref, value):
2589 sr = XendNode.instance.get_sr(sr_ref)
2590 if sr:
2591 sr.name_label = value
2592 XendNode.instance().save()
2593 return xen_api_success_void()
2595 def SR_set_name_description(self, session, sr_ref, value):
2596 sr = XendNode.instance.get_sr(sr_ref)
2597 if sr:
2598 sr.name_description = value
2599 XendNode.instance().save()
2600 return xen_api_success_void()
2603 # Xen API: Class event
2604 # ----------------------------------------------------------------
2606 event_attr_ro = []
2607 event_attr_rw = []
2608 event_funcs = [('register', None),
2609 ('unregister', None),
2610 ('next', None)]
2612 def event_register(self, session, reg_classes):
2613 event_register(session, reg_classes)
2614 return xen_api_success_void()
2616 def event_unregister(self, session, unreg_classes):
2617 event_unregister(session, reg_classes)
2618 return xen_api_success_void()
2620 def event_next(self, session):
2621 return event_next(session)
2623 # Xen API: Class debug
2624 # ----------------------------------------------------------------
2626 debug_methods = [('destroy', None),
2627 ('get_record', 'debug')]
2628 debug_funcs = [('wait', None),
2629 ('return_failure', None)]
2631 def debug_wait(self, session, wait_secs):
2632 import time
2633 prog_units = 100/float(wait_secs)
2634 for i in range(int(wait_secs)):
2635 XendTask.log_progress(prog_units * i, prog_units * (i + 1),
2636 time.sleep, 1)
2637 return xen_api_success_void()
2640 def debug_return_failure(self, session):
2641 return xen_api_error(['DEBUG_FAIL', session])
2643 def debug_create(self, session):
2644 debug_uuid = uuid.createString()
2645 self._debug[debug_uuid] = None
2646 return xen_api_success(debug_uuid)
2648 def debug_destroy(self, session, debug_ref):
2649 del self._debug[debug_ref]
2650 return xen_api_success_void()
2652 def debug_get_record(self, session, debug_ref):
2653 return xen_api_success({'uuid': debug_ref})
2656 class XendAPIAsyncProxy:
2657 """ A redirector for Async.Class.function calls to XendAPI
2658 but wraps the call for use with the XendTaskManager.
2660 @ivar xenapi: Xen API instance
2661 @ivar method_map: Mapping from XMLRPC method name to callable objects.
2662 """
2664 method_prefix = 'Async.'
2666 def __init__(self, xenapi):
2667 """Initialises the Async Proxy by making a map of all
2668 implemented Xen API methods for use with XendTaskManager.
2670 @param xenapi: XendAPI instance
2671 """
2672 self.xenapi = xenapi
2673 self.method_map = {}
2674 for method_name in dir(self.xenapi):
2675 method = getattr(self.xenapi, method_name)
2676 if method_name[0] != '_' and hasattr(method, 'async') \
2677 and method.async == True:
2678 self.method_map[method.api] = method
2680 def _dispatch(self, method, args):
2681 """Overridden method so that SimpleXMLRPCServer will
2682 resolve methods through this method rather than through
2683 inspection.
2685 @param method: marshalled method name from XMLRPC.
2686 @param args: marshalled arguments from XMLRPC.
2687 """
2689 # Only deal with method names that start with "Async."
2690 if not method.startswith(self.method_prefix):
2691 return xen_api_error(['MESSAGE_METHOD_UNKNOWN', method])
2693 # Lookup synchronous version of the method
2694 synchronous_method_name = method[len(self.method_prefix):]
2695 if synchronous_method_name not in self.method_map:
2696 return xen_api_error(['MESSAGE_METHOD_UNKNOWN', method])
2698 method = self.method_map[synchronous_method_name]
2700 # Check that we've got enough arguments before issuing a task ID.
2701 needed = argcounts[method.api]
2702 if len(args) != needed:
2703 return xen_api_error(['MESSAGE_PARAMETER_COUNT_MISMATCH',
2704 self.method_prefix + method.api, needed,
2705 len(args)])
2707 # Validate the session before proceeding
2708 session = args[0]
2709 if not auth_manager().is_session_valid(session):
2710 return xen_api_error(['SESSION_INVALID', session])
2712 # create and execute the task, and return task_uuid
2713 return_type = getattr(method, 'return_type', None)
2714 task_uuid = XendTaskManager.create_task(method, args,
2715 synchronous_method_name,
2716 return_type,
2717 synchronous_method_name,
2718 session)
2719 return xen_api_success(task_uuid)