ia64/xen-unstable

view tools/python/xen/xend/XendAPI.py @ 14405:036e42d1c9bb

Added VM_metrics.get_all.

Signed-off-by: Tom Wilkie <tom.wilkie@gmail.com>
author Ewan Mellor <ewan@xensource.com>
date Wed Mar 14 21:04:04 2007 +0000 (2007-03-14)
parents 0c354aa0bb4a
children b39c0a79d4d5
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 string
21 import sys
22 import traceback
23 import threading
25 from xen.xend import XendDomain, XendDomainInfo, XendNode, XendDmesg
26 from xen.xend import XendLogging, XendTaskManager
28 from xen.xend.XendAPIVersion import *
29 from xen.xend.XendAuthSessions import instance as auth_manager
30 from xen.xend.XendError import *
31 from xen.xend.XendClient import ERROR_INVALID_DOMAIN
32 from xen.xend.XendLogging import log
33 from xen.xend.XendTask import XendTask
34 from xen.xend.XendVMMetrics import XendVMMetrics
36 from xen.xend.XendAPIConstants import *
37 from xen.util.xmlrpclib2 import stringify
39 AUTH_NONE = 'none'
40 AUTH_PAM = 'pam'
42 argcounts = {}
44 # ------------------------------------------
45 # Utility Methods for Xen API Implementation
46 # ------------------------------------------
48 def xen_api_success(value):
49 """Wraps a return value in XenAPI format."""
50 if value is None:
51 s = ''
52 else:
53 s = stringify(value)
54 return {"Status": "Success", "Value": s}
56 def xen_api_success_void():
57 """Return success, but caller expects no return value."""
58 return xen_api_success("")
60 def xen_api_error(error):
61 """Wraps an error value in XenAPI format."""
62 if type(error) == tuple:
63 error = list(error)
64 if type(error) != list:
65 error = [error]
66 if len(error) == 0:
67 error = ['INTERNAL_ERROR', 'Empty list given to xen_api_error']
69 return { "Status": "Failure",
70 "ErrorDescription": [str(x) for x in error] }
73 def xen_api_todo():
74 """Temporary method to make sure we track down all the TODOs"""
75 return {"Status": "Error", "ErrorDescription": XEND_ERROR_TODO}
77 # ---------------------------------------------------
78 # Python Method Decorators for input value validation
79 # ---------------------------------------------------
81 def trace(func, api_name = ''):
82 """Decorator to trace XMLRPC Xen API methods.
84 @param func: function with any parameters
85 @param api_name: name of the api call for debugging.
86 """
87 if hasattr(func, 'api'):
88 api_name = func.api
89 def trace_func(self, *args, **kwargs):
90 log.debug('%s: %s' % (api_name, args))
91 return func(self, *args, **kwargs)
92 trace_func.api = api_name
93 return trace_func
96 def catch_typeerror(func):
97 """Decorator to catch any TypeErrors and translate them into Xen-API
98 errors.
100 @param func: function with params: (self, ...)
101 @rtype: callable object
102 """
103 def f(self, *args, **kwargs):
104 try:
105 return func(self, *args, **kwargs)
106 except TypeError, exn:
107 #log.exception('catch_typeerror')
108 if hasattr(func, 'api') and func.api in argcounts:
109 # Assume that if the argument count was wrong and if the
110 # exception was thrown inside this file, then it is due to an
111 # invalid call from the client, otherwise it's an internal
112 # error (which will be handled further up).
113 expected = argcounts[func.api]
114 actual = len(args) + len(kwargs)
115 if expected != actual:
116 tb = sys.exc_info()[2]
117 try:
118 sourcefile = traceback.extract_tb(tb)[-1][0]
119 if sourcefile == inspect.getsourcefile(XendAPI):
120 return xen_api_error(
121 ['MESSAGE_PARAMETER_COUNT_MISMATCH',
122 func.api, expected, actual])
123 finally:
124 del tb
125 raise
127 return f
130 def session_required(func):
131 """Decorator to verify if session is valid before calling method.
133 @param func: function with params: (self, session, ...)
134 @rtype: callable object
135 """
136 def check_session(self, session, *args, **kwargs):
137 if auth_manager().is_session_valid(session):
138 return func(self, session, *args, **kwargs)
139 else:
140 return xen_api_error(['SESSION_INVALID', session])
142 return check_session
145 def _is_valid_ref(ref, validator):
146 return type(ref) == str and validator(ref)
148 def _check_ref(validator, clas, func, api, session, ref, *args, **kwargs):
149 if _is_valid_ref(ref, validator):
150 return func(api, session, ref, *args, **kwargs)
151 else:
152 return xen_api_error(['HANDLE_INVALID', clas, ref])
155 def valid_host(func):
156 """Decorator to verify if host_ref is valid before calling method.
158 @param func: function with params: (self, session, host_ref, ...)
159 @rtype: callable object
160 """
161 return lambda *args, **kwargs: \
162 _check_ref(XendNode.instance().is_valid_host,
163 'host', func, *args, **kwargs)
165 def valid_host_metrics(func):
166 """Decorator to verify if host_metrics_ref is valid before calling
167 method.
169 @param func: function with params: (self, session, host_metrics_ref)
170 @rtype: callable object
171 """
172 return lambda *args, **kwargs: \
173 _check_ref(lambda r: r == XendNode.instance().host_metrics_uuid,
174 'host_metrics', func, *args, **kwargs)
176 def valid_host_cpu(func):
177 """Decorator to verify if host_cpu_ref is valid before calling method.
179 @param func: function with params: (self, session, host_cpu_ref, ...)
180 @rtype: callable object
181 """
182 return lambda *args, **kwargs: \
183 _check_ref(XendNode.instance().is_valid_cpu,
184 'host_cpu', func, *args, **kwargs)
186 def valid_vm(func):
187 """Decorator to verify if vm_ref is valid before calling method.
189 @param func: function with params: (self, session, vm_ref, ...)
190 @rtype: callable object
191 """
192 return lambda *args, **kwargs: \
193 _check_ref(XendDomain.instance().is_valid_vm,
194 'VM', func, *args, **kwargs)
196 def valid_vm_metrics(func):
197 """Decorator to verify if vm_metrics_ref is valid before calling method.
199 @param func: function with params: (self, session, vm_metrics_ref, ...)
200 @rtype: callable object
201 """
202 return lambda *args, **kwargs: \
203 _check_ref(XendVMMetrics.is_valid_vm_metrics,
204 'VM_metrics', func, *args, **kwargs)
206 def valid_network(func):
207 """Decorator to verify if network_ref is valid before calling method.
209 @param func: function with params: (self, session, network_ref, ...)
210 @rtype: callable object
211 """
212 return lambda *args, **kwargs: \
213 _check_ref(XendNode.instance().is_valid_network,
214 'network', func, *args, **kwargs)
216 def valid_vbd(func):
217 """Decorator to verify if vbd_ref is valid before calling method.
219 @param func: function with params: (self, session, vbd_ref, ...)
220 @rtype: callable object
221 """
222 return lambda *args, **kwargs: \
223 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vbd', r),
224 'VBD', func, *args, **kwargs)
226 def valid_vbd_metrics(func):
227 """Decorator to verify if ref is valid before calling method.
229 @param func: function with params: (self, session, ref, ...)
230 @rtype: callable object
231 """
232 return lambda *args, **kwargs: \
233 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vbd', r),
234 'VBD_metrics', func, *args, **kwargs)
236 def valid_vif(func):
237 """Decorator to verify if vif_ref is valid before calling method.
239 @param func: function with params: (self, session, vif_ref, ...)
240 @rtype: callable object
241 """
242 return lambda *args, **kwargs: \
243 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vif', r),
244 'VIF', func, *args, **kwargs)
246 def valid_vif_metrics(func):
247 """Decorator to verify if ref is valid before calling method.
249 @param func: function with params: (self, session, ref, ...)
250 @rtype: callable object
251 """
252 return lambda *args, **kwargs: \
253 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vif', r),
254 'VIF_metrics', func, *args, **kwargs)
256 def valid_vdi(func):
257 """Decorator to verify if vdi_ref is valid before calling method.
259 @param func: function with params: (self, session, vdi_ref, ...)
260 @rtype: callable object
261 """
262 return lambda *args, **kwargs: \
263 _check_ref(XendNode.instance().is_valid_vdi,
264 'VDI', func, *args, **kwargs)
266 def valid_vtpm(func):
267 """Decorator to verify if vtpm_ref is valid before calling method.
269 @param func: function with params: (self, session, vtpm_ref, ...)
270 @rtype: callable object
271 """
272 return lambda *args, **kwargs: \
273 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vtpm', r),
274 'VTPM', func, *args, **kwargs)
277 def valid_console(func):
278 """Decorator to verify if console_ref is valid before calling method.
280 @param func: function with params: (self, session, console_ref, ...)
281 @rtype: callable object
282 """
283 return lambda *args, **kwargs: \
284 _check_ref(lambda r: XendDomain.instance().is_valid_dev('console',
285 r),
286 'console', func, *args, **kwargs)
288 def valid_sr(func):
289 """Decorator to verify if sr_ref is valid before calling method.
291 @param func: function with params: (self, session, sr_ref, ...)
292 @rtype: callable object
293 """
294 return lambda *args, **kwargs: \
295 _check_ref(lambda r: XendNode.instance().is_valid_sr,
296 'SR', func, *args, **kwargs)
298 def valid_pif(func):
299 """Decorator to verify if pif_ref is valid before calling
300 method.
302 @param func: function with params: (self, session, pif_ref)
303 @rtype: callable object
304 """
305 return lambda *args, **kwargs: \
306 _check_ref(lambda r: r in XendNode.instance().pifs,
307 'PIF', func, *args, **kwargs)
309 def valid_pif_metrics(func):
310 """Decorator to verify if pif_metrics_ref is valid before calling
311 method.
313 @param func: function with params: (self, session, pif_metrics_ref)
314 @rtype: callable object
315 """
316 return lambda *args, **kwargs: \
317 _check_ref(lambda r: r in XendNode.instance().pif_metrics,
318 'PIF_metrics', func, *args, **kwargs)
320 def valid_task(func):
321 """Decorator to verify if task_ref is valid before calling
322 method.
324 @param func: function with params: (self, session, task_ref)
325 @rtype: callable object
326 """
327 return lambda *args, **kwargs: \
328 _check_ref(XendTaskManager.get_task,
329 'task', func, *args, **kwargs)
331 def valid_debug(func):
332 """Decorator to verify if task_ref is valid before calling
333 method.
335 @param func: function with params: (self, session, task_ref)
336 @rtype: callable object
337 """
338 return lambda *args, **kwargs: \
339 _check_ref(lambda r: r in XendAPI._debug,
340 'debug', func, *args, **kwargs)
342 # -----------------------------
343 # Bridge to Legacy XM API calls
344 # -----------------------------
346 def do_vm_func(fn_name, vm_ref, *args, **kwargs):
347 """Helper wrapper func to abstract away from repetitive code.
349 @param fn_name: function name for XendDomain instance
350 @type fn_name: string
351 @param vm_ref: vm_ref
352 @type vm_ref: string
353 @param *args: more arguments
354 @type *args: tuple
355 """
356 try:
357 xendom = XendDomain.instance()
358 fn = getattr(xendom, fn_name)
359 xendom.do_legacy_api_with_uuid(fn, vm_ref, *args, **kwargs)
360 return xen_api_success_void()
361 except VMBadState, exn:
362 return xen_api_error(['VM_BAD_POWER_STATE', vm_ref, exn.expected,
363 exn.actual])
366 class XendAPI(object):
367 """Implementation of the Xen-API in Xend. Expects to be
368 used via XMLRPCServer.
370 All methods that need a valid session are marked with
371 a L{session_required} decorator that will
372 transparently perform the required session authentication.
374 We need to support Python <2.4, so we use the old decorator syntax.
376 All XMLRPC accessible methods require an 'api' attribute and
377 is set to the XMLRPC function name which the method implements.
378 """
380 __decorated__ = False
381 __init_lock__ = threading.Lock()
382 _debug = {}
384 def __new__(cls, *args, **kwds):
385 """ Override __new__ to decorate the class only once.
387 Lock to make sure the classes are not decorated twice.
388 """
389 cls.__init_lock__.acquire()
390 try:
391 if not cls.__decorated__:
392 cls._decorate()
393 cls.__decorated__ = True
395 return object.__new__(cls, *args, **kwds)
396 finally:
397 cls.__init_lock__.release()
399 def _decorate(cls):
400 """ Decorate all the object methods to have validators
401 and appropriate function attributes.
403 This should only be executed once for the duration of the
404 server.
405 """
406 global_validators = [session_required, catch_typeerror]
407 classes = {
408 'session' : None,
409 'host' : valid_host,
410 'host_cpu' : valid_host_cpu,
411 'host_metrics' : valid_host_metrics,
412 'network' : valid_network,
413 'VM' : valid_vm,
414 'VM_metrics' : valid_vm_metrics,
415 'VBD' : valid_vbd,
416 'VBD_metrics' : valid_vbd_metrics,
417 'VIF' : valid_vif,
418 'VIF_metrics' : valid_vif_metrics,
419 'VDI' : valid_vdi,
420 'VTPM' : valid_vtpm,
421 'console' : valid_console,
422 'SR' : valid_sr,
423 'PIF' : valid_pif,
424 'PIF_metrics' : valid_pif_metrics,
425 'task' : valid_task,
426 'debug' : valid_debug,
427 }
429 # Cheat methods
430 # -------------
431 # Methods that have a trivial implementation for all classes.
432 # 1. get_by_uuid == getting by ref, so just return uuid for
433 # all get_by_uuid() methods.
435 for api_cls in classes.keys():
436 if api_cls == 'session':
437 continue
439 get_by_uuid = '%s_get_by_uuid' % api_cls
440 get_uuid = '%s_get_uuid' % api_cls
441 def _get_by_uuid(_1, _2, ref):
442 return xen_api_success(ref)
444 def _get_uuid(_1, _2, ref):
445 return xen_api_success(ref)
447 setattr(cls, get_by_uuid, _get_by_uuid)
448 setattr(cls, get_uuid, _get_uuid)
450 # Wrapping validators around XMLRPC calls
451 # ---------------------------------------
453 for api_cls, validator in classes.items():
454 def doit(n, takes_instance, async_support = False,
455 return_type = None):
456 n_ = n.replace('.', '_')
457 try:
458 f = getattr(cls, n_)
459 argcounts[n] = f.func_code.co_argcount - 1
461 validators = takes_instance and validator and \
462 [validator] or []
464 validators += global_validators
465 for v in validators:
466 f = v(f)
467 f.api = n
468 f.async = async_support
469 if return_type:
470 f.return_type = return_type
472 setattr(cls, n_, f)
473 except AttributeError:
474 log.warn("API call: %s not found" % n)
477 ro_attrs = getattr(cls, '%s_attr_ro' % api_cls, [])
478 rw_attrs = getattr(cls, '%s_attr_rw' % api_cls, [])
479 methods = getattr(cls, '%s_methods' % api_cls, [])
480 funcs = getattr(cls, '%s_funcs' % api_cls, [])
482 # wrap validators around readable class attributes
483 for attr_name in ro_attrs + rw_attrs + cls.Base_attr_ro:
484 doit('%s.get_%s' % (api_cls, attr_name), True,
485 async_support = False)
487 # wrap validators around writable class attrributes
488 for attr_name in rw_attrs + cls.Base_attr_rw:
489 doit('%s.set_%s' % (api_cls, attr_name), True,
490 async_support = False)
492 # wrap validators around methods
493 for method_name, return_type in methods + cls.Base_methods:
494 doit('%s.%s' % (api_cls, method_name), True,
495 async_support = True)
497 # wrap validators around class functions
498 for func_name, return_type in funcs + cls.Base_funcs:
499 doit('%s.%s' % (api_cls, func_name), False, async_support = True,
500 return_type = return_type)
502 _decorate = classmethod(_decorate)
504 def __init__(self, auth):
505 self.auth = auth
507 Base_attr_ro = ['uuid']
508 Base_attr_rw = []
509 Base_methods = [('destroy', None), ('get_record', 'Struct')]
510 Base_funcs = [('get_all', 'Set'), ('get_by_uuid', None)]
512 # Xen API: Class Session
513 # ----------------------------------------------------------------
514 # NOTE: Left unwrapped by __init__
516 session_attr_ro = ['this_host', 'this_user']
517 session_methods = [('logout', None)]
519 def session_login_with_password(self, *args):
520 if len(args) != 2:
521 return xen_api_error(
522 ['MESSAGE_PARAMETER_COUNT_MISMATCH',
523 'session.login_with_password', 2, len(args)])
524 username = args[0]
525 password = args[1]
526 try:
527 session = (self.auth == AUTH_NONE and
528 auth_manager().login_unconditionally(username) or
529 auth_manager().login_with_password(username, password))
530 return xen_api_success(session)
531 except XendError, e:
532 return xen_api_error(['SESSION_AUTHENTICATION_FAILED'])
533 session_login_with_password.api = 'session.login_with_password'
535 # object methods
536 def session_logout(self, session):
537 auth_manager().logout(session)
538 return xen_api_success_void()
539 def session_get_record(self, session):
540 record = {'uuid' : session,
541 'this_host': XendNode.instance().uuid,
542 'this_user': auth_manager().get_user(session)}
543 return xen_api_success(record)
545 def session_get_uuid(self, session):
546 return xen_api_success(session)
548 def session_get_by_uuid(self, session):
549 return xen_api_success(session)
551 # attributes (ro)
552 def session_get_this_host(self, session):
553 return xen_api_success(XendNode.instance().uuid)
554 def session_get_this_user(self, session):
555 user = auth_manager().get_user(session)
556 if user:
557 return xen_api_success(user)
558 return xen_api_error(['SESSION_INVALID', session])
561 # Xen API: Class User
562 # ----------------------------------------------------------------
563 # TODO: NOT IMPLEMENTED YET
565 # Xen API: Class Tasks
566 # ----------------------------------------------------------------
568 task_attr_ro = ['name_label',
569 'name_description',
570 'status',
571 'progress',
572 'type',
573 'result',
574 'error_code',
575 'error_info',
576 'allowed_operations',
577 'session'
578 ]
580 task_attr_rw = []
582 task_funcs = [('get_by_name_label', 'Set(task)'),
583 ('cancel', None)]
585 def task_get_name_label(self, session, task_ref):
586 task = XendTaskManager.get_task(task_ref)
587 return xen_api_success(task.name_label)
589 def task_get_name_description(self, session, task_ref):
590 task = XendTaskManager.get_task(task_ref)
591 return xen_api_success(task.name_description)
593 def task_get_status(self, session, task_ref):
594 task = XendTaskManager.get_task(task_ref)
595 return xen_api_success(task.get_status())
597 def task_get_progress(self, session, task_ref):
598 task = XendTaskManager.get_task(task_ref)
599 return xen_api_success(task.progress)
601 def task_get_type(self, session, task_ref):
602 task = XendTaskManager.get_task(task_ref)
603 return xen_api_success(task.type)
605 def task_get_result(self, session, task_ref):
606 task = XendTaskManager.get_task(task_ref)
607 return xen_api_success(task.result)
609 def task_get_error_code(self, session, task_ref):
610 task = XendTaskManager.get_task(task_ref)
611 return xen_api_success(task.error_code)
613 def task_get_error_info(self, session, task_ref):
614 task = XendTaskManager.get_task(task_ref)
615 return xen_api_success(task.error_info)
617 def task_get_allowed_operations(self, session, task_ref):
618 return xen_api_success({})
620 def task_get_session(self, session, task_ref):
621 task = XendTaskManager.get_task(task_ref)
622 return xen_api_success(task.session)
624 def task_get_all(self, session):
625 tasks = XendTaskManager.get_all_tasks()
626 return xen_api_success(tasks)
628 def task_get_record(self, session, task_ref):
629 task = XendTaskManager.get_task(task_ref)
630 return xen_api_success(task.get_record())
632 def task_cancel(self, session, task_ref):
633 return xen_api_error('OPERATION_NOT_ALLOWED')
635 def task_get_by_name_label(self, session, name):
636 return xen_api_success(XendTaskManager.get_task_by_name(name))
638 # Xen API: Class host
639 # ----------------------------------------------------------------
641 host_attr_ro = ['software_version',
642 'resident_VMs',
643 'host_CPUs',
644 'cpu_configuration',
645 'metrics',
646 'capabilities',
647 'supported_bootloaders',
648 'API_version_major',
649 'API_version_minor',
650 'API_version_vendor',
651 'API_version_vendor_implementation']
653 host_attr_rw = ['name_label',
654 'sched_policy',
655 'name_description',
656 'other_config']
658 host_methods = [('disable', None),
659 ('enable', None),
660 ('reboot', None),
661 ('shutdown', None),
662 ('add_to_other_config', None),
663 ('remove_from_other_config', None),
664 ('dmesg', 'String')]
666 host_funcs = [('get_by_name_label', 'Set(host)')]
668 # attributes
669 def host_get_name_label(self, session, host_ref):
670 return xen_api_success(XendNode.instance().name)
671 def host_set_name_label(self, session, host_ref, new_name):
672 XendNode.instance().set_name(new_name)
673 return xen_api_success_void()
674 def host_get_name_description(self, session, host_ref):
675 return xen_api_success(XendNode.instance().description)
676 def host_set_name_description(self, session, host_ref, new_desc):
677 XendNode.instance().set_description(new_desc)
678 return xen_api_success_void()
679 def host_get_other_config(self, session, host_ref):
680 return xen_api_success(XendNode.instance().other_config)
681 def host_set_other_config(self, session, host_ref, other_config):
682 node = XendNode.instance()
683 node.other_config = dict(other_config)
684 node.save()
685 return xen_api_success_void()
686 def host_add_to_other_config(self, session, host_ref, key, value):
687 node = XendNode.instance()
688 node.other_config[key] = value
689 node.save()
690 return xen_api_success_void()
691 def host_remove_from_other_config(self, session, host_ref, key):
692 node = XendNode.instance()
693 if key in node.other_config:
694 del node.other_config[key]
695 node.save()
696 return xen_api_success_void()
697 def host_get_API_version_major(self, _, ref):
698 return xen_api_success(XEN_API_VERSION_MAJOR)
699 def host_get_API_version_minor(self, _, ref):
700 return xen_api_success(XEN_API_VERSION_MINOR)
701 def host_get_API_version_vendor(self, _, ref):
702 return xen_api_success(XEN_API_VERSION_VENDOR)
703 def host_get_API_version_vendor_implementation(self, _, ref):
704 return xen_api_success(XEN_API_VERSION_VENDOR_IMPLEMENTATION)
705 def host_get_software_version(self, session, host_ref):
706 return xen_api_success(XendNode.instance().xen_version())
707 def host_get_resident_VMs(self, session, host_ref):
708 return xen_api_success(XendDomain.instance().get_domain_refs())
709 def host_get_host_CPUs(self, session, host_ref):
710 return xen_api_success(XendNode.instance().get_host_cpu_refs())
711 def host_get_metrics(self, _, ref):
712 return xen_api_success(XendNode.instance().host_metrics_uuid)
713 def host_get_capabilities(self, session, host_ref):
714 return xen_api_success(XendNode.instance().get_capabilities())
715 def host_get_supported_bootloaders(self, session, host_ref):
716 return xen_api_success(['pygrub'])
717 def host_get_sched_policy(self, _, host_ref):
718 return xen_api_success(XendNode.instance().get_vcpus_policy())
719 def host_set_sched_policy(self, _, host_ref, policy):
720 return xen_api_todo()
721 def host_get_cpu_configuration(self, _, host_ref):
722 return xen_api_success(XendNode.instance().get_cpu_configuration())
724 # object methods
725 def host_disable(self, session, host_ref):
726 XendDomain.instance().set_allow_new_domains(False)
727 return xen_api_success_void()
728 def host_enable(self, session, host_ref):
729 XendDomain.instance().set_allow_new_domains(True)
730 return xen_api_success_void()
731 def host_reboot(self, session, host_ref):
732 if not XendDomain.instance().allow_new_domains():
733 return xen_api_error(XEND_ERROR_HOST_RUNNING)
734 return xen_api_error(XEND_ERROR_UNSUPPORTED)
735 def host_shutdown(self, session, host_ref):
736 if not XendDomain.instance().allow_new_domains():
737 return xen_api_error(XEND_ERROR_HOST_RUNNING)
738 return xen_api_error(XEND_ERROR_UNSUPPORTED)
740 def host_dmesg(self, session, host_ref):
741 return xen_api_success(XendDmesg.instance().info())
743 def host_get_record(self, session, host_ref):
744 node = XendNode.instance()
745 dom = XendDomain.instance()
746 record = {'uuid': node.uuid,
747 'name_label': node.name,
748 'name_description': '',
749 'API_version_major': XEN_API_VERSION_MAJOR,
750 'API_version_minor': XEN_API_VERSION_MINOR,
751 'API_version_vendor': XEN_API_VERSION_VENDOR,
752 'API_version_vendor_implementation':
753 XEN_API_VERSION_VENDOR_IMPLEMENTATION,
754 'software_version': node.xen_version(),
755 'other_config': node.other_config,
756 'resident_VMs': dom.get_domain_refs(),
757 'host_CPUs': node.get_host_cpu_refs(),
758 'cpu_configuration': node.get_cpu_configuration(),
759 'metrics': node.host_metrics_uuid,
760 'capabilities': node.get_capabilities(),
761 'supported_bootloaders': 'pygrub',
762 'sched_policy': node.get_vcpus_policy()}
763 return xen_api_success(record)
765 # class methods
766 def host_get_all(self, session):
767 return xen_api_success((XendNode.instance().uuid,))
768 def host_get_by_name_label(self, session, name):
769 if XendNode.instance().name == name:
770 return xen_api_success((XendNode.instance().uuid,))
771 return xen_api_success([])
774 # Xen API: Class host_CPU
775 # ----------------------------------------------------------------
777 host_cpu_attr_ro = ['host',
778 'number',
779 'vendor',
780 'speed',
781 'modelname',
782 'stepping',
783 'flags',
784 'utilisation',
785 'features']
787 # attributes
788 def _host_cpu_get(self, ref, field):
789 return xen_api_success(
790 XendNode.instance().get_host_cpu_field(ref, field))
792 def host_cpu_get_host(self, _, ref):
793 return xen_api_success(XendNode.instance().uuid)
794 def host_cpu_get_features(self, _, ref):
795 return self._host_cpu_get(ref, 'features')
796 def host_cpu_get_number(self, _, ref):
797 return self._host_cpu_get(ref, 'number')
798 def host_cpu_get_vendor(self, _, ref):
799 return self._host_cpu_get(ref, 'vendor')
800 def host_cpu_get_speed(self, _, ref):
801 return self._host_cpu_get(ref, 'speed')
802 def host_cpu_get_modelname(self, _, ref):
803 return self._host_cpu_get(ref, 'modelname')
804 def host_cpu_get_stepping(self, _, ref):
805 return self._host_cpu_get(ref, 'stepping')
806 def host_cpu_get_flags(self, _, ref):
807 return self._host_cpu_get(ref, 'flags')
808 def host_cpu_get_utilisation(self, _, ref):
809 return xen_api_success(XendNode.instance().get_host_cpu_load(ref))
811 # object methods
812 def host_cpu_get_record(self, _, ref):
813 node = XendNode.instance()
814 record = dict([(f, node.get_host_cpu_field(ref, f))
815 for f in self.host_cpu_attr_ro
816 if f not in ['uuid', 'host', 'utilisation']])
817 record['uuid'] = ref
818 record['host'] = node.uuid
819 record['utilisation'] = node.get_host_cpu_load(ref)
820 return xen_api_success(record)
822 # class methods
823 def host_cpu_get_all(self, session):
824 return xen_api_success(XendNode.instance().get_host_cpu_refs())
827 # Xen API: Class host_metrics
828 # ----------------------------------------------------------------
830 host_metrics_attr_ro = ['memory_total',
831 'memory_free']
832 host_metrics_attr_rw = []
833 host_metrics_methods = []
835 def host_metrics_get_all(self, _):
836 return xen_api_success([XendNode.instance().host_metrics_uuid])
838 def _host_metrics_get(self, ref, f):
839 return xen_api_success(getattr(node, f)())
841 def host_metrics_get_record(self, _, ref):
842 return xen_api_success({
843 'uuid' : ref,
844 'memory_total' : self._host_metrics_get_memory_total(),
845 'memory_free' : self._host_metrics_get_memory_free(),
846 })
848 def host_metrics_get_memory_total(self, _, ref):
849 return xen_api_success(self._host_metrics_get_memory_total())
851 def host_metrics_get_memory_free(self, _, ref):
852 return xen_api_success(self._host_metrics_get_memory_free())
854 def _host_metrics_get_memory_total(self):
855 node = XendNode.instance()
856 return node.xc.physinfo()['total_memory'] * 1024
858 def _host_metrics_get_memory_free(self):
859 node = XendNode.instance()
860 return node.xc.physinfo()['free_memory'] * 1024
863 # Xen API: Class network
864 # ----------------------------------------------------------------
866 network_attr_ro = ['VIFs', 'PIFs']
867 network_attr_rw = ['name_label',
868 'name_description']
870 network_funcs = [('create', 'network')]
872 def network_create(self, _, name_label, name_description):
873 return xen_api_success(
874 XendNode.instance().network_create(name_label, name_description))
876 def network_destroy(self, _, ref):
877 return xen_api_success(XendNode.instance().network_destroy(ref))
879 def _get_network(self, ref):
880 return XendNode.instance().get_network(ref)
882 def network_get_all(self, _):
883 return xen_api_success(XendNode.instance().get_network_refs())
885 def network_get_record(self, _, ref):
886 return xen_api_success(
887 XendNode.instance().get_network(ref).get_record())
889 def network_get_name_label(self, _, ref):
890 return xen_api_success(self._get_network(ref).name_label)
892 def network_get_name_description(self, _, ref):
893 return xen_api_success(self._get_network(ref).name_description)
895 def network_get_VIFs(self, _, ref):
896 return xen_api_success(self._get_network(ref).get_VIF_UUIDs())
898 def network_get_PIFs(self, session, ref):
899 return xen_api_success(self._get_network(ref).get_PIF_UUIDs())
901 def network_set_name_label(self, _, ref, val):
902 return xen_api_success(self._get_network(ref).set_name_label(val))
904 def network_set_name_description(self, _, ref, val):
905 return xen_api_success(self._get_network(ref).set_name_description(val))
907 # Xen API: Class PIF
908 # ----------------------------------------------------------------
910 PIF_attr_ro = ['metrics']
911 PIF_attr_rw = ['device',
912 'network',
913 'host',
914 'MAC',
915 'MTU',
916 'VLAN']
918 PIF_attr_inst = PIF_attr_rw
920 PIF_methods = [('create_VLAN', 'int')]
922 def _get_PIF(self, ref):
923 return XendNode.instance().pifs[ref]
925 def PIF_destroy(self, _, ref):
926 try:
927 return xen_api_success(XendNode.instance().PIF_destroy(ref))
928 except PIFIsPhysical, exn:
929 return xen_api_error(['PIF_IS_PHYSICAL', ref])
931 # object methods
932 def PIF_get_record(self, _, ref):
933 return xen_api_success(self._get_PIF(ref).get_record())
935 def PIF_get_all(self, _):
936 return xen_api_success(XendNode.instance().pifs.keys())
938 def PIF_get_metrics(self, _, ref):
939 return xen_api_success(self._get_PIF(ref).metrics.uuid)
941 def PIF_get_device(self, _, ref):
942 return xen_api_success(self._get_PIF(ref).device)
944 def PIF_get_network(self, _, ref):
945 return xen_api_success(self._get_PIF(ref).network.uuid)
947 def PIF_get_host(self, _, ref):
948 return xen_api_success(self._get_PIF(ref).host.uuid)
950 def PIF_get_MAC(self, _, ref):
951 return xen_api_success(self._get_PIF(ref).mac)
953 def PIF_get_MTU(self, _, ref):
954 return xen_api_success(self._get_PIF(ref).mtu)
956 def PIF_get_VLAN(self, _, ref):
957 return xen_api_success(self._get_PIF(ref).vlan)
959 def PIF_set_device(self, _, ref, device):
960 return xen_api_success(self._get_PIF(ref).set_device(device))
962 def PIF_set_MAC(self, _, ref, mac):
963 return xen_api_success(self._get_PIF(ref).set_mac(mac))
965 def PIF_set_MTU(self, _, ref, mtu):
966 return xen_api_success(self._get_PIF(ref).set_mtu(mtu))
968 def PIF_create_VLAN(self, _, ref, network, vlan):
969 try:
970 vlan = int(vlan)
971 except:
972 return xen_api_error(['VLAN_TAG_INVALID', vlan])
974 try:
975 node = XendNode.instance()
977 if _is_valid_ref(network, node.is_valid_network):
978 return xen_api_success(
979 node.PIF_create_VLAN(ref, network, vlan))
980 else:
981 return xen_api_error(['HANDLE_INVALID', 'network', network])
982 except NetworkAlreadyConnected, exn:
983 return xen_api_error(['NETWORK_ALREADY_CONNECTED',
984 network, exn.pif_uuid])
985 except VLANTagInvalid:
986 return xen_api_error(['VLAN_TAG_INVALID', vlan])
989 # Xen API: Class PIF_metrics
990 # ----------------------------------------------------------------
992 PIF_metrics_attr_ro = ['io_read_kbs',
993 'io_write_kbs']
994 PIF_metrics_attr_rw = []
995 PIF_methods = []
997 def PIF_metrics_get_all(self, _):
998 return xen_api_success(XendNode.instance().pif_metrics.keys())
1000 def _PIF_metrics_get(self, ref):
1001 return XendNode.instance().pif_metrics[ref]
1003 def PIF_metrics_get_record(self, _, ref):
1004 return xen_api_success(self._PIF_metrics_get(ref).get_record())
1006 def PIF_metrics_get_io_read_kbs(self, _, ref):
1007 return xen_api_success(self._PIF_metrics_get(ref).get_io_read_kbs())
1009 def PIF_metrics_get_io_write_kbs(self, _, ref):
1010 return xen_api_success(self._PIF_metrics_get(ref).get_io_write_kbs())
1013 # Xen API: Class VM
1014 # ----------------------------------------------------------------
1016 VM_attr_ro = ['power_state',
1017 'resident_on',
1018 'memory_static_max',
1019 'memory_static_min',
1020 'VCPUs_number',
1021 'consoles',
1022 'VIFs',
1023 'VBDs',
1024 'VTPMs',
1025 'tools_version',
1026 'domid',
1027 'is_control_domain',
1028 'metrics'
1031 VM_attr_rw = ['name_label',
1032 'name_description',
1033 'user_version',
1034 'is_a_template',
1035 'auto_power_on',
1036 'memory_dynamic_max',
1037 'memory_dynamic_min',
1038 'VCPUs_params',
1039 'actions_after_shutdown',
1040 'actions_after_reboot',
1041 'actions_after_suspend',
1042 'actions_after_crash',
1043 'PV_bootloader',
1044 'PV_kernel',
1045 'PV_ramdisk',
1046 'PV_args',
1047 'PV_bootloader_args',
1048 'HVM_boot_policy',
1049 'HVM_boot_params',
1050 'platform',
1051 'PCI_bus',
1052 'other_config']
1054 VM_methods = [('clone', 'VM'),
1055 ('start', None),
1056 ('pause', None),
1057 ('unpause', None),
1058 ('clean_shutdown', None),
1059 ('clean_reboot', None),
1060 ('hard_shutdown', None),
1061 ('hard_reboot', None),
1062 ('suspend', None),
1063 ('resume', None),
1064 ('add_to_HVM_boot_params', None),
1065 ('remove_from_HVM_boot_params', None),
1066 ('add_to_VCPUs_params', None),
1067 ('remove_from_VCPUs_params', None),
1068 ('add_to_platform', None),
1069 ('remove_from_platform', None),
1070 ('add_to_other_config', None),
1071 ('remove_from_other_config', None)]
1073 VM_funcs = [('create', 'VM'),
1074 ('get_by_name_label', 'Set(VM)')]
1076 # parameters required for _create()
1077 VM_attr_inst = [
1078 'name_label',
1079 'name_description',
1080 'user_version',
1081 'is_a_template',
1082 'memory_static_max',
1083 'memory_dynamic_max',
1084 'memory_dynamic_min',
1085 'memory_static_min',
1086 'VCPUs_params',
1087 'actions_after_shutdown',
1088 'actions_after_reboot',
1089 'actions_after_suspend',
1090 'actions_after_crash',
1091 'PV_bootloader',
1092 'PV_kernel',
1093 'PV_ramdisk',
1094 'PV_args',
1095 'PV_bootloader_args',
1096 'HVM_boot_policy',
1097 'HVM_boot_params',
1098 'platform',
1099 'PCI_bus',
1100 'other_config']
1102 def VM_get(self, name, session, vm_ref):
1103 return xen_api_success(
1104 XendDomain.instance().get_vm_by_uuid(vm_ref).info[name])
1106 def VM_set(self, name, session, vm_ref, value):
1107 xd = XendDomain.instance()
1108 dominfo = xd.get_vm_by_uuid(vm_ref)
1109 dominfo.info[name] = value
1110 return self._VM_save(dominfo)
1112 def _VM_save(self, dominfo):
1113 XendDomain.instance().managed_config_save(dominfo)
1114 return xen_api_success_void()
1116 # attributes (ro)
1117 def VM_get_power_state(self, session, vm_ref):
1118 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1119 return xen_api_success(dom.get_power_state())
1121 def VM_get_resident_on(self, session, vm_ref):
1122 return xen_api_success(XendNode.instance().uuid)
1124 def VM_get_memory_static_max(self, session, vm_ref):
1125 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1126 return xen_api_success(dom.get_memory_static_max())
1128 def VM_get_memory_static_min(self, session, vm_ref):
1129 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1130 return xen_api_success(dom.get_memory_static_min())
1132 def VM_get_VCPUs_number(self, session, vm_ref):
1133 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1134 return xen_api_success(dom.getVCpuCount())
1136 def VM_get_VIFs(self, session, vm_ref):
1137 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1138 return xen_api_success(dom.get_vifs())
1140 def VM_get_VBDs(self, session, vm_ref):
1141 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1142 return xen_api_success(dom.get_vbds())
1144 def VM_get_VTPMs(self, session, vm_ref):
1145 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1146 return xen_api_success(dom.get_vtpms())
1148 def VM_get_consoles(self, session, vm_ref):
1149 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1150 return xen_api_success(dom.get_consoles())
1152 def VM_get_tools_version(self, session, vm_ref):
1153 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1154 return dom.get_tools_version()
1156 def VM_get_metrics(self, _, vm_ref):
1157 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1158 return xen_api_success(dom.get_metrics())
1160 # attributes (rw)
1161 def VM_get_name_label(self, session, vm_ref):
1162 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1163 return xen_api_success(dom.getName())
1165 def VM_get_name_description(self, session, vm_ref):
1166 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1167 return xen_api_todo()
1169 def VM_get_user_version(self, session, vm_ref):
1170 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1171 return xen_api_todo()
1173 def VM_get_is_a_template(self, session, vm_ref):
1174 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1175 return xen_api_todo()
1177 def VM_get_memory_dynamic_max(self, session, vm_ref):
1178 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1179 return xen_api_success(dom.get_memory_dynamic_max())
1181 def VM_get_memory_dynamic_min(self, session, vm_ref):
1182 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1183 return xen_api_success(dom.get_memory_dynamic_min())
1185 def VM_get_VCPUs_params(self, session, vm_ref):
1186 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1187 return xen_api_success(dom.get_vcpus_params())
1189 def VM_get_actions_after_shutdown(self, session, vm_ref):
1190 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1191 return xen_api_success(dom.get_on_shutdown())
1193 def VM_get_actions_after_reboot(self, session, vm_ref):
1194 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1195 return xen_api_success(dom.get_on_reboot())
1197 def VM_get_actions_after_suspend(self, session, vm_ref):
1198 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1199 return xen_api_success(dom.get_on_suspend())
1201 def VM_get_actions_after_crash(self, session, vm_ref):
1202 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1203 return xen_api_success(dom.get_on_crash())
1205 def VM_get_PV_bootloader(self, session, vm_ref):
1206 return self.VM_get('PV_bootloader', session, vm_ref)
1208 def VM_get_PV_kernel(self, session, vm_ref):
1209 return self.VM_get('PV_kernel', session, vm_ref)
1211 def VM_get_PV_ramdisk(self, session, vm_ref):
1212 return self.VM_get('PV_ramdisk', session, vm_ref)
1214 def VM_get_PV_args(self, session, vm_ref):
1215 return self.VM_get('PV_args', session, vm_ref)
1217 def VM_get_PV_bootloader_args(self, session, vm_ref):
1218 return self.VM_get('PV_bootloader_args', session, vm_ref)
1220 def VM_get_HVM_boot_policy(self, session, vm_ref):
1221 return self.VM_get('HVM_boot_policy', session, vm_ref)
1223 def VM_get_HVM_boot_params(self, session, vm_ref):
1224 return self.VM_get('HVM_boot_params', session, vm_ref)
1226 def VM_get_platform(self, session, vm_ref):
1227 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1228 return xen_api_success(dom.get_platform())
1230 def VM_get_PCI_bus(self, session, vm_ref):
1231 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1232 return dom.get_pci_bus()
1234 def VM_set_PCI_bus(self, session, vm_ref, val):
1235 return self.VM_set('PCI_bus', session, vm_ref, val)
1237 def VM_get_other_config(self, session, vm_ref):
1238 return self.VM_get('other_config', session, vm_ref)
1240 def VM_get_domid(self, _, ref):
1241 domid = XendDomain.instance().get_vm_by_uuid(ref).getDomid()
1242 return xen_api_success(domid is None and -1 or domid)
1244 def VM_get_is_control_domain(self, session, vm_ref):
1245 xd = XendDomain.instance()
1246 return xen_api_success(
1247 xd.get_vm_by_uuid(vm_ref) == xd.privilegedDomain())
1249 def VM_set_name_label(self, session, vm_ref, label):
1250 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1251 dom.setName(label)
1252 return self._VM_save(dom)
1254 def VM_set_name_description(self, session, vm_ref, desc):
1255 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1256 return xen_api_todo()
1258 def VM_set_user_version(self, session, vm_ref, ver):
1259 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1260 return xen_api_todo()
1262 def VM_set_is_a_template(self, session, vm_ref, is_template):
1263 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1264 return xen_api_todo()
1266 def VM_set_memory_dynamic_max(self, session, vm_ref, mem):
1267 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1268 return xen_api_todo()
1270 def VM_set_memory_dynamic_min(self, session, vm_ref, mem):
1271 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1272 return xen_api_todo()
1274 def VM_set_VCPUs_params(self, session, vm_ref, value):
1275 return self.VM_set('vcpus_params', session, vm_ref, value)
1277 def VM_add_to_VCPUs_params(self, session, vm_ref, key, value):
1278 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1279 if 'vcpus_params' not in dom.info:
1280 dom.info['vcpus_params'] = {}
1281 dom.info['vcpus_params'][key] = value
1282 return self._VM_save(dom)
1284 def VM_remove_from_VCPUs_params(self, session, vm_ref, key):
1285 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1286 if 'vcpus_params' in dom.info \
1287 and key in dom.info['vcpus_params']:
1288 del dom.info['vcpus_params'][key]
1289 return self._VM_save(dom)
1290 else:
1291 return xen_api_success_void()
1293 def VM_set_actions_after_shutdown(self, session, vm_ref, action):
1294 if action not in XEN_API_ON_NORMAL_EXIT:
1295 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1296 return self.VM_set('actions_after_shutdown', session, vm_ref, action)
1298 def VM_set_actions_after_reboot(self, session, vm_ref, action):
1299 if action not in XEN_API_ON_NORMAL_EXIT:
1300 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1301 return self.VM_set('actions_after_reboot', session, vm_ref, action)
1303 def VM_set_actions_after_suspend(self, session, vm_ref, action):
1304 if action not in XEN_API_ON_NORMAL_EXIT:
1305 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1306 return self.VM_set('actions_after_suspend', session, vm_ref, action)
1308 def VM_set_actions_after_crash(self, session, vm_ref, action):
1309 if action not in XEN_API_ON_CRASH_BEHAVIOUR:
1310 return xen_api_error(['VM_ON_CRASH_BEHAVIOUR_INVALID', vm_ref])
1311 return self.VM_set('actions_after_crash', session, vm_ref, action)
1313 def VM_set_HVM_boot_policy(self, session, vm_ref, value):
1314 if value != "" and value != "BIOS order":
1315 return xen_api_error(
1316 ['VALUE_NOT_SUPPORTED', 'VM.HVM_boot_policy', value,
1317 'Xend supports only the "BIOS order" boot policy.'])
1318 else:
1319 return self.VM_set('HVM_boot_policy', session, vm_ref, value)
1321 def VM_set_HVM_boot_params(self, session, vm_ref, value):
1322 return self.VM_set('HVM_boot_params', session, vm_ref, value)
1324 def VM_add_to_HVM_boot_params(self, session, vm_ref, key, value):
1325 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1326 if 'HVM_boot_params' not in dom.info:
1327 dom.info['HVM_boot_params'] = {}
1328 dom.info['HVM_boot_params'][key] = value
1329 return self._VM_save(dom)
1331 def VM_remove_from_HVM_boot_params(self, session, vm_ref, key):
1332 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1333 if 'HVM_boot_params' in dom.info \
1334 and key in dom.info['HVM_boot_params']:
1335 del dom.info['HVM_boot_params'][key]
1336 return self._VM_save(dom)
1337 else:
1338 return xen_api_success_void()
1340 def VM_set_PV_bootloader(self, session, vm_ref, value):
1341 return self.VM_set('PV_bootloader', session, vm_ref, value)
1343 def VM_set_PV_kernel(self, session, vm_ref, value):
1344 return self.VM_set('PV_kernel', session, vm_ref, value)
1346 def VM_set_PV_ramdisk(self, session, vm_ref, value):
1347 return self.VM_set('PV_ramdisk', session, vm_ref, value)
1349 def VM_set_PV_args(self, session, vm_ref, value):
1350 return self.VM_set('PV_args', session, vm_ref, value)
1352 def VM_set_PV_bootloader_args(self, session, vm_ref, value):
1353 return self.VM_set('PV_bootloader_args', session, vm_ref, value)
1355 def VM_set_platform(self, session, vm_ref, value):
1356 return self.VM_set('platform', session, vm_ref, value)
1358 def VM_add_to_platform(self, session, vm_ref, key, value):
1359 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1360 plat = dom.get_platform()
1361 plat[key] = value
1362 return self.VM_set_platform(session, vm_ref, plat)
1364 def VM_remove_from_platform(self, session, vm_ref, key):
1365 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1366 plat = dom.get_platform()
1367 if key in plat:
1368 del plat[key]
1369 return self.VM_set_platform(session, vm_ref, plat)
1370 else:
1371 return xen_api_success_void()
1373 def VM_set_other_config(self, session, vm_ref, value):
1374 return self.VM_set('other_config', session, vm_ref, value)
1376 def VM_add_to_other_config(self, session, vm_ref, key, value):
1377 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1378 if dom and 'other_config' in dom.info:
1379 dom.info['other_config'][key] = value
1380 return self._VM_save(dom)
1382 def VM_remove_from_other_config(self, session, vm_ref, key):
1383 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1384 if dom and 'other_config' in dom.info \
1385 and key in dom.info['other_config']:
1386 del dom.info['other_config'][key]
1387 return self._VM_save(dom)
1388 else:
1389 return xen_api_success_void()
1391 # class methods
1392 def VM_get_all(self, session):
1393 refs = [d.get_uuid() for d in XendDomain.instance().list('all')]
1394 return xen_api_success(refs)
1396 def VM_get_by_name_label(self, session, label):
1397 xendom = XendDomain.instance()
1398 dom = xendom.domain_lookup_nr(label)
1399 if dom:
1400 return xen_api_success([dom.get_uuid()])
1401 return xen_api_success([])
1403 def VM_create(self, session, vm_struct):
1404 xendom = XendDomain.instance()
1405 domuuid = XendTask.log_progress(0, 100,
1406 xendom.create_domain, vm_struct)
1407 return xen_api_success(domuuid)
1409 # object methods
1410 def VM_get_record(self, session, vm_ref):
1411 xendom = XendDomain.instance()
1412 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1413 if not xeninfo:
1414 return xen_api_error(['HANDLE_INVALID', 'VM', vm_ref])
1416 domid = xeninfo.getDomid()
1418 record = {
1419 'uuid': xeninfo.get_uuid(),
1420 'power_state': xeninfo.get_power_state(),
1421 'name_label': xeninfo.getName(),
1422 'name_description': xeninfo.getName(),
1423 'user_version': 1,
1424 'is_a_template': False,
1425 'auto_power_on': False,
1426 'resident_on': XendNode.instance().uuid,
1427 'memory_static_min': xeninfo.get_memory_static_min(),
1428 'memory_static_max': xeninfo.get_memory_static_max(),
1429 'memory_dynamic_min': xeninfo.get_memory_dynamic_min(),
1430 'memory_dynamic_max': xeninfo.get_memory_dynamic_max(),
1431 'VCPUs_params': xeninfo.get_vcpus_params(),
1432 'VCPUs_number': xeninfo.getVCpuCount(),
1433 'actions_after_shutdown': xeninfo.get_on_shutdown(),
1434 'actions_after_reboot': xeninfo.get_on_reboot(),
1435 'actions_after_suspend': xeninfo.get_on_suspend(),
1436 'actions_after_crash': xeninfo.get_on_crash(),
1437 'consoles': xeninfo.get_consoles(),
1438 'VIFs': xeninfo.get_vifs(),
1439 'VBDs': xeninfo.get_vbds(),
1440 'VTPMs': xeninfo.get_vtpms(),
1441 'PV_bootloader': xeninfo.info.get('PV_bootloader'),
1442 'PV_kernel': xeninfo.info.get('PV_kernel'),
1443 'PV_ramdisk': xeninfo.info.get('PV_ramdisk'),
1444 'PV_args': xeninfo.info.get('PV_args'),
1445 'PV_bootloader_args': xeninfo.info.get('PV_bootloader_args'),
1446 'HVM_boot_policy': xeninfo.info.get('HVM_boot_policy'),
1447 'HVM_boot_params': xeninfo.info.get('HVM_boot_params'),
1448 'platform': xeninfo.get_platform(),
1449 'PCI_bus': xeninfo.get_pci_bus(),
1450 'tools_version': xeninfo.get_tools_version(),
1451 'other_config': xeninfo.info.get('other_config', {}),
1452 'domid': domid is None and -1 or domid,
1453 'is_control_domain': xeninfo == xendom.privilegedDomain(),
1455 return xen_api_success(record)
1457 def VM_clean_reboot(self, session, vm_ref):
1458 xendom = XendDomain.instance()
1459 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1460 XendTask.log_progress(0, 100, xeninfo.shutdown, "reboot")
1461 return xen_api_success_void()
1463 def VM_clean_shutdown(self, session, vm_ref):
1464 xendom = XendDomain.instance()
1465 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1466 XendTask.log_progress(0, 100, xeninfo.shutdown, "poweroff")
1467 return xen_api_success_void()
1469 def VM_clone(self, session, vm_ref):
1470 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1472 def VM_destroy(self, session, vm_ref):
1473 return XendTask.log_progress(0, 100, do_vm_func,
1474 "domain_delete", vm_ref)
1476 def VM_hard_reboot(self, session, vm_ref):
1477 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1479 def VM_hard_shutdown(self, session, vm_ref):
1480 return XendTask.log_progress(0, 100, do_vm_func,
1481 "domain_destroy", vm_ref)
1482 def VM_pause(self, session, vm_ref):
1483 return XendTask.log_progress(0, 100, do_vm_func,
1484 "domain_pause", vm_ref)
1486 def VM_resume(self, session, vm_ref, start_paused):
1487 return XendTask.log_progress(0, 100, do_vm_func,
1488 "domain_resume", vm_ref,
1489 start_paused = start_paused)
1491 def VM_start(self, session, vm_ref, start_paused):
1492 try:
1493 return XendTask.log_progress(0, 100, do_vm_func,
1494 "domain_start", vm_ref,
1495 start_paused = start_paused)
1496 except HVMRequired, exn:
1497 return xen_api_error(['VM_HVM_REQUIRED', vm_ref])
1499 def VM_suspend(self, session, vm_ref):
1500 return XendTask.log_progress(0, 100, do_vm_func,
1501 "domain_suspend", vm_ref)
1503 def VM_unpause(self, session, vm_ref):
1504 return XendTask.log_progress(0, 100, do_vm_func,
1505 "domain_unpause", vm_ref)
1507 # Xen API: Class VM_metrics
1508 # ----------------------------------------------------------------
1510 VM_metrics_attr_ro = ['memory_actual',
1511 'vcpus_number',
1512 'vcpus_utilisation']
1513 VM_metrics_attr_rw = []
1514 VM_metrics_methods = []
1516 def _VM_metrics_get(self, ref):
1517 return XendVMMetrics.get_by_uuid(ref)
1519 def VM_metrics_get_all(self, _):
1520 return xen_api_success(XendVMMetrics.get_all())
1522 def VM_metrics_get_record(self, _, ref):
1523 return xen_api_success(self._VM_metrics_get(ref).get_record())
1525 def VM_metrics_get_memory_actual(self, _, ref):
1526 return xen_api_success(self._VM_metrics_get(ref).get_memory_actual())
1528 def VM_metrics_get_vcpus_number(self, _, ref):
1529 return xen_api_success(self._VM_metrics_get(ref).get_vcpus_number())
1531 def VM_metrics_get_vcpus_utilisation(self, _, ref):
1532 return xen_api_success(self._VM_metrics_get(ref).get_metrics_get_vcpus_utilisation())
1534 # Xen API: Class VBD
1535 # ----------------------------------------------------------------
1537 VBD_attr_ro = ['metrics']
1538 VBD_attr_rw = ['VM',
1539 'VDI',
1540 'device',
1541 'bootable',
1542 'mode',
1543 'type']
1545 VBD_attr_inst = VBD_attr_rw
1547 VBD_methods = [('media_change', None)]
1548 VBD_funcs = [('create', 'VBD')]
1550 # object methods
1551 def VBD_get_record(self, session, vbd_ref):
1552 xendom = XendDomain.instance()
1553 vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1554 if not vm:
1555 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1556 cfg = vm.get_dev_xenapi_config('vbd', vbd_ref)
1557 if not cfg:
1558 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1560 valid_vbd_keys = self.VBD_attr_ro + self.VBD_attr_rw + \
1561 self.Base_attr_ro + self.Base_attr_rw
1563 return_cfg = {}
1564 for k in cfg.keys():
1565 if k in valid_vbd_keys:
1566 return_cfg[k] = cfg[k]
1568 return_cfg['metrics'] = vbd_ref
1570 return xen_api_success(return_cfg)
1572 def VBD_media_change(self, session, vbd_ref, vdi_ref):
1573 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1575 # class methods
1576 def VBD_create(self, session, vbd_struct):
1577 xendom = XendDomain.instance()
1578 if not xendom.is_valid_vm(vbd_struct['VM']):
1579 return xen_api_error(['HANDLE_INVALID', 'VM', vbd_struct['VM']])
1581 dom = xendom.get_vm_by_uuid(vbd_struct['VM'])
1582 vbd_ref = ''
1583 try:
1584 # new VBD via VDI/SR
1585 vdi_ref = vbd_struct.get('VDI')
1586 vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
1587 if not vdi:
1588 return xen_api_error(['HANDLE_INVALID', 'VDI', vdi_ref])
1589 vdi_image = vdi.get_location()
1590 vbd_ref = XendTask.log_progress(0, 100,
1591 dom.create_vbd,
1592 vbd_struct, vdi_image)
1593 except XendError:
1594 return xen_api_todo()
1596 xendom.managed_config_save(dom)
1597 return xen_api_success(vbd_ref)
1600 def VBD_destroy(self, session, vbd_ref):
1601 xendom = XendDomain.instance()
1602 vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1603 if not vm:
1604 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1606 XendTask.log_progress(0, 100, vm.destroy_vbd, vbd_ref)
1607 return xen_api_success_void()
1609 def _VBD_get(self, vbd_ref, prop):
1610 return xen_api_success(
1611 XendDomain.instance().get_dev_property_by_uuid(
1612 'vbd', vbd_ref, prop))
1614 # attributes (ro)
1615 def VBD_get_metrics(self, _, vbd_ref):
1616 return xen_api_success(vbd_ref)
1618 # attributes (rw)
1619 def VBD_get_VM(self, session, vbd_ref):
1620 return self._VBD_get(vbd_ref, 'VM')
1622 def VBD_get_VDI(self, session, vbd_ref):
1623 return self._VBD_get(vbd_ref, 'VDI')
1625 def VBD_get_device(self, session, vbd_ref):
1626 return self._VBD_get(vbd_ref, 'device')
1628 def VBD_get_bootable(self, session, vbd_ref):
1629 return self._VBD_get(vbd_ref, 'bootable')
1631 def VBD_get_mode(self, session, vbd_ref):
1632 return self._VBD_get(vbd_ref, 'mode')
1634 def VBD_get_type(self, session, vbd_ref):
1635 return self._VBD_get(vbd_ref, 'type')
1637 def VBD_set_bootable(self, session, vbd_ref, bootable):
1638 bootable = bool(bootable)
1639 xd = XendDomain.instance()
1640 vm = xd.get_vm_with_dev_uuid('vbd', vbd_ref)
1641 vm.set_dev_property('vbd', vbd_ref, 'bootable', bootable)
1642 xd.managed_config_save(vm)
1643 return xen_api_success_void()
1645 def VBD_get_all(self, session):
1646 xendom = XendDomain.instance()
1647 vbds = [d.get_vbds() for d in XendDomain.instance().list('all')]
1648 vbds = reduce(lambda x, y: x + y, vbds)
1649 return xen_api_success(vbds)
1652 # Xen API: Class VBD_metrics
1653 # ----------------------------------------------------------------
1655 VBD_metrics_attr_ro = ['io_read_kbs',
1656 'io_write_kbs']
1657 VBD_metrics_attr_rw = []
1658 VBD_methods = []
1660 def VBD_metrics_get_record(self, _, ref):
1661 vm = XendDomain.instance().get_vm_with_dev_uuid('vbd', ref)
1662 if not vm:
1663 return xen_api_error(['HANDLE_INVALID', 'VBD_metrics', ref])
1664 return xen_api_success(
1665 { 'io_read_kbs' : vm.get_dev_property('vbd', ref, 'io_read_kbs'),
1666 'io_write_kbs' : vm.get_dev_property('vbd', ref, 'io_write_kbs') })
1668 def VBD_metrics_get_io_read_kbs(self, _, ref):
1669 return self._VBD_get(ref, 'io_read_kbs')
1671 def VBD_metrics_get_io_write_kbs(self, session, ref):
1672 return self._VBD_get(ref, 'io_write_kbs')
1675 # Xen API: Class VIF
1676 # ----------------------------------------------------------------
1678 VIF_attr_ro = ['metrics']
1679 VIF_attr_rw = ['device',
1680 'network',
1681 'VM',
1682 'MAC',
1683 'MTU']
1685 VIF_attr_inst = VIF_attr_rw
1687 VIF_funcs = [('create', 'VIF')]
1690 # object methods
1691 def VIF_get_record(self, session, vif_ref):
1692 xendom = XendDomain.instance()
1693 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
1694 if not vm:
1695 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
1696 cfg = vm.get_dev_xenapi_config('vif', vif_ref)
1697 if not cfg:
1698 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
1700 valid_vif_keys = self.VIF_attr_ro + self.VIF_attr_rw + \
1701 self.Base_attr_ro + self.Base_attr_rw
1703 return_cfg = {}
1704 for k in cfg.keys():
1705 if k in valid_vif_keys:
1706 return_cfg[k] = cfg[k]
1708 return_cfg['metrics'] = vif_ref
1710 return xen_api_success(return_cfg)
1712 # class methods
1713 def VIF_create(self, session, vif_struct):
1714 xendom = XendDomain.instance()
1715 if xendom.is_valid_vm(vif_struct['VM']):
1716 dom = xendom.get_vm_by_uuid(vif_struct['VM'])
1717 try:
1718 vif_ref = dom.create_vif(vif_struct)
1719 xendom.managed_config_save(dom)
1720 return xen_api_success(vif_ref)
1721 except XendError:
1722 return xen_api_error(XEND_ERROR_TODO)
1723 else:
1724 return xen_api_error(['HANDLE_INVALID', 'VM', vif_struct['VM']])
1727 def VIF_destroy(self, session, vif_ref):
1728 xendom = XendDomain.instance()
1729 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
1730 if not vm:
1731 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
1733 vm.destroy_vif(vif_ref)
1734 return xen_api_success_void()
1736 def _VIF_get(self, ref, prop):
1737 return xen_api_success(
1738 XendDomain.instance().get_dev_property_by_uuid('vif', ref, prop))
1740 # getters/setters
1741 def VIF_get_metrics(self, _, vif_ref):
1742 return xen_api_success(vif_ref)
1744 def VIF_get_VM(self, session, vif_ref):
1745 xendom = XendDomain.instance()
1746 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
1747 return xen_api_success(vm.get_uuid())
1749 def VIF_get_MTU(self, session, vif_ref):
1750 return self._VIF_get(vif_ref, 'MTU')
1752 def VIF_get_MAC(self, session, vif_ref):
1753 return self._VIF_get(vif_ref, 'MAC')
1755 def VIF_get_device(self, session, vif_ref):
1756 return self._VIF_get(vif_ref, 'device')
1758 def VIF_get_all(self, session):
1759 xendom = XendDomain.instance()
1760 vifs = [d.get_vifs() for d in XendDomain.instance().list('all')]
1761 vifs = reduce(lambda x, y: x + y, vifs)
1762 return xen_api_success(vifs)
1765 # Xen API: Class VIF_metrics
1766 # ----------------------------------------------------------------
1768 VIF_metrics_attr_ro = ['io_read_kbs',
1769 'io_write_kbs']
1770 VIF_metrics_attr_rw = []
1771 VIF_methods = []
1773 def VIF_metrics_get_record(self, _, ref):
1774 vm = XendDomain.instance().get_vm_with_dev_uuid('vif', ref)
1775 if not vm:
1776 return xen_api_error(['HANDLE_INVALID', 'VIF_metrics', ref])
1777 return xen_api_success(
1778 { 'io_read_kbs' : vm.get_dev_property('vif', ref, 'io_read_kbs'),
1779 'io_write_kbs' : vm.get_dev_property('vif', ref, 'io_write_kbs') })
1781 def VIF_metrics_get_io_read_kbs(self, _, ref):
1782 return self._VIF_get(ref, 'io_read_kbs')
1784 def VIF_metrics_get_io_write_kbs(self, session, ref):
1785 return self._VIF_get(ref, 'io_write_kbs')
1788 # Xen API: Class VDI
1789 # ----------------------------------------------------------------
1790 VDI_attr_ro = ['SR',
1791 'VBDs',
1792 'physical_utilisation',
1793 'sector_size',
1794 'type']
1795 VDI_attr_rw = ['name_label',
1796 'name_description',
1797 'virtual_size',
1798 'sharable',
1799 'read_only']
1800 VDI_attr_inst = VDI_attr_ro + VDI_attr_rw
1802 VDI_methods = [('snapshot', 'VDI')]
1803 VDI_funcs = [('create', 'VDI'),
1804 ('get_by_name_label', 'Set(VDI)')]
1806 def _get_VDI(self, ref):
1807 return XendNode.instance().get_vdi_by_uuid(ref)
1809 def VDI_get_VBDs(self, session, vdi_ref):
1810 return xen_api_todo()
1812 def VDI_get_physical_utilisation(self, session, vdi_ref):
1813 return xen_api_success(self._get_VDI(vdi_ref).
1814 get_physical_utilisation())
1816 def VDI_get_sector_size(self, session, vdi_ref):
1817 return xen_api_success(self._get_VDI(vdi_ref).sector_size)
1819 def VDI_get_type(self, session, vdi_ref):
1820 return xen_api_success(self._get_VDI(vdi_ref).type)
1822 def VDI_get_name_label(self, session, vdi_ref):
1823 return xen_api_success(self._get_VDI(vdi_ref).name_label)
1825 def VDI_get_name_description(self, session, vdi_ref):
1826 return xen_api_success(self._get_VDI(vdi_ref).name_description)
1828 def VDI_get_SR(self, session, vdi_ref):
1829 return xen_api_success(self._get_VDI(vdi_ref).sr_uuid)
1831 def VDI_get_virtual_size(self, session, vdi_ref):
1832 return xen_api_success(self._get_VDI(vdi_ref).virtual_size)
1834 def VDI_get_sharable(self, session, vdi_ref):
1835 return xen_api_success(self._get_VDI(vdi_ref).sharable)
1837 def VDI_get_read_only(self, session, vdi_ref):
1838 return xen_api_success(self._get_VDI(vdi_ref).read_only)
1840 def VDI_set_name_label(self, session, vdi_ref, value):
1841 self._get_VDI(vdi_ref).name_label = value
1842 return xen_api_success_void()
1844 def VDI_set_name_description(self, session, vdi_ref, value):
1845 self._get_VDI(vdi_ref).name_description = value
1846 return xen_api_success_void()
1848 def VDI_set_virtual_size(self, session, vdi_ref, value):
1849 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1851 def VDI_set_sharable(self, session, vdi_ref, value):
1852 self._get_VDI(vdi_ref).sharable = bool(value)
1853 return xen_api_success_void()
1855 def VDI_set_read_only(self, session, vdi_ref, value):
1856 self._get_VDI(vdi_ref).read_only = bool(value)
1857 return xen_api_success_void()
1859 # Object Methods
1860 def VDI_snapshot(self, session, vdi_ref):
1861 return xen_api_todo()
1863 def VDI_destroy(self, session, vdi_ref):
1864 sr = XendNode.instance().get_sr_containing_vdi(vdi_ref)
1865 sr.destroy_vdi(vdi_ref)
1866 return xen_api_success_void()
1868 def VDI_get_record(self, session, vdi_ref):
1869 image = XendNode.instance().get_vdi_by_uuid(vdi_ref)
1870 return xen_api_success({
1871 'uuid': vdi_ref,
1872 'name_label': image.name_label,
1873 'name_description': image.name_description,
1874 'SR': image.sr_uuid,
1875 'VBDs': [], # TODO
1876 'virtual_size': image.virtual_size,
1877 'physical_utilisation': image.physical_utilisation,
1878 'sector_size': image.sector_size,
1879 'type': image.type,
1880 'sharable': image.sharable,
1881 'read_only': image.read_only,
1882 })
1884 # Class Functions
1885 def VDI_create(self, session, vdi_struct):
1886 sr_ref = vdi_struct.get('SR')
1887 xennode = XendNode.instance()
1888 if not xennode.is_valid_sr(sr_ref):
1889 return xen_api_error(['HANDLE_INVALID', 'SR', sr_ref])
1891 vdi_uuid = xennode.srs[sr_ref].create_vdi(vdi_struct)
1892 return xen_api_success(vdi_uuid)
1894 def VDI_get_all(self, session):
1895 xennode = XendNode.instance()
1896 vdis = [sr.get_vdis() for sr in xennode.srs.values()]
1897 return xen_api_success(reduce(lambda x, y: x + y, vdis))
1899 def VDI_get_by_name_label(self, session, name):
1900 xennode = XendNode.instance()
1901 return xen_api_success(xennode.get_vdi_by_name_label(name))
1904 # Xen API: Class VTPM
1905 # ----------------------------------------------------------------
1907 VTPM_attr_rw = [ ]
1908 VTPM_attr_ro = ['VM',
1909 'backend']
1911 VTPM_attr_inst = VTPM_attr_rw
1913 VTPM_funcs = [('create', 'VTPM')]
1915 # object methods
1916 def VTPM_get_record(self, session, vtpm_ref):
1917 xendom = XendDomain.instance()
1918 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
1919 if not vm:
1920 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
1921 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
1922 if not cfg:
1923 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
1924 valid_vtpm_keys = self.VTPM_attr_ro + self.VTPM_attr_rw + \
1925 self.Base_attr_ro + self.Base_attr_rw
1926 return_cfg = {}
1927 for k in cfg.keys():
1928 if k in valid_vtpm_keys:
1929 return_cfg[k] = cfg[k]
1931 return xen_api_success(return_cfg)
1933 # Class Functions
1934 def VTPM_get_backend(self, session, vtpm_ref):
1935 xendom = XendDomain.instance()
1936 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
1937 if not vm:
1938 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
1939 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
1940 if not cfg:
1941 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
1942 if not cfg.has_key('backend'):
1943 return xen_api_error(['VTPM backend not set'])
1944 return xen_api_success(cfg['backend'])
1946 def VTPM_get_VM(self, session, vtpm_ref):
1947 xendom = XendDomain.instance()
1948 return xen_api_success(xendom.get_dev_property_by_uuid('vtpm',
1949 vtpm_ref, 'VM'))
1951 def VTPM_destroy(self, session, vtpm_ref):
1952 xendom = XendDomain.instance()
1953 dom = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
1954 if dom:
1955 if dom.state != XEN_API_VM_POWER_STATE_HALTED:
1956 vm_ref = dom.get_dev_property('vtpm', vtpm_ref, 'VM')
1957 return xen_api_error(['VM_BAD_POWER_STATE', vm_ref,
1958 XendDomain.POWER_STATE_NAMES[XEN_API_VM_POWER_STATE_HALTED],
1959 XendDomain.POWER_STATE_NAMES[dom.state]])
1960 from xen.xend.server import tpmif
1961 tpmif.destroy_vtpmstate(dom.getName())
1962 return xen_api_success_void()
1963 else:
1964 return xen_api_error(['HANDLE_INVALID', 'VM', vtpm_struct['VM']])
1966 # class methods
1967 def VTPM_create(self, session, vtpm_struct):
1968 xendom = XendDomain.instance()
1969 if xendom.is_valid_vm(vtpm_struct['VM']):
1970 dom = xendom.get_vm_by_uuid(vtpm_struct['VM'])
1971 try:
1972 vtpm_ref = dom.create_vtpm(vtpm_struct)
1973 xendom.managed_config_save(dom)
1974 return xen_api_success(vtpm_ref)
1975 except XendError:
1976 return xen_api_error(XEND_ERROR_TODO)
1977 else:
1978 return xen_api_error(['HANDLE_INVALID', 'VM', vtpm_struct['VM']])
1980 def VTPM_get_all(self, session):
1981 xendom = XendDomain.instance()
1982 vtpms = [d.get_vtpms() for d in XendDomain.instance().list('all')]
1983 vtpms = reduce(lambda x, y: x + y, vtpms)
1984 return xen_api_success(vtpms)
1986 # Xen API: Class console
1987 # ----------------------------------------------------------------
1990 console_attr_ro = ['location', 'protocol', 'VM']
1991 console_attr_rw = ['other_config']
1992 console_funcs = [('create', 'console')]
1994 def console_get_all(self, session):
1995 xendom = XendDomain.instance()
1996 cons = [d.get_consoles() for d in XendDomain.instance().list('all')]
1997 cons = reduce(lambda x, y: x + y, cons)
1998 return xen_api_success(cons)
2000 def console_get_location(self, session, console_ref):
2001 return xen_api_success(xendom.get_dev_property_by_uuid('console',
2002 console_ref,
2003 'location'))
2005 def console_get_protocol(self, session, console_ref):
2006 return xen_api_success(xendom.get_dev_property_by_uuid('console',
2007 console_ref,
2008 'protocol'))
2010 def console_get_VM(self, session, console_ref):
2011 xendom = XendDomain.instance()
2012 vm = xendom.get_vm_with_dev_uuid('console', console_ref)
2013 return xen_api_success(vm.get_uuid())
2015 # object methods
2016 def console_get_record(self, session, console_ref):
2017 xendom = XendDomain.instance()
2018 vm = xendom.get_vm_with_dev_uuid('console', console_ref)
2019 if not vm:
2020 return xen_api_error(['HANDLE_INVALID', 'console', console_ref])
2021 cfg = vm.get_dev_xenapi_config('console', console_ref)
2022 if not cfg:
2023 return xen_api_error(['HANDLE_INVALID', 'console', console_ref])
2025 valid_console_keys = self.console_attr_ro + self.console_attr_rw + \
2026 self.Base_attr_ro + self.Base_attr_rw
2028 return_cfg = {}
2029 for k in cfg.keys():
2030 if k in valid_console_keys:
2031 return_cfg[k] = cfg[k]
2033 return xen_api_success(return_cfg)
2035 def console_create(self, session, console_struct):
2036 xendom = XendDomain.instance()
2037 if not xendom.is_valid_vm(console_struct['VM']):
2038 return xen_api_error(['HANDLE_INVALID', 'VM',
2039 console_struct['VM']])
2041 dom = xendom.get_vm_by_uuid(console_struct['VM'])
2042 try:
2043 if 'protocol' not in console_struct:
2044 return xen_api_error(['CONSOLE_PROTOCOL_INVALID',
2045 'No protocol specified'])
2047 console_ref = dom.create_console(console_struct)
2048 xendom.managed_config_save(dom)
2049 return xen_api_success(console_ref)
2050 except XendError, e:
2051 return xen_api_error([XEND_ERROR_TODO, str(e)])
2053 # Xen API: Class SR
2054 # ----------------------------------------------------------------
2055 SR_attr_ro = ['VDIs',
2056 'virtual_allocation',
2057 'physical_utilisation',
2058 'physical_size',
2059 'type',
2060 'location']
2062 SR_attr_rw = ['name_label',
2063 'name_description']
2065 SR_attr_inst = ['physical_size',
2066 'type',
2067 'location',
2068 'name_label',
2069 'name_description']
2071 SR_methods = [('clone', 'SR')]
2072 SR_funcs = [('get_by_name_label', 'Set(SR)'),
2073 ('get_by_uuid', 'SR')]
2075 # Class Functions
2076 def SR_get_all(self, session):
2077 return xen_api_success(XendNode.instance().get_all_sr_uuid())
2079 def SR_get_by_name_label(self, session, label):
2080 return xen_api_success(XendNode.instance().get_sr_by_name(label))
2082 def SR_create(self, session):
2083 return xen_api_error(XEND_ERROR_UNSUPPORTED)
2085 # Class Methods
2086 def SR_clone(self, session, sr_ref):
2087 return xen_api_error(XEND_ERROR_UNSUPPORTED)
2089 def SR_destroy(self, session, sr_ref):
2090 return xen_api_error(XEND_ERROR_UNSUPPORTED)
2092 def SR_get_record(self, session, sr_ref):
2093 sr = XendNode.instance().get_sr(sr_ref)
2094 if sr:
2095 return xen_api_success(sr.get_record())
2096 return xen_api_error(['HANDLE_INVALID', 'SR', sr_ref])
2098 # Attribute acceess
2100 def _get_SR_func(self, sr_ref, func):
2101 return xen_api_success(getattr(XendNode.instance().get_sr(sr_ref),
2102 func)())
2104 def _get_SR_attr(self, sr_ref, attr):
2105 return xen_api_success(getattr(XendNode.instance().get_sr(sr_ref),
2106 attr))
2108 def SR_get_VDIs(self, _, ref):
2109 return self._get_SR_func(ref, 'list_images')
2111 def SR_get_virtual_allocation(self, _, ref):
2112 return self._get_SR_func(ref, 'virtual_allocation')
2114 def SR_get_physical_utilisation(self, _, ref):
2115 return self._get_SR_func(ref, 'physical_utilisation')
2117 def SR_get_physical_size(self, _, ref):
2118 return self._get_SR_func(ref, 'physical_size')
2120 def SR_get_type(self, _, ref):
2121 return self._get_SR_attr(ref, 'type')
2123 def SR_get_location(self, _, ref):
2124 return self._get_SR_attr(ref, 'location')
2126 def SR_get_name_label(self, _, ref):
2127 return self._get_SR_attr(ref, 'name_label')
2129 def SR_get_name_description(self, _, ref):
2130 return self._get_SR_attr(ref, 'name_description')
2132 def SR_set_name_label(self, session, sr_ref, value):
2133 sr = XendNode.instance.get_sr(sr_ref)
2134 if sr:
2135 sr.name_label = value
2136 XendNode.instance().save()
2137 return xen_api_success_void()
2139 def SR_set_name_description(self, session, sr_ref, value):
2140 sr = XendNode.instance.get_sr(sr_ref)
2141 if sr:
2142 sr.name_description = value
2143 XendNode.instance().save()
2144 return xen_api_success_void()
2147 # Xen API: Class debug
2148 # ----------------------------------------------------------------
2150 debug_methods = [('destroy', None),
2151 ('get_record', 'debug')]
2152 debug_funcs = [('wait', None),
2153 ('return_failure', None)]
2155 def debug_wait(self, session, wait_secs):
2156 import time
2157 prog_units = 100/float(wait_secs)
2158 for i in range(int(wait_secs)):
2159 XendTask.log_progress(prog_units * i, prog_units * (i + 1),
2160 time.sleep, 1)
2161 return xen_api_success_void()
2164 def debug_return_failure(self, session):
2165 return xen_api_error(['DEBUG_FAIL', session])
2167 def debug_create(self, session):
2168 debug_uuid = uuid.createString()
2169 self._debug[debug_uuid] = None
2170 return xen_api_success(debug_uuid)
2172 def debug_destroy(self, session, debug_ref):
2173 del self._debug[debug_ref]
2174 return xen_api_success_void()
2176 def debug_get_record(self, session, debug_ref):
2177 return xen_api_success({'uuid': debug_ref})
2180 def list_all_methods(self, _):
2181 def _funcs():
2182 return [getattr(XendAPI, x) for x in XendAPI.__dict__]
2184 return xen_api_success([x.api for x in _funcs()
2185 if hasattr(x, 'api')])
2186 list_all_methods.api = '_UNSUPPORTED_list_all_methods'
2189 class XendAPIAsyncProxy:
2190 """ A redirector for Async.Class.function calls to XendAPI
2191 but wraps the call for use with the XendTaskManager.
2193 @ivar xenapi: Xen API instance
2194 @ivar method_map: Mapping from XMLRPC method name to callable objects.
2195 """
2197 method_prefix = 'Async.'
2199 def __init__(self, xenapi):
2200 """Initialises the Async Proxy by making a map of all
2201 implemented Xen API methods for use with XendTaskManager.
2203 @param xenapi: XendAPI instance
2204 """
2205 self.xenapi = xenapi
2206 self.method_map = {}
2207 for method_name in dir(self.xenapi):
2208 method = getattr(self.xenapi, method_name)
2209 if method_name[0] != '_' and hasattr(method, 'async') \
2210 and method.async == True:
2211 self.method_map[method.api] = method
2213 def _dispatch(self, method, args):
2214 """Overridden method so that SimpleXMLRPCServer will
2215 resolve methods through this method rather than through
2216 inspection.
2218 @param method: marshalled method name from XMLRPC.
2219 @param args: marshalled arguments from XMLRPC.
2220 """
2222 # Only deal with method names that start with "Async."
2223 if not method.startswith(self.method_prefix):
2224 return xen_api_error(['MESSAGE_METHOD_UNKNOWN', method])
2226 # Lookup synchronous version of the method
2227 synchronous_method_name = method[len(self.method_prefix):]
2228 if synchronous_method_name not in self.method_map:
2229 return xen_api_error(['MESSAGE_METHOD_UNKNOWN', method])
2231 method = self.method_map[synchronous_method_name]
2233 # Check that we've got enough arguments before issuing a task ID.
2234 needed = argcounts[method.api]
2235 if len(args) != needed:
2236 return xen_api_error(['MESSAGE_PARAMETER_COUNT_MISMATCH',
2237 self.method_prefix + method.api, needed,
2238 len(args)])
2240 # Validate the session before proceeding
2241 session = args[0]
2242 if not auth_manager().is_session_valid(session):
2243 return xen_api_error(['SESSION_INVALID', session])
2245 # create and execute the task, and return task_uuid
2246 return_type = getattr(method, 'return_type', None)
2247 task_uuid = XendTaskManager.create_task(method, args,
2248 synchronous_method_name,
2249 return_type,
2250 synchronous_method_name,
2251 session)
2252 return xen_api_success(task_uuid)
2255 # Auto generate some stubs based on XendAPI introspection
2257 if __name__ == "__main__":
2258 def output(line):
2259 print ' ' + line
2261 classes = ['VDI', 'SR']
2262 for cls in classes:
2263 ro_attrs = getattr(XendAPI, '%s_attr_ro' % cls, [])
2264 rw_attrs = getattr(XendAPI, '%s_attr_rw' % cls, [])
2265 methods = getattr(XendAPI, '%s_methods' % cls, [])
2266 funcs = getattr(XendAPI, '%s_funcs' % cls, [])
2268 ref = '%s_ref' % cls
2270 for attr_name in ro_attrs + rw_attrs + XendAPI.Base_attr_ro:
2271 getter_name = '%s_get_%s' % (cls, attr_name)
2272 output('def %s(self, session, %s):' % (getter_name, ref))
2273 output(' return xen_api_todo()')
2275 for attr_name in rw_attrs + XendAPI.Base_attr_rw:
2276 setter_name = '%s_set_%s' % (cls, attr_name)
2277 output('def %s(self, session, %s, value):' % (setter_name, ref))
2278 output(' return xen_api_todo()')
2280 for method_name in methods + XendAPI.Base_methods:
2281 method_full_name = '%s_%s' % (cls,method_name)
2282 output('def %s(self, session, %s):' % (method_full_name, ref))
2283 output(' return xen_api_todo()')
2285 for func_name in funcs + XendAPI.Base_funcs:
2286 func_full_name = '%s_%s' % (cls, func_name)
2287 output('def %s(self, session):' % func_full_name)
2288 output(' return xen_api_todo()')