direct-io.hg

view tools/python/xen/xend/XendAPI.py @ 14375:01e35a77ce8f

Implement VM.{add_to,remove_from}_VCPUs_params.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author Ewan Mellor <ewan@xensource.com>
date Tue Mar 13 22:13:40 2007 +0000 (2007-03-13)
parents e5d7b878118f
children 460dac5742cf
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_VCPUs_params', None),
1044 ('remove_from_VCPUs_params', None),
1045 ('add_to_platform', None),
1046 ('remove_from_platform', None),
1047 ('add_to_other_config', None),
1048 ('remove_from_other_config', None)]
1050 VM_funcs = [('create', 'VM'),
1051 ('get_by_name_label', 'Set(VM)')]
1053 # parameters required for _create()
1054 VM_attr_inst = [
1055 'name_label',
1056 'name_description',
1057 'user_version',
1058 'is_a_template',
1059 'memory_static_max',
1060 'memory_dynamic_max',
1061 'memory_dynamic_min',
1062 'memory_static_min',
1063 'VCPUs_policy',
1064 'VCPUs_params',
1065 'actions_after_shutdown',
1066 'actions_after_reboot',
1067 'actions_after_suspend',
1068 'actions_after_crash',
1069 'PV_bootloader',
1070 'PV_kernel',
1071 'PV_ramdisk',
1072 'PV_args',
1073 'PV_bootloader_args',
1074 'HVM_boot_policy',
1075 'HVM_boot_params',
1076 'platform',
1077 'PCI_bus',
1078 'other_config']
1080 def VM_get(self, name, session, vm_ref):
1081 return xen_api_success(
1082 XendDomain.instance().get_vm_by_uuid(vm_ref).info[name])
1084 def VM_set(self, name, session, vm_ref, value):
1085 xd = XendDomain.instance()
1086 dominfo = xd.get_vm_by_uuid(vm_ref)
1087 dominfo.info[name] = value
1088 return self._VM_save(dominfo)
1090 def _VM_save(self, dominfo):
1091 XendDomain.instance().managed_config_save(dominfo)
1092 return xen_api_success_void()
1094 # attributes (ro)
1095 def VM_get_power_state(self, session, vm_ref):
1096 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1097 return xen_api_success(dom.get_power_state())
1099 def VM_get_resident_on(self, session, vm_ref):
1100 return xen_api_success(XendNode.instance().uuid)
1102 def VM_get_memory_actual(self, session, vm_ref):
1103 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1104 return xen_api_todo() # unsupported by xc
1106 def VM_get_memory_static_max(self, session, vm_ref):
1107 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1108 return xen_api_success(dom.get_memory_static_max())
1110 def VM_get_memory_static_min(self, session, vm_ref):
1111 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1112 return xen_api_success(dom.get_memory_static_min())
1114 def VM_get_VCPUs_number(self, session, vm_ref):
1115 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1116 return xen_api_success(dom.getVCpuCount())
1118 def VM_get_VCPUs_utilisation(self, session, vm_ref):
1119 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1120 return xen_api_success(dom.get_vcpus_util())
1122 def VM_get_VIFs(self, session, vm_ref):
1123 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1124 return xen_api_success(dom.get_vifs())
1126 def VM_get_VBDs(self, session, vm_ref):
1127 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1128 return xen_api_success(dom.get_vbds())
1130 def VM_get_VTPMs(self, session, vm_ref):
1131 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1132 return xen_api_success(dom.get_vtpms())
1134 def VM_get_consoles(self, session, vm_ref):
1135 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1136 return xen_api_success(dom.get_consoles())
1138 def VM_get_tools_version(self, session, vm_ref):
1139 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1140 return dom.get_tools_version()
1142 # attributes (rw)
1143 def VM_get_name_label(self, session, vm_ref):
1144 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1145 return xen_api_success(dom.getName())
1147 def VM_get_name_description(self, session, vm_ref):
1148 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1149 return xen_api_todo()
1151 def VM_get_user_version(self, session, vm_ref):
1152 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1153 return xen_api_todo()
1155 def VM_get_is_a_template(self, session, vm_ref):
1156 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1157 return xen_api_todo()
1159 def VM_get_memory_dynamic_max(self, session, vm_ref):
1160 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1161 return xen_api_success(dom.get_memory_dynamic_max())
1163 def VM_get_memory_dynamic_min(self, session, vm_ref):
1164 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1165 return xen_api_success(dom.get_memory_dynamic_min())
1167 def VM_get_VCPUs_policy(self, session, vm_ref):
1168 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1169 return xen_api_success(dom.get_vcpus_policy())
1171 def VM_get_VCPUs_params(self, session, vm_ref):
1172 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1173 return xen_api_success(dom.get_vcpus_params())
1175 def VM_get_actions_after_shutdown(self, session, vm_ref):
1176 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1177 return xen_api_success(dom.get_on_shutdown())
1179 def VM_get_actions_after_reboot(self, session, vm_ref):
1180 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1181 return xen_api_success(dom.get_on_reboot())
1183 def VM_get_actions_after_suspend(self, session, vm_ref):
1184 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1185 return xen_api_success(dom.get_on_suspend())
1187 def VM_get_actions_after_crash(self, session, vm_ref):
1188 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1189 return xen_api_success(dom.get_on_crash())
1191 def VM_get_PV_bootloader(self, session, vm_ref):
1192 return self.VM_get('PV_bootloader', session, vm_ref)
1194 def VM_get_PV_kernel(self, session, vm_ref):
1195 return self.VM_get('PV_kernel', session, vm_ref)
1197 def VM_get_PV_ramdisk(self, session, vm_ref):
1198 return self.VM_get('PV_ramdisk', session, vm_ref)
1200 def VM_get_PV_args(self, session, vm_ref):
1201 return self.VM_get('PV_args', session, vm_ref)
1203 def VM_get_PV_bootloader_args(self, session, vm_ref):
1204 return self.VM_get('PV_bootloader_args', session, vm_ref)
1206 def VM_get_HVM_boot_policy(self, session, vm_ref):
1207 return self.VM_get('HVM_boot_policy', session, vm_ref)
1209 def VM_get_HVM_boot_params(self, session, vm_ref):
1210 return self.VM_get('HVM_boot_params', session, vm_ref)
1212 def VM_get_platform(self, session, vm_ref):
1213 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1214 return xen_api_success(dom.get_platform())
1216 def VM_get_PCI_bus(self, session, vm_ref):
1217 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1218 return dom.get_pci_bus()
1220 def VM_set_PCI_bus(self, session, vm_ref, val):
1221 return self.VM_set('PCI_bus', session, vm_ref, val)
1223 def VM_get_other_config(self, session, vm_ref):
1224 return self.VM_get('other_config', session, vm_ref)
1226 def VM_get_domid(self, _, ref):
1227 domid = XendDomain.instance().get_vm_by_uuid(ref).getDomid()
1228 return xen_api_success(domid is None and -1 or domid)
1230 def VM_get_is_control_domain(self, session, vm_ref):
1231 xd = XendDomain.instance()
1232 return xen_api_success(
1233 xd.get_vm_by_uuid(vm_ref) == xd.privilegedDomain())
1235 def VM_set_name_label(self, session, vm_ref, label):
1236 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1237 dom.setName(label)
1238 return self._VM_save(dom)
1240 def VM_set_name_description(self, session, vm_ref, desc):
1241 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1242 return xen_api_todo()
1244 def VM_set_user_version(self, session, vm_ref, ver):
1245 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1246 return xen_api_todo()
1248 def VM_set_is_a_template(self, session, vm_ref, is_template):
1249 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1250 return xen_api_todo()
1252 def VM_set_memory_dynamic_max(self, session, vm_ref, mem):
1253 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1254 return xen_api_todo()
1256 def VM_set_memory_dynamic_min(self, session, vm_ref, mem):
1257 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1258 return xen_api_todo()
1260 def VM_set_VCPUs_policy(self, session, vm_ref, policy):
1261 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1262 return xen_api_todo()
1264 def VM_set_VCPUs_params(self, session, vm_ref, value):
1265 return self.VM_set('vcpus_params', session, vm_ref, value)
1267 def VM_add_to_VCPUs_params(self, session, vm_ref, key, value):
1268 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1269 if 'vcpus_params' not in dom.info:
1270 dom.info['vcpus_params'] = {}
1271 dom.info['vcpus_params'][key] = value
1272 return self._VM_save(dom)
1274 def VM_remove_from_VCPUs_params(self, session, vm_ref, key):
1275 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1276 if 'vcpus_params' in dom.info \
1277 and key in dom.info['vcpus_params']:
1278 del dom.info['vcpus_params'][key]
1279 return self._VM_save(dom)
1280 else:
1281 return xen_api_success_void()
1283 def VM_set_actions_after_shutdown(self, session, vm_ref, action):
1284 if action not in XEN_API_ON_NORMAL_EXIT:
1285 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1286 return self.VM_set('actions_after_shutdown', session, vm_ref, action)
1288 def VM_set_actions_after_reboot(self, session, vm_ref, action):
1289 if action not in XEN_API_ON_NORMAL_EXIT:
1290 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1291 return self.VM_set('actions_after_reboot', session, vm_ref, action)
1293 def VM_set_actions_after_suspend(self, session, vm_ref, action):
1294 if action not in XEN_API_ON_NORMAL_EXIT:
1295 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1296 return self.VM_set('actions_after_suspend', session, vm_ref, action)
1298 def VM_set_actions_after_crash(self, session, vm_ref, action):
1299 if action not in XEN_API_ON_CRASH_BEHAVIOUR:
1300 return xen_api_error(['VM_ON_CRASH_BEHAVIOUR_INVALID', vm_ref])
1301 return self.VM_set('actions_after_crash', session, vm_ref, action)
1303 def VM_set_HVM_boot_policy(self, session, vm_ref, value):
1304 if value != "" and value != "BIOS order":
1305 return xen_api_error(
1306 ['VALUE_NOT_SUPPORTED', 'VM.HVM_boot_policy', value,
1307 'Xend supports only the "BIOS order" boot policy.'])
1308 else:
1309 return self.VM_set('HVM_boot_policy', session, vm_ref, value)
1311 def VM_set_HVM_boot_params(self, session, vm_ref, value):
1312 return self.VM_set('HVM_boot_params', session, vm_ref, value)
1314 def VM_add_to_HVM_boot_params(self, session, vm_ref, key, value):
1315 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1316 if 'HVM_boot_params' not in dom.info:
1317 dom.info['HVM_boot_params'] = {}
1318 dom.info['HVM_boot_params'][key] = value
1319 return self._VM_save(dom)
1321 def VM_remove_from_HVM_boot_params(self, session, vm_ref, key):
1322 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1323 if 'HVM_boot_params' in dom.info \
1324 and key in dom.info['HVM_boot_params']:
1325 del dom.info['HVM_boot_params'][key]
1326 return self._VM_save(dom)
1327 else:
1328 return xen_api_success_void()
1330 def VM_set_PV_bootloader(self, session, vm_ref, value):
1331 return self.VM_set('PV_bootloader', session, vm_ref, value)
1333 def VM_set_PV_kernel(self, session, vm_ref, value):
1334 return self.VM_set('PV_kernel', session, vm_ref, value)
1336 def VM_set_PV_ramdisk(self, session, vm_ref, value):
1337 return self.VM_set('PV_ramdisk', session, vm_ref, value)
1339 def VM_set_PV_args(self, session, vm_ref, value):
1340 return self.VM_set('PV_args', session, vm_ref, value)
1342 def VM_set_PV_bootloader_args(self, session, vm_ref, value):
1343 return self.VM_set('PV_bootloader_args', session, vm_ref, value)
1345 def VM_set_platform(self, session, vm_ref, value):
1346 return self.VM_set('platform', session, vm_ref, value)
1348 def VM_add_to_platform(self, session, vm_ref, key, value):
1349 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1350 plat = dom.get_platform()
1351 plat[key] = value
1352 return self.VM_set_platform(session, vm_ref, plat)
1354 def VM_remove_from_platform(self, session, vm_ref, key):
1355 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1356 plat = dom.get_platform()
1357 if key in plat:
1358 del plat[key]
1359 return self.VM_set_platform(session, vm_ref, plat)
1360 else:
1361 return xen_api_success_void()
1363 def VM_set_other_config(self, session, vm_ref, value):
1364 return self.VM_set('other_config', session, vm_ref, value)
1366 def VM_add_to_other_config(self, session, vm_ref, key, value):
1367 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1368 if dom and 'other_config' in dom.info:
1369 dom.info['other_config'][key] = value
1370 return self._VM_save(dom)
1372 def VM_remove_from_other_config(self, session, vm_ref, key):
1373 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1374 if dom and 'other_config' in dom.info \
1375 and key in dom.info['other_config']:
1376 del dom.info['other_config'][key]
1377 return self._VM_save(dom)
1378 else:
1379 return xen_api_success_void()
1381 # class methods
1382 def VM_get_all(self, session):
1383 refs = [d.get_uuid() for d in XendDomain.instance().list('all')]
1384 return xen_api_success(refs)
1386 def VM_get_by_name_label(self, session, label):
1387 xendom = XendDomain.instance()
1388 dom = xendom.domain_lookup_nr(label)
1389 if dom:
1390 return xen_api_success([dom.get_uuid()])
1391 return xen_api_success([])
1393 def VM_create(self, session, vm_struct):
1394 xendom = XendDomain.instance()
1395 domuuid = XendTask.log_progress(0, 100,
1396 xendom.create_domain, vm_struct)
1397 return xen_api_success(domuuid)
1399 # object methods
1400 def VM_get_record(self, session, vm_ref):
1401 xendom = XendDomain.instance()
1402 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1403 if not xeninfo:
1404 return xen_api_error(['HANDLE_INVALID', 'VM', vm_ref])
1406 domid = xeninfo.getDomid()
1408 record = {
1409 'uuid': xeninfo.get_uuid(),
1410 'power_state': xeninfo.get_power_state(),
1411 'name_label': xeninfo.getName(),
1412 'name_description': xeninfo.getName(),
1413 'user_version': 1,
1414 'is_a_template': False,
1415 'auto_power_on': False,
1416 'resident_on': XendNode.instance().uuid,
1417 'memory_static_min': xeninfo.get_memory_static_min(),
1418 'memory_static_max': xeninfo.get_memory_static_max(),
1419 'memory_dynamic_min': xeninfo.get_memory_dynamic_min(),
1420 'memory_dynamic_max': xeninfo.get_memory_dynamic_max(),
1421 'memory_actual': xeninfo.get_memory_static_min(),
1422 'VCPUs_policy': xeninfo.get_vcpus_policy(),
1423 'VCPUs_params': xeninfo.get_vcpus_params(),
1424 'VCPUs_number': xeninfo.getVCpuCount(),
1425 'VCPUs_utilisation': xeninfo.get_vcpus_util(),
1426 'actions_after_shutdown': xeninfo.get_on_shutdown(),
1427 'actions_after_reboot': xeninfo.get_on_reboot(),
1428 'actions_after_suspend': xeninfo.get_on_suspend(),
1429 'actions_after_crash': xeninfo.get_on_crash(),
1430 'consoles': xeninfo.get_consoles(),
1431 'VIFs': xeninfo.get_vifs(),
1432 'VBDs': xeninfo.get_vbds(),
1433 'VTPMs': xeninfo.get_vtpms(),
1434 'PV_bootloader': xeninfo.info.get('PV_bootloader'),
1435 'PV_kernel': xeninfo.info.get('PV_kernel'),
1436 'PV_ramdisk': xeninfo.info.get('PV_ramdisk'),
1437 'PV_args': xeninfo.info.get('PV_args'),
1438 'PV_bootloader_args': xeninfo.info.get('PV_bootloader_args'),
1439 'HVM_boot_policy': xeninfo.info.get('HVM_boot_policy'),
1440 'HVM_boot_params': xeninfo.info.get('HVM_boot_params'),
1441 'platform': xeninfo.get_platform(),
1442 'PCI_bus': xeninfo.get_pci_bus(),
1443 'tools_version': xeninfo.get_tools_version(),
1444 'other_config': xeninfo.info.get('other_config', {}),
1445 'domid': domid is None and -1 or domid,
1446 'is_control_domain': xeninfo == xendom.privilegedDomain(),
1448 return xen_api_success(record)
1450 def VM_clean_reboot(self, session, vm_ref):
1451 xendom = XendDomain.instance()
1452 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1453 XendTask.log_progress(0, 100, xeninfo.shutdown, "reboot")
1454 return xen_api_success_void()
1456 def VM_clean_shutdown(self, session, vm_ref):
1457 xendom = XendDomain.instance()
1458 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1459 XendTask.log_progress(0, 100, xeninfo.shutdown, "poweroff")
1460 return xen_api_success_void()
1462 def VM_clone(self, session, vm_ref):
1463 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1465 def VM_destroy(self, session, vm_ref):
1466 return XendTask.log_progress(0, 100, do_vm_func,
1467 "domain_delete", vm_ref)
1469 def VM_hard_reboot(self, session, vm_ref):
1470 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1472 def VM_hard_shutdown(self, session, vm_ref):
1473 return XendTask.log_progress(0, 100, do_vm_func,
1474 "domain_destroy", vm_ref)
1475 def VM_pause(self, session, vm_ref):
1476 return XendTask.log_progress(0, 100, do_vm_func,
1477 "domain_pause", vm_ref)
1479 def VM_resume(self, session, vm_ref, start_paused):
1480 return XendTask.log_progress(0, 100, do_vm_func,
1481 "domain_resume", vm_ref,
1482 start_paused = start_paused)
1484 def VM_start(self, session, vm_ref, start_paused):
1485 try:
1486 return XendTask.log_progress(0, 100, do_vm_func,
1487 "domain_start", vm_ref,
1488 start_paused = start_paused)
1489 except HVMRequired, exn:
1490 return xen_api_error(['VM_HVM_REQUIRED', vm_ref])
1492 def VM_suspend(self, session, vm_ref):
1493 return XendTask.log_progress(0, 100, do_vm_func,
1494 "domain_suspend", vm_ref)
1496 def VM_unpause(self, session, vm_ref):
1497 return XendTask.log_progress(0, 100, do_vm_func,
1498 "domain_unpause", vm_ref)
1500 # Xen API: Class VBD
1501 # ----------------------------------------------------------------
1503 VBD_attr_ro = ['metrics']
1504 VBD_attr_rw = ['VM',
1505 'VDI',
1506 'device',
1507 'bootable',
1508 'mode',
1509 'type']
1511 VBD_attr_inst = VBD_attr_rw
1513 VBD_methods = [('media_change', None)]
1514 VBD_funcs = [('create', 'VBD')]
1516 # object methods
1517 def VBD_get_record(self, session, vbd_ref):
1518 xendom = XendDomain.instance()
1519 vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1520 if not vm:
1521 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1522 cfg = vm.get_dev_xenapi_config('vbd', vbd_ref)
1523 if not cfg:
1524 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1526 valid_vbd_keys = self.VBD_attr_ro + self.VBD_attr_rw + \
1527 self.Base_attr_ro + self.Base_attr_rw
1529 return_cfg = {}
1530 for k in cfg.keys():
1531 if k in valid_vbd_keys:
1532 return_cfg[k] = cfg[k]
1534 return_cfg['metrics'] = vbd_ref
1536 return xen_api_success(return_cfg)
1538 def VBD_media_change(self, session, vbd_ref, vdi_ref):
1539 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1541 # class methods
1542 def VBD_create(self, session, vbd_struct):
1543 xendom = XendDomain.instance()
1544 if not xendom.is_valid_vm(vbd_struct['VM']):
1545 return xen_api_error(['HANDLE_INVALID', 'VM', vbd_struct['VM']])
1547 dom = xendom.get_vm_by_uuid(vbd_struct['VM'])
1548 vbd_ref = ''
1549 try:
1550 # new VBD via VDI/SR
1551 vdi_ref = vbd_struct.get('VDI')
1552 vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
1553 if not vdi:
1554 return xen_api_error(['HANDLE_INVALID', 'VDI', vdi_ref])
1555 vdi_image = vdi.get_location()
1556 vbd_ref = XendTask.log_progress(0, 100,
1557 dom.create_vbd,
1558 vbd_struct, vdi_image)
1559 except XendError:
1560 return xen_api_todo()
1562 xendom.managed_config_save(dom)
1563 return xen_api_success(vbd_ref)
1566 def VBD_destroy(self, session, vbd_ref):
1567 xendom = XendDomain.instance()
1568 vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1569 if not vm:
1570 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1572 XendTask.log_progress(0, 100, vm.destroy_vbd, vbd_ref)
1573 return xen_api_success_void()
1575 def _VBD_get(self, vbd_ref, prop):
1576 return xen_api_success(
1577 XendDomain.instance().get_dev_property_by_uuid(
1578 'vbd', vbd_ref, prop))
1580 # attributes (ro)
1581 def VBD_get_metrics(self, _, vbd_ref):
1582 return xen_api_success(vbd_ref)
1584 # attributes (rw)
1585 def VBD_get_VM(self, session, vbd_ref):
1586 return self._VBD_get(vbd_ref, 'VM')
1588 def VBD_get_VDI(self, session, vbd_ref):
1589 return self._VBD_get(vbd_ref, 'VDI')
1591 def VBD_get_device(self, session, vbd_ref):
1592 return self._VBD_get(vbd_ref, 'device')
1594 def VBD_get_bootable(self, session, vbd_ref):
1595 return self._VBD_get(vbd_ref, 'bootable')
1597 def VBD_get_mode(self, session, vbd_ref):
1598 return self._VBD_get(vbd_ref, 'mode')
1600 def VBD_get_type(self, session, vbd_ref):
1601 return self._VBD_get(vbd_ref, 'type')
1603 def VBD_set_bootable(self, session, vbd_ref, bootable):
1604 bootable = bool(bootable)
1605 xd = XendDomain.instance()
1606 vm = xd.get_vm_with_dev_uuid('vbd', vbd_ref)
1607 vm.set_dev_property('vbd', vbd_ref, 'bootable', bootable)
1608 xd.managed_config_save(vm)
1609 return xen_api_success_void()
1611 def VBD_get_all(self, session):
1612 xendom = XendDomain.instance()
1613 vbds = [d.get_vbds() for d in XendDomain.instance().list('all')]
1614 vbds = reduce(lambda x, y: x + y, vbds)
1615 return xen_api_success(vbds)
1618 # Xen API: Class VBD_metrics
1619 # ----------------------------------------------------------------
1621 VBD_metrics_attr_ro = ['io_read_kbs',
1622 'io_write_kbs']
1623 VBD_metrics_attr_rw = []
1624 VBD_methods = []
1626 def VBD_metrics_get_record(self, _, ref):
1627 vm = XendDomain.instance().get_vm_with_dev_uuid('vbd', ref)
1628 if not vm:
1629 return xen_api_error(['HANDLE_INVALID', 'VBD_metrics', ref])
1630 return xen_api_success(
1631 { 'io_read_kbs' : vm.get_dev_property('vbd', ref, 'io_read_kbs'),
1632 'io_write_kbs' : vm.get_dev_property('vbd', ref, 'io_write_kbs') })
1634 def VBD_metrics_get_io_read_kbs(self, _, ref):
1635 return self._VBD_get(ref, 'io_read_kbs')
1637 def VBD_metrics_get_io_write_kbs(self, session, ref):
1638 return self._VBD_get(ref, 'io_write_kbs')
1641 # Xen API: Class VIF
1642 # ----------------------------------------------------------------
1644 VIF_attr_ro = ['metrics']
1645 VIF_attr_rw = ['device',
1646 'network',
1647 'VM',
1648 'MAC',
1649 'MTU']
1651 VIF_attr_inst = VIF_attr_rw
1653 VIF_funcs = [('create', 'VIF')]
1656 # object methods
1657 def VIF_get_record(self, session, vif_ref):
1658 xendom = XendDomain.instance()
1659 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
1660 if not vm:
1661 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
1662 cfg = vm.get_dev_xenapi_config('vif', vif_ref)
1663 if not cfg:
1664 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
1666 valid_vif_keys = self.VIF_attr_ro + self.VIF_attr_rw + \
1667 self.Base_attr_ro + self.Base_attr_rw
1669 return_cfg = {}
1670 for k in cfg.keys():
1671 if k in valid_vif_keys:
1672 return_cfg[k] = cfg[k]
1674 return_cfg['metrics'] = vif_ref
1676 return xen_api_success(return_cfg)
1678 # class methods
1679 def VIF_create(self, session, vif_struct):
1680 xendom = XendDomain.instance()
1681 if xendom.is_valid_vm(vif_struct['VM']):
1682 dom = xendom.get_vm_by_uuid(vif_struct['VM'])
1683 try:
1684 vif_ref = dom.create_vif(vif_struct)
1685 xendom.managed_config_save(dom)
1686 return xen_api_success(vif_ref)
1687 except XendError:
1688 return xen_api_error(XEND_ERROR_TODO)
1689 else:
1690 return xen_api_error(['HANDLE_INVALID', 'VM', vif_struct['VM']])
1693 def VIF_destroy(self, session, vif_ref):
1694 xendom = XendDomain.instance()
1695 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
1696 if not vm:
1697 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
1699 vm.destroy_vif(vif_ref)
1700 return xen_api_success_void()
1702 def _VIF_get(self, ref, prop):
1703 return xen_api_success(
1704 XendDomain.instance().get_dev_property_by_uuid('vif', ref, prop))
1706 # getters/setters
1707 def VIF_get_metrics(self, _, vif_ref):
1708 return xen_api_success(vif_ref)
1710 def VIF_get_VM(self, session, vif_ref):
1711 xendom = XendDomain.instance()
1712 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
1713 return xen_api_success(vm.get_uuid())
1715 def VIF_get_MTU(self, session, vif_ref):
1716 return self._VIF_get(vif_ref, 'MTU')
1718 def VIF_get_MAC(self, session, vif_ref):
1719 return self._VIF_get(vif_ref, 'MAC')
1721 def VIF_get_device(self, session, vif_ref):
1722 return self._VIF_get(vif_ref, 'device')
1724 def VIF_get_all(self, session):
1725 xendom = XendDomain.instance()
1726 vifs = [d.get_vifs() for d in XendDomain.instance().list('all')]
1727 vifs = reduce(lambda x, y: x + y, vifs)
1728 return xen_api_success(vifs)
1731 # Xen API: Class VIF_metrics
1732 # ----------------------------------------------------------------
1734 VIF_metrics_attr_ro = ['io_read_kbs',
1735 'io_write_kbs']
1736 VIF_metrics_attr_rw = []
1737 VIF_methods = []
1739 def VIF_metrics_get_record(self, _, ref):
1740 vm = XendDomain.instance().get_vm_with_dev_uuid('vif', ref)
1741 if not vm:
1742 return xen_api_error(['HANDLE_INVALID', 'VIF_metrics', ref])
1743 return xen_api_success(
1744 { 'io_read_kbs' : vm.get_dev_property('vif', ref, 'io_read_kbs'),
1745 'io_write_kbs' : vm.get_dev_property('vif', ref, 'io_write_kbs') })
1747 def VIF_metrics_get_io_read_kbs(self, _, ref):
1748 return self._VIF_get(ref, 'io_read_kbs')
1750 def VIF_metrics_get_io_write_kbs(self, session, ref):
1751 return self._VIF_get(ref, 'io_write_kbs')
1754 # Xen API: Class VDI
1755 # ----------------------------------------------------------------
1756 VDI_attr_ro = ['SR',
1757 'VBDs',
1758 'physical_utilisation',
1759 'sector_size',
1760 'type']
1761 VDI_attr_rw = ['name_label',
1762 'name_description',
1763 'virtual_size',
1764 'sharable',
1765 'read_only']
1766 VDI_attr_inst = VDI_attr_ro + VDI_attr_rw
1768 VDI_methods = [('snapshot', 'VDI')]
1769 VDI_funcs = [('create', 'VDI'),
1770 ('get_by_name_label', 'Set(VDI)')]
1772 def _get_VDI(self, ref):
1773 return XendNode.instance().get_vdi_by_uuid(ref)
1775 def VDI_get_VBDs(self, session, vdi_ref):
1776 return xen_api_todo()
1778 def VDI_get_physical_utilisation(self, session, vdi_ref):
1779 return xen_api_success(self._get_VDI(vdi_ref).
1780 get_physical_utilisation())
1782 def VDI_get_sector_size(self, session, vdi_ref):
1783 return xen_api_success(self._get_VDI(vdi_ref).sector_size)
1785 def VDI_get_type(self, session, vdi_ref):
1786 return xen_api_success(self._get_VDI(vdi_ref).type)
1788 def VDI_get_name_label(self, session, vdi_ref):
1789 return xen_api_success(self._get_VDI(vdi_ref).name_label)
1791 def VDI_get_name_description(self, session, vdi_ref):
1792 return xen_api_success(self._get_VDI(vdi_ref).name_description)
1794 def VDI_get_SR(self, session, vdi_ref):
1795 return xen_api_success(self._get_VDI(vdi_ref).sr_uuid)
1797 def VDI_get_virtual_size(self, session, vdi_ref):
1798 return xen_api_success(self._get_VDI(vdi_ref).virtual_size)
1800 def VDI_get_sharable(self, session, vdi_ref):
1801 return xen_api_success(self._get_VDI(vdi_ref).sharable)
1803 def VDI_get_read_only(self, session, vdi_ref):
1804 return xen_api_success(self._get_VDI(vdi_ref).read_only)
1806 def VDI_set_name_label(self, session, vdi_ref, value):
1807 self._get_VDI(vdi_ref).name_label = value
1808 return xen_api_success_void()
1810 def VDI_set_name_description(self, session, vdi_ref, value):
1811 self._get_VDI(vdi_ref).name_description = value
1812 return xen_api_success_void()
1814 def VDI_set_virtual_size(self, session, vdi_ref, value):
1815 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1817 def VDI_set_sharable(self, session, vdi_ref, value):
1818 self._get_VDI(vdi_ref).sharable = bool(value)
1819 return xen_api_success_void()
1821 def VDI_set_read_only(self, session, vdi_ref, value):
1822 self._get_VDI(vdi_ref).read_only = bool(value)
1823 return xen_api_success_void()
1825 # Object Methods
1826 def VDI_snapshot(self, session, vdi_ref):
1827 return xen_api_todo()
1829 def VDI_destroy(self, session, vdi_ref):
1830 sr = XendNode.instance().get_sr_containing_vdi(vdi_ref)
1831 sr.destroy_vdi(vdi_ref)
1832 return xen_api_success_void()
1834 def VDI_get_record(self, session, vdi_ref):
1835 image = XendNode.instance().get_vdi_by_uuid(vdi_ref)
1836 return xen_api_success({
1837 'uuid': vdi_ref,
1838 'name_label': image.name_label,
1839 'name_description': image.name_description,
1840 'SR': image.sr_uuid,
1841 'VBDs': [], # TODO
1842 'virtual_size': image.virtual_size,
1843 'physical_utilisation': image.physical_utilisation,
1844 'sector_size': image.sector_size,
1845 'type': image.type,
1846 'sharable': image.sharable,
1847 'read_only': image.read_only,
1848 })
1850 # Class Functions
1851 def VDI_create(self, session, vdi_struct):
1852 sr_ref = vdi_struct.get('SR')
1853 xennode = XendNode.instance()
1854 if not xennode.is_valid_sr(sr_ref):
1855 return xen_api_error(['HANDLE_INVALID', 'SR', sr_ref])
1857 vdi_uuid = xennode.srs[sr_ref].create_vdi(vdi_struct)
1858 return xen_api_success(vdi_uuid)
1860 def VDI_get_all(self, session):
1861 xennode = XendNode.instance()
1862 vdis = [sr.get_vdis() for sr in xennode.srs.values()]
1863 return xen_api_success(reduce(lambda x, y: x + y, vdis))
1865 def VDI_get_by_name_label(self, session, name):
1866 xennode = XendNode.instance()
1867 return xen_api_success(xennode.get_vdi_by_name_label(name))
1870 # Xen API: Class VTPM
1871 # ----------------------------------------------------------------
1873 VTPM_attr_rw = [ ]
1874 VTPM_attr_ro = ['VM',
1875 'backend']
1877 VTPM_attr_inst = VTPM_attr_rw
1879 VTPM_funcs = [('create', 'VTPM')]
1881 # object methods
1882 def VTPM_get_record(self, session, vtpm_ref):
1883 xendom = XendDomain.instance()
1884 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
1885 if not vm:
1886 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
1887 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
1888 if not cfg:
1889 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
1890 valid_vtpm_keys = self.VTPM_attr_ro + self.VTPM_attr_rw + \
1891 self.Base_attr_ro + self.Base_attr_rw
1892 return_cfg = {}
1893 for k in cfg.keys():
1894 if k in valid_vtpm_keys:
1895 return_cfg[k] = cfg[k]
1897 return xen_api_success(return_cfg)
1899 # Class Functions
1900 def VTPM_get_backend(self, session, vtpm_ref):
1901 xendom = XendDomain.instance()
1902 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
1903 if not vm:
1904 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
1905 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
1906 if not cfg:
1907 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
1908 if not cfg.has_key('backend'):
1909 return xen_api_error(['VTPM backend not set'])
1910 return xen_api_success(cfg['backend'])
1912 def VTPM_get_VM(self, session, vtpm_ref):
1913 xendom = XendDomain.instance()
1914 return xen_api_success(xendom.get_dev_property_by_uuid('vtpm',
1915 vtpm_ref, 'VM'))
1917 def VTPM_destroy(self, session, vtpm_ref):
1918 xendom = XendDomain.instance()
1919 dom = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
1920 if dom:
1921 if dom.state != XEN_API_VM_POWER_STATE_HALTED:
1922 vm_ref = dom.get_dev_property('vtpm', vtpm_ref, 'VM')
1923 return xen_api_error(['VM_BAD_POWER_STATE', vm_ref,
1924 XendDomain.POWER_STATE_NAMES[XEN_API_VM_POWER_STATE_HALTED],
1925 XendDomain.POWER_STATE_NAMES[dom.state]])
1926 from xen.xend.server import tpmif
1927 tpmif.destroy_vtpmstate(dom.getName())
1928 return xen_api_success_void()
1929 else:
1930 return xen_api_error(['HANDLE_INVALID', 'VM', vtpm_struct['VM']])
1932 # class methods
1933 def VTPM_create(self, session, vtpm_struct):
1934 xendom = XendDomain.instance()
1935 if xendom.is_valid_vm(vtpm_struct['VM']):
1936 dom = xendom.get_vm_by_uuid(vtpm_struct['VM'])
1937 try:
1938 vtpm_ref = dom.create_vtpm(vtpm_struct)
1939 xendom.managed_config_save(dom)
1940 return xen_api_success(vtpm_ref)
1941 except XendError:
1942 return xen_api_error(XEND_ERROR_TODO)
1943 else:
1944 return xen_api_error(['HANDLE_INVALID', 'VM', vtpm_struct['VM']])
1946 def VTPM_get_all(self, session):
1947 xendom = XendDomain.instance()
1948 vtpms = [d.get_vtpms() for d in XendDomain.instance().list('all')]
1949 vtpms = reduce(lambda x, y: x + y, vtpms)
1950 return xen_api_success(vtpms)
1952 # Xen API: Class console
1953 # ----------------------------------------------------------------
1956 console_attr_ro = ['location', 'protocol', 'VM']
1957 console_attr_rw = ['other_config']
1958 console_funcs = [('create', 'console')]
1960 def console_get_all(self, session):
1961 xendom = XendDomain.instance()
1962 cons = [d.get_consoles() for d in XendDomain.instance().list('all')]
1963 cons = reduce(lambda x, y: x + y, cons)
1964 return xen_api_success(cons)
1966 def console_get_location(self, session, console_ref):
1967 return xen_api_success(xendom.get_dev_property_by_uuid('console',
1968 console_ref,
1969 'location'))
1971 def console_get_protocol(self, session, console_ref):
1972 return xen_api_success(xendom.get_dev_property_by_uuid('console',
1973 console_ref,
1974 'protocol'))
1976 def console_get_VM(self, session, console_ref):
1977 xendom = XendDomain.instance()
1978 vm = xendom.get_vm_with_dev_uuid('console', console_ref)
1979 return xen_api_success(vm.get_uuid())
1981 # object methods
1982 def console_get_record(self, session, console_ref):
1983 xendom = XendDomain.instance()
1984 vm = xendom.get_vm_with_dev_uuid('console', console_ref)
1985 if not vm:
1986 return xen_api_error(['HANDLE_INVALID', 'console', console_ref])
1987 cfg = vm.get_dev_xenapi_config('console', console_ref)
1988 if not cfg:
1989 return xen_api_error(['HANDLE_INVALID', 'console', console_ref])
1991 valid_console_keys = self.console_attr_ro + self.console_attr_rw + \
1992 self.Base_attr_ro + self.Base_attr_rw
1994 return_cfg = {}
1995 for k in cfg.keys():
1996 if k in valid_console_keys:
1997 return_cfg[k] = cfg[k]
1999 return xen_api_success(return_cfg)
2001 def console_create(self, session, console_struct):
2002 xendom = XendDomain.instance()
2003 if not xendom.is_valid_vm(console_struct['VM']):
2004 return xen_api_error(['HANDLE_INVALID', 'VM',
2005 console_struct['VM']])
2007 dom = xendom.get_vm_by_uuid(console_struct['VM'])
2008 try:
2009 if 'protocol' not in console_struct:
2010 return xen_api_error(['CONSOLE_PROTOCOL_INVALID',
2011 'No protocol specified'])
2013 console_ref = dom.create_console(console_struct)
2014 xendom.managed_config_save(dom)
2015 return xen_api_success(console_ref)
2016 except XendError, e:
2017 return xen_api_error([XEND_ERROR_TODO, str(e)])
2019 # Xen API: Class SR
2020 # ----------------------------------------------------------------
2021 SR_attr_ro = ['VDIs',
2022 'virtual_allocation',
2023 'physical_utilisation',
2024 'physical_size',
2025 'type',
2026 'location']
2028 SR_attr_rw = ['name_label',
2029 'name_description']
2031 SR_attr_inst = ['physical_size',
2032 'type',
2033 'location',
2034 'name_label',
2035 'name_description']
2037 SR_methods = [('clone', 'SR')]
2038 SR_funcs = [('get_by_name_label', 'Set(SR)'),
2039 ('get_by_uuid', 'SR')]
2041 # Class Functions
2042 def SR_get_all(self, session):
2043 return xen_api_success(XendNode.instance().get_all_sr_uuid())
2045 def SR_get_by_name_label(self, session, label):
2046 return xen_api_success(XendNode.instance().get_sr_by_name(label))
2048 def SR_create(self, session):
2049 return xen_api_error(XEND_ERROR_UNSUPPORTED)
2051 # Class Methods
2052 def SR_clone(self, session, sr_ref):
2053 return xen_api_error(XEND_ERROR_UNSUPPORTED)
2055 def SR_destroy(self, session, sr_ref):
2056 return xen_api_error(XEND_ERROR_UNSUPPORTED)
2058 def SR_get_record(self, session, sr_ref):
2059 sr = XendNode.instance().get_sr(sr_ref)
2060 if sr:
2061 return xen_api_success(sr.get_record())
2062 return xen_api_error(['HANDLE_INVALID', 'SR', sr_ref])
2064 # Attribute acceess
2066 def _get_SR_func(self, sr_ref, func):
2067 return xen_api_success(getattr(XendNode.instance().get_sr(sr_ref),
2068 func)())
2070 def _get_SR_attr(self, sr_ref, attr):
2071 return xen_api_success(getattr(XendNode.instance().get_sr(sr_ref),
2072 attr))
2074 def SR_get_VDIs(self, _, ref):
2075 return self._get_SR_func(ref, 'list_images')
2077 def SR_get_virtual_allocation(self, _, ref):
2078 return self._get_SR_func(ref, 'virtual_allocation')
2080 def SR_get_physical_utilisation(self, _, ref):
2081 return self._get_SR_func(ref, 'physical_utilisation')
2083 def SR_get_physical_size(self, _, ref):
2084 return self._get_SR_func(ref, 'physical_size')
2086 def SR_get_type(self, _, ref):
2087 return self._get_SR_attr(ref, 'type')
2089 def SR_get_location(self, _, ref):
2090 return self._get_SR_attr(ref, 'location')
2092 def SR_get_name_label(self, _, ref):
2093 return self._get_SR_attr(ref, 'name_label')
2095 def SR_get_name_description(self, _, ref):
2096 return self._get_SR_attr(ref, 'name_description')
2098 def SR_set_name_label(self, session, sr_ref, value):
2099 sr = XendNode.instance.get_sr(sr_ref)
2100 if sr:
2101 sr.name_label = value
2102 XendNode.instance().save()
2103 return xen_api_success_void()
2105 def SR_set_name_description(self, session, sr_ref, value):
2106 sr = XendNode.instance.get_sr(sr_ref)
2107 if sr:
2108 sr.name_description = value
2109 XendNode.instance().save()
2110 return xen_api_success_void()
2113 # Xen API: Class debug
2114 # ----------------------------------------------------------------
2116 debug_methods = [('destroy', None),
2117 ('get_record', 'debug')]
2118 debug_funcs = [('wait', None),
2119 ('return_failure', None)]
2121 def debug_wait(self, session, wait_secs):
2122 import time
2123 prog_units = 100/float(wait_secs)
2124 for i in range(int(wait_secs)):
2125 XendTask.log_progress(prog_units * i, prog_units * (i + 1),
2126 time.sleep, 1)
2127 return xen_api_success_void()
2130 def debug_return_failure(self, session):
2131 return xen_api_error(['DEBUG_FAIL', session])
2133 def debug_create(self, session):
2134 debug_uuid = uuid.createString()
2135 self._debug[debug_uuid] = None
2136 return xen_api_success(debug_uuid)
2138 def debug_destroy(self, session, debug_ref):
2139 del self._debug[debug_ref]
2140 return xen_api_success_void()
2142 def debug_get_record(self, session, debug_ref):
2143 return xen_api_success({'uuid': debug_ref})
2146 def list_all_methods(self, _):
2147 def _funcs():
2148 return [getattr(XendAPI, x) for x in XendAPI.__dict__]
2150 return xen_api_success([x.api for x in _funcs()
2151 if hasattr(x, 'api')])
2152 list_all_methods.api = '_UNSUPPORTED_list_all_methods'
2155 class XendAPIAsyncProxy:
2156 """ A redirector for Async.Class.function calls to XendAPI
2157 but wraps the call for use with the XendTaskManager.
2159 @ivar xenapi: Xen API instance
2160 @ivar method_map: Mapping from XMLRPC method name to callable objects.
2161 """
2163 method_prefix = 'Async.'
2165 def __init__(self, xenapi):
2166 """Initialises the Async Proxy by making a map of all
2167 implemented Xen API methods for use with XendTaskManager.
2169 @param xenapi: XendAPI instance
2170 """
2171 self.xenapi = xenapi
2172 self.method_map = {}
2173 for method_name in dir(self.xenapi):
2174 method = getattr(self.xenapi, method_name)
2175 if method_name[0] != '_' and hasattr(method, 'async') \
2176 and method.async == True:
2177 self.method_map[method.api] = method
2179 def _dispatch(self, method, args):
2180 """Overridden method so that SimpleXMLRPCServer will
2181 resolve methods through this method rather than through
2182 inspection.
2184 @param method: marshalled method name from XMLRPC.
2185 @param args: marshalled arguments from XMLRPC.
2186 """
2188 # Only deal with method names that start with "Async."
2189 if not method.startswith(self.method_prefix):
2190 return xen_api_error(['MESSAGE_METHOD_UNKNOWN', method])
2192 # Lookup synchronous version of the method
2193 synchronous_method_name = method[len(self.method_prefix):]
2194 if synchronous_method_name not in self.method_map:
2195 return xen_api_error(['MESSAGE_METHOD_UNKNOWN', method])
2197 method = self.method_map[synchronous_method_name]
2199 # Check that we've got enough arguments before issuing a task ID.
2200 needed = argcounts[method.api]
2201 if len(args) != needed:
2202 return xen_api_error(['MESSAGE_PARAMETER_COUNT_MISMATCH',
2203 self.method_prefix + method.api, needed,
2204 len(args)])
2206 # Validate the session before proceeding
2207 session = args[0]
2208 if not auth_manager().is_session_valid(session):
2209 return xen_api_error(['SESSION_INVALID', session])
2211 # create and execute the task, and return task_uuid
2212 return_type = getattr(method, 'return_type', None)
2213 task_uuid = XendTaskManager.create_task(method, args,
2214 synchronous_method_name,
2215 return_type,
2216 synchronous_method_name,
2217 session)
2218 return xen_api_success(task_uuid)
2221 # Auto generate some stubs based on XendAPI introspection
2223 if __name__ == "__main__":
2224 def output(line):
2225 print ' ' + line
2227 classes = ['VDI', 'SR']
2228 for cls in classes:
2229 ro_attrs = getattr(XendAPI, '%s_attr_ro' % cls, [])
2230 rw_attrs = getattr(XendAPI, '%s_attr_rw' % cls, [])
2231 methods = getattr(XendAPI, '%s_methods' % cls, [])
2232 funcs = getattr(XendAPI, '%s_funcs' % cls, [])
2234 ref = '%s_ref' % cls
2236 for attr_name in ro_attrs + rw_attrs + XendAPI.Base_attr_ro:
2237 getter_name = '%s_get_%s' % (cls, attr_name)
2238 output('def %s(self, session, %s):' % (getter_name, ref))
2239 output(' return xen_api_todo()')
2241 for attr_name in rw_attrs + XendAPI.Base_attr_rw:
2242 setter_name = '%s_set_%s' % (cls, attr_name)
2243 output('def %s(self, session, %s, value):' % (setter_name, ref))
2244 output(' return xen_api_todo()')
2246 for method_name in methods + XendAPI.Base_methods:
2247 method_full_name = '%s_%s' % (cls,method_name)
2248 output('def %s(self, session, %s):' % (method_full_name, ref))
2249 output(' return xen_api_todo()')
2251 for func_name in funcs + XendAPI.Base_funcs:
2252 func_full_name = '%s_%s' % (cls, func_name)
2253 output('def %s(self, session):' % func_full_name)
2254 output(' return xen_api_todo()')