debuggers.hg

view tools/python/xen/xend/XendAPI.py @ 0:7d21f7218375

Exact replica of unstable on 051908 + README-this
author Mukesh Rathor
date Mon May 19 15:34:57 2008 -0700 (2008-05-19)
parents
children 5c0bf00e371d
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 xen_api_error(XEND_ERROR_UNSUPPORTED)
1712 def VM_hard_shutdown(self, session, vm_ref):
1713 return XendTask.log_progress(0, 100, do_vm_func,
1714 "domain_destroy", vm_ref)
1715 def VM_pause(self, session, vm_ref):
1716 return XendTask.log_progress(0, 100, do_vm_func,
1717 "domain_pause", vm_ref)
1719 def VM_resume(self, session, vm_ref, start_paused):
1720 return XendTask.log_progress(0, 100, do_vm_func,
1721 "domain_resume", vm_ref,
1722 start_paused = start_paused)
1724 def VM_start(self, session, vm_ref, start_paused):
1725 try:
1726 return XendTask.log_progress(0, 100, do_vm_func,
1727 "domain_start", vm_ref,
1728 start_paused = start_paused)
1729 except HVMRequired, exn:
1730 return xen_api_error(['VM_HVM_REQUIRED', vm_ref])
1732 def VM_suspend(self, session, vm_ref):
1733 return XendTask.log_progress(0, 100, do_vm_func,
1734 "domain_suspend", vm_ref)
1736 def VM_unpause(self, session, vm_ref):
1737 return XendTask.log_progress(0, 100, do_vm_func,
1738 "domain_unpause", vm_ref)
1740 def VM_send_sysrq(self, _, vm_ref, req):
1741 xeninfo = XendDomain.instance().get_vm_by_uuid(vm_ref)
1742 if xeninfo.state == XEN_API_VM_POWER_STATE_RUNNING \
1743 or xeninfo.state == XEN_API_VM_POWER_STATE_PAUSED:
1744 xeninfo.send_sysrq(req)
1745 return xen_api_success_void()
1746 else:
1747 return xen_api_error(
1748 ['VM_BAD_POWER_STATE', vm_ref,
1749 XendDomain.POWER_STATE_NAMES[XEN_API_VM_POWER_STATE_RUNNING],
1750 XendDomain.POWER_STATE_NAMES[xeninfo.state]])
1752 def VM_send_trigger(self, _, vm_ref, trigger, vcpu):
1753 xendom = XendDomain.instance()
1754 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1755 xendom.domain_send_trigger(xeninfo.getDomid(), trigger, vcpu)
1756 return xen_api_success_void()
1758 def VM_migrate(self, _, vm_ref, destination_url, live, other_config):
1759 xendom = XendDomain.instance()
1760 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1762 resource = other_config.get("resource", 0)
1763 port = other_config.get("port", 0)
1764 node = other_config.get("node", 0)
1766 xendom.domain_migrate(xeninfo.getDomid(), destination_url,
1767 bool(live), resource, port, node)
1768 return xen_api_success_void()
1770 def VM_save(self, _, vm_ref, dest, checkpoint):
1771 xendom = XendDomain.instance()
1772 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1773 xendom.domain_save(xeninfo.getDomid(), dest, checkpoint)
1774 return xen_api_success_void()
1776 def VM_restore(self, _, src, paused):
1777 xendom = XendDomain.instance()
1778 xendom.domain_restore(src, bool(paused))
1779 return xen_api_success_void()
1782 # Xen API: Class VBD
1783 # ----------------------------------------------------------------
1785 VBD_attr_ro = ['VM',
1786 'VDI',
1787 'metrics',
1788 'runtime_properties']
1789 VBD_attr_rw = ['device',
1790 'bootable',
1791 'mode',
1792 'type']
1794 VBD_attr_inst = VBD_attr_rw
1796 VBD_methods = [('media_change', None), ('destroy', None)]
1797 VBD_funcs = [('create', 'VBD')]
1799 # object methods
1800 def VBD_get_record(self, session, vbd_ref):
1801 xendom = XendDomain.instance()
1802 vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1803 if not vm:
1804 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1805 cfg = vm.get_dev_xenapi_config('vbd', vbd_ref)
1806 if not cfg:
1807 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1809 valid_vbd_keys = self.VBD_attr_ro + self.VBD_attr_rw + \
1810 self.Base_attr_ro + self.Base_attr_rw
1812 return_cfg = {}
1813 for k in cfg.keys():
1814 if k in valid_vbd_keys:
1815 return_cfg[k] = cfg[k]
1817 return_cfg['metrics'] = vbd_ref
1818 return_cfg['runtime_properties'] = {} #todo
1820 return xen_api_success(return_cfg)
1822 def VBD_media_change(self, session, vbd_ref, vdi_ref):
1823 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1825 # class methods
1826 def VBD_create(self, session, vbd_struct):
1827 xendom = XendDomain.instance()
1828 xennode = XendNode.instance()
1830 if not xendom.is_valid_vm(vbd_struct['VM']):
1831 return xen_api_error(['HANDLE_INVALID', 'VM', vbd_struct['VM']])
1833 dom = xendom.get_vm_by_uuid(vbd_struct['VM'])
1834 vdi = xennode.get_vdi_by_uuid(vbd_struct['VDI'])
1835 if not vdi:
1836 return xen_api_error(['HANDLE_INVALID', 'VDI', vdi_ref])
1838 # new VBD via VDI/SR
1839 vdi_image = vdi.get_location()
1841 try:
1842 vbd_ref = XendTask.log_progress(0, 100,
1843 dom.create_vbd,
1844 vbd_struct, vdi_image)
1845 except XendError, e:
1846 log.exception("Error in VBD_create")
1847 return xen_api_error(['INTERNAL_ERROR', str(e)])
1849 vdi.addVBD(vbd_ref)
1851 xendom.managed_config_save(dom)
1852 return xen_api_success(vbd_ref)
1855 def VBD_destroy(self, session, vbd_ref):
1856 xendom = XendDomain.instance()
1857 vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1858 if not vm:
1859 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1861 vdi_ref = XendDomain.instance()\
1862 .get_dev_property_by_uuid('vbd', vbd_ref, "VDI")
1863 vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
1865 XendTask.log_progress(0, 100, vm.destroy_vbd, vbd_ref)
1867 vdi.removeVBD(vbd_ref)
1869 return xen_api_success_void()
1871 def _VBD_get(self, vbd_ref, prop):
1872 return xen_api_success(
1873 XendDomain.instance().get_dev_property_by_uuid(
1874 'vbd', vbd_ref, prop))
1876 # attributes (ro)
1877 def VBD_get_metrics(self, _, vbd_ref):
1878 return xen_api_success(vbd_ref)
1880 def VBD_get_runtime_properties(self, _, vbd_ref):
1881 xendom = XendDomain.instance()
1882 dominfo = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1883 device = dominfo.get_dev_config_by_uuid('vbd', vbd_ref)
1885 try:
1886 devid = int(device['id'])
1887 device_sxps = dominfo.getDeviceSxprs('vbd')
1888 device_dicts = [dict(device_sxp[1][0:]) for device_sxp in device_sxps]
1889 device_dict = [device_dict
1890 for device_dict in device_dicts
1891 if int(device_dict['virtual-device']) == devid][0]
1893 return xen_api_success(device_dict)
1894 except Exception, exn:
1895 log.exception(exn)
1896 return xen_api_success({})
1898 # attributes (rw)
1899 def VBD_get_VM(self, session, vbd_ref):
1900 return self._VBD_get(vbd_ref, 'VM')
1902 def VBD_get_VDI(self, session, vbd_ref):
1903 return self._VBD_get(vbd_ref, 'VDI')
1905 def VBD_get_device(self, session, vbd_ref):
1906 return self._VBD_get(vbd_ref, 'device')
1908 def VBD_get_bootable(self, session, vbd_ref):
1909 return self._VBD_get(vbd_ref, 'bootable')
1911 def VBD_get_mode(self, session, vbd_ref):
1912 return self._VBD_get(vbd_ref, 'mode')
1914 def VBD_get_type(self, session, vbd_ref):
1915 return self._VBD_get(vbd_ref, 'type')
1917 def VBD_set_bootable(self, session, vbd_ref, bootable):
1918 bootable = bool(bootable)
1919 xd = XendDomain.instance()
1920 vm = xd.get_vm_with_dev_uuid('vbd', vbd_ref)
1921 vm.set_dev_property('vbd', vbd_ref, 'bootable', bootable)
1922 xd.managed_config_save(vm)
1923 return xen_api_success_void()
1925 def VBD_set_mode(self, session, vbd_ref, mode):
1926 if mode == 'RW':
1927 mode = 'w'
1928 else:
1929 mode = 'r'
1930 xd = XendDomain.instance()
1931 vm = xd.get_vm_with_dev_uuid('vbd', vbd_ref)
1932 vm.set_dev_property('vbd', vbd_ref, 'mode', mode)
1933 xd.managed_config_save(vm)
1934 return xen_api_success_void()
1936 def VBD_get_all(self, session):
1937 xendom = XendDomain.instance()
1938 vbds = [d.get_vbds() for d in XendDomain.instance().list('all')]
1939 vbds = reduce(lambda x, y: x + y, vbds)
1940 return xen_api_success(vbds)
1943 # Xen API: Class VBD_metrics
1944 # ----------------------------------------------------------------
1946 VBD_metrics_attr_ro = ['io_read_kbs',
1947 'io_write_kbs',
1948 'last_updated']
1949 VBD_metrics_attr_rw = []
1950 VBD_metrics_methods = []
1952 def VBD_metrics_get_all(self, session):
1953 return self.VBD_get_all(session)
1955 def VBD_metrics_get_record(self, _, ref):
1956 vm = XendDomain.instance().get_vm_with_dev_uuid('vbd', ref)
1957 if not vm:
1958 return xen_api_error(['HANDLE_INVALID', 'VBD_metrics', ref])
1959 return xen_api_success(
1960 { 'io_read_kbs' : vm.get_dev_property('vbd', ref, 'io_read_kbs'),
1961 'io_write_kbs' : vm.get_dev_property('vbd', ref, 'io_write_kbs'),
1962 'last_updated' : now()
1963 })
1965 def VBD_metrics_get_io_read_kbs(self, _, ref):
1966 return self._VBD_get(ref, 'io_read_kbs')
1968 def VBD_metrics_get_io_write_kbs(self, session, ref):
1969 return self._VBD_get(ref, 'io_write_kbs')
1971 def VBD_metrics_get_last_updated(self, _1, _2):
1972 return xen_api_success(now())
1975 # Xen API: Class VIF
1976 # ----------------------------------------------------------------
1978 VIF_attr_ro = ['network',
1979 'VM',
1980 'metrics',
1981 'runtime_properties']
1982 VIF_attr_rw = ['device',
1983 'MAC',
1984 'MTU',
1985 'security_label']
1987 VIF_attr_inst = VIF_attr_rw
1989 VIF_methods = [('destroy', None)]
1990 VIF_funcs = [('create', 'VIF')]
1993 # object methods
1994 def VIF_get_record(self, session, vif_ref):
1995 xendom = XendDomain.instance()
1996 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
1997 if not vm:
1998 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
1999 cfg = vm.get_dev_xenapi_config('vif', vif_ref)
2000 if not cfg:
2001 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
2003 valid_vif_keys = self.VIF_attr_ro + self.VIF_attr_rw + \
2004 self.Base_attr_ro + self.Base_attr_rw
2006 return_cfg = {}
2007 for k in cfg.keys():
2008 if k in valid_vif_keys:
2009 return_cfg[k] = cfg[k]
2011 return_cfg['metrics'] = vif_ref
2013 return xen_api_success(return_cfg)
2015 # class methods
2016 def VIF_create(self, session, vif_struct):
2017 xendom = XendDomain.instance()
2018 if not xendom.is_valid_vm(vif_struct['VM']):
2019 return xen_api_error(['HANDLE_INVALID', 'VM', vif_struct['VM']])
2021 dom = xendom.get_vm_by_uuid(vif_struct['VM'])
2022 try:
2023 vif_ref = dom.create_vif(vif_struct)
2024 xendom.managed_config_save(dom)
2025 return xen_api_success(vif_ref)
2026 except XendError, exn:
2027 return xen_api_error(['INTERNAL_ERROR', str(exn)])
2029 def VIF_destroy(self, session, vif_ref):
2030 xendom = XendDomain.instance()
2031 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
2032 if not vm:
2033 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
2035 vm.destroy_vif(vif_ref)
2036 return xen_api_success_void()
2038 def _VIF_get(self, ref, prop):
2039 return xen_api_success(
2040 XendDomain.instance().get_dev_property_by_uuid('vif', ref, prop))
2042 # getters/setters
2043 def VIF_get_metrics(self, _, vif_ref):
2044 return xen_api_success(vif_ref)
2046 def VIF_get_VM(self, session, vif_ref):
2047 xendom = XendDomain.instance()
2048 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
2049 return xen_api_success(vm.get_uuid())
2051 def VIF_get_MTU(self, session, vif_ref):
2052 return self._VIF_get(vif_ref, 'MTU')
2054 def VIF_get_MAC(self, session, vif_ref):
2055 return self._VIF_get(vif_ref, 'MAC')
2057 def VIF_get_device(self, session, vif_ref):
2058 return self._VIF_get(vif_ref, 'device')
2060 def VIF_get_all(self, session):
2061 xendom = XendDomain.instance()
2062 vifs = [d.get_vifs() for d in XendDomain.instance().list('all')]
2063 vifs = reduce(lambda x, y: x + y, vifs)
2064 return xen_api_success(vifs)
2066 def VIF_get_runtime_properties(self, _, vif_ref):
2067 xendom = XendDomain.instance()
2068 dominfo = xendom.get_vm_with_dev_uuid('vif', vif_ref)
2069 device = dominfo.get_dev_config_by_uuid('vif', vif_ref)
2071 try:
2072 devid = int(device['id'])
2074 device_sxps = dominfo.getDeviceSxprs('vif')
2075 device_dicts = [dict(device_sxp[1][1:])
2076 for device_sxp in device_sxps]
2078 device_dict = [device_dict
2079 for device_dict in device_dicts
2080 if int(device_dict['handle']) == devid][0]
2082 return xen_api_success(device_dict)
2084 except Exception, exn:
2085 log.exception(exn)
2086 return xen_api_success({})
2088 def VIF_get_security_label(self, session, vif_ref):
2089 return self._VIF_get(vif_ref, 'security_label')
2091 def _VIF_set(self, ref, prop, val, old_val):
2092 return XendDomain.instance().set_dev_property_by_uuid(
2093 'vif', ref, prop, val, old_val)
2095 def VIF_set_security_label(self, session, vif_ref, sec_lab, old_lab):
2096 xendom = XendDomain.instance()
2097 dom = xendom.get_vm_with_dev_uuid('vif', vif_ref)
2098 if not dom:
2099 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
2101 if dom._stateGet() == XEN_API_VM_POWER_STATE_RUNNING:
2102 raise SecurityError(-xsconstants.XSERR_RESOURCE_IN_USE)
2104 rc = self._VIF_set(vif_ref, 'security_label', sec_lab, old_lab)
2105 if rc == False:
2106 raise SecurityError(-xsconstants.XSERR_BAD_LABEL)
2107 return xen_api_success(xsconstants.XSERR_SUCCESS)
2110 # Xen API: Class VIF_metrics
2111 # ----------------------------------------------------------------
2113 VIF_metrics_attr_ro = ['io_read_kbs',
2114 'io_write_kbs',
2115 'io_total_read_kbs',
2116 'io_total_write_kbs',
2117 'last_updated']
2118 VIF_metrics_attr_rw = []
2119 VIF_metrics_methods = []
2121 def VIF_metrics_get_all(self, session):
2122 return self.VIF_get_all(session)
2124 def VIF_metrics_get_record(self, _, ref):
2125 vm = XendDomain.instance().get_vm_with_dev_uuid('vif', ref)
2126 if not vm:
2127 return xen_api_error(['HANDLE_INVALID', 'VIF_metrics', ref])
2128 return xen_api_success(
2129 { 'io_read_kbs' : vm.get_dev_property('vif', ref, 'io_read_kbs'),
2130 'io_write_kbs' : vm.get_dev_property('vif', ref, 'io_write_kbs'),
2131 'io_total_read_kbs' : vm.get_dev_property('vif', ref, 'io_total_read_kbs'),
2132 'io_total_write_kbs' : vm.get_dev_property('vif', ref, 'io_total_write_kbs'),
2133 'last_updated' : now()
2134 })
2136 def VIF_metrics_get_io_read_kbs(self, _, ref):
2137 return self._VIF_get(ref, 'io_read_kbs')
2139 def VIF_metrics_get_io_write_kbs(self, session, ref):
2140 return self._VIF_get(ref, 'io_write_kbs')
2142 def VIF_metrics_get_io_total_read_kbs(self, _, ref):
2143 return self._VIF_get(ref, 'io_total_read_kbs')
2145 def VIF_metrics_get_io_total_write_kbs(self, session, ref):
2146 return self._VIF_get(ref, 'io_total_write_kbs')
2148 def VIF_metrics_get_last_updated(self, _1, _2):
2149 return xen_api_success(now())
2152 # Xen API: Class VDI
2153 # ----------------------------------------------------------------
2154 VDI_attr_ro = ['SR',
2155 'VBDs',
2156 'physical_utilisation',
2157 'type']
2158 VDI_attr_rw = ['name_label',
2159 'name_description',
2160 'virtual_size',
2161 'sharable',
2162 'read_only',
2163 'other_config',
2164 'security_label']
2165 VDI_attr_inst = VDI_attr_ro + VDI_attr_rw
2167 VDI_methods = [('destroy', None)]
2168 VDI_funcs = [('create', 'VDI'),
2169 ('get_by_name_label', 'Set(VDI)')]
2171 def _get_VDI(self, ref):
2172 return XendNode.instance().get_vdi_by_uuid(ref)
2174 def VDI_get_VBDs(self, session, vdi_ref):
2175 vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
2176 return xen_api_success(vdi.getVBDs())
2178 def VDI_get_physical_utilisation(self, session, vdi_ref):
2179 return xen_api_success(self._get_VDI(vdi_ref).
2180 get_physical_utilisation())
2182 def VDI_get_type(self, session, vdi_ref):
2183 return xen_api_success(self._get_VDI(vdi_ref).type)
2185 def VDI_get_name_label(self, session, vdi_ref):
2186 return xen_api_success(self._get_VDI(vdi_ref).name_label)
2188 def VDI_get_name_description(self, session, vdi_ref):
2189 return xen_api_success(self._get_VDI(vdi_ref).name_description)
2191 def VDI_get_SR(self, session, vdi_ref):
2192 return xen_api_success(self._get_VDI(vdi_ref).sr_uuid)
2194 def VDI_get_virtual_size(self, session, vdi_ref):
2195 return xen_api_success(self._get_VDI(vdi_ref).virtual_size)
2197 def VDI_get_sharable(self, session, vdi_ref):
2198 return xen_api_success(self._get_VDI(vdi_ref).sharable)
2200 def VDI_get_read_only(self, session, vdi_ref):
2201 return xen_api_success(self._get_VDI(vdi_ref).read_only)
2203 def VDI_set_name_label(self, session, vdi_ref, value):
2204 self._get_VDI(vdi_ref).name_label = value
2205 return xen_api_success_void()
2207 def VDI_set_name_description(self, session, vdi_ref, value):
2208 self._get_VDI(vdi_ref).name_description = value
2209 return xen_api_success_void()
2211 def VDI_set_virtual_size(self, session, vdi_ref, value):
2212 return xen_api_error(XEND_ERROR_UNSUPPORTED)
2214 def VDI_set_sharable(self, session, vdi_ref, value):
2215 self._get_VDI(vdi_ref).sharable = bool(value)
2216 return xen_api_success_void()
2218 def VDI_set_read_only(self, session, vdi_ref, value):
2219 self._get_VDI(vdi_ref).read_only = bool(value)
2220 return xen_api_success_void()
2222 def VDI_get_other_config(self, session, vdi_ref):
2223 return xen_api_success(
2224 self._get_VDI(vdi_ref).other_config)
2226 def VDI_set_other_config(self, session, vdi_ref, other_config):
2227 self._get_VDI(vdi_ref).other_config = other_config
2228 return xen_api_success_void()
2230 # Object Methods
2232 def VDI_destroy(self, session, vdi_ref):
2233 sr = XendNode.instance().get_sr_containing_vdi(vdi_ref)
2234 sr.destroy_vdi(vdi_ref)
2235 return xen_api_success_void()
2237 def VDI_get_record(self, session, vdi_ref):
2238 image = XendNode.instance().get_vdi_by_uuid(vdi_ref)
2239 return xen_api_success({
2240 'uuid': vdi_ref,
2241 'name_label': image.name_label,
2242 'name_description': image.name_description,
2243 'SR': image.sr_uuid,
2244 'VBDs': image.getVBDs(),
2245 'virtual_size': image.virtual_size,
2246 'physical_utilisation': image.physical_utilisation,
2247 'type': image.type,
2248 'sharable': image.sharable,
2249 'read_only': image.read_only,
2250 'other_config': image.other_config
2251 })
2253 # Class Functions
2254 def VDI_create(self, session, vdi_struct):
2255 sr_ref = vdi_struct.get('SR')
2256 xennode = XendNode.instance()
2257 if not xennode.is_valid_sr(sr_ref):
2258 return xen_api_error(['HANDLE_INVALID', 'SR', sr_ref])
2260 vdi_uuid = xennode.srs[sr_ref].create_vdi(vdi_struct)
2261 return xen_api_success(vdi_uuid)
2263 def VDI_get_all(self, session):
2264 xennode = XendNode.instance()
2265 vdis = [sr.get_vdis() for sr in xennode.srs.values()]
2266 return xen_api_success(reduce(lambda x, y: x + y, vdis))
2268 def VDI_get_by_name_label(self, session, name):
2269 xennode = XendNode.instance()
2270 return xen_api_success(xennode.get_vdi_by_name_label(name))
2272 def VDI_set_security_label(self, session, vdi_ref, sec_lab, old_lab):
2273 vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
2274 rc = vdi.set_security_label(sec_lab, old_lab)
2275 if rc < 0:
2276 return xen_api_error(['SECURITY_ERROR', rc,
2277 xsconstants.xserr2string(-rc)])
2278 return xen_api_success(rc)
2280 def VDI_get_security_label(self, session, vdi_ref):
2281 vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
2282 return xen_api_success(vdi.get_security_label())
2284 # Xen API: Class VTPM
2285 # ----------------------------------------------------------------
2287 VTPM_attr_rw = ['other_config']
2288 VTPM_attr_ro = ['VM',
2289 'backend',
2290 'runtime_properties' ]
2292 VTPM_attr_inst = VTPM_attr_rw
2294 VTPM_methods = [('destroy', None)]
2295 VTPM_funcs = [('create', 'VTPM')]
2297 def VTPM_get_other_config(self, session, vtpm_ref):
2298 xendom = XendDomain.instance()
2299 return xen_api_success(xendom.get_dev_property_by_uuid('vtpm',
2300 vtpm_ref,
2301 'other_config'))
2303 def VTPM_set_other_config(self, session, vtpm_ref, other_config):
2304 xendom = XendDomain.instance()
2305 xendom.set_dev_property_by_uuid('vtpm',
2306 vtpm_ref,
2307 'other_config',
2308 other_config)
2309 return xen_api_success_void()
2311 # object methods
2312 def VTPM_get_record(self, session, vtpm_ref):
2313 xendom = XendDomain.instance()
2314 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
2315 if not vm:
2316 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
2317 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
2318 if not cfg:
2319 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
2320 valid_vtpm_keys = self.VTPM_attr_ro + self.VTPM_attr_rw + \
2321 self.Base_attr_ro + self.Base_attr_rw
2322 return_cfg = {}
2323 for k in cfg.keys():
2324 if k in valid_vtpm_keys:
2325 return_cfg[k] = cfg[k]
2327 return xen_api_success(return_cfg)
2329 # Class Functions
2330 def VTPM_get_backend(self, session, vtpm_ref):
2331 xendom = XendDomain.instance()
2332 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
2333 if not vm:
2334 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
2335 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
2336 if not cfg:
2337 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
2338 if not cfg.has_key('backend'):
2339 return xen_api_error(['INTERNAL_ERROR', 'VTPM backend not set'])
2340 return xen_api_success(cfg['backend'])
2342 def VTPM_get_VM(self, session, vtpm_ref):
2343 xendom = XendDomain.instance()
2344 return xen_api_success(xendom.get_dev_property_by_uuid('vtpm',
2345 vtpm_ref, 'VM'))
2347 def VTPM_destroy(self, session, vtpm_ref):
2348 xendom = XendDomain.instance()
2349 dom = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
2350 if dom:
2351 if dom.state != XEN_API_VM_POWER_STATE_HALTED:
2352 vm_ref = dom.get_dev_property('vtpm', vtpm_ref, 'VM')
2353 return xen_api_error(['VM_BAD_POWER_STATE', vm_ref,
2354 XendDomain.POWER_STATE_NAMES[XEN_API_VM_POWER_STATE_HALTED],
2355 XendDomain.POWER_STATE_NAMES[dom.state]])
2356 from xen.xend.server import tpmif
2357 tpmif.destroy_vtpmstate(dom.getName())
2358 return xen_api_success_void()
2359 else:
2360 return xen_api_error(['HANDLE_INVALID', 'VM', vtpm_struct['VM']])
2362 # class methods
2363 def VTPM_create(self, session, vtpm_struct):
2364 xendom = XendDomain.instance()
2365 if xendom.is_valid_vm(vtpm_struct['VM']):
2366 dom = xendom.get_vm_by_uuid(vtpm_struct['VM'])
2367 try:
2368 vtpm_ref = dom.create_vtpm(vtpm_struct)
2369 xendom.managed_config_save(dom)
2370 return xen_api_success(vtpm_ref)
2371 except XendError, exn:
2372 return xen_api_error(['INTERNAL_ERROR', str(exn)])
2373 else:
2374 return xen_api_error(['HANDLE_INVALID', 'VM', vtpm_struct['VM']])
2376 def VTPM_get_all(self, session):
2377 xendom = XendDomain.instance()
2378 vtpms = [d.get_vtpms() for d in XendDomain.instance().list('all')]
2379 vtpms = reduce(lambda x, y: x + y, vtpms)
2380 return xen_api_success(vtpms)
2382 def VTPM_get_runtime_properties(self, _, vtpm_ref):
2383 xendom = XendDomain.instance()
2384 dominfo = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
2385 device = dominfo.get_dev_config_by_uuid('vtpm', vtpm_ref)
2387 try:
2388 device_sxps = dominfo.getDeviceSxprs('vtpm')
2389 device_dict = dict(device_sxps[0][1])
2390 return xen_api_success(device_dict)
2391 except:
2392 return xen_api_success({})
2394 # Xen API: Class console
2395 # ----------------------------------------------------------------
2398 console_attr_ro = ['location', 'protocol', 'VM']
2399 console_attr_rw = ['other_config']
2400 console_funcs = [('create', 'console')]
2402 def console_get_all(self, session):
2403 xendom = XendDomain.instance()
2404 cons = [d.get_consoles() for d in XendDomain.instance().list('all')]
2405 cons = reduce(lambda x, y: x + y, cons)
2406 return xen_api_success(cons)
2408 def console_get_location(self, session, console_ref):
2409 xendom = XendDomain.instance()
2410 return xen_api_success(xendom.get_dev_property_by_uuid('console',
2411 console_ref,
2412 'location'))
2414 def console_get_protocol(self, session, console_ref):
2415 xendom = XendDomain.instance()
2416 return xen_api_success(xendom.get_dev_property_by_uuid('console',
2417 console_ref,
2418 'protocol'))
2420 def console_get_VM(self, session, console_ref):
2421 xendom = XendDomain.instance()
2422 vm = xendom.get_vm_with_dev_uuid('console', console_ref)
2423 return xen_api_success(vm.get_uuid())
2425 def console_get_other_config(self, session, console_ref):
2426 xendom = XendDomain.instance()
2427 return xen_api_success(xendom.get_dev_property_by_uuid('console',
2428 console_ref,
2429 'other_config'))
2431 # object methods
2432 def console_get_record(self, session, console_ref):
2433 xendom = XendDomain.instance()
2434 vm = xendom.get_vm_with_dev_uuid('console', console_ref)
2435 if not vm:
2436 return xen_api_error(['HANDLE_INVALID', 'console', console_ref])
2437 cfg = vm.get_dev_xenapi_config('console', console_ref)
2438 if not cfg:
2439 return xen_api_error(['HANDLE_INVALID', 'console', console_ref])
2441 valid_console_keys = self.console_attr_ro + self.console_attr_rw + \
2442 self.Base_attr_ro + self.Base_attr_rw
2444 return_cfg = {}
2445 for k in cfg.keys():
2446 if k in valid_console_keys:
2447 return_cfg[k] = cfg[k]
2449 return xen_api_success(return_cfg)
2451 def console_create(self, session, console_struct):
2452 xendom = XendDomain.instance()
2453 if not xendom.is_valid_vm(console_struct['VM']):
2454 return xen_api_error(['HANDLE_INVALID', 'VM',
2455 console_struct['VM']])
2457 dom = xendom.get_vm_by_uuid(console_struct['VM'])
2458 try:
2459 if 'protocol' not in console_struct:
2460 return xen_api_error(['CONSOLE_PROTOCOL_INVALID',
2461 'No protocol specified'])
2463 console_ref = dom.create_console(console_struct)
2464 xendom.managed_config_save(dom)
2465 return xen_api_success(console_ref)
2466 except XendError, exn:
2467 return xen_api_error(['INTERNAL_ERROR', str(exn)])
2469 def console_set_other_config(self, session, console_ref, other_config):
2470 xd = XendDomain.instance()
2471 vm = xd.get_vm_with_dev_uuid('console', console_ref)
2472 vm.set_console_other_config(console_ref, other_config)
2473 xd.managed_config_save(vm)
2474 return xen_api_success_void()
2476 # Xen API: Class SR
2477 # ----------------------------------------------------------------
2478 SR_attr_ro = ['VDIs',
2479 'PBDs',
2480 'virtual_allocation',
2481 'physical_utilisation',
2482 'physical_size',
2483 'type',
2484 'content_type']
2486 SR_attr_rw = ['name_label',
2487 'name_description']
2489 SR_attr_inst = ['physical_size',
2490 'type',
2491 'name_label',
2492 'name_description']
2494 SR_methods = []
2495 SR_funcs = [('get_by_name_label', 'Set(SR)'),
2496 ('get_by_uuid', 'SR')]
2498 # Class Functions
2499 def SR_get_all(self, session):
2500 return xen_api_success(XendNode.instance().get_all_sr_uuid())
2502 def SR_get_by_name_label(self, session, label):
2503 return xen_api_success(XendNode.instance().get_sr_by_name(label))
2505 def SR_get_supported_types(self, _):
2506 return xen_api_success(['local', 'qcow_file'])
2508 # Class Methods
2510 def SR_get_record(self, session, sr_ref):
2511 sr = XendNode.instance().get_sr(sr_ref)
2512 if sr:
2513 return xen_api_success(sr.get_record())
2514 return xen_api_error(['HANDLE_INVALID', 'SR', sr_ref])
2516 # Attribute acceess
2518 def _get_SR_func(self, sr_ref, func):
2519 return xen_api_success(getattr(XendNode.instance().get_sr(sr_ref),
2520 func)())
2522 def _get_SR_attr(self, sr_ref, attr):
2523 return xen_api_success(getattr(XendNode.instance().get_sr(sr_ref),
2524 attr))
2526 def SR_get_VDIs(self, _, ref):
2527 return self._get_SR_func(ref, 'list_images')
2529 def SR_get_PBDs(self, _, ref):
2530 return xen_api_success(XendPBD.get_by_SR(ref))
2532 def SR_get_virtual_allocation(self, _, ref):
2533 return self._get_SR_func(ref, 'virtual_allocation')
2535 def SR_get_physical_utilisation(self, _, ref):
2536 return self._get_SR_func(ref, 'physical_utilisation')
2538 def SR_get_physical_size(self, _, ref):
2539 return self._get_SR_attr(ref, 'physical_size')
2541 def SR_get_type(self, _, ref):
2542 return self._get_SR_attr(ref, 'type')
2544 def SR_get_content_type(self, _, ref):
2545 return self._get_SR_attr(ref, 'content_type')
2547 def SR_get_name_label(self, _, ref):
2548 return self._get_SR_attr(ref, 'name_label')
2550 def SR_get_name_description(self, _, ref):
2551 return self._get_SR_attr(ref, 'name_description')
2553 def SR_set_name_label(self, session, sr_ref, value):
2554 sr = XendNode.instance.get_sr(sr_ref)
2555 if sr:
2556 sr.name_label = value
2557 XendNode.instance().save()
2558 return xen_api_success_void()
2560 def SR_set_name_description(self, session, sr_ref, value):
2561 sr = XendNode.instance.get_sr(sr_ref)
2562 if sr:
2563 sr.name_description = value
2564 XendNode.instance().save()
2565 return xen_api_success_void()
2568 # Xen API: Class event
2569 # ----------------------------------------------------------------
2571 event_attr_ro = []
2572 event_attr_rw = []
2573 event_funcs = [('register', None),
2574 ('unregister', None),
2575 ('next', None)]
2577 def event_register(self, session, reg_classes):
2578 event_register(session, reg_classes)
2579 return xen_api_success_void()
2581 def event_unregister(self, session, unreg_classes):
2582 event_unregister(session, reg_classes)
2583 return xen_api_success_void()
2585 def event_next(self, session):
2586 return event_next(session)
2588 # Xen API: Class debug
2589 # ----------------------------------------------------------------
2591 debug_methods = [('destroy', None),
2592 ('get_record', 'debug')]
2593 debug_funcs = [('wait', None),
2594 ('return_failure', None)]
2596 def debug_wait(self, session, wait_secs):
2597 import time
2598 prog_units = 100/float(wait_secs)
2599 for i in range(int(wait_secs)):
2600 XendTask.log_progress(prog_units * i, prog_units * (i + 1),
2601 time.sleep, 1)
2602 return xen_api_success_void()
2605 def debug_return_failure(self, session):
2606 return xen_api_error(['DEBUG_FAIL', session])
2608 def debug_create(self, session):
2609 debug_uuid = uuid.createString()
2610 self._debug[debug_uuid] = None
2611 return xen_api_success(debug_uuid)
2613 def debug_destroy(self, session, debug_ref):
2614 del self._debug[debug_ref]
2615 return xen_api_success_void()
2617 def debug_get_record(self, session, debug_ref):
2618 return xen_api_success({'uuid': debug_ref})
2621 class XendAPIAsyncProxy:
2622 """ A redirector for Async.Class.function calls to XendAPI
2623 but wraps the call for use with the XendTaskManager.
2625 @ivar xenapi: Xen API instance
2626 @ivar method_map: Mapping from XMLRPC method name to callable objects.
2627 """
2629 method_prefix = 'Async.'
2631 def __init__(self, xenapi):
2632 """Initialises the Async Proxy by making a map of all
2633 implemented Xen API methods for use with XendTaskManager.
2635 @param xenapi: XendAPI instance
2636 """
2637 self.xenapi = xenapi
2638 self.method_map = {}
2639 for method_name in dir(self.xenapi):
2640 method = getattr(self.xenapi, method_name)
2641 if method_name[0] != '_' and hasattr(method, 'async') \
2642 and method.async == True:
2643 self.method_map[method.api] = method
2645 def _dispatch(self, method, args):
2646 """Overridden method so that SimpleXMLRPCServer will
2647 resolve methods through this method rather than through
2648 inspection.
2650 @param method: marshalled method name from XMLRPC.
2651 @param args: marshalled arguments from XMLRPC.
2652 """
2654 # Only deal with method names that start with "Async."
2655 if not method.startswith(self.method_prefix):
2656 return xen_api_error(['MESSAGE_METHOD_UNKNOWN', method])
2658 # Lookup synchronous version of the method
2659 synchronous_method_name = method[len(self.method_prefix):]
2660 if synchronous_method_name not in self.method_map:
2661 return xen_api_error(['MESSAGE_METHOD_UNKNOWN', method])
2663 method = self.method_map[synchronous_method_name]
2665 # Check that we've got enough arguments before issuing a task ID.
2666 needed = argcounts[method.api]
2667 if len(args) != needed:
2668 return xen_api_error(['MESSAGE_PARAMETER_COUNT_MISMATCH',
2669 self.method_prefix + method.api, needed,
2670 len(args)])
2672 # Validate the session before proceeding
2673 session = args[0]
2674 if not auth_manager().is_session_valid(session):
2675 return xen_api_error(['SESSION_INVALID', session])
2677 # create and execute the task, and return task_uuid
2678 return_type = getattr(method, 'return_type', None)
2679 task_uuid = XendTaskManager.create_task(method, args,
2680 synchronous_method_name,
2681 return_type,
2682 synchronous_method_name,
2683 session)
2684 return xen_api_success(task_uuid)