direct-io.hg

view tools/python/xen/xend/XendAPI.py @ 14342:e5d7b878118f

Added an VM_HVM_REQUIRED error code, and use it on VM.start.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author Ewan Mellor <ewan@xensource.com>
date Sat Mar 10 23:22:00 2007 +0000 (2007-03-10)
parents 0affe03ee985
children 01e35a77ce8f
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
35 from xen.xend.XendAPIConstants import *
36 from xen.util.xmlrpclib2 import stringify
38 AUTH_NONE = 'none'
39 AUTH_PAM = 'pam'
41 argcounts = {}
43 # ------------------------------------------
44 # Utility Methods for Xen API Implementation
45 # ------------------------------------------
47 def xen_api_success(value):
48 """Wraps a return value in XenAPI format."""
49 if value is None:
50 s = ''
51 else:
52 s = stringify(value)
53 return {"Status": "Success", "Value": s}
55 def xen_api_success_void():
56 """Return success, but caller expects no return value."""
57 return xen_api_success("")
59 def xen_api_error(error):
60 """Wraps an error value in XenAPI format."""
61 if type(error) == tuple:
62 error = list(error)
63 if type(error) != list:
64 error = [error]
65 if len(error) == 0:
66 error = ['INTERNAL_ERROR', 'Empty list given to xen_api_error']
68 return { "Status": "Failure",
69 "ErrorDescription": [str(x) for x in error] }
72 def xen_api_todo():
73 """Temporary method to make sure we track down all the TODOs"""
74 return {"Status": "Error", "ErrorDescription": XEND_ERROR_TODO}
76 # ---------------------------------------------------
77 # Python Method Decorators for input value validation
78 # ---------------------------------------------------
80 def trace(func, api_name = ''):
81 """Decorator to trace XMLRPC Xen API methods.
83 @param func: function with any parameters
84 @param api_name: name of the api call for debugging.
85 """
86 if hasattr(func, 'api'):
87 api_name = func.api
88 def trace_func(self, *args, **kwargs):
89 log.debug('%s: %s' % (api_name, args))
90 return func(self, *args, **kwargs)
91 trace_func.api = api_name
92 return trace_func
95 def catch_typeerror(func):
96 """Decorator to catch any TypeErrors and translate them into Xen-API
97 errors.
99 @param func: function with params: (self, ...)
100 @rtype: callable object
101 """
102 def f(self, *args, **kwargs):
103 try:
104 return func(self, *args, **kwargs)
105 except TypeError, exn:
106 #log.exception('catch_typeerror')
107 if hasattr(func, 'api') and func.api in argcounts:
108 # Assume that if the argument count was wrong and if the
109 # exception was thrown inside this file, then it is due to an
110 # invalid call from the client, otherwise it's an internal
111 # error (which will be handled further up).
112 expected = argcounts[func.api]
113 actual = len(args) + len(kwargs)
114 if expected != actual:
115 tb = sys.exc_info()[2]
116 try:
117 sourcefile = traceback.extract_tb(tb)[-1][0]
118 if sourcefile == inspect.getsourcefile(XendAPI):
119 return xen_api_error(
120 ['MESSAGE_PARAMETER_COUNT_MISMATCH',
121 func.api, expected, actual])
122 finally:
123 del tb
124 raise
126 return f
129 def session_required(func):
130 """Decorator to verify if session is valid before calling method.
132 @param func: function with params: (self, session, ...)
133 @rtype: callable object
134 """
135 def check_session(self, session, *args, **kwargs):
136 if auth_manager().is_session_valid(session):
137 return func(self, session, *args, **kwargs)
138 else:
139 return xen_api_error(['SESSION_INVALID', session])
141 return check_session
144 def _is_valid_ref(ref, validator):
145 return type(ref) == str and validator(ref)
147 def _check_ref(validator, clas, func, api, session, ref, *args, **kwargs):
148 if _is_valid_ref(ref, validator):
149 return func(api, session, ref, *args, **kwargs)
150 else:
151 return xen_api_error(['HANDLE_INVALID', clas, ref])
154 def valid_host(func):
155 """Decorator to verify if host_ref is valid before calling method.
157 @param func: function with params: (self, session, host_ref, ...)
158 @rtype: callable object
159 """
160 return lambda *args, **kwargs: \
161 _check_ref(XendNode.instance().is_valid_host,
162 'host', func, *args, **kwargs)
164 def valid_host_metrics(func):
165 """Decorator to verify if host_metrics_ref is valid before calling
166 method.
168 @param func: function with params: (self, session, host_metrics_ref)
169 @rtype: callable object
170 """
171 return lambda *args, **kwargs: \
172 _check_ref(lambda r: r == XendNode.instance().host_metrics_uuid,
173 'host_metrics', func, *args, **kwargs)
175 def valid_host_cpu(func):
176 """Decorator to verify if host_cpu_ref is valid before calling method.
178 @param func: function with params: (self, session, host_cpu_ref, ...)
179 @rtype: callable object
180 """
181 return lambda *args, **kwargs: \
182 _check_ref(XendNode.instance().is_valid_cpu,
183 'host_cpu', func, *args, **kwargs)
185 def valid_vm(func):
186 """Decorator to verify if vm_ref is valid before calling method.
188 @param func: function with params: (self, session, vm_ref, ...)
189 @rtype: callable object
190 """
191 return lambda *args, **kwargs: \
192 _check_ref(XendDomain.instance().is_valid_vm,
193 'VM', func, *args, **kwargs)
195 def valid_network(func):
196 """Decorator to verify if network_ref is valid before calling method.
198 @param func: function with params: (self, session, network_ref, ...)
199 @rtype: callable object
200 """
201 return lambda *args, **kwargs: \
202 _check_ref(XendNode.instance().is_valid_network,
203 'network', func, *args, **kwargs)
205 def valid_vbd(func):
206 """Decorator to verify if vbd_ref is valid before calling method.
208 @param func: function with params: (self, session, vbd_ref, ...)
209 @rtype: callable object
210 """
211 return lambda *args, **kwargs: \
212 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vbd', r),
213 'VBD', func, *args, **kwargs)
215 def valid_vbd_metrics(func):
216 """Decorator to verify if ref is valid before calling method.
218 @param func: function with params: (self, session, ref, ...)
219 @rtype: callable object
220 """
221 return lambda *args, **kwargs: \
222 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vbd', r),
223 'VBD_metrics', func, *args, **kwargs)
225 def valid_vif(func):
226 """Decorator to verify if vif_ref is valid before calling method.
228 @param func: function with params: (self, session, vif_ref, ...)
229 @rtype: callable object
230 """
231 return lambda *args, **kwargs: \
232 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vif', r),
233 'VIF', func, *args, **kwargs)
235 def valid_vif_metrics(func):
236 """Decorator to verify if ref is valid before calling method.
238 @param func: function with params: (self, session, ref, ...)
239 @rtype: callable object
240 """
241 return lambda *args, **kwargs: \
242 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vif', r),
243 'VIF_metrics', func, *args, **kwargs)
245 def valid_vdi(func):
246 """Decorator to verify if vdi_ref is valid before calling method.
248 @param func: function with params: (self, session, vdi_ref, ...)
249 @rtype: callable object
250 """
251 return lambda *args, **kwargs: \
252 _check_ref(XendNode.instance().is_valid_vdi,
253 'VDI', func, *args, **kwargs)
255 def valid_vtpm(func):
256 """Decorator to verify if vtpm_ref is valid before calling method.
258 @param func: function with params: (self, session, vtpm_ref, ...)
259 @rtype: callable object
260 """
261 return lambda *args, **kwargs: \
262 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vtpm', r),
263 'VTPM', func, *args, **kwargs)
266 def valid_console(func):
267 """Decorator to verify if console_ref is valid before calling method.
269 @param func: function with params: (self, session, console_ref, ...)
270 @rtype: callable object
271 """
272 return lambda *args, **kwargs: \
273 _check_ref(lambda r: XendDomain.instance().is_valid_dev('console',
274 r),
275 'console', func, *args, **kwargs)
277 def valid_sr(func):
278 """Decorator to verify if sr_ref is valid before calling method.
280 @param func: function with params: (self, session, sr_ref, ...)
281 @rtype: callable object
282 """
283 return lambda *args, **kwargs: \
284 _check_ref(lambda r: XendNode.instance().is_valid_sr,
285 'SR', func, *args, **kwargs)
287 def valid_pif(func):
288 """Decorator to verify if pif_ref is valid before calling
289 method.
291 @param func: function with params: (self, session, pif_ref)
292 @rtype: callable object
293 """
294 return lambda *args, **kwargs: \
295 _check_ref(lambda r: r in XendNode.instance().pifs,
296 'PIF', func, *args, **kwargs)
298 def valid_pif_metrics(func):
299 """Decorator to verify if pif_metrics_ref is valid before calling
300 method.
302 @param func: function with params: (self, session, pif_metrics_ref)
303 @rtype: callable object
304 """
305 return lambda *args, **kwargs: \
306 _check_ref(lambda r: r in XendNode.instance().pif_metrics,
307 'PIF_metrics', func, *args, **kwargs)
309 def valid_task(func):
310 """Decorator to verify if task_ref is valid before calling
311 method.
313 @param func: function with params: (self, session, task_ref)
314 @rtype: callable object
315 """
316 return lambda *args, **kwargs: \
317 _check_ref(XendTaskManager.get_task,
318 'task', func, *args, **kwargs)
320 def valid_debug(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(lambda r: r in XendAPI._debug,
329 'debug', func, *args, **kwargs)
331 # -----------------------------
332 # Bridge to Legacy XM API calls
333 # -----------------------------
335 def do_vm_func(fn_name, vm_ref, *args, **kwargs):
336 """Helper wrapper func to abstract away from repetitive code.
338 @param fn_name: function name for XendDomain instance
339 @type fn_name: string
340 @param vm_ref: vm_ref
341 @type vm_ref: string
342 @param *args: more arguments
343 @type *args: tuple
344 """
345 try:
346 xendom = XendDomain.instance()
347 fn = getattr(xendom, fn_name)
348 xendom.do_legacy_api_with_uuid(fn, vm_ref, *args, **kwargs)
349 return xen_api_success_void()
350 except VMBadState, exn:
351 return xen_api_error(['VM_BAD_POWER_STATE', vm_ref, exn.expected,
352 exn.actual])
355 class XendAPI(object):
356 """Implementation of the Xen-API in Xend. Expects to be
357 used via XMLRPCServer.
359 All methods that need a valid session are marked with
360 a L{session_required} decorator that will
361 transparently perform the required session authentication.
363 We need to support Python <2.4, so we use the old decorator syntax.
365 All XMLRPC accessible methods require an 'api' attribute and
366 is set to the XMLRPC function name which the method implements.
367 """
369 __decorated__ = False
370 __init_lock__ = threading.Lock()
371 _debug = {}
373 def __new__(cls, *args, **kwds):
374 """ Override __new__ to decorate the class only once.
376 Lock to make sure the classes are not decorated twice.
377 """
378 cls.__init_lock__.acquire()
379 try:
380 if not cls.__decorated__:
381 cls._decorate()
382 cls.__decorated__ = True
384 return object.__new__(cls, *args, **kwds)
385 finally:
386 cls.__init_lock__.release()
388 def _decorate(cls):
389 """ Decorate all the object methods to have validators
390 and appropriate function attributes.
392 This should only be executed once for the duration of the
393 server.
394 """
395 global_validators = [session_required, catch_typeerror]
396 classes = {
397 'session' : None,
398 'host' : valid_host,
399 'host_cpu' : valid_host_cpu,
400 'host_metrics' : valid_host_metrics,
401 'network' : valid_network,
402 'VM' : valid_vm,
403 'VBD' : valid_vbd,
404 'VBD_metrics' : valid_vbd_metrics,
405 'VIF' : valid_vif,
406 'VIF_metrics' : valid_vif_metrics,
407 'VDI' : valid_vdi,
408 'VTPM' : valid_vtpm,
409 'console' : valid_console,
410 'SR' : valid_sr,
411 'PIF' : valid_pif,
412 'PIF_metrics' : valid_pif_metrics,
413 'task' : valid_task,
414 'debug' : valid_debug,
415 }
417 # Cheat methods
418 # -------------
419 # Methods that have a trivial implementation for all classes.
420 # 1. get_by_uuid == getting by ref, so just return uuid for
421 # all get_by_uuid() methods.
423 for api_cls in classes.keys():
424 if api_cls == 'session':
425 continue
427 get_by_uuid = '%s_get_by_uuid' % api_cls
428 get_uuid = '%s_get_uuid' % api_cls
429 def _get_by_uuid(_1, _2, ref):
430 return xen_api_success(ref)
432 def _get_uuid(_1, _2, ref):
433 return xen_api_success(ref)
435 setattr(cls, get_by_uuid, _get_by_uuid)
436 setattr(cls, get_uuid, _get_uuid)
438 # Wrapping validators around XMLRPC calls
439 # ---------------------------------------
441 for api_cls, validator in classes.items():
442 def doit(n, takes_instance, async_support = False,
443 return_type = None):
444 n_ = n.replace('.', '_')
445 try:
446 f = getattr(cls, n_)
447 argcounts[n] = f.func_code.co_argcount - 1
449 validators = takes_instance and validator and \
450 [validator] or []
452 validators += global_validators
453 for v in validators:
454 f = v(f)
455 f.api = n
456 f.async = async_support
457 if return_type:
458 f.return_type = return_type
460 setattr(cls, n_, f)
461 except AttributeError:
462 log.warn("API call: %s not found" % n)
465 ro_attrs = getattr(cls, '%s_attr_ro' % api_cls, [])
466 rw_attrs = getattr(cls, '%s_attr_rw' % api_cls, [])
467 methods = getattr(cls, '%s_methods' % api_cls, [])
468 funcs = getattr(cls, '%s_funcs' % api_cls, [])
470 # wrap validators around readable class attributes
471 for attr_name in ro_attrs + rw_attrs + cls.Base_attr_ro:
472 doit('%s.get_%s' % (api_cls, attr_name), True,
473 async_support = False)
475 # wrap validators around writable class attrributes
476 for attr_name in rw_attrs + cls.Base_attr_rw:
477 doit('%s.set_%s' % (api_cls, attr_name), True,
478 async_support = False)
480 # wrap validators around methods
481 for method_name, return_type in methods + cls.Base_methods:
482 doit('%s.%s' % (api_cls, method_name), True,
483 async_support = True)
485 # wrap validators around class functions
486 for func_name, return_type in funcs + cls.Base_funcs:
487 doit('%s.%s' % (api_cls, func_name), False, async_support = True,
488 return_type = return_type)
490 _decorate = classmethod(_decorate)
492 def __init__(self, auth):
493 self.auth = auth
495 Base_attr_ro = ['uuid']
496 Base_attr_rw = []
497 Base_methods = [('destroy', None), ('get_record', 'Struct')]
498 Base_funcs = [('get_all', 'Set'), ('get_by_uuid', None)]
500 # Xen API: Class Session
501 # ----------------------------------------------------------------
502 # NOTE: Left unwrapped by __init__
504 session_attr_ro = ['this_host', 'this_user']
505 session_methods = [('logout', None)]
507 def session_login_with_password(self, *args):
508 if len(args) != 2:
509 return xen_api_error(
510 ['MESSAGE_PARAMETER_COUNT_MISMATCH',
511 'session.login_with_password', 2, len(args)])
512 username = args[0]
513 password = args[1]
514 try:
515 session = (self.auth == AUTH_NONE and
516 auth_manager().login_unconditionally(username) or
517 auth_manager().login_with_password(username, password))
518 return xen_api_success(session)
519 except XendError, e:
520 return xen_api_error(['SESSION_AUTHENTICATION_FAILED'])
521 session_login_with_password.api = 'session.login_with_password'
523 # object methods
524 def session_logout(self, session):
525 auth_manager().logout(session)
526 return xen_api_success_void()
527 def session_get_record(self, session):
528 record = {'uuid' : session,
529 'this_host': XendNode.instance().uuid,
530 'this_user': auth_manager().get_user(session)}
531 return xen_api_success(record)
533 def session_get_uuid(self, session):
534 return xen_api_success(session)
536 def session_get_by_uuid(self, session):
537 return xen_api_success(session)
539 # attributes (ro)
540 def session_get_this_host(self, session):
541 return xen_api_success(XendNode.instance().uuid)
542 def session_get_this_user(self, session):
543 user = auth_manager().get_user(session)
544 if user:
545 return xen_api_success(user)
546 return xen_api_error(['SESSION_INVALID', session])
549 # Xen API: Class User
550 # ----------------------------------------------------------------
551 # TODO: NOT IMPLEMENTED YET
553 # Xen API: Class Tasks
554 # ----------------------------------------------------------------
556 task_attr_ro = ['name_label',
557 'name_description',
558 'status',
559 'progress',
560 'type',
561 'result',
562 'error_code',
563 'error_info',
564 'allowed_operations',
565 'session'
566 ]
568 task_attr_rw = []
570 task_funcs = [('get_by_name_label', 'Set(task)'),
571 ('cancel', None)]
573 def task_get_name_label(self, session, task_ref):
574 task = XendTaskManager.get_task(task_ref)
575 return xen_api_success(task.name_label)
577 def task_get_name_description(self, session, task_ref):
578 task = XendTaskManager.get_task(task_ref)
579 return xen_api_success(task.name_description)
581 def task_get_status(self, session, task_ref):
582 task = XendTaskManager.get_task(task_ref)
583 return xen_api_success(task.get_status())
585 def task_get_progress(self, session, task_ref):
586 task = XendTaskManager.get_task(task_ref)
587 return xen_api_success(task.progress)
589 def task_get_type(self, session, task_ref):
590 task = XendTaskManager.get_task(task_ref)
591 return xen_api_success(task.type)
593 def task_get_result(self, session, task_ref):
594 task = XendTaskManager.get_task(task_ref)
595 return xen_api_success(task.result)
597 def task_get_error_code(self, session, task_ref):
598 task = XendTaskManager.get_task(task_ref)
599 return xen_api_success(task.error_code)
601 def task_get_error_info(self, session, task_ref):
602 task = XendTaskManager.get_task(task_ref)
603 return xen_api_success(task.error_info)
605 def task_get_allowed_operations(self, session, task_ref):
606 return xen_api_success({})
608 def task_get_session(self, session, task_ref):
609 task = XendTaskManager.get_task(task_ref)
610 return xen_api_success(task.session)
612 def task_get_all(self, session):
613 tasks = XendTaskManager.get_all_tasks()
614 return xen_api_success(tasks)
616 def task_get_record(self, session, task_ref):
617 task = XendTaskManager.get_task(task_ref)
618 return xen_api_success(task.get_record())
620 def task_cancel(self, session, task_ref):
621 return xen_api_error('OPERATION_NOT_ALLOWED')
623 def task_get_by_name_label(self, session, name):
624 return xen_api_success(XendTaskManager.get_task_by_name(name))
626 # Xen API: Class host
627 # ----------------------------------------------------------------
629 host_attr_ro = ['software_version',
630 'resident_VMs',
631 'host_CPUs',
632 'metrics',
633 'capabilities',
634 'supported_bootloaders',
635 'API_version_major',
636 'API_version_minor',
637 'API_version_vendor',
638 'API_version_vendor_implementation']
640 host_attr_rw = ['name_label',
641 'name_description',
642 'other_config']
644 host_methods = [('disable', None),
645 ('enable', None),
646 ('reboot', None),
647 ('shutdown', None),
648 ('add_to_other_config', None),
649 ('remove_from_other_config', None),
650 ('dmesg', 'String')]
652 host_funcs = [('get_by_name_label', 'Set(host)')]
654 # attributes
655 def host_get_name_label(self, session, host_ref):
656 return xen_api_success(XendNode.instance().name)
657 def host_set_name_label(self, session, host_ref, new_name):
658 XendNode.instance().set_name(new_name)
659 return xen_api_success_void()
660 def host_get_name_description(self, session, host_ref):
661 return xen_api_success(XendNode.instance().description)
662 def host_set_name_description(self, session, host_ref, new_desc):
663 XendNode.instance().set_description(new_desc)
664 return xen_api_success_void()
665 def host_get_other_config(self, session, host_ref):
666 return xen_api_success(XendNode.instance().other_config)
667 def host_set_other_config(self, session, host_ref, other_config):
668 node = XendNode.instance()
669 node.other_config = dict(other_config)
670 node.save()
671 return xen_api_success_void()
672 def host_add_to_other_config(self, session, host_ref, key, value):
673 node = XendNode.instance()
674 node.other_config[key] = value
675 node.save()
676 return xen_api_success_void()
677 def host_remove_from_other_config(self, session, host_ref, key):
678 node = XendNode.instance()
679 if key in node.other_config:
680 del node.other_config[key]
681 node.save()
682 return xen_api_success_void()
683 def host_get_API_version_major(self, _, ref):
684 return xen_api_success(XEN_API_VERSION_MAJOR)
685 def host_get_API_version_minor(self, _, ref):
686 return xen_api_success(XEN_API_VERSION_MINOR)
687 def host_get_API_version_vendor(self, _, ref):
688 return xen_api_success(XEN_API_VERSION_VENDOR)
689 def host_get_API_version_vendor_implementation(self, _, ref):
690 return xen_api_success(XEN_API_VERSION_VENDOR_IMPLEMENTATION)
691 def host_get_software_version(self, session, host_ref):
692 return xen_api_success(XendNode.instance().xen_version())
693 def host_get_resident_VMs(self, session, host_ref):
694 return xen_api_success(XendDomain.instance().get_domain_refs())
695 def host_get_host_CPUs(self, session, host_ref):
696 return xen_api_success(XendNode.instance().get_host_cpu_refs())
697 def host_get_metrics(self, _, ref):
698 return xen_api_success(XendNode.instance().host_metrics_uuid)
699 def host_get_capabilities(self, session, host_ref):
700 return xen_api_success(XendNode.instance().get_capabilities())
701 def host_get_supported_bootloaders(self, session, host_ref):
702 return xen_api_success(['pygrub'])
704 # object methods
705 def host_disable(self, session, host_ref):
706 XendDomain.instance().set_allow_new_domains(False)
707 return xen_api_success_void()
708 def host_enable(self, session, host_ref):
709 XendDomain.instance().set_allow_new_domains(True)
710 return xen_api_success_void()
711 def host_reboot(self, session, host_ref):
712 if not XendDomain.instance().allow_new_domains():
713 return xen_api_error(XEND_ERROR_HOST_RUNNING)
714 return xen_api_error(XEND_ERROR_UNSUPPORTED)
715 def host_shutdown(self, session, host_ref):
716 if not XendDomain.instance().allow_new_domains():
717 return xen_api_error(XEND_ERROR_HOST_RUNNING)
718 return xen_api_error(XEND_ERROR_UNSUPPORTED)
720 def host_dmesg(self, session, host_ref):
721 return xen_api_success(XendDmesg.instance().info())
723 def host_get_record(self, session, host_ref):
724 node = XendNode.instance()
725 dom = XendDomain.instance()
726 record = {'uuid': node.uuid,
727 'name_label': node.name,
728 'name_description': '',
729 'API_version_major': XEN_API_VERSION_MAJOR,
730 'API_version_minor': XEN_API_VERSION_MINOR,
731 'API_version_vendor': XEN_API_VERSION_VENDOR,
732 'API_version_vendor_implementation':
733 XEN_API_VERSION_VENDOR_IMPLEMENTATION,
734 'software_version': node.xen_version(),
735 'other_config': node.other_config,
736 'resident_VMs': dom.get_domain_refs(),
737 'host_CPUs': node.get_host_cpu_refs(),
738 'metrics': node.host_metrics_uuid,
739 'capabilities': node.get_capabilities(),
740 'supported_bootloaders': 'pygrub'}
741 return xen_api_success(record)
743 # class methods
744 def host_get_all(self, session):
745 return xen_api_success((XendNode.instance().uuid,))
746 def host_get_by_name_label(self, session, name):
747 if XendNode.instance().name == name:
748 return xen_api_success((XendNode.instance().uuid,))
749 return xen_api_success([])
752 # Xen API: Class host_CPU
753 # ----------------------------------------------------------------
755 host_cpu_attr_ro = ['host',
756 'number',
757 'vendor',
758 'speed',
759 'modelname',
760 'stepping',
761 'flags',
762 'utilisation']
764 # attributes
765 def _host_cpu_get(self, ref, field):
766 return xen_api_success(
767 XendNode.instance().get_host_cpu_field(ref, field))
769 def host_cpu_get_host(self, _, ref):
770 return xen_api_success(XendNode.instance().uuid)
771 def host_cpu_get_number(self, _, ref):
772 return self._host_cpu_get(ref, 'number')
773 def host_cpu_get_vendor(self, _, ref):
774 return self._host_cpu_get(ref, 'vendor')
775 def host_cpu_get_speed(self, _, ref):
776 return self._host_cpu_get(ref, 'speed')
777 def host_cpu_get_modelname(self, _, ref):
778 return self._host_cpu_get(ref, 'modelname')
779 def host_cpu_get_stepping(self, _, ref):
780 return self._host_cpu_get(ref, 'stepping')
781 def host_cpu_get_flags(self, _, ref):
782 return self._host_cpu_get(ref, 'flags')
783 def host_cpu_get_utilisation(self, _, ref):
784 return xen_api_success(XendNode.instance().get_host_cpu_load(ref))
786 # object methods
787 def host_cpu_get_record(self, _, ref):
788 node = XendNode.instance()
789 record = dict([(f, node.get_host_cpu_field(ref, f))
790 for f in self.host_cpu_attr_ro
791 if f not in ['uuid', 'host', 'utilisation']])
792 record['uuid'] = ref
793 record['host'] = node.uuid
794 record['utilisation'] = node.get_host_cpu_load(ref)
795 return xen_api_success(record)
797 # class methods
798 def host_cpu_get_all(self, session):
799 return xen_api_success(XendNode.instance().get_host_cpu_refs())
802 # Xen API: Class host_metrics
803 # ----------------------------------------------------------------
805 host_metrics_attr_ro = ['memory_total',
806 'memory_free']
807 host_metrics_attr_rw = []
808 host_metrics_methods = []
810 def host_metrics_get_all(self, _):
811 return xen_api_success([XendNode.instance().host_metrics_uuid])
813 def _host_metrics_get(self, ref, f):
814 return xen_api_success(getattr(node, f)())
816 def host_metrics_get_record(self, _, ref):
817 return xen_api_success({
818 'uuid' : ref,
819 'memory_total' : self._host_metrics_get_memory_total(),
820 'memory_free' : self._host_metrics_get_memory_free(),
821 })
823 def host_metrics_get_memory_total(self, _, ref):
824 return xen_api_success(self._host_metrics_get_memory_total())
826 def host_metrics_get_memory_free(self, _, ref):
827 return xen_api_success(self._host_metrics_get_memory_free())
829 def _host_metrics_get_memory_total(self):
830 node = XendNode.instance()
831 return node.xc.physinfo()['total_memory'] * 1024
833 def _host_metrics_get_memory_free(self):
834 node = XendNode.instance()
835 return node.xc.physinfo()['free_memory'] * 1024
838 # Xen API: Class network
839 # ----------------------------------------------------------------
841 network_attr_ro = ['VIFs', 'PIFs']
842 network_attr_rw = ['name_label',
843 'name_description']
845 network_funcs = [('create', 'network')]
847 def network_create(self, _, name_label, name_description):
848 return xen_api_success(
849 XendNode.instance().network_create(name_label, name_description))
851 def network_destroy(self, _, ref):
852 return xen_api_success(XendNode.instance().network_destroy(ref))
854 def _get_network(self, ref):
855 return XendNode.instance().get_network(ref)
857 def network_get_all(self, _):
858 return xen_api_success(XendNode.instance().get_network_refs())
860 def network_get_record(self, _, ref):
861 return xen_api_success(
862 XendNode.instance().get_network(ref).get_record())
864 def network_get_name_label(self, _, ref):
865 return xen_api_success(self._get_network(ref).name_label)
867 def network_get_name_description(self, _, ref):
868 return xen_api_success(self._get_network(ref).name_description)
870 def network_get_VIFs(self, _, ref):
871 return xen_api_success(self._get_network(ref).get_VIF_UUIDs())
873 def network_get_PIFs(self, session, ref):
874 return xen_api_success(self._get_network(ref).get_PIF_UUIDs())
876 def network_set_name_label(self, _, ref, val):
877 return xen_api_success(self._get_network(ref).set_name_label(val))
879 def network_set_name_description(self, _, ref, val):
880 return xen_api_success(self._get_network(ref).set_name_description(val))
882 # Xen API: Class PIF
883 # ----------------------------------------------------------------
885 PIF_attr_ro = ['metrics']
886 PIF_attr_rw = ['device',
887 'network',
888 'host',
889 'MAC',
890 'MTU',
891 'VLAN']
893 PIF_attr_inst = PIF_attr_rw
895 PIF_methods = [('create_VLAN', 'int')]
897 def _get_PIF(self, ref):
898 return XendNode.instance().pifs[ref]
900 def PIF_destroy(self, _, ref):
901 try:
902 return xen_api_success(XendNode.instance().PIF_destroy(ref))
903 except PIFIsPhysical, exn:
904 return xen_api_error(['PIF_IS_PHYSICAL', ref])
906 # object methods
907 def PIF_get_record(self, _, ref):
908 return xen_api_success(self._get_PIF(ref).get_record())
910 def PIF_get_all(self, _):
911 return xen_api_success(XendNode.instance().pifs.keys())
913 def PIF_get_metrics(self, _, ref):
914 return xen_api_success(self._get_PIF(ref).metrics.uuid)
916 def PIF_get_device(self, _, ref):
917 return xen_api_success(self._get_PIF(ref).device)
919 def PIF_get_network(self, _, ref):
920 return xen_api_success(self._get_PIF(ref).network.uuid)
922 def PIF_get_host(self, _, ref):
923 return xen_api_success(self._get_PIF(ref).host.uuid)
925 def PIF_get_MAC(self, _, ref):
926 return xen_api_success(self._get_PIF(ref).mac)
928 def PIF_get_MTU(self, _, ref):
929 return xen_api_success(self._get_PIF(ref).mtu)
931 def PIF_get_VLAN(self, _, ref):
932 return xen_api_success(self._get_PIF(ref).vlan)
934 def PIF_set_device(self, _, ref, device):
935 return xen_api_success(self._get_PIF(ref).set_device(device))
937 def PIF_set_MAC(self, _, ref, mac):
938 return xen_api_success(self._get_PIF(ref).set_mac(mac))
940 def PIF_set_MTU(self, _, ref, mtu):
941 return xen_api_success(self._get_PIF(ref).set_mtu(mtu))
943 def PIF_create_VLAN(self, _, ref, network, vlan):
944 try:
945 vlan = int(vlan)
946 except:
947 return xen_api_error(['VLAN_TAG_INVALID', vlan])
949 try:
950 node = XendNode.instance()
952 if _is_valid_ref(network, node.is_valid_network):
953 return xen_api_success(
954 node.PIF_create_VLAN(ref, network, vlan))
955 else:
956 return xen_api_error(['HANDLE_INVALID', 'network', network])
957 except NetworkAlreadyConnected, exn:
958 return xen_api_error(['NETWORK_ALREADY_CONNECTED',
959 network, exn.pif_uuid])
960 except VLANTagInvalid:
961 return xen_api_error(['VLAN_TAG_INVALID', vlan])
964 # Xen API: Class PIF_metrics
965 # ----------------------------------------------------------------
967 PIF_metrics_attr_ro = ['io_read_kbs',
968 'io_write_kbs']
969 PIF_metrics_attr_rw = []
970 PIF_methods = []
972 def PIF_metrics_get_all(self, _):
973 return xen_api_success(XendNode.instance().pif_metrics.keys())
975 def _PIF_metrics_get(self, ref):
976 return XendNode.instance().pif_metrics[ref]
978 def PIF_metrics_get_record(self, _, ref):
979 return xen_api_success(self._PIF_metrics_get(ref).get_record())
981 def PIF_metrics_get_io_read_kbs(self, _, ref):
982 return xen_api_success(self._PIF_metrics_get(ref).get_io_read_kbs())
984 def PIF_metrics_get_io_write_kbs(self, _, ref):
985 return xen_api_success(self._PIF_metrics_get(ref).get_io_write_kbs())
988 # Xen API: Class VM
989 # ----------------------------------------------------------------
991 VM_attr_ro = ['power_state',
992 'resident_on',
993 'memory_actual',
994 'memory_static_max',
995 'memory_static_min',
996 'VCPUs_number',
997 'VCPUs_utilisation',
998 'consoles',
999 'VIFs',
1000 'VBDs',
1001 'VTPMs',
1002 'tools_version',
1003 'domid',
1004 'is_control_domain',
1007 VM_attr_rw = ['name_label',
1008 'name_description',
1009 'user_version',
1010 'is_a_template',
1011 'auto_power_on',
1012 'memory_dynamic_max',
1013 'memory_dynamic_min',
1014 'VCPUs_policy',
1015 'VCPUs_params',
1016 'actions_after_shutdown',
1017 'actions_after_reboot',
1018 'actions_after_suspend',
1019 'actions_after_crash',
1020 'PV_bootloader',
1021 'PV_kernel',
1022 'PV_ramdisk',
1023 'PV_args',
1024 'PV_bootloader_args',
1025 'HVM_boot_policy',
1026 'HVM_boot_params',
1027 'platform',
1028 'PCI_bus',
1029 'other_config']
1031 VM_methods = [('clone', 'VM'),
1032 ('start', None),
1033 ('pause', None),
1034 ('unpause', None),
1035 ('clean_shutdown', None),
1036 ('clean_reboot', None),
1037 ('hard_shutdown', None),
1038 ('hard_reboot', None),
1039 ('suspend', None),
1040 ('resume', None),
1041 ('add_to_HVM_boot_params', None),
1042 ('remove_from_HVM_boot_params', None),
1043 ('add_to_platform', None),
1044 ('remove_from_platform', None),
1045 ('add_to_other_config', None),
1046 ('remove_from_other_config', None)]
1048 VM_funcs = [('create', 'VM'),
1049 ('get_by_name_label', 'Set(VM)')]
1051 # parameters required for _create()
1052 VM_attr_inst = [
1053 'name_label',
1054 'name_description',
1055 'user_version',
1056 'is_a_template',
1057 'memory_static_max',
1058 'memory_dynamic_max',
1059 'memory_dynamic_min',
1060 'memory_static_min',
1061 'VCPUs_policy',
1062 'VCPUs_params',
1063 'actions_after_shutdown',
1064 'actions_after_reboot',
1065 'actions_after_suspend',
1066 'actions_after_crash',
1067 'PV_bootloader',
1068 'PV_kernel',
1069 'PV_ramdisk',
1070 'PV_args',
1071 'PV_bootloader_args',
1072 'HVM_boot_policy',
1073 'HVM_boot_params',
1074 'platform',
1075 'PCI_bus',
1076 'other_config']
1078 def VM_get(self, name, session, vm_ref):
1079 return xen_api_success(
1080 XendDomain.instance().get_vm_by_uuid(vm_ref).info[name])
1082 def VM_set(self, name, session, vm_ref, value):
1083 xd = XendDomain.instance()
1084 dominfo = xd.get_vm_by_uuid(vm_ref)
1085 dominfo.info[name] = value
1086 return self._VM_save(dominfo)
1088 def _VM_save(self, dominfo):
1089 XendDomain.instance().managed_config_save(dominfo)
1090 return xen_api_success_void()
1092 # attributes (ro)
1093 def VM_get_power_state(self, session, vm_ref):
1094 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1095 return xen_api_success(dom.get_power_state())
1097 def VM_get_resident_on(self, session, vm_ref):
1098 return xen_api_success(XendNode.instance().uuid)
1100 def VM_get_memory_actual(self, session, vm_ref):
1101 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1102 return xen_api_todo() # unsupported by xc
1104 def VM_get_memory_static_max(self, session, vm_ref):
1105 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1106 return xen_api_success(dom.get_memory_static_max())
1108 def VM_get_memory_static_min(self, session, vm_ref):
1109 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1110 return xen_api_success(dom.get_memory_static_min())
1112 def VM_get_VCPUs_number(self, session, vm_ref):
1113 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1114 return xen_api_success(dom.getVCpuCount())
1116 def VM_get_VCPUs_utilisation(self, session, vm_ref):
1117 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1118 return xen_api_success(dom.get_vcpus_util())
1120 def VM_get_VIFs(self, session, vm_ref):
1121 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1122 return xen_api_success(dom.get_vifs())
1124 def VM_get_VBDs(self, session, vm_ref):
1125 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1126 return xen_api_success(dom.get_vbds())
1128 def VM_get_VTPMs(self, session, vm_ref):
1129 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1130 return xen_api_success(dom.get_vtpms())
1132 def VM_get_consoles(self, session, vm_ref):
1133 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1134 return xen_api_success(dom.get_consoles())
1136 def VM_get_tools_version(self, session, vm_ref):
1137 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1138 return dom.get_tools_version()
1140 # attributes (rw)
1141 def VM_get_name_label(self, session, vm_ref):
1142 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1143 return xen_api_success(dom.getName())
1145 def VM_get_name_description(self, session, vm_ref):
1146 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1147 return xen_api_todo()
1149 def VM_get_user_version(self, session, vm_ref):
1150 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1151 return xen_api_todo()
1153 def VM_get_is_a_template(self, session, vm_ref):
1154 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1155 return xen_api_todo()
1157 def VM_get_memory_dynamic_max(self, session, vm_ref):
1158 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1159 return xen_api_success(dom.get_memory_dynamic_max())
1161 def VM_get_memory_dynamic_min(self, session, vm_ref):
1162 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1163 return xen_api_success(dom.get_memory_dynamic_min())
1165 def VM_get_VCPUs_policy(self, session, vm_ref):
1166 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1167 return xen_api_success(dom.get_vcpus_policy())
1169 def VM_get_VCPUs_params(self, session, vm_ref):
1170 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1171 return xen_api_success(dom.get_vcpus_params())
1173 def VM_get_actions_after_shutdown(self, session, vm_ref):
1174 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1175 return xen_api_success(dom.get_on_shutdown())
1177 def VM_get_actions_after_reboot(self, session, vm_ref):
1178 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1179 return xen_api_success(dom.get_on_reboot())
1181 def VM_get_actions_after_suspend(self, session, vm_ref):
1182 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1183 return xen_api_success(dom.get_on_suspend())
1185 def VM_get_actions_after_crash(self, session, vm_ref):
1186 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1187 return xen_api_success(dom.get_on_crash())
1189 def VM_get_PV_bootloader(self, session, vm_ref):
1190 return self.VM_get('PV_bootloader', session, vm_ref)
1192 def VM_get_PV_kernel(self, session, vm_ref):
1193 return self.VM_get('PV_kernel', session, vm_ref)
1195 def VM_get_PV_ramdisk(self, session, vm_ref):
1196 return self.VM_get('PV_ramdisk', session, vm_ref)
1198 def VM_get_PV_args(self, session, vm_ref):
1199 return self.VM_get('PV_args', session, vm_ref)
1201 def VM_get_PV_bootloader_args(self, session, vm_ref):
1202 return self.VM_get('PV_bootloader_args', session, vm_ref)
1204 def VM_get_HVM_boot_policy(self, session, vm_ref):
1205 return self.VM_get('HVM_boot_policy', session, vm_ref)
1207 def VM_get_HVM_boot_params(self, session, vm_ref):
1208 return self.VM_get('HVM_boot_params', session, vm_ref)
1210 def VM_get_platform(self, session, vm_ref):
1211 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1212 return xen_api_success(dom.get_platform())
1214 def VM_get_PCI_bus(self, session, vm_ref):
1215 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1216 return dom.get_pci_bus()
1218 def VM_set_PCI_bus(self, session, vm_ref, val):
1219 return self.VM_set('PCI_bus', session, vm_ref, val)
1221 def VM_get_other_config(self, session, vm_ref):
1222 return self.VM_get('other_config', session, vm_ref)
1224 def VM_get_domid(self, _, ref):
1225 domid = XendDomain.instance().get_vm_by_uuid(ref).getDomid()
1226 return xen_api_success(domid is None and -1 or domid)
1228 def VM_get_is_control_domain(self, session, vm_ref):
1229 xd = XendDomain.instance()
1230 return xen_api_success(
1231 xd.get_vm_by_uuid(vm_ref) == xd.privilegedDomain())
1233 def VM_set_name_label(self, session, vm_ref, label):
1234 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1235 dom.setName(label)
1236 return self._VM_save(dom)
1238 def VM_set_name_description(self, session, vm_ref, desc):
1239 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1240 return xen_api_todo()
1242 def VM_set_user_version(self, session, vm_ref, ver):
1243 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1244 return xen_api_todo()
1246 def VM_set_is_a_template(self, session, vm_ref, is_template):
1247 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1248 return xen_api_todo()
1250 def VM_set_memory_dynamic_max(self, session, vm_ref, mem):
1251 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1252 return xen_api_todo()
1254 def VM_set_memory_dynamic_min(self, session, vm_ref, mem):
1255 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1256 return xen_api_todo()
1258 def VM_set_VCPUs_policy(self, session, vm_ref, policy):
1259 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1260 return xen_api_todo()
1262 def VM_set_VCPUs_params(self, session, vm_ref, params):
1263 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1264 return xen_api_todo()
1266 def VM_set_actions_after_shutdown(self, session, vm_ref, action):
1267 if action not in XEN_API_ON_NORMAL_EXIT:
1268 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1269 return self.VM_set('actions_after_shutdown', session, vm_ref, action)
1271 def VM_set_actions_after_reboot(self, session, vm_ref, action):
1272 if action not in XEN_API_ON_NORMAL_EXIT:
1273 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1274 return self.VM_set('actions_after_reboot', session, vm_ref, action)
1276 def VM_set_actions_after_suspend(self, session, vm_ref, action):
1277 if action not in XEN_API_ON_NORMAL_EXIT:
1278 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1279 return self.VM_set('actions_after_suspend', session, vm_ref, action)
1281 def VM_set_actions_after_crash(self, session, vm_ref, action):
1282 if action not in XEN_API_ON_CRASH_BEHAVIOUR:
1283 return xen_api_error(['VM_ON_CRASH_BEHAVIOUR_INVALID', vm_ref])
1284 return self.VM_set('actions_after_crash', session, vm_ref, action)
1286 def VM_set_HVM_boot_policy(self, session, vm_ref, value):
1287 if value != "" and value != "BIOS order":
1288 return xen_api_error(
1289 ['VALUE_NOT_SUPPORTED', 'VM.HVM_boot_policy', value,
1290 'Xend supports only the "BIOS order" boot policy.'])
1291 else:
1292 return self.VM_set('HVM_boot_policy', session, vm_ref, value)
1294 def VM_set_HVM_boot_params(self, session, vm_ref, value):
1295 return self.VM_set('HVM_boot_params', session, vm_ref, value)
1297 def VM_add_to_HVM_boot_params(self, session, vm_ref, key, value):
1298 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1299 if 'HVM_boot_params' not in dom.info:
1300 dom.info['HVM_boot_params'] = {}
1301 dom.info['HVM_boot_params'][key] = value
1302 return self._VM_save(dom)
1304 def VM_remove_from_HVM_boot_params(self, session, vm_ref, key):
1305 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1306 if 'HVM_boot_params' in dom.info \
1307 and key in dom.info['HVM_boot_params']:
1308 del dom.info['HVM_boot_params'][key]
1309 return self._VM_save(dom)
1310 else:
1311 return xen_api_success_void()
1313 def VM_set_PV_bootloader(self, session, vm_ref, value):
1314 return self.VM_set('PV_bootloader', session, vm_ref, value)
1316 def VM_set_PV_kernel(self, session, vm_ref, value):
1317 return self.VM_set('PV_kernel', session, vm_ref, value)
1319 def VM_set_PV_ramdisk(self, session, vm_ref, value):
1320 return self.VM_set('PV_ramdisk', session, vm_ref, value)
1322 def VM_set_PV_args(self, session, vm_ref, value):
1323 return self.VM_set('PV_args', session, vm_ref, value)
1325 def VM_set_PV_bootloader_args(self, session, vm_ref, value):
1326 return self.VM_set('PV_bootloader_args', session, vm_ref, value)
1328 def VM_set_platform(self, session, vm_ref, value):
1329 return self.VM_set('platform', session, vm_ref, value)
1331 def VM_add_to_platform(self, session, vm_ref, key, value):
1332 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1333 plat = dom.get_platform()
1334 plat[key] = value
1335 return self.VM_set_platform(session, vm_ref, plat)
1337 def VM_remove_from_platform(self, session, vm_ref, key):
1338 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1339 plat = dom.get_platform()
1340 if key in plat:
1341 del plat[key]
1342 return self.VM_set_platform(session, vm_ref, plat)
1343 else:
1344 return xen_api_success_void()
1346 def VM_set_other_config(self, session, vm_ref, value):
1347 return self.VM_set('other_config', session, vm_ref, value)
1349 def VM_add_to_other_config(self, session, vm_ref, key, value):
1350 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1351 if dom and 'other_config' in dom.info:
1352 dom.info['other_config'][key] = value
1353 return self._VM_save(dom)
1355 def VM_remove_from_other_config(self, session, vm_ref, key):
1356 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1357 if dom and 'other_config' in dom.info \
1358 and key in dom.info['other_config']:
1359 del dom.info['other_config'][key]
1360 return self._VM_save(dom)
1361 else:
1362 return xen_api_success_void()
1364 # class methods
1365 def VM_get_all(self, session):
1366 refs = [d.get_uuid() for d in XendDomain.instance().list('all')]
1367 return xen_api_success(refs)
1369 def VM_get_by_name_label(self, session, label):
1370 xendom = XendDomain.instance()
1371 dom = xendom.domain_lookup_nr(label)
1372 if dom:
1373 return xen_api_success([dom.get_uuid()])
1374 return xen_api_success([])
1376 def VM_create(self, session, vm_struct):
1377 xendom = XendDomain.instance()
1378 domuuid = XendTask.log_progress(0, 100,
1379 xendom.create_domain, vm_struct)
1380 return xen_api_success(domuuid)
1382 # object methods
1383 def VM_get_record(self, session, vm_ref):
1384 xendom = XendDomain.instance()
1385 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1386 if not xeninfo:
1387 return xen_api_error(['HANDLE_INVALID', 'VM', vm_ref])
1389 domid = xeninfo.getDomid()
1391 record = {
1392 'uuid': xeninfo.get_uuid(),
1393 'power_state': xeninfo.get_power_state(),
1394 'name_label': xeninfo.getName(),
1395 'name_description': xeninfo.getName(),
1396 'user_version': 1,
1397 'is_a_template': False,
1398 'auto_power_on': False,
1399 'resident_on': XendNode.instance().uuid,
1400 'memory_static_min': xeninfo.get_memory_static_min(),
1401 'memory_static_max': xeninfo.get_memory_static_max(),
1402 'memory_dynamic_min': xeninfo.get_memory_dynamic_min(),
1403 'memory_dynamic_max': xeninfo.get_memory_dynamic_max(),
1404 'memory_actual': xeninfo.get_memory_static_min(),
1405 'VCPUs_policy': xeninfo.get_vcpus_policy(),
1406 'VCPUs_params': xeninfo.get_vcpus_params(),
1407 'VCPUs_number': xeninfo.getVCpuCount(),
1408 'VCPUs_utilisation': xeninfo.get_vcpus_util(),
1409 'actions_after_shutdown': xeninfo.get_on_shutdown(),
1410 'actions_after_reboot': xeninfo.get_on_reboot(),
1411 'actions_after_suspend': xeninfo.get_on_suspend(),
1412 'actions_after_crash': xeninfo.get_on_crash(),
1413 'consoles': xeninfo.get_consoles(),
1414 'VIFs': xeninfo.get_vifs(),
1415 'VBDs': xeninfo.get_vbds(),
1416 'VTPMs': xeninfo.get_vtpms(),
1417 'PV_bootloader': xeninfo.info.get('PV_bootloader'),
1418 'PV_kernel': xeninfo.info.get('PV_kernel'),
1419 'PV_ramdisk': xeninfo.info.get('PV_ramdisk'),
1420 'PV_args': xeninfo.info.get('PV_args'),
1421 'PV_bootloader_args': xeninfo.info.get('PV_bootloader_args'),
1422 'HVM_boot_policy': xeninfo.info.get('HVM_boot_policy'),
1423 'HVM_boot_params': xeninfo.info.get('HVM_boot_params'),
1424 'platform': xeninfo.get_platform(),
1425 'PCI_bus': xeninfo.get_pci_bus(),
1426 'tools_version': xeninfo.get_tools_version(),
1427 'other_config': xeninfo.info.get('other_config', {}),
1428 'domid': domid is None and -1 or domid,
1429 'is_control_domain': xeninfo == xendom.privilegedDomain(),
1431 return xen_api_success(record)
1433 def VM_clean_reboot(self, session, vm_ref):
1434 xendom = XendDomain.instance()
1435 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1436 XendTask.log_progress(0, 100, xeninfo.shutdown, "reboot")
1437 return xen_api_success_void()
1439 def VM_clean_shutdown(self, session, vm_ref):
1440 xendom = XendDomain.instance()
1441 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1442 XendTask.log_progress(0, 100, xeninfo.shutdown, "poweroff")
1443 return xen_api_success_void()
1445 def VM_clone(self, session, vm_ref):
1446 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1448 def VM_destroy(self, session, vm_ref):
1449 return XendTask.log_progress(0, 100, do_vm_func,
1450 "domain_delete", vm_ref)
1452 def VM_hard_reboot(self, session, vm_ref):
1453 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1455 def VM_hard_shutdown(self, session, vm_ref):
1456 return XendTask.log_progress(0, 100, do_vm_func,
1457 "domain_destroy", vm_ref)
1458 def VM_pause(self, session, vm_ref):
1459 return XendTask.log_progress(0, 100, do_vm_func,
1460 "domain_pause", vm_ref)
1462 def VM_resume(self, session, vm_ref, start_paused):
1463 return XendTask.log_progress(0, 100, do_vm_func,
1464 "domain_resume", vm_ref,
1465 start_paused = start_paused)
1467 def VM_start(self, session, vm_ref, start_paused):
1468 try:
1469 return XendTask.log_progress(0, 100, do_vm_func,
1470 "domain_start", vm_ref,
1471 start_paused = start_paused)
1472 except HVMRequired, exn:
1473 return xen_api_error(['VM_HVM_REQUIRED', vm_ref])
1475 def VM_suspend(self, session, vm_ref):
1476 return XendTask.log_progress(0, 100, do_vm_func,
1477 "domain_suspend", vm_ref)
1479 def VM_unpause(self, session, vm_ref):
1480 return XendTask.log_progress(0, 100, do_vm_func,
1481 "domain_unpause", vm_ref)
1483 # Xen API: Class VBD
1484 # ----------------------------------------------------------------
1486 VBD_attr_ro = ['metrics']
1487 VBD_attr_rw = ['VM',
1488 'VDI',
1489 'device',
1490 'bootable',
1491 'mode',
1492 'type']
1494 VBD_attr_inst = VBD_attr_rw
1496 VBD_methods = [('media_change', None)]
1497 VBD_funcs = [('create', 'VBD')]
1499 # object methods
1500 def VBD_get_record(self, session, vbd_ref):
1501 xendom = XendDomain.instance()
1502 vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1503 if not vm:
1504 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1505 cfg = vm.get_dev_xenapi_config('vbd', vbd_ref)
1506 if not cfg:
1507 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1509 valid_vbd_keys = self.VBD_attr_ro + self.VBD_attr_rw + \
1510 self.Base_attr_ro + self.Base_attr_rw
1512 return_cfg = {}
1513 for k in cfg.keys():
1514 if k in valid_vbd_keys:
1515 return_cfg[k] = cfg[k]
1517 return_cfg['metrics'] = vbd_ref
1519 return xen_api_success(return_cfg)
1521 def VBD_media_change(self, session, vbd_ref, vdi_ref):
1522 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1524 # class methods
1525 def VBD_create(self, session, vbd_struct):
1526 xendom = XendDomain.instance()
1527 if not xendom.is_valid_vm(vbd_struct['VM']):
1528 return xen_api_error(['HANDLE_INVALID', 'VM', vbd_struct['VM']])
1530 dom = xendom.get_vm_by_uuid(vbd_struct['VM'])
1531 vbd_ref = ''
1532 try:
1533 # new VBD via VDI/SR
1534 vdi_ref = vbd_struct.get('VDI')
1535 vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
1536 if not vdi:
1537 return xen_api_error(['HANDLE_INVALID', 'VDI', vdi_ref])
1538 vdi_image = vdi.get_location()
1539 vbd_ref = XendTask.log_progress(0, 100,
1540 dom.create_vbd,
1541 vbd_struct, vdi_image)
1542 except XendError:
1543 return xen_api_todo()
1545 xendom.managed_config_save(dom)
1546 return xen_api_success(vbd_ref)
1549 def VBD_destroy(self, session, vbd_ref):
1550 xendom = XendDomain.instance()
1551 vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1552 if not vm:
1553 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1555 XendTask.log_progress(0, 100, vm.destroy_vbd, vbd_ref)
1556 return xen_api_success_void()
1558 def _VBD_get(self, vbd_ref, prop):
1559 return xen_api_success(
1560 XendDomain.instance().get_dev_property_by_uuid(
1561 'vbd', vbd_ref, prop))
1563 # attributes (ro)
1564 def VBD_get_metrics(self, _, vbd_ref):
1565 return xen_api_success(vbd_ref)
1567 # attributes (rw)
1568 def VBD_get_VM(self, session, vbd_ref):
1569 return self._VBD_get(vbd_ref, 'VM')
1571 def VBD_get_VDI(self, session, vbd_ref):
1572 return self._VBD_get(vbd_ref, 'VDI')
1574 def VBD_get_device(self, session, vbd_ref):
1575 return self._VBD_get(vbd_ref, 'device')
1577 def VBD_get_bootable(self, session, vbd_ref):
1578 return self._VBD_get(vbd_ref, 'bootable')
1580 def VBD_get_mode(self, session, vbd_ref):
1581 return self._VBD_get(vbd_ref, 'mode')
1583 def VBD_get_type(self, session, vbd_ref):
1584 return self._VBD_get(vbd_ref, 'type')
1586 def VBD_set_bootable(self, session, vbd_ref, bootable):
1587 bootable = bool(bootable)
1588 xd = XendDomain.instance()
1589 vm = xd.get_vm_with_dev_uuid('vbd', vbd_ref)
1590 vm.set_dev_property('vbd', vbd_ref, 'bootable', bootable)
1591 xd.managed_config_save(vm)
1592 return xen_api_success_void()
1594 def VBD_get_all(self, session):
1595 xendom = XendDomain.instance()
1596 vbds = [d.get_vbds() for d in XendDomain.instance().list('all')]
1597 vbds = reduce(lambda x, y: x + y, vbds)
1598 return xen_api_success(vbds)
1601 # Xen API: Class VBD_metrics
1602 # ----------------------------------------------------------------
1604 VBD_metrics_attr_ro = ['io_read_kbs',
1605 'io_write_kbs']
1606 VBD_metrics_attr_rw = []
1607 VBD_methods = []
1609 def VBD_metrics_get_record(self, _, ref):
1610 vm = XendDomain.instance().get_vm_with_dev_uuid('vbd', ref)
1611 if not vm:
1612 return xen_api_error(['HANDLE_INVALID', 'VBD_metrics', ref])
1613 return xen_api_success(
1614 { 'io_read_kbs' : vm.get_dev_property('vbd', ref, 'io_read_kbs'),
1615 'io_write_kbs' : vm.get_dev_property('vbd', ref, 'io_write_kbs') })
1617 def VBD_metrics_get_io_read_kbs(self, _, ref):
1618 return self._VBD_get(ref, 'io_read_kbs')
1620 def VBD_metrics_get_io_write_kbs(self, session, ref):
1621 return self._VBD_get(ref, 'io_write_kbs')
1624 # Xen API: Class VIF
1625 # ----------------------------------------------------------------
1627 VIF_attr_ro = ['metrics']
1628 VIF_attr_rw = ['device',
1629 'network',
1630 'VM',
1631 'MAC',
1632 'MTU']
1634 VIF_attr_inst = VIF_attr_rw
1636 VIF_funcs = [('create', 'VIF')]
1639 # object methods
1640 def VIF_get_record(self, session, vif_ref):
1641 xendom = XendDomain.instance()
1642 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
1643 if not vm:
1644 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
1645 cfg = vm.get_dev_xenapi_config('vif', vif_ref)
1646 if not cfg:
1647 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
1649 valid_vif_keys = self.VIF_attr_ro + self.VIF_attr_rw + \
1650 self.Base_attr_ro + self.Base_attr_rw
1652 return_cfg = {}
1653 for k in cfg.keys():
1654 if k in valid_vif_keys:
1655 return_cfg[k] = cfg[k]
1657 return_cfg['metrics'] = vif_ref
1659 return xen_api_success(return_cfg)
1661 # class methods
1662 def VIF_create(self, session, vif_struct):
1663 xendom = XendDomain.instance()
1664 if xendom.is_valid_vm(vif_struct['VM']):
1665 dom = xendom.get_vm_by_uuid(vif_struct['VM'])
1666 try:
1667 vif_ref = dom.create_vif(vif_struct)
1668 xendom.managed_config_save(dom)
1669 return xen_api_success(vif_ref)
1670 except XendError:
1671 return xen_api_error(XEND_ERROR_TODO)
1672 else:
1673 return xen_api_error(['HANDLE_INVALID', 'VM', vif_struct['VM']])
1676 def VIF_destroy(self, session, vif_ref):
1677 xendom = XendDomain.instance()
1678 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
1679 if not vm:
1680 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
1682 vm.destroy_vif(vif_ref)
1683 return xen_api_success_void()
1685 def _VIF_get(self, ref, prop):
1686 return xen_api_success(
1687 XendDomain.instance().get_dev_property_by_uuid('vif', ref, prop))
1689 # getters/setters
1690 def VIF_get_metrics(self, _, vif_ref):
1691 return xen_api_success(vif_ref)
1693 def VIF_get_VM(self, session, vif_ref):
1694 xendom = XendDomain.instance()
1695 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
1696 return xen_api_success(vm.get_uuid())
1698 def VIF_get_MTU(self, session, vif_ref):
1699 return self._VIF_get(vif_ref, 'MTU')
1701 def VIF_get_MAC(self, session, vif_ref):
1702 return self._VIF_get(vif_ref, 'MAC')
1704 def VIF_get_device(self, session, vif_ref):
1705 return self._VIF_get(vif_ref, 'device')
1707 def VIF_get_all(self, session):
1708 xendom = XendDomain.instance()
1709 vifs = [d.get_vifs() for d in XendDomain.instance().list('all')]
1710 vifs = reduce(lambda x, y: x + y, vifs)
1711 return xen_api_success(vifs)
1714 # Xen API: Class VIF_metrics
1715 # ----------------------------------------------------------------
1717 VIF_metrics_attr_ro = ['io_read_kbs',
1718 'io_write_kbs']
1719 VIF_metrics_attr_rw = []
1720 VIF_methods = []
1722 def VIF_metrics_get_record(self, _, ref):
1723 vm = XendDomain.instance().get_vm_with_dev_uuid('vif', ref)
1724 if not vm:
1725 return xen_api_error(['HANDLE_INVALID', 'VIF_metrics', ref])
1726 return xen_api_success(
1727 { 'io_read_kbs' : vm.get_dev_property('vif', ref, 'io_read_kbs'),
1728 'io_write_kbs' : vm.get_dev_property('vif', ref, 'io_write_kbs') })
1730 def VIF_metrics_get_io_read_kbs(self, _, ref):
1731 return self._VIF_get(ref, 'io_read_kbs')
1733 def VIF_metrics_get_io_write_kbs(self, session, ref):
1734 return self._VIF_get(ref, 'io_write_kbs')
1737 # Xen API: Class VDI
1738 # ----------------------------------------------------------------
1739 VDI_attr_ro = ['SR',
1740 'VBDs',
1741 'physical_utilisation',
1742 'sector_size',
1743 'type']
1744 VDI_attr_rw = ['name_label',
1745 'name_description',
1746 'virtual_size',
1747 'sharable',
1748 'read_only']
1749 VDI_attr_inst = VDI_attr_ro + VDI_attr_rw
1751 VDI_methods = [('snapshot', 'VDI')]
1752 VDI_funcs = [('create', 'VDI'),
1753 ('get_by_name_label', 'Set(VDI)')]
1755 def _get_VDI(self, ref):
1756 return XendNode.instance().get_vdi_by_uuid(ref)
1758 def VDI_get_VBDs(self, session, vdi_ref):
1759 return xen_api_todo()
1761 def VDI_get_physical_utilisation(self, session, vdi_ref):
1762 return xen_api_success(self._get_VDI(vdi_ref).
1763 get_physical_utilisation())
1765 def VDI_get_sector_size(self, session, vdi_ref):
1766 return xen_api_success(self._get_VDI(vdi_ref).sector_size)
1768 def VDI_get_type(self, session, vdi_ref):
1769 return xen_api_success(self._get_VDI(vdi_ref).type)
1771 def VDI_get_name_label(self, session, vdi_ref):
1772 return xen_api_success(self._get_VDI(vdi_ref).name_label)
1774 def VDI_get_name_description(self, session, vdi_ref):
1775 return xen_api_success(self._get_VDI(vdi_ref).name_description)
1777 def VDI_get_SR(self, session, vdi_ref):
1778 return xen_api_success(self._get_VDI(vdi_ref).sr_uuid)
1780 def VDI_get_virtual_size(self, session, vdi_ref):
1781 return xen_api_success(self._get_VDI(vdi_ref).virtual_size)
1783 def VDI_get_sharable(self, session, vdi_ref):
1784 return xen_api_success(self._get_VDI(vdi_ref).sharable)
1786 def VDI_get_read_only(self, session, vdi_ref):
1787 return xen_api_success(self._get_VDI(vdi_ref).read_only)
1789 def VDI_set_name_label(self, session, vdi_ref, value):
1790 self._get_VDI(vdi_ref).name_label = value
1791 return xen_api_success_void()
1793 def VDI_set_name_description(self, session, vdi_ref, value):
1794 self._get_VDI(vdi_ref).name_description = value
1795 return xen_api_success_void()
1797 def VDI_set_virtual_size(self, session, vdi_ref, value):
1798 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1800 def VDI_set_sharable(self, session, vdi_ref, value):
1801 self._get_VDI(vdi_ref).sharable = bool(value)
1802 return xen_api_success_void()
1804 def VDI_set_read_only(self, session, vdi_ref, value):
1805 self._get_VDI(vdi_ref).read_only = bool(value)
1806 return xen_api_success_void()
1808 # Object Methods
1809 def VDI_snapshot(self, session, vdi_ref):
1810 return xen_api_todo()
1812 def VDI_destroy(self, session, vdi_ref):
1813 sr = XendNode.instance().get_sr_containing_vdi(vdi_ref)
1814 sr.destroy_vdi(vdi_ref)
1815 return xen_api_success_void()
1817 def VDI_get_record(self, session, vdi_ref):
1818 image = XendNode.instance().get_vdi_by_uuid(vdi_ref)
1819 return xen_api_success({
1820 'uuid': vdi_ref,
1821 'name_label': image.name_label,
1822 'name_description': image.name_description,
1823 'SR': image.sr_uuid,
1824 'VBDs': [], # TODO
1825 'virtual_size': image.virtual_size,
1826 'physical_utilisation': image.physical_utilisation,
1827 'sector_size': image.sector_size,
1828 'type': image.type,
1829 'sharable': image.sharable,
1830 'read_only': image.read_only,
1831 })
1833 # Class Functions
1834 def VDI_create(self, session, vdi_struct):
1835 sr_ref = vdi_struct.get('SR')
1836 xennode = XendNode.instance()
1837 if not xennode.is_valid_sr(sr_ref):
1838 return xen_api_error(['HANDLE_INVALID', 'SR', sr_ref])
1840 vdi_uuid = xennode.srs[sr_ref].create_vdi(vdi_struct)
1841 return xen_api_success(vdi_uuid)
1843 def VDI_get_all(self, session):
1844 xennode = XendNode.instance()
1845 vdis = [sr.get_vdis() for sr in xennode.srs.values()]
1846 return xen_api_success(reduce(lambda x, y: x + y, vdis))
1848 def VDI_get_by_name_label(self, session, name):
1849 xennode = XendNode.instance()
1850 return xen_api_success(xennode.get_vdi_by_name_label(name))
1853 # Xen API: Class VTPM
1854 # ----------------------------------------------------------------
1856 VTPM_attr_rw = [ ]
1857 VTPM_attr_ro = ['VM',
1858 'backend']
1860 VTPM_attr_inst = VTPM_attr_rw
1862 VTPM_funcs = [('create', 'VTPM')]
1864 # object methods
1865 def VTPM_get_record(self, session, vtpm_ref):
1866 xendom = XendDomain.instance()
1867 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
1868 if not vm:
1869 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
1870 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
1871 if not cfg:
1872 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
1873 valid_vtpm_keys = self.VTPM_attr_ro + self.VTPM_attr_rw + \
1874 self.Base_attr_ro + self.Base_attr_rw
1875 return_cfg = {}
1876 for k in cfg.keys():
1877 if k in valid_vtpm_keys:
1878 return_cfg[k] = cfg[k]
1880 return xen_api_success(return_cfg)
1882 # Class Functions
1883 def VTPM_get_backend(self, session, vtpm_ref):
1884 xendom = XendDomain.instance()
1885 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
1886 if not vm:
1887 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
1888 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
1889 if not cfg:
1890 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
1891 if not cfg.has_key('backend'):
1892 return xen_api_error(['VTPM backend not set'])
1893 return xen_api_success(cfg['backend'])
1895 def VTPM_get_VM(self, session, vtpm_ref):
1896 xendom = XendDomain.instance()
1897 return xen_api_success(xendom.get_dev_property_by_uuid('vtpm',
1898 vtpm_ref, 'VM'))
1900 def VTPM_destroy(self, session, vtpm_ref):
1901 xendom = XendDomain.instance()
1902 dom = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
1903 if dom:
1904 if dom.state != XEN_API_VM_POWER_STATE_HALTED:
1905 vm_ref = dom.get_dev_property('vtpm', vtpm_ref, 'VM')
1906 return xen_api_error(['VM_BAD_POWER_STATE', vm_ref,
1907 XendDomain.POWER_STATE_NAMES[XEN_API_VM_POWER_STATE_HALTED],
1908 XendDomain.POWER_STATE_NAMES[dom.state]])
1909 from xen.xend.server import tpmif
1910 tpmif.destroy_vtpmstate(dom.getName())
1911 return xen_api_success_void()
1912 else:
1913 return xen_api_error(['HANDLE_INVALID', 'VM', vtpm_struct['VM']])
1915 # class methods
1916 def VTPM_create(self, session, vtpm_struct):
1917 xendom = XendDomain.instance()
1918 if xendom.is_valid_vm(vtpm_struct['VM']):
1919 dom = xendom.get_vm_by_uuid(vtpm_struct['VM'])
1920 try:
1921 vtpm_ref = dom.create_vtpm(vtpm_struct)
1922 xendom.managed_config_save(dom)
1923 return xen_api_success(vtpm_ref)
1924 except XendError:
1925 return xen_api_error(XEND_ERROR_TODO)
1926 else:
1927 return xen_api_error(['HANDLE_INVALID', 'VM', vtpm_struct['VM']])
1929 def VTPM_get_all(self, session):
1930 xendom = XendDomain.instance()
1931 vtpms = [d.get_vtpms() for d in XendDomain.instance().list('all')]
1932 vtpms = reduce(lambda x, y: x + y, vtpms)
1933 return xen_api_success(vtpms)
1935 # Xen API: Class console
1936 # ----------------------------------------------------------------
1939 console_attr_ro = ['location', 'protocol', 'VM']
1940 console_attr_rw = ['other_config']
1941 console_funcs = [('create', 'console')]
1943 def console_get_all(self, session):
1944 xendom = XendDomain.instance()
1945 cons = [d.get_consoles() for d in XendDomain.instance().list('all')]
1946 cons = reduce(lambda x, y: x + y, cons)
1947 return xen_api_success(cons)
1949 def console_get_location(self, session, console_ref):
1950 return xen_api_success(xendom.get_dev_property_by_uuid('console',
1951 console_ref,
1952 'location'))
1954 def console_get_protocol(self, session, console_ref):
1955 return xen_api_success(xendom.get_dev_property_by_uuid('console',
1956 console_ref,
1957 'protocol'))
1959 def console_get_VM(self, session, console_ref):
1960 xendom = XendDomain.instance()
1961 vm = xendom.get_vm_with_dev_uuid('console', console_ref)
1962 return xen_api_success(vm.get_uuid())
1964 # object methods
1965 def console_get_record(self, session, console_ref):
1966 xendom = XendDomain.instance()
1967 vm = xendom.get_vm_with_dev_uuid('console', console_ref)
1968 if not vm:
1969 return xen_api_error(['HANDLE_INVALID', 'console', console_ref])
1970 cfg = vm.get_dev_xenapi_config('console', console_ref)
1971 if not cfg:
1972 return xen_api_error(['HANDLE_INVALID', 'console', console_ref])
1974 valid_console_keys = self.console_attr_ro + self.console_attr_rw + \
1975 self.Base_attr_ro + self.Base_attr_rw
1977 return_cfg = {}
1978 for k in cfg.keys():
1979 if k in valid_console_keys:
1980 return_cfg[k] = cfg[k]
1982 return xen_api_success(return_cfg)
1984 def console_create(self, session, console_struct):
1985 xendom = XendDomain.instance()
1986 if not xendom.is_valid_vm(console_struct['VM']):
1987 return xen_api_error(['HANDLE_INVALID', 'VM',
1988 console_struct['VM']])
1990 dom = xendom.get_vm_by_uuid(console_struct['VM'])
1991 try:
1992 if 'protocol' not in console_struct:
1993 return xen_api_error(['CONSOLE_PROTOCOL_INVALID',
1994 'No protocol specified'])
1996 console_ref = dom.create_console(console_struct)
1997 xendom.managed_config_save(dom)
1998 return xen_api_success(console_ref)
1999 except XendError, e:
2000 return xen_api_error([XEND_ERROR_TODO, str(e)])
2002 # Xen API: Class SR
2003 # ----------------------------------------------------------------
2004 SR_attr_ro = ['VDIs',
2005 'virtual_allocation',
2006 'physical_utilisation',
2007 'physical_size',
2008 'type',
2009 'location']
2011 SR_attr_rw = ['name_label',
2012 'name_description']
2014 SR_attr_inst = ['physical_size',
2015 'type',
2016 'location',
2017 'name_label',
2018 'name_description']
2020 SR_methods = [('clone', 'SR')]
2021 SR_funcs = [('get_by_name_label', 'Set(SR)'),
2022 ('get_by_uuid', 'SR')]
2024 # Class Functions
2025 def SR_get_all(self, session):
2026 return xen_api_success(XendNode.instance().get_all_sr_uuid())
2028 def SR_get_by_name_label(self, session, label):
2029 return xen_api_success(XendNode.instance().get_sr_by_name(label))
2031 def SR_create(self, session):
2032 return xen_api_error(XEND_ERROR_UNSUPPORTED)
2034 # Class Methods
2035 def SR_clone(self, session, sr_ref):
2036 return xen_api_error(XEND_ERROR_UNSUPPORTED)
2038 def SR_destroy(self, session, sr_ref):
2039 return xen_api_error(XEND_ERROR_UNSUPPORTED)
2041 def SR_get_record(self, session, sr_ref):
2042 sr = XendNode.instance().get_sr(sr_ref)
2043 if sr:
2044 return xen_api_success(sr.get_record())
2045 return xen_api_error(['HANDLE_INVALID', 'SR', sr_ref])
2047 # Attribute acceess
2049 def _get_SR_func(self, sr_ref, func):
2050 return xen_api_success(getattr(XendNode.instance().get_sr(sr_ref),
2051 func)())
2053 def _get_SR_attr(self, sr_ref, attr):
2054 return xen_api_success(getattr(XendNode.instance().get_sr(sr_ref),
2055 attr))
2057 def SR_get_VDIs(self, _, ref):
2058 return self._get_SR_func(ref, 'list_images')
2060 def SR_get_virtual_allocation(self, _, ref):
2061 return self._get_SR_func(ref, 'virtual_allocation')
2063 def SR_get_physical_utilisation(self, _, ref):
2064 return self._get_SR_func(ref, 'physical_utilisation')
2066 def SR_get_physical_size(self, _, ref):
2067 return self._get_SR_func(ref, 'physical_size')
2069 def SR_get_type(self, _, ref):
2070 return self._get_SR_attr(ref, 'type')
2072 def SR_get_location(self, _, ref):
2073 return self._get_SR_attr(ref, 'location')
2075 def SR_get_name_label(self, _, ref):
2076 return self._get_SR_attr(ref, 'name_label')
2078 def SR_get_name_description(self, _, ref):
2079 return self._get_SR_attr(ref, 'name_description')
2081 def SR_set_name_label(self, session, sr_ref, value):
2082 sr = XendNode.instance.get_sr(sr_ref)
2083 if sr:
2084 sr.name_label = value
2085 XendNode.instance().save()
2086 return xen_api_success_void()
2088 def SR_set_name_description(self, session, sr_ref, value):
2089 sr = XendNode.instance.get_sr(sr_ref)
2090 if sr:
2091 sr.name_description = value
2092 XendNode.instance().save()
2093 return xen_api_success_void()
2096 # Xen API: Class debug
2097 # ----------------------------------------------------------------
2099 debug_methods = [('destroy', None),
2100 ('get_record', 'debug')]
2101 debug_funcs = [('wait', None),
2102 ('return_failure', None)]
2104 def debug_wait(self, session, wait_secs):
2105 import time
2106 prog_units = 100/float(wait_secs)
2107 for i in range(int(wait_secs)):
2108 XendTask.log_progress(prog_units * i, prog_units * (i + 1),
2109 time.sleep, 1)
2110 return xen_api_success_void()
2113 def debug_return_failure(self, session):
2114 return xen_api_error(['DEBUG_FAIL', session])
2116 def debug_create(self, session):
2117 debug_uuid = uuid.createString()
2118 self._debug[debug_uuid] = None
2119 return xen_api_success(debug_uuid)
2121 def debug_destroy(self, session, debug_ref):
2122 del self._debug[debug_ref]
2123 return xen_api_success_void()
2125 def debug_get_record(self, session, debug_ref):
2126 return xen_api_success({'uuid': debug_ref})
2129 def list_all_methods(self, _):
2130 def _funcs():
2131 return [getattr(XendAPI, x) for x in XendAPI.__dict__]
2133 return xen_api_success([x.api for x in _funcs()
2134 if hasattr(x, 'api')])
2135 list_all_methods.api = '_UNSUPPORTED_list_all_methods'
2138 class XendAPIAsyncProxy:
2139 """ A redirector for Async.Class.function calls to XendAPI
2140 but wraps the call for use with the XendTaskManager.
2142 @ivar xenapi: Xen API instance
2143 @ivar method_map: Mapping from XMLRPC method name to callable objects.
2144 """
2146 method_prefix = 'Async.'
2148 def __init__(self, xenapi):
2149 """Initialises the Async Proxy by making a map of all
2150 implemented Xen API methods for use with XendTaskManager.
2152 @param xenapi: XendAPI instance
2153 """
2154 self.xenapi = xenapi
2155 self.method_map = {}
2156 for method_name in dir(self.xenapi):
2157 method = getattr(self.xenapi, method_name)
2158 if method_name[0] != '_' and hasattr(method, 'async') \
2159 and method.async == True:
2160 self.method_map[method.api] = method
2162 def _dispatch(self, method, args):
2163 """Overridden method so that SimpleXMLRPCServer will
2164 resolve methods through this method rather than through
2165 inspection.
2167 @param method: marshalled method name from XMLRPC.
2168 @param args: marshalled arguments from XMLRPC.
2169 """
2171 # Only deal with method names that start with "Async."
2172 if not method.startswith(self.method_prefix):
2173 return xen_api_error(['MESSAGE_METHOD_UNKNOWN', method])
2175 # Lookup synchronous version of the method
2176 synchronous_method_name = method[len(self.method_prefix):]
2177 if synchronous_method_name not in self.method_map:
2178 return xen_api_error(['MESSAGE_METHOD_UNKNOWN', method])
2180 method = self.method_map[synchronous_method_name]
2182 # Check that we've got enough arguments before issuing a task ID.
2183 needed = argcounts[method.api]
2184 if len(args) != needed:
2185 return xen_api_error(['MESSAGE_PARAMETER_COUNT_MISMATCH',
2186 self.method_prefix + method.api, needed,
2187 len(args)])
2189 # Validate the session before proceeding
2190 session = args[0]
2191 if not auth_manager().is_session_valid(session):
2192 return xen_api_error(['SESSION_INVALID', session])
2194 # create and execute the task, and return task_uuid
2195 return_type = getattr(method, 'return_type', None)
2196 task_uuid = XendTaskManager.create_task(method, args,
2197 synchronous_method_name,
2198 return_type,
2199 synchronous_method_name,
2200 session)
2201 return xen_api_success(task_uuid)
2204 # Auto generate some stubs based on XendAPI introspection
2206 if __name__ == "__main__":
2207 def output(line):
2208 print ' ' + line
2210 classes = ['VDI', 'SR']
2211 for cls in classes:
2212 ro_attrs = getattr(XendAPI, '%s_attr_ro' % cls, [])
2213 rw_attrs = getattr(XendAPI, '%s_attr_rw' % cls, [])
2214 methods = getattr(XendAPI, '%s_methods' % cls, [])
2215 funcs = getattr(XendAPI, '%s_funcs' % cls, [])
2217 ref = '%s_ref' % cls
2219 for attr_name in ro_attrs + rw_attrs + XendAPI.Base_attr_ro:
2220 getter_name = '%s_get_%s' % (cls, attr_name)
2221 output('def %s(self, session, %s):' % (getter_name, ref))
2222 output(' return xen_api_todo()')
2224 for attr_name in rw_attrs + XendAPI.Base_attr_rw:
2225 setter_name = '%s_set_%s' % (cls, attr_name)
2226 output('def %s(self, session, %s, value):' % (setter_name, ref))
2227 output(' return xen_api_todo()')
2229 for method_name in methods + XendAPI.Base_methods:
2230 method_full_name = '%s_%s' % (cls,method_name)
2231 output('def %s(self, session, %s):' % (method_full_name, ref))
2232 output(' return xen_api_todo()')
2234 for func_name in funcs + XendAPI.Base_funcs:
2235 func_full_name = '%s_%s' % (cls, func_name)
2236 output('def %s(self, session):' % func_full_name)
2237 output(' return xen_api_todo()')