ia64/xen-unstable

view tools/python/xen/xend/XendAPI.py @ 14430:edccebeea4a3

Added a new Xen-API call VM.send_sysrq, and use that to implement xm sysrq
through Xen-API.

Signed-off-by: Tom Wilkie <tom.wilkie@gmail.com>
author Ewan Mellor <ewan@xensource.com>
date Thu Mar 15 21:59:34 2007 +0000 (2007-03-15)
parents b39c0a79d4d5
children 3c418dbb71b2
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'),
665 ('get_log', 'String')]
667 host_funcs = [('get_by_name_label', 'Set(host)')]
669 # attributes
670 def host_get_name_label(self, session, host_ref):
671 return xen_api_success(XendNode.instance().name)
672 def host_set_name_label(self, session, host_ref, new_name):
673 XendNode.instance().set_name(new_name)
674 return xen_api_success_void()
675 def host_get_name_description(self, session, host_ref):
676 return xen_api_success(XendNode.instance().description)
677 def host_set_name_description(self, session, host_ref, new_desc):
678 XendNode.instance().set_description(new_desc)
679 return xen_api_success_void()
680 def host_get_other_config(self, session, host_ref):
681 return xen_api_success(XendNode.instance().other_config)
682 def host_set_other_config(self, session, host_ref, other_config):
683 node = XendNode.instance()
684 node.other_config = dict(other_config)
685 node.save()
686 return xen_api_success_void()
687 def host_add_to_other_config(self, session, host_ref, key, value):
688 node = XendNode.instance()
689 node.other_config[key] = value
690 node.save()
691 return xen_api_success_void()
692 def host_remove_from_other_config(self, session, host_ref, key):
693 node = XendNode.instance()
694 if key in node.other_config:
695 del node.other_config[key]
696 node.save()
697 return xen_api_success_void()
698 def host_get_API_version_major(self, _, ref):
699 return xen_api_success(XEN_API_VERSION_MAJOR)
700 def host_get_API_version_minor(self, _, ref):
701 return xen_api_success(XEN_API_VERSION_MINOR)
702 def host_get_API_version_vendor(self, _, ref):
703 return xen_api_success(XEN_API_VERSION_VENDOR)
704 def host_get_API_version_vendor_implementation(self, _, ref):
705 return xen_api_success(XEN_API_VERSION_VENDOR_IMPLEMENTATION)
706 def host_get_software_version(self, session, host_ref):
707 return xen_api_success(XendNode.instance().xen_version())
708 def host_get_resident_VMs(self, session, host_ref):
709 return xen_api_success(XendDomain.instance().get_domain_refs())
710 def host_get_host_CPUs(self, session, host_ref):
711 return xen_api_success(XendNode.instance().get_host_cpu_refs())
712 def host_get_metrics(self, _, ref):
713 return xen_api_success(XendNode.instance().host_metrics_uuid)
714 def host_get_capabilities(self, session, host_ref):
715 return xen_api_success(XendNode.instance().get_capabilities())
716 def host_get_supported_bootloaders(self, session, host_ref):
717 return xen_api_success(['pygrub'])
718 def host_get_sched_policy(self, _, host_ref):
719 return xen_api_success(XendNode.instance().get_vcpus_policy())
720 def host_set_sched_policy(self, _, host_ref, policy):
721 return xen_api_todo()
722 def host_get_cpu_configuration(self, _, host_ref):
723 return xen_api_success(XendNode.instance().get_cpu_configuration())
725 # object methods
726 def host_disable(self, session, host_ref):
727 XendDomain.instance().set_allow_new_domains(False)
728 return xen_api_success_void()
729 def host_enable(self, session, host_ref):
730 XendDomain.instance().set_allow_new_domains(True)
731 return xen_api_success_void()
732 def host_reboot(self, session, host_ref):
733 if not XendDomain.instance().allow_new_domains():
734 return xen_api_error(XEND_ERROR_HOST_RUNNING)
735 return xen_api_error(XEND_ERROR_UNSUPPORTED)
736 def host_shutdown(self, session, host_ref):
737 if not XendDomain.instance().allow_new_domains():
738 return xen_api_error(XEND_ERROR_HOST_RUNNING)
739 return xen_api_error(XEND_ERROR_UNSUPPORTED)
741 def host_dmesg(self, session, host_ref, clear):
742 if clear:
743 return xen_api_success(XendDmesg.instance().clear())
744 else:
745 return xen_api_success(XendDmesg.instance().info())
747 def host_get_log(self, session, host_ref):
748 log_file = open(XendLogging.getLogFilename())
749 log_buffer = log_file.read()
750 return xen_api_success(log_buffer)
752 def host_get_record(self, session, host_ref):
753 node = XendNode.instance()
754 dom = XendDomain.instance()
755 record = {'uuid': node.uuid,
756 'name_label': node.name,
757 'name_description': '',
758 'API_version_major': XEN_API_VERSION_MAJOR,
759 'API_version_minor': XEN_API_VERSION_MINOR,
760 'API_version_vendor': XEN_API_VERSION_VENDOR,
761 'API_version_vendor_implementation':
762 XEN_API_VERSION_VENDOR_IMPLEMENTATION,
763 'software_version': node.xen_version(),
764 'other_config': node.other_config,
765 'resident_VMs': dom.get_domain_refs(),
766 'host_CPUs': node.get_host_cpu_refs(),
767 'cpu_configuration': node.get_cpu_configuration(),
768 'metrics': node.host_metrics_uuid,
769 'capabilities': node.get_capabilities(),
770 'supported_bootloaders': 'pygrub',
771 'sched_policy': node.get_vcpus_policy()}
772 return xen_api_success(record)
774 # class methods
775 def host_get_all(self, session):
776 return xen_api_success((XendNode.instance().uuid,))
777 def host_get_by_name_label(self, session, name):
778 if XendNode.instance().name == name:
779 return xen_api_success((XendNode.instance().uuid,))
780 return xen_api_success([])
783 # Xen API: Class host_CPU
784 # ----------------------------------------------------------------
786 host_cpu_attr_ro = ['host',
787 'number',
788 'vendor',
789 'speed',
790 'modelname',
791 'stepping',
792 'flags',
793 'utilisation',
794 'features']
796 # attributes
797 def _host_cpu_get(self, ref, field):
798 return xen_api_success(
799 XendNode.instance().get_host_cpu_field(ref, field))
801 def host_cpu_get_host(self, _, ref):
802 return xen_api_success(XendNode.instance().uuid)
803 def host_cpu_get_features(self, _, ref):
804 return self._host_cpu_get(ref, 'features')
805 def host_cpu_get_number(self, _, ref):
806 return self._host_cpu_get(ref, 'number')
807 def host_cpu_get_vendor(self, _, ref):
808 return self._host_cpu_get(ref, 'vendor')
809 def host_cpu_get_speed(self, _, ref):
810 return self._host_cpu_get(ref, 'speed')
811 def host_cpu_get_modelname(self, _, ref):
812 return self._host_cpu_get(ref, 'modelname')
813 def host_cpu_get_stepping(self, _, ref):
814 return self._host_cpu_get(ref, 'stepping')
815 def host_cpu_get_flags(self, _, ref):
816 return self._host_cpu_get(ref, 'flags')
817 def host_cpu_get_utilisation(self, _, ref):
818 return xen_api_success(XendNode.instance().get_host_cpu_load(ref))
820 # object methods
821 def host_cpu_get_record(self, _, ref):
822 node = XendNode.instance()
823 record = dict([(f, node.get_host_cpu_field(ref, f))
824 for f in self.host_cpu_attr_ro
825 if f not in ['uuid', 'host', 'utilisation']])
826 record['uuid'] = ref
827 record['host'] = node.uuid
828 record['utilisation'] = node.get_host_cpu_load(ref)
829 return xen_api_success(record)
831 # class methods
832 def host_cpu_get_all(self, session):
833 return xen_api_success(XendNode.instance().get_host_cpu_refs())
836 # Xen API: Class host_metrics
837 # ----------------------------------------------------------------
839 host_metrics_attr_ro = ['memory_total',
840 'memory_free']
841 host_metrics_attr_rw = []
842 host_metrics_methods = []
844 def host_metrics_get_all(self, _):
845 return xen_api_success([XendNode.instance().host_metrics_uuid])
847 def _host_metrics_get(self, ref, f):
848 return xen_api_success(getattr(node, f)())
850 def host_metrics_get_record(self, _, ref):
851 return xen_api_success({
852 'uuid' : ref,
853 'memory_total' : self._host_metrics_get_memory_total(),
854 'memory_free' : self._host_metrics_get_memory_free(),
855 })
857 def host_metrics_get_memory_total(self, _, ref):
858 return xen_api_success(self._host_metrics_get_memory_total())
860 def host_metrics_get_memory_free(self, _, ref):
861 return xen_api_success(self._host_metrics_get_memory_free())
863 def _host_metrics_get_memory_total(self):
864 node = XendNode.instance()
865 return node.xc.physinfo()['total_memory'] * 1024
867 def _host_metrics_get_memory_free(self):
868 node = XendNode.instance()
869 return node.xc.physinfo()['free_memory'] * 1024
872 # Xen API: Class network
873 # ----------------------------------------------------------------
875 network_attr_ro = ['VIFs', 'PIFs']
876 network_attr_rw = ['name_label',
877 'name_description']
879 network_funcs = [('create', 'network')]
881 def network_create(self, _, name_label, name_description):
882 return xen_api_success(
883 XendNode.instance().network_create(name_label, name_description))
885 def network_destroy(self, _, ref):
886 return xen_api_success(XendNode.instance().network_destroy(ref))
888 def _get_network(self, ref):
889 return XendNode.instance().get_network(ref)
891 def network_get_all(self, _):
892 return xen_api_success(XendNode.instance().get_network_refs())
894 def network_get_record(self, _, ref):
895 return xen_api_success(
896 XendNode.instance().get_network(ref).get_record())
898 def network_get_name_label(self, _, ref):
899 return xen_api_success(self._get_network(ref).name_label)
901 def network_get_name_description(self, _, ref):
902 return xen_api_success(self._get_network(ref).name_description)
904 def network_get_VIFs(self, _, ref):
905 return xen_api_success(self._get_network(ref).get_VIF_UUIDs())
907 def network_get_PIFs(self, session, ref):
908 return xen_api_success(self._get_network(ref).get_PIF_UUIDs())
910 def network_set_name_label(self, _, ref, val):
911 return xen_api_success(self._get_network(ref).set_name_label(val))
913 def network_set_name_description(self, _, ref, val):
914 return xen_api_success(self._get_network(ref).set_name_description(val))
916 # Xen API: Class PIF
917 # ----------------------------------------------------------------
919 PIF_attr_ro = ['metrics']
920 PIF_attr_rw = ['device',
921 'network',
922 'host',
923 'MAC',
924 'MTU',
925 'VLAN']
927 PIF_attr_inst = PIF_attr_rw
929 PIF_methods = [('create_VLAN', 'int')]
931 def _get_PIF(self, ref):
932 return XendNode.instance().pifs[ref]
934 def PIF_destroy(self, _, ref):
935 try:
936 return xen_api_success(XendNode.instance().PIF_destroy(ref))
937 except PIFIsPhysical, exn:
938 return xen_api_error(['PIF_IS_PHYSICAL', ref])
940 # object methods
941 def PIF_get_record(self, _, ref):
942 return xen_api_success(self._get_PIF(ref).get_record())
944 def PIF_get_all(self, _):
945 return xen_api_success(XendNode.instance().pifs.keys())
947 def PIF_get_metrics(self, _, ref):
948 return xen_api_success(self._get_PIF(ref).metrics.uuid)
950 def PIF_get_device(self, _, ref):
951 return xen_api_success(self._get_PIF(ref).device)
953 def PIF_get_network(self, _, ref):
954 return xen_api_success(self._get_PIF(ref).network.uuid)
956 def PIF_get_host(self, _, ref):
957 return xen_api_success(self._get_PIF(ref).host.uuid)
959 def PIF_get_MAC(self, _, ref):
960 return xen_api_success(self._get_PIF(ref).mac)
962 def PIF_get_MTU(self, _, ref):
963 return xen_api_success(self._get_PIF(ref).mtu)
965 def PIF_get_VLAN(self, _, ref):
966 return xen_api_success(self._get_PIF(ref).vlan)
968 def PIF_set_device(self, _, ref, device):
969 return xen_api_success(self._get_PIF(ref).set_device(device))
971 def PIF_set_MAC(self, _, ref, mac):
972 return xen_api_success(self._get_PIF(ref).set_mac(mac))
974 def PIF_set_MTU(self, _, ref, mtu):
975 return xen_api_success(self._get_PIF(ref).set_mtu(mtu))
977 def PIF_create_VLAN(self, _, ref, network, vlan):
978 try:
979 vlan = int(vlan)
980 except:
981 return xen_api_error(['VLAN_TAG_INVALID', vlan])
983 try:
984 node = XendNode.instance()
986 if _is_valid_ref(network, node.is_valid_network):
987 return xen_api_success(
988 node.PIF_create_VLAN(ref, network, vlan))
989 else:
990 return xen_api_error(['HANDLE_INVALID', 'network', network])
991 except NetworkAlreadyConnected, exn:
992 return xen_api_error(['NETWORK_ALREADY_CONNECTED',
993 network, exn.pif_uuid])
994 except VLANTagInvalid:
995 return xen_api_error(['VLAN_TAG_INVALID', vlan])
998 # Xen API: Class PIF_metrics
999 # ----------------------------------------------------------------
1001 PIF_metrics_attr_ro = ['io_read_kbs',
1002 'io_write_kbs']
1003 PIF_metrics_attr_rw = []
1004 PIF_methods = []
1006 def PIF_metrics_get_all(self, _):
1007 return xen_api_success(XendNode.instance().pif_metrics.keys())
1009 def _PIF_metrics_get(self, ref):
1010 return XendNode.instance().pif_metrics[ref]
1012 def PIF_metrics_get_record(self, _, ref):
1013 return xen_api_success(self._PIF_metrics_get(ref).get_record())
1015 def PIF_metrics_get_io_read_kbs(self, _, ref):
1016 return xen_api_success(self._PIF_metrics_get(ref).get_io_read_kbs())
1018 def PIF_metrics_get_io_write_kbs(self, _, ref):
1019 return xen_api_success(self._PIF_metrics_get(ref).get_io_write_kbs())
1022 # Xen API: Class VM
1023 # ----------------------------------------------------------------
1025 VM_attr_ro = ['power_state',
1026 'resident_on',
1027 'memory_static_max',
1028 'memory_static_min',
1029 'VCPUs_number',
1030 'consoles',
1031 'VIFs',
1032 'VBDs',
1033 'VTPMs',
1034 'tools_version',
1035 'domid',
1036 'is_control_domain',
1037 'metrics'
1040 VM_attr_rw = ['name_label',
1041 'name_description',
1042 'user_version',
1043 'is_a_template',
1044 'auto_power_on',
1045 'memory_dynamic_max',
1046 'memory_dynamic_min',
1047 'VCPUs_params',
1048 'actions_after_shutdown',
1049 'actions_after_reboot',
1050 'actions_after_suspend',
1051 'actions_after_crash',
1052 'PV_bootloader',
1053 'PV_kernel',
1054 'PV_ramdisk',
1055 'PV_args',
1056 'PV_bootloader_args',
1057 'HVM_boot_policy',
1058 'HVM_boot_params',
1059 'platform',
1060 'PCI_bus',
1061 'other_config']
1063 VM_methods = [('clone', 'VM'),
1064 ('start', None),
1065 ('pause', None),
1066 ('unpause', None),
1067 ('clean_shutdown', None),
1068 ('clean_reboot', None),
1069 ('hard_shutdown', None),
1070 ('hard_reboot', None),
1071 ('suspend', None),
1072 ('resume', None),
1073 ('send_sysrq', None),
1074 ('add_to_HVM_boot_params', None),
1075 ('remove_from_HVM_boot_params', None),
1076 ('add_to_VCPUs_params', None),
1077 ('remove_from_VCPUs_params', None),
1078 ('add_to_platform', None),
1079 ('remove_from_platform', None),
1080 ('add_to_other_config', None),
1081 ('remove_from_other_config', None)]
1083 VM_funcs = [('create', 'VM'),
1084 ('get_by_name_label', 'Set(VM)')]
1086 # parameters required for _create()
1087 VM_attr_inst = [
1088 'name_label',
1089 'name_description',
1090 'user_version',
1091 'is_a_template',
1092 'memory_static_max',
1093 'memory_dynamic_max',
1094 'memory_dynamic_min',
1095 'memory_static_min',
1096 'VCPUs_params',
1097 'actions_after_shutdown',
1098 'actions_after_reboot',
1099 'actions_after_suspend',
1100 'actions_after_crash',
1101 'PV_bootloader',
1102 'PV_kernel',
1103 'PV_ramdisk',
1104 'PV_args',
1105 'PV_bootloader_args',
1106 'HVM_boot_policy',
1107 'HVM_boot_params',
1108 'platform',
1109 'PCI_bus',
1110 'other_config']
1112 def VM_get(self, name, session, vm_ref):
1113 return xen_api_success(
1114 XendDomain.instance().get_vm_by_uuid(vm_ref).info[name])
1116 def VM_set(self, name, session, vm_ref, value):
1117 xd = XendDomain.instance()
1118 dominfo = xd.get_vm_by_uuid(vm_ref)
1119 dominfo.info[name] = value
1120 return self._VM_save(dominfo)
1122 def _VM_save(self, dominfo):
1123 XendDomain.instance().managed_config_save(dominfo)
1124 return xen_api_success_void()
1126 # attributes (ro)
1127 def VM_get_power_state(self, session, vm_ref):
1128 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1129 return xen_api_success(dom.get_power_state())
1131 def VM_get_resident_on(self, session, vm_ref):
1132 return xen_api_success(XendNode.instance().uuid)
1134 def VM_get_memory_static_max(self, session, vm_ref):
1135 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1136 return xen_api_success(dom.get_memory_static_max())
1138 def VM_get_memory_static_min(self, session, vm_ref):
1139 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1140 return xen_api_success(dom.get_memory_static_min())
1142 def VM_get_VCPUs_number(self, session, vm_ref):
1143 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1144 return xen_api_success(dom.getVCpuCount())
1146 def VM_get_VIFs(self, session, vm_ref):
1147 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1148 return xen_api_success(dom.get_vifs())
1150 def VM_get_VBDs(self, session, vm_ref):
1151 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1152 return xen_api_success(dom.get_vbds())
1154 def VM_get_VTPMs(self, session, vm_ref):
1155 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1156 return xen_api_success(dom.get_vtpms())
1158 def VM_get_consoles(self, session, vm_ref):
1159 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1160 return xen_api_success(dom.get_consoles())
1162 def VM_get_tools_version(self, session, vm_ref):
1163 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1164 return dom.get_tools_version()
1166 def VM_get_metrics(self, _, vm_ref):
1167 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1168 return xen_api_success(dom.get_metrics())
1170 # attributes (rw)
1171 def VM_get_name_label(self, session, vm_ref):
1172 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1173 return xen_api_success(dom.getName())
1175 def VM_get_name_description(self, session, vm_ref):
1176 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1177 return xen_api_todo()
1179 def VM_get_user_version(self, session, vm_ref):
1180 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1181 return xen_api_todo()
1183 def VM_get_is_a_template(self, session, vm_ref):
1184 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1185 return xen_api_todo()
1187 def VM_get_memory_dynamic_max(self, session, vm_ref):
1188 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1189 return xen_api_success(dom.get_memory_dynamic_max())
1191 def VM_get_memory_dynamic_min(self, session, vm_ref):
1192 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1193 return xen_api_success(dom.get_memory_dynamic_min())
1195 def VM_get_VCPUs_params(self, session, vm_ref):
1196 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1197 return xen_api_success(dom.get_vcpus_params())
1199 def VM_get_actions_after_shutdown(self, session, vm_ref):
1200 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1201 return xen_api_success(dom.get_on_shutdown())
1203 def VM_get_actions_after_reboot(self, session, vm_ref):
1204 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1205 return xen_api_success(dom.get_on_reboot())
1207 def VM_get_actions_after_suspend(self, session, vm_ref):
1208 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1209 return xen_api_success(dom.get_on_suspend())
1211 def VM_get_actions_after_crash(self, session, vm_ref):
1212 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1213 return xen_api_success(dom.get_on_crash())
1215 def VM_get_PV_bootloader(self, session, vm_ref):
1216 return self.VM_get('PV_bootloader', session, vm_ref)
1218 def VM_get_PV_kernel(self, session, vm_ref):
1219 return self.VM_get('PV_kernel', session, vm_ref)
1221 def VM_get_PV_ramdisk(self, session, vm_ref):
1222 return self.VM_get('PV_ramdisk', session, vm_ref)
1224 def VM_get_PV_args(self, session, vm_ref):
1225 return self.VM_get('PV_args', session, vm_ref)
1227 def VM_get_PV_bootloader_args(self, session, vm_ref):
1228 return self.VM_get('PV_bootloader_args', session, vm_ref)
1230 def VM_get_HVM_boot_policy(self, session, vm_ref):
1231 return self.VM_get('HVM_boot_policy', session, vm_ref)
1233 def VM_get_HVM_boot_params(self, session, vm_ref):
1234 return self.VM_get('HVM_boot_params', session, vm_ref)
1236 def VM_get_platform(self, session, vm_ref):
1237 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1238 return xen_api_success(dom.get_platform())
1240 def VM_get_PCI_bus(self, session, vm_ref):
1241 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1242 return dom.get_pci_bus()
1244 def VM_set_PCI_bus(self, session, vm_ref, val):
1245 return self.VM_set('PCI_bus', session, vm_ref, val)
1247 def VM_get_other_config(self, session, vm_ref):
1248 return self.VM_get('other_config', session, vm_ref)
1250 def VM_get_domid(self, _, ref):
1251 domid = XendDomain.instance().get_vm_by_uuid(ref).getDomid()
1252 return xen_api_success(domid is None and -1 or domid)
1254 def VM_get_is_control_domain(self, session, vm_ref):
1255 xd = XendDomain.instance()
1256 return xen_api_success(
1257 xd.get_vm_by_uuid(vm_ref) == xd.privilegedDomain())
1259 def VM_set_name_label(self, session, vm_ref, label):
1260 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1261 dom.setName(label)
1262 return self._VM_save(dom)
1264 def VM_set_name_description(self, session, vm_ref, desc):
1265 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1266 return xen_api_todo()
1268 def VM_set_user_version(self, session, vm_ref, ver):
1269 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1270 return xen_api_todo()
1272 def VM_set_is_a_template(self, session, vm_ref, is_template):
1273 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1274 return xen_api_todo()
1276 def VM_set_memory_dynamic_max(self, session, vm_ref, mem):
1277 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1278 return xen_api_todo()
1280 def VM_set_memory_dynamic_min(self, session, vm_ref, mem):
1281 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1282 return xen_api_todo()
1284 def VM_set_VCPUs_params(self, session, vm_ref, value):
1285 return self.VM_set('vcpus_params', session, vm_ref, value)
1287 def VM_add_to_VCPUs_params(self, session, vm_ref, key, value):
1288 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1289 if 'vcpus_params' not in dom.info:
1290 dom.info['vcpus_params'] = {}
1291 dom.info['vcpus_params'][key] = value
1292 return self._VM_save(dom)
1294 def VM_remove_from_VCPUs_params(self, session, vm_ref, key):
1295 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1296 if 'vcpus_params' in dom.info \
1297 and key in dom.info['vcpus_params']:
1298 del dom.info['vcpus_params'][key]
1299 return self._VM_save(dom)
1300 else:
1301 return xen_api_success_void()
1303 def VM_set_actions_after_shutdown(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_shutdown', session, vm_ref, action)
1308 def VM_set_actions_after_reboot(self, session, vm_ref, action):
1309 if action not in XEN_API_ON_NORMAL_EXIT:
1310 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1311 return self.VM_set('actions_after_reboot', session, vm_ref, action)
1313 def VM_set_actions_after_suspend(self, session, vm_ref, action):
1314 if action not in XEN_API_ON_NORMAL_EXIT:
1315 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1316 return self.VM_set('actions_after_suspend', session, vm_ref, action)
1318 def VM_set_actions_after_crash(self, session, vm_ref, action):
1319 if action not in XEN_API_ON_CRASH_BEHAVIOUR:
1320 return xen_api_error(['VM_ON_CRASH_BEHAVIOUR_INVALID', vm_ref])
1321 return self.VM_set('actions_after_crash', session, vm_ref, action)
1323 def VM_set_HVM_boot_policy(self, session, vm_ref, value):
1324 if value != "" and value != "BIOS order":
1325 return xen_api_error(
1326 ['VALUE_NOT_SUPPORTED', 'VM.HVM_boot_policy', value,
1327 'Xend supports only the "BIOS order" boot policy.'])
1328 else:
1329 return self.VM_set('HVM_boot_policy', session, vm_ref, value)
1331 def VM_set_HVM_boot_params(self, session, vm_ref, value):
1332 return self.VM_set('HVM_boot_params', session, vm_ref, value)
1334 def VM_add_to_HVM_boot_params(self, session, vm_ref, key, value):
1335 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1336 if 'HVM_boot_params' not in dom.info:
1337 dom.info['HVM_boot_params'] = {}
1338 dom.info['HVM_boot_params'][key] = value
1339 return self._VM_save(dom)
1341 def VM_remove_from_HVM_boot_params(self, session, vm_ref, key):
1342 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1343 if 'HVM_boot_params' in dom.info \
1344 and key in dom.info['HVM_boot_params']:
1345 del dom.info['HVM_boot_params'][key]
1346 return self._VM_save(dom)
1347 else:
1348 return xen_api_success_void()
1350 def VM_set_PV_bootloader(self, session, vm_ref, value):
1351 return self.VM_set('PV_bootloader', session, vm_ref, value)
1353 def VM_set_PV_kernel(self, session, vm_ref, value):
1354 return self.VM_set('PV_kernel', session, vm_ref, value)
1356 def VM_set_PV_ramdisk(self, session, vm_ref, value):
1357 return self.VM_set('PV_ramdisk', session, vm_ref, value)
1359 def VM_set_PV_args(self, session, vm_ref, value):
1360 return self.VM_set('PV_args', session, vm_ref, value)
1362 def VM_set_PV_bootloader_args(self, session, vm_ref, value):
1363 return self.VM_set('PV_bootloader_args', session, vm_ref, value)
1365 def VM_set_platform(self, session, vm_ref, value):
1366 return self.VM_set('platform', session, vm_ref, value)
1368 def VM_add_to_platform(self, session, vm_ref, key, value):
1369 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1370 plat = dom.get_platform()
1371 plat[key] = value
1372 return self.VM_set_platform(session, vm_ref, plat)
1374 def VM_remove_from_platform(self, session, vm_ref, key):
1375 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1376 plat = dom.get_platform()
1377 if key in plat:
1378 del plat[key]
1379 return self.VM_set_platform(session, vm_ref, plat)
1380 else:
1381 return xen_api_success_void()
1383 def VM_set_other_config(self, session, vm_ref, value):
1384 return self.VM_set('other_config', session, vm_ref, value)
1386 def VM_add_to_other_config(self, session, vm_ref, key, value):
1387 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1388 if dom and 'other_config' in dom.info:
1389 dom.info['other_config'][key] = value
1390 return self._VM_save(dom)
1392 def VM_remove_from_other_config(self, session, vm_ref, key):
1393 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1394 if dom and 'other_config' in dom.info \
1395 and key in dom.info['other_config']:
1396 del dom.info['other_config'][key]
1397 return self._VM_save(dom)
1398 else:
1399 return xen_api_success_void()
1401 # class methods
1402 def VM_get_all(self, session):
1403 refs = [d.get_uuid() for d in XendDomain.instance().list('all')]
1404 return xen_api_success(refs)
1406 def VM_get_by_name_label(self, session, label):
1407 xendom = XendDomain.instance()
1408 dom = xendom.domain_lookup_nr(label)
1409 if dom:
1410 return xen_api_success([dom.get_uuid()])
1411 return xen_api_success([])
1413 def VM_create(self, session, vm_struct):
1414 xendom = XendDomain.instance()
1415 domuuid = XendTask.log_progress(0, 100,
1416 xendom.create_domain, vm_struct)
1417 return xen_api_success(domuuid)
1419 # object methods
1420 def VM_get_record(self, session, vm_ref):
1421 xendom = XendDomain.instance()
1422 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1423 if not xeninfo:
1424 return xen_api_error(['HANDLE_INVALID', 'VM', vm_ref])
1426 domid = xeninfo.getDomid()
1428 record = {
1429 'uuid': xeninfo.get_uuid(),
1430 'power_state': xeninfo.get_power_state(),
1431 'name_label': xeninfo.getName(),
1432 'name_description': xeninfo.getName(),
1433 'user_version': 1,
1434 'is_a_template': False,
1435 'auto_power_on': False,
1436 'resident_on': XendNode.instance().uuid,
1437 'memory_static_min': xeninfo.get_memory_static_min(),
1438 'memory_static_max': xeninfo.get_memory_static_max(),
1439 'memory_dynamic_min': xeninfo.get_memory_dynamic_min(),
1440 'memory_dynamic_max': xeninfo.get_memory_dynamic_max(),
1441 'VCPUs_params': xeninfo.get_vcpus_params(),
1442 'VCPUs_number': xeninfo.getVCpuCount(),
1443 'actions_after_shutdown': xeninfo.get_on_shutdown(),
1444 'actions_after_reboot': xeninfo.get_on_reboot(),
1445 'actions_after_suspend': xeninfo.get_on_suspend(),
1446 'actions_after_crash': xeninfo.get_on_crash(),
1447 'consoles': xeninfo.get_consoles(),
1448 'VIFs': xeninfo.get_vifs(),
1449 'VBDs': xeninfo.get_vbds(),
1450 'VTPMs': xeninfo.get_vtpms(),
1451 'PV_bootloader': xeninfo.info.get('PV_bootloader'),
1452 'PV_kernel': xeninfo.info.get('PV_kernel'),
1453 'PV_ramdisk': xeninfo.info.get('PV_ramdisk'),
1454 'PV_args': xeninfo.info.get('PV_args'),
1455 'PV_bootloader_args': xeninfo.info.get('PV_bootloader_args'),
1456 'HVM_boot_policy': xeninfo.info.get('HVM_boot_policy'),
1457 'HVM_boot_params': xeninfo.info.get('HVM_boot_params'),
1458 'platform': xeninfo.get_platform(),
1459 'PCI_bus': xeninfo.get_pci_bus(),
1460 'tools_version': xeninfo.get_tools_version(),
1461 'other_config': xeninfo.info.get('other_config', {}),
1462 'domid': domid is None and -1 or domid,
1463 'is_control_domain': xeninfo == xendom.privilegedDomain(),
1465 return xen_api_success(record)
1467 def VM_clean_reboot(self, session, vm_ref):
1468 xendom = XendDomain.instance()
1469 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1470 XendTask.log_progress(0, 100, xeninfo.shutdown, "reboot")
1471 return xen_api_success_void()
1473 def VM_clean_shutdown(self, session, vm_ref):
1474 xendom = XendDomain.instance()
1475 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1476 XendTask.log_progress(0, 100, xeninfo.shutdown, "poweroff")
1477 return xen_api_success_void()
1479 def VM_clone(self, session, vm_ref):
1480 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1482 def VM_destroy(self, session, vm_ref):
1483 return XendTask.log_progress(0, 100, do_vm_func,
1484 "domain_delete", vm_ref)
1486 def VM_hard_reboot(self, session, vm_ref):
1487 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1489 def VM_hard_shutdown(self, session, vm_ref):
1490 return XendTask.log_progress(0, 100, do_vm_func,
1491 "domain_destroy", vm_ref)
1492 def VM_pause(self, session, vm_ref):
1493 return XendTask.log_progress(0, 100, do_vm_func,
1494 "domain_pause", vm_ref)
1496 def VM_resume(self, session, vm_ref, start_paused):
1497 return XendTask.log_progress(0, 100, do_vm_func,
1498 "domain_resume", vm_ref,
1499 start_paused = start_paused)
1501 def VM_start(self, session, vm_ref, start_paused):
1502 try:
1503 return XendTask.log_progress(0, 100, do_vm_func,
1504 "domain_start", vm_ref,
1505 start_paused = start_paused)
1506 except HVMRequired, exn:
1507 return xen_api_error(['VM_HVM_REQUIRED', vm_ref])
1509 def VM_suspend(self, session, vm_ref):
1510 return XendTask.log_progress(0, 100, do_vm_func,
1511 "domain_suspend", vm_ref)
1513 def VM_unpause(self, session, vm_ref):
1514 return XendTask.log_progress(0, 100, do_vm_func,
1515 "domain_unpause", vm_ref)
1517 def VM_send_sysrq(self, _, vm_ref, req):
1518 xendom = XendDomain.instance()
1519 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1520 xeninfo.send_sysrq(req)
1521 return xen_api_success_void()
1523 # Xen API: Class VM_metrics
1524 # ----------------------------------------------------------------
1526 VM_metrics_attr_ro = ['memory_actual',
1527 'vcpus_number',
1528 'vcpus_utilisation']
1529 VM_metrics_attr_rw = []
1530 VM_metrics_methods = []
1532 def _VM_metrics_get(self, ref):
1533 return XendVMMetrics.get_by_uuid(ref)
1535 def VM_metrics_get_all(self, _):
1536 return xen_api_success(XendVMMetrics.get_all())
1538 def VM_metrics_get_record(self, _, ref):
1539 return xen_api_success(self._VM_metrics_get(ref).get_record())
1541 def VM_metrics_get_memory_actual(self, _, ref):
1542 return xen_api_success(self._VM_metrics_get(ref).get_memory_actual())
1544 def VM_metrics_get_vcpus_number(self, _, ref):
1545 return xen_api_success(self._VM_metrics_get(ref).get_vcpus_number())
1547 def VM_metrics_get_vcpus_utilisation(self, _, ref):
1548 return xen_api_success(self._VM_metrics_get(ref).get_metrics_get_vcpus_utilisation())
1550 # Xen API: Class VBD
1551 # ----------------------------------------------------------------
1553 VBD_attr_ro = ['metrics']
1554 VBD_attr_rw = ['VM',
1555 'VDI',
1556 'device',
1557 'bootable',
1558 'mode',
1559 'type']
1561 VBD_attr_inst = VBD_attr_rw
1563 VBD_methods = [('media_change', None)]
1564 VBD_funcs = [('create', 'VBD')]
1566 # object methods
1567 def VBD_get_record(self, session, vbd_ref):
1568 xendom = XendDomain.instance()
1569 vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1570 if not vm:
1571 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1572 cfg = vm.get_dev_xenapi_config('vbd', vbd_ref)
1573 if not cfg:
1574 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1576 valid_vbd_keys = self.VBD_attr_ro + self.VBD_attr_rw + \
1577 self.Base_attr_ro + self.Base_attr_rw
1579 return_cfg = {}
1580 for k in cfg.keys():
1581 if k in valid_vbd_keys:
1582 return_cfg[k] = cfg[k]
1584 return_cfg['metrics'] = vbd_ref
1586 return xen_api_success(return_cfg)
1588 def VBD_media_change(self, session, vbd_ref, vdi_ref):
1589 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1591 # class methods
1592 def VBD_create(self, session, vbd_struct):
1593 xendom = XendDomain.instance()
1594 if not xendom.is_valid_vm(vbd_struct['VM']):
1595 return xen_api_error(['HANDLE_INVALID', 'VM', vbd_struct['VM']])
1597 dom = xendom.get_vm_by_uuid(vbd_struct['VM'])
1598 vbd_ref = ''
1599 try:
1600 # new VBD via VDI/SR
1601 vdi_ref = vbd_struct.get('VDI')
1602 vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
1603 if not vdi:
1604 return xen_api_error(['HANDLE_INVALID', 'VDI', vdi_ref])
1605 vdi_image = vdi.get_location()
1606 vbd_ref = XendTask.log_progress(0, 100,
1607 dom.create_vbd,
1608 vbd_struct, vdi_image)
1609 except XendError:
1610 return xen_api_todo()
1612 xendom.managed_config_save(dom)
1613 return xen_api_success(vbd_ref)
1616 def VBD_destroy(self, session, vbd_ref):
1617 xendom = XendDomain.instance()
1618 vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1619 if not vm:
1620 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1622 XendTask.log_progress(0, 100, vm.destroy_vbd, vbd_ref)
1623 return xen_api_success_void()
1625 def _VBD_get(self, vbd_ref, prop):
1626 return xen_api_success(
1627 XendDomain.instance().get_dev_property_by_uuid(
1628 'vbd', vbd_ref, prop))
1630 # attributes (ro)
1631 def VBD_get_metrics(self, _, vbd_ref):
1632 return xen_api_success(vbd_ref)
1634 # attributes (rw)
1635 def VBD_get_VM(self, session, vbd_ref):
1636 return self._VBD_get(vbd_ref, 'VM')
1638 def VBD_get_VDI(self, session, vbd_ref):
1639 return self._VBD_get(vbd_ref, 'VDI')
1641 def VBD_get_device(self, session, vbd_ref):
1642 return self._VBD_get(vbd_ref, 'device')
1644 def VBD_get_bootable(self, session, vbd_ref):
1645 return self._VBD_get(vbd_ref, 'bootable')
1647 def VBD_get_mode(self, session, vbd_ref):
1648 return self._VBD_get(vbd_ref, 'mode')
1650 def VBD_get_type(self, session, vbd_ref):
1651 return self._VBD_get(vbd_ref, 'type')
1653 def VBD_set_bootable(self, session, vbd_ref, bootable):
1654 bootable = bool(bootable)
1655 xd = XendDomain.instance()
1656 vm = xd.get_vm_with_dev_uuid('vbd', vbd_ref)
1657 vm.set_dev_property('vbd', vbd_ref, 'bootable', bootable)
1658 xd.managed_config_save(vm)
1659 return xen_api_success_void()
1661 def VBD_get_all(self, session):
1662 xendom = XendDomain.instance()
1663 vbds = [d.get_vbds() for d in XendDomain.instance().list('all')]
1664 vbds = reduce(lambda x, y: x + y, vbds)
1665 return xen_api_success(vbds)
1668 # Xen API: Class VBD_metrics
1669 # ----------------------------------------------------------------
1671 VBD_metrics_attr_ro = ['io_read_kbs',
1672 'io_write_kbs']
1673 VBD_metrics_attr_rw = []
1674 VBD_methods = []
1676 def VBD_metrics_get_record(self, _, ref):
1677 vm = XendDomain.instance().get_vm_with_dev_uuid('vbd', ref)
1678 if not vm:
1679 return xen_api_error(['HANDLE_INVALID', 'VBD_metrics', ref])
1680 return xen_api_success(
1681 { 'io_read_kbs' : vm.get_dev_property('vbd', ref, 'io_read_kbs'),
1682 'io_write_kbs' : vm.get_dev_property('vbd', ref, 'io_write_kbs') })
1684 def VBD_metrics_get_io_read_kbs(self, _, ref):
1685 return self._VBD_get(ref, 'io_read_kbs')
1687 def VBD_metrics_get_io_write_kbs(self, session, ref):
1688 return self._VBD_get(ref, 'io_write_kbs')
1691 # Xen API: Class VIF
1692 # ----------------------------------------------------------------
1694 VIF_attr_ro = ['metrics']
1695 VIF_attr_rw = ['device',
1696 'network',
1697 'VM',
1698 'MAC',
1699 'MTU']
1701 VIF_attr_inst = VIF_attr_rw
1703 VIF_funcs = [('create', 'VIF')]
1706 # object methods
1707 def VIF_get_record(self, session, vif_ref):
1708 xendom = XendDomain.instance()
1709 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
1710 if not vm:
1711 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
1712 cfg = vm.get_dev_xenapi_config('vif', vif_ref)
1713 if not cfg:
1714 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
1716 valid_vif_keys = self.VIF_attr_ro + self.VIF_attr_rw + \
1717 self.Base_attr_ro + self.Base_attr_rw
1719 return_cfg = {}
1720 for k in cfg.keys():
1721 if k in valid_vif_keys:
1722 return_cfg[k] = cfg[k]
1724 return_cfg['metrics'] = vif_ref
1726 return xen_api_success(return_cfg)
1728 # class methods
1729 def VIF_create(self, session, vif_struct):
1730 xendom = XendDomain.instance()
1731 if xendom.is_valid_vm(vif_struct['VM']):
1732 dom = xendom.get_vm_by_uuid(vif_struct['VM'])
1733 try:
1734 vif_ref = dom.create_vif(vif_struct)
1735 xendom.managed_config_save(dom)
1736 return xen_api_success(vif_ref)
1737 except XendError:
1738 return xen_api_error(XEND_ERROR_TODO)
1739 else:
1740 return xen_api_error(['HANDLE_INVALID', 'VM', vif_struct['VM']])
1743 def VIF_destroy(self, session, vif_ref):
1744 xendom = XendDomain.instance()
1745 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
1746 if not vm:
1747 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
1749 vm.destroy_vif(vif_ref)
1750 return xen_api_success_void()
1752 def _VIF_get(self, ref, prop):
1753 return xen_api_success(
1754 XendDomain.instance().get_dev_property_by_uuid('vif', ref, prop))
1756 # getters/setters
1757 def VIF_get_metrics(self, _, vif_ref):
1758 return xen_api_success(vif_ref)
1760 def VIF_get_VM(self, session, vif_ref):
1761 xendom = XendDomain.instance()
1762 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
1763 return xen_api_success(vm.get_uuid())
1765 def VIF_get_MTU(self, session, vif_ref):
1766 return self._VIF_get(vif_ref, 'MTU')
1768 def VIF_get_MAC(self, session, vif_ref):
1769 return self._VIF_get(vif_ref, 'MAC')
1771 def VIF_get_device(self, session, vif_ref):
1772 return self._VIF_get(vif_ref, 'device')
1774 def VIF_get_all(self, session):
1775 xendom = XendDomain.instance()
1776 vifs = [d.get_vifs() for d in XendDomain.instance().list('all')]
1777 vifs = reduce(lambda x, y: x + y, vifs)
1778 return xen_api_success(vifs)
1781 # Xen API: Class VIF_metrics
1782 # ----------------------------------------------------------------
1784 VIF_metrics_attr_ro = ['io_read_kbs',
1785 'io_write_kbs']
1786 VIF_metrics_attr_rw = []
1787 VIF_methods = []
1789 def VIF_metrics_get_record(self, _, ref):
1790 vm = XendDomain.instance().get_vm_with_dev_uuid('vif', ref)
1791 if not vm:
1792 return xen_api_error(['HANDLE_INVALID', 'VIF_metrics', ref])
1793 return xen_api_success(
1794 { 'io_read_kbs' : vm.get_dev_property('vif', ref, 'io_read_kbs'),
1795 'io_write_kbs' : vm.get_dev_property('vif', ref, 'io_write_kbs') })
1797 def VIF_metrics_get_io_read_kbs(self, _, ref):
1798 return self._VIF_get(ref, 'io_read_kbs')
1800 def VIF_metrics_get_io_write_kbs(self, session, ref):
1801 return self._VIF_get(ref, 'io_write_kbs')
1804 # Xen API: Class VDI
1805 # ----------------------------------------------------------------
1806 VDI_attr_ro = ['SR',
1807 'VBDs',
1808 'physical_utilisation',
1809 'sector_size',
1810 'type']
1811 VDI_attr_rw = ['name_label',
1812 'name_description',
1813 'virtual_size',
1814 'sharable',
1815 'read_only']
1816 VDI_attr_inst = VDI_attr_ro + VDI_attr_rw
1818 VDI_methods = [('snapshot', 'VDI')]
1819 VDI_funcs = [('create', 'VDI'),
1820 ('get_by_name_label', 'Set(VDI)')]
1822 def _get_VDI(self, ref):
1823 return XendNode.instance().get_vdi_by_uuid(ref)
1825 def VDI_get_VBDs(self, session, vdi_ref):
1826 return xen_api_todo()
1828 def VDI_get_physical_utilisation(self, session, vdi_ref):
1829 return xen_api_success(self._get_VDI(vdi_ref).
1830 get_physical_utilisation())
1832 def VDI_get_sector_size(self, session, vdi_ref):
1833 return xen_api_success(self._get_VDI(vdi_ref).sector_size)
1835 def VDI_get_type(self, session, vdi_ref):
1836 return xen_api_success(self._get_VDI(vdi_ref).type)
1838 def VDI_get_name_label(self, session, vdi_ref):
1839 return xen_api_success(self._get_VDI(vdi_ref).name_label)
1841 def VDI_get_name_description(self, session, vdi_ref):
1842 return xen_api_success(self._get_VDI(vdi_ref).name_description)
1844 def VDI_get_SR(self, session, vdi_ref):
1845 return xen_api_success(self._get_VDI(vdi_ref).sr_uuid)
1847 def VDI_get_virtual_size(self, session, vdi_ref):
1848 return xen_api_success(self._get_VDI(vdi_ref).virtual_size)
1850 def VDI_get_sharable(self, session, vdi_ref):
1851 return xen_api_success(self._get_VDI(vdi_ref).sharable)
1853 def VDI_get_read_only(self, session, vdi_ref):
1854 return xen_api_success(self._get_VDI(vdi_ref).read_only)
1856 def VDI_set_name_label(self, session, vdi_ref, value):
1857 self._get_VDI(vdi_ref).name_label = value
1858 return xen_api_success_void()
1860 def VDI_set_name_description(self, session, vdi_ref, value):
1861 self._get_VDI(vdi_ref).name_description = value
1862 return xen_api_success_void()
1864 def VDI_set_virtual_size(self, session, vdi_ref, value):
1865 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1867 def VDI_set_sharable(self, session, vdi_ref, value):
1868 self._get_VDI(vdi_ref).sharable = bool(value)
1869 return xen_api_success_void()
1871 def VDI_set_read_only(self, session, vdi_ref, value):
1872 self._get_VDI(vdi_ref).read_only = bool(value)
1873 return xen_api_success_void()
1875 # Object Methods
1876 def VDI_snapshot(self, session, vdi_ref):
1877 return xen_api_todo()
1879 def VDI_destroy(self, session, vdi_ref):
1880 sr = XendNode.instance().get_sr_containing_vdi(vdi_ref)
1881 sr.destroy_vdi(vdi_ref)
1882 return xen_api_success_void()
1884 def VDI_get_record(self, session, vdi_ref):
1885 image = XendNode.instance().get_vdi_by_uuid(vdi_ref)
1886 return xen_api_success({
1887 'uuid': vdi_ref,
1888 'name_label': image.name_label,
1889 'name_description': image.name_description,
1890 'SR': image.sr_uuid,
1891 'VBDs': [], # TODO
1892 'virtual_size': image.virtual_size,
1893 'physical_utilisation': image.physical_utilisation,
1894 'sector_size': image.sector_size,
1895 'type': image.type,
1896 'sharable': image.sharable,
1897 'read_only': image.read_only,
1898 })
1900 # Class Functions
1901 def VDI_create(self, session, vdi_struct):
1902 sr_ref = vdi_struct.get('SR')
1903 xennode = XendNode.instance()
1904 if not xennode.is_valid_sr(sr_ref):
1905 return xen_api_error(['HANDLE_INVALID', 'SR', sr_ref])
1907 vdi_uuid = xennode.srs[sr_ref].create_vdi(vdi_struct)
1908 return xen_api_success(vdi_uuid)
1910 def VDI_get_all(self, session):
1911 xennode = XendNode.instance()
1912 vdis = [sr.get_vdis() for sr in xennode.srs.values()]
1913 return xen_api_success(reduce(lambda x, y: x + y, vdis))
1915 def VDI_get_by_name_label(self, session, name):
1916 xennode = XendNode.instance()
1917 return xen_api_success(xennode.get_vdi_by_name_label(name))
1920 # Xen API: Class VTPM
1921 # ----------------------------------------------------------------
1923 VTPM_attr_rw = [ ]
1924 VTPM_attr_ro = ['VM',
1925 'backend']
1927 VTPM_attr_inst = VTPM_attr_rw
1929 VTPM_funcs = [('create', 'VTPM')]
1931 # object methods
1932 def VTPM_get_record(self, session, vtpm_ref):
1933 xendom = XendDomain.instance()
1934 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
1935 if not vm:
1936 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
1937 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
1938 if not cfg:
1939 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
1940 valid_vtpm_keys = self.VTPM_attr_ro + self.VTPM_attr_rw + \
1941 self.Base_attr_ro + self.Base_attr_rw
1942 return_cfg = {}
1943 for k in cfg.keys():
1944 if k in valid_vtpm_keys:
1945 return_cfg[k] = cfg[k]
1947 return xen_api_success(return_cfg)
1949 # Class Functions
1950 def VTPM_get_backend(self, session, vtpm_ref):
1951 xendom = XendDomain.instance()
1952 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
1953 if not vm:
1954 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
1955 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
1956 if not cfg:
1957 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
1958 if not cfg.has_key('backend'):
1959 return xen_api_error(['VTPM backend not set'])
1960 return xen_api_success(cfg['backend'])
1962 def VTPM_get_VM(self, session, vtpm_ref):
1963 xendom = XendDomain.instance()
1964 return xen_api_success(xendom.get_dev_property_by_uuid('vtpm',
1965 vtpm_ref, 'VM'))
1967 def VTPM_destroy(self, session, vtpm_ref):
1968 xendom = XendDomain.instance()
1969 dom = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
1970 if dom:
1971 if dom.state != XEN_API_VM_POWER_STATE_HALTED:
1972 vm_ref = dom.get_dev_property('vtpm', vtpm_ref, 'VM')
1973 return xen_api_error(['VM_BAD_POWER_STATE', vm_ref,
1974 XendDomain.POWER_STATE_NAMES[XEN_API_VM_POWER_STATE_HALTED],
1975 XendDomain.POWER_STATE_NAMES[dom.state]])
1976 from xen.xend.server import tpmif
1977 tpmif.destroy_vtpmstate(dom.getName())
1978 return xen_api_success_void()
1979 else:
1980 return xen_api_error(['HANDLE_INVALID', 'VM', vtpm_struct['VM']])
1982 # class methods
1983 def VTPM_create(self, session, vtpm_struct):
1984 xendom = XendDomain.instance()
1985 if xendom.is_valid_vm(vtpm_struct['VM']):
1986 dom = xendom.get_vm_by_uuid(vtpm_struct['VM'])
1987 try:
1988 vtpm_ref = dom.create_vtpm(vtpm_struct)
1989 xendom.managed_config_save(dom)
1990 return xen_api_success(vtpm_ref)
1991 except XendError:
1992 return xen_api_error(XEND_ERROR_TODO)
1993 else:
1994 return xen_api_error(['HANDLE_INVALID', 'VM', vtpm_struct['VM']])
1996 def VTPM_get_all(self, session):
1997 xendom = XendDomain.instance()
1998 vtpms = [d.get_vtpms() for d in XendDomain.instance().list('all')]
1999 vtpms = reduce(lambda x, y: x + y, vtpms)
2000 return xen_api_success(vtpms)
2002 # Xen API: Class console
2003 # ----------------------------------------------------------------
2006 console_attr_ro = ['location', 'protocol', 'VM']
2007 console_attr_rw = ['other_config']
2008 console_funcs = [('create', 'console')]
2010 def console_get_all(self, session):
2011 xendom = XendDomain.instance()
2012 cons = [d.get_consoles() for d in XendDomain.instance().list('all')]
2013 cons = reduce(lambda x, y: x + y, cons)
2014 return xen_api_success(cons)
2016 def console_get_location(self, session, console_ref):
2017 return xen_api_success(xendom.get_dev_property_by_uuid('console',
2018 console_ref,
2019 'location'))
2021 def console_get_protocol(self, session, console_ref):
2022 return xen_api_success(xendom.get_dev_property_by_uuid('console',
2023 console_ref,
2024 'protocol'))
2026 def console_get_VM(self, session, console_ref):
2027 xendom = XendDomain.instance()
2028 vm = xendom.get_vm_with_dev_uuid('console', console_ref)
2029 return xen_api_success(vm.get_uuid())
2031 # object methods
2032 def console_get_record(self, session, console_ref):
2033 xendom = XendDomain.instance()
2034 vm = xendom.get_vm_with_dev_uuid('console', console_ref)
2035 if not vm:
2036 return xen_api_error(['HANDLE_INVALID', 'console', console_ref])
2037 cfg = vm.get_dev_xenapi_config('console', console_ref)
2038 if not cfg:
2039 return xen_api_error(['HANDLE_INVALID', 'console', console_ref])
2041 valid_console_keys = self.console_attr_ro + self.console_attr_rw + \
2042 self.Base_attr_ro + self.Base_attr_rw
2044 return_cfg = {}
2045 for k in cfg.keys():
2046 if k in valid_console_keys:
2047 return_cfg[k] = cfg[k]
2049 return xen_api_success(return_cfg)
2051 def console_create(self, session, console_struct):
2052 xendom = XendDomain.instance()
2053 if not xendom.is_valid_vm(console_struct['VM']):
2054 return xen_api_error(['HANDLE_INVALID', 'VM',
2055 console_struct['VM']])
2057 dom = xendom.get_vm_by_uuid(console_struct['VM'])
2058 try:
2059 if 'protocol' not in console_struct:
2060 return xen_api_error(['CONSOLE_PROTOCOL_INVALID',
2061 'No protocol specified'])
2063 console_ref = dom.create_console(console_struct)
2064 xendom.managed_config_save(dom)
2065 return xen_api_success(console_ref)
2066 except XendError, e:
2067 return xen_api_error([XEND_ERROR_TODO, str(e)])
2069 # Xen API: Class SR
2070 # ----------------------------------------------------------------
2071 SR_attr_ro = ['VDIs',
2072 'virtual_allocation',
2073 'physical_utilisation',
2074 'physical_size',
2075 'type',
2076 'location']
2078 SR_attr_rw = ['name_label',
2079 'name_description']
2081 SR_attr_inst = ['physical_size',
2082 'type',
2083 'location',
2084 'name_label',
2085 'name_description']
2087 SR_methods = [('clone', 'SR')]
2088 SR_funcs = [('get_by_name_label', 'Set(SR)'),
2089 ('get_by_uuid', 'SR')]
2091 # Class Functions
2092 def SR_get_all(self, session):
2093 return xen_api_success(XendNode.instance().get_all_sr_uuid())
2095 def SR_get_by_name_label(self, session, label):
2096 return xen_api_success(XendNode.instance().get_sr_by_name(label))
2098 def SR_create(self, session):
2099 return xen_api_error(XEND_ERROR_UNSUPPORTED)
2101 # Class Methods
2102 def SR_clone(self, session, sr_ref):
2103 return xen_api_error(XEND_ERROR_UNSUPPORTED)
2105 def SR_destroy(self, session, sr_ref):
2106 return xen_api_error(XEND_ERROR_UNSUPPORTED)
2108 def SR_get_record(self, session, sr_ref):
2109 sr = XendNode.instance().get_sr(sr_ref)
2110 if sr:
2111 return xen_api_success(sr.get_record())
2112 return xen_api_error(['HANDLE_INVALID', 'SR', sr_ref])
2114 # Attribute acceess
2116 def _get_SR_func(self, sr_ref, func):
2117 return xen_api_success(getattr(XendNode.instance().get_sr(sr_ref),
2118 func)())
2120 def _get_SR_attr(self, sr_ref, attr):
2121 return xen_api_success(getattr(XendNode.instance().get_sr(sr_ref),
2122 attr))
2124 def SR_get_VDIs(self, _, ref):
2125 return self._get_SR_func(ref, 'list_images')
2127 def SR_get_virtual_allocation(self, _, ref):
2128 return self._get_SR_func(ref, 'virtual_allocation')
2130 def SR_get_physical_utilisation(self, _, ref):
2131 return self._get_SR_func(ref, 'physical_utilisation')
2133 def SR_get_physical_size(self, _, ref):
2134 return self._get_SR_func(ref, 'physical_size')
2136 def SR_get_type(self, _, ref):
2137 return self._get_SR_attr(ref, 'type')
2139 def SR_get_location(self, _, ref):
2140 return self._get_SR_attr(ref, 'location')
2142 def SR_get_name_label(self, _, ref):
2143 return self._get_SR_attr(ref, 'name_label')
2145 def SR_get_name_description(self, _, ref):
2146 return self._get_SR_attr(ref, 'name_description')
2148 def SR_set_name_label(self, session, sr_ref, value):
2149 sr = XendNode.instance.get_sr(sr_ref)
2150 if sr:
2151 sr.name_label = value
2152 XendNode.instance().save()
2153 return xen_api_success_void()
2155 def SR_set_name_description(self, session, sr_ref, value):
2156 sr = XendNode.instance.get_sr(sr_ref)
2157 if sr:
2158 sr.name_description = value
2159 XendNode.instance().save()
2160 return xen_api_success_void()
2163 # Xen API: Class debug
2164 # ----------------------------------------------------------------
2166 debug_methods = [('destroy', None),
2167 ('get_record', 'debug')]
2168 debug_funcs = [('wait', None),
2169 ('return_failure', None)]
2171 def debug_wait(self, session, wait_secs):
2172 import time
2173 prog_units = 100/float(wait_secs)
2174 for i in range(int(wait_secs)):
2175 XendTask.log_progress(prog_units * i, prog_units * (i + 1),
2176 time.sleep, 1)
2177 return xen_api_success_void()
2180 def debug_return_failure(self, session):
2181 return xen_api_error(['DEBUG_FAIL', session])
2183 def debug_create(self, session):
2184 debug_uuid = uuid.createString()
2185 self._debug[debug_uuid] = None
2186 return xen_api_success(debug_uuid)
2188 def debug_destroy(self, session, debug_ref):
2189 del self._debug[debug_ref]
2190 return xen_api_success_void()
2192 def debug_get_record(self, session, debug_ref):
2193 return xen_api_success({'uuid': debug_ref})
2196 def list_all_methods(self, _):
2197 def _funcs():
2198 return [getattr(XendAPI, x) for x in XendAPI.__dict__]
2200 return xen_api_success([x.api for x in _funcs()
2201 if hasattr(x, 'api')])
2202 list_all_methods.api = '_UNSUPPORTED_list_all_methods'
2205 class XendAPIAsyncProxy:
2206 """ A redirector for Async.Class.function calls to XendAPI
2207 but wraps the call for use with the XendTaskManager.
2209 @ivar xenapi: Xen API instance
2210 @ivar method_map: Mapping from XMLRPC method name to callable objects.
2211 """
2213 method_prefix = 'Async.'
2215 def __init__(self, xenapi):
2216 """Initialises the Async Proxy by making a map of all
2217 implemented Xen API methods for use with XendTaskManager.
2219 @param xenapi: XendAPI instance
2220 """
2221 self.xenapi = xenapi
2222 self.method_map = {}
2223 for method_name in dir(self.xenapi):
2224 method = getattr(self.xenapi, method_name)
2225 if method_name[0] != '_' and hasattr(method, 'async') \
2226 and method.async == True:
2227 self.method_map[method.api] = method
2229 def _dispatch(self, method, args):
2230 """Overridden method so that SimpleXMLRPCServer will
2231 resolve methods through this method rather than through
2232 inspection.
2234 @param method: marshalled method name from XMLRPC.
2235 @param args: marshalled arguments from XMLRPC.
2236 """
2238 # Only deal with method names that start with "Async."
2239 if not method.startswith(self.method_prefix):
2240 return xen_api_error(['MESSAGE_METHOD_UNKNOWN', method])
2242 # Lookup synchronous version of the method
2243 synchronous_method_name = method[len(self.method_prefix):]
2244 if synchronous_method_name not in self.method_map:
2245 return xen_api_error(['MESSAGE_METHOD_UNKNOWN', method])
2247 method = self.method_map[synchronous_method_name]
2249 # Check that we've got enough arguments before issuing a task ID.
2250 needed = argcounts[method.api]
2251 if len(args) != needed:
2252 return xen_api_error(['MESSAGE_PARAMETER_COUNT_MISMATCH',
2253 self.method_prefix + method.api, needed,
2254 len(args)])
2256 # Validate the session before proceeding
2257 session = args[0]
2258 if not auth_manager().is_session_valid(session):
2259 return xen_api_error(['SESSION_INVALID', session])
2261 # create and execute the task, and return task_uuid
2262 return_type = getattr(method, 'return_type', None)
2263 task_uuid = XendTaskManager.create_task(method, args,
2264 synchronous_method_name,
2265 return_type,
2266 synchronous_method_name,
2267 session)
2268 return xen_api_success(task_uuid)
2271 # Auto generate some stubs based on XendAPI introspection
2273 if __name__ == "__main__":
2274 def output(line):
2275 print ' ' + line
2277 classes = ['VDI', 'SR']
2278 for cls in classes:
2279 ro_attrs = getattr(XendAPI, '%s_attr_ro' % cls, [])
2280 rw_attrs = getattr(XendAPI, '%s_attr_rw' % cls, [])
2281 methods = getattr(XendAPI, '%s_methods' % cls, [])
2282 funcs = getattr(XendAPI, '%s_funcs' % cls, [])
2284 ref = '%s_ref' % cls
2286 for attr_name in ro_attrs + rw_attrs + XendAPI.Base_attr_ro:
2287 getter_name = '%s_get_%s' % (cls, attr_name)
2288 output('def %s(self, session, %s):' % (getter_name, ref))
2289 output(' return xen_api_todo()')
2291 for attr_name in rw_attrs + XendAPI.Base_attr_rw:
2292 setter_name = '%s_set_%s' % (cls, attr_name)
2293 output('def %s(self, session, %s, value):' % (setter_name, ref))
2294 output(' return xen_api_todo()')
2296 for method_name in methods + XendAPI.Base_methods:
2297 method_full_name = '%s_%s' % (cls,method_name)
2298 output('def %s(self, session, %s):' % (method_full_name, ref))
2299 output(' return xen_api_todo()')
2301 for func_name in funcs + XendAPI.Base_funcs:
2302 func_full_name = '%s_%s' % (cls, func_name)
2303 output('def %s(self, session):' % func_full_name)
2304 output(' return xen_api_todo()')