ia64/xen-unstable

view tools/python/xen/xend/XendAPI.py @ 19212:5ae8ed54e2cd

xenapi: Correct some syntax errors in xen/xend/XendAPI.py

- usage of undefined variables in error cases (invalid handle
specified) in methods VBD_create, VTPM_destroy, event_unregister
- not imported module 'uuid' in method debug_create results in an
exception

Signed-off-by: Lutz Dube <Lutz.Dube@fujitsu-siemens.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Feb 13 09:38:16 2009 +0000 (2009-02-13)
parents 368e072feb29
children 2269d8704139
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 xen.xend import uuid as genuuid
33 from XendAPIVersion import *
34 from XendAuthSessions import instance as auth_manager
35 from XendError import *
36 from XendClient import ERROR_INVALID_DOMAIN
37 from XendLogging import log
38 from XendNetwork import XendNetwork
39 from XendTask import XendTask
40 from XendPIFMetrics import XendPIFMetrics
41 from XendVMMetrics import XendVMMetrics
42 from XendPIF import XendPIF
43 from XendPBD import XendPBD
44 from XendPPCI import XendPPCI
45 from XendDPCI import XendDPCI
46 from XendPSCSI import XendPSCSI
47 from XendDSCSI import XendDSCSI
48 from XendXSPolicy import XendXSPolicy, XendACMPolicy
50 from XendAPIConstants import *
51 from xen.util.xmlrpclib2 import stringify
53 from xen.util.blkif import blkdev_name_to_number
54 from xen.util import xsconstants
57 AUTH_NONE = 'none'
58 AUTH_PAM = 'pam'
60 argcounts = {}
62 # ------------------------------------------
63 # Utility Methods for Xen API Implementation
64 # ------------------------------------------
66 def xen_api_success(value):
67 """Wraps a return value in XenAPI format."""
68 if value is None:
69 s = ''
70 else:
71 s = stringify(value)
72 return {"Status": "Success", "Value": s}
74 def xen_api_success_void():
75 """Return success, but caller expects no return value."""
76 return xen_api_success("")
78 def xen_api_error(error):
79 """Wraps an error value in XenAPI format."""
80 if type(error) == tuple:
81 error = list(error)
82 if type(error) != list:
83 error = [error]
84 if len(error) == 0:
85 error = ['INTERNAL_ERROR', 'Empty list given to xen_api_error']
87 return { "Status": "Failure",
88 "ErrorDescription": [str(x) for x in error] }
91 def xen_api_todo():
92 """Temporary method to make sure we track down all the TODOs"""
93 return {"Status": "Error", "ErrorDescription": XEND_ERROR_TODO}
96 def now():
97 return datetime()
100 def datetime(when = None):
101 """Marshall the given time as a Xen-API DateTime.
103 @param when The time in question, given as seconds since the epoch, UTC.
104 May be None, in which case the current time is used.
105 """
106 if when is None:
107 return xmlrpclib.DateTime(time.gmtime())
108 else:
109 return xmlrpclib.DateTime(time.gmtime(when))
112 # ---------------------------------------------------
113 # Event dispatch
114 # ---------------------------------------------------
116 EVENT_QUEUE_LENGTH = 50
117 event_registrations = {}
119 def event_register(session, reg_classes):
120 if session not in event_registrations:
121 event_registrations[session] = {
122 'classes' : sets.Set(),
123 'queue' : Queue.Queue(EVENT_QUEUE_LENGTH),
124 'next-id' : 1
125 }
126 if not reg_classes:
127 reg_classes = classes
128 event_registrations[session]['classes'].union_update(reg_classes)
131 def event_unregister(session, unreg_classes):
132 if session not in event_registrations:
133 return
135 if unreg_classes:
136 event_registrations[session]['classes'].intersection_update(
137 unreg_classes)
138 if len(event_registrations[session]['classes']) == 0:
139 del event_registrations[session]
140 else:
141 del event_registrations[session]
144 def event_next(session):
145 if session not in event_registrations:
146 return xen_api_error(['SESSION_NOT_REGISTERED', session])
147 queue = event_registrations[session]['queue']
148 events = [queue.get()]
149 try:
150 while True:
151 events.append(queue.get(False))
152 except Queue.Empty:
153 pass
155 return xen_api_success(events)
158 def _ctor_event_dispatch(xenapi, ctor, api_cls, session, args):
159 result = ctor(xenapi, session, *args)
160 if result['Status'] == 'Success':
161 ref = result['Value']
162 event_dispatch('add', api_cls, ref, '')
163 return result
166 def _dtor_event_dispatch(xenapi, dtor, api_cls, session, ref, args):
167 result = dtor(xenapi, session, ref, *args)
168 if result['Status'] == 'Success':
169 event_dispatch('del', api_cls, ref, '')
170 return result
173 def _setter_event_dispatch(xenapi, setter, api_cls, attr_name, session, ref,
174 args):
175 result = setter(xenapi, session, ref, *args)
176 if result['Status'] == 'Success':
177 event_dispatch('mod', api_cls, ref, attr_name)
178 return result
181 def event_dispatch(operation, api_cls, ref, attr_name):
182 assert operation in ['add', 'del', 'mod']
183 event = {
184 'timestamp' : now(),
185 'class' : api_cls,
186 'operation' : operation,
187 'ref' : ref,
188 'obj_uuid' : ref,
189 'field' : attr_name,
190 }
191 for reg in event_registrations.values():
192 if api_cls in reg['classes']:
193 event['id'] = reg['next-id']
194 reg['next-id'] += 1
195 reg['queue'].put(event)
198 # ---------------------------------------------------
199 # Python Method Decorators for input value validation
200 # ---------------------------------------------------
202 def trace(func, api_name = ''):
203 """Decorator to trace XMLRPC Xen API methods.
205 @param func: function with any parameters
206 @param api_name: name of the api call for debugging.
207 """
208 if hasattr(func, 'api'):
209 api_name = func.api
210 def trace_func(self, *args, **kwargs):
211 log.debug('%s: %s' % (api_name, args))
212 return func(self, *args, **kwargs)
213 trace_func.api = api_name
214 return trace_func
217 def catch_typeerror(func):
218 """Decorator to catch any TypeErrors and translate them into Xen-API
219 errors.
221 @param func: function with params: (self, ...)
222 @rtype: callable object
223 """
224 def f(self, *args, **kwargs):
225 try:
226 return func(self, *args, **kwargs)
227 except TypeError, exn:
228 #log.exception('catch_typeerror')
229 if hasattr(func, 'api') and func.api in argcounts:
230 # Assume that if the argument count was wrong and if the
231 # exception was thrown inside this file, then it is due to an
232 # invalid call from the client, otherwise it's an internal
233 # error (which will be handled further up).
234 expected = argcounts[func.api]
235 actual = len(args) + len(kwargs)
236 if expected != actual:
237 tb = sys.exc_info()[2]
238 try:
239 sourcefile = traceback.extract_tb(tb)[-1][0]
240 if sourcefile == inspect.getsourcefile(XendAPI):
241 return xen_api_error(
242 ['MESSAGE_PARAMETER_COUNT_MISMATCH',
243 func.api, expected, actual])
244 finally:
245 del tb
246 raise
247 except XendAPIError, exn:
248 return xen_api_error(exn.get_api_error())
250 return f
253 def session_required(func):
254 """Decorator to verify if session is valid before calling method.
256 @param func: function with params: (self, session, ...)
257 @rtype: callable object
258 """
259 def check_session(self, session, *args, **kwargs):
260 if auth_manager().is_session_valid(session):
261 return func(self, session, *args, **kwargs)
262 else:
263 return xen_api_error(['SESSION_INVALID', session])
265 return check_session
268 def _is_valid_ref(ref, validator):
269 return type(ref) == str and validator(ref)
271 def _check_ref(validator, clas, func, api, session, ref, *args, **kwargs):
272 if _is_valid_ref(ref, validator):
273 return func(api, session, ref, *args, **kwargs)
274 else:
275 return xen_api_error(['HANDLE_INVALID', clas, ref])
278 def valid_host(func):
279 """Decorator to verify if host_ref is valid before calling method.
281 @param func: function with params: (self, session, host_ref, ...)
282 @rtype: callable object
283 """
284 return lambda *args, **kwargs: \
285 _check_ref(XendNode.instance().is_valid_host,
286 'host', func, *args, **kwargs)
288 def valid_host_metrics(func):
289 """Decorator to verify if host_metrics_ref is valid before calling
290 method.
292 @param func: function with params: (self, session, host_metrics_ref)
293 @rtype: callable object
294 """
295 return lambda *args, **kwargs: \
296 _check_ref(lambda r: r == XendNode.instance().host_metrics_uuid,
297 'host_metrics', func, *args, **kwargs)
299 def valid_host_cpu(func):
300 """Decorator to verify if host_cpu_ref is valid before calling method.
302 @param func: function with params: (self, session, host_cpu_ref, ...)
303 @rtype: callable object
304 """
305 return lambda *args, **kwargs: \
306 _check_ref(XendNode.instance().is_valid_cpu,
307 'host_cpu', func, *args, **kwargs)
309 def valid_vm(func):
310 """Decorator to verify if vm_ref is valid before calling method.
312 @param func: function with params: (self, session, vm_ref, ...)
313 @rtype: callable object
314 """
315 return lambda *args, **kwargs: \
316 _check_ref(XendDomain.instance().is_valid_vm,
317 'VM', func, *args, **kwargs)
319 def valid_vbd(func):
320 """Decorator to verify if vbd_ref is valid before calling method.
322 @param func: function with params: (self, session, vbd_ref, ...)
323 @rtype: callable object
324 """
325 return lambda *args, **kwargs: \
326 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vbd', r),
327 'VBD', func, *args, **kwargs)
329 def valid_vbd_metrics(func):
330 """Decorator to verify if ref is valid before calling method.
332 @param func: function with params: (self, session, ref, ...)
333 @rtype: callable object
334 """
335 return lambda *args, **kwargs: \
336 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vbd', r),
337 'VBD_metrics', func, *args, **kwargs)
339 def valid_vif(func):
340 """Decorator to verify if vif_ref is valid before calling method.
342 @param func: function with params: (self, session, vif_ref, ...)
343 @rtype: callable object
344 """
345 return lambda *args, **kwargs: \
346 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vif', r),
347 'VIF', func, *args, **kwargs)
349 def valid_vif_metrics(func):
350 """Decorator to verify if ref is valid before calling method.
352 @param func: function with params: (self, session, ref, ...)
353 @rtype: callable object
354 """
355 return lambda *args, **kwargs: \
356 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vif', r),
357 'VIF_metrics', func, *args, **kwargs)
359 def valid_vdi(func):
360 """Decorator to verify if vdi_ref is valid before calling method.
362 @param func: function with params: (self, session, vdi_ref, ...)
363 @rtype: callable object
364 """
365 return lambda *args, **kwargs: \
366 _check_ref(XendNode.instance().is_valid_vdi,
367 'VDI', func, *args, **kwargs)
369 def valid_vtpm(func):
370 """Decorator to verify if vtpm_ref is valid before calling method.
372 @param func: function with params: (self, session, vtpm_ref, ...)
373 @rtype: callable object
374 """
375 return lambda *args, **kwargs: \
376 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vtpm', r),
377 'VTPM', func, *args, **kwargs)
380 def valid_console(func):
381 """Decorator to verify if console_ref is valid before calling method.
383 @param func: function with params: (self, session, console_ref, ...)
384 @rtype: callable object
385 """
386 return lambda *args, **kwargs: \
387 _check_ref(lambda r: XendDomain.instance().is_valid_dev('console',
388 r),
389 'console', func, *args, **kwargs)
391 def valid_sr(func):
392 """Decorator to verify if sr_ref is valid before calling method.
394 @param func: function with params: (self, session, sr_ref, ...)
395 @rtype: callable object
396 """
397 return lambda *args, **kwargs: \
398 _check_ref(lambda r: XendNode.instance().is_valid_sr,
399 'SR', func, *args, **kwargs)
401 def valid_task(func):
402 """Decorator to verify if task_ref is valid before calling
403 method.
405 @param func: function with params: (self, session, task_ref)
406 @rtype: callable object
407 """
408 return lambda *args, **kwargs: \
409 _check_ref(XendTaskManager.get_task,
410 'task', func, *args, **kwargs)
412 def valid_debug(func):
413 """Decorator to verify if task_ref is valid before calling
414 method.
416 @param func: function with params: (self, session, task_ref)
417 @rtype: callable object
418 """
419 return lambda *args, **kwargs: \
420 _check_ref(lambda r: r in XendAPI._debug,
421 'debug', func, *args, **kwargs)
424 def valid_object(class_name):
425 """Decorator to verify if object is valid before calling
426 method.
428 @param func: function with params: (self, session, pif_ref)
429 @rtype: callable object
430 """
431 return lambda func: \
432 lambda *args, **kwargs: \
433 _check_ref(lambda r: \
434 XendAPIStore.get(r, class_name) is not None,
435 class_name, func, *args, **kwargs)
437 # -----------------------------
438 # Bridge to Legacy XM API calls
439 # -----------------------------
441 def do_vm_func(fn_name, vm_ref, *args, **kwargs):
442 """Helper wrapper func to abstract away from repetitive code.
444 @param fn_name: function name for XendDomain instance
445 @type fn_name: string
446 @param vm_ref: vm_ref
447 @type vm_ref: string
448 @param *args: more arguments
449 @type *args: tuple
450 """
451 try:
452 xendom = XendDomain.instance()
453 fn = getattr(xendom, fn_name)
454 xendom.do_legacy_api_with_uuid(fn, vm_ref, *args, **kwargs)
455 return xen_api_success_void()
456 except VMBadState, exn:
457 return xen_api_error(['VM_BAD_POWER_STATE', vm_ref, exn.expected,
458 exn.actual])
461 classes = {
462 'session' : None,
463 'event' : None,
464 'host' : valid_host,
465 'host_cpu' : valid_host_cpu,
466 'host_metrics' : valid_host_metrics,
467 'VM' : valid_vm,
468 'VBD' : valid_vbd,
469 'VBD_metrics' : valid_vbd_metrics,
470 'VIF' : valid_vif,
471 'VIF_metrics' : valid_vif_metrics,
472 'VDI' : valid_vdi,
473 'VTPM' : valid_vtpm,
474 'console' : valid_console,
475 'SR' : valid_sr,
476 'task' : valid_task,
477 'XSPolicy' : valid_object("XSPolicy"),
478 'ACMPolicy' : valid_object("ACMPolicy"),
479 'debug' : valid_debug,
480 'network' : valid_object("network"),
481 'PIF' : valid_object("PIF"),
482 'VM_metrics' : valid_object("VM_metrics"),
483 'PBD' : valid_object("PBD"),
484 'PIF_metrics' : valid_object("PIF_metrics"),
485 'PPCI' : valid_object("PPCI"),
486 'DPCI' : valid_object("DPCI"),
487 'PSCSI' : valid_object("PSCSI"),
488 'DSCSI' : valid_object("DSCSI")
489 }
491 autoplug_classes = {
492 'network' : XendNetwork,
493 'PIF' : XendPIF,
494 'VM_metrics' : XendVMMetrics,
495 'PBD' : XendPBD,
496 'PIF_metrics' : XendPIFMetrics,
497 'PPCI' : XendPPCI,
498 'DPCI' : XendDPCI,
499 'PSCSI' : XendPSCSI,
500 'DSCSI' : XendDSCSI,
501 'XSPolicy' : XendXSPolicy,
502 'ACMPolicy' : XendACMPolicy,
503 }
505 class XendAPI(object):
506 """Implementation of the Xen-API in Xend. Expects to be
507 used via XMLRPCServer.
509 All methods that need a valid session are marked with
510 a L{session_required} decorator that will
511 transparently perform the required session authentication.
513 We need to support Python <2.4, so we use the old decorator syntax.
515 All XMLRPC accessible methods require an 'api' attribute and
516 is set to the XMLRPC function name which the method implements.
517 """
519 __decorated__ = False
520 __init_lock__ = threading.Lock()
521 _debug = {}
523 def __new__(cls, *args, **kwds):
524 """ Override __new__ to decorate the class only once.
526 Lock to make sure the classes are not decorated twice.
527 """
528 cls.__init_lock__.acquire()
529 try:
530 if not cls.__decorated__:
531 cls._decorate()
532 cls.__decorated__ = True
534 return object.__new__(cls, *args, **kwds)
535 finally:
536 cls.__init_lock__.release()
538 def _decorate(cls):
539 """ Decorate all the object methods to have validators
540 and appropriate function attributes.
542 This should only be executed once for the duration of the
543 server.
544 """
545 global_validators = [session_required, catch_typeerror]
548 # Cheat methods
549 # -------------
550 # Methods that have a trivial implementation for all classes.
551 # 1. get_by_uuid == getting by ref, so just return uuid for
552 # all get_by_uuid() methods.
554 for api_cls in classes.keys():
555 # We'll let the autoplug classes implement these functions
556 # themselves - its much cleaner to do it in the base class
557 if api_cls == 'session' or api_cls in autoplug_classes.keys():
558 continue
560 get_by_uuid = '%s_get_by_uuid' % api_cls
561 get_uuid = '%s_get_uuid' % api_cls
562 get_all_records = '%s_get_all_records' % api_cls
564 def _get_by_uuid(_1, _2, ref):
565 return xen_api_success(ref)
567 def _get_uuid(_1, _2, ref):
568 return xen_api_success(ref)
570 def unpack(v):
571 return v.get('Value')
573 def _get_all_records(_api_cls):
574 return lambda s, session: \
575 xen_api_success(dict([(ref, unpack(getattr(cls, '%s_get_record' % _api_cls)(s, session, ref)))\
576 for ref in unpack(getattr(cls, '%s_get_all' % _api_cls)(s, session))]))
578 setattr(cls, get_by_uuid, _get_by_uuid)
579 setattr(cls, get_uuid, _get_uuid)
580 setattr(cls, get_all_records, _get_all_records(api_cls))
582 # Autoplugging classes
583 # --------------------
584 # These have all of their methods grabbed out from the implementation
585 # class, and wrapped up to be compatible with the Xen-API.
587 def getter(ref, type):
588 return XendAPIStore.get(ref, type)
590 for api_cls, impl_cls in autoplug_classes.items():
591 def doit(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 + 1
597 g = lambda api_cls: \
598 setattr(cls, full_n, \
599 lambda s, session, ref, *args: \
600 xen_api_success( \
601 f(getter(ref, api_cls), *args)))
602 g(api_cls) # Force api_cls to be captured
604 def doit_func(n):
605 dot_n = '%s.%s' % (api_cls, n)
606 full_n = '%s_%s' % (api_cls, n)
607 if not hasattr(cls, full_n):
608 f = getattr(impl_cls, n)
609 argcounts[dot_n] = f.func_code.co_argcount
610 setattr(cls, full_n, \
611 lambda s, session, *args: \
612 xen_api_success( \
613 f(*args)))
615 ro_attrs = impl_cls.getAttrRO()
616 rw_attrs = impl_cls.getAttrRW()
617 methods = impl_cls.getMethods()
618 funcs = impl_cls.getFuncs()
620 for attr_name in ro_attrs + rw_attrs:
621 doit('get_%s' % attr_name)
622 for attr_name in rw_attrs:
623 doit('set_%s' % attr_name)
624 for method in methods:
625 doit('%s' % method)
626 for func in funcs:
627 doit_func('%s' % func)
629 def wrap_method(name, new_f):
630 try:
631 f = getattr(cls, name)
632 wrapped_f = (lambda *args: new_f(f, *args))
633 wrapped_f.api = f.api
634 wrapped_f.async = f.async
635 setattr(cls, name, wrapped_f)
636 except AttributeError:
637 # Logged below (API call: %s not found)
638 pass
641 def setter_event_wrapper(api_cls, attr_name):
642 setter_name = '%s_set_%s' % (api_cls, attr_name)
643 wrap_method(
644 setter_name,
645 lambda setter, s, session, ref, *args:
646 _setter_event_dispatch(s, setter, api_cls, attr_name,
647 session, ref, args))
650 def ctor_event_wrapper(api_cls):
651 ctor_name = '%s_create' % api_cls
652 wrap_method(
653 ctor_name,
654 lambda ctor, s, session, *args:
655 _ctor_event_dispatch(s, ctor, api_cls, session, args))
658 def dtor_event_wrapper(api_cls):
659 dtor_name = '%s_destroy' % api_cls
660 wrap_method(
661 dtor_name,
662 lambda dtor, s, session, ref, *args:
663 _dtor_event_dispatch(s, dtor, api_cls, session, ref, args))
666 # Wrapping validators around XMLRPC calls
667 # ---------------------------------------
669 for api_cls, validator in classes.items():
670 def doit(n, takes_instance, async_support = False,
671 return_type = None):
672 n_ = n.replace('.', '_')
673 try:
674 f = getattr(cls, n_)
675 if n not in argcounts:
676 argcounts[n] = f.func_code.co_argcount - 1
678 validators = takes_instance and validator and \
679 [validator] or []
681 validators += global_validators
682 for v in validators:
683 f = v(f)
684 f.api = n
685 f.async = async_support
686 if return_type:
687 f.return_type = return_type
689 setattr(cls, n_, f)
690 except AttributeError:
691 log.warn("API call: %s not found" % n)
693 if api_cls in autoplug_classes.keys():
694 impl_cls = autoplug_classes[api_cls]
695 ro_attrs = impl_cls.getAttrRO()
696 rw_attrs = impl_cls.getAttrRW()
697 methods = map(lambda x: (x, ""), impl_cls.getMethods())
698 funcs = map(lambda x: (x, ""), impl_cls.getFuncs())
699 else:
700 ro_attrs = getattr(cls, '%s_attr_ro' % api_cls, []) \
701 + cls.Base_attr_ro
702 rw_attrs = getattr(cls, '%s_attr_rw' % api_cls, []) \
703 + cls.Base_attr_rw
704 methods = getattr(cls, '%s_methods' % api_cls, []) \
705 + cls.Base_methods
706 funcs = getattr(cls, '%s_funcs' % api_cls, []) \
707 + cls.Base_funcs
709 # wrap validators around readable class attributes
710 for attr_name in ro_attrs + rw_attrs:
711 doit('%s.get_%s' % (api_cls, attr_name), True,
712 async_support = False)
714 # wrap validators around writable class attrributes
715 for attr_name in rw_attrs:
716 doit('%s.set_%s' % (api_cls, attr_name), True,
717 async_support = False)
718 setter_event_wrapper(api_cls, attr_name)
720 # wrap validators around methods
721 for method_name, return_type in methods:
722 doit('%s.%s' % (api_cls, method_name), True,
723 async_support = True)
725 # wrap validators around class functions
726 for func_name, return_type in funcs:
727 doit('%s.%s' % (api_cls, func_name), False,
728 async_support = True,
729 return_type = return_type)
731 ctor_event_wrapper(api_cls)
732 dtor_event_wrapper(api_cls)
735 _decorate = classmethod(_decorate)
737 def __init__(self, auth):
738 self.auth = auth
740 Base_attr_ro = ['uuid']
741 Base_attr_rw = []
742 Base_methods = [('get_record', 'Struct')]
743 Base_funcs = [('get_all', 'Set'), ('get_by_uuid', None), ('get_all_records', 'Set')]
745 # Xen API: Class Session
746 # ----------------------------------------------------------------
747 # NOTE: Left unwrapped by __init__
749 session_attr_ro = ['this_host', 'this_user', 'last_active']
750 session_methods = [('logout', None)]
752 def session_get_all(self, session):
753 return xen_api_success([session])
755 def session_login_with_password(self, *args):
756 if len(args) != 2:
757 return xen_api_error(
758 ['MESSAGE_PARAMETER_COUNT_MISMATCH',
759 'session.login_with_password', 2, len(args)])
760 username = args[0]
761 password = args[1]
762 try:
763 session = ((self.auth == AUTH_NONE and
764 auth_manager().login_unconditionally(username)) or
765 auth_manager().login_with_password(username, password))
766 return xen_api_success(session)
767 except XendError, e:
768 return xen_api_error(['SESSION_AUTHENTICATION_FAILED'])
769 session_login_with_password.api = 'session.login_with_password'
771 # object methods
772 def session_logout(self, session):
773 auth_manager().logout(session)
774 return xen_api_success_void()
776 def session_get_record(self, session, self_session):
777 if self_session != session:
778 return xen_api_error(['PERMISSION_DENIED'])
779 record = {'uuid' : session,
780 'this_host' : XendNode.instance().uuid,
781 'this_user' : auth_manager().get_user(session),
782 'last_active': now()}
783 return xen_api_success(record)
785 def session_get_uuid(self, session, self_session):
786 return xen_api_success(self_session)
788 def session_get_by_uuid(self, session, self_session):
789 return xen_api_success(self_session)
791 # attributes (ro)
792 def session_get_this_host(self, session, self_session):
793 if self_session != session:
794 return xen_api_error(['PERMISSION_DENIED'])
795 return xen_api_success(XendNode.instance().uuid)
797 def session_get_this_user(self, session, self_session):
798 if self_session != session:
799 return xen_api_error(['PERMISSION_DENIED'])
800 user = auth_manager().get_user(session)
801 if user is not None:
802 return xen_api_success(user)
803 return xen_api_error(['SESSION_INVALID', session])
805 def session_get_last_active(self, session, self_session):
806 if self_session != session:
807 return xen_api_error(['PERMISSION_DENIED'])
808 return xen_api_success(now())
811 # Xen API: Class User
812 # ----------------------------------------------------------------
813 # TODO: NOT IMPLEMENTED YET
815 # Xen API: Class Tasks
816 # ----------------------------------------------------------------
818 task_attr_ro = ['name_label',
819 'name_description',
820 'status',
821 'progress',
822 'type',
823 'result',
824 'error_info',
825 'allowed_operations',
826 'session'
827 ]
829 task_attr_rw = []
831 task_funcs = [('get_by_name_label', 'Set(task)'),
832 ('cancel', None)]
834 def task_get_name_label(self, session, task_ref):
835 task = XendTaskManager.get_task(task_ref)
836 return xen_api_success(task.name_label)
838 def task_get_name_description(self, session, task_ref):
839 task = XendTaskManager.get_task(task_ref)
840 return xen_api_success(task.name_description)
842 def task_get_status(self, session, task_ref):
843 task = XendTaskManager.get_task(task_ref)
844 return xen_api_success(task.get_status())
846 def task_get_progress(self, session, task_ref):
847 task = XendTaskManager.get_task(task_ref)
848 return xen_api_success(task.progress)
850 def task_get_type(self, session, task_ref):
851 task = XendTaskManager.get_task(task_ref)
852 return xen_api_success(task.type)
854 def task_get_result(self, session, task_ref):
855 task = XendTaskManager.get_task(task_ref)
856 return xen_api_success(task.result)
858 def task_get_error_info(self, session, task_ref):
859 task = XendTaskManager.get_task(task_ref)
860 return xen_api_success(task.error_info)
862 def task_get_allowed_operations(self, session, task_ref):
863 return xen_api_success({})
865 def task_get_session(self, session, task_ref):
866 task = XendTaskManager.get_task(task_ref)
867 return xen_api_success(task.session)
869 def task_get_all(self, session):
870 tasks = XendTaskManager.get_all_tasks()
871 return xen_api_success(tasks)
873 def task_get_record(self, session, task_ref):
874 task = XendTaskManager.get_task(task_ref)
875 return xen_api_success(task.get_record())
877 def task_cancel(self, session, task_ref):
878 return xen_api_error('OPERATION_NOT_ALLOWED')
880 def task_get_by_name_label(self, session, name):
881 return xen_api_success(XendTaskManager.get_task_by_name(name))
883 # Xen API: Class host
884 # ----------------------------------------------------------------
886 host_attr_ro = ['software_version',
887 'resident_VMs',
888 'PBDs',
889 'PIFs',
890 'PPCIs',
891 'PSCSIs',
892 'host_CPUs',
893 'cpu_configuration',
894 'metrics',
895 'capabilities',
896 'supported_bootloaders',
897 'sched_policy',
898 'API_version_major',
899 'API_version_minor',
900 'API_version_vendor',
901 'API_version_vendor_implementation',
902 'enabled']
904 host_attr_rw = ['name_label',
905 'name_description',
906 'other_config',
907 'logging']
909 host_methods = [('disable', None),
910 ('enable', None),
911 ('reboot', None),
912 ('shutdown', None),
913 ('add_to_other_config', None),
914 ('remove_from_other_config', None),
915 ('dmesg', 'String'),
916 ('dmesg_clear', 'String'),
917 ('get_log', 'String'),
918 ('send_debug_keys', None)]
920 host_funcs = [('get_by_name_label', None),
921 ('list_methods', None)]
923 # attributes
924 def host_get_name_label(self, session, host_ref):
925 return xen_api_success(XendNode.instance().name)
926 def host_set_name_label(self, session, host_ref, new_name):
927 XendNode.instance().set_name(new_name)
928 return xen_api_success_void()
929 def host_get_name_description(self, session, host_ref):
930 return xen_api_success(XendNode.instance().get_description())
931 def host_set_name_description(self, session, host_ref, new_desc):
932 XendNode.instance().set_description(new_desc)
933 return xen_api_success_void()
934 def host_get_other_config(self, session, host_ref):
935 return xen_api_success(XendNode.instance().other_config)
936 def host_set_other_config(self, session, host_ref, other_config):
937 node = XendNode.instance()
938 node.other_config = dict(other_config)
939 node.save()
940 return xen_api_success_void()
941 def host_add_to_other_config(self, session, host_ref, key, value):
942 node = XendNode.instance()
943 node.other_config[key] = value
944 node.save()
945 return xen_api_success_void()
946 def host_remove_from_other_config(self, session, host_ref, key):
947 node = XendNode.instance()
948 if key in node.other_config:
949 del node.other_config[key]
950 node.save()
951 return xen_api_success_void()
952 def host_get_API_version_major(self, _, ref):
953 return xen_api_success(XEN_API_VERSION_MAJOR)
954 def host_get_API_version_minor(self, _, ref):
955 return xen_api_success(XEN_API_VERSION_MINOR)
956 def host_get_API_version_vendor(self, _, ref):
957 return xen_api_success(XEN_API_VERSION_VENDOR)
958 def host_get_API_version_vendor_implementation(self, _, ref):
959 return xen_api_success(XEN_API_VERSION_VENDOR_IMPLEMENTATION)
960 def host_get_software_version(self, session, host_ref):
961 return xen_api_success(XendNode.instance().xen_version())
962 def host_get_enabled(self, _1, _2):
963 return xen_api_success(XendDomain.instance().allow_new_domains())
964 def host_get_resident_VMs(self, session, host_ref):
965 return xen_api_success(XendDomain.instance().get_domain_refs())
966 def host_get_PBDs(self, _, ref):
967 return xen_api_success(XendPBD.get_all())
968 def host_get_PIFs(self, session, ref):
969 return xen_api_success(XendNode.instance().get_PIF_refs())
970 def host_get_PPCIs(self, session, ref):
971 return xen_api_success(XendNode.instance().get_PPCI_refs())
972 def host_get_PSCSIs(self, session, ref):
973 return xen_api_success(XendNode.instance().get_PSCSI_refs())
974 def host_get_host_CPUs(self, session, host_ref):
975 return xen_api_success(XendNode.instance().get_host_cpu_refs())
976 def host_get_metrics(self, _, ref):
977 return xen_api_success(XendNode.instance().host_metrics_uuid)
978 def host_get_capabilities(self, session, host_ref):
979 return xen_api_success(XendNode.instance().get_capabilities())
980 def host_get_supported_bootloaders(self, session, host_ref):
981 return xen_api_success(['pygrub'])
982 def host_get_sched_policy(self, _, host_ref):
983 return xen_api_success(XendNode.instance().get_vcpus_policy())
984 def host_get_cpu_configuration(self, _, host_ref):
985 return xen_api_success(XendNode.instance().get_cpu_configuration())
986 def host_set_logging(self, _, host_ref, logging):
987 return xen_api_todo()
988 def host_get_logging(self, _, host_ref):
989 return xen_api_todo()
991 # object methods
992 def host_disable(self, session, host_ref):
993 XendDomain.instance().set_allow_new_domains(False)
994 return xen_api_success_void()
995 def host_enable(self, session, host_ref):
996 XendDomain.instance().set_allow_new_domains(True)
997 return xen_api_success_void()
998 def host_reboot(self, session, host_ref):
999 if not XendDomain.instance().allow_new_domains():
1000 return xen_api_error(XEND_ERROR_HOST_RUNNING)
1001 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1002 def host_shutdown(self, session, host_ref):
1003 if not XendDomain.instance().allow_new_domains():
1004 return xen_api_error(XEND_ERROR_HOST_RUNNING)
1005 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1007 def host_dmesg(self, session, host_ref):
1008 return xen_api_success(XendDmesg.instance().info())
1010 def host_dmesg_clear(self, session, host_ref):
1011 return xen_api_success(XendDmesg.instance().clear())
1013 def host_get_log(self, session, host_ref):
1014 log_file = open(XendLogging.getLogFilename())
1015 log_buffer = log_file.read()
1016 log_buffer = log_buffer.replace('\b', ' ')
1017 log_buffer = log_buffer.replace('\f', '\n')
1018 log_file.close()
1019 return xen_api_success(log_buffer)
1021 def host_send_debug_keys(self, _, host_ref, keys):
1022 node = XendNode.instance()
1023 node.send_debug_keys(keys)
1024 return xen_api_success_void()
1026 def host_get_record(self, session, host_ref):
1027 node = XendNode.instance()
1028 dom = XendDomain.instance()
1029 record = {'uuid': node.uuid,
1030 'name_label': node.name,
1031 'name_description': '',
1032 'API_version_major': XEN_API_VERSION_MAJOR,
1033 'API_version_minor': XEN_API_VERSION_MINOR,
1034 'API_version_vendor': XEN_API_VERSION_VENDOR,
1035 'API_version_vendor_implementation':
1036 XEN_API_VERSION_VENDOR_IMPLEMENTATION,
1037 'software_version': node.xen_version(),
1038 'enabled': XendDomain.instance().allow_new_domains(),
1039 'other_config': node.other_config,
1040 'resident_VMs': dom.get_domain_refs(),
1041 'host_CPUs': node.get_host_cpu_refs(),
1042 'cpu_configuration': node.get_cpu_configuration(),
1043 'metrics': node.host_metrics_uuid,
1044 'capabilities': node.get_capabilities(),
1045 'supported_bootloaders': ['pygrub'],
1046 'sched_policy': node.get_vcpus_policy(),
1047 'logging': {},
1048 'PIFs': XendPIF.get_all(),
1049 'PBDs': XendPBD.get_all(),
1050 'PPCIs': XendPPCI.get_all(),
1051 'PSCSIs': XendPSCSI.get_all()}
1052 return xen_api_success(record)
1054 # class methods
1055 def host_get_all(self, session):
1056 return xen_api_success((XendNode.instance().uuid,))
1057 def host_get_by_name_label(self, session, name):
1058 if XendNode.instance().name == name:
1059 return xen_api_success((XendNode.instance().uuid,))
1060 return xen_api_success([])
1062 def host_list_methods(self, _):
1063 def _funcs():
1064 return [getattr(XendAPI, x) for x in XendAPI.__dict__]
1066 return xen_api_success([x.api for x in _funcs()
1067 if hasattr(x, 'api')])
1069 # Xen API: Class host_CPU
1070 # ----------------------------------------------------------------
1072 host_cpu_attr_ro = ['host',
1073 'number',
1074 'vendor',
1075 'speed',
1076 'modelname',
1077 'stepping',
1078 'flags',
1079 'utilisation',
1080 'features']
1082 # attributes
1083 def _host_cpu_get(self, ref, field):
1084 return xen_api_success(
1085 XendNode.instance().get_host_cpu_field(ref, field))
1087 def host_cpu_get_host(self, _, ref):
1088 return xen_api_success(XendNode.instance().uuid)
1089 def host_cpu_get_features(self, _, ref):
1090 return self._host_cpu_get(ref, 'features')
1091 def host_cpu_get_number(self, _, ref):
1092 return self._host_cpu_get(ref, 'number')
1093 def host_cpu_get_vendor(self, _, ref):
1094 return self._host_cpu_get(ref, 'vendor')
1095 def host_cpu_get_speed(self, _, ref):
1096 return self._host_cpu_get(ref, 'speed')
1097 def host_cpu_get_modelname(self, _, ref):
1098 return self._host_cpu_get(ref, 'modelname')
1099 def host_cpu_get_stepping(self, _, ref):
1100 return self._host_cpu_get(ref, 'stepping')
1101 def host_cpu_get_flags(self, _, ref):
1102 return self._host_cpu_get(ref, 'flags')
1103 def host_cpu_get_utilisation(self, _, ref):
1104 return xen_api_success(XendNode.instance().get_host_cpu_load(ref))
1106 # object methods
1107 def host_cpu_get_record(self, _, ref):
1108 node = XendNode.instance()
1109 record = dict([(f, node.get_host_cpu_field(ref, f))
1110 for f in self.host_cpu_attr_ro
1111 if f not in ['uuid', 'host', 'utilisation']])
1112 record['uuid'] = ref
1113 record['host'] = node.uuid
1114 record['utilisation'] = node.get_host_cpu_load(ref)
1115 return xen_api_success(record)
1117 # class methods
1118 def host_cpu_get_all(self, session):
1119 return xen_api_success(XendNode.instance().get_host_cpu_refs())
1122 # Xen API: Class host_metrics
1123 # ----------------------------------------------------------------
1125 host_metrics_attr_ro = ['memory_total',
1126 'memory_free',
1127 'last_updated']
1128 host_metrics_attr_rw = []
1129 host_metrics_methods = []
1131 def host_metrics_get_all(self, _):
1132 return xen_api_success([XendNode.instance().host_metrics_uuid])
1134 def _host_metrics_get(self, ref, f):
1135 return xen_api_success(getattr(node, f)())
1137 def host_metrics_get_record(self, _, ref):
1138 return xen_api_success({
1139 'uuid' : ref,
1140 'memory_total' : self._host_metrics_get_memory_total(),
1141 'memory_free' : self._host_metrics_get_memory_free(),
1142 'last_updated' : now(),
1143 })
1145 def host_metrics_get_memory_total(self, _1, _2):
1146 return xen_api_success(self._host_metrics_get_memory_total())
1148 def host_metrics_get_memory_free(self, _1, _2):
1149 return xen_api_success(self._host_metrics_get_memory_free())
1151 def host_metrics_get_last_updated(self, _1, _2):
1152 return xen_api_success(now())
1154 def _host_metrics_get_memory_total(self):
1155 node = XendNode.instance()
1156 return node.xc.physinfo()['total_memory'] * 1024
1158 def _host_metrics_get_memory_free(self):
1159 node = XendNode.instance()
1160 return node.xc.physinfo()['free_memory'] * 1024
1162 # Xen API: Class VM
1163 # ----------------------------------------------------------------
1165 VM_attr_ro = ['power_state',
1166 'resident_on',
1167 'consoles',
1168 'VIFs',
1169 'VBDs',
1170 'VTPMs',
1171 'DPCIs',
1172 'DSCSIs',
1173 'tools_version',
1174 'domid',
1175 'is_control_domain',
1176 'metrics',
1177 'crash_dumps',
1180 VM_attr_rw = ['name_label',
1181 'name_description',
1182 'user_version',
1183 'is_a_template',
1184 'auto_power_on',
1185 'memory_dynamic_max',
1186 'memory_dynamic_min',
1187 'memory_static_max',
1188 'memory_static_min',
1189 'VCPUs_max',
1190 'VCPUs_at_startup',
1191 'VCPUs_params',
1192 'actions_after_shutdown',
1193 'actions_after_reboot',
1194 'actions_after_suspend',
1195 'actions_after_crash',
1196 'PV_bootloader',
1197 'PV_kernel',
1198 'PV_ramdisk',
1199 'PV_args',
1200 'PV_bootloader_args',
1201 'HVM_boot_policy',
1202 'HVM_boot_params',
1203 'platform',
1204 'PCI_bus',
1205 'other_config',
1206 'security_label']
1208 VM_methods = [('clone', 'VM'),
1209 ('start', None),
1210 ('pause', None),
1211 ('unpause', None),
1212 ('clean_shutdown', None),
1213 ('clean_reboot', None),
1214 ('hard_shutdown', None),
1215 ('hard_reboot', None),
1216 ('suspend', None),
1217 ('resume', None),
1218 ('send_sysrq', None),
1219 ('set_VCPUs_number_live', None),
1220 ('add_to_HVM_boot_params', None),
1221 ('remove_from_HVM_boot_params', None),
1222 ('add_to_VCPUs_params', None),
1223 ('add_to_VCPUs_params_live', None),
1224 ('remove_from_VCPUs_params', None),
1225 ('add_to_platform', None),
1226 ('remove_from_platform', None),
1227 ('add_to_other_config', None),
1228 ('remove_from_other_config', None),
1229 ('save', None),
1230 ('set_memory_dynamic_max_live', None),
1231 ('set_memory_dynamic_min_live', None),
1232 ('send_trigger', None),
1233 ('migrate', None),
1234 ('destroy', None)]
1236 VM_funcs = [('create', 'VM'),
1237 ('restore', None),
1238 ('get_by_name_label', 'Set(VM)')]
1240 # parameters required for _create()
1241 VM_attr_inst = [
1242 'name_label',
1243 'name_description',
1244 'user_version',
1245 'is_a_template',
1246 'memory_static_max',
1247 'memory_dynamic_max',
1248 'memory_dynamic_min',
1249 'memory_static_min',
1250 'VCPUs_max',
1251 'VCPUs_at_startup',
1252 'VCPUs_params',
1253 'actions_after_shutdown',
1254 'actions_after_reboot',
1255 'actions_after_suspend',
1256 'actions_after_crash',
1257 'PV_bootloader',
1258 'PV_kernel',
1259 'PV_ramdisk',
1260 'PV_args',
1261 'PV_bootloader_args',
1262 'HVM_boot_policy',
1263 'HVM_boot_params',
1264 'platform',
1265 'PCI_bus',
1266 'other_config',
1267 'security_label']
1269 def VM_get(self, name, session, vm_ref):
1270 return xen_api_success(
1271 XendDomain.instance().get_vm_by_uuid(vm_ref).info[name])
1273 def VM_set(self, name, session, vm_ref, value):
1274 xd = XendDomain.instance()
1275 dominfo = xd.get_vm_by_uuid(vm_ref)
1276 dominfo.info[name] = value
1277 return self._VM_save(dominfo)
1279 def _VM_save(self, dominfo):
1280 XendDomain.instance().managed_config_save(dominfo)
1281 return xen_api_success_void()
1283 # attributes (ro)
1284 def VM_get_power_state(self, session, vm_ref):
1285 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1286 return xen_api_success(dom.get_power_state())
1288 def VM_get_resident_on(self, session, vm_ref):
1289 return xen_api_success(XendNode.instance().uuid)
1291 def VM_get_memory_static_max(self, session, vm_ref):
1292 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1293 return xen_api_success(dom.get_memory_static_max())
1295 def VM_get_memory_static_min(self, session, vm_ref):
1296 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1297 return xen_api_success(dom.get_memory_static_min())
1299 def VM_get_VIFs(self, session, vm_ref):
1300 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1301 return xen_api_success(dom.get_vifs())
1303 def VM_get_VBDs(self, session, vm_ref):
1304 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1305 return xen_api_success(dom.get_vbds())
1307 def VM_get_VTPMs(self, session, vm_ref):
1308 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1309 return xen_api_success(dom.get_vtpms())
1311 def VM_get_consoles(self, session, vm_ref):
1312 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1313 return xen_api_success(dom.get_consoles())
1315 def VM_get_DPCIs(self, session, vm_ref):
1316 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1317 return xen_api_success(dom.get_dpcis())
1319 def VM_get_DSCSIs(self, session, vm_ref):
1320 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1321 return xen_api_success(dom.get_dscsis())
1323 def VM_get_tools_version(self, session, vm_ref):
1324 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1325 return dom.get_tools_version()
1327 def VM_get_metrics(self, _, vm_ref):
1328 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1329 return xen_api_success(dom.get_metrics())
1331 def VM_get_VCPUs_max(self, _, vm_ref):
1332 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1333 return xen_api_todo()
1335 def VM_get_VCPUs_at_startup(self, _, vm_ref):
1336 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1337 return xen_api_todo()
1339 # attributes (rw)
1340 def VM_get_name_label(self, session, vm_ref):
1341 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1342 return xen_api_success(dom.getName())
1344 def VM_get_name_description(self, session, vm_ref):
1345 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1346 return xen_api_todo()
1348 def VM_get_user_version(self, session, vm_ref):
1349 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1350 return xen_api_todo()
1352 def VM_get_is_a_template(self, session, ref):
1353 return self.VM_get('is_a_template', session, ref)
1355 def VM_get_memory_dynamic_max(self, session, vm_ref):
1356 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1357 return xen_api_success(dom.get_memory_dynamic_max())
1359 def VM_get_memory_dynamic_min(self, session, vm_ref):
1360 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1361 return xen_api_success(dom.get_memory_dynamic_min())
1363 def VM_get_VCPUs_params(self, session, vm_ref):
1364 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1365 return xen_api_success(dom.get_vcpus_params())
1367 def VM_get_actions_after_shutdown(self, session, vm_ref):
1368 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1369 return xen_api_success(dom.get_on_shutdown())
1371 def VM_get_actions_after_reboot(self, session, vm_ref):
1372 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1373 return xen_api_success(dom.get_on_reboot())
1375 def VM_get_actions_after_suspend(self, session, vm_ref):
1376 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1377 return xen_api_success(dom.get_on_suspend())
1379 def VM_get_actions_after_crash(self, session, vm_ref):
1380 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1381 return xen_api_success(dom.get_on_crash())
1383 def VM_get_PV_bootloader(self, session, vm_ref):
1384 return self.VM_get('PV_bootloader', session, vm_ref)
1386 def VM_get_PV_kernel(self, session, vm_ref):
1387 return self.VM_get('PV_kernel', session, vm_ref)
1389 def VM_get_PV_ramdisk(self, session, vm_ref):
1390 return self.VM_get('PV_ramdisk', session, vm_ref)
1392 def VM_get_PV_args(self, session, vm_ref):
1393 return self.VM_get('PV_args', session, vm_ref)
1395 def VM_get_PV_bootloader_args(self, session, vm_ref):
1396 return self.VM_get('PV_bootloader_args', session, vm_ref)
1398 def VM_get_HVM_boot_policy(self, session, vm_ref):
1399 return self.VM_get('HVM_boot_policy', session, vm_ref)
1401 def VM_get_HVM_boot_params(self, session, vm_ref):
1402 return self.VM_get('HVM_boot_params', session, vm_ref)
1404 def VM_get_platform(self, session, vm_ref):
1405 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1406 return xen_api_success(dom.get_platform())
1408 def VM_get_PCI_bus(self, session, vm_ref):
1409 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1410 return dom.get_pci_bus()
1412 def VM_set_PCI_bus(self, session, vm_ref, val):
1413 return self.VM_set('PCI_bus', session, vm_ref, val)
1415 def VM_get_other_config(self, session, vm_ref):
1416 return self.VM_get('other_config', session, vm_ref)
1418 def VM_get_domid(self, _, ref):
1419 domid = XendDomain.instance().get_vm_by_uuid(ref).getDomid()
1420 return xen_api_success(domid is None and -1 or domid)
1422 def VM_get_is_control_domain(self, session, vm_ref):
1423 xd = XendDomain.instance()
1424 return xen_api_success(
1425 xd.get_vm_by_uuid(vm_ref) == xd.privilegedDomain())
1427 def VM_set_name_label(self, session, vm_ref, label):
1428 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1429 dom.setName(label)
1430 return self._VM_save(dom)
1432 def VM_set_name_description(self, session, vm_ref, desc):
1433 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1434 return xen_api_todo()
1436 def VM_set_user_version(self, session, vm_ref, ver):
1437 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1438 return xen_api_todo()
1440 def VM_set_is_a_template(self, session, vm_ref, is_template):
1441 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1442 return xen_api_todo()
1444 def VM_set_memory_dynamic_max(self, session, vm_ref, mem):
1445 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1446 dom.set_memory_dynamic_max(int(mem))
1447 return self._VM_save(dom)
1449 def VM_set_memory_dynamic_min(self, session, vm_ref, mem):
1450 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1451 dom.set_memory_dynamic_min(int(mem))
1452 return self._VM_save(dom)
1454 def VM_set_memory_static_max(self, session, vm_ref, mem):
1455 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1456 dom.set_memory_static_max(int(mem))
1457 return self._VM_save(dom)
1459 def VM_set_memory_static_min(self, session, vm_ref, mem):
1460 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1461 dom.set_memory_static_min(int(mem))
1462 return self._VM_save(dom)
1464 def VM_set_memory_dynamic_max_live(self, session, vm_ref, mem):
1465 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1466 dom.set_memory_dynamic_max(int(mem))
1467 # need to pass target as MiB
1468 dom.setMemoryTarget(int(mem)/1024/1024)
1469 return xen_api_success_void()
1471 def VM_set_memory_dynamic_min_live(self, session, vm_ref, mem):
1472 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1473 dom.set_memory_dynamic_min(int(mem))
1474 # need to pass target as MiB
1475 dom.setMemoryTarget(int(mem)/1024/1024)
1476 return xen_api_success_void()
1478 def VM_set_VCPUs_params(self, session, vm_ref, value):
1479 return self.VM_set('vcpus_params', session, vm_ref, value)
1481 def VM_add_to_VCPUs_params(self, session, vm_ref, key, value):
1482 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1483 if 'vcpus_params' not in dom.info:
1484 dom.info['vcpus_params'] = {}
1485 dom.info['vcpus_params'][key] = value
1486 return self._VM_save(dom)
1488 def VM_add_to_VCPUs_params_live(self, session, vm_ref, key, value):
1489 self.VM_add_to_VCPUs_params(session, vm_ref, key, value)
1490 self._VM_VCPUs_params_refresh(vm_ref)
1491 return xen_api_success_void()
1493 def _VM_VCPUs_params_refresh(self, vm_ref):
1494 xendom = XendDomain.instance()
1495 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1497 #update the cpumaps
1498 for key, value in xeninfo.info['vcpus_params'].items():
1499 if key.startswith("cpumap"):
1500 vcpu = int(key[6:])
1501 try:
1502 cpus = map(int, value.split(","))
1503 xendom.domain_pincpu(xeninfo.getDomid(), vcpu, cpus)
1504 except Exception, ex:
1505 log.exception(ex)
1507 #need to update sched params aswell
1508 if 'weight' in xeninfo.info['vcpus_params'] \
1509 and 'cap' in xeninfo.info['vcpus_params']:
1510 weight = xeninfo.info['vcpus_params']['weight']
1511 cap = xeninfo.info['vcpus_params']['cap']
1512 xendom.domain_sched_credit_set(xeninfo.getDomid(), weight, cap)
1514 def VM_set_VCPUs_number_live(self, _, vm_ref, num):
1515 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1516 dom.setVCpuCount(int(num))
1517 return xen_api_success_void()
1519 def VM_remove_from_VCPUs_params(self, session, vm_ref, key):
1520 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1521 if 'vcpus_params' in dom.info \
1522 and key in dom.info['vcpus_params']:
1523 del dom.info['vcpus_params'][key]
1524 return self._VM_save(dom)
1525 else:
1526 return xen_api_success_void()
1528 def VM_set_VCPUs_at_startup(self, session, vm_ref, num):
1529 return self.VM_set('VCPUs_at_startup', session, vm_ref, num)
1531 def VM_set_VCPUs_max(self, session, vm_ref, num):
1532 return self.VM_set('VCPUs_max', session, vm_ref, num)
1534 def VM_set_actions_after_shutdown(self, session, vm_ref, action):
1535 if action not in XEN_API_ON_NORMAL_EXIT:
1536 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1537 return self.VM_set('actions_after_shutdown', session, vm_ref, action)
1539 def VM_set_actions_after_reboot(self, session, vm_ref, action):
1540 if action not in XEN_API_ON_NORMAL_EXIT:
1541 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1542 return self.VM_set('actions_after_reboot', session, vm_ref, action)
1544 def VM_set_actions_after_suspend(self, session, vm_ref, action):
1545 if action not in XEN_API_ON_NORMAL_EXIT:
1546 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1547 return self.VM_set('actions_after_suspend', session, vm_ref, action)
1549 def VM_set_actions_after_crash(self, session, vm_ref, action):
1550 if action not in XEN_API_ON_CRASH_BEHAVIOUR:
1551 return xen_api_error(['VM_ON_CRASH_BEHAVIOUR_INVALID', vm_ref])
1552 return self.VM_set('actions_after_crash', session, vm_ref, action)
1554 def VM_set_HVM_boot_policy(self, session, vm_ref, value):
1555 if value != "" and value != "BIOS order":
1556 return xen_api_error(
1557 ['VALUE_NOT_SUPPORTED', 'VM.HVM_boot_policy', value,
1558 'Xend supports only the "BIOS order" boot policy.'])
1559 else:
1560 return self.VM_set('HVM_boot_policy', session, vm_ref, value)
1562 def VM_set_HVM_boot_params(self, session, vm_ref, value):
1563 return self.VM_set('HVM_boot_params', session, vm_ref, value)
1565 def VM_add_to_HVM_boot_params(self, session, vm_ref, key, value):
1566 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1567 if 'HVM_boot_params' not in dom.info:
1568 dom.info['HVM_boot_params'] = {}
1569 dom.info['HVM_boot_params'][key] = value
1570 return self._VM_save(dom)
1572 def VM_remove_from_HVM_boot_params(self, session, vm_ref, key):
1573 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1574 if 'HVM_boot_params' in dom.info \
1575 and key in dom.info['HVM_boot_params']:
1576 del dom.info['HVM_boot_params'][key]
1577 return self._VM_save(dom)
1578 else:
1579 return xen_api_success_void()
1581 def VM_set_PV_bootloader(self, session, vm_ref, value):
1582 return self.VM_set('PV_bootloader', session, vm_ref, value)
1584 def VM_set_PV_kernel(self, session, vm_ref, value):
1585 return self.VM_set('PV_kernel', session, vm_ref, value)
1587 def VM_set_PV_ramdisk(self, session, vm_ref, value):
1588 return self.VM_set('PV_ramdisk', session, vm_ref, value)
1590 def VM_set_PV_args(self, session, vm_ref, value):
1591 return self.VM_set('PV_args', session, vm_ref, value)
1593 def VM_set_PV_bootloader_args(self, session, vm_ref, value):
1594 return self.VM_set('PV_bootloader_args', session, vm_ref, value)
1596 def VM_set_platform(self, session, vm_ref, value):
1597 return self.VM_set('platform', session, vm_ref, value)
1599 def VM_add_to_platform(self, session, vm_ref, key, value):
1600 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1601 plat = dom.get_platform()
1602 plat[key] = value
1603 return self.VM_set_platform(session, vm_ref, plat)
1605 def VM_remove_from_platform(self, session, vm_ref, key):
1606 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1607 plat = dom.get_platform()
1608 if key in plat:
1609 del plat[key]
1610 return self.VM_set_platform(session, vm_ref, plat)
1611 else:
1612 return xen_api_success_void()
1614 def VM_set_other_config(self, session, vm_ref, value):
1615 return self.VM_set('other_config', session, vm_ref, value)
1617 def VM_add_to_other_config(self, session, vm_ref, key, value):
1618 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1619 if dom and 'other_config' in dom.info:
1620 dom.info['other_config'][key] = value
1621 return self._VM_save(dom)
1623 def VM_remove_from_other_config(self, session, vm_ref, key):
1624 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1625 if dom and 'other_config' in dom.info \
1626 and key in dom.info['other_config']:
1627 del dom.info['other_config'][key]
1628 return self._VM_save(dom)
1629 else:
1630 return xen_api_success_void()
1632 def VM_get_crash_dumps(self, _, vm_ref):
1633 return xen_api_todo()
1635 # class methods
1636 def VM_get_all(self, session):
1637 refs = [d.get_uuid() for d in XendDomain.instance().list('all')]
1638 return xen_api_success(refs)
1640 def VM_get_by_name_label(self, session, label):
1641 xendom = XendDomain.instance()
1642 dom = xendom.domain_lookup_nr(label)
1643 if dom:
1644 return xen_api_success([dom.get_uuid()])
1645 return xen_api_success([])
1647 def VM_get_security_label(self, session, vm_ref):
1648 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1649 label = dom.get_security_label()
1650 return xen_api_success(label)
1652 def VM_set_security_label(self, session, vm_ref, sec_label, old_label):
1653 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1654 (rc, errors, oldlabel, new_ssidref) = \
1655 dom.set_security_label(sec_label, old_label)
1656 if rc != xsconstants.XSERR_SUCCESS:
1657 return xen_api_error(['SECURITY_ERROR', rc,
1658 xsconstants.xserr2string(-rc)])
1659 if rc == 0:
1660 rc = new_ssidref
1661 return xen_api_success(rc)
1663 def VM_create(self, session, vm_struct):
1664 xendom = XendDomain.instance()
1665 domuuid = XendTask.log_progress(0, 100,
1666 xendom.create_domain, vm_struct)
1667 return xen_api_success(domuuid)
1669 # object methods
1670 def VM_get_record(self, session, vm_ref):
1671 xendom = XendDomain.instance()
1672 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1673 if not xeninfo:
1674 return xen_api_error(['HANDLE_INVALID', 'VM', vm_ref])
1676 domid = xeninfo.getDomid()
1678 record = {
1679 'uuid': xeninfo.get_uuid(),
1680 'power_state': xeninfo.get_power_state(),
1681 'name_label': xeninfo.getName(),
1682 'name_description': xeninfo.getName(),
1683 'user_version': 1,
1684 'is_a_template': xeninfo.info['is_a_template'],
1685 'auto_power_on': False,
1686 'resident_on': XendNode.instance().uuid,
1687 'memory_static_min': xeninfo.get_memory_static_min(),
1688 'memory_static_max': xeninfo.get_memory_static_max(),
1689 'memory_dynamic_min': xeninfo.get_memory_dynamic_min(),
1690 'memory_dynamic_max': xeninfo.get_memory_dynamic_max(),
1691 'VCPUs_params': xeninfo.get_vcpus_params(),
1692 'VCPUs_at_startup': xeninfo.getVCpuCount(),
1693 'VCPUs_max': xeninfo.getVCpuCount(),
1694 'actions_after_shutdown': xeninfo.get_on_shutdown(),
1695 'actions_after_reboot': xeninfo.get_on_reboot(),
1696 'actions_after_suspend': xeninfo.get_on_suspend(),
1697 'actions_after_crash': xeninfo.get_on_crash(),
1698 'consoles': xeninfo.get_consoles(),
1699 'VIFs': xeninfo.get_vifs(),
1700 'VBDs': xeninfo.get_vbds(),
1701 'VTPMs': xeninfo.get_vtpms(),
1702 'DPCIs': xeninfo.get_dpcis(),
1703 'DSCSIs': xeninfo.get_dscsis(),
1704 'PV_bootloader': xeninfo.info.get('PV_bootloader'),
1705 'PV_kernel': xeninfo.info.get('PV_kernel'),
1706 'PV_ramdisk': xeninfo.info.get('PV_ramdisk'),
1707 'PV_args': xeninfo.info.get('PV_args'),
1708 'PV_bootloader_args': xeninfo.info.get('PV_bootloader_args'),
1709 'HVM_boot_policy': xeninfo.info.get('HVM_boot_policy'),
1710 'HVM_boot_params': xeninfo.info.get('HVM_boot_params'),
1711 'platform': xeninfo.get_platform(),
1712 'PCI_bus': xeninfo.get_pci_bus(),
1713 'tools_version': xeninfo.get_tools_version(),
1714 'other_config': xeninfo.info.get('other_config', {}),
1715 'domid': domid is None and -1 or domid,
1716 'is_control_domain': xeninfo.info['is_control_domain'],
1717 'metrics': xeninfo.get_metrics(),
1718 'security_label': xeninfo.get_security_label(),
1719 'crash_dumps': []
1721 return xen_api_success(record)
1723 def VM_clean_reboot(self, session, vm_ref):
1724 xendom = XendDomain.instance()
1725 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1726 XendTask.log_progress(0, 100, xeninfo.shutdown, "reboot")
1727 return xen_api_success_void()
1729 def VM_clean_shutdown(self, session, vm_ref):
1730 xendom = XendDomain.instance()
1731 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1732 XendTask.log_progress(0, 100, xeninfo.shutdown, "poweroff")
1733 return xen_api_success_void()
1735 def VM_clone(self, session, vm_ref):
1736 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1738 def VM_destroy(self, session, vm_ref):
1739 return XendTask.log_progress(0, 100, do_vm_func,
1740 "domain_delete", vm_ref)
1742 def VM_hard_reboot(self, session, vm_ref):
1743 return XendTask.log_progress(0, 100, do_vm_func,
1744 "domain_reset", vm_ref)
1746 def VM_hard_shutdown(self, session, vm_ref):
1747 return XendTask.log_progress(0, 100, do_vm_func,
1748 "domain_destroy", vm_ref)
1750 def VM_pause(self, session, vm_ref):
1751 return XendTask.log_progress(0, 100, do_vm_func,
1752 "domain_pause", vm_ref)
1754 def VM_resume(self, session, vm_ref, start_paused):
1755 return XendTask.log_progress(0, 100, do_vm_func,
1756 "domain_resume", vm_ref,
1757 start_paused = start_paused)
1759 def VM_start(self, session, vm_ref, start_paused):
1760 try:
1761 return XendTask.log_progress(0, 100, do_vm_func,
1762 "domain_start", vm_ref,
1763 start_paused = start_paused)
1764 except HVMRequired, exn:
1765 return xen_api_error(['VM_HVM_REQUIRED', vm_ref])
1767 def VM_suspend(self, session, vm_ref):
1768 return XendTask.log_progress(0, 100, do_vm_func,
1769 "domain_suspend", vm_ref)
1771 def VM_unpause(self, session, vm_ref):
1772 return XendTask.log_progress(0, 100, do_vm_func,
1773 "domain_unpause", vm_ref)
1775 def VM_send_sysrq(self, _, vm_ref, req):
1776 xeninfo = XendDomain.instance().get_vm_by_uuid(vm_ref)
1777 if xeninfo.state == XEN_API_VM_POWER_STATE_RUNNING \
1778 or xeninfo.state == XEN_API_VM_POWER_STATE_PAUSED:
1779 xeninfo.send_sysrq(req)
1780 return xen_api_success_void()
1781 else:
1782 return xen_api_error(
1783 ['VM_BAD_POWER_STATE', vm_ref,
1784 XendDomain.POWER_STATE_NAMES[XEN_API_VM_POWER_STATE_RUNNING],
1785 XendDomain.POWER_STATE_NAMES[xeninfo.state]])
1787 def VM_send_trigger(self, _, vm_ref, trigger, vcpu):
1788 xendom = XendDomain.instance()
1789 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1790 xendom.domain_send_trigger(xeninfo.getDomid(), trigger, vcpu)
1791 return xen_api_success_void()
1793 def VM_migrate(self, _, vm_ref, destination_url, live, other_config):
1794 xendom = XendDomain.instance()
1795 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1797 port = other_config.get("port", 0)
1798 node = other_config.get("node", -1)
1799 ssl = other_config.get("ssl", None)
1801 xendom.domain_migrate(xeninfo.getDomid(), destination_url,
1802 bool(live), port, node, ssl)
1803 return xen_api_success_void()
1805 def VM_save(self, _, vm_ref, dest, checkpoint):
1806 xendom = XendDomain.instance()
1807 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1808 xendom.domain_save(xeninfo.getDomid(), dest, checkpoint)
1809 return xen_api_success_void()
1811 def VM_restore(self, _, src, paused):
1812 xendom = XendDomain.instance()
1813 xendom.domain_restore(src, bool(paused))
1814 return xen_api_success_void()
1817 # Xen API: Class VBD
1818 # ----------------------------------------------------------------
1820 VBD_attr_ro = ['VM',
1821 'VDI',
1822 'metrics',
1823 'runtime_properties']
1824 VBD_attr_rw = ['device',
1825 'bootable',
1826 'mode',
1827 'type']
1829 VBD_attr_inst = VBD_attr_rw
1831 VBD_methods = [('media_change', None), ('destroy', None)]
1832 VBD_funcs = [('create', 'VBD')]
1834 # object methods
1835 def VBD_get_record(self, session, vbd_ref):
1836 xendom = XendDomain.instance()
1837 vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1838 if not vm:
1839 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1840 cfg = vm.get_dev_xenapi_config('vbd', vbd_ref)
1841 if not cfg:
1842 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1844 valid_vbd_keys = self.VBD_attr_ro + self.VBD_attr_rw + \
1845 self.Base_attr_ro + self.Base_attr_rw
1847 return_cfg = {}
1848 for k in cfg.keys():
1849 if k in valid_vbd_keys:
1850 return_cfg[k] = cfg[k]
1852 return_cfg['metrics'] = vbd_ref
1853 return_cfg['runtime_properties'] = {} #todo
1855 return xen_api_success(return_cfg)
1857 def VBD_media_change(self, session, vbd_ref, vdi_ref):
1858 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1860 # class methods
1861 def VBD_create(self, session, vbd_struct):
1862 xendom = XendDomain.instance()
1863 xennode = XendNode.instance()
1865 if not xendom.is_valid_vm(vbd_struct['VM']):
1866 return xen_api_error(['HANDLE_INVALID', 'VM', vbd_struct['VM']])
1868 dom = xendom.get_vm_by_uuid(vbd_struct['VM'])
1869 vdi = xennode.get_vdi_by_uuid(vbd_struct['VDI'])
1870 if not vdi:
1871 return xen_api_error(['HANDLE_INVALID', 'VDI', vbd_struct['VDI']])
1873 # new VBD via VDI/SR
1874 vdi_image = vdi.get_location()
1876 try:
1877 vbd_ref = XendTask.log_progress(0, 100,
1878 dom.create_vbd,
1879 vbd_struct, vdi_image)
1880 except XendError, e:
1881 log.exception("Error in VBD_create")
1882 return xen_api_error(['INTERNAL_ERROR', str(e)])
1884 vdi.addVBD(vbd_ref)
1886 xendom.managed_config_save(dom)
1887 return xen_api_success(vbd_ref)
1890 def VBD_destroy(self, session, vbd_ref):
1891 xendom = XendDomain.instance()
1892 vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1893 if not vm:
1894 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1896 vdi_ref = XendDomain.instance()\
1897 .get_dev_property_by_uuid('vbd', vbd_ref, "VDI")
1898 vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
1900 XendTask.log_progress(0, 100, vm.destroy_vbd, vbd_ref)
1902 vdi.removeVBD(vbd_ref)
1904 return xen_api_success_void()
1906 def _VBD_get(self, vbd_ref, prop):
1907 return xen_api_success(
1908 XendDomain.instance().get_dev_property_by_uuid(
1909 'vbd', vbd_ref, prop))
1911 # attributes (ro)
1912 def VBD_get_metrics(self, _, vbd_ref):
1913 return xen_api_success(vbd_ref)
1915 def VBD_get_runtime_properties(self, _, vbd_ref):
1916 xendom = XendDomain.instance()
1917 dominfo = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1918 device = dominfo.get_dev_config_by_uuid('vbd', vbd_ref)
1920 try:
1921 devid = int(device['id'])
1922 device_sxps = dominfo.getDeviceSxprs('vbd')
1923 device_dicts = [dict(device_sxp[1][0:]) for device_sxp in device_sxps]
1924 device_dict = [device_dict
1925 for device_dict in device_dicts
1926 if int(device_dict['virtual-device']) == devid][0]
1928 return xen_api_success(device_dict)
1929 except Exception, exn:
1930 log.exception(exn)
1931 return xen_api_success({})
1933 # attributes (rw)
1934 def VBD_get_VM(self, session, vbd_ref):
1935 return self._VBD_get(vbd_ref, 'VM')
1937 def VBD_get_VDI(self, session, vbd_ref):
1938 return self._VBD_get(vbd_ref, 'VDI')
1940 def VBD_get_device(self, session, vbd_ref):
1941 return self._VBD_get(vbd_ref, 'device')
1943 def VBD_get_bootable(self, session, vbd_ref):
1944 return self._VBD_get(vbd_ref, 'bootable')
1946 def VBD_get_mode(self, session, vbd_ref):
1947 return self._VBD_get(vbd_ref, 'mode')
1949 def VBD_get_type(self, session, vbd_ref):
1950 return self._VBD_get(vbd_ref, 'type')
1952 def VBD_set_bootable(self, session, vbd_ref, bootable):
1953 bootable = bool(bootable)
1954 xd = XendDomain.instance()
1955 vm = xd.get_vm_with_dev_uuid('vbd', vbd_ref)
1956 vm.set_dev_property('vbd', vbd_ref, 'bootable', bootable)
1957 xd.managed_config_save(vm)
1958 return xen_api_success_void()
1960 def VBD_set_mode(self, session, vbd_ref, mode):
1961 if mode == 'RW':
1962 mode = 'w'
1963 else:
1964 mode = 'r'
1965 xd = XendDomain.instance()
1966 vm = xd.get_vm_with_dev_uuid('vbd', vbd_ref)
1967 vm.set_dev_property('vbd', vbd_ref, 'mode', mode)
1968 xd.managed_config_save(vm)
1969 return xen_api_success_void()
1971 def VBD_get_all(self, session):
1972 xendom = XendDomain.instance()
1973 vbds = [d.get_vbds() for d in XendDomain.instance().list('all')]
1974 vbds = reduce(lambda x, y: x + y, vbds)
1975 return xen_api_success(vbds)
1978 # Xen API: Class VBD_metrics
1979 # ----------------------------------------------------------------
1981 VBD_metrics_attr_ro = ['io_read_kbs',
1982 'io_write_kbs',
1983 'last_updated']
1984 VBD_metrics_attr_rw = []
1985 VBD_metrics_methods = []
1987 def VBD_metrics_get_all(self, session):
1988 return self.VBD_get_all(session)
1990 def VBD_metrics_get_record(self, _, ref):
1991 vm = XendDomain.instance().get_vm_with_dev_uuid('vbd', ref)
1992 if not vm:
1993 return xen_api_error(['HANDLE_INVALID', 'VBD_metrics', ref])
1994 return xen_api_success(
1995 { 'io_read_kbs' : vm.get_dev_property('vbd', ref, 'io_read_kbs'),
1996 'io_write_kbs' : vm.get_dev_property('vbd', ref, 'io_write_kbs'),
1997 'last_updated' : now()
1998 })
2000 def VBD_metrics_get_io_read_kbs(self, _, ref):
2001 return self._VBD_get(ref, 'io_read_kbs')
2003 def VBD_metrics_get_io_write_kbs(self, session, ref):
2004 return self._VBD_get(ref, 'io_write_kbs')
2006 def VBD_metrics_get_last_updated(self, _1, _2):
2007 return xen_api_success(now())
2010 # Xen API: Class VIF
2011 # ----------------------------------------------------------------
2013 VIF_attr_ro = ['network',
2014 'VM',
2015 'metrics',
2016 'runtime_properties']
2017 VIF_attr_rw = ['device',
2018 'MAC',
2019 'MTU',
2020 'security_label']
2022 VIF_attr_inst = VIF_attr_rw
2024 VIF_methods = [('destroy', None)]
2025 VIF_funcs = [('create', 'VIF')]
2028 # object methods
2029 def VIF_get_record(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])
2034 cfg = vm.get_dev_xenapi_config('vif', vif_ref)
2035 if not cfg:
2036 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
2038 valid_vif_keys = self.VIF_attr_ro + self.VIF_attr_rw + \
2039 self.Base_attr_ro + self.Base_attr_rw
2041 return_cfg = {}
2042 for k in cfg.keys():
2043 if k in valid_vif_keys:
2044 return_cfg[k] = cfg[k]
2046 return_cfg['metrics'] = vif_ref
2048 return xen_api_success(return_cfg)
2050 # class methods
2051 def VIF_create(self, session, vif_struct):
2052 xendom = XendDomain.instance()
2053 if not xendom.is_valid_vm(vif_struct['VM']):
2054 return xen_api_error(['HANDLE_INVALID', 'VM', vif_struct['VM']])
2056 dom = xendom.get_vm_by_uuid(vif_struct['VM'])
2057 try:
2058 vif_ref = dom.create_vif(vif_struct)
2059 xendom.managed_config_save(dom)
2060 return xen_api_success(vif_ref)
2061 except XendError, exn:
2062 return xen_api_error(['INTERNAL_ERROR', str(exn)])
2064 def VIF_destroy(self, session, vif_ref):
2065 xendom = XendDomain.instance()
2066 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
2067 if not vm:
2068 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
2070 vm.destroy_vif(vif_ref)
2071 return xen_api_success_void()
2073 def _VIF_get(self, ref, prop):
2074 return xen_api_success(
2075 XendDomain.instance().get_dev_property_by_uuid('vif', ref, prop))
2077 # getters/setters
2078 def VIF_get_metrics(self, _, vif_ref):
2079 return xen_api_success(vif_ref)
2081 def VIF_get_VM(self, session, vif_ref):
2082 xendom = XendDomain.instance()
2083 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
2084 return xen_api_success(vm.get_uuid())
2086 def VIF_get_MTU(self, session, vif_ref):
2087 return self._VIF_get(vif_ref, 'MTU')
2089 def VIF_get_MAC(self, session, vif_ref):
2090 return self._VIF_get(vif_ref, 'MAC')
2092 def VIF_get_device(self, session, vif_ref):
2093 return self._VIF_get(vif_ref, 'device')
2095 def VIF_get_all(self, session):
2096 xendom = XendDomain.instance()
2097 vifs = [d.get_vifs() for d in XendDomain.instance().list('all')]
2098 vifs = reduce(lambda x, y: x + y, vifs)
2099 return xen_api_success(vifs)
2101 def VIF_get_runtime_properties(self, _, vif_ref):
2102 xendom = XendDomain.instance()
2103 dominfo = xendom.get_vm_with_dev_uuid('vif', vif_ref)
2104 device = dominfo.get_dev_config_by_uuid('vif', vif_ref)
2106 try:
2107 devid = int(device['id'])
2109 device_sxps = dominfo.getDeviceSxprs('vif')
2110 device_dicts = [dict(device_sxp[1][1:])
2111 for device_sxp in device_sxps]
2113 device_dict = [device_dict
2114 for device_dict in device_dicts
2115 if int(device_dict['handle']) == devid][0]
2117 return xen_api_success(device_dict)
2119 except Exception, exn:
2120 log.exception(exn)
2121 return xen_api_success({})
2123 def VIF_get_security_label(self, session, vif_ref):
2124 return self._VIF_get(vif_ref, 'security_label')
2126 def _VIF_set(self, ref, prop, val, old_val):
2127 return XendDomain.instance().set_dev_property_by_uuid(
2128 'vif', ref, prop, val, old_val)
2130 def VIF_set_security_label(self, session, vif_ref, sec_lab, old_lab):
2131 xendom = XendDomain.instance()
2132 dom = xendom.get_vm_with_dev_uuid('vif', vif_ref)
2133 if not dom:
2134 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
2136 if dom._stateGet() == XEN_API_VM_POWER_STATE_RUNNING:
2137 raise SecurityError(-xsconstants.XSERR_RESOURCE_IN_USE)
2139 rc = self._VIF_set(vif_ref, 'security_label', sec_lab, old_lab)
2140 if rc == False:
2141 raise SecurityError(-xsconstants.XSERR_BAD_LABEL)
2142 return xen_api_success(xsconstants.XSERR_SUCCESS)
2145 # Xen API: Class VIF_metrics
2146 # ----------------------------------------------------------------
2148 VIF_metrics_attr_ro = ['io_read_kbs',
2149 'io_write_kbs',
2150 'io_total_read_kbs',
2151 'io_total_write_kbs',
2152 'last_updated']
2153 VIF_metrics_attr_rw = []
2154 VIF_metrics_methods = []
2156 def VIF_metrics_get_all(self, session):
2157 return self.VIF_get_all(session)
2159 def VIF_metrics_get_record(self, _, ref):
2160 vm = XendDomain.instance().get_vm_with_dev_uuid('vif', ref)
2161 if not vm:
2162 return xen_api_error(['HANDLE_INVALID', 'VIF_metrics', ref])
2163 return xen_api_success(
2164 { 'io_read_kbs' : vm.get_dev_property('vif', ref, 'io_read_kbs'),
2165 'io_write_kbs' : vm.get_dev_property('vif', ref, 'io_write_kbs'),
2166 'io_total_read_kbs' : vm.get_dev_property('vif', ref, 'io_total_read_kbs'),
2167 'io_total_write_kbs' : vm.get_dev_property('vif', ref, 'io_total_write_kbs'),
2168 'last_updated' : now()
2169 })
2171 def VIF_metrics_get_io_read_kbs(self, _, ref):
2172 return self._VIF_get(ref, 'io_read_kbs')
2174 def VIF_metrics_get_io_write_kbs(self, session, ref):
2175 return self._VIF_get(ref, 'io_write_kbs')
2177 def VIF_metrics_get_io_total_read_kbs(self, _, ref):
2178 return self._VIF_get(ref, 'io_total_read_kbs')
2180 def VIF_metrics_get_io_total_write_kbs(self, session, ref):
2181 return self._VIF_get(ref, 'io_total_write_kbs')
2183 def VIF_metrics_get_last_updated(self, _1, _2):
2184 return xen_api_success(now())
2187 # Xen API: Class VDI
2188 # ----------------------------------------------------------------
2189 VDI_attr_ro = ['SR',
2190 'VBDs',
2191 'physical_utilisation',
2192 'type']
2193 VDI_attr_rw = ['name_label',
2194 'name_description',
2195 'virtual_size',
2196 'sharable',
2197 'read_only',
2198 'other_config',
2199 'security_label']
2200 VDI_attr_inst = VDI_attr_ro + VDI_attr_rw
2202 VDI_methods = [('destroy', None)]
2203 VDI_funcs = [('create', 'VDI'),
2204 ('get_by_name_label', 'Set(VDI)')]
2206 def _get_VDI(self, ref):
2207 return XendNode.instance().get_vdi_by_uuid(ref)
2209 def VDI_get_VBDs(self, session, vdi_ref):
2210 vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
2211 return xen_api_success(vdi.getVBDs())
2213 def VDI_get_physical_utilisation(self, session, vdi_ref):
2214 return xen_api_success(self._get_VDI(vdi_ref).
2215 get_physical_utilisation())
2217 def VDI_get_type(self, session, vdi_ref):
2218 return xen_api_success(self._get_VDI(vdi_ref).type)
2220 def VDI_get_name_label(self, session, vdi_ref):
2221 return xen_api_success(self._get_VDI(vdi_ref).name_label)
2223 def VDI_get_name_description(self, session, vdi_ref):
2224 return xen_api_success(self._get_VDI(vdi_ref).name_description)
2226 def VDI_get_SR(self, session, vdi_ref):
2227 return xen_api_success(self._get_VDI(vdi_ref).sr_uuid)
2229 def VDI_get_virtual_size(self, session, vdi_ref):
2230 return xen_api_success(self._get_VDI(vdi_ref).virtual_size)
2232 def VDI_get_sharable(self, session, vdi_ref):
2233 return xen_api_success(self._get_VDI(vdi_ref).sharable)
2235 def VDI_get_read_only(self, session, vdi_ref):
2236 return xen_api_success(self._get_VDI(vdi_ref).read_only)
2238 def VDI_set_name_label(self, session, vdi_ref, value):
2239 self._get_VDI(vdi_ref).name_label = value
2240 return xen_api_success_void()
2242 def VDI_set_name_description(self, session, vdi_ref, value):
2243 self._get_VDI(vdi_ref).name_description = value
2244 return xen_api_success_void()
2246 def VDI_set_virtual_size(self, session, vdi_ref, value):
2247 return xen_api_error(XEND_ERROR_UNSUPPORTED)
2249 def VDI_set_sharable(self, session, vdi_ref, value):
2250 self._get_VDI(vdi_ref).sharable = bool(value)
2251 return xen_api_success_void()
2253 def VDI_set_read_only(self, session, vdi_ref, value):
2254 self._get_VDI(vdi_ref).read_only = bool(value)
2255 return xen_api_success_void()
2257 def VDI_get_other_config(self, session, vdi_ref):
2258 return xen_api_success(
2259 self._get_VDI(vdi_ref).other_config)
2261 def VDI_set_other_config(self, session, vdi_ref, other_config):
2262 self._get_VDI(vdi_ref).other_config = other_config
2263 return xen_api_success_void()
2265 # Object Methods
2267 def VDI_destroy(self, session, vdi_ref):
2268 sr = XendNode.instance().get_sr_containing_vdi(vdi_ref)
2269 sr.destroy_vdi(vdi_ref)
2270 return xen_api_success_void()
2272 def VDI_get_record(self, session, vdi_ref):
2273 image = XendNode.instance().get_vdi_by_uuid(vdi_ref)
2274 return xen_api_success({
2275 'uuid': vdi_ref,
2276 'name_label': image.name_label,
2277 'name_description': image.name_description,
2278 'SR': image.sr_uuid,
2279 'VBDs': image.getVBDs(),
2280 'virtual_size': image.virtual_size,
2281 'physical_utilisation': image.physical_utilisation,
2282 'type': image.type,
2283 'sharable': image.sharable,
2284 'read_only': image.read_only,
2285 'other_config': image.other_config,
2286 'security_label' : image.get_security_label()
2287 })
2289 # Class Functions
2290 def VDI_create(self, session, vdi_struct):
2291 sr_ref = vdi_struct.get('SR')
2292 xennode = XendNode.instance()
2293 if not xennode.is_valid_sr(sr_ref):
2294 return xen_api_error(['HANDLE_INVALID', 'SR', sr_ref])
2296 vdi_uuid = xennode.srs[sr_ref].create_vdi(vdi_struct)
2297 return xen_api_success(vdi_uuid)
2299 def VDI_get_all(self, session):
2300 xennode = XendNode.instance()
2301 vdis = [sr.get_vdis() for sr in xennode.srs.values()]
2302 return xen_api_success(reduce(lambda x, y: x + y, vdis))
2304 def VDI_get_by_name_label(self, session, name):
2305 xennode = XendNode.instance()
2306 return xen_api_success(xennode.get_vdi_by_name_label(name))
2308 def VDI_set_security_label(self, session, vdi_ref, sec_lab, old_lab):
2309 vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
2310 rc = vdi.set_security_label(sec_lab, old_lab)
2311 if rc < 0:
2312 return xen_api_error(['SECURITY_ERROR', rc,
2313 xsconstants.xserr2string(-rc)])
2314 return xen_api_success(rc)
2316 def VDI_get_security_label(self, session, vdi_ref):
2317 vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
2318 return xen_api_success(vdi.get_security_label())
2320 # Xen API: Class VTPM
2321 # ----------------------------------------------------------------
2323 VTPM_attr_rw = ['other_config']
2324 VTPM_attr_ro = ['VM',
2325 'backend',
2326 'runtime_properties' ]
2328 VTPM_attr_inst = VTPM_attr_rw
2330 VTPM_methods = [('destroy', None)]
2331 VTPM_funcs = [('create', 'VTPM')]
2333 def VTPM_get_other_config(self, session, vtpm_ref):
2334 xendom = XendDomain.instance()
2335 return xen_api_success(xendom.get_dev_property_by_uuid('vtpm',
2336 vtpm_ref,
2337 'other_config'))
2339 def VTPM_set_other_config(self, session, vtpm_ref, other_config):
2340 xendom = XendDomain.instance()
2341 xendom.set_dev_property_by_uuid('vtpm',
2342 vtpm_ref,
2343 'other_config',
2344 other_config)
2345 return xen_api_success_void()
2347 # object methods
2348 def VTPM_get_record(self, session, vtpm_ref):
2349 xendom = XendDomain.instance()
2350 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
2351 if not vm:
2352 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
2353 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
2354 if not cfg:
2355 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
2356 valid_vtpm_keys = self.VTPM_attr_ro + self.VTPM_attr_rw + \
2357 self.Base_attr_ro + self.Base_attr_rw
2358 return_cfg = {}
2359 for k in cfg.keys():
2360 if k in valid_vtpm_keys:
2361 return_cfg[k] = cfg[k]
2363 return xen_api_success(return_cfg)
2365 # Class Functions
2366 def VTPM_get_backend(self, session, vtpm_ref):
2367 xendom = XendDomain.instance()
2368 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
2369 if not vm:
2370 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
2371 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
2372 if not cfg:
2373 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
2374 if not cfg.has_key('backend'):
2375 return xen_api_error(['INTERNAL_ERROR', 'VTPM backend not set'])
2376 return xen_api_success(cfg['backend'])
2378 def VTPM_get_VM(self, session, vtpm_ref):
2379 xendom = XendDomain.instance()
2380 return xen_api_success(xendom.get_dev_property_by_uuid('vtpm',
2381 vtpm_ref, 'VM'))
2383 def VTPM_destroy(self, session, vtpm_ref):
2384 xendom = XendDomain.instance()
2385 dom = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
2386 if dom:
2387 if dom.state != XEN_API_VM_POWER_STATE_HALTED:
2388 vm_ref = dom.get_dev_property('vtpm', vtpm_ref, 'VM')
2389 return xen_api_error(['VM_BAD_POWER_STATE', vm_ref,
2390 XendDomain.POWER_STATE_NAMES[XEN_API_VM_POWER_STATE_HALTED],
2391 XendDomain.POWER_STATE_NAMES[dom.state]])
2392 from xen.xend.server import tpmif
2393 tpmif.destroy_vtpmstate(dom.getName())
2394 return xen_api_success_void()
2395 else:
2396 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
2398 # class methods
2399 def VTPM_create(self, session, vtpm_struct):
2400 xendom = XendDomain.instance()
2401 if xendom.is_valid_vm(vtpm_struct['VM']):
2402 dom = xendom.get_vm_by_uuid(vtpm_struct['VM'])
2403 try:
2404 vtpm_ref = dom.create_vtpm(vtpm_struct)
2405 xendom.managed_config_save(dom)
2406 return xen_api_success(vtpm_ref)
2407 except XendError, exn:
2408 return xen_api_error(['INTERNAL_ERROR', str(exn)])
2409 else:
2410 return xen_api_error(['HANDLE_INVALID', 'VM', vtpm_struct['VM']])
2412 def VTPM_get_all(self, session):
2413 xendom = XendDomain.instance()
2414 vtpms = [d.get_vtpms() for d in XendDomain.instance().list('all')]
2415 vtpms = reduce(lambda x, y: x + y, vtpms)
2416 return xen_api_success(vtpms)
2418 def VTPM_get_runtime_properties(self, _, vtpm_ref):
2419 xendom = XendDomain.instance()
2420 dominfo = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
2421 device = dominfo.get_dev_config_by_uuid('vtpm', vtpm_ref)
2423 try:
2424 device_sxps = dominfo.getDeviceSxprs('vtpm')
2425 device_dict = dict(device_sxps[0][1])
2426 return xen_api_success(device_dict)
2427 except:
2428 return xen_api_success({})
2430 # Xen API: Class console
2431 # ----------------------------------------------------------------
2434 console_attr_ro = ['location', 'protocol', 'VM']
2435 console_attr_rw = ['other_config']
2436 console_funcs = [('create', 'console')]
2438 def console_get_all(self, session):
2439 xendom = XendDomain.instance()
2440 cons = [d.get_consoles() for d in XendDomain.instance().list('all')]
2441 cons = reduce(lambda x, y: x + y, cons)
2442 return xen_api_success(cons)
2444 def console_get_location(self, session, console_ref):
2445 xendom = XendDomain.instance()
2446 return xen_api_success(xendom.get_dev_property_by_uuid('console',
2447 console_ref,
2448 'location'))
2450 def console_get_protocol(self, session, console_ref):
2451 xendom = XendDomain.instance()
2452 return xen_api_success(xendom.get_dev_property_by_uuid('console',
2453 console_ref,
2454 'protocol'))
2456 def console_get_VM(self, session, console_ref):
2457 xendom = XendDomain.instance()
2458 vm = xendom.get_vm_with_dev_uuid('console', console_ref)
2459 return xen_api_success(vm.get_uuid())
2461 def console_get_other_config(self, session, console_ref):
2462 xendom = XendDomain.instance()
2463 return xen_api_success(xendom.get_dev_property_by_uuid('console',
2464 console_ref,
2465 'other_config'))
2467 # object methods
2468 def console_get_record(self, session, console_ref):
2469 xendom = XendDomain.instance()
2470 vm = xendom.get_vm_with_dev_uuid('console', console_ref)
2471 if not vm:
2472 return xen_api_error(['HANDLE_INVALID', 'console', console_ref])
2473 cfg = vm.get_dev_xenapi_config('console', console_ref)
2474 if not cfg:
2475 return xen_api_error(['HANDLE_INVALID', 'console', console_ref])
2477 valid_console_keys = self.console_attr_ro + self.console_attr_rw + \
2478 self.Base_attr_ro + self.Base_attr_rw
2480 return_cfg = {}
2481 for k in cfg.keys():
2482 if k in valid_console_keys:
2483 return_cfg[k] = cfg[k]
2485 return xen_api_success(return_cfg)
2487 def console_create(self, session, console_struct):
2488 xendom = XendDomain.instance()
2489 if not xendom.is_valid_vm(console_struct['VM']):
2490 return xen_api_error(['HANDLE_INVALID', 'VM',
2491 console_struct['VM']])
2493 dom = xendom.get_vm_by_uuid(console_struct['VM'])
2494 try:
2495 if 'protocol' not in console_struct:
2496 return xen_api_error(['CONSOLE_PROTOCOL_INVALID',
2497 'No protocol specified'])
2499 console_ref = dom.create_console(console_struct)
2500 xendom.managed_config_save(dom)
2501 return xen_api_success(console_ref)
2502 except XendError, exn:
2503 return xen_api_error(['INTERNAL_ERROR', str(exn)])
2505 def console_set_other_config(self, session, console_ref, other_config):
2506 xd = XendDomain.instance()
2507 vm = xd.get_vm_with_dev_uuid('console', console_ref)
2508 vm.set_console_other_config(console_ref, other_config)
2509 xd.managed_config_save(vm)
2510 return xen_api_success_void()
2512 # Xen API: Class SR
2513 # ----------------------------------------------------------------
2514 SR_attr_ro = ['VDIs',
2515 'PBDs',
2516 'virtual_allocation',
2517 'physical_utilisation',
2518 'physical_size',
2519 'type',
2520 'content_type']
2522 SR_attr_rw = ['name_label',
2523 'name_description']
2525 SR_attr_inst = ['physical_size',
2526 'type',
2527 'name_label',
2528 'name_description']
2530 SR_methods = []
2531 SR_funcs = [('get_by_name_label', 'Set(SR)'),
2532 ('get_by_uuid', 'SR')]
2534 # Class Functions
2535 def SR_get_all(self, session):
2536 return xen_api_success(XendNode.instance().get_all_sr_uuid())
2538 def SR_get_by_name_label(self, session, label):
2539 return xen_api_success(XendNode.instance().get_sr_by_name(label))
2541 def SR_get_supported_types(self, _):
2542 return xen_api_success(['local', 'qcow_file'])
2544 # Class Methods
2546 def SR_get_record(self, session, sr_ref):
2547 sr = XendNode.instance().get_sr(sr_ref)
2548 if sr:
2549 return xen_api_success(sr.get_record())
2550 return xen_api_error(['HANDLE_INVALID', 'SR', sr_ref])
2552 # Attribute acceess
2554 def _get_SR_func(self, sr_ref, func):
2555 return xen_api_success(getattr(XendNode.instance().get_sr(sr_ref),
2556 func)())
2558 def _get_SR_attr(self, sr_ref, attr):
2559 return xen_api_success(getattr(XendNode.instance().get_sr(sr_ref),
2560 attr))
2562 def SR_get_VDIs(self, _, ref):
2563 return self._get_SR_func(ref, 'list_images')
2565 def SR_get_PBDs(self, _, ref):
2566 return xen_api_success(XendPBD.get_by_SR(ref))
2568 def SR_get_virtual_allocation(self, _, ref):
2569 return self._get_SR_func(ref, 'virtual_allocation')
2571 def SR_get_physical_utilisation(self, _, ref):
2572 return self._get_SR_func(ref, 'physical_utilisation')
2574 def SR_get_physical_size(self, _, ref):
2575 return self._get_SR_attr(ref, 'physical_size')
2577 def SR_get_type(self, _, ref):
2578 return self._get_SR_attr(ref, 'type')
2580 def SR_get_content_type(self, _, ref):
2581 return self._get_SR_attr(ref, 'content_type')
2583 def SR_get_name_label(self, _, ref):
2584 return self._get_SR_attr(ref, 'name_label')
2586 def SR_get_name_description(self, _, ref):
2587 return self._get_SR_attr(ref, 'name_description')
2589 def SR_set_name_label(self, session, sr_ref, value):
2590 sr = XendNode.instance.get_sr(sr_ref)
2591 if sr:
2592 sr.name_label = value
2593 XendNode.instance().save()
2594 return xen_api_success_void()
2596 def SR_set_name_description(self, session, sr_ref, value):
2597 sr = XendNode.instance.get_sr(sr_ref)
2598 if sr:
2599 sr.name_description = value
2600 XendNode.instance().save()
2601 return xen_api_success_void()
2604 # Xen API: Class event
2605 # ----------------------------------------------------------------
2607 event_attr_ro = []
2608 event_attr_rw = []
2609 event_funcs = [('register', None),
2610 ('unregister', None),
2611 ('next', None)]
2613 def event_register(self, session, reg_classes):
2614 event_register(session, reg_classes)
2615 return xen_api_success_void()
2617 def event_unregister(self, session, unreg_classes):
2618 event_unregister(session, unreg_classes)
2619 return xen_api_success_void()
2621 def event_next(self, session):
2622 return event_next(session)
2624 # Xen API: Class debug
2625 # ----------------------------------------------------------------
2627 debug_methods = [('destroy', None),
2628 ('get_record', 'debug')]
2629 debug_funcs = [('wait', None),
2630 ('return_failure', None)]
2632 def debug_wait(self, session, wait_secs):
2633 import time
2634 prog_units = 100/float(wait_secs)
2635 for i in range(int(wait_secs)):
2636 XendTask.log_progress(prog_units * i, prog_units * (i + 1),
2637 time.sleep, 1)
2638 return xen_api_success_void()
2641 def debug_return_failure(self, session):
2642 return xen_api_error(['DEBUG_FAIL', session])
2644 def debug_create(self, session):
2645 debug_uuid = genuuid.createString()
2646 self._debug[debug_uuid] = None
2647 return xen_api_success(debug_uuid)
2649 def debug_destroy(self, session, debug_ref):
2650 del self._debug[debug_ref]
2651 return xen_api_success_void()
2653 def debug_get_record(self, session, debug_ref):
2654 return xen_api_success({'uuid': debug_ref})
2657 class XendAPIAsyncProxy:
2658 """ A redirector for Async.Class.function calls to XendAPI
2659 but wraps the call for use with the XendTaskManager.
2661 @ivar xenapi: Xen API instance
2662 @ivar method_map: Mapping from XMLRPC method name to callable objects.
2663 """
2665 method_prefix = 'Async.'
2667 def __init__(self, xenapi):
2668 """Initialises the Async Proxy by making a map of all
2669 implemented Xen API methods for use with XendTaskManager.
2671 @param xenapi: XendAPI instance
2672 """
2673 self.xenapi = xenapi
2674 self.method_map = {}
2675 for method_name in dir(self.xenapi):
2676 method = getattr(self.xenapi, method_name)
2677 if method_name[0] != '_' and hasattr(method, 'async') \
2678 and method.async == True:
2679 self.method_map[method.api] = method
2681 def _dispatch(self, method, args):
2682 """Overridden method so that SimpleXMLRPCServer will
2683 resolve methods through this method rather than through
2684 inspection.
2686 @param method: marshalled method name from XMLRPC.
2687 @param args: marshalled arguments from XMLRPC.
2688 """
2690 # Only deal with method names that start with "Async."
2691 if not method.startswith(self.method_prefix):
2692 return xen_api_error(['MESSAGE_METHOD_UNKNOWN', method])
2694 # Lookup synchronous version of the method
2695 synchronous_method_name = method[len(self.method_prefix):]
2696 if synchronous_method_name not in self.method_map:
2697 return xen_api_error(['MESSAGE_METHOD_UNKNOWN', method])
2699 method = self.method_map[synchronous_method_name]
2701 # Check that we've got enough arguments before issuing a task ID.
2702 needed = argcounts[method.api]
2703 if len(args) != needed:
2704 return xen_api_error(['MESSAGE_PARAMETER_COUNT_MISMATCH',
2705 self.method_prefix + method.api, needed,
2706 len(args)])
2708 # Validate the session before proceeding
2709 session = args[0]
2710 if not auth_manager().is_session_valid(session):
2711 return xen_api_error(['SESSION_INVALID', session])
2713 # create and execute the task, and return task_uuid
2714 return_type = getattr(method, 'return_type', None)
2715 task_uuid = XendTaskManager.create_task(method, args,
2716 synchronous_method_name,
2717 return_type,
2718 synchronous_method_name,
2719 session)
2720 return xen_api_success(task_uuid)