direct-io.hg

view tools/python/xen/xend/XendAPI.py @ 14388:b39c0a79d4d5

Added the clear flag to host.dmesg, and added host.get_log. Use these to
implement xm dmesg and xm log using the Xen-API.

Signed-off-by: Tom Wilkie <tom.wilkie@gmail.com>
Signed-off-by: Ewan Mellor <ewan@xensource.com>
author Ewan Mellor <ewan@xensource.com>
date Wed Mar 14 23:16:59 2007 +0000 (2007-03-14)
parents 036e42d1c9bb
children edccebeea4a3
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 ('add_to_HVM_boot_params', None),
1074 ('remove_from_HVM_boot_params', None),
1075 ('add_to_VCPUs_params', None),
1076 ('remove_from_VCPUs_params', None),
1077 ('add_to_platform', None),
1078 ('remove_from_platform', None),
1079 ('add_to_other_config', None),
1080 ('remove_from_other_config', None)]
1082 VM_funcs = [('create', 'VM'),
1083 ('get_by_name_label', 'Set(VM)')]
1085 # parameters required for _create()
1086 VM_attr_inst = [
1087 'name_label',
1088 'name_description',
1089 'user_version',
1090 'is_a_template',
1091 'memory_static_max',
1092 'memory_dynamic_max',
1093 'memory_dynamic_min',
1094 'memory_static_min',
1095 'VCPUs_params',
1096 'actions_after_shutdown',
1097 'actions_after_reboot',
1098 'actions_after_suspend',
1099 'actions_after_crash',
1100 'PV_bootloader',
1101 'PV_kernel',
1102 'PV_ramdisk',
1103 'PV_args',
1104 'PV_bootloader_args',
1105 'HVM_boot_policy',
1106 'HVM_boot_params',
1107 'platform',
1108 'PCI_bus',
1109 'other_config']
1111 def VM_get(self, name, session, vm_ref):
1112 return xen_api_success(
1113 XendDomain.instance().get_vm_by_uuid(vm_ref).info[name])
1115 def VM_set(self, name, session, vm_ref, value):
1116 xd = XendDomain.instance()
1117 dominfo = xd.get_vm_by_uuid(vm_ref)
1118 dominfo.info[name] = value
1119 return self._VM_save(dominfo)
1121 def _VM_save(self, dominfo):
1122 XendDomain.instance().managed_config_save(dominfo)
1123 return xen_api_success_void()
1125 # attributes (ro)
1126 def VM_get_power_state(self, session, vm_ref):
1127 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1128 return xen_api_success(dom.get_power_state())
1130 def VM_get_resident_on(self, session, vm_ref):
1131 return xen_api_success(XendNode.instance().uuid)
1133 def VM_get_memory_static_max(self, session, vm_ref):
1134 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1135 return xen_api_success(dom.get_memory_static_max())
1137 def VM_get_memory_static_min(self, session, vm_ref):
1138 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1139 return xen_api_success(dom.get_memory_static_min())
1141 def VM_get_VCPUs_number(self, session, vm_ref):
1142 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1143 return xen_api_success(dom.getVCpuCount())
1145 def VM_get_VIFs(self, session, vm_ref):
1146 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1147 return xen_api_success(dom.get_vifs())
1149 def VM_get_VBDs(self, session, vm_ref):
1150 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1151 return xen_api_success(dom.get_vbds())
1153 def VM_get_VTPMs(self, session, vm_ref):
1154 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1155 return xen_api_success(dom.get_vtpms())
1157 def VM_get_consoles(self, session, vm_ref):
1158 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1159 return xen_api_success(dom.get_consoles())
1161 def VM_get_tools_version(self, session, vm_ref):
1162 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1163 return dom.get_tools_version()
1165 def VM_get_metrics(self, _, vm_ref):
1166 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1167 return xen_api_success(dom.get_metrics())
1169 # attributes (rw)
1170 def VM_get_name_label(self, session, vm_ref):
1171 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1172 return xen_api_success(dom.getName())
1174 def VM_get_name_description(self, session, vm_ref):
1175 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1176 return xen_api_todo()
1178 def VM_get_user_version(self, session, vm_ref):
1179 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1180 return xen_api_todo()
1182 def VM_get_is_a_template(self, session, vm_ref):
1183 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1184 return xen_api_todo()
1186 def VM_get_memory_dynamic_max(self, session, vm_ref):
1187 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1188 return xen_api_success(dom.get_memory_dynamic_max())
1190 def VM_get_memory_dynamic_min(self, session, vm_ref):
1191 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1192 return xen_api_success(dom.get_memory_dynamic_min())
1194 def VM_get_VCPUs_params(self, session, vm_ref):
1195 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1196 return xen_api_success(dom.get_vcpus_params())
1198 def VM_get_actions_after_shutdown(self, session, vm_ref):
1199 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1200 return xen_api_success(dom.get_on_shutdown())
1202 def VM_get_actions_after_reboot(self, session, vm_ref):
1203 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1204 return xen_api_success(dom.get_on_reboot())
1206 def VM_get_actions_after_suspend(self, session, vm_ref):
1207 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1208 return xen_api_success(dom.get_on_suspend())
1210 def VM_get_actions_after_crash(self, session, vm_ref):
1211 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1212 return xen_api_success(dom.get_on_crash())
1214 def VM_get_PV_bootloader(self, session, vm_ref):
1215 return self.VM_get('PV_bootloader', session, vm_ref)
1217 def VM_get_PV_kernel(self, session, vm_ref):
1218 return self.VM_get('PV_kernel', session, vm_ref)
1220 def VM_get_PV_ramdisk(self, session, vm_ref):
1221 return self.VM_get('PV_ramdisk', session, vm_ref)
1223 def VM_get_PV_args(self, session, vm_ref):
1224 return self.VM_get('PV_args', session, vm_ref)
1226 def VM_get_PV_bootloader_args(self, session, vm_ref):
1227 return self.VM_get('PV_bootloader_args', session, vm_ref)
1229 def VM_get_HVM_boot_policy(self, session, vm_ref):
1230 return self.VM_get('HVM_boot_policy', session, vm_ref)
1232 def VM_get_HVM_boot_params(self, session, vm_ref):
1233 return self.VM_get('HVM_boot_params', session, vm_ref)
1235 def VM_get_platform(self, session, vm_ref):
1236 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1237 return xen_api_success(dom.get_platform())
1239 def VM_get_PCI_bus(self, session, vm_ref):
1240 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1241 return dom.get_pci_bus()
1243 def VM_set_PCI_bus(self, session, vm_ref, val):
1244 return self.VM_set('PCI_bus', session, vm_ref, val)
1246 def VM_get_other_config(self, session, vm_ref):
1247 return self.VM_get('other_config', session, vm_ref)
1249 def VM_get_domid(self, _, ref):
1250 domid = XendDomain.instance().get_vm_by_uuid(ref).getDomid()
1251 return xen_api_success(domid is None and -1 or domid)
1253 def VM_get_is_control_domain(self, session, vm_ref):
1254 xd = XendDomain.instance()
1255 return xen_api_success(
1256 xd.get_vm_by_uuid(vm_ref) == xd.privilegedDomain())
1258 def VM_set_name_label(self, session, vm_ref, label):
1259 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1260 dom.setName(label)
1261 return self._VM_save(dom)
1263 def VM_set_name_description(self, session, vm_ref, desc):
1264 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1265 return xen_api_todo()
1267 def VM_set_user_version(self, session, vm_ref, ver):
1268 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1269 return xen_api_todo()
1271 def VM_set_is_a_template(self, session, vm_ref, is_template):
1272 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1273 return xen_api_todo()
1275 def VM_set_memory_dynamic_max(self, session, vm_ref, mem):
1276 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1277 return xen_api_todo()
1279 def VM_set_memory_dynamic_min(self, session, vm_ref, mem):
1280 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1281 return xen_api_todo()
1283 def VM_set_VCPUs_params(self, session, vm_ref, value):
1284 return self.VM_set('vcpus_params', session, vm_ref, value)
1286 def VM_add_to_VCPUs_params(self, session, vm_ref, key, value):
1287 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1288 if 'vcpus_params' not in dom.info:
1289 dom.info['vcpus_params'] = {}
1290 dom.info['vcpus_params'][key] = value
1291 return self._VM_save(dom)
1293 def VM_remove_from_VCPUs_params(self, session, vm_ref, key):
1294 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1295 if 'vcpus_params' in dom.info \
1296 and key in dom.info['vcpus_params']:
1297 del dom.info['vcpus_params'][key]
1298 return self._VM_save(dom)
1299 else:
1300 return xen_api_success_void()
1302 def VM_set_actions_after_shutdown(self, session, vm_ref, action):
1303 if action not in XEN_API_ON_NORMAL_EXIT:
1304 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1305 return self.VM_set('actions_after_shutdown', session, vm_ref, action)
1307 def VM_set_actions_after_reboot(self, session, vm_ref, action):
1308 if action not in XEN_API_ON_NORMAL_EXIT:
1309 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1310 return self.VM_set('actions_after_reboot', session, vm_ref, action)
1312 def VM_set_actions_after_suspend(self, session, vm_ref, action):
1313 if action not in XEN_API_ON_NORMAL_EXIT:
1314 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1315 return self.VM_set('actions_after_suspend', session, vm_ref, action)
1317 def VM_set_actions_after_crash(self, session, vm_ref, action):
1318 if action not in XEN_API_ON_CRASH_BEHAVIOUR:
1319 return xen_api_error(['VM_ON_CRASH_BEHAVIOUR_INVALID', vm_ref])
1320 return self.VM_set('actions_after_crash', session, vm_ref, action)
1322 def VM_set_HVM_boot_policy(self, session, vm_ref, value):
1323 if value != "" and value != "BIOS order":
1324 return xen_api_error(
1325 ['VALUE_NOT_SUPPORTED', 'VM.HVM_boot_policy', value,
1326 'Xend supports only the "BIOS order" boot policy.'])
1327 else:
1328 return self.VM_set('HVM_boot_policy', session, vm_ref, value)
1330 def VM_set_HVM_boot_params(self, session, vm_ref, value):
1331 return self.VM_set('HVM_boot_params', session, vm_ref, value)
1333 def VM_add_to_HVM_boot_params(self, session, vm_ref, key, value):
1334 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1335 if 'HVM_boot_params' not in dom.info:
1336 dom.info['HVM_boot_params'] = {}
1337 dom.info['HVM_boot_params'][key] = value
1338 return self._VM_save(dom)
1340 def VM_remove_from_HVM_boot_params(self, session, vm_ref, key):
1341 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1342 if 'HVM_boot_params' in dom.info \
1343 and key in dom.info['HVM_boot_params']:
1344 del dom.info['HVM_boot_params'][key]
1345 return self._VM_save(dom)
1346 else:
1347 return xen_api_success_void()
1349 def VM_set_PV_bootloader(self, session, vm_ref, value):
1350 return self.VM_set('PV_bootloader', session, vm_ref, value)
1352 def VM_set_PV_kernel(self, session, vm_ref, value):
1353 return self.VM_set('PV_kernel', session, vm_ref, value)
1355 def VM_set_PV_ramdisk(self, session, vm_ref, value):
1356 return self.VM_set('PV_ramdisk', session, vm_ref, value)
1358 def VM_set_PV_args(self, session, vm_ref, value):
1359 return self.VM_set('PV_args', session, vm_ref, value)
1361 def VM_set_PV_bootloader_args(self, session, vm_ref, value):
1362 return self.VM_set('PV_bootloader_args', session, vm_ref, value)
1364 def VM_set_platform(self, session, vm_ref, value):
1365 return self.VM_set('platform', session, vm_ref, value)
1367 def VM_add_to_platform(self, session, vm_ref, key, value):
1368 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1369 plat = dom.get_platform()
1370 plat[key] = value
1371 return self.VM_set_platform(session, vm_ref, plat)
1373 def VM_remove_from_platform(self, session, vm_ref, key):
1374 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1375 plat = dom.get_platform()
1376 if key in plat:
1377 del plat[key]
1378 return self.VM_set_platform(session, vm_ref, plat)
1379 else:
1380 return xen_api_success_void()
1382 def VM_set_other_config(self, session, vm_ref, value):
1383 return self.VM_set('other_config', session, vm_ref, value)
1385 def VM_add_to_other_config(self, session, vm_ref, key, value):
1386 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1387 if dom and 'other_config' in dom.info:
1388 dom.info['other_config'][key] = value
1389 return self._VM_save(dom)
1391 def VM_remove_from_other_config(self, session, vm_ref, key):
1392 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1393 if dom and 'other_config' in dom.info \
1394 and key in dom.info['other_config']:
1395 del dom.info['other_config'][key]
1396 return self._VM_save(dom)
1397 else:
1398 return xen_api_success_void()
1400 # class methods
1401 def VM_get_all(self, session):
1402 refs = [d.get_uuid() for d in XendDomain.instance().list('all')]
1403 return xen_api_success(refs)
1405 def VM_get_by_name_label(self, session, label):
1406 xendom = XendDomain.instance()
1407 dom = xendom.domain_lookup_nr(label)
1408 if dom:
1409 return xen_api_success([dom.get_uuid()])
1410 return xen_api_success([])
1412 def VM_create(self, session, vm_struct):
1413 xendom = XendDomain.instance()
1414 domuuid = XendTask.log_progress(0, 100,
1415 xendom.create_domain, vm_struct)
1416 return xen_api_success(domuuid)
1418 # object methods
1419 def VM_get_record(self, session, vm_ref):
1420 xendom = XendDomain.instance()
1421 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1422 if not xeninfo:
1423 return xen_api_error(['HANDLE_INVALID', 'VM', vm_ref])
1425 domid = xeninfo.getDomid()
1427 record = {
1428 'uuid': xeninfo.get_uuid(),
1429 'power_state': xeninfo.get_power_state(),
1430 'name_label': xeninfo.getName(),
1431 'name_description': xeninfo.getName(),
1432 'user_version': 1,
1433 'is_a_template': False,
1434 'auto_power_on': False,
1435 'resident_on': XendNode.instance().uuid,
1436 'memory_static_min': xeninfo.get_memory_static_min(),
1437 'memory_static_max': xeninfo.get_memory_static_max(),
1438 'memory_dynamic_min': xeninfo.get_memory_dynamic_min(),
1439 'memory_dynamic_max': xeninfo.get_memory_dynamic_max(),
1440 'VCPUs_params': xeninfo.get_vcpus_params(),
1441 'VCPUs_number': xeninfo.getVCpuCount(),
1442 'actions_after_shutdown': xeninfo.get_on_shutdown(),
1443 'actions_after_reboot': xeninfo.get_on_reboot(),
1444 'actions_after_suspend': xeninfo.get_on_suspend(),
1445 'actions_after_crash': xeninfo.get_on_crash(),
1446 'consoles': xeninfo.get_consoles(),
1447 'VIFs': xeninfo.get_vifs(),
1448 'VBDs': xeninfo.get_vbds(),
1449 'VTPMs': xeninfo.get_vtpms(),
1450 'PV_bootloader': xeninfo.info.get('PV_bootloader'),
1451 'PV_kernel': xeninfo.info.get('PV_kernel'),
1452 'PV_ramdisk': xeninfo.info.get('PV_ramdisk'),
1453 'PV_args': xeninfo.info.get('PV_args'),
1454 'PV_bootloader_args': xeninfo.info.get('PV_bootloader_args'),
1455 'HVM_boot_policy': xeninfo.info.get('HVM_boot_policy'),
1456 'HVM_boot_params': xeninfo.info.get('HVM_boot_params'),
1457 'platform': xeninfo.get_platform(),
1458 'PCI_bus': xeninfo.get_pci_bus(),
1459 'tools_version': xeninfo.get_tools_version(),
1460 'other_config': xeninfo.info.get('other_config', {}),
1461 'domid': domid is None and -1 or domid,
1462 'is_control_domain': xeninfo == xendom.privilegedDomain(),
1464 return xen_api_success(record)
1466 def VM_clean_reboot(self, session, vm_ref):
1467 xendom = XendDomain.instance()
1468 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1469 XendTask.log_progress(0, 100, xeninfo.shutdown, "reboot")
1470 return xen_api_success_void()
1472 def VM_clean_shutdown(self, session, vm_ref):
1473 xendom = XendDomain.instance()
1474 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1475 XendTask.log_progress(0, 100, xeninfo.shutdown, "poweroff")
1476 return xen_api_success_void()
1478 def VM_clone(self, session, vm_ref):
1479 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1481 def VM_destroy(self, session, vm_ref):
1482 return XendTask.log_progress(0, 100, do_vm_func,
1483 "domain_delete", vm_ref)
1485 def VM_hard_reboot(self, session, vm_ref):
1486 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1488 def VM_hard_shutdown(self, session, vm_ref):
1489 return XendTask.log_progress(0, 100, do_vm_func,
1490 "domain_destroy", vm_ref)
1491 def VM_pause(self, session, vm_ref):
1492 return XendTask.log_progress(0, 100, do_vm_func,
1493 "domain_pause", vm_ref)
1495 def VM_resume(self, session, vm_ref, start_paused):
1496 return XendTask.log_progress(0, 100, do_vm_func,
1497 "domain_resume", vm_ref,
1498 start_paused = start_paused)
1500 def VM_start(self, session, vm_ref, start_paused):
1501 try:
1502 return XendTask.log_progress(0, 100, do_vm_func,
1503 "domain_start", vm_ref,
1504 start_paused = start_paused)
1505 except HVMRequired, exn:
1506 return xen_api_error(['VM_HVM_REQUIRED', vm_ref])
1508 def VM_suspend(self, session, vm_ref):
1509 return XendTask.log_progress(0, 100, do_vm_func,
1510 "domain_suspend", vm_ref)
1512 def VM_unpause(self, session, vm_ref):
1513 return XendTask.log_progress(0, 100, do_vm_func,
1514 "domain_unpause", vm_ref)
1516 # Xen API: Class VM_metrics
1517 # ----------------------------------------------------------------
1519 VM_metrics_attr_ro = ['memory_actual',
1520 'vcpus_number',
1521 'vcpus_utilisation']
1522 VM_metrics_attr_rw = []
1523 VM_metrics_methods = []
1525 def _VM_metrics_get(self, ref):
1526 return XendVMMetrics.get_by_uuid(ref)
1528 def VM_metrics_get_all(self, _):
1529 return xen_api_success(XendVMMetrics.get_all())
1531 def VM_metrics_get_record(self, _, ref):
1532 return xen_api_success(self._VM_metrics_get(ref).get_record())
1534 def VM_metrics_get_memory_actual(self, _, ref):
1535 return xen_api_success(self._VM_metrics_get(ref).get_memory_actual())
1537 def VM_metrics_get_vcpus_number(self, _, ref):
1538 return xen_api_success(self._VM_metrics_get(ref).get_vcpus_number())
1540 def VM_metrics_get_vcpus_utilisation(self, _, ref):
1541 return xen_api_success(self._VM_metrics_get(ref).get_metrics_get_vcpus_utilisation())
1543 # Xen API: Class VBD
1544 # ----------------------------------------------------------------
1546 VBD_attr_ro = ['metrics']
1547 VBD_attr_rw = ['VM',
1548 'VDI',
1549 'device',
1550 'bootable',
1551 'mode',
1552 'type']
1554 VBD_attr_inst = VBD_attr_rw
1556 VBD_methods = [('media_change', None)]
1557 VBD_funcs = [('create', 'VBD')]
1559 # object methods
1560 def VBD_get_record(self, session, vbd_ref):
1561 xendom = XendDomain.instance()
1562 vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1563 if not vm:
1564 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1565 cfg = vm.get_dev_xenapi_config('vbd', vbd_ref)
1566 if not cfg:
1567 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1569 valid_vbd_keys = self.VBD_attr_ro + self.VBD_attr_rw + \
1570 self.Base_attr_ro + self.Base_attr_rw
1572 return_cfg = {}
1573 for k in cfg.keys():
1574 if k in valid_vbd_keys:
1575 return_cfg[k] = cfg[k]
1577 return_cfg['metrics'] = vbd_ref
1579 return xen_api_success(return_cfg)
1581 def VBD_media_change(self, session, vbd_ref, vdi_ref):
1582 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1584 # class methods
1585 def VBD_create(self, session, vbd_struct):
1586 xendom = XendDomain.instance()
1587 if not xendom.is_valid_vm(vbd_struct['VM']):
1588 return xen_api_error(['HANDLE_INVALID', 'VM', vbd_struct['VM']])
1590 dom = xendom.get_vm_by_uuid(vbd_struct['VM'])
1591 vbd_ref = ''
1592 try:
1593 # new VBD via VDI/SR
1594 vdi_ref = vbd_struct.get('VDI')
1595 vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
1596 if not vdi:
1597 return xen_api_error(['HANDLE_INVALID', 'VDI', vdi_ref])
1598 vdi_image = vdi.get_location()
1599 vbd_ref = XendTask.log_progress(0, 100,
1600 dom.create_vbd,
1601 vbd_struct, vdi_image)
1602 except XendError:
1603 return xen_api_todo()
1605 xendom.managed_config_save(dom)
1606 return xen_api_success(vbd_ref)
1609 def VBD_destroy(self, session, vbd_ref):
1610 xendom = XendDomain.instance()
1611 vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1612 if not vm:
1613 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1615 XendTask.log_progress(0, 100, vm.destroy_vbd, vbd_ref)
1616 return xen_api_success_void()
1618 def _VBD_get(self, vbd_ref, prop):
1619 return xen_api_success(
1620 XendDomain.instance().get_dev_property_by_uuid(
1621 'vbd', vbd_ref, prop))
1623 # attributes (ro)
1624 def VBD_get_metrics(self, _, vbd_ref):
1625 return xen_api_success(vbd_ref)
1627 # attributes (rw)
1628 def VBD_get_VM(self, session, vbd_ref):
1629 return self._VBD_get(vbd_ref, 'VM')
1631 def VBD_get_VDI(self, session, vbd_ref):
1632 return self._VBD_get(vbd_ref, 'VDI')
1634 def VBD_get_device(self, session, vbd_ref):
1635 return self._VBD_get(vbd_ref, 'device')
1637 def VBD_get_bootable(self, session, vbd_ref):
1638 return self._VBD_get(vbd_ref, 'bootable')
1640 def VBD_get_mode(self, session, vbd_ref):
1641 return self._VBD_get(vbd_ref, 'mode')
1643 def VBD_get_type(self, session, vbd_ref):
1644 return self._VBD_get(vbd_ref, 'type')
1646 def VBD_set_bootable(self, session, vbd_ref, bootable):
1647 bootable = bool(bootable)
1648 xd = XendDomain.instance()
1649 vm = xd.get_vm_with_dev_uuid('vbd', vbd_ref)
1650 vm.set_dev_property('vbd', vbd_ref, 'bootable', bootable)
1651 xd.managed_config_save(vm)
1652 return xen_api_success_void()
1654 def VBD_get_all(self, session):
1655 xendom = XendDomain.instance()
1656 vbds = [d.get_vbds() for d in XendDomain.instance().list('all')]
1657 vbds = reduce(lambda x, y: x + y, vbds)
1658 return xen_api_success(vbds)
1661 # Xen API: Class VBD_metrics
1662 # ----------------------------------------------------------------
1664 VBD_metrics_attr_ro = ['io_read_kbs',
1665 'io_write_kbs']
1666 VBD_metrics_attr_rw = []
1667 VBD_methods = []
1669 def VBD_metrics_get_record(self, _, ref):
1670 vm = XendDomain.instance().get_vm_with_dev_uuid('vbd', ref)
1671 if not vm:
1672 return xen_api_error(['HANDLE_INVALID', 'VBD_metrics', ref])
1673 return xen_api_success(
1674 { 'io_read_kbs' : vm.get_dev_property('vbd', ref, 'io_read_kbs'),
1675 'io_write_kbs' : vm.get_dev_property('vbd', ref, 'io_write_kbs') })
1677 def VBD_metrics_get_io_read_kbs(self, _, ref):
1678 return self._VBD_get(ref, 'io_read_kbs')
1680 def VBD_metrics_get_io_write_kbs(self, session, ref):
1681 return self._VBD_get(ref, 'io_write_kbs')
1684 # Xen API: Class VIF
1685 # ----------------------------------------------------------------
1687 VIF_attr_ro = ['metrics']
1688 VIF_attr_rw = ['device',
1689 'network',
1690 'VM',
1691 'MAC',
1692 'MTU']
1694 VIF_attr_inst = VIF_attr_rw
1696 VIF_funcs = [('create', 'VIF')]
1699 # object methods
1700 def VIF_get_record(self, session, vif_ref):
1701 xendom = XendDomain.instance()
1702 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
1703 if not vm:
1704 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
1705 cfg = vm.get_dev_xenapi_config('vif', vif_ref)
1706 if not cfg:
1707 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
1709 valid_vif_keys = self.VIF_attr_ro + self.VIF_attr_rw + \
1710 self.Base_attr_ro + self.Base_attr_rw
1712 return_cfg = {}
1713 for k in cfg.keys():
1714 if k in valid_vif_keys:
1715 return_cfg[k] = cfg[k]
1717 return_cfg['metrics'] = vif_ref
1719 return xen_api_success(return_cfg)
1721 # class methods
1722 def VIF_create(self, session, vif_struct):
1723 xendom = XendDomain.instance()
1724 if xendom.is_valid_vm(vif_struct['VM']):
1725 dom = xendom.get_vm_by_uuid(vif_struct['VM'])
1726 try:
1727 vif_ref = dom.create_vif(vif_struct)
1728 xendom.managed_config_save(dom)
1729 return xen_api_success(vif_ref)
1730 except XendError:
1731 return xen_api_error(XEND_ERROR_TODO)
1732 else:
1733 return xen_api_error(['HANDLE_INVALID', 'VM', vif_struct['VM']])
1736 def VIF_destroy(self, session, vif_ref):
1737 xendom = XendDomain.instance()
1738 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
1739 if not vm:
1740 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
1742 vm.destroy_vif(vif_ref)
1743 return xen_api_success_void()
1745 def _VIF_get(self, ref, prop):
1746 return xen_api_success(
1747 XendDomain.instance().get_dev_property_by_uuid('vif', ref, prop))
1749 # getters/setters
1750 def VIF_get_metrics(self, _, vif_ref):
1751 return xen_api_success(vif_ref)
1753 def VIF_get_VM(self, session, vif_ref):
1754 xendom = XendDomain.instance()
1755 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
1756 return xen_api_success(vm.get_uuid())
1758 def VIF_get_MTU(self, session, vif_ref):
1759 return self._VIF_get(vif_ref, 'MTU')
1761 def VIF_get_MAC(self, session, vif_ref):
1762 return self._VIF_get(vif_ref, 'MAC')
1764 def VIF_get_device(self, session, vif_ref):
1765 return self._VIF_get(vif_ref, 'device')
1767 def VIF_get_all(self, session):
1768 xendom = XendDomain.instance()
1769 vifs = [d.get_vifs() for d in XendDomain.instance().list('all')]
1770 vifs = reduce(lambda x, y: x + y, vifs)
1771 return xen_api_success(vifs)
1774 # Xen API: Class VIF_metrics
1775 # ----------------------------------------------------------------
1777 VIF_metrics_attr_ro = ['io_read_kbs',
1778 'io_write_kbs']
1779 VIF_metrics_attr_rw = []
1780 VIF_methods = []
1782 def VIF_metrics_get_record(self, _, ref):
1783 vm = XendDomain.instance().get_vm_with_dev_uuid('vif', ref)
1784 if not vm:
1785 return xen_api_error(['HANDLE_INVALID', 'VIF_metrics', ref])
1786 return xen_api_success(
1787 { 'io_read_kbs' : vm.get_dev_property('vif', ref, 'io_read_kbs'),
1788 'io_write_kbs' : vm.get_dev_property('vif', ref, 'io_write_kbs') })
1790 def VIF_metrics_get_io_read_kbs(self, _, ref):
1791 return self._VIF_get(ref, 'io_read_kbs')
1793 def VIF_metrics_get_io_write_kbs(self, session, ref):
1794 return self._VIF_get(ref, 'io_write_kbs')
1797 # Xen API: Class VDI
1798 # ----------------------------------------------------------------
1799 VDI_attr_ro = ['SR',
1800 'VBDs',
1801 'physical_utilisation',
1802 'sector_size',
1803 'type']
1804 VDI_attr_rw = ['name_label',
1805 'name_description',
1806 'virtual_size',
1807 'sharable',
1808 'read_only']
1809 VDI_attr_inst = VDI_attr_ro + VDI_attr_rw
1811 VDI_methods = [('snapshot', 'VDI')]
1812 VDI_funcs = [('create', 'VDI'),
1813 ('get_by_name_label', 'Set(VDI)')]
1815 def _get_VDI(self, ref):
1816 return XendNode.instance().get_vdi_by_uuid(ref)
1818 def VDI_get_VBDs(self, session, vdi_ref):
1819 return xen_api_todo()
1821 def VDI_get_physical_utilisation(self, session, vdi_ref):
1822 return xen_api_success(self._get_VDI(vdi_ref).
1823 get_physical_utilisation())
1825 def VDI_get_sector_size(self, session, vdi_ref):
1826 return xen_api_success(self._get_VDI(vdi_ref).sector_size)
1828 def VDI_get_type(self, session, vdi_ref):
1829 return xen_api_success(self._get_VDI(vdi_ref).type)
1831 def VDI_get_name_label(self, session, vdi_ref):
1832 return xen_api_success(self._get_VDI(vdi_ref).name_label)
1834 def VDI_get_name_description(self, session, vdi_ref):
1835 return xen_api_success(self._get_VDI(vdi_ref).name_description)
1837 def VDI_get_SR(self, session, vdi_ref):
1838 return xen_api_success(self._get_VDI(vdi_ref).sr_uuid)
1840 def VDI_get_virtual_size(self, session, vdi_ref):
1841 return xen_api_success(self._get_VDI(vdi_ref).virtual_size)
1843 def VDI_get_sharable(self, session, vdi_ref):
1844 return xen_api_success(self._get_VDI(vdi_ref).sharable)
1846 def VDI_get_read_only(self, session, vdi_ref):
1847 return xen_api_success(self._get_VDI(vdi_ref).read_only)
1849 def VDI_set_name_label(self, session, vdi_ref, value):
1850 self._get_VDI(vdi_ref).name_label = value
1851 return xen_api_success_void()
1853 def VDI_set_name_description(self, session, vdi_ref, value):
1854 self._get_VDI(vdi_ref).name_description = value
1855 return xen_api_success_void()
1857 def VDI_set_virtual_size(self, session, vdi_ref, value):
1858 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1860 def VDI_set_sharable(self, session, vdi_ref, value):
1861 self._get_VDI(vdi_ref).sharable = bool(value)
1862 return xen_api_success_void()
1864 def VDI_set_read_only(self, session, vdi_ref, value):
1865 self._get_VDI(vdi_ref).read_only = bool(value)
1866 return xen_api_success_void()
1868 # Object Methods
1869 def VDI_snapshot(self, session, vdi_ref):
1870 return xen_api_todo()
1872 def VDI_destroy(self, session, vdi_ref):
1873 sr = XendNode.instance().get_sr_containing_vdi(vdi_ref)
1874 sr.destroy_vdi(vdi_ref)
1875 return xen_api_success_void()
1877 def VDI_get_record(self, session, vdi_ref):
1878 image = XendNode.instance().get_vdi_by_uuid(vdi_ref)
1879 return xen_api_success({
1880 'uuid': vdi_ref,
1881 'name_label': image.name_label,
1882 'name_description': image.name_description,
1883 'SR': image.sr_uuid,
1884 'VBDs': [], # TODO
1885 'virtual_size': image.virtual_size,
1886 'physical_utilisation': image.physical_utilisation,
1887 'sector_size': image.sector_size,
1888 'type': image.type,
1889 'sharable': image.sharable,
1890 'read_only': image.read_only,
1891 })
1893 # Class Functions
1894 def VDI_create(self, session, vdi_struct):
1895 sr_ref = vdi_struct.get('SR')
1896 xennode = XendNode.instance()
1897 if not xennode.is_valid_sr(sr_ref):
1898 return xen_api_error(['HANDLE_INVALID', 'SR', sr_ref])
1900 vdi_uuid = xennode.srs[sr_ref].create_vdi(vdi_struct)
1901 return xen_api_success(vdi_uuid)
1903 def VDI_get_all(self, session):
1904 xennode = XendNode.instance()
1905 vdis = [sr.get_vdis() for sr in xennode.srs.values()]
1906 return xen_api_success(reduce(lambda x, y: x + y, vdis))
1908 def VDI_get_by_name_label(self, session, name):
1909 xennode = XendNode.instance()
1910 return xen_api_success(xennode.get_vdi_by_name_label(name))
1913 # Xen API: Class VTPM
1914 # ----------------------------------------------------------------
1916 VTPM_attr_rw = [ ]
1917 VTPM_attr_ro = ['VM',
1918 'backend']
1920 VTPM_attr_inst = VTPM_attr_rw
1922 VTPM_funcs = [('create', 'VTPM')]
1924 # object methods
1925 def VTPM_get_record(self, session, vtpm_ref):
1926 xendom = XendDomain.instance()
1927 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
1928 if not vm:
1929 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
1930 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
1931 if not cfg:
1932 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
1933 valid_vtpm_keys = self.VTPM_attr_ro + self.VTPM_attr_rw + \
1934 self.Base_attr_ro + self.Base_attr_rw
1935 return_cfg = {}
1936 for k in cfg.keys():
1937 if k in valid_vtpm_keys:
1938 return_cfg[k] = cfg[k]
1940 return xen_api_success(return_cfg)
1942 # Class Functions
1943 def VTPM_get_backend(self, session, vtpm_ref):
1944 xendom = XendDomain.instance()
1945 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
1946 if not vm:
1947 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
1948 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
1949 if not cfg:
1950 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
1951 if not cfg.has_key('backend'):
1952 return xen_api_error(['VTPM backend not set'])
1953 return xen_api_success(cfg['backend'])
1955 def VTPM_get_VM(self, session, vtpm_ref):
1956 xendom = XendDomain.instance()
1957 return xen_api_success(xendom.get_dev_property_by_uuid('vtpm',
1958 vtpm_ref, 'VM'))
1960 def VTPM_destroy(self, session, vtpm_ref):
1961 xendom = XendDomain.instance()
1962 dom = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
1963 if dom:
1964 if dom.state != XEN_API_VM_POWER_STATE_HALTED:
1965 vm_ref = dom.get_dev_property('vtpm', vtpm_ref, 'VM')
1966 return xen_api_error(['VM_BAD_POWER_STATE', vm_ref,
1967 XendDomain.POWER_STATE_NAMES[XEN_API_VM_POWER_STATE_HALTED],
1968 XendDomain.POWER_STATE_NAMES[dom.state]])
1969 from xen.xend.server import tpmif
1970 tpmif.destroy_vtpmstate(dom.getName())
1971 return xen_api_success_void()
1972 else:
1973 return xen_api_error(['HANDLE_INVALID', 'VM', vtpm_struct['VM']])
1975 # class methods
1976 def VTPM_create(self, session, vtpm_struct):
1977 xendom = XendDomain.instance()
1978 if xendom.is_valid_vm(vtpm_struct['VM']):
1979 dom = xendom.get_vm_by_uuid(vtpm_struct['VM'])
1980 try:
1981 vtpm_ref = dom.create_vtpm(vtpm_struct)
1982 xendom.managed_config_save(dom)
1983 return xen_api_success(vtpm_ref)
1984 except XendError:
1985 return xen_api_error(XEND_ERROR_TODO)
1986 else:
1987 return xen_api_error(['HANDLE_INVALID', 'VM', vtpm_struct['VM']])
1989 def VTPM_get_all(self, session):
1990 xendom = XendDomain.instance()
1991 vtpms = [d.get_vtpms() for d in XendDomain.instance().list('all')]
1992 vtpms = reduce(lambda x, y: x + y, vtpms)
1993 return xen_api_success(vtpms)
1995 # Xen API: Class console
1996 # ----------------------------------------------------------------
1999 console_attr_ro = ['location', 'protocol', 'VM']
2000 console_attr_rw = ['other_config']
2001 console_funcs = [('create', 'console')]
2003 def console_get_all(self, session):
2004 xendom = XendDomain.instance()
2005 cons = [d.get_consoles() for d in XendDomain.instance().list('all')]
2006 cons = reduce(lambda x, y: x + y, cons)
2007 return xen_api_success(cons)
2009 def console_get_location(self, session, console_ref):
2010 return xen_api_success(xendom.get_dev_property_by_uuid('console',
2011 console_ref,
2012 'location'))
2014 def console_get_protocol(self, session, console_ref):
2015 return xen_api_success(xendom.get_dev_property_by_uuid('console',
2016 console_ref,
2017 'protocol'))
2019 def console_get_VM(self, session, console_ref):
2020 xendom = XendDomain.instance()
2021 vm = xendom.get_vm_with_dev_uuid('console', console_ref)
2022 return xen_api_success(vm.get_uuid())
2024 # object methods
2025 def console_get_record(self, session, console_ref):
2026 xendom = XendDomain.instance()
2027 vm = xendom.get_vm_with_dev_uuid('console', console_ref)
2028 if not vm:
2029 return xen_api_error(['HANDLE_INVALID', 'console', console_ref])
2030 cfg = vm.get_dev_xenapi_config('console', console_ref)
2031 if not cfg:
2032 return xen_api_error(['HANDLE_INVALID', 'console', console_ref])
2034 valid_console_keys = self.console_attr_ro + self.console_attr_rw + \
2035 self.Base_attr_ro + self.Base_attr_rw
2037 return_cfg = {}
2038 for k in cfg.keys():
2039 if k in valid_console_keys:
2040 return_cfg[k] = cfg[k]
2042 return xen_api_success(return_cfg)
2044 def console_create(self, session, console_struct):
2045 xendom = XendDomain.instance()
2046 if not xendom.is_valid_vm(console_struct['VM']):
2047 return xen_api_error(['HANDLE_INVALID', 'VM',
2048 console_struct['VM']])
2050 dom = xendom.get_vm_by_uuid(console_struct['VM'])
2051 try:
2052 if 'protocol' not in console_struct:
2053 return xen_api_error(['CONSOLE_PROTOCOL_INVALID',
2054 'No protocol specified'])
2056 console_ref = dom.create_console(console_struct)
2057 xendom.managed_config_save(dom)
2058 return xen_api_success(console_ref)
2059 except XendError, e:
2060 return xen_api_error([XEND_ERROR_TODO, str(e)])
2062 # Xen API: Class SR
2063 # ----------------------------------------------------------------
2064 SR_attr_ro = ['VDIs',
2065 'virtual_allocation',
2066 'physical_utilisation',
2067 'physical_size',
2068 'type',
2069 'location']
2071 SR_attr_rw = ['name_label',
2072 'name_description']
2074 SR_attr_inst = ['physical_size',
2075 'type',
2076 'location',
2077 'name_label',
2078 'name_description']
2080 SR_methods = [('clone', 'SR')]
2081 SR_funcs = [('get_by_name_label', 'Set(SR)'),
2082 ('get_by_uuid', 'SR')]
2084 # Class Functions
2085 def SR_get_all(self, session):
2086 return xen_api_success(XendNode.instance().get_all_sr_uuid())
2088 def SR_get_by_name_label(self, session, label):
2089 return xen_api_success(XendNode.instance().get_sr_by_name(label))
2091 def SR_create(self, session):
2092 return xen_api_error(XEND_ERROR_UNSUPPORTED)
2094 # Class Methods
2095 def SR_clone(self, session, sr_ref):
2096 return xen_api_error(XEND_ERROR_UNSUPPORTED)
2098 def SR_destroy(self, session, sr_ref):
2099 return xen_api_error(XEND_ERROR_UNSUPPORTED)
2101 def SR_get_record(self, session, sr_ref):
2102 sr = XendNode.instance().get_sr(sr_ref)
2103 if sr:
2104 return xen_api_success(sr.get_record())
2105 return xen_api_error(['HANDLE_INVALID', 'SR', sr_ref])
2107 # Attribute acceess
2109 def _get_SR_func(self, sr_ref, func):
2110 return xen_api_success(getattr(XendNode.instance().get_sr(sr_ref),
2111 func)())
2113 def _get_SR_attr(self, sr_ref, attr):
2114 return xen_api_success(getattr(XendNode.instance().get_sr(sr_ref),
2115 attr))
2117 def SR_get_VDIs(self, _, ref):
2118 return self._get_SR_func(ref, 'list_images')
2120 def SR_get_virtual_allocation(self, _, ref):
2121 return self._get_SR_func(ref, 'virtual_allocation')
2123 def SR_get_physical_utilisation(self, _, ref):
2124 return self._get_SR_func(ref, 'physical_utilisation')
2126 def SR_get_physical_size(self, _, ref):
2127 return self._get_SR_func(ref, 'physical_size')
2129 def SR_get_type(self, _, ref):
2130 return self._get_SR_attr(ref, 'type')
2132 def SR_get_location(self, _, ref):
2133 return self._get_SR_attr(ref, 'location')
2135 def SR_get_name_label(self, _, ref):
2136 return self._get_SR_attr(ref, 'name_label')
2138 def SR_get_name_description(self, _, ref):
2139 return self._get_SR_attr(ref, 'name_description')
2141 def SR_set_name_label(self, session, sr_ref, value):
2142 sr = XendNode.instance.get_sr(sr_ref)
2143 if sr:
2144 sr.name_label = value
2145 XendNode.instance().save()
2146 return xen_api_success_void()
2148 def SR_set_name_description(self, session, sr_ref, value):
2149 sr = XendNode.instance.get_sr(sr_ref)
2150 if sr:
2151 sr.name_description = value
2152 XendNode.instance().save()
2153 return xen_api_success_void()
2156 # Xen API: Class debug
2157 # ----------------------------------------------------------------
2159 debug_methods = [('destroy', None),
2160 ('get_record', 'debug')]
2161 debug_funcs = [('wait', None),
2162 ('return_failure', None)]
2164 def debug_wait(self, session, wait_secs):
2165 import time
2166 prog_units = 100/float(wait_secs)
2167 for i in range(int(wait_secs)):
2168 XendTask.log_progress(prog_units * i, prog_units * (i + 1),
2169 time.sleep, 1)
2170 return xen_api_success_void()
2173 def debug_return_failure(self, session):
2174 return xen_api_error(['DEBUG_FAIL', session])
2176 def debug_create(self, session):
2177 debug_uuid = uuid.createString()
2178 self._debug[debug_uuid] = None
2179 return xen_api_success(debug_uuid)
2181 def debug_destroy(self, session, debug_ref):
2182 del self._debug[debug_ref]
2183 return xen_api_success_void()
2185 def debug_get_record(self, session, debug_ref):
2186 return xen_api_success({'uuid': debug_ref})
2189 def list_all_methods(self, _):
2190 def _funcs():
2191 return [getattr(XendAPI, x) for x in XendAPI.__dict__]
2193 return xen_api_success([x.api for x in _funcs()
2194 if hasattr(x, 'api')])
2195 list_all_methods.api = '_UNSUPPORTED_list_all_methods'
2198 class XendAPIAsyncProxy:
2199 """ A redirector for Async.Class.function calls to XendAPI
2200 but wraps the call for use with the XendTaskManager.
2202 @ivar xenapi: Xen API instance
2203 @ivar method_map: Mapping from XMLRPC method name to callable objects.
2204 """
2206 method_prefix = 'Async.'
2208 def __init__(self, xenapi):
2209 """Initialises the Async Proxy by making a map of all
2210 implemented Xen API methods for use with XendTaskManager.
2212 @param xenapi: XendAPI instance
2213 """
2214 self.xenapi = xenapi
2215 self.method_map = {}
2216 for method_name in dir(self.xenapi):
2217 method = getattr(self.xenapi, method_name)
2218 if method_name[0] != '_' and hasattr(method, 'async') \
2219 and method.async == True:
2220 self.method_map[method.api] = method
2222 def _dispatch(self, method, args):
2223 """Overridden method so that SimpleXMLRPCServer will
2224 resolve methods through this method rather than through
2225 inspection.
2227 @param method: marshalled method name from XMLRPC.
2228 @param args: marshalled arguments from XMLRPC.
2229 """
2231 # Only deal with method names that start with "Async."
2232 if not method.startswith(self.method_prefix):
2233 return xen_api_error(['MESSAGE_METHOD_UNKNOWN', method])
2235 # Lookup synchronous version of the method
2236 synchronous_method_name = method[len(self.method_prefix):]
2237 if synchronous_method_name not in self.method_map:
2238 return xen_api_error(['MESSAGE_METHOD_UNKNOWN', method])
2240 method = self.method_map[synchronous_method_name]
2242 # Check that we've got enough arguments before issuing a task ID.
2243 needed = argcounts[method.api]
2244 if len(args) != needed:
2245 return xen_api_error(['MESSAGE_PARAMETER_COUNT_MISMATCH',
2246 self.method_prefix + method.api, needed,
2247 len(args)])
2249 # Validate the session before proceeding
2250 session = args[0]
2251 if not auth_manager().is_session_valid(session):
2252 return xen_api_error(['SESSION_INVALID', session])
2254 # create and execute the task, and return task_uuid
2255 return_type = getattr(method, 'return_type', None)
2256 task_uuid = XendTaskManager.create_task(method, args,
2257 synchronous_method_name,
2258 return_type,
2259 synchronous_method_name,
2260 session)
2261 return xen_api_success(task_uuid)
2264 # Auto generate some stubs based on XendAPI introspection
2266 if __name__ == "__main__":
2267 def output(line):
2268 print ' ' + line
2270 classes = ['VDI', 'SR']
2271 for cls in classes:
2272 ro_attrs = getattr(XendAPI, '%s_attr_ro' % cls, [])
2273 rw_attrs = getattr(XendAPI, '%s_attr_rw' % cls, [])
2274 methods = getattr(XendAPI, '%s_methods' % cls, [])
2275 funcs = getattr(XendAPI, '%s_funcs' % cls, [])
2277 ref = '%s_ref' % cls
2279 for attr_name in ro_attrs + rw_attrs + XendAPI.Base_attr_ro:
2280 getter_name = '%s_get_%s' % (cls, attr_name)
2281 output('def %s(self, session, %s):' % (getter_name, ref))
2282 output(' return xen_api_todo()')
2284 for attr_name in rw_attrs + XendAPI.Base_attr_rw:
2285 setter_name = '%s_set_%s' % (cls, attr_name)
2286 output('def %s(self, session, %s, value):' % (setter_name, ref))
2287 output(' return xen_api_todo()')
2289 for method_name in methods + XendAPI.Base_methods:
2290 method_full_name = '%s_%s' % (cls,method_name)
2291 output('def %s(self, session, %s):' % (method_full_name, ref))
2292 output(' return xen_api_todo()')
2294 for func_name in funcs + XendAPI.Base_funcs:
2295 func_full_name = '%s_%s' % (cls, func_name)
2296 output('def %s(self, session):' % func_full_name)
2297 output(' return xen_api_todo()')