ia64/xen-unstable

view tools/python/xen/xend/XendAPI.py @ 14049:ee3ea729f5de

Added host.supported_bootloaders field.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author Ewan Mellor <ewan@xensource.com>
date Tue Feb 20 22:54:30 2007 +0000 (2007-02-20)
parents e0e300fda3f0
children f3aa6e34aeb1
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.XendAuthSessions import instance as auth_manager
29 from xen.xend.XendError import *
30 from xen.xend.XendClient import ERROR_INVALID_DOMAIN
31 from xen.xend.XendLogging import log
32 from xen.xend.XendTask import XendTask
34 from xen.xend.XendAPIConstants import *
35 from xen.util.xmlrpclib2 import stringify
37 AUTH_NONE = 'none'
38 AUTH_PAM = 'pam'
40 argcounts = {}
42 # ------------------------------------------
43 # Utility Methods for Xen API Implementation
44 # ------------------------------------------
46 def xen_api_success(value):
47 """Wraps a return value in XenAPI format."""
48 if value is None:
49 s = ''
50 else:
51 s = stringify(value)
52 return {"Status": "Success", "Value": s}
54 def xen_api_success_void():
55 """Return success, but caller expects no return value."""
56 return xen_api_success("")
58 def xen_api_error(error):
59 """Wraps an error value in XenAPI format."""
60 if type(error) == tuple:
61 error = list(error)
62 if type(error) != list:
63 error = [error]
64 if len(error) == 0:
65 error = ['INTERNAL_ERROR', 'Empty list given to xen_api_error']
67 return { "Status": "Failure",
68 "ErrorDescription": [str(x) for x in error] }
71 def xen_api_todo():
72 """Temporary method to make sure we track down all the TODOs"""
73 return {"Status": "Error", "ErrorDescription": XEND_ERROR_TODO}
75 # ---------------------------------------------------
76 # Python Method Decorators for input value validation
77 # ---------------------------------------------------
79 def trace(func, api_name = ''):
80 """Decorator to trace XMLRPC Xen API methods.
82 @param func: function with any parameters
83 @param api_name: name of the api call for debugging.
84 """
85 if hasattr(func, 'api'):
86 api_name = func.api
87 def trace_func(self, *args, **kwargs):
88 log.debug('%s: %s' % (api_name, args))
89 return func(self, *args, **kwargs)
90 trace_func.api = api_name
91 return trace_func
94 def catch_typeerror(func):
95 """Decorator to catch any TypeErrors and translate them into Xen-API
96 errors.
98 @param func: function with params: (self, ...)
99 @rtype: callable object
100 """
101 def f(self, *args, **kwargs):
102 try:
103 return func(self, *args, **kwargs)
104 except TypeError, exn:
105 #log.exception('catch_typeerror')
106 if hasattr(func, 'api') and func.api in argcounts:
107 # Assume that if the exception was thrown inside this
108 # file, then it is due to an invalid call from the client,
109 # but if it was thrown elsewhere, then it's an internal
110 # error (which will be handled further up).
111 tb = sys.exc_info()[2]
112 try:
113 sourcefile = traceback.extract_tb(tb)[-1][0]
114 if sourcefile == inspect.getsourcefile(XendAPI):
115 return xen_api_error(
116 ['MESSAGE_PARAMETER_COUNT_MISMATCH',
117 func.api, argcounts[func.api],
118 len(args) + len(kwargs)])
119 finally:
120 del tb
121 raise
123 return f
126 def session_required(func):
127 """Decorator to verify if session is valid before calling method.
129 @param func: function with params: (self, session, ...)
130 @rtype: callable object
131 """
132 def check_session(self, session, *args, **kwargs):
133 if auth_manager().is_session_valid(session):
134 return func(self, session, *args, **kwargs)
135 else:
136 return xen_api_error(['SESSION_INVALID', session])
138 return check_session
141 def _is_valid_ref(ref, validator):
142 return type(ref) == str and validator(ref)
144 def _check_ref(validator, clas, func, api, session, ref, *args, **kwargs):
145 if _is_valid_ref(ref, validator):
146 return func(api, session, ref, *args, **kwargs)
147 else:
148 return xen_api_error(['HANDLE_INVALID', clas, ref])
151 def valid_host(func):
152 """Decorator to verify if host_ref is valid before calling method.
154 @param func: function with params: (self, session, host_ref, ...)
155 @rtype: callable object
156 """
157 return lambda *args, **kwargs: \
158 _check_ref(XendNode.instance().is_valid_host,
159 'host', func, *args, **kwargs)
161 def valid_host_metrics(func):
162 """Decorator to verify if host_metrics_ref is valid before calling
163 method.
165 @param func: function with params: (self, session, host_metrics_ref)
166 @rtype: callable object
167 """
168 return lambda *args, **kwargs: \
169 _check_ref(lambda r: r == XendNode.instance().host_metrics_uuid,
170 'host_metrics', func, *args, **kwargs)
172 def valid_host_cpu(func):
173 """Decorator to verify if host_cpu_ref is valid before calling method.
175 @param func: function with params: (self, session, host_cpu_ref, ...)
176 @rtype: callable object
177 """
178 return lambda *args, **kwargs: \
179 _check_ref(XendNode.instance().is_valid_cpu,
180 'host_cpu', func, *args, **kwargs)
182 def valid_vm(func):
183 """Decorator to verify if vm_ref is valid before calling method.
185 @param func: function with params: (self, session, vm_ref, ...)
186 @rtype: callable object
187 """
188 return lambda *args, **kwargs: \
189 _check_ref(XendDomain.instance().is_valid_vm,
190 'VM', func, *args, **kwargs)
192 def valid_network(func):
193 """Decorator to verify if network_ref is valid before calling method.
195 @param func: function with params: (self, session, network_ref, ...)
196 @rtype: callable object
197 """
198 return lambda *args, **kwargs: \
199 _check_ref(XendNode.instance().is_valid_network,
200 'network', func, *args, **kwargs)
202 def valid_vbd(func):
203 """Decorator to verify if vbd_ref is valid before calling method.
205 @param func: function with params: (self, session, vbd_ref, ...)
206 @rtype: callable object
207 """
208 return lambda *args, **kwargs: \
209 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vbd', r),
210 'VBD', func, *args, **kwargs)
212 def valid_vbd_metrics(func):
213 """Decorator to verify if ref is valid before calling method.
215 @param func: function with params: (self, session, ref, ...)
216 @rtype: callable object
217 """
218 return lambda *args, **kwargs: \
219 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vbd', r),
220 'VBD_metrics', func, *args, **kwargs)
222 def valid_vif(func):
223 """Decorator to verify if vif_ref is valid before calling method.
225 @param func: function with params: (self, session, vif_ref, ...)
226 @rtype: callable object
227 """
228 return lambda *args, **kwargs: \
229 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vif', r),
230 'VIF', func, *args, **kwargs)
232 def valid_vif_metrics(func):
233 """Decorator to verify if ref is valid before calling method.
235 @param func: function with params: (self, session, ref, ...)
236 @rtype: callable object
237 """
238 return lambda *args, **kwargs: \
239 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vif', r),
240 'VIF_metrics', func, *args, **kwargs)
242 def valid_vdi(func):
243 """Decorator to verify if vdi_ref is valid before calling method.
245 @param func: function with params: (self, session, vdi_ref, ...)
246 @rtype: callable object
247 """
248 return lambda *args, **kwargs: \
249 _check_ref(XendNode.instance().is_valid_vdi,
250 'VDI', func, *args, **kwargs)
252 def valid_vtpm(func):
253 """Decorator to verify if vtpm_ref is valid before calling method.
255 @param func: function with params: (self, session, vtpm_ref, ...)
256 @rtype: callable object
257 """
258 return lambda *args, **kwargs: \
259 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vtpm', r),
260 'VTPM', func, *args, **kwargs)
263 def valid_console(func):
264 """Decorator to verify if console_ref is valid before calling method.
266 @param func: function with params: (self, session, console_ref, ...)
267 @rtype: callable object
268 """
269 return lambda *args, **kwargs: \
270 _check_ref(lambda r: XendDomain.instance().is_valid_dev('console',
271 r),
272 'console', func, *args, **kwargs)
274 def valid_sr(func):
275 """Decorator to verify if sr_ref is valid before calling method.
277 @param func: function with params: (self, session, sr_ref, ...)
278 @rtype: callable object
279 """
280 return lambda *args, **kwargs: \
281 _check_ref(lambda r: XendNode.instance().is_valid_sr,
282 'SR', func, *args, **kwargs)
284 def valid_pif(func):
285 """Decorator to verify if pif_ref is valid before calling
286 method.
288 @param func: function with params: (self, session, pif_ref)
289 @rtype: callable object
290 """
291 return lambda *args, **kwargs: \
292 _check_ref(lambda r: r in XendNode.instance().pifs,
293 'PIF', func, *args, **kwargs)
295 def valid_pif_metrics(func):
296 """Decorator to verify if pif_metrics_ref is valid before calling
297 method.
299 @param func: function with params: (self, session, pif_metrics_ref)
300 @rtype: callable object
301 """
302 return lambda *args, **kwargs: \
303 _check_ref(lambda r: r in XendNode.instance().pif_metrics,
304 'PIF_metrics', func, *args, **kwargs)
306 def valid_task(func):
307 """Decorator to verify if task_ref is valid before calling
308 method.
310 @param func: function with params: (self, session, task_ref)
311 @rtype: callable object
312 """
313 return lambda *args, **kwargs: \
314 _check_ref(XendTaskManager.get_task,
315 'task', func, *args, **kwargs)
317 def valid_debug(func):
318 """Decorator to verify if task_ref is valid before calling
319 method.
321 @param func: function with params: (self, session, task_ref)
322 @rtype: callable object
323 """
324 return lambda *args, **kwargs: \
325 _check_ref(lambda r: r in XendAPI._debug,
326 'debug', func, *args, **kwargs)
328 # -----------------------------
329 # Bridge to Legacy XM API calls
330 # -----------------------------
332 def do_vm_func(fn_name, vm_ref, *args, **kwargs):
333 """Helper wrapper func to abstract away from repetitive code.
335 @param fn_name: function name for XendDomain instance
336 @type fn_name: string
337 @param vm_ref: vm_ref
338 @type vm_ref: string
339 @param *args: more arguments
340 @type *args: tuple
341 """
342 try:
343 xendom = XendDomain.instance()
344 fn = getattr(xendom, fn_name)
345 xendom.do_legacy_api_with_uuid(fn, vm_ref, *args, **kwargs)
346 return xen_api_success_void()
347 except VMBadState, exn:
348 return xen_api_error(['VM_BAD_POWER_STATE', vm_ref, exn.expected,
349 exn.actual])
352 class XendAPI(object):
353 """Implementation of the Xen-API in Xend. Expects to be
354 used via XMLRPCServer.
356 All methods that need a valid session are marked with
357 a L{session_required} decorator that will
358 transparently perform the required session authentication.
360 We need to support Python <2.4, so we use the old decorator syntax.
362 All XMLRPC accessible methods require an 'api' attribute and
363 is set to the XMLRPC function name which the method implements.
364 """
366 __decorated__ = False
367 __init_lock__ = threading.Lock()
368 _debug = {}
370 def __new__(cls, *args, **kwds):
371 """ Override __new__ to decorate the class only once.
373 Lock to make sure the classes are not decorated twice.
374 """
375 cls.__init_lock__.acquire()
376 try:
377 if not cls.__decorated__:
378 cls._decorate()
379 cls.__decorated__ = True
381 return object.__new__(cls, *args, **kwds)
382 finally:
383 cls.__init_lock__.release()
385 def _decorate(cls):
386 """ Decorate all the object methods to have validators
387 and appropriate function attributes.
389 This should only be executed once for the duration of the
390 server.
391 """
392 global_validators = [session_required, catch_typeerror]
393 classes = {
394 'session' : None,
395 'host' : valid_host,
396 'host_cpu' : valid_host_cpu,
397 'host_metrics' : valid_host_metrics,
398 'network' : valid_network,
399 'VM' : valid_vm,
400 'VBD' : valid_vbd,
401 'VBD_metrics' : valid_vbd_metrics,
402 'VIF' : valid_vif,
403 'VIF_metrics' : valid_vif_metrics,
404 'VDI' : valid_vdi,
405 'VTPM' : valid_vtpm,
406 'console' : valid_console,
407 'SR' : valid_sr,
408 'PIF' : valid_pif,
409 'PIF_metrics' : valid_pif_metrics,
410 'task' : valid_task,
411 'debug' : valid_debug,
412 }
414 # Cheat methods
415 # -------------
416 # Methods that have a trivial implementation for all classes.
417 # 1. get_by_uuid == getting by ref, so just return uuid for
418 # all get_by_uuid() methods.
420 for api_cls in classes.keys():
421 if api_cls == 'session':
422 continue
424 get_by_uuid = '%s_get_by_uuid' % api_cls
425 get_uuid = '%s_get_uuid' % api_cls
426 def _get_by_uuid(_1, _2, ref):
427 return xen_api_success(ref)
429 def _get_uuid(_1, _2, ref):
430 return xen_api_success(ref)
432 setattr(cls, get_by_uuid, _get_by_uuid)
433 setattr(cls, get_uuid, _get_uuid)
435 # Wrapping validators around XMLRPC calls
436 # ---------------------------------------
438 for api_cls, validator in classes.items():
439 def doit(n, takes_instance, async_support = False,
440 return_type = None):
441 n_ = n.replace('.', '_')
442 try:
443 f = getattr(cls, n_)
444 argcounts[n] = f.func_code.co_argcount - 1
446 validators = takes_instance and validator and \
447 [validator] or []
449 validators += global_validators
450 for v in validators:
451 f = v(f)
452 f.api = n
453 f.async = async_support
454 if return_type:
455 f.return_type = return_type
457 setattr(cls, n_, f)
458 except AttributeError:
459 log.warn("API call: %s not found" % n)
462 ro_attrs = getattr(cls, '%s_attr_ro' % api_cls, [])
463 rw_attrs = getattr(cls, '%s_attr_rw' % api_cls, [])
464 methods = getattr(cls, '%s_methods' % api_cls, [])
465 funcs = getattr(cls, '%s_funcs' % api_cls, [])
467 # wrap validators around readable class attributes
468 for attr_name in ro_attrs + rw_attrs + cls.Base_attr_ro:
469 doit('%s.get_%s' % (api_cls, attr_name), True,
470 async_support = False)
472 # wrap validators around writable class attrributes
473 for attr_name in rw_attrs + cls.Base_attr_rw:
474 doit('%s.set_%s' % (api_cls, attr_name), True,
475 async_support = False)
477 # wrap validators around methods
478 for method_name, return_type in methods + cls.Base_methods:
479 doit('%s.%s' % (api_cls, method_name), True,
480 async_support = True)
482 # wrap validators around class functions
483 for func_name, return_type in funcs + cls.Base_funcs:
484 doit('%s.%s' % (api_cls, func_name), False, async_support = True,
485 return_type = return_type)
487 _decorate = classmethod(_decorate)
489 def __init__(self, auth):
490 self.auth = auth
492 Base_attr_ro = ['uuid']
493 Base_attr_rw = []
494 Base_methods = [('destroy', None), ('get_record', 'Struct')]
495 Base_funcs = [('get_all', 'Set'), ('get_by_uuid', None)]
497 # Xen API: Class Session
498 # ----------------------------------------------------------------
499 # NOTE: Left unwrapped by __init__
501 session_attr_ro = ['this_host', 'this_user']
502 session_methods = [('logout', None)]
504 def session_login_with_password(self, *args):
505 if len(args) != 2:
506 return xen_api_error(
507 ['MESSAGE_PARAMETER_COUNT_MISMATCH',
508 'session.login_with_password', 2, len(args)])
509 username = args[0]
510 password = args[1]
511 try:
512 session = (self.auth == AUTH_NONE and
513 auth_manager().login_unconditionally(username) or
514 auth_manager().login_with_password(username, password))
515 return xen_api_success(session)
516 except XendError, e:
517 return xen_api_error(['SESSION_AUTHENTICATION_FAILED'])
518 session_login_with_password.api = 'session.login_with_password'
520 # object methods
521 def session_logout(self, session):
522 auth_manager().logout(session)
523 return xen_api_success_void()
524 def session_get_record(self, session):
525 record = {'uuid' : session,
526 'this_host': XendNode.instance().uuid,
527 'this_user': auth_manager().get_user(session)}
528 return xen_api_success(record)
530 def session_get_uuid(self, session):
531 return xen_api_success(session)
533 def session_get_by_uuid(self, session):
534 return xen_api_success(session)
536 # attributes (ro)
537 def session_get_this_host(self, session):
538 return xen_api_success(XendNode.instance().uuid)
539 def session_get_this_user(self, session):
540 user = auth_manager().get_user(session)
541 if user:
542 return xen_api_success(user)
543 return xen_api_error(['SESSION_INVALID', session])
546 # Xen API: Class User
547 # ----------------------------------------------------------------
548 # TODO: NOT IMPLEMENTED YET
550 # Xen API: Class Tasks
551 # ----------------------------------------------------------------
553 task_attr_ro = ['name_label',
554 'name_description',
555 'status',
556 'progress',
557 'type',
558 'result',
559 'error_code',
560 'error_info',
561 'allowed_operations',
562 'session'
563 ]
565 task_attr_rw = []
567 task_funcs = [('get_by_name_label', 'Set(task)'),
568 ('cancel', None)]
570 def task_get_name_label(self, session, task_ref):
571 task = XendTaskManager.get_task(task_ref)
572 return xen_api_success(task.name_label)
574 def task_get_name_description(self, session, task_ref):
575 task = XendTaskManager.get_task(task_ref)
576 return xen_api_success(task.name_description)
578 def task_get_status(self, session, task_ref):
579 task = XendTaskManager.get_task(task_ref)
580 return xen_api_success(task.get_status())
582 def task_get_progress(self, session, task_ref):
583 task = XendTaskManager.get_task(task_ref)
584 return xen_api_success(task.progress)
586 def task_get_type(self, session, task_ref):
587 task = XendTaskManager.get_task(task_ref)
588 return xen_api_success(task.type)
590 def task_get_result(self, session, task_ref):
591 task = XendTaskManager.get_task(task_ref)
592 return xen_api_success(task.result)
594 def task_get_error_code(self, session, task_ref):
595 task = XendTaskManager.get_task(task_ref)
596 return xen_api_success(task.error_code)
598 def task_get_error_info(self, session, task_ref):
599 task = XendTaskManager.get_task(task_ref)
600 return xen_api_success(task.error_info)
602 def task_get_allowed_operations(self, session, task_ref):
603 return xen_api_success({})
605 def task_get_session(self, session, task_ref):
606 task = XendTaskManager.get_task(task_ref)
607 return xen_api_success(task.session)
609 def task_get_all(self, session):
610 tasks = XendTaskManager.get_all_tasks()
611 return xen_api_success(tasks)
613 def task_get_record(self, session, task_ref):
614 task = XendTaskManager.get_task(task_ref)
615 return xen_api_success(task.get_record())
617 def task_cancel(self, session, task_ref):
618 return xen_api_error('OPERATION_NOT_ALLOWED')
620 def task_get_by_name_label(self, session, name):
621 return xen_api_success(XendTaskManager.get_task_by_name(name))
623 # Xen API: Class host
624 # ----------------------------------------------------------------
626 host_attr_ro = ['software_version',
627 'resident_VMs',
628 'host_CPUs',
629 'metrics',
630 'supported_bootloaders']
632 host_attr_rw = ['name_label',
633 'name_description',
634 'other_config']
636 host_methods = [('disable', None),
637 ('enable', None),
638 ('reboot', None),
639 ('shutdown', None),
640 ('add_to_other_config', None),
641 ('remove_from_other_config', None),
642 ('dmesg', 'String')]
644 host_funcs = [('get_by_name_label', 'Set(host)')]
646 # attributes
647 def host_get_name_label(self, session, host_ref):
648 return xen_api_success(XendNode.instance().name)
649 def host_set_name_label(self, session, host_ref, new_name):
650 XendNode.instance().set_name(new_name)
651 return xen_api_success_void()
652 def host_get_name_description(self, session, host_ref):
653 return xen_api_success(XendNode.instance().description)
654 def host_set_name_description(self, session, host_ref, new_desc):
655 XendNode.instance().set_description(new_desc)
656 return xen_api_success_void()
657 def host_get_other_config(self, session, host_ref):
658 return xen_api_success(XendNode.instance().other_config)
659 def host_set_other_config(self, session, host_ref, other_config):
660 node = XendNode.instance()
661 node.other_config = dict(other_config)
662 node.save()
663 return xen_api_success_void()
664 def host_add_to_other_config(self, session, host_ref, key, value):
665 node = XendNode.instance()
666 node.other_config[key] = value
667 node.save()
668 return xen_api_success_void()
669 def host_remove_from_other_config(self, session, host_ref, key):
670 node = XendNode.instance()
671 del node.other_config[key]
672 node.save()
673 return xen_api_success_void()
674 def host_get_software_version(self, session, host_ref):
675 return xen_api_success(XendNode.instance().xen_version())
676 def host_get_resident_VMs(self, session, host_ref):
677 return xen_api_success(XendDomain.instance().get_domain_refs())
678 def host_get_host_CPUs(self, session, host_ref):
679 return xen_api_success(XendNode.instance().get_host_cpu_refs())
680 def host_get_metrics(self, _, ref):
681 return xen_api_success(XendNode.instance().host_metrics_uuid)
682 def host_get_supported_bootloaders(self, session, host_ref):
683 return xen_api_success(['pygrub'])
685 # object methods
686 def host_disable(self, session, host_ref):
687 XendDomain.instance().set_allow_new_domains(False)
688 return xen_api_success_void()
689 def host_enable(self, session, host_ref):
690 XendDomain.instance().set_allow_new_domains(True)
691 return xen_api_success_void()
692 def host_reboot(self, session, host_ref):
693 if not XendDomain.instance().allow_new_domains():
694 return xen_api_error(XEND_ERROR_HOST_RUNNING)
695 return xen_api_error(XEND_ERROR_UNSUPPORTED)
696 def host_shutdown(self, session, host_ref):
697 if not XendDomain.instance().allow_new_domains():
698 return xen_api_error(XEND_ERROR_HOST_RUNNING)
699 return xen_api_error(XEND_ERROR_UNSUPPORTED)
701 def host_dmesg(self, session, host_ref):
702 return xen_api_success(XendDmesg.instance().info())
704 def host_get_record(self, session, host_ref):
705 node = XendNode.instance()
706 dom = XendDomain.instance()
707 record = {'uuid': node.uuid,
708 'name_label': node.name,
709 'name_description': '',
710 'software_version': node.xen_version(),
711 'resident_VMs': dom.get_domain_refs(),
712 'host_CPUs': node.get_host_cpu_refs(),
713 'metrics': node.host_metrics_uuid,
714 'supported_bootloaders': 'pygrub'}
715 return xen_api_success(record)
717 # class methods
718 def host_get_all(self, session):
719 return xen_api_success((XendNode.instance().uuid,))
720 def host_get_by_name_label(self, session, name):
721 if XendNode.instance().name == name:
722 return xen_api_success((XendNode.instance().uuid,))
723 return xen_api_success([])
726 # Xen API: Class host_CPU
727 # ----------------------------------------------------------------
729 host_cpu_attr_ro = ['host',
730 'number',
731 'utilisation']
733 # attributes
734 def host_cpu_get_host(self, session, host_cpu_ref):
735 return xen_api_success(XendNode.instance().uuid)
736 def host_cpu_get_utilisation(self, session, host_cpu_ref):
737 util = XendNode.instance().get_host_cpu_load(host_cpu_ref)
738 return xen_api_success(util)
739 def host_cpu_get_number(self, session, host_cpu_ref):
740 num = XendNode.instance().get_host_cpu_number(host_cpu_ref)
741 return xen_api_success(num)
743 # object methods
744 def host_cpu_destroy(self, session, host_cpu_ref):
745 return xen_api_error(XEND_ERROR_UNSUPPORTED)
746 def host_cpu_get_record(self, session, host_cpu_ref):
747 node = XendNode.instance()
748 record = {'uuid': host_cpu_ref,
749 'host': node.uuid,
750 'number': node.get_host_cpu_number(host_cpu_ref),
751 'utilisation': node.get_host_cpu_load(host_cpu_ref)}
752 return xen_api_success(record)
754 # class methods
755 def host_cpu_get_all(self, session):
756 return xen_api_success(XendNode.instance().get_host_cpu_refs())
759 # Xen API: Class host_metrics
760 # ----------------------------------------------------------------
762 host_metrics_attr_ro = ['memory_total',
763 'memory_free',
764 'host']
765 host_metrics_attr_rw = []
766 host_metrics_methods = []
768 def _host_metrics_get(self, ref, f):
769 return xen_api_success(getattr(node, f)())
771 def host_metrics_get_record(self, _, ref):
772 return xen_api_success({
773 'uuid' : ref,
774 'host' : XendNode.instance().uuid,
775 'memory_total' : self._host_metrics_get_memory_total(),
776 'memory_free' : self._host_metrics_get_memory_free(),
777 })
779 def host_metrics_get_host(self, _, ref):
780 return xen_api_success(XendNode.instance().uuid)
782 def host_metrics_get_memory_total(self, _, ref):
783 return xen_api_success(self._host_metrics_get_memory_total())
785 def host_metrics_get_memory_free(self, _, ref):
786 return xen_api_success(self._host_metrics_get_memory_free())
788 def _host_metrics_get_memory_total(self):
789 node = XendNode.instance()
790 return node.xc.physinfo()['total_memory'] * 1024
792 def _host_metrics_get_memory_free(self):
793 node = XendNode.instance()
794 return node.xc.physinfo()['free_memory'] * 1024
797 # Xen API: Class network
798 # ----------------------------------------------------------------
800 network_attr_ro = ['VIFs', 'PIFs']
801 network_attr_rw = ['name_label',
802 'name_description',
803 'default_gateway',
804 'default_netmask']
806 network_funcs = [('create', 'network')]
808 def network_create(self, _, name_label, name_description,
809 default_gateway, default_netmask):
810 return xen_api_success(
811 XendNode.instance().network_create(name_label, name_description,
812 default_gateway,
813 default_netmask))
815 def network_destroy(self, _, ref):
816 return xen_api_success(XendNode.instance().network_destroy(ref))
818 def _get_network(self, ref):
819 return XendNode.instance().get_network(ref)
821 def network_get_all(self, _):
822 return xen_api_success(XendNode.instance().get_network_refs())
824 def network_get_record(self, _, ref):
825 return xen_api_success(
826 XendNode.instance().get_network(ref).get_record())
828 def network_get_name_label(self, _, ref):
829 return xen_api_success(self._get_network(ref).name_label)
831 def network_get_name_description(self, _, ref):
832 return xen_api_success(self._get_network(ref).name_description)
834 def network_get_default_gateway(self, _, ref):
835 return xen_api_success(self._get_network(ref).default_gateway)
837 def network_get_default_netmask(self, _, ref):
838 return xen_api_success(self._get_network(ref).default_netmask)
840 def network_get_VIFs(self, _, ref):
841 return xen_api_success(self._get_network(ref).get_VIF_UUIDs())
843 def network_get_PIFs(self, session, ref):
844 return xen_api_success(self._get_network(ref).get_PIF_UUIDs())
846 def network_set_name_label(self, _, ref, val):
847 return xen_api_success(self._get_network(ref).set_name_label(val))
849 def network_set_name_description(self, _, ref, val):
850 return xen_api_success(self._get_network(ref).set_name_description(val))
852 def network_set_default_gateway(self, _, ref, val):
853 return xen_api_success(self._get_network(ref).set_default_gateway(val))
855 def network_set_default_netmask(self, _, ref, val):
856 return xen_api_success(self._get_network(ref).set_default_netmask(val))
859 # Xen API: Class PIF
860 # ----------------------------------------------------------------
862 PIF_attr_ro = ['metrics']
863 PIF_attr_rw = ['device',
864 'network',
865 'host',
866 'MAC',
867 'MTU',
868 'VLAN']
870 PIF_attr_inst = PIF_attr_rw
872 PIF_methods = [('create_VLAN', 'int')]
874 def _get_PIF(self, ref):
875 return XendNode.instance().pifs[ref]
877 def PIF_destroy(self, _, ref):
878 try:
879 return xen_api_success(XendNode.instance().PIF_destroy(ref))
880 except PIFIsPhysical, exn:
881 return xen_api_error(['PIF_IS_PHYSICAL', ref])
883 # object methods
884 def PIF_get_record(self, _, ref):
885 return xen_api_success(self._get_PIF(ref).get_record())
887 def PIF_get_all(self, _):
888 return xen_api_success(XendNode.instance().pifs.keys())
890 def PIF_get_metrics(self, _, ref):
891 return xen_api_success(self._get_PIF(ref).metrics.uuid)
893 def PIF_get_device(self, _, ref):
894 return xen_api_success(self._get_PIF(ref).device)
896 def PIF_get_network(self, _, ref):
897 return xen_api_success(self._get_PIF(ref).network.uuid)
899 def PIF_get_host(self, _, ref):
900 return xen_api_success(self._get_PIF(ref).host.uuid)
902 def PIF_get_MAC(self, _, ref):
903 return xen_api_success(self._get_PIF(ref).mac)
905 def PIF_get_MTU(self, _, ref):
906 return xen_api_success(self._get_PIF(ref).mtu)
908 def PIF_get_VLAN(self, _, ref):
909 return xen_api_success(self._get_PIF(ref).vlan)
911 def PIF_set_device(self, _, ref, device):
912 return xen_api_success(self._get_PIF(ref).set_device(device))
914 def PIF_set_MAC(self, _, ref, mac):
915 return xen_api_success(self._get_PIF(ref).set_mac(mac))
917 def PIF_set_MTU(self, _, ref, mtu):
918 return xen_api_success(self._get_PIF(ref).set_mtu(mtu))
920 def PIF_create_VLAN(self, _, ref, network, vlan):
921 try:
922 vlan = int(vlan)
923 except:
924 return xen_api_error(['VLAN_TAG_INVALID', vlan])
926 try:
927 node = XendNode.instance()
929 if _is_valid_ref(network, node.is_valid_network):
930 return xen_api_success(
931 node.PIF_create_VLAN(ref, network, vlan))
932 else:
933 return xen_api_error(['HANDLE_INVALID', 'network', network])
934 except NetworkAlreadyConnected, exn:
935 return xen_api_error(['NETWORK_ALREADY_CONNECTED',
936 network, exn.pif_uuid])
937 except VLANTagInvalid:
938 return xen_api_error(['VLAN_TAG_INVALID', vlan])
941 # Xen API: Class PIF_metrics
942 # ----------------------------------------------------------------
944 PIF_metrics_attr_ro = ['PIF',
945 'io_read_kbs',
946 'io_write_kbs']
947 PIF_metrics_attr_rw = []
948 PIF_methods = []
950 def _PIF_metrics_get(self, ref):
951 return XendNode.instance().pif_metrics[ref]
953 def PIF_metrics_get_record(self, _, ref):
954 return xen_api_success(self._PIF_metrics_get(ref).get_record())
956 def PIF_metrics_get_PIF(self, _, ref):
957 return xen_api_success(self._PIF_metrics_get(ref).pif.uuid)
959 def PIF_metrics_get_io_read_kbs(self, _, ref):
960 return xen_api_success(self._PIF_metrics_get(ref).get_io_read_kbs())
962 def PIF_metrics_get_io_write_kbs(self, _, ref):
963 return xen_api_success(self._PIF_metrics_get(ref).get_io_write_kbs())
966 # Xen API: Class VM
967 # ----------------------------------------------------------------
969 VM_attr_ro = ['power_state',
970 'resident_on',
971 'memory_actual',
972 'memory_static_max',
973 'memory_static_min',
974 'VCPUs_number',
975 'VCPUs_utilisation',
976 'consoles',
977 'VIFs',
978 'VBDs',
979 'VTPMs',
980 'PCI_bus',
981 'tools_version',
982 'is_control_domain',
983 ]
985 VM_attr_rw = ['name_label',
986 'name_description',
987 'user_version',
988 'is_a_template',
989 'auto_power_on',
990 'memory_dynamic_max',
991 'memory_dynamic_min',
992 'VCPUs_policy',
993 'VCPUs_params',
994 'actions_after_shutdown',
995 'actions_after_reboot',
996 'actions_after_suspend',
997 'actions_after_crash',
998 'PV_bootloader',
999 'PV_kernel',
1000 'PV_ramdisk',
1001 'PV_args',
1002 'PV_bootloader_args',
1003 'HVM_boot_policy',
1004 'HVM_boot_params',
1005 'platform_std_VGA',
1006 'platform_serial',
1007 'platform_localtime',
1008 'platform_clock_offset',
1009 'platform_enable_audio',
1010 'platform_keymap',
1011 'other_config']
1013 VM_methods = [('clone', 'VM'),
1014 ('start', None),
1015 ('pause', None),
1016 ('unpause', None),
1017 ('clean_shutdown', None),
1018 ('clean_reboot', None),
1019 ('hard_shutdown', None),
1020 ('hard_reboot', None),
1021 ('suspend', None),
1022 ('resume', None),
1023 ('add_to_other_config', None),
1024 ('remove_from_other_config', None)]
1026 VM_funcs = [('create', 'VM'),
1027 ('get_by_name_label', 'Set(VM)')]
1029 # parameters required for _create()
1030 VM_attr_inst = [
1031 'name_label',
1032 'name_description',
1033 'user_version',
1034 'is_a_template',
1035 'memory_static_max',
1036 'memory_dynamic_max',
1037 'memory_dynamic_min',
1038 'memory_static_min',
1039 'VCPUs_policy',
1040 'VCPUs_params',
1041 'actions_after_shutdown',
1042 'actions_after_reboot',
1043 'actions_after_suspend',
1044 'actions_after_crash',
1045 'PV_bootloader',
1046 'PV_kernel',
1047 'PV_ramdisk',
1048 'PV_args',
1049 'PV_bootloader_args',
1050 'HVM_boot_policy',
1051 'HVM_boot_params',
1052 'platform_std_VGA',
1053 'platform_serial',
1054 'platform_localtime',
1055 'platform_clock_offset',
1056 'platform_enable_audio',
1057 'platform_keymap',
1058 'grub_cmdline',
1059 'PCI_bus',
1060 'other_config']
1062 def VM_get(self, name, session, vm_ref):
1063 return xen_api_success(
1064 XendDomain.instance().get_vm_by_uuid(vm_ref).info[name])
1066 def VM_set(self, name, session, vm_ref, value):
1067 xd = XendDomain.instance()
1068 dominfo = xd.get_vm_by_uuid(vm_ref)
1069 dominfo.info[name] = value
1070 xd.managed_config_save(dominfo)
1071 return xen_api_success_void()
1073 # attributes (ro)
1074 def VM_get_power_state(self, session, vm_ref):
1075 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1076 return xen_api_success(dom.get_power_state())
1078 def VM_get_resident_on(self, session, vm_ref):
1079 return xen_api_success(XendNode.instance().uuid)
1081 def VM_get_memory_actual(self, session, vm_ref):
1082 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1083 return xen_api_todo() # unsupported by xc
1085 def VM_get_memory_static_max(self, session, vm_ref):
1086 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1087 return xen_api_success(dom.get_memory_static_max())
1089 def VM_get_memory_static_min(self, session, vm_ref):
1090 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1091 return xen_api_success(dom.get_memory_static_min())
1093 def VM_get_VCPUs_number(self, session, vm_ref):
1094 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1095 return xen_api_success(dom.getVCpuCount())
1097 def VM_get_VCPUs_utilisation(self, session, vm_ref):
1098 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1099 return xen_api_success(dom.get_vcpus_util())
1101 def VM_get_VIFs(self, session, vm_ref):
1102 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1103 return xen_api_success(dom.get_vifs())
1105 def VM_get_VBDs(self, session, vm_ref):
1106 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1107 return xen_api_success(dom.get_vbds())
1109 def VM_get_VTPMs(self, session, vm_ref):
1110 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1111 return xen_api_success(dom.get_vtpms())
1113 def VM_get_consoles(self, session, vm_ref):
1114 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1115 return xen_api_success(dom.get_consoles())
1117 def VM_get_PCI_bus(self, session, vm_ref):
1118 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1119 return dom.get_pci_bus()
1121 def VM_get_tools_version(self, session, vm_ref):
1122 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1123 return dom.get_tools_version()
1125 # attributes (rw)
1126 def VM_get_name_label(self, session, vm_ref):
1127 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1128 return xen_api_success(dom.getName())
1130 def VM_get_name_description(self, session, vm_ref):
1131 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1132 return xen_api_todo()
1134 def VM_get_user_version(self, session, vm_ref):
1135 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1136 return xen_api_todo()
1138 def VM_get_is_a_template(self, session, vm_ref):
1139 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1140 return xen_api_todo()
1142 def VM_get_memory_dynamic_max(self, session, vm_ref):
1143 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1144 return xen_api_success(dom.get_memory_dynamic_max())
1146 def VM_get_memory_dynamic_min(self, session, vm_ref):
1147 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1148 return xen_api_success(dom.get_memory_dynamic_min())
1150 def VM_get_VCPUs_policy(self, session, vm_ref):
1151 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1152 return xen_api_success(dom.get_vcpus_policy())
1154 def VM_get_VCPUs_params(self, session, vm_ref):
1155 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1156 return xen_api_success(dom.get_vcpus_params())
1158 def VM_get_actions_after_shutdown(self, session, vm_ref):
1159 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1160 return xen_api_success(dom.get_on_shutdown())
1162 def VM_get_actions_after_reboot(self, session, vm_ref):
1163 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1164 return xen_api_success(dom.get_on_reboot())
1166 def VM_get_actions_after_suspend(self, session, vm_ref):
1167 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1168 return xen_api_success(dom.get_on_suspend())
1170 def VM_get_actions_after_crash(self, session, vm_ref):
1171 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1172 return xen_api_success(dom.get_on_crash())
1174 def VM_get_PV_bootloader(self, session, vm_ref):
1175 return self.VM_get('PV_bootloader', session, vm_ref)
1177 def VM_get_PV_kernel(self, session, vm_ref):
1178 return self.VM_get('PV_kernel', session, vm_ref)
1180 def VM_get_PV_ramdisk(self, session, vm_ref):
1181 return self.VM_get('PV_ramdisk', session, vm_ref)
1183 def VM_get_PV_args(self, session, vm_ref):
1184 return self.VM_get('PV_args', session, vm_ref)
1186 def VM_get_PV_bootloader_args(self, session, vm_ref):
1187 return self.VM_get('PV_bootloader_args', session, vm_ref)
1189 def VM_get_HVM_boot_policy(self, session, vm_ref):
1190 return self.VM_get('HVM_boot_policy', session, vm_ref)
1192 def VM_get_HVM_boot_params(self, session, vm_ref):
1193 return self.VM_get('HVM_boot_params', session, vm_ref)
1195 def VM_get_platform_std_VGA(self, session, vm_ref):
1196 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1197 return xen_api_success(dom.get_platform_std_vga())
1199 def VM_get_platform_serial(self, session, vm_ref):
1200 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1201 return xen_api_success(dom.get_platform_serial())
1203 def VM_get_platform_localtime(self, session, vm_ref):
1204 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1205 return xen_api_success(dom.get_platform_localtime())
1207 def VM_get_platform_clock_offset(self, session, vm_ref):
1208 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1209 return xen_api_success(dom.get_platform_clock_offset())
1211 def VM_get_platform_enable_audio(self, session, vm_ref):
1212 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1213 return xen_api_success(dom.get_platform_enable_audio())
1215 def VM_get_platform_keymap(self, session, vm_ref):
1216 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1217 return xen_api_success(dom.get_platform_keymap())
1219 def VM_get_other_config(self, session, vm_ref):
1220 return self.VM_get('other_config', session, vm_ref)
1222 def VM_get_is_control_domain(self, session, vm_ref):
1223 xd = XendDomain.instance()
1224 return xen_api_success(
1225 xd.get_vm_by_uuid(vm_ref) == xd.privilegedDomain())
1227 def VM_set_name_label(self, session, vm_ref, label):
1228 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1229 dom.setName(label)
1230 return xen_api_success_void()
1232 def VM_set_name_description(self, session, vm_ref, desc):
1233 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1234 return xen_api_todo()
1236 def VM_set_user_version(self, session, vm_ref, ver):
1237 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1238 return xen_api_todo()
1240 def VM_set_is_a_template(self, session, vm_ref, is_template):
1241 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1242 return xen_api_todo()
1244 def VM_set_memory_dynamic_max(self, session, vm_ref, mem):
1245 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1246 return xen_api_todo()
1248 def VM_set_memory_dynamic_min(self, session, vm_ref, mem):
1249 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1250 return xen_api_todo()
1252 def VM_set_VCPUs_policy(self, session, vm_ref, policy):
1253 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1254 return xen_api_todo()
1256 def VM_set_VCPUs_params(self, session, vm_ref, params):
1257 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1258 return xen_api_todo()
1260 def VM_set_actions_after_shutdown(self, session, vm_ref, action):
1261 if action not in XEN_API_ON_NORMAL_EXIST:
1262 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1263 return self.VM_set('actions_after_shutdown', session, vm_ref, action)
1265 def VM_set_actions_after_reboot(self, session, vm_ref, action):
1266 if action not in XEN_API_ON_NORMAL_EXIST:
1267 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1268 return self.VM_set('actions_after_reboot', session, vm_ref, action)
1270 def VM_set_actions_after_suspend(self, session, vm_ref, action):
1271 if action not in XEN_API_ON_NORMAL_EXIT:
1272 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1273 return self.VM_set('actions_after_suspend', session, vm_ref, action)
1275 def VM_set_actions_after_crash(self, session, vm_ref, action):
1276 if action not in XEN_API_ON_CRASH_BEHAVIOUR:
1277 return xen_api_error(['VM_ON_CRASH_BEHAVIOUR_INVALID', vm_ref])
1278 return self.VM_set('actions_after_crash', session, vm_ref, action)
1280 def VM_set_HVM_boot_policy(self, session, vm_ref, value):
1281 if value != "" and value != "BIOS order":
1282 return xen_api_error(
1283 ['VALUE_NOT_SUPPORTED', 'VM.HVM_boot_policy', value,
1284 'Xend supports only the "BIOS order" boot policy.'])
1285 else:
1286 return self.VM_set('HVM_boot_policy', session, vm_ref, value)
1288 def VM_set_HVM_boot_params(self, session, vm_ref, value):
1289 return self.VM_set('HVM_boot_params', session, vm_ref, value)
1291 def VM_add_to_HVM_boot_params(self, session, vm_ref, key, value):
1292 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1293 if 'HVM_boot_params' not in dom.info:
1294 dom.info['HVM_boot_params'] = {}
1295 dom.info['HVM_boot_params'][key] = value
1296 return xen_api_success_void()
1298 def VM_remove_from_HVM_boot_params(self, session, vm_ref, key):
1299 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1300 if 'HVM_boot_params' in dom.info \
1301 and key in dom.info['HVM_boot_params']:
1302 del dom.info['HVM_boot_params'][key]
1303 return xen_api_success_void()
1305 def VM_set_PV_bootloader(self, session, vm_ref, value):
1306 return self.VM_set('PV_bootloader', session, vm_ref, value)
1308 def VM_set_PV_kernel(self, session, vm_ref, value):
1309 return self.VM_set('PV_kernel', session, vm_ref, value)
1311 def VM_set_PV_ramdisk(self, session, vm_ref, value):
1312 return self.VM_set('PV_ramdisk', session, vm_ref, value)
1314 def VM_set_PV_args(self, session, vm_ref, value):
1315 return self.VM_set('PV_args', session, vm_ref, value)
1317 def VM_set_PV_bootloader_args(self, session, vm_ref, value):
1318 return self.VM_set('PV_bootloader_args', session, vm_ref, value)
1320 def VM_set_platform_std_VGA(self, session, vm_ref, value):
1321 return self.VM_set('platform_std_vga', session, vm_ref, value)
1323 def VM_set_platform_serial(self, session, vm_ref, value):
1324 return self.VM_set('platform_serial', session, vm_ref, value)
1326 def VM_set_platform_keymap(self, session, vm_ref, value):
1327 return self.VM_set('platform_keymap', session, vm_ref, value)
1329 def VM_set_platform_localtime(self, session, vm_ref, value):
1330 return self.VM_set('platform_localtime', session, vm_ref, value)
1332 def VM_set_platform_clock_offset(self, session, vm_ref, value):
1333 return self.VM_set('platform_clock_offset', session, vm_ref, value)
1335 def VM_set_platform_enable_audio(self, session, vm_ref, value):
1336 return self.VM_set('platform_enable_audio', session, vm_ref, value)
1338 def VM_set_other_config(self, session, vm_ref, value):
1339 return self.VM_set('otherconfig', session, vm_ref, value)
1341 def VM_add_to_other_config(self, session, vm_ref, key, value):
1342 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1343 if dom and 'otherconfig' in dom.info:
1344 dom.info['otherconfig'][key] = value
1345 return xen_api_success_void()
1347 def VM_remove_from_other_config(self, session, vm_ref, key):
1348 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1349 if dom and 'otherconfig' in dom.info \
1350 and key in dom.info['otherconfig']:
1351 del dom.info['otherconfig'][key]
1352 return xen_api_success_void()
1354 # class methods
1355 def VM_get_all(self, session):
1356 refs = [d.get_uuid() for d in XendDomain.instance().list('all')]
1357 return xen_api_success(refs)
1359 def VM_get_by_name_label(self, session, label):
1360 xendom = XendDomain.instance()
1361 dom = xendom.domain_lookup_nr(label)
1362 if dom:
1363 return xen_api_success([dom.get_uuid()])
1364 return xen_api_success([])
1366 def VM_create(self, session, vm_struct):
1367 xendom = XendDomain.instance()
1368 domuuid = XendTask.log_progress(0, 100,
1369 xendom.create_domain, vm_struct)
1370 return xen_api_success(domuuid)
1372 # object methods
1373 def VM_get_record(self, session, vm_ref):
1374 xendom = XendDomain.instance()
1375 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1376 if not xeninfo:
1377 return xen_api_error(['HANDLE_INVALID', 'VM', vm_ref])
1379 record = {
1380 'uuid': xeninfo.get_uuid(),
1381 'power_state': xeninfo.get_power_state(),
1382 'name_label': xeninfo.getName(),
1383 'name_description': xeninfo.getName(),
1384 'user_version': 1,
1385 'is_a_template': False,
1386 'auto_power_on': False,
1387 'resident_on': XendNode.instance().uuid,
1388 'memory_static_min': xeninfo.get_memory_static_min(),
1389 'memory_static_max': xeninfo.get_memory_static_max(),
1390 'memory_dynamic_min': xeninfo.get_memory_dynamic_min(),
1391 'memory_dynamic_max': xeninfo.get_memory_dynamic_max(),
1392 'memory_actual': xeninfo.get_memory_static_min(),
1393 'VCPUs_policy': xeninfo.get_vcpus_policy(),
1394 'VCPUs_params': xeninfo.get_vcpus_params(),
1395 'VCPUs_number': xeninfo.getVCpuCount(),
1396 'VCPUs_utilisation': xeninfo.get_vcpus_util(),
1397 'actions_after_shutdown': xeninfo.get_on_shutdown(),
1398 'actions_after_reboot': xeninfo.get_on_reboot(),
1399 'actions_after_suspend': xeninfo.get_on_suspend(),
1400 'actions_after_crash': xeninfo.get_on_crash(),
1401 'consoles': xeninfo.get_consoles(),
1402 'VIFs': xeninfo.get_vifs(),
1403 'VBDs': xeninfo.get_vbds(),
1404 'VTPMs': xeninfo.get_vtpms(),
1405 'PV_bootloader': xeninfo.info.get('PV_bootloader'),
1406 'PV_kernel': xeninfo.info.get('PV_kernel'),
1407 'PV_ramdisk': xeninfo.info.get('PV_ramdisk'),
1408 'PV_args': xeninfo.info.get('PV_args'),
1409 'PV_bootloader_args': xeninfo.info.get('PV_bootloader_args'),
1410 'HVM_boot_policy': xeninfo.info.get('HVM_boot_policy'),
1411 'HVM_boot_params': xeninfo.info.get('HVM_boot_params'),
1412 'platform_std_VGA': xeninfo.get_platform_std_vga(),
1413 'platform_serial': xeninfo.get_platform_serial(),
1414 'platform_localtime': xeninfo.get_platform_localtime(),
1415 'platform_clock_offset': xeninfo.get_platform_clock_offset(),
1416 'platform_enable_audio': xeninfo.get_platform_enable_audio(),
1417 'platform_keymap': xeninfo.get_platform_keymap(),
1418 'PCI_bus': xeninfo.get_pci_bus(),
1419 'tools_version': xeninfo.get_tools_version(),
1420 'other_config': xeninfo.info.get('other_config', {}),
1421 'is_control_domain': xeninfo == xendom.privilegedDomain(),
1423 return xen_api_success(record)
1425 def VM_clean_reboot(self, session, vm_ref):
1426 xendom = XendDomain.instance()
1427 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1428 XendTask.log_progress(0, 100, xeninfo.shutdown, "reboot")
1429 return xen_api_success_void()
1431 def VM_clean_shutdown(self, session, vm_ref):
1432 xendom = XendDomain.instance()
1433 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1434 XendTask.log_progress(0, 100, xeninfo.shutdown, "poweroff")
1435 return xen_api_success_void()
1437 def VM_clone(self, session, vm_ref):
1438 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1440 def VM_destroy(self, session, vm_ref):
1441 return XendTask.log_progress(0, 100, do_vm_func,
1442 "domain_delete", vm_ref)
1444 def VM_hard_reboot(self, session, vm_ref):
1445 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1447 def VM_hard_shutdown(self, session, vm_ref):
1448 return XendTask.log_progress(0, 100, do_vm_func,
1449 "domain_destroy", vm_ref)
1450 def VM_pause(self, session, vm_ref):
1451 return XendTask.log_progress(0, 100, do_vm_func,
1452 "domain_pause", vm_ref)
1454 def VM_resume(self, session, vm_ref, start_paused):
1455 return XendTask.log_progress(0, 100, do_vm_func,
1456 "domain_resume", vm_ref,
1457 start_paused = start_paused)
1459 def VM_start(self, session, vm_ref, start_paused):
1460 return XendTask.log_progress(0, 100, do_vm_func,
1461 "domain_start", vm_ref,
1462 start_paused = start_paused)
1464 def VM_suspend(self, session, vm_ref):
1465 return XendTask.log_progress(0, 100, do_vm_func,
1466 "domain_suspend", vm_ref)
1468 def VM_unpause(self, session, vm_ref):
1469 return XendTask.log_progress(0, 100, do_vm_func,
1470 "domain_unpause", vm_ref)
1472 # Xen API: Class VBD
1473 # ----------------------------------------------------------------
1475 VBD_attr_ro = ['metrics']
1476 VBD_attr_rw = ['VM',
1477 'VDI',
1478 'device',
1479 'bootable',
1480 'mode',
1481 'type']
1483 VBD_attr_inst = VBD_attr_rw
1485 VBD_methods = [('media_change', None)]
1486 VBD_funcs = [('create', 'VBD')]
1488 # object methods
1489 def VBD_get_record(self, session, vbd_ref):
1490 xendom = XendDomain.instance()
1491 vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1492 if not vm:
1493 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1494 cfg = vm.get_dev_xenapi_config('vbd', vbd_ref)
1495 if not cfg:
1496 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1498 valid_vbd_keys = self.VBD_attr_ro + self.VBD_attr_rw + \
1499 self.Base_attr_ro + self.Base_attr_rw
1501 return_cfg = {}
1502 for k in cfg.keys():
1503 if k in valid_vbd_keys:
1504 return_cfg[k] = cfg[k]
1506 return_cfg['metrics'] = vbd_ref
1508 return xen_api_success(return_cfg)
1510 def VBD_media_change(self, session, vbd_ref, vdi_ref):
1511 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1513 # class methods
1514 def VBD_create(self, session, vbd_struct):
1515 xendom = XendDomain.instance()
1516 if not xendom.is_valid_vm(vbd_struct['VM']):
1517 return xen_api_error(['HANDLE_INVALID', 'VM', vbd_struct['VM']])
1519 dom = xendom.get_vm_by_uuid(vbd_struct['VM'])
1520 vbd_ref = ''
1521 try:
1522 # new VBD via VDI/SR
1523 vdi_ref = vbd_struct.get('VDI')
1524 vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
1525 if not vdi:
1526 return xen_api_error(['HANDLE_INVALID', 'VDI', vdi_ref])
1527 vdi_image = vdi.get_location()
1528 vbd_ref = XendTask.log_progress(0, 100,
1529 dom.create_vbd,
1530 vbd_struct, vdi_image)
1531 except XendError:
1532 return xen_api_todo()
1534 xendom.managed_config_save(dom)
1535 return xen_api_success(vbd_ref)
1538 def VBD_destroy(self, session, vbd_ref):
1539 xendom = XendDomain.instance()
1540 vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1541 if not vm:
1542 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1544 XendTask.log_progress(0, 100, vm.destroy_vbd, vbd_ref)
1545 return xen_api_success_void()
1547 def _VBD_get(self, vbd_ref, prop):
1548 return xen_api_success(
1549 XendDomain.instance().get_dev_property_by_uuid(
1550 'vbd', vbd_ref, prop))
1552 # attributes (ro)
1553 def VBD_get_metrics(self, _, vbd_ref):
1554 return xen_api_success(vbd_ref)
1556 # attributes (rw)
1557 def VBD_get_VM(self, session, vbd_ref):
1558 return self._VBD_get(vbd_ref, 'VM')
1560 def VBD_get_VDI(self, session, vbd_ref):
1561 return self._VBD_get(vbd_ref, 'VDI')
1563 def VBD_get_device(self, session, vbd_ref):
1564 return self._VBD_get(vbd_ref, 'device')
1566 def VBD_get_bootable(self, session, vbd_ref):
1567 return self._VBD_get(vbd_ref, 'bootable')
1569 def VBD_get_mode(self, session, vbd_ref):
1570 return self._VBD_get(vbd_ref, 'mode')
1572 def VBD_get_type(self, session, vbd_ref):
1573 return self._VBD_get(vbd_ref, 'type')
1575 def VBD_set_bootable(self, session, vbd_ref, bootable):
1576 bootable = bool(bootable)
1577 xd = XendDomain.instance()
1578 vm = xd.get_vm_with_dev_uuid('vbd', vbd_ref)
1579 vm.set_dev_property('vbd', vbd_ref, 'bootable', bootable)
1580 xd.managed_config_save(vm)
1581 return xen_api_success_void()
1583 def VBD_get_all(self, session):
1584 xendom = XendDomain.instance()
1585 vbds = [d.get_vbds() for d in XendDomain.instance().list('all')]
1586 vbds = reduce(lambda x, y: x + y, vbds)
1587 return xen_api_success(vbds)
1590 # Xen API: Class VBD_metrics
1591 # ----------------------------------------------------------------
1593 VBD_metrics_attr_ro = ['io_read_kbs',
1594 'io_write_kbs']
1595 VBD_metrics_attr_rw = []
1596 VBD_methods = []
1598 def VBD_metrics_get_record(self, _, ref):
1599 vm = XendDomain.instance().get_vm_with_dev_uuid('vbd', ref)
1600 if not vm:
1601 return xen_api_error(['HANDLE_INVALID', 'VBD_metrics', ref])
1602 return xen_api_success(
1603 { 'io_read_kbs' : vm.get_dev_property('vbd', ref, 'io_read_kbs'),
1604 'io_write_kbs' : vm.get_dev_property('vbd', ref, 'io_write_kbs') })
1606 def VBD_metrics_get_io_read_kbs(self, _, ref):
1607 return self._VBD_get(ref, 'io_read_kbs')
1609 def VBD_metrics_get_io_write_kbs(self, session, ref):
1610 return self._VBD_get(ref, 'io_write_kbs')
1613 # Xen API: Class VIF
1614 # ----------------------------------------------------------------
1616 VIF_attr_ro = ['metrics']
1617 VIF_attr_rw = ['device',
1618 'network',
1619 'VM',
1620 'MAC',
1621 'MTU']
1623 VIF_attr_inst = VIF_attr_rw
1625 VIF_funcs = [('create', 'VIF')]
1628 # object methods
1629 def VIF_get_record(self, session, vif_ref):
1630 xendom = XendDomain.instance()
1631 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
1632 if not vm:
1633 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
1634 cfg = vm.get_dev_xenapi_config('vif', vif_ref)
1635 if not cfg:
1636 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
1638 valid_vif_keys = self.VIF_attr_ro + self.VIF_attr_rw + \
1639 self.Base_attr_ro + self.Base_attr_rw
1641 return_cfg = {}
1642 for k in cfg.keys():
1643 if k in valid_vif_keys:
1644 return_cfg[k] = cfg[k]
1646 return_cfg['metrics'] = vif_ref
1648 return xen_api_success(return_cfg)
1650 # class methods
1651 def VIF_create(self, session, vif_struct):
1652 xendom = XendDomain.instance()
1653 if xendom.is_valid_vm(vif_struct['VM']):
1654 dom = xendom.get_vm_by_uuid(vif_struct['VM'])
1655 try:
1656 vif_ref = dom.create_vif(vif_struct)
1657 xendom.managed_config_save(dom)
1658 return xen_api_success(vif_ref)
1659 except XendError:
1660 return xen_api_error(XEND_ERROR_TODO)
1661 else:
1662 return xen_api_error(['HANDLE_INVALID', 'VM', vif_struct['VM']])
1665 def VIF_destroy(self, session, vif_ref):
1666 xendom = XendDomain.instance()
1667 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
1668 if not vm:
1669 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
1671 vm.destroy_vif(vif_ref)
1672 return xen_api_success_void()
1674 def _VIF_get(self, ref, prop):
1675 return xen_api_success(
1676 XendDomain.instance().get_dev_property_by_uuid('vif', ref, prop))
1678 # getters/setters
1679 def VIF_get_metrics(self, _, vif_ref):
1680 return xen_api_success(vif_ref)
1682 def VIF_get_VM(self, session, vif_ref):
1683 xendom = XendDomain.instance()
1684 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
1685 return xen_api_success(vm.get_uuid())
1687 def VIF_get_MTU(self, session, vif_ref):
1688 return self._VIF_get(vif_ref, 'MTU')
1690 def VIF_get_MAC(self, session, vif_ref):
1691 return self._VIF_get(vif_ref, 'MAC')
1693 def VIF_get_device(self, session, vif_ref):
1694 return self._VIF_get(vif_ref, 'device')
1696 def VIF_get_all(self, session):
1697 xendom = XendDomain.instance()
1698 vifs = [d.get_vifs() for d in XendDomain.instance().list('all')]
1699 vifs = reduce(lambda x, y: x + y, vifs)
1700 return xen_api_success(vifs)
1703 # Xen API: Class VIF_metrics
1704 # ----------------------------------------------------------------
1706 VIF_metrics_attr_ro = ['io_read_kbs',
1707 'io_write_kbs']
1708 VIF_metrics_attr_rw = []
1709 VIF_methods = []
1711 def VIF_metrics_get_record(self, _, ref):
1712 vm = XendDomain.instance().get_vm_with_dev_uuid('vif', ref)
1713 if not vm:
1714 return xen_api_error(['HANDLE_INVALID', 'VIF_metrics', ref])
1715 return xen_api_success(
1716 { 'io_read_kbs' : vm.get_dev_property('vif', ref, 'io_read_kbs'),
1717 'io_write_kbs' : vm.get_dev_property('vif', ref, 'io_write_kbs') })
1719 def VIF_metrics_get_io_read_kbs(self, _, ref):
1720 return self._VIF_get(ref, 'io_read_kbs')
1722 def VIF_metrics_get_io_write_kbs(self, session, ref):
1723 return self._VIF_get(ref, 'io_write_kbs')
1726 # Xen API: Class VDI
1727 # ----------------------------------------------------------------
1728 VDI_attr_ro = ['VBDs',
1729 'physical_utilisation',
1730 'sector_size',
1731 'type']
1732 VDI_attr_rw = ['name_label',
1733 'name_description',
1734 'SR',
1735 'virtual_size',
1736 'sharable',
1737 'read_only']
1738 VDI_attr_inst = VDI_attr_ro + VDI_attr_rw
1740 VDI_methods = [('snapshot', 'VDI')]
1741 VDI_funcs = [('create', 'VDI'),
1742 ('get_by_name_label', 'Set(VDI)')]
1744 def _get_VDI(self, ref):
1745 return XendNode.instance().get_vdi_by_uuid(ref)
1747 def VDI_get_VBDs(self, session, vdi_ref):
1748 return xen_api_todo()
1750 def VDI_get_physical_utilisation(self, session, vdi_ref):
1751 return xen_api_success(self._get_VDI(vdi_ref).
1752 get_physical_utilisation())
1754 def VDI_get_sector_size(self, session, vdi_ref):
1755 return xen_api_success(self._get_VDI(vdi_ref).sector_size)
1757 def VDI_get_type(self, session, vdi_ref):
1758 return xen_api_success(self._get_VDI(vdi_ref).type)
1760 def VDI_get_name_label(self, session, vdi_ref):
1761 return xen_api_success(self._get_VDI(vdi_ref).name_label)
1763 def VDI_get_name_description(self, session, vdi_ref):
1764 return xen_api_success(self._get_VDI(vdi_ref).name_description)
1766 def VDI_get_SR(self, session, vdi_ref):
1767 return xen_api_success(self._get_VDI(vdi_ref).sr_uuid)
1769 def VDI_get_virtual_size(self, session, vdi_ref):
1770 return xen_api_success(self._get_VDI(vdi_ref).virtual_size)
1772 def VDI_get_sharable(self, session, vdi_ref):
1773 return xen_api_success(self._get_VDI(vdi_ref).sharable)
1775 def VDI_get_read_only(self, session, vdi_ref):
1776 return xen_api_success(self._get_VDI(vdi_ref).read_only)
1778 def VDI_set_name_label(self, session, vdi_ref, value):
1779 self._get_VDI(vdi_ref).name_label = value
1780 return xen_api_success_void()
1782 def VDI_set_name_description(self, session, vdi_ref, value):
1783 self._get_VDI(vdi_ref).name_description = value
1784 return xen_api_success_void()
1786 def VDI_set_SR(self, session, vdi_ref, value):
1787 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1789 def VDI_set_virtual_size(self, session, vdi_ref, value):
1790 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1792 def VDI_set_sharable(self, session, vdi_ref, value):
1793 self._get_VDI(vdi_ref).sharable = bool(value)
1794 return xen_api_success_void()
1796 def VDI_set_read_only(self, session, vdi_ref, value):
1797 self._get_VDI(vdi_ref).read_only = bool(value)
1798 return xen_api_success_void()
1800 # Object Methods
1801 def VDI_snapshot(self, session, vdi_ref):
1802 return xen_api_todo()
1804 def VDI_destroy(self, session, vdi_ref):
1805 sr = XendNode.instance().get_sr_containing_vdi(vdi_ref)
1806 sr.destroy_vdi(vdi_ref)
1807 return xen_api_success_void()
1809 def VDI_get_record(self, session, vdi_ref):
1810 image = XendNode.instance().get_vdi_by_uuid(vdi_ref)
1811 return xen_api_success({
1812 'uuid': vdi_ref,
1813 'name_label': image.name_label,
1814 'name_description': image.name_description,
1815 'SR': image.sr_uuid,
1816 'VBDs': [], # TODO
1817 'virtual_size': image.virtual_size,
1818 'physical_utilisation': image.physical_utilisation,
1819 'sector_size': image.sector_size,
1820 'type': image.type,
1821 'sharable': image.sharable,
1822 'read_only': image.read_only,
1823 })
1825 # Class Functions
1826 def VDI_create(self, session, vdi_struct):
1827 sr_ref = vdi_struct.get('SR')
1828 xennode = XendNode.instance()
1829 if not xennode.is_valid_sr(sr_ref):
1830 return xen_api_error(['HANDLE_INVALID', 'SR', sr_ref])
1832 vdi_uuid = xennode.srs[sr_ref].create_vdi(vdi_struct)
1833 return xen_api_success(vdi_uuid)
1835 def VDI_get_all(self, session):
1836 xennode = XendNode.instance()
1837 vdis = [sr.get_vdis() for sr in xennode.srs.values()]
1838 return xen_api_success(reduce(lambda x, y: x + y, vdis))
1840 def VDI_get_by_name_label(self, session, name):
1841 xennode = XendNode.instance()
1842 return xen_api_success(xennode.get_vdi_by_name_label(name))
1845 # Xen API: Class VTPM
1846 # ----------------------------------------------------------------
1848 VTPM_attr_rw = [ ]
1849 VTPM_attr_ro = ['VM',
1850 'backend']
1852 VTPM_attr_inst = VTPM_attr_rw
1854 VTPM_funcs = [('create', 'VTPM')]
1856 # object methods
1857 def VTPM_get_record(self, session, vtpm_ref):
1858 xendom = XendDomain.instance()
1859 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
1860 if not vm:
1861 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
1862 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
1863 if not cfg:
1864 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
1865 valid_vtpm_keys = self.VTPM_attr_ro + self.VTPM_attr_rw + \
1866 self.Base_attr_ro + self.Base_attr_rw
1867 return_cfg = {}
1868 for k in cfg.keys():
1869 if k in valid_vtpm_keys:
1870 return_cfg[k] = cfg[k]
1872 return xen_api_success(return_cfg)
1874 # Class Functions
1875 def VTPM_get_backend(self, session, vtpm_ref):
1876 xendom = XendDomain.instance()
1877 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
1878 if not vm:
1879 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
1880 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
1881 if not cfg:
1882 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
1883 if not cfg.has_key('backend'):
1884 return xen_api_error(['VTPM backend not set'])
1885 return xen_api_success(cfg['backend'])
1887 def VTPM_get_VM(self, session, vtpm_ref):
1888 xendom = XendDomain.instance()
1889 return xen_api_success(xendom.get_dev_property_by_uuid('vtpm',
1890 vtpm_ref, 'VM'))
1892 def VTPM_destroy(self, session, vtpm_ref):
1893 xendom = XendDomain.instance()
1894 dom = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
1895 if dom:
1896 if dom.state != XEN_API_VM_POWER_STATE_HALTED:
1897 vm_ref = dom.get_dev_property('vtpm', vtpm_ref, 'VM')
1898 return xen_api_error(['VM_BAD_POWER_STATE', vm_ref,
1899 XendDomain.POWER_STATE_NAMES[XEN_API_VM_POWER_STATE_HALTED],
1900 XendDomain.POWER_STATE_NAMES[dom.state]])
1901 from xen.xend.server import tpmif
1902 tpmif.destroy_vtpmstate(dom.getName())
1903 return xen_api_success(True)
1904 else:
1905 return xen_api_error(['HANDLE_INVALID', 'VM', vtpm_struct['VM']])
1907 # class methods
1908 def VTPM_create(self, session, vtpm_struct):
1909 xendom = XendDomain.instance()
1910 if xendom.is_valid_vm(vtpm_struct['VM']):
1911 dom = xendom.get_vm_by_uuid(vtpm_struct['VM'])
1912 try:
1913 vtpm_ref = dom.create_vtpm(vtpm_struct)
1914 xendom.managed_config_save(dom)
1915 return xen_api_success(vtpm_ref)
1916 except XendError:
1917 return xen_api_error(XEND_ERROR_TODO)
1918 else:
1919 return xen_api_error(['HANDLE_INVALID', 'VM', vtpm_struct['VM']])
1921 def VTPM_get_all(self, session):
1922 xendom = XendDomain.instance()
1923 vtpms = [d.get_vtpms() for d in XendDomain.instance().list('all')]
1924 vtpms = reduce(lambda x, y: x + y, vtpms)
1925 return xen_api_success(vtpms)
1927 # Xen API: Class console
1928 # ----------------------------------------------------------------
1931 console_attr_ro = ['location', 'protocol', 'VM']
1932 console_attr_rw = ['other_config']
1933 console_funcs = [('create', 'console')]
1935 def console_get_all(self, session):
1936 xendom = XendDomain.instance()
1937 cons = [d.get_consoles() for d in XendDomain.instance().list('all')]
1938 cons = reduce(lambda x, y: x + y, cons)
1939 return xen_api_success(cons)
1941 def console_get_location(self, session, console_ref):
1942 return xen_api_success(xendom.get_dev_property_by_uuid('console',
1943 console_ref,
1944 'location'))
1946 def console_get_protocol(self, session, console_ref):
1947 return xen_api_success(xendom.get_dev_property_by_uuid('console',
1948 console_ref,
1949 'protocol'))
1951 def console_get_VM(self, session, console_ref):
1952 xendom = XendDomain.instance()
1953 vm = xendom.get_vm_with_dev_uuid('console', console_ref)
1954 return xen_api_success(vm.get_uuid())
1956 # object methods
1957 def console_get_record(self, session, console_ref):
1958 xendom = XendDomain.instance()
1959 vm = xendom.get_vm_with_dev_uuid('console', console_ref)
1960 if not vm:
1961 return xen_api_error(['HANDLE_INVALID', 'console', console_ref])
1962 cfg = vm.get_dev_xenapi_config('console', console_ref)
1963 if not cfg:
1964 return xen_api_error(['HANDLE_INVALID', 'console', console_ref])
1966 valid_console_keys = self.console_attr_ro + self.console_attr_rw + \
1967 self.Base_attr_ro + self.Base_attr_rw
1969 return_cfg = {}
1970 for k in cfg.keys():
1971 if k in valid_console_keys:
1972 return_cfg[k] = cfg[k]
1974 return xen_api_success(return_cfg)
1976 def console_create(self, session, console_struct):
1977 xendom = XendDomain.instance()
1978 if not xendom.is_valid_vm(console_struct['VM']):
1979 return xen_api_error(['HANDLE_INVALID', 'VM',
1980 console_struct['VM']])
1982 dom = xendom.get_vm_by_uuid(console_struct['VM'])
1983 try:
1984 if 'protocol' not in console_struct:
1985 return xen_api_error(['CONSOLE_PROTOCOL_INVALID',
1986 'No protocol specified'])
1988 console_ref = dom.create_console(console_struct)
1989 xendom.managed_config_save(dom)
1990 return xen_api_success(console_ref)
1991 except XendError, e:
1992 return xen_api_error([XEND_ERROR_TODO, str(e)])
1994 # Xen API: Class SR
1995 # ----------------------------------------------------------------
1996 SR_attr_ro = ['VDIs',
1997 'virtual_allocation',
1998 'physical_utilisation',
1999 'physical_size',
2000 'type',
2001 'location']
2003 SR_attr_rw = ['name_label',
2004 'name_description']
2006 SR_attr_inst = ['physical_size',
2007 'type',
2008 'location',
2009 'name_label',
2010 'name_description']
2012 SR_methods = [('clone', 'SR')]
2013 SR_funcs = [('get_by_name_label', 'Set(SR)'),
2014 ('get_by_uuid', 'SR')]
2016 # Class Functions
2017 def SR_get_all(self, session):
2018 return xen_api_success(XendNode.instance().get_all_sr_uuid())
2020 def SR_get_by_name_label(self, session, label):
2021 return xen_api_success(XendNode.instance().get_sr_by_name(label))
2023 def SR_create(self, session):
2024 return xen_api_error(XEND_ERROR_UNSUPPORTED)
2026 # Class Methods
2027 def SR_clone(self, session, sr_ref):
2028 return xen_api_error(XEND_ERROR_UNSUPPORTED)
2030 def SR_destroy(self, session, sr_ref):
2031 return xen_api_error(XEND_ERROR_UNSUPPORTED)
2033 def SR_get_record(self, session, sr_ref):
2034 sr = XendNode.instance().get_sr(sr_ref)
2035 if sr:
2036 return xen_api_success(sr.get_record())
2037 return xen_api_error(['HANDLE_INVALID', 'SR', sr_ref])
2039 # Attribute acceess
2041 def _get_SR_func(self, sr_ref, func):
2042 return xen_api_success(getattr(XendNode.instance().get_sr(sr_ref),
2043 func)())
2045 def _get_SR_attr(self, sr_ref, attr):
2046 return xen_api_success(getattr(XendNode.instance().get_sr(sr_ref),
2047 attr))
2049 def SR_get_VDIs(self, _, ref):
2050 return self._get_SR_func(ref, 'list_images')
2052 def SR_get_virtual_allocation(self, _, ref):
2053 return self._get_SR_func(ref, 'virtual_allocation')
2055 def SR_get_physical_utilisation(self, _, ref):
2056 return self._get_SR_func(ref, 'physical_utilisation')
2058 def SR_get_physical_size(self, _, ref):
2059 return self._get_SR_func(ref, 'physical_size')
2061 def SR_get_type(self, _, ref):
2062 return self._get_SR_attr(ref, 'type')
2064 def SR_get_location(self, _, ref):
2065 return self._get_SR_attr(ref, 'location')
2067 def SR_get_name_label(self, _, ref):
2068 return self._get_SR_attr(ref, 'name_label')
2070 def SR_get_name_description(self, _, ref):
2071 return self._get_SR_attr(ref, 'name_description')
2073 def SR_set_name_label(self, session, sr_ref, value):
2074 sr = XendNode.instance.get_sr(sr_ref)
2075 if sr:
2076 sr.name_label = value
2077 XendNode.instance().save()
2078 return xen_api_success_void()
2080 def SR_set_name_description(self, session, sr_ref, value):
2081 sr = XendNode.instance.get_sr(sr_ref)
2082 if sr:
2083 sr.name_description = value
2084 XendNode.instance().save()
2085 return xen_api_success_void()
2088 # Xen API: Class debug
2089 # ----------------------------------------------------------------
2091 debug_methods = [('destroy', None),
2092 ('get_record', 'debug')]
2093 debug_funcs = [('wait', None),
2094 ('return_failure', None)]
2096 def debug_wait(self, session, wait_secs):
2097 import time
2098 prog_units = 100/float(wait_secs)
2099 for i in range(int(wait_secs)):
2100 XendTask.log_progress(prog_units * i, prog_units * (i + 1),
2101 time.sleep, 1)
2102 return xen_api_success_void()
2105 def debug_return_failure(self, session):
2106 return xen_api_error(['DEBUG_FAIL', session])
2108 def debug_create(self, session):
2109 debug_uuid = uuid.createString()
2110 self._debug[debug_uuid] = None
2111 return xen_api_success(debug_uuid)
2113 def debug_destroy(self, session, debug_ref):
2114 del self._debug[debug_ref]
2115 return xen_api_success_void()
2117 def debug_get_record(self, session, debug_ref):
2118 return xen_api_success({'uuid': debug_ref})
2122 class XendAPIAsyncProxy:
2123 """ A redirector for Async.Class.function calls to XendAPI
2124 but wraps the call for use with the XendTaskManager.
2126 @ivar xenapi: Xen API instance
2127 @ivar method_map: Mapping from XMLRPC method name to callable objects.
2128 """
2130 method_prefix = 'Async.'
2132 def __init__(self, xenapi):
2133 """Initialises the Async Proxy by making a map of all
2134 implemented Xen API methods for use with XendTaskManager.
2136 @param xenapi: XendAPI instance
2137 """
2138 self.xenapi = xenapi
2139 self.method_map = {}
2140 for method_name in dir(self.xenapi):
2141 method = getattr(self.xenapi, method_name)
2142 if method_name[0] != '_' and hasattr(method, 'async') \
2143 and method.async == True:
2144 self.method_map[method.api] = method
2146 def _dispatch(self, method, args):
2147 """Overridden method so that SimpleXMLRPCServer will
2148 resolve methods through this method rather than through
2149 inspection.
2151 @param method: marshalled method name from XMLRPC.
2152 @param args: marshalled arguments from XMLRPC.
2153 """
2155 # Only deal with method names that start with "Async."
2156 if not method.startswith(self.method_prefix):
2157 return xen_api_error(['MESSAGE_METHOD_UNKNOWN', method])
2159 # Lookup synchronous version of the method
2160 synchronous_method_name = method[len(self.method_prefix):]
2161 if synchronous_method_name not in self.method_map:
2162 return xen_api_error(['MESSAGE_METHOD_UNKNOWN', method])
2164 method = self.method_map[synchronous_method_name]
2166 # Check that we've got enough arguments before issuing a task ID.
2167 needed = argcounts[method.api]
2168 if len(args) != needed:
2169 return xen_api_error(['MESSAGE_PARAMETER_COUNT_MISMATCH',
2170 self.method_prefix + method.api, needed,
2171 len(args)])
2173 # Validate the session before proceeding
2174 session = args[0]
2175 if not auth_manager().is_session_valid(session):
2176 return xen_api_error(['SESSION_INVALID', session])
2178 # create and execute the task, and return task_uuid
2179 return_type = getattr(method, 'return_type', None)
2180 task_uuid = XendTaskManager.create_task(method, args,
2181 synchronous_method_name,
2182 return_type,
2183 synchronous_method_name,
2184 session)
2185 return xen_api_success(task_uuid)
2188 # Auto generate some stubs based on XendAPI introspection
2190 if __name__ == "__main__":
2191 def output(line):
2192 print ' ' + line
2194 classes = ['VDI', 'SR']
2195 for cls in classes:
2196 ro_attrs = getattr(XendAPI, '%s_attr_ro' % cls, [])
2197 rw_attrs = getattr(XendAPI, '%s_attr_rw' % cls, [])
2198 methods = getattr(XendAPI, '%s_methods' % cls, [])
2199 funcs = getattr(XendAPI, '%s_funcs' % cls, [])
2201 ref = '%s_ref' % cls
2203 for attr_name in ro_attrs + rw_attrs + XendAPI.Base_attr_ro:
2204 getter_name = '%s_get_%s' % (cls, attr_name)
2205 output('def %s(self, session, %s):' % (getter_name, ref))
2206 output(' return xen_api_todo()')
2208 for attr_name in rw_attrs + XendAPI.Base_attr_rw:
2209 setter_name = '%s_set_%s' % (cls, attr_name)
2210 output('def %s(self, session, %s, value):' % (setter_name, ref))
2211 output(' return xen_api_todo()')
2213 for method_name in methods + XendAPI.Base_methods:
2214 method_full_name = '%s_%s' % (cls,method_name)
2215 output('def %s(self, session, %s):' % (method_full_name, ref))
2216 output(' return xen_api_todo()')
2218 for func_name in funcs + XendAPI.Base_funcs:
2219 func_full_name = '%s_%s' % (cls, func_name)
2220 output('def %s(self, session):' % func_full_name)
2221 output(' return xen_api_todo()')