ia64/xen-unstable

view tools/python/xen/xend/XendAPI.py @ 17780:420db89188ca

xend: implement VM_hard_reboot of XenAPI.

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