debuggers.hg

view tools/python/xen/xend/XendAPI.py @ 17989:e65fe28b5288

XenAPI: Add Physical PCI Device (PPCI) Support

Signed-off-by: Yosuke Iwamatsu <y-iwamatsu@ab.jp.nec.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Jul 03 10:26:16 2008 +0100 (2008-07-03)
parents 420db89188ca
children 52a388ec09f8
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 XendXSPolicy import XendXSPolicy, XendACMPolicy
46 from XendAPIConstants import *
47 from xen.util.xmlrpclib2 import stringify
49 from xen.util.blkif import blkdev_name_to_number
50 from xen.util import xsconstants
53 AUTH_NONE = 'none'
54 AUTH_PAM = 'pam'
56 argcounts = {}
58 # ------------------------------------------
59 # Utility Methods for Xen API Implementation
60 # ------------------------------------------
62 def xen_api_success(value):
63 """Wraps a return value in XenAPI format."""
64 if value is None:
65 s = ''
66 else:
67 s = stringify(value)
68 return {"Status": "Success", "Value": s}
70 def xen_api_success_void():
71 """Return success, but caller expects no return value."""
72 return xen_api_success("")
74 def xen_api_error(error):
75 """Wraps an error value in XenAPI format."""
76 if type(error) == tuple:
77 error = list(error)
78 if type(error) != list:
79 error = [error]
80 if len(error) == 0:
81 error = ['INTERNAL_ERROR', 'Empty list given to xen_api_error']
83 return { "Status": "Failure",
84 "ErrorDescription": [str(x) for x in error] }
87 def xen_api_todo():
88 """Temporary method to make sure we track down all the TODOs"""
89 return {"Status": "Error", "ErrorDescription": XEND_ERROR_TODO}
92 def now():
93 return datetime()
96 def datetime(when = None):
97 """Marshall the given time as a Xen-API DateTime.
99 @param when The time in question, given as seconds since the epoch, UTC.
100 May be None, in which case the current time is used.
101 """
102 if when is None:
103 return xmlrpclib.DateTime(time.gmtime())
104 else:
105 return xmlrpclib.DateTime(time.gmtime(when))
108 # ---------------------------------------------------
109 # Event dispatch
110 # ---------------------------------------------------
112 EVENT_QUEUE_LENGTH = 50
113 event_registrations = {}
115 def event_register(session, reg_classes):
116 if session not in event_registrations:
117 event_registrations[session] = {
118 'classes' : sets.Set(),
119 'queue' : Queue.Queue(EVENT_QUEUE_LENGTH),
120 'next-id' : 1
121 }
122 if not reg_classes:
123 reg_classes = classes
124 event_registrations[session]['classes'].union_update(reg_classes)
127 def event_unregister(session, unreg_classes):
128 if session not in event_registrations:
129 return
131 if unreg_classes:
132 event_registrations[session]['classes'].intersection_update(
133 unreg_classes)
134 if len(event_registrations[session]['classes']) == 0:
135 del event_registrations[session]
136 else:
137 del event_registrations[session]
140 def event_next(session):
141 if session not in event_registrations:
142 return xen_api_error(['SESSION_NOT_REGISTERED', session])
143 queue = event_registrations[session]['queue']
144 events = [queue.get()]
145 try:
146 while True:
147 events.append(queue.get(False))
148 except Queue.Empty:
149 pass
151 return xen_api_success(events)
154 def _ctor_event_dispatch(xenapi, ctor, api_cls, session, args):
155 result = ctor(xenapi, session, *args)
156 if result['Status'] == 'Success':
157 ref = result['Value']
158 event_dispatch('add', api_cls, ref, '')
159 return result
162 def _dtor_event_dispatch(xenapi, dtor, api_cls, session, ref, args):
163 result = dtor(xenapi, session, ref, *args)
164 if result['Status'] == 'Success':
165 event_dispatch('del', api_cls, ref, '')
166 return result
169 def _setter_event_dispatch(xenapi, setter, api_cls, attr_name, session, ref,
170 args):
171 result = setter(xenapi, session, ref, *args)
172 if result['Status'] == 'Success':
173 event_dispatch('mod', api_cls, ref, attr_name)
174 return result
177 def event_dispatch(operation, api_cls, ref, attr_name):
178 assert operation in ['add', 'del', 'mod']
179 event = {
180 'timestamp' : now(),
181 'class' : api_cls,
182 'operation' : operation,
183 'ref' : ref,
184 'obj_uuid' : ref,
185 'field' : attr_name,
186 }
187 for reg in event_registrations.values():
188 if api_cls in reg['classes']:
189 event['id'] = reg['next-id']
190 reg['next-id'] += 1
191 reg['queue'].put(event)
194 # ---------------------------------------------------
195 # Python Method Decorators for input value validation
196 # ---------------------------------------------------
198 def trace(func, api_name = ''):
199 """Decorator to trace XMLRPC Xen API methods.
201 @param func: function with any parameters
202 @param api_name: name of the api call for debugging.
203 """
204 if hasattr(func, 'api'):
205 api_name = func.api
206 def trace_func(self, *args, **kwargs):
207 log.debug('%s: %s' % (api_name, args))
208 return func(self, *args, **kwargs)
209 trace_func.api = api_name
210 return trace_func
213 def catch_typeerror(func):
214 """Decorator to catch any TypeErrors and translate them into Xen-API
215 errors.
217 @param func: function with params: (self, ...)
218 @rtype: callable object
219 """
220 def f(self, *args, **kwargs):
221 try:
222 return func(self, *args, **kwargs)
223 except TypeError, exn:
224 #log.exception('catch_typeerror')
225 if hasattr(func, 'api') and func.api in argcounts:
226 # Assume that if the argument count was wrong and if the
227 # exception was thrown inside this file, then it is due to an
228 # invalid call from the client, otherwise it's an internal
229 # error (which will be handled further up).
230 expected = argcounts[func.api]
231 actual = len(args) + len(kwargs)
232 if expected != actual:
233 tb = sys.exc_info()[2]
234 try:
235 sourcefile = traceback.extract_tb(tb)[-1][0]
236 if sourcefile == inspect.getsourcefile(XendAPI):
237 return xen_api_error(
238 ['MESSAGE_PARAMETER_COUNT_MISMATCH',
239 func.api, expected, actual])
240 finally:
241 del tb
242 raise
243 except XendAPIError, exn:
244 return xen_api_error(exn.get_api_error())
246 return f
249 def session_required(func):
250 """Decorator to verify if session is valid before calling method.
252 @param func: function with params: (self, session, ...)
253 @rtype: callable object
254 """
255 def check_session(self, session, *args, **kwargs):
256 if auth_manager().is_session_valid(session):
257 return func(self, session, *args, **kwargs)
258 else:
259 return xen_api_error(['SESSION_INVALID', session])
261 return check_session
264 def _is_valid_ref(ref, validator):
265 return type(ref) == str and validator(ref)
267 def _check_ref(validator, clas, func, api, session, ref, *args, **kwargs):
268 if _is_valid_ref(ref, validator):
269 return func(api, session, ref, *args, **kwargs)
270 else:
271 return xen_api_error(['HANDLE_INVALID', clas, ref])
274 def valid_host(func):
275 """Decorator to verify if host_ref is valid before calling method.
277 @param func: function with params: (self, session, host_ref, ...)
278 @rtype: callable object
279 """
280 return lambda *args, **kwargs: \
281 _check_ref(XendNode.instance().is_valid_host,
282 'host', func, *args, **kwargs)
284 def valid_host_metrics(func):
285 """Decorator to verify if host_metrics_ref is valid before calling
286 method.
288 @param func: function with params: (self, session, host_metrics_ref)
289 @rtype: callable object
290 """
291 return lambda *args, **kwargs: \
292 _check_ref(lambda r: r == XendNode.instance().host_metrics_uuid,
293 'host_metrics', func, *args, **kwargs)
295 def valid_host_cpu(func):
296 """Decorator to verify if host_cpu_ref is valid before calling method.
298 @param func: function with params: (self, session, host_cpu_ref, ...)
299 @rtype: callable object
300 """
301 return lambda *args, **kwargs: \
302 _check_ref(XendNode.instance().is_valid_cpu,
303 'host_cpu', func, *args, **kwargs)
305 def valid_vm(func):
306 """Decorator to verify if vm_ref is valid before calling method.
308 @param func: function with params: (self, session, vm_ref, ...)
309 @rtype: callable object
310 """
311 return lambda *args, **kwargs: \
312 _check_ref(XendDomain.instance().is_valid_vm,
313 'VM', func, *args, **kwargs)
315 def valid_vbd(func):
316 """Decorator to verify if vbd_ref is valid before calling method.
318 @param func: function with params: (self, session, vbd_ref, ...)
319 @rtype: callable object
320 """
321 return lambda *args, **kwargs: \
322 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vbd', r),
323 'VBD', func, *args, **kwargs)
325 def valid_vbd_metrics(func):
326 """Decorator to verify if ref is valid before calling method.
328 @param func: function with params: (self, session, ref, ...)
329 @rtype: callable object
330 """
331 return lambda *args, **kwargs: \
332 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vbd', r),
333 'VBD_metrics', func, *args, **kwargs)
335 def valid_vif(func):
336 """Decorator to verify if vif_ref is valid before calling method.
338 @param func: function with params: (self, session, vif_ref, ...)
339 @rtype: callable object
340 """
341 return lambda *args, **kwargs: \
342 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vif', r),
343 'VIF', func, *args, **kwargs)
345 def valid_vif_metrics(func):
346 """Decorator to verify if ref is valid before calling method.
348 @param func: function with params: (self, session, ref, ...)
349 @rtype: callable object
350 """
351 return lambda *args, **kwargs: \
352 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vif', r),
353 'VIF_metrics', func, *args, **kwargs)
355 def valid_vdi(func):
356 """Decorator to verify if vdi_ref is valid before calling method.
358 @param func: function with params: (self, session, vdi_ref, ...)
359 @rtype: callable object
360 """
361 return lambda *args, **kwargs: \
362 _check_ref(XendNode.instance().is_valid_vdi,
363 'VDI', func, *args, **kwargs)
365 def valid_vtpm(func):
366 """Decorator to verify if vtpm_ref is valid before calling method.
368 @param func: function with params: (self, session, vtpm_ref, ...)
369 @rtype: callable object
370 """
371 return lambda *args, **kwargs: \
372 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vtpm', r),
373 'VTPM', func, *args, **kwargs)
376 def valid_console(func):
377 """Decorator to verify if console_ref is valid before calling method.
379 @param func: function with params: (self, session, console_ref, ...)
380 @rtype: callable object
381 """
382 return lambda *args, **kwargs: \
383 _check_ref(lambda r: XendDomain.instance().is_valid_dev('console',
384 r),
385 'console', func, *args, **kwargs)
387 def valid_sr(func):
388 """Decorator to verify if sr_ref is valid before calling method.
390 @param func: function with params: (self, session, sr_ref, ...)
391 @rtype: callable object
392 """
393 return lambda *args, **kwargs: \
394 _check_ref(lambda r: XendNode.instance().is_valid_sr,
395 'SR', func, *args, **kwargs)
397 def valid_task(func):
398 """Decorator to verify if task_ref is valid before calling
399 method.
401 @param func: function with params: (self, session, task_ref)
402 @rtype: callable object
403 """
404 return lambda *args, **kwargs: \
405 _check_ref(XendTaskManager.get_task,
406 'task', func, *args, **kwargs)
408 def valid_debug(func):
409 """Decorator to verify if task_ref is valid before calling
410 method.
412 @param func: function with params: (self, session, task_ref)
413 @rtype: callable object
414 """
415 return lambda *args, **kwargs: \
416 _check_ref(lambda r: r in XendAPI._debug,
417 'debug', func, *args, **kwargs)
420 def valid_object(class_name):
421 """Decorator to verify if object is valid before calling
422 method.
424 @param func: function with params: (self, session, pif_ref)
425 @rtype: callable object
426 """
427 return lambda func: \
428 lambda *args, **kwargs: \
429 _check_ref(lambda r: \
430 XendAPIStore.get(r, class_name) is not None,
431 'PIF', func, *args, **kwargs)
433 # -----------------------------
434 # Bridge to Legacy XM API calls
435 # -----------------------------
437 def do_vm_func(fn_name, vm_ref, *args, **kwargs):
438 """Helper wrapper func to abstract away from repetitive code.
440 @param fn_name: function name for XendDomain instance
441 @type fn_name: string
442 @param vm_ref: vm_ref
443 @type vm_ref: string
444 @param *args: more arguments
445 @type *args: tuple
446 """
447 try:
448 xendom = XendDomain.instance()
449 fn = getattr(xendom, fn_name)
450 xendom.do_legacy_api_with_uuid(fn, vm_ref, *args, **kwargs)
451 return xen_api_success_void()
452 except VMBadState, exn:
453 return xen_api_error(['VM_BAD_POWER_STATE', vm_ref, exn.expected,
454 exn.actual])
457 classes = {
458 'session' : None,
459 'event' : None,
460 'host' : valid_host,
461 'host_cpu' : valid_host_cpu,
462 'host_metrics' : valid_host_metrics,
463 'VM' : valid_vm,
464 'VBD' : valid_vbd,
465 'VBD_metrics' : valid_vbd_metrics,
466 'VIF' : valid_vif,
467 'VIF_metrics' : valid_vif_metrics,
468 'VDI' : valid_vdi,
469 'VTPM' : valid_vtpm,
470 'console' : valid_console,
471 'SR' : valid_sr,
472 'task' : valid_task,
473 'XSPolicy' : valid_object("XSPolicy"),
474 'ACMPolicy' : valid_object("ACMPolicy"),
475 'debug' : valid_debug,
476 'network' : valid_object("network"),
477 'PIF' : valid_object("PIF"),
478 'VM_metrics' : valid_object("VM_metrics"),
479 'PBD' : valid_object("PBD"),
480 'PIF_metrics' : valid_object("PIF_metrics"),
481 'PPCI' : valid_object("PPCI"),
482 }
484 autoplug_classes = {
485 'network' : XendNetwork,
486 'PIF' : XendPIF,
487 'VM_metrics' : XendVMMetrics,
488 'PBD' : XendPBD,
489 'PIF_metrics' : XendPIFMetrics,
490 'PPCI' : XendPPCI,
491 'XSPolicy' : XendXSPolicy,
492 'ACMPolicy' : XendACMPolicy,
493 }
495 class XendAPI(object):
496 """Implementation of the Xen-API in Xend. Expects to be
497 used via XMLRPCServer.
499 All methods that need a valid session are marked with
500 a L{session_required} decorator that will
501 transparently perform the required session authentication.
503 We need to support Python <2.4, so we use the old decorator syntax.
505 All XMLRPC accessible methods require an 'api' attribute and
506 is set to the XMLRPC function name which the method implements.
507 """
509 __decorated__ = False
510 __init_lock__ = threading.Lock()
511 _debug = {}
513 def __new__(cls, *args, **kwds):
514 """ Override __new__ to decorate the class only once.
516 Lock to make sure the classes are not decorated twice.
517 """
518 cls.__init_lock__.acquire()
519 try:
520 if not cls.__decorated__:
521 cls._decorate()
522 cls.__decorated__ = True
524 return object.__new__(cls, *args, **kwds)
525 finally:
526 cls.__init_lock__.release()
528 def _decorate(cls):
529 """ Decorate all the object methods to have validators
530 and appropriate function attributes.
532 This should only be executed once for the duration of the
533 server.
534 """
535 global_validators = [session_required, catch_typeerror]
538 # Cheat methods
539 # -------------
540 # Methods that have a trivial implementation for all classes.
541 # 1. get_by_uuid == getting by ref, so just return uuid for
542 # all get_by_uuid() methods.
544 for api_cls in classes.keys():
545 # We'll let the autoplug classes implement these functions
546 # themselves - its much cleaner to do it in the base class
547 if api_cls == 'session' or api_cls in autoplug_classes.keys():
548 continue
550 get_by_uuid = '%s_get_by_uuid' % api_cls
551 get_uuid = '%s_get_uuid' % api_cls
552 get_all_records = '%s_get_all_records' % api_cls
554 def _get_by_uuid(_1, _2, ref):
555 return xen_api_success(ref)
557 def _get_uuid(_1, _2, ref):
558 return xen_api_success(ref)
560 def unpack(v):
561 return v.get('Value')
563 def _get_all_records(_api_cls):
564 return lambda s, session: \
565 xen_api_success(dict([(ref, unpack(getattr(cls, '%s_get_record' % _api_cls)(s, session, ref)))\
566 for ref in unpack(getattr(cls, '%s_get_all' % _api_cls)(s, session))]))
568 setattr(cls, get_by_uuid, _get_by_uuid)
569 setattr(cls, get_uuid, _get_uuid)
570 setattr(cls, get_all_records, _get_all_records(api_cls))
572 # Autoplugging classes
573 # --------------------
574 # These have all of their methods grabbed out from the implementation
575 # class, and wrapped up to be compatible with the Xen-API.
577 def getter(ref, type):
578 return XendAPIStore.get(ref, type)
580 for api_cls, impl_cls in autoplug_classes.items():
581 def doit(n):
582 dot_n = '%s.%s' % (api_cls, n)
583 full_n = '%s_%s' % (api_cls, n)
584 if not hasattr(cls, full_n):
585 f = getattr(impl_cls, n)
586 argcounts[dot_n] = f.func_code.co_argcount + 1
587 g = lambda api_cls: \
588 setattr(cls, full_n, \
589 lambda s, session, ref, *args: \
590 xen_api_success( \
591 f(getter(ref, api_cls), *args)))
592 g(api_cls) # Force api_cls to be captured
594 def doit_func(n):
595 dot_n = '%s.%s' % (api_cls, n)
596 full_n = '%s_%s' % (api_cls, n)
597 if not hasattr(cls, full_n):
598 f = getattr(impl_cls, n)
599 argcounts[dot_n] = f.func_code.co_argcount
600 setattr(cls, full_n, \
601 lambda s, session, *args: \
602 xen_api_success( \
603 f(*args)))
605 ro_attrs = impl_cls.getAttrRO()
606 rw_attrs = impl_cls.getAttrRW()
607 methods = impl_cls.getMethods()
608 funcs = impl_cls.getFuncs()
610 for attr_name in ro_attrs + rw_attrs:
611 doit('get_%s' % attr_name)
612 for attr_name in rw_attrs:
613 doit('set_%s' % attr_name)
614 for method in methods:
615 doit('%s' % method)
616 for func in funcs:
617 doit_func('%s' % func)
619 def wrap_method(name, new_f):
620 try:
621 f = getattr(cls, name)
622 wrapped_f = (lambda *args: new_f(f, *args))
623 wrapped_f.api = f.api
624 wrapped_f.async = f.async
625 setattr(cls, name, wrapped_f)
626 except AttributeError:
627 # Logged below (API call: %s not found)
628 pass
631 def setter_event_wrapper(api_cls, attr_name):
632 setter_name = '%s_set_%s' % (api_cls, attr_name)
633 wrap_method(
634 setter_name,
635 lambda setter, s, session, ref, *args:
636 _setter_event_dispatch(s, setter, api_cls, attr_name,
637 session, ref, args))
640 def ctor_event_wrapper(api_cls):
641 ctor_name = '%s_create' % api_cls
642 wrap_method(
643 ctor_name,
644 lambda ctor, s, session, *args:
645 _ctor_event_dispatch(s, ctor, api_cls, session, args))
648 def dtor_event_wrapper(api_cls):
649 dtor_name = '%s_destroy' % api_cls
650 wrap_method(
651 dtor_name,
652 lambda dtor, s, session, ref, *args:
653 _dtor_event_dispatch(s, dtor, api_cls, session, ref, args))
656 # Wrapping validators around XMLRPC calls
657 # ---------------------------------------
659 for api_cls, validator in classes.items():
660 def doit(n, takes_instance, async_support = False,
661 return_type = None):
662 n_ = n.replace('.', '_')
663 try:
664 f = getattr(cls, n_)
665 if n not in argcounts:
666 argcounts[n] = f.func_code.co_argcount - 1
668 validators = takes_instance and validator and \
669 [validator] or []
671 validators += global_validators
672 for v in validators:
673 f = v(f)
674 f.api = n
675 f.async = async_support
676 if return_type:
677 f.return_type = return_type
679 setattr(cls, n_, f)
680 except AttributeError:
681 log.warn("API call: %s not found" % n)
683 if api_cls in autoplug_classes.keys():
684 impl_cls = autoplug_classes[api_cls]
685 ro_attrs = impl_cls.getAttrRO()
686 rw_attrs = impl_cls.getAttrRW()
687 methods = map(lambda x: (x, ""), impl_cls.getMethods())
688 funcs = map(lambda x: (x, ""), impl_cls.getFuncs())
689 else:
690 ro_attrs = getattr(cls, '%s_attr_ro' % api_cls, []) \
691 + cls.Base_attr_ro
692 rw_attrs = getattr(cls, '%s_attr_rw' % api_cls, []) \
693 + cls.Base_attr_rw
694 methods = getattr(cls, '%s_methods' % api_cls, []) \
695 + cls.Base_methods
696 funcs = getattr(cls, '%s_funcs' % api_cls, []) \
697 + cls.Base_funcs
699 # wrap validators around readable class attributes
700 for attr_name in ro_attrs + rw_attrs:
701 doit('%s.get_%s' % (api_cls, attr_name), True,
702 async_support = False)
704 # wrap validators around writable class attrributes
705 for attr_name in rw_attrs:
706 doit('%s.set_%s' % (api_cls, attr_name), True,
707 async_support = False)
708 setter_event_wrapper(api_cls, attr_name)
710 # wrap validators around methods
711 for method_name, return_type in methods:
712 doit('%s.%s' % (api_cls, method_name), True,
713 async_support = True)
715 # wrap validators around class functions
716 for func_name, return_type in funcs:
717 doit('%s.%s' % (api_cls, func_name), False,
718 async_support = True,
719 return_type = return_type)
721 ctor_event_wrapper(api_cls)
722 dtor_event_wrapper(api_cls)
725 _decorate = classmethod(_decorate)
727 def __init__(self, auth):
728 self.auth = auth
730 Base_attr_ro = ['uuid']
731 Base_attr_rw = []
732 Base_methods = [('get_record', 'Struct')]
733 Base_funcs = [('get_all', 'Set'), ('get_by_uuid', None), ('get_all_records', 'Set')]
735 # Xen API: Class Session
736 # ----------------------------------------------------------------
737 # NOTE: Left unwrapped by __init__
739 session_attr_ro = ['this_host', 'this_user', 'last_active']
740 session_methods = [('logout', None)]
742 def session_get_all(self, session):
743 return xen_api_success([session])
745 def session_login_with_password(self, *args):
746 if len(args) != 2:
747 return xen_api_error(
748 ['MESSAGE_PARAMETER_COUNT_MISMATCH',
749 'session.login_with_password', 2, len(args)])
750 username = args[0]
751 password = args[1]
752 try:
753 session = ((self.auth == AUTH_NONE and
754 auth_manager().login_unconditionally(username)) or
755 auth_manager().login_with_password(username, password))
756 return xen_api_success(session)
757 except XendError, e:
758 return xen_api_error(['SESSION_AUTHENTICATION_FAILED'])
759 session_login_with_password.api = 'session.login_with_password'
761 # object methods
762 def session_logout(self, session):
763 auth_manager().logout(session)
764 return xen_api_success_void()
766 def session_get_record(self, session, self_session):
767 if self_session != session:
768 return xen_api_error(['PERMISSION_DENIED'])
769 record = {'uuid' : session,
770 'this_host' : XendNode.instance().uuid,
771 'this_user' : auth_manager().get_user(session),
772 'last_active': now()}
773 return xen_api_success(record)
775 def session_get_uuid(self, session, self_session):
776 return xen_api_success(self_session)
778 def session_get_by_uuid(self, session, self_session):
779 return xen_api_success(self_session)
781 # attributes (ro)
782 def session_get_this_host(self, session, self_session):
783 if self_session != session:
784 return xen_api_error(['PERMISSION_DENIED'])
785 return xen_api_success(XendNode.instance().uuid)
787 def session_get_this_user(self, session, self_session):
788 if self_session != session:
789 return xen_api_error(['PERMISSION_DENIED'])
790 user = auth_manager().get_user(session)
791 if user is not None:
792 return xen_api_success(user)
793 return xen_api_error(['SESSION_INVALID', session])
795 def session_get_last_active(self, session, self_session):
796 if self_session != session:
797 return xen_api_error(['PERMISSION_DENIED'])
798 return xen_api_success(now())
801 # Xen API: Class User
802 # ----------------------------------------------------------------
803 # TODO: NOT IMPLEMENTED YET
805 # Xen API: Class Tasks
806 # ----------------------------------------------------------------
808 task_attr_ro = ['name_label',
809 'name_description',
810 'status',
811 'progress',
812 'type',
813 'result',
814 'error_info',
815 'allowed_operations',
816 'session'
817 ]
819 task_attr_rw = []
821 task_funcs = [('get_by_name_label', 'Set(task)'),
822 ('cancel', None)]
824 def task_get_name_label(self, session, task_ref):
825 task = XendTaskManager.get_task(task_ref)
826 return xen_api_success(task.name_label)
828 def task_get_name_description(self, session, task_ref):
829 task = XendTaskManager.get_task(task_ref)
830 return xen_api_success(task.name_description)
832 def task_get_status(self, session, task_ref):
833 task = XendTaskManager.get_task(task_ref)
834 return xen_api_success(task.get_status())
836 def task_get_progress(self, session, task_ref):
837 task = XendTaskManager.get_task(task_ref)
838 return xen_api_success(task.progress)
840 def task_get_type(self, session, task_ref):
841 task = XendTaskManager.get_task(task_ref)
842 return xen_api_success(task.type)
844 def task_get_result(self, session, task_ref):
845 task = XendTaskManager.get_task(task_ref)
846 return xen_api_success(task.result)
848 def task_get_error_info(self, session, task_ref):
849 task = XendTaskManager.get_task(task_ref)
850 return xen_api_success(task.error_info)
852 def task_get_allowed_operations(self, session, task_ref):
853 return xen_api_success({})
855 def task_get_session(self, session, task_ref):
856 task = XendTaskManager.get_task(task_ref)
857 return xen_api_success(task.session)
859 def task_get_all(self, session):
860 tasks = XendTaskManager.get_all_tasks()
861 return xen_api_success(tasks)
863 def task_get_record(self, session, task_ref):
864 task = XendTaskManager.get_task(task_ref)
865 return xen_api_success(task.get_record())
867 def task_cancel(self, session, task_ref):
868 return xen_api_error('OPERATION_NOT_ALLOWED')
870 def task_get_by_name_label(self, session, name):
871 return xen_api_success(XendTaskManager.get_task_by_name(name))
873 # Xen API: Class host
874 # ----------------------------------------------------------------
876 host_attr_ro = ['software_version',
877 'resident_VMs',
878 'PBDs',
879 'PIFs',
880 'PPCIs',
881 'host_CPUs',
882 'cpu_configuration',
883 'metrics',
884 'capabilities',
885 'supported_bootloaders',
886 'sched_policy',
887 'API_version_major',
888 'API_version_minor',
889 'API_version_vendor',
890 'API_version_vendor_implementation',
891 'enabled']
893 host_attr_rw = ['name_label',
894 'name_description',
895 'other_config',
896 'logging']
898 host_methods = [('disable', None),
899 ('enable', None),
900 ('reboot', None),
901 ('shutdown', None),
902 ('add_to_other_config', None),
903 ('remove_from_other_config', None),
904 ('dmesg', 'String'),
905 ('dmesg_clear', 'String'),
906 ('get_log', 'String'),
907 ('send_debug_keys', None)]
909 host_funcs = [('get_by_name_label', None),
910 ('list_methods', None)]
912 # attributes
913 def host_get_name_label(self, session, host_ref):
914 return xen_api_success(XendNode.instance().name)
915 def host_set_name_label(self, session, host_ref, new_name):
916 XendNode.instance().set_name(new_name)
917 return xen_api_success_void()
918 def host_get_name_description(self, session, host_ref):
919 return xen_api_success(XendNode.instance().get_description())
920 def host_set_name_description(self, session, host_ref, new_desc):
921 XendNode.instance().set_description(new_desc)
922 return xen_api_success_void()
923 def host_get_other_config(self, session, host_ref):
924 return xen_api_success(XendNode.instance().other_config)
925 def host_set_other_config(self, session, host_ref, other_config):
926 node = XendNode.instance()
927 node.other_config = dict(other_config)
928 node.save()
929 return xen_api_success_void()
930 def host_add_to_other_config(self, session, host_ref, key, value):
931 node = XendNode.instance()
932 node.other_config[key] = value
933 node.save()
934 return xen_api_success_void()
935 def host_remove_from_other_config(self, session, host_ref, key):
936 node = XendNode.instance()
937 if key in node.other_config:
938 del node.other_config[key]
939 node.save()
940 return xen_api_success_void()
941 def host_get_API_version_major(self, _, ref):
942 return xen_api_success(XEN_API_VERSION_MAJOR)
943 def host_get_API_version_minor(self, _, ref):
944 return xen_api_success(XEN_API_VERSION_MINOR)
945 def host_get_API_version_vendor(self, _, ref):
946 return xen_api_success(XEN_API_VERSION_VENDOR)
947 def host_get_API_version_vendor_implementation(self, _, ref):
948 return xen_api_success(XEN_API_VERSION_VENDOR_IMPLEMENTATION)
949 def host_get_software_version(self, session, host_ref):
950 return xen_api_success(XendNode.instance().xen_version())
951 def host_get_enabled(self, _1, _2):
952 return xen_api_success(XendDomain.instance().allow_new_domains())
953 def host_get_resident_VMs(self, session, host_ref):
954 return xen_api_success(XendDomain.instance().get_domain_refs())
955 def host_get_PBDs(self, _, ref):
956 return xen_api_success(XendPBD.get_all())
957 def host_get_PIFs(self, session, ref):
958 return xen_api_success(XendNode.instance().get_PIF_refs())
959 def host_get_PPCIs(self, session, ref):
960 return xen_api_success(XendNode.instance().get_PPCI_refs())
961 def host_get_host_CPUs(self, session, host_ref):
962 return xen_api_success(XendNode.instance().get_host_cpu_refs())
963 def host_get_metrics(self, _, ref):
964 return xen_api_success(XendNode.instance().host_metrics_uuid)
965 def host_get_capabilities(self, session, host_ref):
966 return xen_api_success(XendNode.instance().get_capabilities())
967 def host_get_supported_bootloaders(self, session, host_ref):
968 return xen_api_success(['pygrub'])
969 def host_get_sched_policy(self, _, host_ref):
970 return xen_api_success(XendNode.instance().get_vcpus_policy())
971 def host_get_cpu_configuration(self, _, host_ref):
972 return xen_api_success(XendNode.instance().get_cpu_configuration())
973 def host_set_logging(self, _, host_ref, logging):
974 return xen_api_todo()
975 def host_get_logging(self, _, host_ref):
976 return xen_api_todo()
978 # object methods
979 def host_disable(self, session, host_ref):
980 XendDomain.instance().set_allow_new_domains(False)
981 return xen_api_success_void()
982 def host_enable(self, session, host_ref):
983 XendDomain.instance().set_allow_new_domains(True)
984 return xen_api_success_void()
985 def host_reboot(self, session, host_ref):
986 if not XendDomain.instance().allow_new_domains():
987 return xen_api_error(XEND_ERROR_HOST_RUNNING)
988 return xen_api_error(XEND_ERROR_UNSUPPORTED)
989 def host_shutdown(self, session, host_ref):
990 if not XendDomain.instance().allow_new_domains():
991 return xen_api_error(XEND_ERROR_HOST_RUNNING)
992 return xen_api_error(XEND_ERROR_UNSUPPORTED)
994 def host_dmesg(self, session, host_ref):
995 return xen_api_success(XendDmesg.instance().info())
997 def host_dmesg_clear(self, session, host_ref):
998 return xen_api_success(XendDmesg.instance().clear())
1000 def host_get_log(self, session, host_ref):
1001 log_file = open(XendLogging.getLogFilename())
1002 log_buffer = log_file.read()
1003 log_buffer = log_buffer.replace('\b', ' ')
1004 log_buffer = log_buffer.replace('\f', '\n')
1005 log_file.close()
1006 return xen_api_success(log_buffer)
1008 def host_send_debug_keys(self, _, host_ref, keys):
1009 node = XendNode.instance()
1010 node.send_debug_keys(keys)
1011 return xen_api_success_void()
1013 def host_get_record(self, session, host_ref):
1014 node = XendNode.instance()
1015 dom = XendDomain.instance()
1016 record = {'uuid': node.uuid,
1017 'name_label': node.name,
1018 'name_description': '',
1019 'API_version_major': XEN_API_VERSION_MAJOR,
1020 'API_version_minor': XEN_API_VERSION_MINOR,
1021 'API_version_vendor': XEN_API_VERSION_VENDOR,
1022 'API_version_vendor_implementation':
1023 XEN_API_VERSION_VENDOR_IMPLEMENTATION,
1024 'software_version': node.xen_version(),
1025 'enabled': XendDomain.instance().allow_new_domains(),
1026 'other_config': node.other_config,
1027 'resident_VMs': dom.get_domain_refs(),
1028 'host_CPUs': node.get_host_cpu_refs(),
1029 'cpu_configuration': node.get_cpu_configuration(),
1030 'metrics': node.host_metrics_uuid,
1031 'capabilities': node.get_capabilities(),
1032 'supported_bootloaders': ['pygrub'],
1033 'sched_policy': node.get_vcpus_policy(),
1034 'logging': {},
1035 'PIFs': XendPIF.get_all(),
1036 'PBDs': XendPBD.get_all(),
1037 'PPCIs': XendPPCI.get_all()}
1038 return xen_api_success(record)
1040 # class methods
1041 def host_get_all(self, session):
1042 return xen_api_success((XendNode.instance().uuid,))
1043 def host_get_by_name_label(self, session, name):
1044 if XendNode.instance().name == name:
1045 return xen_api_success((XendNode.instance().uuid,))
1046 return xen_api_success([])
1048 def host_list_methods(self, _):
1049 def _funcs():
1050 return [getattr(XendAPI, x) for x in XendAPI.__dict__]
1052 return xen_api_success([x.api for x in _funcs()
1053 if hasattr(x, 'api')])
1055 # Xen API: Class host_CPU
1056 # ----------------------------------------------------------------
1058 host_cpu_attr_ro = ['host',
1059 'number',
1060 'vendor',
1061 'speed',
1062 'modelname',
1063 'stepping',
1064 'flags',
1065 'utilisation',
1066 'features']
1068 # attributes
1069 def _host_cpu_get(self, ref, field):
1070 return xen_api_success(
1071 XendNode.instance().get_host_cpu_field(ref, field))
1073 def host_cpu_get_host(self, _, ref):
1074 return xen_api_success(XendNode.instance().uuid)
1075 def host_cpu_get_features(self, _, ref):
1076 return self._host_cpu_get(ref, 'features')
1077 def host_cpu_get_number(self, _, ref):
1078 return self._host_cpu_get(ref, 'number')
1079 def host_cpu_get_vendor(self, _, ref):
1080 return self._host_cpu_get(ref, 'vendor')
1081 def host_cpu_get_speed(self, _, ref):
1082 return self._host_cpu_get(ref, 'speed')
1083 def host_cpu_get_modelname(self, _, ref):
1084 return self._host_cpu_get(ref, 'modelname')
1085 def host_cpu_get_stepping(self, _, ref):
1086 return self._host_cpu_get(ref, 'stepping')
1087 def host_cpu_get_flags(self, _, ref):
1088 return self._host_cpu_get(ref, 'flags')
1089 def host_cpu_get_utilisation(self, _, ref):
1090 return xen_api_success(XendNode.instance().get_host_cpu_load(ref))
1092 # object methods
1093 def host_cpu_get_record(self, _, ref):
1094 node = XendNode.instance()
1095 record = dict([(f, node.get_host_cpu_field(ref, f))
1096 for f in self.host_cpu_attr_ro
1097 if f not in ['uuid', 'host', 'utilisation']])
1098 record['uuid'] = ref
1099 record['host'] = node.uuid
1100 record['utilisation'] = node.get_host_cpu_load(ref)
1101 return xen_api_success(record)
1103 # class methods
1104 def host_cpu_get_all(self, session):
1105 return xen_api_success(XendNode.instance().get_host_cpu_refs())
1108 # Xen API: Class host_metrics
1109 # ----------------------------------------------------------------
1111 host_metrics_attr_ro = ['memory_total',
1112 'memory_free',
1113 'last_updated']
1114 host_metrics_attr_rw = []
1115 host_metrics_methods = []
1117 def host_metrics_get_all(self, _):
1118 return xen_api_success([XendNode.instance().host_metrics_uuid])
1120 def _host_metrics_get(self, ref, f):
1121 return xen_api_success(getattr(node, f)())
1123 def host_metrics_get_record(self, _, ref):
1124 return xen_api_success({
1125 'uuid' : ref,
1126 'memory_total' : self._host_metrics_get_memory_total(),
1127 'memory_free' : self._host_metrics_get_memory_free(),
1128 'last_updated' : now(),
1129 })
1131 def host_metrics_get_memory_total(self, _1, _2):
1132 return xen_api_success(self._host_metrics_get_memory_total())
1134 def host_metrics_get_memory_free(self, _1, _2):
1135 return xen_api_success(self._host_metrics_get_memory_free())
1137 def host_metrics_get_last_updated(self, _1, _2):
1138 return xen_api_success(now())
1140 def _host_metrics_get_memory_total(self):
1141 node = XendNode.instance()
1142 return node.xc.physinfo()['total_memory'] * 1024
1144 def _host_metrics_get_memory_free(self):
1145 node = XendNode.instance()
1146 return node.xc.physinfo()['free_memory'] * 1024
1148 # Xen API: Class VM
1149 # ----------------------------------------------------------------
1151 VM_attr_ro = ['power_state',
1152 'resident_on',
1153 'consoles',
1154 'VIFs',
1155 'VBDs',
1156 'VTPMs',
1157 'tools_version',
1158 'domid',
1159 'is_control_domain',
1160 'metrics',
1161 'crash_dumps',
1164 VM_attr_rw = ['name_label',
1165 'name_description',
1166 'user_version',
1167 'is_a_template',
1168 'auto_power_on',
1169 'memory_dynamic_max',
1170 'memory_dynamic_min',
1171 'memory_static_max',
1172 'memory_static_min',
1173 'VCPUs_max',
1174 'VCPUs_at_startup',
1175 'VCPUs_params',
1176 'actions_after_shutdown',
1177 'actions_after_reboot',
1178 'actions_after_suspend',
1179 'actions_after_crash',
1180 'PV_bootloader',
1181 'PV_kernel',
1182 'PV_ramdisk',
1183 'PV_args',
1184 'PV_bootloader_args',
1185 'HVM_boot_policy',
1186 'HVM_boot_params',
1187 'platform',
1188 'PCI_bus',
1189 'other_config',
1190 'security_label']
1192 VM_methods = [('clone', 'VM'),
1193 ('start', None),
1194 ('pause', None),
1195 ('unpause', None),
1196 ('clean_shutdown', None),
1197 ('clean_reboot', None),
1198 ('hard_shutdown', None),
1199 ('hard_reboot', None),
1200 ('suspend', None),
1201 ('resume', None),
1202 ('send_sysrq', None),
1203 ('set_VCPUs_number_live', None),
1204 ('add_to_HVM_boot_params', None),
1205 ('remove_from_HVM_boot_params', None),
1206 ('add_to_VCPUs_params', None),
1207 ('add_to_VCPUs_params_live', None),
1208 ('remove_from_VCPUs_params', None),
1209 ('add_to_platform', None),
1210 ('remove_from_platform', None),
1211 ('add_to_other_config', None),
1212 ('remove_from_other_config', None),
1213 ('save', None),
1214 ('set_memory_dynamic_max_live', None),
1215 ('set_memory_dynamic_min_live', None),
1216 ('send_trigger', None),
1217 ('migrate', None),
1218 ('destroy', None)]
1220 VM_funcs = [('create', 'VM'),
1221 ('restore', None),
1222 ('get_by_name_label', 'Set(VM)')]
1224 # parameters required for _create()
1225 VM_attr_inst = [
1226 'name_label',
1227 'name_description',
1228 'user_version',
1229 'is_a_template',
1230 'memory_static_max',
1231 'memory_dynamic_max',
1232 'memory_dynamic_min',
1233 'memory_static_min',
1234 'VCPUs_max',
1235 'VCPUs_at_startup',
1236 'VCPUs_params',
1237 'actions_after_shutdown',
1238 'actions_after_reboot',
1239 'actions_after_suspend',
1240 'actions_after_crash',
1241 'PV_bootloader',
1242 'PV_kernel',
1243 'PV_ramdisk',
1244 'PV_args',
1245 'PV_bootloader_args',
1246 'HVM_boot_policy',
1247 'HVM_boot_params',
1248 'platform',
1249 'PCI_bus',
1250 'other_config',
1251 'security_label']
1253 def VM_get(self, name, session, vm_ref):
1254 return xen_api_success(
1255 XendDomain.instance().get_vm_by_uuid(vm_ref).info[name])
1257 def VM_set(self, name, session, vm_ref, value):
1258 xd = XendDomain.instance()
1259 dominfo = xd.get_vm_by_uuid(vm_ref)
1260 dominfo.info[name] = value
1261 return self._VM_save(dominfo)
1263 def _VM_save(self, dominfo):
1264 XendDomain.instance().managed_config_save(dominfo)
1265 return xen_api_success_void()
1267 # attributes (ro)
1268 def VM_get_power_state(self, session, vm_ref):
1269 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1270 return xen_api_success(dom.get_power_state())
1272 def VM_get_resident_on(self, session, vm_ref):
1273 return xen_api_success(XendNode.instance().uuid)
1275 def VM_get_memory_static_max(self, session, vm_ref):
1276 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1277 return xen_api_success(dom.get_memory_static_max())
1279 def VM_get_memory_static_min(self, session, vm_ref):
1280 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1281 return xen_api_success(dom.get_memory_static_min())
1283 def VM_get_VIFs(self, session, vm_ref):
1284 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1285 return xen_api_success(dom.get_vifs())
1287 def VM_get_VBDs(self, session, vm_ref):
1288 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1289 return xen_api_success(dom.get_vbds())
1291 def VM_get_VTPMs(self, session, vm_ref):
1292 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1293 return xen_api_success(dom.get_vtpms())
1295 def VM_get_consoles(self, session, vm_ref):
1296 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1297 return xen_api_success(dom.get_consoles())
1299 def VM_get_tools_version(self, session, vm_ref):
1300 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1301 return dom.get_tools_version()
1303 def VM_get_metrics(self, _, vm_ref):
1304 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1305 return xen_api_success(dom.get_metrics())
1307 def VM_get_VCPUs_max(self, _, vm_ref):
1308 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1309 return xen_api_todo()
1311 def VM_get_VCPUs_at_startup(self, _, vm_ref):
1312 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1313 return xen_api_todo()
1315 # attributes (rw)
1316 def VM_get_name_label(self, session, vm_ref):
1317 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1318 return xen_api_success(dom.getName())
1320 def VM_get_name_description(self, session, vm_ref):
1321 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1322 return xen_api_todo()
1324 def VM_get_user_version(self, session, vm_ref):
1325 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1326 return xen_api_todo()
1328 def VM_get_is_a_template(self, session, ref):
1329 return self.VM_get('is_a_template', session, ref)
1331 def VM_get_memory_dynamic_max(self, session, vm_ref):
1332 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1333 return xen_api_success(dom.get_memory_dynamic_max())
1335 def VM_get_memory_dynamic_min(self, session, vm_ref):
1336 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1337 return xen_api_success(dom.get_memory_dynamic_min())
1339 def VM_get_VCPUs_params(self, session, vm_ref):
1340 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1341 return xen_api_success(dom.get_vcpus_params())
1343 def VM_get_actions_after_shutdown(self, session, vm_ref):
1344 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1345 return xen_api_success(dom.get_on_shutdown())
1347 def VM_get_actions_after_reboot(self, session, vm_ref):
1348 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1349 return xen_api_success(dom.get_on_reboot())
1351 def VM_get_actions_after_suspend(self, session, vm_ref):
1352 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1353 return xen_api_success(dom.get_on_suspend())
1355 def VM_get_actions_after_crash(self, session, vm_ref):
1356 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1357 return xen_api_success(dom.get_on_crash())
1359 def VM_get_PV_bootloader(self, session, vm_ref):
1360 return self.VM_get('PV_bootloader', session, vm_ref)
1362 def VM_get_PV_kernel(self, session, vm_ref):
1363 return self.VM_get('PV_kernel', session, vm_ref)
1365 def VM_get_PV_ramdisk(self, session, vm_ref):
1366 return self.VM_get('PV_ramdisk', session, vm_ref)
1368 def VM_get_PV_args(self, session, vm_ref):
1369 return self.VM_get('PV_args', session, vm_ref)
1371 def VM_get_PV_bootloader_args(self, session, vm_ref):
1372 return self.VM_get('PV_bootloader_args', session, vm_ref)
1374 def VM_get_HVM_boot_policy(self, session, vm_ref):
1375 return self.VM_get('HVM_boot_policy', session, vm_ref)
1377 def VM_get_HVM_boot_params(self, session, vm_ref):
1378 return self.VM_get('HVM_boot_params', session, vm_ref)
1380 def VM_get_platform(self, session, vm_ref):
1381 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1382 return xen_api_success(dom.get_platform())
1384 def VM_get_PCI_bus(self, session, vm_ref):
1385 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1386 return dom.get_pci_bus()
1388 def VM_set_PCI_bus(self, session, vm_ref, val):
1389 return self.VM_set('PCI_bus', session, vm_ref, val)
1391 def VM_get_other_config(self, session, vm_ref):
1392 return self.VM_get('other_config', session, vm_ref)
1394 def VM_get_domid(self, _, ref):
1395 domid = XendDomain.instance().get_vm_by_uuid(ref).getDomid()
1396 return xen_api_success(domid is None and -1 or domid)
1398 def VM_get_is_control_domain(self, session, vm_ref):
1399 xd = XendDomain.instance()
1400 return xen_api_success(
1401 xd.get_vm_by_uuid(vm_ref) == xd.privilegedDomain())
1403 def VM_set_name_label(self, session, vm_ref, label):
1404 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1405 dom.setName(label)
1406 return self._VM_save(dom)
1408 def VM_set_name_description(self, session, vm_ref, desc):
1409 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1410 return xen_api_todo()
1412 def VM_set_user_version(self, session, vm_ref, ver):
1413 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1414 return xen_api_todo()
1416 def VM_set_is_a_template(self, session, vm_ref, is_template):
1417 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1418 return xen_api_todo()
1420 def VM_set_memory_dynamic_max(self, session, vm_ref, mem):
1421 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1422 dom.set_memory_dynamic_max(int(mem))
1423 return self._VM_save(dom)
1425 def VM_set_memory_dynamic_min(self, session, vm_ref, mem):
1426 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1427 dom.set_memory_dynamic_min(int(mem))
1428 return self._VM_save(dom)
1430 def VM_set_memory_static_max(self, session, vm_ref, mem):
1431 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1432 dom.set_memory_static_max(int(mem))
1433 return self._VM_save(dom)
1435 def VM_set_memory_static_min(self, session, vm_ref, mem):
1436 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1437 dom.set_memory_static_min(int(mem))
1438 return self._VM_save(dom)
1440 def VM_set_memory_dynamic_max_live(self, session, vm_ref, mem):
1441 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1442 dom.set_memory_dynamic_max(int(mem))
1443 # need to pass target as MiB
1444 dom.setMemoryTarget(int(mem)/1024/1024)
1445 return xen_api_success_void()
1447 def VM_set_memory_dynamic_min_live(self, session, vm_ref, mem):
1448 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1449 dom.set_memory_dynamic_min(int(mem))
1450 # need to pass target as MiB
1451 dom.setMemoryTarget(int(mem)/1024/1024)
1452 return xen_api_success_void()
1454 def VM_set_VCPUs_params(self, session, vm_ref, value):
1455 return self.VM_set('vcpus_params', session, vm_ref, value)
1457 def VM_add_to_VCPUs_params(self, session, vm_ref, key, value):
1458 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1459 if 'vcpus_params' not in dom.info:
1460 dom.info['vcpus_params'] = {}
1461 dom.info['vcpus_params'][key] = value
1462 return self._VM_save(dom)
1464 def VM_add_to_VCPUs_params_live(self, session, vm_ref, key, value):
1465 self.VM_add_to_VCPUs_params(session, vm_ref, key, value)
1466 self._VM_VCPUs_params_refresh(vm_ref)
1467 return xen_api_success_void()
1469 def _VM_VCPUs_params_refresh(self, vm_ref):
1470 xendom = XendDomain.instance()
1471 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1473 #update the cpumaps
1474 for key, value in xeninfo.info['vcpus_params'].items():
1475 if key.startswith("cpumap"):
1476 vcpu = int(key[6:])
1477 try:
1478 cpus = map(int, value.split(","))
1479 xendom.domain_pincpu(xeninfo.getDomid(), vcpu, cpus)
1480 except Exception, ex:
1481 log.exception(ex)
1483 #need to update sched params aswell
1484 if 'weight' in xeninfo.info['vcpus_params'] \
1485 and 'cap' in xeninfo.info['vcpus_params']:
1486 weight = xeninfo.info['vcpus_params']['weight']
1487 cap = xeninfo.info['vcpus_params']['cap']
1488 xendom.domain_sched_credit_set(xeninfo.getDomid(), weight, cap)
1490 def VM_set_VCPUs_number_live(self, _, vm_ref, num):
1491 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1492 dom.setVCpuCount(int(num))
1493 return xen_api_success_void()
1495 def VM_remove_from_VCPUs_params(self, session, vm_ref, key):
1496 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1497 if 'vcpus_params' in dom.info \
1498 and key in dom.info['vcpus_params']:
1499 del dom.info['vcpus_params'][key]
1500 return self._VM_save(dom)
1501 else:
1502 return xen_api_success_void()
1504 def VM_set_VCPUs_at_startup(self, session, vm_ref, num):
1505 return self.VM_set('VCPUs_at_startup', session, vm_ref, num)
1507 def VM_set_VCPUs_max(self, session, vm_ref, num):
1508 return self.VM_set('VCPUs_max', session, vm_ref, num)
1510 def VM_set_actions_after_shutdown(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_shutdown', session, vm_ref, action)
1515 def VM_set_actions_after_reboot(self, session, vm_ref, action):
1516 if action not in XEN_API_ON_NORMAL_EXIT:
1517 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1518 return self.VM_set('actions_after_reboot', session, vm_ref, action)
1520 def VM_set_actions_after_suspend(self, session, vm_ref, action):
1521 if action not in XEN_API_ON_NORMAL_EXIT:
1522 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1523 return self.VM_set('actions_after_suspend', session, vm_ref, action)
1525 def VM_set_actions_after_crash(self, session, vm_ref, action):
1526 if action not in XEN_API_ON_CRASH_BEHAVIOUR:
1527 return xen_api_error(['VM_ON_CRASH_BEHAVIOUR_INVALID', vm_ref])
1528 return self.VM_set('actions_after_crash', session, vm_ref, action)
1530 def VM_set_HVM_boot_policy(self, session, vm_ref, value):
1531 if value != "" and value != "BIOS order":
1532 return xen_api_error(
1533 ['VALUE_NOT_SUPPORTED', 'VM.HVM_boot_policy', value,
1534 'Xend supports only the "BIOS order" boot policy.'])
1535 else:
1536 return self.VM_set('HVM_boot_policy', session, vm_ref, value)
1538 def VM_set_HVM_boot_params(self, session, vm_ref, value):
1539 return self.VM_set('HVM_boot_params', session, vm_ref, value)
1541 def VM_add_to_HVM_boot_params(self, session, vm_ref, key, value):
1542 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1543 if 'HVM_boot_params' not in dom.info:
1544 dom.info['HVM_boot_params'] = {}
1545 dom.info['HVM_boot_params'][key] = value
1546 return self._VM_save(dom)
1548 def VM_remove_from_HVM_boot_params(self, session, vm_ref, key):
1549 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1550 if 'HVM_boot_params' in dom.info \
1551 and key in dom.info['HVM_boot_params']:
1552 del dom.info['HVM_boot_params'][key]
1553 return self._VM_save(dom)
1554 else:
1555 return xen_api_success_void()
1557 def VM_set_PV_bootloader(self, session, vm_ref, value):
1558 return self.VM_set('PV_bootloader', session, vm_ref, value)
1560 def VM_set_PV_kernel(self, session, vm_ref, value):
1561 return self.VM_set('PV_kernel', session, vm_ref, value)
1563 def VM_set_PV_ramdisk(self, session, vm_ref, value):
1564 return self.VM_set('PV_ramdisk', session, vm_ref, value)
1566 def VM_set_PV_args(self, session, vm_ref, value):
1567 return self.VM_set('PV_args', session, vm_ref, value)
1569 def VM_set_PV_bootloader_args(self, session, vm_ref, value):
1570 return self.VM_set('PV_bootloader_args', session, vm_ref, value)
1572 def VM_set_platform(self, session, vm_ref, value):
1573 return self.VM_set('platform', session, vm_ref, value)
1575 def VM_add_to_platform(self, session, vm_ref, key, value):
1576 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1577 plat = dom.get_platform()
1578 plat[key] = value
1579 return self.VM_set_platform(session, vm_ref, plat)
1581 def VM_remove_from_platform(self, session, vm_ref, key):
1582 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1583 plat = dom.get_platform()
1584 if key in plat:
1585 del plat[key]
1586 return self.VM_set_platform(session, vm_ref, plat)
1587 else:
1588 return xen_api_success_void()
1590 def VM_set_other_config(self, session, vm_ref, value):
1591 return self.VM_set('other_config', session, vm_ref, value)
1593 def VM_add_to_other_config(self, session, vm_ref, key, value):
1594 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1595 if dom and 'other_config' in dom.info:
1596 dom.info['other_config'][key] = value
1597 return self._VM_save(dom)
1599 def VM_remove_from_other_config(self, session, vm_ref, key):
1600 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1601 if dom and 'other_config' in dom.info \
1602 and key in dom.info['other_config']:
1603 del dom.info['other_config'][key]
1604 return self._VM_save(dom)
1605 else:
1606 return xen_api_success_void()
1608 def VM_get_crash_dumps(self, _, vm_ref):
1609 return xen_api_todo()
1611 # class methods
1612 def VM_get_all(self, session):
1613 refs = [d.get_uuid() for d in XendDomain.instance().list('all')]
1614 return xen_api_success(refs)
1616 def VM_get_by_name_label(self, session, label):
1617 xendom = XendDomain.instance()
1618 dom = xendom.domain_lookup_nr(label)
1619 if dom:
1620 return xen_api_success([dom.get_uuid()])
1621 return xen_api_success([])
1623 def VM_get_security_label(self, session, vm_ref):
1624 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1625 label = dom.get_security_label()
1626 return xen_api_success(label)
1628 def VM_set_security_label(self, session, vm_ref, sec_label, old_label):
1629 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1630 (rc, errors, oldlabel, new_ssidref) = \
1631 dom.set_security_label(sec_label, old_label)
1632 if rc != xsconstants.XSERR_SUCCESS:
1633 return xen_api_error(['SECURITY_ERROR', rc,
1634 xsconstants.xserr2string(-rc)])
1635 if rc == 0:
1636 rc = new_ssidref
1637 return xen_api_success(rc)
1639 def VM_create(self, session, vm_struct):
1640 xendom = XendDomain.instance()
1641 domuuid = XendTask.log_progress(0, 100,
1642 xendom.create_domain, vm_struct)
1643 return xen_api_success(domuuid)
1645 # object methods
1646 def VM_get_record(self, session, vm_ref):
1647 xendom = XendDomain.instance()
1648 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1649 if not xeninfo:
1650 return xen_api_error(['HANDLE_INVALID', 'VM', vm_ref])
1652 domid = xeninfo.getDomid()
1654 record = {
1655 'uuid': xeninfo.get_uuid(),
1656 'power_state': xeninfo.get_power_state(),
1657 'name_label': xeninfo.getName(),
1658 'name_description': xeninfo.getName(),
1659 'user_version': 1,
1660 'is_a_template': xeninfo.info['is_a_template'],
1661 'auto_power_on': False,
1662 'resident_on': XendNode.instance().uuid,
1663 'memory_static_min': xeninfo.get_memory_static_min(),
1664 'memory_static_max': xeninfo.get_memory_static_max(),
1665 'memory_dynamic_min': xeninfo.get_memory_dynamic_min(),
1666 'memory_dynamic_max': xeninfo.get_memory_dynamic_max(),
1667 'VCPUs_params': xeninfo.get_vcpus_params(),
1668 'VCPUs_at_startup': xeninfo.getVCpuCount(),
1669 'VCPUs_max': xeninfo.getVCpuCount(),
1670 'actions_after_shutdown': xeninfo.get_on_shutdown(),
1671 'actions_after_reboot': xeninfo.get_on_reboot(),
1672 'actions_after_suspend': xeninfo.get_on_suspend(),
1673 'actions_after_crash': xeninfo.get_on_crash(),
1674 'consoles': xeninfo.get_consoles(),
1675 'VIFs': xeninfo.get_vifs(),
1676 'VBDs': xeninfo.get_vbds(),
1677 'VTPMs': xeninfo.get_vtpms(),
1678 'PV_bootloader': xeninfo.info.get('PV_bootloader'),
1679 'PV_kernel': xeninfo.info.get('PV_kernel'),
1680 'PV_ramdisk': xeninfo.info.get('PV_ramdisk'),
1681 'PV_args': xeninfo.info.get('PV_args'),
1682 'PV_bootloader_args': xeninfo.info.get('PV_bootloader_args'),
1683 'HVM_boot_policy': xeninfo.info.get('HVM_boot_policy'),
1684 'HVM_boot_params': xeninfo.info.get('HVM_boot_params'),
1685 'platform': xeninfo.get_platform(),
1686 'PCI_bus': xeninfo.get_pci_bus(),
1687 'tools_version': xeninfo.get_tools_version(),
1688 'other_config': xeninfo.info.get('other_config', {}),
1689 'domid': domid is None and -1 or domid,
1690 'is_control_domain': xeninfo.info['is_control_domain'],
1691 'metrics': xeninfo.get_metrics(),
1692 'security_label': xeninfo.get_security_label(),
1693 'crash_dumps': []
1695 return xen_api_success(record)
1697 def VM_clean_reboot(self, session, vm_ref):
1698 xendom = XendDomain.instance()
1699 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1700 XendTask.log_progress(0, 100, xeninfo.shutdown, "reboot")
1701 return xen_api_success_void()
1703 def VM_clean_shutdown(self, session, vm_ref):
1704 xendom = XendDomain.instance()
1705 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1706 XendTask.log_progress(0, 100, xeninfo.shutdown, "poweroff")
1707 return xen_api_success_void()
1709 def VM_clone(self, session, vm_ref):
1710 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1712 def VM_destroy(self, session, vm_ref):
1713 return XendTask.log_progress(0, 100, do_vm_func,
1714 "domain_delete", vm_ref)
1716 def VM_hard_reboot(self, session, vm_ref):
1717 return XendTask.log_progress(0, 100, do_vm_func,
1718 "domain_reset", vm_ref)
1720 def VM_hard_shutdown(self, session, vm_ref):
1721 return XendTask.log_progress(0, 100, do_vm_func,
1722 "domain_destroy", vm_ref)
1724 def VM_pause(self, session, vm_ref):
1725 return XendTask.log_progress(0, 100, do_vm_func,
1726 "domain_pause", vm_ref)
1728 def VM_resume(self, session, vm_ref, start_paused):
1729 return XendTask.log_progress(0, 100, do_vm_func,
1730 "domain_resume", vm_ref,
1731 start_paused = start_paused)
1733 def VM_start(self, session, vm_ref, start_paused):
1734 try:
1735 return XendTask.log_progress(0, 100, do_vm_func,
1736 "domain_start", vm_ref,
1737 start_paused = start_paused)
1738 except HVMRequired, exn:
1739 return xen_api_error(['VM_HVM_REQUIRED', vm_ref])
1741 def VM_suspend(self, session, vm_ref):
1742 return XendTask.log_progress(0, 100, do_vm_func,
1743 "domain_suspend", vm_ref)
1745 def VM_unpause(self, session, vm_ref):
1746 return XendTask.log_progress(0, 100, do_vm_func,
1747 "domain_unpause", vm_ref)
1749 def VM_send_sysrq(self, _, vm_ref, req):
1750 xeninfo = XendDomain.instance().get_vm_by_uuid(vm_ref)
1751 if xeninfo.state == XEN_API_VM_POWER_STATE_RUNNING \
1752 or xeninfo.state == XEN_API_VM_POWER_STATE_PAUSED:
1753 xeninfo.send_sysrq(req)
1754 return xen_api_success_void()
1755 else:
1756 return xen_api_error(
1757 ['VM_BAD_POWER_STATE', vm_ref,
1758 XendDomain.POWER_STATE_NAMES[XEN_API_VM_POWER_STATE_RUNNING],
1759 XendDomain.POWER_STATE_NAMES[xeninfo.state]])
1761 def VM_send_trigger(self, _, vm_ref, trigger, vcpu):
1762 xendom = XendDomain.instance()
1763 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1764 xendom.domain_send_trigger(xeninfo.getDomid(), trigger, vcpu)
1765 return xen_api_success_void()
1767 def VM_migrate(self, _, vm_ref, destination_url, live, other_config):
1768 xendom = XendDomain.instance()
1769 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1771 port = other_config.get("port", 0)
1772 node = other_config.get("node", -1)
1773 ssl = other_config.get("ssl", None)
1775 xendom.domain_migrate(xeninfo.getDomid(), destination_url,
1776 bool(live), port, node, ssl)
1777 return xen_api_success_void()
1779 def VM_save(self, _, vm_ref, dest, checkpoint):
1780 xendom = XendDomain.instance()
1781 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1782 xendom.domain_save(xeninfo.getDomid(), dest, checkpoint)
1783 return xen_api_success_void()
1785 def VM_restore(self, _, src, paused):
1786 xendom = XendDomain.instance()
1787 xendom.domain_restore(src, bool(paused))
1788 return xen_api_success_void()
1791 # Xen API: Class VBD
1792 # ----------------------------------------------------------------
1794 VBD_attr_ro = ['VM',
1795 'VDI',
1796 'metrics',
1797 'runtime_properties']
1798 VBD_attr_rw = ['device',
1799 'bootable',
1800 'mode',
1801 'type']
1803 VBD_attr_inst = VBD_attr_rw
1805 VBD_methods = [('media_change', None), ('destroy', None)]
1806 VBD_funcs = [('create', 'VBD')]
1808 # object methods
1809 def VBD_get_record(self, session, vbd_ref):
1810 xendom = XendDomain.instance()
1811 vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1812 if not vm:
1813 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1814 cfg = vm.get_dev_xenapi_config('vbd', vbd_ref)
1815 if not cfg:
1816 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1818 valid_vbd_keys = self.VBD_attr_ro + self.VBD_attr_rw + \
1819 self.Base_attr_ro + self.Base_attr_rw
1821 return_cfg = {}
1822 for k in cfg.keys():
1823 if k in valid_vbd_keys:
1824 return_cfg[k] = cfg[k]
1826 return_cfg['metrics'] = vbd_ref
1827 return_cfg['runtime_properties'] = {} #todo
1829 return xen_api_success(return_cfg)
1831 def VBD_media_change(self, session, vbd_ref, vdi_ref):
1832 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1834 # class methods
1835 def VBD_create(self, session, vbd_struct):
1836 xendom = XendDomain.instance()
1837 xennode = XendNode.instance()
1839 if not xendom.is_valid_vm(vbd_struct['VM']):
1840 return xen_api_error(['HANDLE_INVALID', 'VM', vbd_struct['VM']])
1842 dom = xendom.get_vm_by_uuid(vbd_struct['VM'])
1843 vdi = xennode.get_vdi_by_uuid(vbd_struct['VDI'])
1844 if not vdi:
1845 return xen_api_error(['HANDLE_INVALID', 'VDI', vdi_ref])
1847 # new VBD via VDI/SR
1848 vdi_image = vdi.get_location()
1850 try:
1851 vbd_ref = XendTask.log_progress(0, 100,
1852 dom.create_vbd,
1853 vbd_struct, vdi_image)
1854 except XendError, e:
1855 log.exception("Error in VBD_create")
1856 return xen_api_error(['INTERNAL_ERROR', str(e)])
1858 vdi.addVBD(vbd_ref)
1860 xendom.managed_config_save(dom)
1861 return xen_api_success(vbd_ref)
1864 def VBD_destroy(self, session, vbd_ref):
1865 xendom = XendDomain.instance()
1866 vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1867 if not vm:
1868 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1870 vdi_ref = XendDomain.instance()\
1871 .get_dev_property_by_uuid('vbd', vbd_ref, "VDI")
1872 vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
1874 XendTask.log_progress(0, 100, vm.destroy_vbd, vbd_ref)
1876 vdi.removeVBD(vbd_ref)
1878 return xen_api_success_void()
1880 def _VBD_get(self, vbd_ref, prop):
1881 return xen_api_success(
1882 XendDomain.instance().get_dev_property_by_uuid(
1883 'vbd', vbd_ref, prop))
1885 # attributes (ro)
1886 def VBD_get_metrics(self, _, vbd_ref):
1887 return xen_api_success(vbd_ref)
1889 def VBD_get_runtime_properties(self, _, vbd_ref):
1890 xendom = XendDomain.instance()
1891 dominfo = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1892 device = dominfo.get_dev_config_by_uuid('vbd', vbd_ref)
1894 try:
1895 devid = int(device['id'])
1896 device_sxps = dominfo.getDeviceSxprs('vbd')
1897 device_dicts = [dict(device_sxp[1][0:]) for device_sxp in device_sxps]
1898 device_dict = [device_dict
1899 for device_dict in device_dicts
1900 if int(device_dict['virtual-device']) == devid][0]
1902 return xen_api_success(device_dict)
1903 except Exception, exn:
1904 log.exception(exn)
1905 return xen_api_success({})
1907 # attributes (rw)
1908 def VBD_get_VM(self, session, vbd_ref):
1909 return self._VBD_get(vbd_ref, 'VM')
1911 def VBD_get_VDI(self, session, vbd_ref):
1912 return self._VBD_get(vbd_ref, 'VDI')
1914 def VBD_get_device(self, session, vbd_ref):
1915 return self._VBD_get(vbd_ref, 'device')
1917 def VBD_get_bootable(self, session, vbd_ref):
1918 return self._VBD_get(vbd_ref, 'bootable')
1920 def VBD_get_mode(self, session, vbd_ref):
1921 return self._VBD_get(vbd_ref, 'mode')
1923 def VBD_get_type(self, session, vbd_ref):
1924 return self._VBD_get(vbd_ref, 'type')
1926 def VBD_set_bootable(self, session, vbd_ref, bootable):
1927 bootable = bool(bootable)
1928 xd = XendDomain.instance()
1929 vm = xd.get_vm_with_dev_uuid('vbd', vbd_ref)
1930 vm.set_dev_property('vbd', vbd_ref, 'bootable', bootable)
1931 xd.managed_config_save(vm)
1932 return xen_api_success_void()
1934 def VBD_set_mode(self, session, vbd_ref, mode):
1935 if mode == 'RW':
1936 mode = 'w'
1937 else:
1938 mode = 'r'
1939 xd = XendDomain.instance()
1940 vm = xd.get_vm_with_dev_uuid('vbd', vbd_ref)
1941 vm.set_dev_property('vbd', vbd_ref, 'mode', mode)
1942 xd.managed_config_save(vm)
1943 return xen_api_success_void()
1945 def VBD_get_all(self, session):
1946 xendom = XendDomain.instance()
1947 vbds = [d.get_vbds() for d in XendDomain.instance().list('all')]
1948 vbds = reduce(lambda x, y: x + y, vbds)
1949 return xen_api_success(vbds)
1952 # Xen API: Class VBD_metrics
1953 # ----------------------------------------------------------------
1955 VBD_metrics_attr_ro = ['io_read_kbs',
1956 'io_write_kbs',
1957 'last_updated']
1958 VBD_metrics_attr_rw = []
1959 VBD_metrics_methods = []
1961 def VBD_metrics_get_all(self, session):
1962 return self.VBD_get_all(session)
1964 def VBD_metrics_get_record(self, _, ref):
1965 vm = XendDomain.instance().get_vm_with_dev_uuid('vbd', ref)
1966 if not vm:
1967 return xen_api_error(['HANDLE_INVALID', 'VBD_metrics', ref])
1968 return xen_api_success(
1969 { 'io_read_kbs' : vm.get_dev_property('vbd', ref, 'io_read_kbs'),
1970 'io_write_kbs' : vm.get_dev_property('vbd', ref, 'io_write_kbs'),
1971 'last_updated' : now()
1972 })
1974 def VBD_metrics_get_io_read_kbs(self, _, ref):
1975 return self._VBD_get(ref, 'io_read_kbs')
1977 def VBD_metrics_get_io_write_kbs(self, session, ref):
1978 return self._VBD_get(ref, 'io_write_kbs')
1980 def VBD_metrics_get_last_updated(self, _1, _2):
1981 return xen_api_success(now())
1984 # Xen API: Class VIF
1985 # ----------------------------------------------------------------
1987 VIF_attr_ro = ['network',
1988 'VM',
1989 'metrics',
1990 'runtime_properties']
1991 VIF_attr_rw = ['device',
1992 'MAC',
1993 'MTU',
1994 'security_label']
1996 VIF_attr_inst = VIF_attr_rw
1998 VIF_methods = [('destroy', None)]
1999 VIF_funcs = [('create', 'VIF')]
2002 # object methods
2003 def VIF_get_record(self, session, vif_ref):
2004 xendom = XendDomain.instance()
2005 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
2006 if not vm:
2007 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
2008 cfg = vm.get_dev_xenapi_config('vif', vif_ref)
2009 if not cfg:
2010 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
2012 valid_vif_keys = self.VIF_attr_ro + self.VIF_attr_rw + \
2013 self.Base_attr_ro + self.Base_attr_rw
2015 return_cfg = {}
2016 for k in cfg.keys():
2017 if k in valid_vif_keys:
2018 return_cfg[k] = cfg[k]
2020 return_cfg['metrics'] = vif_ref
2022 return xen_api_success(return_cfg)
2024 # class methods
2025 def VIF_create(self, session, vif_struct):
2026 xendom = XendDomain.instance()
2027 if not xendom.is_valid_vm(vif_struct['VM']):
2028 return xen_api_error(['HANDLE_INVALID', 'VM', vif_struct['VM']])
2030 dom = xendom.get_vm_by_uuid(vif_struct['VM'])
2031 try:
2032 vif_ref = dom.create_vif(vif_struct)
2033 xendom.managed_config_save(dom)
2034 return xen_api_success(vif_ref)
2035 except XendError, exn:
2036 return xen_api_error(['INTERNAL_ERROR', str(exn)])
2038 def VIF_destroy(self, session, vif_ref):
2039 xendom = XendDomain.instance()
2040 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
2041 if not vm:
2042 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
2044 vm.destroy_vif(vif_ref)
2045 return xen_api_success_void()
2047 def _VIF_get(self, ref, prop):
2048 return xen_api_success(
2049 XendDomain.instance().get_dev_property_by_uuid('vif', ref, prop))
2051 # getters/setters
2052 def VIF_get_metrics(self, _, vif_ref):
2053 return xen_api_success(vif_ref)
2055 def VIF_get_VM(self, session, vif_ref):
2056 xendom = XendDomain.instance()
2057 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
2058 return xen_api_success(vm.get_uuid())
2060 def VIF_get_MTU(self, session, vif_ref):
2061 return self._VIF_get(vif_ref, 'MTU')
2063 def VIF_get_MAC(self, session, vif_ref):
2064 return self._VIF_get(vif_ref, 'MAC')
2066 def VIF_get_device(self, session, vif_ref):
2067 return self._VIF_get(vif_ref, 'device')
2069 def VIF_get_all(self, session):
2070 xendom = XendDomain.instance()
2071 vifs = [d.get_vifs() for d in XendDomain.instance().list('all')]
2072 vifs = reduce(lambda x, y: x + y, vifs)
2073 return xen_api_success(vifs)
2075 def VIF_get_runtime_properties(self, _, vif_ref):
2076 xendom = XendDomain.instance()
2077 dominfo = xendom.get_vm_with_dev_uuid('vif', vif_ref)
2078 device = dominfo.get_dev_config_by_uuid('vif', vif_ref)
2080 try:
2081 devid = int(device['id'])
2083 device_sxps = dominfo.getDeviceSxprs('vif')
2084 device_dicts = [dict(device_sxp[1][1:])
2085 for device_sxp in device_sxps]
2087 device_dict = [device_dict
2088 for device_dict in device_dicts
2089 if int(device_dict['handle']) == devid][0]
2091 return xen_api_success(device_dict)
2093 except Exception, exn:
2094 log.exception(exn)
2095 return xen_api_success({})
2097 def VIF_get_security_label(self, session, vif_ref):
2098 return self._VIF_get(vif_ref, 'security_label')
2100 def _VIF_set(self, ref, prop, val, old_val):
2101 return XendDomain.instance().set_dev_property_by_uuid(
2102 'vif', ref, prop, val, old_val)
2104 def VIF_set_security_label(self, session, vif_ref, sec_lab, old_lab):
2105 xendom = XendDomain.instance()
2106 dom = xendom.get_vm_with_dev_uuid('vif', vif_ref)
2107 if not dom:
2108 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
2110 if dom._stateGet() == XEN_API_VM_POWER_STATE_RUNNING:
2111 raise SecurityError(-xsconstants.XSERR_RESOURCE_IN_USE)
2113 rc = self._VIF_set(vif_ref, 'security_label', sec_lab, old_lab)
2114 if rc == False:
2115 raise SecurityError(-xsconstants.XSERR_BAD_LABEL)
2116 return xen_api_success(xsconstants.XSERR_SUCCESS)
2119 # Xen API: Class VIF_metrics
2120 # ----------------------------------------------------------------
2122 VIF_metrics_attr_ro = ['io_read_kbs',
2123 'io_write_kbs',
2124 'io_total_read_kbs',
2125 'io_total_write_kbs',
2126 'last_updated']
2127 VIF_metrics_attr_rw = []
2128 VIF_metrics_methods = []
2130 def VIF_metrics_get_all(self, session):
2131 return self.VIF_get_all(session)
2133 def VIF_metrics_get_record(self, _, ref):
2134 vm = XendDomain.instance().get_vm_with_dev_uuid('vif', ref)
2135 if not vm:
2136 return xen_api_error(['HANDLE_INVALID', 'VIF_metrics', ref])
2137 return xen_api_success(
2138 { 'io_read_kbs' : vm.get_dev_property('vif', ref, 'io_read_kbs'),
2139 'io_write_kbs' : vm.get_dev_property('vif', ref, 'io_write_kbs'),
2140 'io_total_read_kbs' : vm.get_dev_property('vif', ref, 'io_total_read_kbs'),
2141 'io_total_write_kbs' : vm.get_dev_property('vif', ref, 'io_total_write_kbs'),
2142 'last_updated' : now()
2143 })
2145 def VIF_metrics_get_io_read_kbs(self, _, ref):
2146 return self._VIF_get(ref, 'io_read_kbs')
2148 def VIF_metrics_get_io_write_kbs(self, session, ref):
2149 return self._VIF_get(ref, 'io_write_kbs')
2151 def VIF_metrics_get_io_total_read_kbs(self, _, ref):
2152 return self._VIF_get(ref, 'io_total_read_kbs')
2154 def VIF_metrics_get_io_total_write_kbs(self, session, ref):
2155 return self._VIF_get(ref, 'io_total_write_kbs')
2157 def VIF_metrics_get_last_updated(self, _1, _2):
2158 return xen_api_success(now())
2161 # Xen API: Class VDI
2162 # ----------------------------------------------------------------
2163 VDI_attr_ro = ['SR',
2164 'VBDs',
2165 'physical_utilisation',
2166 'type']
2167 VDI_attr_rw = ['name_label',
2168 'name_description',
2169 'virtual_size',
2170 'sharable',
2171 'read_only',
2172 'other_config',
2173 'security_label']
2174 VDI_attr_inst = VDI_attr_ro + VDI_attr_rw
2176 VDI_methods = [('destroy', None)]
2177 VDI_funcs = [('create', 'VDI'),
2178 ('get_by_name_label', 'Set(VDI)')]
2180 def _get_VDI(self, ref):
2181 return XendNode.instance().get_vdi_by_uuid(ref)
2183 def VDI_get_VBDs(self, session, vdi_ref):
2184 vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
2185 return xen_api_success(vdi.getVBDs())
2187 def VDI_get_physical_utilisation(self, session, vdi_ref):
2188 return xen_api_success(self._get_VDI(vdi_ref).
2189 get_physical_utilisation())
2191 def VDI_get_type(self, session, vdi_ref):
2192 return xen_api_success(self._get_VDI(vdi_ref).type)
2194 def VDI_get_name_label(self, session, vdi_ref):
2195 return xen_api_success(self._get_VDI(vdi_ref).name_label)
2197 def VDI_get_name_description(self, session, vdi_ref):
2198 return xen_api_success(self._get_VDI(vdi_ref).name_description)
2200 def VDI_get_SR(self, session, vdi_ref):
2201 return xen_api_success(self._get_VDI(vdi_ref).sr_uuid)
2203 def VDI_get_virtual_size(self, session, vdi_ref):
2204 return xen_api_success(self._get_VDI(vdi_ref).virtual_size)
2206 def VDI_get_sharable(self, session, vdi_ref):
2207 return xen_api_success(self._get_VDI(vdi_ref).sharable)
2209 def VDI_get_read_only(self, session, vdi_ref):
2210 return xen_api_success(self._get_VDI(vdi_ref).read_only)
2212 def VDI_set_name_label(self, session, vdi_ref, value):
2213 self._get_VDI(vdi_ref).name_label = value
2214 return xen_api_success_void()
2216 def VDI_set_name_description(self, session, vdi_ref, value):
2217 self._get_VDI(vdi_ref).name_description = value
2218 return xen_api_success_void()
2220 def VDI_set_virtual_size(self, session, vdi_ref, value):
2221 return xen_api_error(XEND_ERROR_UNSUPPORTED)
2223 def VDI_set_sharable(self, session, vdi_ref, value):
2224 self._get_VDI(vdi_ref).sharable = bool(value)
2225 return xen_api_success_void()
2227 def VDI_set_read_only(self, session, vdi_ref, value):
2228 self._get_VDI(vdi_ref).read_only = bool(value)
2229 return xen_api_success_void()
2231 def VDI_get_other_config(self, session, vdi_ref):
2232 return xen_api_success(
2233 self._get_VDI(vdi_ref).other_config)
2235 def VDI_set_other_config(self, session, vdi_ref, other_config):
2236 self._get_VDI(vdi_ref).other_config = other_config
2237 return xen_api_success_void()
2239 # Object Methods
2241 def VDI_destroy(self, session, vdi_ref):
2242 sr = XendNode.instance().get_sr_containing_vdi(vdi_ref)
2243 sr.destroy_vdi(vdi_ref)
2244 return xen_api_success_void()
2246 def VDI_get_record(self, session, vdi_ref):
2247 image = XendNode.instance().get_vdi_by_uuid(vdi_ref)
2248 return xen_api_success({
2249 'uuid': vdi_ref,
2250 'name_label': image.name_label,
2251 'name_description': image.name_description,
2252 'SR': image.sr_uuid,
2253 'VBDs': image.getVBDs(),
2254 'virtual_size': image.virtual_size,
2255 'physical_utilisation': image.physical_utilisation,
2256 'type': image.type,
2257 'sharable': image.sharable,
2258 'read_only': image.read_only,
2259 'other_config': image.other_config
2260 })
2262 # Class Functions
2263 def VDI_create(self, session, vdi_struct):
2264 sr_ref = vdi_struct.get('SR')
2265 xennode = XendNode.instance()
2266 if not xennode.is_valid_sr(sr_ref):
2267 return xen_api_error(['HANDLE_INVALID', 'SR', sr_ref])
2269 vdi_uuid = xennode.srs[sr_ref].create_vdi(vdi_struct)
2270 return xen_api_success(vdi_uuid)
2272 def VDI_get_all(self, session):
2273 xennode = XendNode.instance()
2274 vdis = [sr.get_vdis() for sr in xennode.srs.values()]
2275 return xen_api_success(reduce(lambda x, y: x + y, vdis))
2277 def VDI_get_by_name_label(self, session, name):
2278 xennode = XendNode.instance()
2279 return xen_api_success(xennode.get_vdi_by_name_label(name))
2281 def VDI_set_security_label(self, session, vdi_ref, sec_lab, old_lab):
2282 vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
2283 rc = vdi.set_security_label(sec_lab, old_lab)
2284 if rc < 0:
2285 return xen_api_error(['SECURITY_ERROR', rc,
2286 xsconstants.xserr2string(-rc)])
2287 return xen_api_success(rc)
2289 def VDI_get_security_label(self, session, vdi_ref):
2290 vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
2291 return xen_api_success(vdi.get_security_label())
2293 # Xen API: Class VTPM
2294 # ----------------------------------------------------------------
2296 VTPM_attr_rw = ['other_config']
2297 VTPM_attr_ro = ['VM',
2298 'backend',
2299 'runtime_properties' ]
2301 VTPM_attr_inst = VTPM_attr_rw
2303 VTPM_methods = [('destroy', None)]
2304 VTPM_funcs = [('create', 'VTPM')]
2306 def VTPM_get_other_config(self, session, vtpm_ref):
2307 xendom = XendDomain.instance()
2308 return xen_api_success(xendom.get_dev_property_by_uuid('vtpm',
2309 vtpm_ref,
2310 'other_config'))
2312 def VTPM_set_other_config(self, session, vtpm_ref, other_config):
2313 xendom = XendDomain.instance()
2314 xendom.set_dev_property_by_uuid('vtpm',
2315 vtpm_ref,
2316 'other_config',
2317 other_config)
2318 return xen_api_success_void()
2320 # object methods
2321 def VTPM_get_record(self, session, vtpm_ref):
2322 xendom = XendDomain.instance()
2323 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
2324 if not vm:
2325 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
2326 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
2327 if not cfg:
2328 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
2329 valid_vtpm_keys = self.VTPM_attr_ro + self.VTPM_attr_rw + \
2330 self.Base_attr_ro + self.Base_attr_rw
2331 return_cfg = {}
2332 for k in cfg.keys():
2333 if k in valid_vtpm_keys:
2334 return_cfg[k] = cfg[k]
2336 return xen_api_success(return_cfg)
2338 # Class Functions
2339 def VTPM_get_backend(self, session, vtpm_ref):
2340 xendom = XendDomain.instance()
2341 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
2342 if not vm:
2343 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
2344 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
2345 if not cfg:
2346 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
2347 if not cfg.has_key('backend'):
2348 return xen_api_error(['INTERNAL_ERROR', 'VTPM backend not set'])
2349 return xen_api_success(cfg['backend'])
2351 def VTPM_get_VM(self, session, vtpm_ref):
2352 xendom = XendDomain.instance()
2353 return xen_api_success(xendom.get_dev_property_by_uuid('vtpm',
2354 vtpm_ref, 'VM'))
2356 def VTPM_destroy(self, session, vtpm_ref):
2357 xendom = XendDomain.instance()
2358 dom = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
2359 if dom:
2360 if dom.state != XEN_API_VM_POWER_STATE_HALTED:
2361 vm_ref = dom.get_dev_property('vtpm', vtpm_ref, 'VM')
2362 return xen_api_error(['VM_BAD_POWER_STATE', vm_ref,
2363 XendDomain.POWER_STATE_NAMES[XEN_API_VM_POWER_STATE_HALTED],
2364 XendDomain.POWER_STATE_NAMES[dom.state]])
2365 from xen.xend.server import tpmif
2366 tpmif.destroy_vtpmstate(dom.getName())
2367 return xen_api_success_void()
2368 else:
2369 return xen_api_error(['HANDLE_INVALID', 'VM', vtpm_struct['VM']])
2371 # class methods
2372 def VTPM_create(self, session, vtpm_struct):
2373 xendom = XendDomain.instance()
2374 if xendom.is_valid_vm(vtpm_struct['VM']):
2375 dom = xendom.get_vm_by_uuid(vtpm_struct['VM'])
2376 try:
2377 vtpm_ref = dom.create_vtpm(vtpm_struct)
2378 xendom.managed_config_save(dom)
2379 return xen_api_success(vtpm_ref)
2380 except XendError, exn:
2381 return xen_api_error(['INTERNAL_ERROR', str(exn)])
2382 else:
2383 return xen_api_error(['HANDLE_INVALID', 'VM', vtpm_struct['VM']])
2385 def VTPM_get_all(self, session):
2386 xendom = XendDomain.instance()
2387 vtpms = [d.get_vtpms() for d in XendDomain.instance().list('all')]
2388 vtpms = reduce(lambda x, y: x + y, vtpms)
2389 return xen_api_success(vtpms)
2391 def VTPM_get_runtime_properties(self, _, vtpm_ref):
2392 xendom = XendDomain.instance()
2393 dominfo = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
2394 device = dominfo.get_dev_config_by_uuid('vtpm', vtpm_ref)
2396 try:
2397 device_sxps = dominfo.getDeviceSxprs('vtpm')
2398 device_dict = dict(device_sxps[0][1])
2399 return xen_api_success(device_dict)
2400 except:
2401 return xen_api_success({})
2403 # Xen API: Class console
2404 # ----------------------------------------------------------------
2407 console_attr_ro = ['location', 'protocol', 'VM']
2408 console_attr_rw = ['other_config']
2409 console_funcs = [('create', 'console')]
2411 def console_get_all(self, session):
2412 xendom = XendDomain.instance()
2413 cons = [d.get_consoles() for d in XendDomain.instance().list('all')]
2414 cons = reduce(lambda x, y: x + y, cons)
2415 return xen_api_success(cons)
2417 def console_get_location(self, session, console_ref):
2418 xendom = XendDomain.instance()
2419 return xen_api_success(xendom.get_dev_property_by_uuid('console',
2420 console_ref,
2421 'location'))
2423 def console_get_protocol(self, session, console_ref):
2424 xendom = XendDomain.instance()
2425 return xen_api_success(xendom.get_dev_property_by_uuid('console',
2426 console_ref,
2427 'protocol'))
2429 def console_get_VM(self, session, console_ref):
2430 xendom = XendDomain.instance()
2431 vm = xendom.get_vm_with_dev_uuid('console', console_ref)
2432 return xen_api_success(vm.get_uuid())
2434 def console_get_other_config(self, session, console_ref):
2435 xendom = XendDomain.instance()
2436 return xen_api_success(xendom.get_dev_property_by_uuid('console',
2437 console_ref,
2438 'other_config'))
2440 # object methods
2441 def console_get_record(self, session, console_ref):
2442 xendom = XendDomain.instance()
2443 vm = xendom.get_vm_with_dev_uuid('console', console_ref)
2444 if not vm:
2445 return xen_api_error(['HANDLE_INVALID', 'console', console_ref])
2446 cfg = vm.get_dev_xenapi_config('console', console_ref)
2447 if not cfg:
2448 return xen_api_error(['HANDLE_INVALID', 'console', console_ref])
2450 valid_console_keys = self.console_attr_ro + self.console_attr_rw + \
2451 self.Base_attr_ro + self.Base_attr_rw
2453 return_cfg = {}
2454 for k in cfg.keys():
2455 if k in valid_console_keys:
2456 return_cfg[k] = cfg[k]
2458 return xen_api_success(return_cfg)
2460 def console_create(self, session, console_struct):
2461 xendom = XendDomain.instance()
2462 if not xendom.is_valid_vm(console_struct['VM']):
2463 return xen_api_error(['HANDLE_INVALID', 'VM',
2464 console_struct['VM']])
2466 dom = xendom.get_vm_by_uuid(console_struct['VM'])
2467 try:
2468 if 'protocol' not in console_struct:
2469 return xen_api_error(['CONSOLE_PROTOCOL_INVALID',
2470 'No protocol specified'])
2472 console_ref = dom.create_console(console_struct)
2473 xendom.managed_config_save(dom)
2474 return xen_api_success(console_ref)
2475 except XendError, exn:
2476 return xen_api_error(['INTERNAL_ERROR', str(exn)])
2478 def console_set_other_config(self, session, console_ref, other_config):
2479 xd = XendDomain.instance()
2480 vm = xd.get_vm_with_dev_uuid('console', console_ref)
2481 vm.set_console_other_config(console_ref, other_config)
2482 xd.managed_config_save(vm)
2483 return xen_api_success_void()
2485 # Xen API: Class SR
2486 # ----------------------------------------------------------------
2487 SR_attr_ro = ['VDIs',
2488 'PBDs',
2489 'virtual_allocation',
2490 'physical_utilisation',
2491 'physical_size',
2492 'type',
2493 'content_type']
2495 SR_attr_rw = ['name_label',
2496 'name_description']
2498 SR_attr_inst = ['physical_size',
2499 'type',
2500 'name_label',
2501 'name_description']
2503 SR_methods = []
2504 SR_funcs = [('get_by_name_label', 'Set(SR)'),
2505 ('get_by_uuid', 'SR')]
2507 # Class Functions
2508 def SR_get_all(self, session):
2509 return xen_api_success(XendNode.instance().get_all_sr_uuid())
2511 def SR_get_by_name_label(self, session, label):
2512 return xen_api_success(XendNode.instance().get_sr_by_name(label))
2514 def SR_get_supported_types(self, _):
2515 return xen_api_success(['local', 'qcow_file'])
2517 # Class Methods
2519 def SR_get_record(self, session, sr_ref):
2520 sr = XendNode.instance().get_sr(sr_ref)
2521 if sr:
2522 return xen_api_success(sr.get_record())
2523 return xen_api_error(['HANDLE_INVALID', 'SR', sr_ref])
2525 # Attribute acceess
2527 def _get_SR_func(self, sr_ref, func):
2528 return xen_api_success(getattr(XendNode.instance().get_sr(sr_ref),
2529 func)())
2531 def _get_SR_attr(self, sr_ref, attr):
2532 return xen_api_success(getattr(XendNode.instance().get_sr(sr_ref),
2533 attr))
2535 def SR_get_VDIs(self, _, ref):
2536 return self._get_SR_func(ref, 'list_images')
2538 def SR_get_PBDs(self, _, ref):
2539 return xen_api_success(XendPBD.get_by_SR(ref))
2541 def SR_get_virtual_allocation(self, _, ref):
2542 return self._get_SR_func(ref, 'virtual_allocation')
2544 def SR_get_physical_utilisation(self, _, ref):
2545 return self._get_SR_func(ref, 'physical_utilisation')
2547 def SR_get_physical_size(self, _, ref):
2548 return self._get_SR_attr(ref, 'physical_size')
2550 def SR_get_type(self, _, ref):
2551 return self._get_SR_attr(ref, 'type')
2553 def SR_get_content_type(self, _, ref):
2554 return self._get_SR_attr(ref, 'content_type')
2556 def SR_get_name_label(self, _, ref):
2557 return self._get_SR_attr(ref, 'name_label')
2559 def SR_get_name_description(self, _, ref):
2560 return self._get_SR_attr(ref, 'name_description')
2562 def SR_set_name_label(self, session, sr_ref, value):
2563 sr = XendNode.instance.get_sr(sr_ref)
2564 if sr:
2565 sr.name_label = value
2566 XendNode.instance().save()
2567 return xen_api_success_void()
2569 def SR_set_name_description(self, session, sr_ref, value):
2570 sr = XendNode.instance.get_sr(sr_ref)
2571 if sr:
2572 sr.name_description = value
2573 XendNode.instance().save()
2574 return xen_api_success_void()
2577 # Xen API: Class event
2578 # ----------------------------------------------------------------
2580 event_attr_ro = []
2581 event_attr_rw = []
2582 event_funcs = [('register', None),
2583 ('unregister', None),
2584 ('next', None)]
2586 def event_register(self, session, reg_classes):
2587 event_register(session, reg_classes)
2588 return xen_api_success_void()
2590 def event_unregister(self, session, unreg_classes):
2591 event_unregister(session, reg_classes)
2592 return xen_api_success_void()
2594 def event_next(self, session):
2595 return event_next(session)
2597 # Xen API: Class debug
2598 # ----------------------------------------------------------------
2600 debug_methods = [('destroy', None),
2601 ('get_record', 'debug')]
2602 debug_funcs = [('wait', None),
2603 ('return_failure', None)]
2605 def debug_wait(self, session, wait_secs):
2606 import time
2607 prog_units = 100/float(wait_secs)
2608 for i in range(int(wait_secs)):
2609 XendTask.log_progress(prog_units * i, prog_units * (i + 1),
2610 time.sleep, 1)
2611 return xen_api_success_void()
2614 def debug_return_failure(self, session):
2615 return xen_api_error(['DEBUG_FAIL', session])
2617 def debug_create(self, session):
2618 debug_uuid = uuid.createString()
2619 self._debug[debug_uuid] = None
2620 return xen_api_success(debug_uuid)
2622 def debug_destroy(self, session, debug_ref):
2623 del self._debug[debug_ref]
2624 return xen_api_success_void()
2626 def debug_get_record(self, session, debug_ref):
2627 return xen_api_success({'uuid': debug_ref})
2630 class XendAPIAsyncProxy:
2631 """ A redirector for Async.Class.function calls to XendAPI
2632 but wraps the call for use with the XendTaskManager.
2634 @ivar xenapi: Xen API instance
2635 @ivar method_map: Mapping from XMLRPC method name to callable objects.
2636 """
2638 method_prefix = 'Async.'
2640 def __init__(self, xenapi):
2641 """Initialises the Async Proxy by making a map of all
2642 implemented Xen API methods for use with XendTaskManager.
2644 @param xenapi: XendAPI instance
2645 """
2646 self.xenapi = xenapi
2647 self.method_map = {}
2648 for method_name in dir(self.xenapi):
2649 method = getattr(self.xenapi, method_name)
2650 if method_name[0] != '_' and hasattr(method, 'async') \
2651 and method.async == True:
2652 self.method_map[method.api] = method
2654 def _dispatch(self, method, args):
2655 """Overridden method so that SimpleXMLRPCServer will
2656 resolve methods through this method rather than through
2657 inspection.
2659 @param method: marshalled method name from XMLRPC.
2660 @param args: marshalled arguments from XMLRPC.
2661 """
2663 # Only deal with method names that start with "Async."
2664 if not method.startswith(self.method_prefix):
2665 return xen_api_error(['MESSAGE_METHOD_UNKNOWN', method])
2667 # Lookup synchronous version of the method
2668 synchronous_method_name = method[len(self.method_prefix):]
2669 if synchronous_method_name not in self.method_map:
2670 return xen_api_error(['MESSAGE_METHOD_UNKNOWN', method])
2672 method = self.method_map[synchronous_method_name]
2674 # Check that we've got enough arguments before issuing a task ID.
2675 needed = argcounts[method.api]
2676 if len(args) != needed:
2677 return xen_api_error(['MESSAGE_PARAMETER_COUNT_MISMATCH',
2678 self.method_prefix + method.api, needed,
2679 len(args)])
2681 # Validate the session before proceeding
2682 session = args[0]
2683 if not auth_manager().is_session_valid(session):
2684 return xen_api_error(['SESSION_INVALID', session])
2686 # create and execute the task, and return task_uuid
2687 return_type = getattr(method, 'return_type', None)
2688 task_uuid = XendTaskManager.create_task(method, args,
2689 synchronous_method_name,
2690 return_type,
2691 synchronous_method_name,
2692 session)
2693 return xen_api_success(task_uuid)