direct-io.hg

view tools/python/xen/xend/XendAPI.py @ 14449:e2f302488983

Add VBD.runtime_properties dictionary, and use that to implement xm block-list
through the Xen-API. Implement xm block-attach and xm block-detach also.

Signed-off-by: Tom Wilkie <tom.wilkie@gmail.com>
author Ewan Mellor <ewan@xensource.com>
date Tue Mar 20 11:45:44 2007 +0000 (2007-03-20)
parents 2adbc1d22fe7
children d86957cea8b8
line source
1 #============================================================================
2 # This library is free software; you can redistribute it and/or
3 # modify it under the terms of version 2.1 of the GNU Lesser General Public
4 # License as published by the Free Software Foundation.
5 #
6 # This library is distributed in the hope that it will be useful,
7 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 # Lesser General Public License for more details.
10 #
11 # You should have received a copy of the GNU Lesser General Public
12 # License along with this library; if not, write to the Free Software
13 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14 #============================================================================
15 # Copyright (C) 2006-2007 XenSource Ltd.
16 #============================================================================
18 import inspect
19 import os
20 import string
21 import sys
22 import traceback
23 import threading
25 from xen.xend import XendDomain, XendDomainInfo, XendNode, XendDmesg
26 from xen.xend import XendLogging, XendTaskManager
28 from xen.xend.XendAPIVersion import *
29 from xen.xend.XendAuthSessions import instance as auth_manager
30 from xen.xend.XendError import *
31 from xen.xend.XendClient import ERROR_INVALID_DOMAIN
32 from xen.xend.XendLogging import log
33 from xen.xend.XendTask import XendTask
34 from xen.xend.XendVMMetrics import XendVMMetrics
36 from xen.xend.XendAPIConstants import *
37 from xen.util.xmlrpclib2 import stringify
39 from xen.util.blkif import blkdev_name_to_number
42 AUTH_NONE = 'none'
43 AUTH_PAM = 'pam'
45 argcounts = {}
47 # ------------------------------------------
48 # Utility Methods for Xen API Implementation
49 # ------------------------------------------
51 def xen_api_success(value):
52 """Wraps a return value in XenAPI format."""
53 if value is None:
54 s = ''
55 else:
56 s = stringify(value)
57 return {"Status": "Success", "Value": s}
59 def xen_api_success_void():
60 """Return success, but caller expects no return value."""
61 return xen_api_success("")
63 def xen_api_error(error):
64 """Wraps an error value in XenAPI format."""
65 if type(error) == tuple:
66 error = list(error)
67 if type(error) != list:
68 error = [error]
69 if len(error) == 0:
70 error = ['INTERNAL_ERROR', 'Empty list given to xen_api_error']
72 return { "Status": "Failure",
73 "ErrorDescription": [str(x) for x in error] }
76 def xen_api_todo():
77 """Temporary method to make sure we track down all the TODOs"""
78 return {"Status": "Error", "ErrorDescription": XEND_ERROR_TODO}
80 # ---------------------------------------------------
81 # Python Method Decorators for input value validation
82 # ---------------------------------------------------
84 def trace(func, api_name = ''):
85 """Decorator to trace XMLRPC Xen API methods.
87 @param func: function with any parameters
88 @param api_name: name of the api call for debugging.
89 """
90 if hasattr(func, 'api'):
91 api_name = func.api
92 def trace_func(self, *args, **kwargs):
93 log.debug('%s: %s' % (api_name, args))
94 return func(self, *args, **kwargs)
95 trace_func.api = api_name
96 return trace_func
99 def catch_typeerror(func):
100 """Decorator to catch any TypeErrors and translate them into Xen-API
101 errors.
103 @param func: function with params: (self, ...)
104 @rtype: callable object
105 """
106 def f(self, *args, **kwargs):
107 try:
108 return func(self, *args, **kwargs)
109 except TypeError, exn:
110 #log.exception('catch_typeerror')
111 if hasattr(func, 'api') and func.api in argcounts:
112 # Assume that if the argument count was wrong and if the
113 # exception was thrown inside this file, then it is due to an
114 # invalid call from the client, otherwise it's an internal
115 # error (which will be handled further up).
116 expected = argcounts[func.api]
117 actual = len(args) + len(kwargs)
118 if expected != actual:
119 tb = sys.exc_info()[2]
120 try:
121 sourcefile = traceback.extract_tb(tb)[-1][0]
122 if sourcefile == inspect.getsourcefile(XendAPI):
123 return xen_api_error(
124 ['MESSAGE_PARAMETER_COUNT_MISMATCH',
125 func.api, expected, actual])
126 finally:
127 del tb
128 raise
130 return f
133 def session_required(func):
134 """Decorator to verify if session is valid before calling method.
136 @param func: function with params: (self, session, ...)
137 @rtype: callable object
138 """
139 def check_session(self, session, *args, **kwargs):
140 if auth_manager().is_session_valid(session):
141 return func(self, session, *args, **kwargs)
142 else:
143 return xen_api_error(['SESSION_INVALID', session])
145 return check_session
148 def _is_valid_ref(ref, validator):
149 return type(ref) == str and validator(ref)
151 def _check_ref(validator, clas, func, api, session, ref, *args, **kwargs):
152 if _is_valid_ref(ref, validator):
153 return func(api, session, ref, *args, **kwargs)
154 else:
155 return xen_api_error(['HANDLE_INVALID', clas, ref])
158 def valid_host(func):
159 """Decorator to verify if host_ref is valid before calling method.
161 @param func: function with params: (self, session, host_ref, ...)
162 @rtype: callable object
163 """
164 return lambda *args, **kwargs: \
165 _check_ref(XendNode.instance().is_valid_host,
166 'host', func, *args, **kwargs)
168 def valid_host_metrics(func):
169 """Decorator to verify if host_metrics_ref is valid before calling
170 method.
172 @param func: function with params: (self, session, host_metrics_ref)
173 @rtype: callable object
174 """
175 return lambda *args, **kwargs: \
176 _check_ref(lambda r: r == XendNode.instance().host_metrics_uuid,
177 'host_metrics', func, *args, **kwargs)
179 def valid_host_cpu(func):
180 """Decorator to verify if host_cpu_ref is valid before calling method.
182 @param func: function with params: (self, session, host_cpu_ref, ...)
183 @rtype: callable object
184 """
185 return lambda *args, **kwargs: \
186 _check_ref(XendNode.instance().is_valid_cpu,
187 'host_cpu', func, *args, **kwargs)
189 def valid_vm(func):
190 """Decorator to verify if vm_ref is valid before calling method.
192 @param func: function with params: (self, session, vm_ref, ...)
193 @rtype: callable object
194 """
195 return lambda *args, **kwargs: \
196 _check_ref(XendDomain.instance().is_valid_vm,
197 'VM', func, *args, **kwargs)
199 def valid_vm_metrics(func):
200 """Decorator to verify if vm_metrics_ref is valid before calling method.
202 @param func: function with params: (self, session, vm_metrics_ref, ...)
203 @rtype: callable object
204 """
205 return lambda *args, **kwargs: \
206 _check_ref(XendVMMetrics.is_valid_vm_metrics,
207 'VM_metrics', func, *args, **kwargs)
209 def valid_network(func):
210 """Decorator to verify if network_ref is valid before calling method.
212 @param func: function with params: (self, session, network_ref, ...)
213 @rtype: callable object
214 """
215 return lambda *args, **kwargs: \
216 _check_ref(XendNode.instance().is_valid_network,
217 'network', func, *args, **kwargs)
219 def valid_vbd(func):
220 """Decorator to verify if vbd_ref is valid before calling method.
222 @param func: function with params: (self, session, vbd_ref, ...)
223 @rtype: callable object
224 """
225 return lambda *args, **kwargs: \
226 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vbd', r),
227 'VBD', func, *args, **kwargs)
229 def valid_vbd_metrics(func):
230 """Decorator to verify if ref is valid before calling method.
232 @param func: function with params: (self, session, ref, ...)
233 @rtype: callable object
234 """
235 return lambda *args, **kwargs: \
236 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vbd', r),
237 'VBD_metrics', func, *args, **kwargs)
239 def valid_vif(func):
240 """Decorator to verify if vif_ref is valid before calling method.
242 @param func: function with params: (self, session, vif_ref, ...)
243 @rtype: callable object
244 """
245 return lambda *args, **kwargs: \
246 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vif', r),
247 'VIF', func, *args, **kwargs)
249 def valid_vif_metrics(func):
250 """Decorator to verify if ref is valid before calling method.
252 @param func: function with params: (self, session, ref, ...)
253 @rtype: callable object
254 """
255 return lambda *args, **kwargs: \
256 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vif', r),
257 'VIF_metrics', func, *args, **kwargs)
259 def valid_vdi(func):
260 """Decorator to verify if vdi_ref is valid before calling method.
262 @param func: function with params: (self, session, vdi_ref, ...)
263 @rtype: callable object
264 """
265 return lambda *args, **kwargs: \
266 _check_ref(XendNode.instance().is_valid_vdi,
267 'VDI', func, *args, **kwargs)
269 def valid_vtpm(func):
270 """Decorator to verify if vtpm_ref is valid before calling method.
272 @param func: function with params: (self, session, vtpm_ref, ...)
273 @rtype: callable object
274 """
275 return lambda *args, **kwargs: \
276 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vtpm', r),
277 'VTPM', func, *args, **kwargs)
280 def valid_console(func):
281 """Decorator to verify if console_ref is valid before calling method.
283 @param func: function with params: (self, session, console_ref, ...)
284 @rtype: callable object
285 """
286 return lambda *args, **kwargs: \
287 _check_ref(lambda r: XendDomain.instance().is_valid_dev('console',
288 r),
289 'console', func, *args, **kwargs)
291 def valid_sr(func):
292 """Decorator to verify if sr_ref is valid before calling method.
294 @param func: function with params: (self, session, sr_ref, ...)
295 @rtype: callable object
296 """
297 return lambda *args, **kwargs: \
298 _check_ref(lambda r: XendNode.instance().is_valid_sr,
299 'SR', func, *args, **kwargs)
301 def valid_pif(func):
302 """Decorator to verify if pif_ref is valid before calling
303 method.
305 @param func: function with params: (self, session, pif_ref)
306 @rtype: callable object
307 """
308 return lambda *args, **kwargs: \
309 _check_ref(lambda r: r in XendNode.instance().pifs,
310 'PIF', func, *args, **kwargs)
312 def valid_pif_metrics(func):
313 """Decorator to verify if pif_metrics_ref is valid before calling
314 method.
316 @param func: function with params: (self, session, pif_metrics_ref)
317 @rtype: callable object
318 """
319 return lambda *args, **kwargs: \
320 _check_ref(lambda r: r in XendNode.instance().pif_metrics,
321 'PIF_metrics', func, *args, **kwargs)
323 def valid_task(func):
324 """Decorator to verify if task_ref is valid before calling
325 method.
327 @param func: function with params: (self, session, task_ref)
328 @rtype: callable object
329 """
330 return lambda *args, **kwargs: \
331 _check_ref(XendTaskManager.get_task,
332 'task', func, *args, **kwargs)
334 def valid_debug(func):
335 """Decorator to verify if task_ref is valid before calling
336 method.
338 @param func: function with params: (self, session, task_ref)
339 @rtype: callable object
340 """
341 return lambda *args, **kwargs: \
342 _check_ref(lambda r: r in XendAPI._debug,
343 'debug', func, *args, **kwargs)
345 # -----------------------------
346 # Bridge to Legacy XM API calls
347 # -----------------------------
349 def do_vm_func(fn_name, vm_ref, *args, **kwargs):
350 """Helper wrapper func to abstract away from repetitive code.
352 @param fn_name: function name for XendDomain instance
353 @type fn_name: string
354 @param vm_ref: vm_ref
355 @type vm_ref: string
356 @param *args: more arguments
357 @type *args: tuple
358 """
359 try:
360 xendom = XendDomain.instance()
361 fn = getattr(xendom, fn_name)
362 xendom.do_legacy_api_with_uuid(fn, vm_ref, *args, **kwargs)
363 return xen_api_success_void()
364 except VMBadState, exn:
365 return xen_api_error(['VM_BAD_POWER_STATE', vm_ref, exn.expected,
366 exn.actual])
369 class XendAPI(object):
370 """Implementation of the Xen-API in Xend. Expects to be
371 used via XMLRPCServer.
373 All methods that need a valid session are marked with
374 a L{session_required} decorator that will
375 transparently perform the required session authentication.
377 We need to support Python <2.4, so we use the old decorator syntax.
379 All XMLRPC accessible methods require an 'api' attribute and
380 is set to the XMLRPC function name which the method implements.
381 """
383 __decorated__ = False
384 __init_lock__ = threading.Lock()
385 _debug = {}
387 def __new__(cls, *args, **kwds):
388 """ Override __new__ to decorate the class only once.
390 Lock to make sure the classes are not decorated twice.
391 """
392 cls.__init_lock__.acquire()
393 try:
394 if not cls.__decorated__:
395 cls._decorate()
396 cls.__decorated__ = True
398 return object.__new__(cls, *args, **kwds)
399 finally:
400 cls.__init_lock__.release()
402 def _decorate(cls):
403 """ Decorate all the object methods to have validators
404 and appropriate function attributes.
406 This should only be executed once for the duration of the
407 server.
408 """
409 global_validators = [session_required, catch_typeerror]
410 classes = {
411 'session' : None,
412 'host' : valid_host,
413 'host_cpu' : valid_host_cpu,
414 'host_metrics' : valid_host_metrics,
415 'network' : valid_network,
416 'VM' : valid_vm,
417 'VM_metrics' : valid_vm_metrics,
418 'VBD' : valid_vbd,
419 'VBD_metrics' : valid_vbd_metrics,
420 'VIF' : valid_vif,
421 'VIF_metrics' : valid_vif_metrics,
422 'VDI' : valid_vdi,
423 'VTPM' : valid_vtpm,
424 'console' : valid_console,
425 'SR' : valid_sr,
426 'PIF' : valid_pif,
427 'PIF_metrics' : valid_pif_metrics,
428 'task' : valid_task,
429 'debug' : valid_debug,
430 }
432 # Cheat methods
433 # -------------
434 # Methods that have a trivial implementation for all classes.
435 # 1. get_by_uuid == getting by ref, so just return uuid for
436 # all get_by_uuid() methods.
438 for api_cls in classes.keys():
439 if api_cls == 'session':
440 continue
442 get_by_uuid = '%s_get_by_uuid' % api_cls
443 get_uuid = '%s_get_uuid' % api_cls
444 def _get_by_uuid(_1, _2, ref):
445 return xen_api_success(ref)
447 def _get_uuid(_1, _2, ref):
448 return xen_api_success(ref)
450 setattr(cls, get_by_uuid, _get_by_uuid)
451 setattr(cls, get_uuid, _get_uuid)
453 # Wrapping validators around XMLRPC calls
454 # ---------------------------------------
456 for api_cls, validator in classes.items():
457 def doit(n, takes_instance, async_support = False,
458 return_type = None):
459 n_ = n.replace('.', '_')
460 try:
461 f = getattr(cls, n_)
462 argcounts[n] = f.func_code.co_argcount - 1
464 validators = takes_instance and validator and \
465 [validator] or []
467 validators += global_validators
468 for v in validators:
469 f = v(f)
470 f.api = n
471 f.async = async_support
472 if return_type:
473 f.return_type = return_type
475 setattr(cls, n_, f)
476 except AttributeError:
477 log.warn("API call: %s not found" % n)
480 ro_attrs = getattr(cls, '%s_attr_ro' % api_cls, [])
481 rw_attrs = getattr(cls, '%s_attr_rw' % api_cls, [])
482 methods = getattr(cls, '%s_methods' % api_cls, [])
483 funcs = getattr(cls, '%s_funcs' % api_cls, [])
485 # wrap validators around readable class attributes
486 for attr_name in ro_attrs + rw_attrs + cls.Base_attr_ro:
487 doit('%s.get_%s' % (api_cls, attr_name), True,
488 async_support = False)
490 # wrap validators around writable class attrributes
491 for attr_name in rw_attrs + cls.Base_attr_rw:
492 doit('%s.set_%s' % (api_cls, attr_name), True,
493 async_support = False)
495 # wrap validators around methods
496 for method_name, return_type in methods + cls.Base_methods:
497 doit('%s.%s' % (api_cls, method_name), True,
498 async_support = True)
500 # wrap validators around class functions
501 for func_name, return_type in funcs + cls.Base_funcs:
502 doit('%s.%s' % (api_cls, func_name), False, async_support = True,
503 return_type = return_type)
505 _decorate = classmethod(_decorate)
507 def __init__(self, auth):
508 self.auth = auth
510 Base_attr_ro = ['uuid']
511 Base_attr_rw = []
512 Base_methods = [('destroy', None), ('get_record', 'Struct')]
513 Base_funcs = [('get_all', 'Set'), ('get_by_uuid', None)]
515 # Xen API: Class Session
516 # ----------------------------------------------------------------
517 # NOTE: Left unwrapped by __init__
519 session_attr_ro = ['this_host', 'this_user']
520 session_methods = [('logout', None)]
522 def session_login_with_password(self, *args):
523 if len(args) != 2:
524 return xen_api_error(
525 ['MESSAGE_PARAMETER_COUNT_MISMATCH',
526 'session.login_with_password', 2, len(args)])
527 username = args[0]
528 password = args[1]
529 try:
530 session = (self.auth == AUTH_NONE and
531 auth_manager().login_unconditionally(username) or
532 auth_manager().login_with_password(username, password))
533 return xen_api_success(session)
534 except XendError, e:
535 return xen_api_error(['SESSION_AUTHENTICATION_FAILED'])
536 session_login_with_password.api = 'session.login_with_password'
538 # object methods
539 def session_logout(self, session):
540 auth_manager().logout(session)
541 return xen_api_success_void()
542 def session_get_record(self, session):
543 record = {'uuid' : session,
544 'this_host': XendNode.instance().uuid,
545 'this_user': auth_manager().get_user(session)}
546 return xen_api_success(record)
548 def session_get_uuid(self, session):
549 return xen_api_success(session)
551 def session_get_by_uuid(self, session):
552 return xen_api_success(session)
554 # attributes (ro)
555 def session_get_this_host(self, session):
556 return xen_api_success(XendNode.instance().uuid)
557 def session_get_this_user(self, session):
558 user = auth_manager().get_user(session)
559 if user:
560 return xen_api_success(user)
561 return xen_api_error(['SESSION_INVALID', session])
564 # Xen API: Class User
565 # ----------------------------------------------------------------
566 # TODO: NOT IMPLEMENTED YET
568 # Xen API: Class Tasks
569 # ----------------------------------------------------------------
571 task_attr_ro = ['name_label',
572 'name_description',
573 'status',
574 'progress',
575 'type',
576 'result',
577 'error_code',
578 'error_info',
579 'allowed_operations',
580 'session'
581 ]
583 task_attr_rw = []
585 task_funcs = [('get_by_name_label', 'Set(task)'),
586 ('cancel', None)]
588 def task_get_name_label(self, session, task_ref):
589 task = XendTaskManager.get_task(task_ref)
590 return xen_api_success(task.name_label)
592 def task_get_name_description(self, session, task_ref):
593 task = XendTaskManager.get_task(task_ref)
594 return xen_api_success(task.name_description)
596 def task_get_status(self, session, task_ref):
597 task = XendTaskManager.get_task(task_ref)
598 return xen_api_success(task.get_status())
600 def task_get_progress(self, session, task_ref):
601 task = XendTaskManager.get_task(task_ref)
602 return xen_api_success(task.progress)
604 def task_get_type(self, session, task_ref):
605 task = XendTaskManager.get_task(task_ref)
606 return xen_api_success(task.type)
608 def task_get_result(self, session, task_ref):
609 task = XendTaskManager.get_task(task_ref)
610 return xen_api_success(task.result)
612 def task_get_error_code(self, session, task_ref):
613 task = XendTaskManager.get_task(task_ref)
614 return xen_api_success(task.error_code)
616 def task_get_error_info(self, session, task_ref):
617 task = XendTaskManager.get_task(task_ref)
618 return xen_api_success(task.error_info)
620 def task_get_allowed_operations(self, session, task_ref):
621 return xen_api_success({})
623 def task_get_session(self, session, task_ref):
624 task = XendTaskManager.get_task(task_ref)
625 return xen_api_success(task.session)
627 def task_get_all(self, session):
628 tasks = XendTaskManager.get_all_tasks()
629 return xen_api_success(tasks)
631 def task_get_record(self, session, task_ref):
632 task = XendTaskManager.get_task(task_ref)
633 return xen_api_success(task.get_record())
635 def task_cancel(self, session, task_ref):
636 return xen_api_error('OPERATION_NOT_ALLOWED')
638 def task_get_by_name_label(self, session, name):
639 return xen_api_success(XendTaskManager.get_task_by_name(name))
641 # Xen API: Class host
642 # ----------------------------------------------------------------
644 host_attr_ro = ['software_version',
645 'resident_VMs',
646 'host_CPUs',
647 'cpu_configuration',
648 'metrics',
649 'capabilities',
650 'supported_bootloaders',
651 'API_version_major',
652 'API_version_minor',
653 'API_version_vendor',
654 'API_version_vendor_implementation']
656 host_attr_rw = ['name_label',
657 'sched_policy',
658 'name_description',
659 'other_config']
661 host_methods = [('disable', None),
662 ('enable', None),
663 ('reboot', None),
664 ('shutdown', None),
665 ('add_to_other_config', None),
666 ('remove_from_other_config', None),
667 ('dmesg', 'String'),
668 ('get_log', 'String')]
670 host_funcs = [('get_by_name_label', 'Set(host)')]
672 # attributes
673 def host_get_name_label(self, session, host_ref):
674 return xen_api_success(XendNode.instance().name)
675 def host_set_name_label(self, session, host_ref, new_name):
676 XendNode.instance().set_name(new_name)
677 return xen_api_success_void()
678 def host_get_name_description(self, session, host_ref):
679 return xen_api_success(XendNode.instance().description)
680 def host_set_name_description(self, session, host_ref, new_desc):
681 XendNode.instance().set_description(new_desc)
682 return xen_api_success_void()
683 def host_get_other_config(self, session, host_ref):
684 return xen_api_success(XendNode.instance().other_config)
685 def host_set_other_config(self, session, host_ref, other_config):
686 node = XendNode.instance()
687 node.other_config = dict(other_config)
688 node.save()
689 return xen_api_success_void()
690 def host_add_to_other_config(self, session, host_ref, key, value):
691 node = XendNode.instance()
692 node.other_config[key] = value
693 node.save()
694 return xen_api_success_void()
695 def host_remove_from_other_config(self, session, host_ref, key):
696 node = XendNode.instance()
697 if key in node.other_config:
698 del node.other_config[key]
699 node.save()
700 return xen_api_success_void()
701 def host_get_API_version_major(self, _, ref):
702 return xen_api_success(XEN_API_VERSION_MAJOR)
703 def host_get_API_version_minor(self, _, ref):
704 return xen_api_success(XEN_API_VERSION_MINOR)
705 def host_get_API_version_vendor(self, _, ref):
706 return xen_api_success(XEN_API_VERSION_VENDOR)
707 def host_get_API_version_vendor_implementation(self, _, ref):
708 return xen_api_success(XEN_API_VERSION_VENDOR_IMPLEMENTATION)
709 def host_get_software_version(self, session, host_ref):
710 return xen_api_success(XendNode.instance().xen_version())
711 def host_get_resident_VMs(self, session, host_ref):
712 return xen_api_success(XendDomain.instance().get_domain_refs())
713 def host_get_host_CPUs(self, session, host_ref):
714 return xen_api_success(XendNode.instance().get_host_cpu_refs())
715 def host_get_metrics(self, _, ref):
716 return xen_api_success(XendNode.instance().host_metrics_uuid)
717 def host_get_capabilities(self, session, host_ref):
718 return xen_api_success(XendNode.instance().get_capabilities())
719 def host_get_supported_bootloaders(self, session, host_ref):
720 return xen_api_success(['pygrub'])
721 def host_get_sched_policy(self, _, host_ref):
722 return xen_api_success(XendNode.instance().get_vcpus_policy())
723 def host_set_sched_policy(self, _, host_ref, policy):
724 return xen_api_todo()
725 def host_get_cpu_configuration(self, _, host_ref):
726 return xen_api_success(XendNode.instance().get_cpu_configuration())
728 # object methods
729 def host_disable(self, session, host_ref):
730 XendDomain.instance().set_allow_new_domains(False)
731 return xen_api_success_void()
732 def host_enable(self, session, host_ref):
733 XendDomain.instance().set_allow_new_domains(True)
734 return xen_api_success_void()
735 def host_reboot(self, session, host_ref):
736 if not XendDomain.instance().allow_new_domains():
737 return xen_api_error(XEND_ERROR_HOST_RUNNING)
738 return xen_api_error(XEND_ERROR_UNSUPPORTED)
739 def host_shutdown(self, session, host_ref):
740 if not XendDomain.instance().allow_new_domains():
741 return xen_api_error(XEND_ERROR_HOST_RUNNING)
742 return xen_api_error(XEND_ERROR_UNSUPPORTED)
744 def host_dmesg(self, session, host_ref, clear):
745 if clear:
746 return xen_api_success(XendDmesg.instance().clear())
747 else:
748 return xen_api_success(XendDmesg.instance().info())
750 def host_get_log(self, session, host_ref):
751 log_file = open(XendLogging.getLogFilename())
752 log_buffer = log_file.read()
753 return xen_api_success(log_buffer)
755 def host_get_record(self, session, host_ref):
756 node = XendNode.instance()
757 dom = XendDomain.instance()
758 record = {'uuid': node.uuid,
759 'name_label': node.name,
760 'name_description': '',
761 'API_version_major': XEN_API_VERSION_MAJOR,
762 'API_version_minor': XEN_API_VERSION_MINOR,
763 'API_version_vendor': XEN_API_VERSION_VENDOR,
764 'API_version_vendor_implementation':
765 XEN_API_VERSION_VENDOR_IMPLEMENTATION,
766 'software_version': node.xen_version(),
767 'other_config': node.other_config,
768 'resident_VMs': dom.get_domain_refs(),
769 'host_CPUs': node.get_host_cpu_refs(),
770 'cpu_configuration': node.get_cpu_configuration(),
771 'metrics': node.host_metrics_uuid,
772 'capabilities': node.get_capabilities(),
773 'supported_bootloaders': 'pygrub',
774 'sched_policy': node.get_vcpus_policy()}
775 return xen_api_success(record)
777 # class methods
778 def host_get_all(self, session):
779 return xen_api_success((XendNode.instance().uuid,))
780 def host_get_by_name_label(self, session, name):
781 if XendNode.instance().name == name:
782 return xen_api_success((XendNode.instance().uuid,))
783 return xen_api_success([])
786 # Xen API: Class host_CPU
787 # ----------------------------------------------------------------
789 host_cpu_attr_ro = ['host',
790 'number',
791 'vendor',
792 'speed',
793 'modelname',
794 'stepping',
795 'flags',
796 'utilisation',
797 'features']
799 # attributes
800 def _host_cpu_get(self, ref, field):
801 return xen_api_success(
802 XendNode.instance().get_host_cpu_field(ref, field))
804 def host_cpu_get_host(self, _, ref):
805 return xen_api_success(XendNode.instance().uuid)
806 def host_cpu_get_features(self, _, ref):
807 return self._host_cpu_get(ref, 'features')
808 def host_cpu_get_number(self, _, ref):
809 return self._host_cpu_get(ref, 'number')
810 def host_cpu_get_vendor(self, _, ref):
811 return self._host_cpu_get(ref, 'vendor')
812 def host_cpu_get_speed(self, _, ref):
813 return self._host_cpu_get(ref, 'speed')
814 def host_cpu_get_modelname(self, _, ref):
815 return self._host_cpu_get(ref, 'modelname')
816 def host_cpu_get_stepping(self, _, ref):
817 return self._host_cpu_get(ref, 'stepping')
818 def host_cpu_get_flags(self, _, ref):
819 return self._host_cpu_get(ref, 'flags')
820 def host_cpu_get_utilisation(self, _, ref):
821 return xen_api_success(XendNode.instance().get_host_cpu_load(ref))
823 # object methods
824 def host_cpu_get_record(self, _, ref):
825 node = XendNode.instance()
826 record = dict([(f, node.get_host_cpu_field(ref, f))
827 for f in self.host_cpu_attr_ro
828 if f not in ['uuid', 'host', 'utilisation']])
829 record['uuid'] = ref
830 record['host'] = node.uuid
831 record['utilisation'] = node.get_host_cpu_load(ref)
832 return xen_api_success(record)
834 # class methods
835 def host_cpu_get_all(self, session):
836 return xen_api_success(XendNode.instance().get_host_cpu_refs())
839 # Xen API: Class host_metrics
840 # ----------------------------------------------------------------
842 host_metrics_attr_ro = ['memory_total',
843 'memory_free']
844 host_metrics_attr_rw = []
845 host_metrics_methods = []
847 def host_metrics_get_all(self, _):
848 return xen_api_success([XendNode.instance().host_metrics_uuid])
850 def _host_metrics_get(self, ref, f):
851 return xen_api_success(getattr(node, f)())
853 def host_metrics_get_record(self, _, ref):
854 return xen_api_success({
855 'uuid' : ref,
856 'memory_total' : self._host_metrics_get_memory_total(),
857 'memory_free' : self._host_metrics_get_memory_free(),
858 })
860 def host_metrics_get_memory_total(self, _, ref):
861 return xen_api_success(self._host_metrics_get_memory_total())
863 def host_metrics_get_memory_free(self, _, ref):
864 return xen_api_success(self._host_metrics_get_memory_free())
866 def _host_metrics_get_memory_total(self):
867 node = XendNode.instance()
868 return node.xc.physinfo()['total_memory'] * 1024
870 def _host_metrics_get_memory_free(self):
871 node = XendNode.instance()
872 return node.xc.physinfo()['free_memory'] * 1024
875 # Xen API: Class network
876 # ----------------------------------------------------------------
878 network_attr_ro = ['VIFs', 'PIFs']
879 network_attr_rw = ['name_label',
880 'name_description']
882 network_funcs = [('create', 'network')]
884 def network_create(self, _, name_label, name_description):
885 return xen_api_success(
886 XendNode.instance().network_create(name_label, name_description))
888 def network_destroy(self, _, ref):
889 return xen_api_success(XendNode.instance().network_destroy(ref))
891 def _get_network(self, ref):
892 return XendNode.instance().get_network(ref)
894 def network_get_all(self, _):
895 return xen_api_success(XendNode.instance().get_network_refs())
897 def network_get_record(self, _, ref):
898 return xen_api_success(
899 XendNode.instance().get_network(ref).get_record())
901 def network_get_name_label(self, _, ref):
902 return xen_api_success(self._get_network(ref).name_label)
904 def network_get_name_description(self, _, ref):
905 return xen_api_success(self._get_network(ref).name_description)
907 def network_get_VIFs(self, _, ref):
908 return xen_api_success(self._get_network(ref).get_VIF_UUIDs())
910 def network_get_PIFs(self, session, ref):
911 return xen_api_success(self._get_network(ref).get_PIF_UUIDs())
913 def network_set_name_label(self, _, ref, val):
914 return xen_api_success(self._get_network(ref).set_name_label(val))
916 def network_set_name_description(self, _, ref, val):
917 return xen_api_success(self._get_network(ref).set_name_description(val))
919 # Xen API: Class PIF
920 # ----------------------------------------------------------------
922 PIF_attr_ro = ['metrics']
923 PIF_attr_rw = ['device',
924 'network',
925 'host',
926 'MAC',
927 'MTU',
928 'VLAN']
930 PIF_attr_inst = PIF_attr_rw
932 PIF_methods = [('create_VLAN', 'int')]
934 def _get_PIF(self, ref):
935 return XendNode.instance().pifs[ref]
937 def PIF_destroy(self, _, ref):
938 try:
939 return xen_api_success(XendNode.instance().PIF_destroy(ref))
940 except PIFIsPhysical, exn:
941 return xen_api_error(['PIF_IS_PHYSICAL', ref])
943 # object methods
944 def PIF_get_record(self, _, ref):
945 return xen_api_success(self._get_PIF(ref).get_record())
947 def PIF_get_all(self, _):
948 return xen_api_success(XendNode.instance().pifs.keys())
950 def PIF_get_metrics(self, _, ref):
951 return xen_api_success(self._get_PIF(ref).metrics.uuid)
953 def PIF_get_device(self, _, ref):
954 return xen_api_success(self._get_PIF(ref).device)
956 def PIF_get_network(self, _, ref):
957 return xen_api_success(self._get_PIF(ref).network.uuid)
959 def PIF_get_host(self, _, ref):
960 return xen_api_success(self._get_PIF(ref).host.uuid)
962 def PIF_get_MAC(self, _, ref):
963 return xen_api_success(self._get_PIF(ref).mac)
965 def PIF_get_MTU(self, _, ref):
966 return xen_api_success(self._get_PIF(ref).mtu)
968 def PIF_get_VLAN(self, _, ref):
969 return xen_api_success(self._get_PIF(ref).vlan)
971 def PIF_set_device(self, _, ref, device):
972 return xen_api_success(self._get_PIF(ref).set_device(device))
974 def PIF_set_MAC(self, _, ref, mac):
975 return xen_api_success(self._get_PIF(ref).set_mac(mac))
977 def PIF_set_MTU(self, _, ref, mtu):
978 return xen_api_success(self._get_PIF(ref).set_mtu(mtu))
980 def PIF_create_VLAN(self, _, ref, network, vlan):
981 try:
982 vlan = int(vlan)
983 except:
984 return xen_api_error(['VLAN_TAG_INVALID', vlan])
986 try:
987 node = XendNode.instance()
989 if _is_valid_ref(network, node.is_valid_network):
990 return xen_api_success(
991 node.PIF_create_VLAN(ref, network, vlan))
992 else:
993 return xen_api_error(['HANDLE_INVALID', 'network', network])
994 except NetworkAlreadyConnected, exn:
995 return xen_api_error(['NETWORK_ALREADY_CONNECTED',
996 network, exn.pif_uuid])
997 except VLANTagInvalid:
998 return xen_api_error(['VLAN_TAG_INVALID', vlan])
1001 # Xen API: Class PIF_metrics
1002 # ----------------------------------------------------------------
1004 PIF_metrics_attr_ro = ['io_read_kbs',
1005 'io_write_kbs']
1006 PIF_metrics_attr_rw = []
1007 PIF_methods = []
1009 def PIF_metrics_get_all(self, _):
1010 return xen_api_success(XendNode.instance().pif_metrics.keys())
1012 def _PIF_metrics_get(self, ref):
1013 return XendNode.instance().pif_metrics[ref]
1015 def PIF_metrics_get_record(self, _, ref):
1016 return xen_api_success(self._PIF_metrics_get(ref).get_record())
1018 def PIF_metrics_get_io_read_kbs(self, _, ref):
1019 return xen_api_success(self._PIF_metrics_get(ref).get_io_read_kbs())
1021 def PIF_metrics_get_io_write_kbs(self, _, ref):
1022 return xen_api_success(self._PIF_metrics_get(ref).get_io_write_kbs())
1025 # Xen API: Class VM
1026 # ----------------------------------------------------------------
1028 VM_attr_ro = ['power_state',
1029 'resident_on',
1030 'memory_static_max',
1031 'memory_static_min',
1032 'VCPUs_number',
1033 'consoles',
1034 'VIFs',
1035 'VBDs',
1036 'VTPMs',
1037 'tools_version',
1038 'domid',
1039 'is_control_domain',
1040 'metrics'
1043 VM_attr_rw = ['name_label',
1044 'name_description',
1045 'user_version',
1046 'is_a_template',
1047 'auto_power_on',
1048 'memory_dynamic_max',
1049 'memory_dynamic_min',
1050 'VCPUs_params',
1051 'actions_after_shutdown',
1052 'actions_after_reboot',
1053 'actions_after_suspend',
1054 'actions_after_crash',
1055 'PV_bootloader',
1056 'PV_kernel',
1057 'PV_ramdisk',
1058 'PV_args',
1059 'PV_bootloader_args',
1060 'HVM_boot_policy',
1061 'HVM_boot_params',
1062 'platform',
1063 'PCI_bus',
1064 'other_config']
1066 VM_methods = [('clone', 'VM'),
1067 ('start', None),
1068 ('pause', None),
1069 ('unpause', None),
1070 ('clean_shutdown', None),
1071 ('clean_reboot', None),
1072 ('hard_shutdown', None),
1073 ('hard_reboot', None),
1074 ('suspend', None),
1075 ('resume', None),
1076 ('send_sysrq', None),
1077 ('add_to_HVM_boot_params', None),
1078 ('remove_from_HVM_boot_params', None),
1079 ('add_to_VCPUs_params', None),
1080 ('remove_from_VCPUs_params', None),
1081 ('add_to_platform', None),
1082 ('remove_from_platform', None),
1083 ('add_to_other_config', None),
1084 ('remove_from_other_config', None)]
1086 VM_funcs = [('create', 'VM'),
1087 ('get_by_name_label', 'Set(VM)')]
1089 # parameters required for _create()
1090 VM_attr_inst = [
1091 'name_label',
1092 'name_description',
1093 'user_version',
1094 'is_a_template',
1095 'memory_static_max',
1096 'memory_dynamic_max',
1097 'memory_dynamic_min',
1098 'memory_static_min',
1099 'VCPUs_params',
1100 'actions_after_shutdown',
1101 'actions_after_reboot',
1102 'actions_after_suspend',
1103 'actions_after_crash',
1104 'PV_bootloader',
1105 'PV_kernel',
1106 'PV_ramdisk',
1107 'PV_args',
1108 'PV_bootloader_args',
1109 'HVM_boot_policy',
1110 'HVM_boot_params',
1111 'platform',
1112 'PCI_bus',
1113 'other_config']
1115 def VM_get(self, name, session, vm_ref):
1116 return xen_api_success(
1117 XendDomain.instance().get_vm_by_uuid(vm_ref).info[name])
1119 def VM_set(self, name, session, vm_ref, value):
1120 xd = XendDomain.instance()
1121 dominfo = xd.get_vm_by_uuid(vm_ref)
1122 dominfo.info[name] = value
1123 return self._VM_save(dominfo)
1125 def _VM_save(self, dominfo):
1126 XendDomain.instance().managed_config_save(dominfo)
1127 return xen_api_success_void()
1129 # attributes (ro)
1130 def VM_get_power_state(self, session, vm_ref):
1131 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1132 return xen_api_success(dom.get_power_state())
1134 def VM_get_resident_on(self, session, vm_ref):
1135 return xen_api_success(XendNode.instance().uuid)
1137 def VM_get_memory_static_max(self, session, vm_ref):
1138 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1139 return xen_api_success(dom.get_memory_static_max())
1141 def VM_get_memory_static_min(self, session, vm_ref):
1142 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1143 return xen_api_success(dom.get_memory_static_min())
1145 def VM_get_VCPUs_number(self, session, vm_ref):
1146 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1147 return xen_api_success(dom.getVCpuCount())
1149 def VM_get_VIFs(self, session, vm_ref):
1150 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1151 return xen_api_success(dom.get_vifs())
1153 def VM_get_VBDs(self, session, vm_ref):
1154 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1155 return xen_api_success(dom.get_vbds())
1157 def VM_get_VTPMs(self, session, vm_ref):
1158 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1159 return xen_api_success(dom.get_vtpms())
1161 def VM_get_consoles(self, session, vm_ref):
1162 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1163 return xen_api_success(dom.get_consoles())
1165 def VM_get_tools_version(self, session, vm_ref):
1166 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1167 return dom.get_tools_version()
1169 def VM_get_metrics(self, _, vm_ref):
1170 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1171 return xen_api_success(dom.get_metrics())
1173 # attributes (rw)
1174 def VM_get_name_label(self, session, vm_ref):
1175 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1176 return xen_api_success(dom.getName())
1178 def VM_get_name_description(self, session, vm_ref):
1179 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1180 return xen_api_todo()
1182 def VM_get_user_version(self, session, vm_ref):
1183 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1184 return xen_api_todo()
1186 def VM_get_is_a_template(self, session, vm_ref):
1187 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1188 return xen_api_todo()
1190 def VM_get_memory_dynamic_max(self, session, vm_ref):
1191 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1192 return xen_api_success(dom.get_memory_dynamic_max())
1194 def VM_get_memory_dynamic_min(self, session, vm_ref):
1195 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1196 return xen_api_success(dom.get_memory_dynamic_min())
1198 def VM_get_VCPUs_params(self, session, vm_ref):
1199 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1200 return xen_api_success(dom.get_vcpus_params())
1202 def VM_get_actions_after_shutdown(self, session, vm_ref):
1203 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1204 return xen_api_success(dom.get_on_shutdown())
1206 def VM_get_actions_after_reboot(self, session, vm_ref):
1207 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1208 return xen_api_success(dom.get_on_reboot())
1210 def VM_get_actions_after_suspend(self, session, vm_ref):
1211 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1212 return xen_api_success(dom.get_on_suspend())
1214 def VM_get_actions_after_crash(self, session, vm_ref):
1215 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1216 return xen_api_success(dom.get_on_crash())
1218 def VM_get_PV_bootloader(self, session, vm_ref):
1219 return self.VM_get('PV_bootloader', session, vm_ref)
1221 def VM_get_PV_kernel(self, session, vm_ref):
1222 return self.VM_get('PV_kernel', session, vm_ref)
1224 def VM_get_PV_ramdisk(self, session, vm_ref):
1225 return self.VM_get('PV_ramdisk', session, vm_ref)
1227 def VM_get_PV_args(self, session, vm_ref):
1228 return self.VM_get('PV_args', session, vm_ref)
1230 def VM_get_PV_bootloader_args(self, session, vm_ref):
1231 return self.VM_get('PV_bootloader_args', session, vm_ref)
1233 def VM_get_HVM_boot_policy(self, session, vm_ref):
1234 return self.VM_get('HVM_boot_policy', session, vm_ref)
1236 def VM_get_HVM_boot_params(self, session, vm_ref):
1237 return self.VM_get('HVM_boot_params', session, vm_ref)
1239 def VM_get_platform(self, session, vm_ref):
1240 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1241 return xen_api_success(dom.get_platform())
1243 def VM_get_PCI_bus(self, session, vm_ref):
1244 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1245 return dom.get_pci_bus()
1247 def VM_set_PCI_bus(self, session, vm_ref, val):
1248 return self.VM_set('PCI_bus', session, vm_ref, val)
1250 def VM_get_other_config(self, session, vm_ref):
1251 return self.VM_get('other_config', session, vm_ref)
1253 def VM_get_domid(self, _, ref):
1254 domid = XendDomain.instance().get_vm_by_uuid(ref).getDomid()
1255 return xen_api_success(domid is None and -1 or domid)
1257 def VM_get_is_control_domain(self, session, vm_ref):
1258 xd = XendDomain.instance()
1259 return xen_api_success(
1260 xd.get_vm_by_uuid(vm_ref) == xd.privilegedDomain())
1262 def VM_set_name_label(self, session, vm_ref, label):
1263 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1264 dom.setName(label)
1265 return self._VM_save(dom)
1267 def VM_set_name_description(self, session, vm_ref, desc):
1268 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1269 return xen_api_todo()
1271 def VM_set_user_version(self, session, vm_ref, ver):
1272 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1273 return xen_api_todo()
1275 def VM_set_is_a_template(self, session, vm_ref, is_template):
1276 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1277 return xen_api_todo()
1279 def VM_set_memory_dynamic_max(self, session, vm_ref, mem):
1280 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1281 return xen_api_todo()
1283 def VM_set_memory_dynamic_min(self, session, vm_ref, mem):
1284 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1285 return xen_api_todo()
1287 def VM_set_VCPUs_params(self, session, vm_ref, value):
1288 return self.VM_set('vcpus_params', session, vm_ref, value)
1290 def VM_add_to_VCPUs_params(self, session, vm_ref, key, value):
1291 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1292 if 'vcpus_params' not in dom.info:
1293 dom.info['vcpus_params'] = {}
1294 dom.info['vcpus_params'][key] = value
1295 return self._VM_save(dom)
1297 def VM_remove_from_VCPUs_params(self, session, vm_ref, key):
1298 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1299 if 'vcpus_params' in dom.info \
1300 and key in dom.info['vcpus_params']:
1301 del dom.info['vcpus_params'][key]
1302 return self._VM_save(dom)
1303 else:
1304 return xen_api_success_void()
1306 def VM_set_actions_after_shutdown(self, session, vm_ref, action):
1307 if action not in XEN_API_ON_NORMAL_EXIT:
1308 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1309 return self.VM_set('actions_after_shutdown', session, vm_ref, action)
1311 def VM_set_actions_after_reboot(self, session, vm_ref, action):
1312 if action not in XEN_API_ON_NORMAL_EXIT:
1313 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1314 return self.VM_set('actions_after_reboot', session, vm_ref, action)
1316 def VM_set_actions_after_suspend(self, session, vm_ref, action):
1317 if action not in XEN_API_ON_NORMAL_EXIT:
1318 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1319 return self.VM_set('actions_after_suspend', session, vm_ref, action)
1321 def VM_set_actions_after_crash(self, session, vm_ref, action):
1322 if action not in XEN_API_ON_CRASH_BEHAVIOUR:
1323 return xen_api_error(['VM_ON_CRASH_BEHAVIOUR_INVALID', vm_ref])
1324 return self.VM_set('actions_after_crash', session, vm_ref, action)
1326 def VM_set_HVM_boot_policy(self, session, vm_ref, value):
1327 if value != "" and value != "BIOS order":
1328 return xen_api_error(
1329 ['VALUE_NOT_SUPPORTED', 'VM.HVM_boot_policy', value,
1330 'Xend supports only the "BIOS order" boot policy.'])
1331 else:
1332 return self.VM_set('HVM_boot_policy', session, vm_ref, value)
1334 def VM_set_HVM_boot_params(self, session, vm_ref, value):
1335 return self.VM_set('HVM_boot_params', session, vm_ref, value)
1337 def VM_add_to_HVM_boot_params(self, session, vm_ref, key, value):
1338 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1339 if 'HVM_boot_params' not in dom.info:
1340 dom.info['HVM_boot_params'] = {}
1341 dom.info['HVM_boot_params'][key] = value
1342 return self._VM_save(dom)
1344 def VM_remove_from_HVM_boot_params(self, session, vm_ref, key):
1345 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1346 if 'HVM_boot_params' in dom.info \
1347 and key in dom.info['HVM_boot_params']:
1348 del dom.info['HVM_boot_params'][key]
1349 return self._VM_save(dom)
1350 else:
1351 return xen_api_success_void()
1353 def VM_set_PV_bootloader(self, session, vm_ref, value):
1354 return self.VM_set('PV_bootloader', session, vm_ref, value)
1356 def VM_set_PV_kernel(self, session, vm_ref, value):
1357 return self.VM_set('PV_kernel', session, vm_ref, value)
1359 def VM_set_PV_ramdisk(self, session, vm_ref, value):
1360 return self.VM_set('PV_ramdisk', session, vm_ref, value)
1362 def VM_set_PV_args(self, session, vm_ref, value):
1363 return self.VM_set('PV_args', session, vm_ref, value)
1365 def VM_set_PV_bootloader_args(self, session, vm_ref, value):
1366 return self.VM_set('PV_bootloader_args', session, vm_ref, value)
1368 def VM_set_platform(self, session, vm_ref, value):
1369 return self.VM_set('platform', session, vm_ref, value)
1371 def VM_add_to_platform(self, session, vm_ref, key, value):
1372 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1373 plat = dom.get_platform()
1374 plat[key] = value
1375 return self.VM_set_platform(session, vm_ref, plat)
1377 def VM_remove_from_platform(self, session, vm_ref, key):
1378 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1379 plat = dom.get_platform()
1380 if key in plat:
1381 del plat[key]
1382 return self.VM_set_platform(session, vm_ref, plat)
1383 else:
1384 return xen_api_success_void()
1386 def VM_set_other_config(self, session, vm_ref, value):
1387 return self.VM_set('other_config', session, vm_ref, value)
1389 def VM_add_to_other_config(self, session, vm_ref, key, value):
1390 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1391 if dom and 'other_config' in dom.info:
1392 dom.info['other_config'][key] = value
1393 return self._VM_save(dom)
1395 def VM_remove_from_other_config(self, session, vm_ref, key):
1396 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1397 if dom and 'other_config' in dom.info \
1398 and key in dom.info['other_config']:
1399 del dom.info['other_config'][key]
1400 return self._VM_save(dom)
1401 else:
1402 return xen_api_success_void()
1404 # class methods
1405 def VM_get_all(self, session):
1406 refs = [d.get_uuid() for d in XendDomain.instance().list('all')]
1407 return xen_api_success(refs)
1409 def VM_get_by_name_label(self, session, label):
1410 xendom = XendDomain.instance()
1411 dom = xendom.domain_lookup_nr(label)
1412 if dom:
1413 return xen_api_success([dom.get_uuid()])
1414 return xen_api_success([])
1416 def VM_create(self, session, vm_struct):
1417 xendom = XendDomain.instance()
1418 domuuid = XendTask.log_progress(0, 100,
1419 xendom.create_domain, vm_struct)
1420 return xen_api_success(domuuid)
1422 # object methods
1423 def VM_get_record(self, session, vm_ref):
1424 xendom = XendDomain.instance()
1425 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1426 if not xeninfo:
1427 return xen_api_error(['HANDLE_INVALID', 'VM', vm_ref])
1429 domid = xeninfo.getDomid()
1431 record = {
1432 'uuid': xeninfo.get_uuid(),
1433 'power_state': xeninfo.get_power_state(),
1434 'name_label': xeninfo.getName(),
1435 'name_description': xeninfo.getName(),
1436 'user_version': 1,
1437 'is_a_template': False,
1438 'auto_power_on': False,
1439 'resident_on': XendNode.instance().uuid,
1440 'memory_static_min': xeninfo.get_memory_static_min(),
1441 'memory_static_max': xeninfo.get_memory_static_max(),
1442 'memory_dynamic_min': xeninfo.get_memory_dynamic_min(),
1443 'memory_dynamic_max': xeninfo.get_memory_dynamic_max(),
1444 'VCPUs_params': xeninfo.get_vcpus_params(),
1445 'VCPUs_number': xeninfo.getVCpuCount(),
1446 'actions_after_shutdown': xeninfo.get_on_shutdown(),
1447 'actions_after_reboot': xeninfo.get_on_reboot(),
1448 'actions_after_suspend': xeninfo.get_on_suspend(),
1449 'actions_after_crash': xeninfo.get_on_crash(),
1450 'consoles': xeninfo.get_consoles(),
1451 'VIFs': xeninfo.get_vifs(),
1452 'VBDs': xeninfo.get_vbds(),
1453 'VTPMs': xeninfo.get_vtpms(),
1454 'PV_bootloader': xeninfo.info.get('PV_bootloader'),
1455 'PV_kernel': xeninfo.info.get('PV_kernel'),
1456 'PV_ramdisk': xeninfo.info.get('PV_ramdisk'),
1457 'PV_args': xeninfo.info.get('PV_args'),
1458 'PV_bootloader_args': xeninfo.info.get('PV_bootloader_args'),
1459 'HVM_boot_policy': xeninfo.info.get('HVM_boot_policy'),
1460 'HVM_boot_params': xeninfo.info.get('HVM_boot_params'),
1461 'platform': xeninfo.get_platform(),
1462 'PCI_bus': xeninfo.get_pci_bus(),
1463 'tools_version': xeninfo.get_tools_version(),
1464 'other_config': xeninfo.info.get('other_config', {}),
1465 'domid': domid is None and -1 or domid,
1466 'is_control_domain': xeninfo == xendom.privilegedDomain(),
1468 return xen_api_success(record)
1470 def VM_clean_reboot(self, session, vm_ref):
1471 xendom = XendDomain.instance()
1472 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1473 XendTask.log_progress(0, 100, xeninfo.shutdown, "reboot")
1474 return xen_api_success_void()
1476 def VM_clean_shutdown(self, session, vm_ref):
1477 xendom = XendDomain.instance()
1478 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1479 XendTask.log_progress(0, 100, xeninfo.shutdown, "poweroff")
1480 return xen_api_success_void()
1482 def VM_clone(self, session, vm_ref):
1483 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1485 def VM_destroy(self, session, vm_ref):
1486 return XendTask.log_progress(0, 100, do_vm_func,
1487 "domain_delete", vm_ref)
1489 def VM_hard_reboot(self, session, vm_ref):
1490 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1492 def VM_hard_shutdown(self, session, vm_ref):
1493 return XendTask.log_progress(0, 100, do_vm_func,
1494 "domain_destroy", vm_ref)
1495 def VM_pause(self, session, vm_ref):
1496 return XendTask.log_progress(0, 100, do_vm_func,
1497 "domain_pause", vm_ref)
1499 def VM_resume(self, session, vm_ref, start_paused):
1500 return XendTask.log_progress(0, 100, do_vm_func,
1501 "domain_resume", vm_ref,
1502 start_paused = start_paused)
1504 def VM_start(self, session, vm_ref, start_paused):
1505 try:
1506 return XendTask.log_progress(0, 100, do_vm_func,
1507 "domain_start", vm_ref,
1508 start_paused = start_paused)
1509 except HVMRequired, exn:
1510 return xen_api_error(['VM_HVM_REQUIRED', vm_ref])
1512 def VM_suspend(self, session, vm_ref):
1513 return XendTask.log_progress(0, 100, do_vm_func,
1514 "domain_suspend", vm_ref)
1516 def VM_unpause(self, session, vm_ref):
1517 return XendTask.log_progress(0, 100, do_vm_func,
1518 "domain_unpause", vm_ref)
1520 def VM_send_sysrq(self, _, vm_ref, req):
1521 xeninfo = XendDomain.instance().get_vm_by_uuid(vm_ref)
1522 if xeninfo.state != XEN_API_VM_POWER_STATE_RUNNING:
1523 return xen_api_error(
1524 ['VM_BAD_POWER_STATE', vm_ref,
1525 XendDomain.POWER_STATE_NAMES[XEN_API_VM_POWER_STATE_RUNNING],
1526 XendDomain.POWER_STATE_NAMES[xeninfo.state]])
1527 xeninfo.send_sysrq(req)
1528 return xen_api_success_void()
1531 # Xen API: Class VM_metrics
1532 # ----------------------------------------------------------------
1534 VM_metrics_attr_ro = ['memory_actual',
1535 'vcpus_number',
1536 'vcpus_utilisation']
1537 VM_metrics_attr_rw = []
1538 VM_metrics_methods = []
1540 def _VM_metrics_get(self, ref):
1541 return XendVMMetrics.get_by_uuid(ref)
1543 def VM_metrics_get_all(self, _):
1544 return xen_api_success(XendVMMetrics.get_all())
1546 def VM_metrics_get_record(self, _, ref):
1547 return xen_api_success(self._VM_metrics_get(ref).get_record())
1549 def VM_metrics_get_memory_actual(self, _, ref):
1550 return xen_api_success(self._VM_metrics_get(ref).get_memory_actual())
1552 def VM_metrics_get_vcpus_number(self, _, ref):
1553 return xen_api_success(self._VM_metrics_get(ref).get_vcpus_number())
1555 def VM_metrics_get_vcpus_utilisation(self, _, ref):
1556 return xen_api_success(self._VM_metrics_get(ref).get_vcpus_utilisation())
1558 # Xen API: Class VBD
1559 # ----------------------------------------------------------------
1561 VBD_attr_ro = ['metrics',
1562 'runtime_properties']
1563 VBD_attr_rw = ['VM',
1564 'VDI',
1565 'device',
1566 'bootable',
1567 'mode',
1568 'type']
1570 VBD_attr_inst = VBD_attr_rw
1572 VBD_methods = [('media_change', None)]
1573 VBD_funcs = [('create', 'VBD')]
1575 # object methods
1576 def VBD_get_record(self, session, vbd_ref):
1577 xendom = XendDomain.instance()
1578 vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1579 if not vm:
1580 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1581 cfg = vm.get_dev_xenapi_config('vbd', vbd_ref)
1582 if not cfg:
1583 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1585 valid_vbd_keys = self.VBD_attr_ro + self.VBD_attr_rw + \
1586 self.Base_attr_ro + self.Base_attr_rw
1588 return_cfg = {}
1589 for k in cfg.keys():
1590 if k in valid_vbd_keys:
1591 return_cfg[k] = cfg[k]
1593 return_cfg['metrics'] = vbd_ref
1595 return xen_api_success(return_cfg)
1597 def VBD_media_change(self, session, vbd_ref, vdi_ref):
1598 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1600 # class methods
1601 def VBD_create(self, session, vbd_struct):
1602 xendom = XendDomain.instance()
1603 xennode = XendNode.instance()
1605 if not xendom.is_valid_vm(vbd_struct['VM']):
1606 return xen_api_error(['HANDLE_INVALID', 'VM', vbd_struct['VM']])
1608 dom = xendom.get_vm_by_uuid(vbd_struct['VM'])
1609 vdi = xennode.get_vdi_by_uuid(vbd_struct['VDI'])
1610 if not vdi:
1611 return xen_api_error(['HANDLE_INVALID', 'VDI', vdi_ref])
1613 # new VBD via VDI/SR
1614 vdi_image = vdi.get_location()
1616 try:
1617 vbd_ref = XendTask.log_progress(0, 100,
1618 dom.create_vbd,
1619 vbd_struct, vdi_image)
1620 except XendError, e:
1621 log.exception("Error in VBD_create")
1622 return xen_api_error(['INTERNAL_ERROR', str(e)])
1624 vdi.addVBD(vbd_ref)
1626 xendom.managed_config_save(dom)
1627 return xen_api_success(vbd_ref)
1630 def VBD_destroy(self, session, vbd_ref):
1631 xendom = XendDomain.instance()
1632 vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1633 if not vm:
1634 return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
1636 vdi_ref = XendDomain.instance()\
1637 .get_dev_property_by_uuid('vbd', vbd_ref, "VDI")
1638 vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
1640 XendTask.log_progress(0, 100, vm.destroy_vbd, vbd_ref)
1642 vdi.removeVBD(vbd_ref)
1644 return xen_api_success_void()
1646 def _VBD_get(self, vbd_ref, prop):
1647 return xen_api_success(
1648 XendDomain.instance().get_dev_property_by_uuid(
1649 'vbd', vbd_ref, prop))
1651 # attributes (ro)
1652 def VBD_get_metrics(self, _, vbd_ref):
1653 return xen_api_success(vbd_ref)
1655 def VBD_get_runtime_properties(self, _, vbd_ref):
1656 xendom = XendDomain.instance()
1657 dominfo = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1658 device = dominfo.get_dev_config_by_uuid('vbd', vbd_ref)
1659 devid = int(device['id'])
1660 device_sxps = dominfo.getDeviceSxprs('vbd')
1662 log.debug("VBD_get_runtime_properties devid: %i device_sxps: %s",
1663 devid, device_sxps)
1665 device_dicts = [dict(device_sxp[1][1:]) for device_sxp in device_sxps]
1667 device_dict = [device_dict
1668 for device_dict in device_dicts
1669 if int(device_dict['virtual-device']) == devid][0]
1671 log.debug("VBD_get_runtime_properties device_dict: %s", device_dict)
1673 return xen_api_success(device_dict)
1675 # attributes (rw)
1676 def VBD_get_VM(self, session, vbd_ref):
1677 return self._VBD_get(vbd_ref, 'VM')
1679 def VBD_get_VDI(self, session, vbd_ref):
1680 return self._VBD_get(vbd_ref, 'VDI')
1682 def VBD_get_device(self, session, vbd_ref):
1683 return self._VBD_get(vbd_ref, 'device')
1685 def VBD_get_bootable(self, session, vbd_ref):
1686 return self._VBD_get(vbd_ref, 'bootable')
1688 def VBD_get_mode(self, session, vbd_ref):
1689 return self._VBD_get(vbd_ref, 'mode')
1691 def VBD_get_type(self, session, vbd_ref):
1692 return self._VBD_get(vbd_ref, 'type')
1694 def VBD_set_bootable(self, session, vbd_ref, bootable):
1695 bootable = bool(bootable)
1696 xd = XendDomain.instance()
1697 vm = xd.get_vm_with_dev_uuid('vbd', vbd_ref)
1698 vm.set_dev_property('vbd', vbd_ref, 'bootable', bootable)
1699 xd.managed_config_save(vm)
1700 return xen_api_success_void()
1702 def VBD_get_all(self, session):
1703 xendom = XendDomain.instance()
1704 vbds = [d.get_vbds() for d in XendDomain.instance().list('all')]
1705 vbds = reduce(lambda x, y: x + y, vbds)
1706 return xen_api_success(vbds)
1709 # Xen API: Class VBD_metrics
1710 # ----------------------------------------------------------------
1712 VBD_metrics_attr_ro = ['io_read_kbs',
1713 'io_write_kbs']
1714 VBD_metrics_attr_rw = []
1715 VBD_methods = []
1717 def VBD_metrics_get_record(self, _, ref):
1718 vm = XendDomain.instance().get_vm_with_dev_uuid('vbd', ref)
1719 if not vm:
1720 return xen_api_error(['HANDLE_INVALID', 'VBD_metrics', ref])
1721 return xen_api_success(
1722 { 'io_read_kbs' : vm.get_dev_property('vbd', ref, 'io_read_kbs'),
1723 'io_write_kbs' : vm.get_dev_property('vbd', ref, 'io_write_kbs') })
1725 def VBD_metrics_get_io_read_kbs(self, _, ref):
1726 return self._VBD_get(ref, 'io_read_kbs')
1728 def VBD_metrics_get_io_write_kbs(self, session, ref):
1729 return self._VBD_get(ref, 'io_write_kbs')
1732 # Xen API: Class VIF
1733 # ----------------------------------------------------------------
1735 VIF_attr_ro = ['metrics']
1736 VIF_attr_rw = ['device',
1737 'network',
1738 'VM',
1739 'MAC',
1740 'MTU']
1742 VIF_attr_inst = VIF_attr_rw
1744 VIF_funcs = [('create', 'VIF')]
1747 # object methods
1748 def VIF_get_record(self, session, vif_ref):
1749 xendom = XendDomain.instance()
1750 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
1751 if not vm:
1752 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
1753 cfg = vm.get_dev_xenapi_config('vif', vif_ref)
1754 if not cfg:
1755 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
1757 valid_vif_keys = self.VIF_attr_ro + self.VIF_attr_rw + \
1758 self.Base_attr_ro + self.Base_attr_rw
1760 return_cfg = {}
1761 for k in cfg.keys():
1762 if k in valid_vif_keys:
1763 return_cfg[k] = cfg[k]
1765 return_cfg['metrics'] = vif_ref
1767 return xen_api_success(return_cfg)
1769 # class methods
1770 def VIF_create(self, session, vif_struct):
1771 xendom = XendDomain.instance()
1772 if xendom.is_valid_vm(vif_struct['VM']):
1773 dom = xendom.get_vm_by_uuid(vif_struct['VM'])
1774 try:
1775 vif_ref = dom.create_vif(vif_struct)
1776 xendom.managed_config_save(dom)
1777 return xen_api_success(vif_ref)
1778 except XendError:
1779 return xen_api_error(XEND_ERROR_TODO)
1780 else:
1781 return xen_api_error(['HANDLE_INVALID', 'VM', vif_struct['VM']])
1784 def VIF_destroy(self, session, vif_ref):
1785 xendom = XendDomain.instance()
1786 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
1787 if not vm:
1788 return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
1790 vm.destroy_vif(vif_ref)
1791 return xen_api_success_void()
1793 def _VIF_get(self, ref, prop):
1794 return xen_api_success(
1795 XendDomain.instance().get_dev_property_by_uuid('vif', ref, prop))
1797 # getters/setters
1798 def VIF_get_metrics(self, _, vif_ref):
1799 return xen_api_success(vif_ref)
1801 def VIF_get_VM(self, session, vif_ref):
1802 xendom = XendDomain.instance()
1803 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
1804 return xen_api_success(vm.get_uuid())
1806 def VIF_get_MTU(self, session, vif_ref):
1807 return self._VIF_get(vif_ref, 'MTU')
1809 def VIF_get_MAC(self, session, vif_ref):
1810 return self._VIF_get(vif_ref, 'MAC')
1812 def VIF_get_device(self, session, vif_ref):
1813 return self._VIF_get(vif_ref, 'device')
1815 def VIF_get_all(self, session):
1816 xendom = XendDomain.instance()
1817 vifs = [d.get_vifs() for d in XendDomain.instance().list('all')]
1818 vifs = reduce(lambda x, y: x + y, vifs)
1819 return xen_api_success(vifs)
1822 # Xen API: Class VIF_metrics
1823 # ----------------------------------------------------------------
1825 VIF_metrics_attr_ro = ['io_read_kbs',
1826 'io_write_kbs']
1827 VIF_metrics_attr_rw = []
1828 VIF_methods = []
1830 def VIF_metrics_get_record(self, _, ref):
1831 vm = XendDomain.instance().get_vm_with_dev_uuid('vif', ref)
1832 if not vm:
1833 return xen_api_error(['HANDLE_INVALID', 'VIF_metrics', ref])
1834 return xen_api_success(
1835 { 'io_read_kbs' : vm.get_dev_property('vif', ref, 'io_read_kbs'),
1836 'io_write_kbs' : vm.get_dev_property('vif', ref, 'io_write_kbs') })
1838 def VIF_metrics_get_io_read_kbs(self, _, ref):
1839 return self._VIF_get(ref, 'io_read_kbs')
1841 def VIF_metrics_get_io_write_kbs(self, session, ref):
1842 return self._VIF_get(ref, 'io_write_kbs')
1845 # Xen API: Class VDI
1846 # ----------------------------------------------------------------
1847 VDI_attr_ro = ['SR',
1848 'VBDs',
1849 'physical_utilisation',
1850 'type']
1851 VDI_attr_rw = ['name_label',
1852 'name_description',
1853 'virtual_size',
1854 'sharable',
1855 'read_only',
1856 'other_config']
1857 VDI_attr_inst = VDI_attr_ro + VDI_attr_rw
1859 VDI_methods = [('snapshot', 'VDI')]
1860 VDI_funcs = [('create', 'VDI'),
1861 ('get_by_name_label', 'Set(VDI)')]
1863 def _get_VDI(self, ref):
1864 return XendNode.instance().get_vdi_by_uuid(ref)
1866 def VDI_get_VBDs(self, session, vdi_ref):
1867 vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
1868 return xen_api_success(vdi.getVBDs())
1870 def VDI_get_physical_utilisation(self, session, vdi_ref):
1871 return xen_api_success(self._get_VDI(vdi_ref).
1872 get_physical_utilisation())
1874 def VDI_get_type(self, session, vdi_ref):
1875 return xen_api_success(self._get_VDI(vdi_ref).type)
1877 def VDI_get_name_label(self, session, vdi_ref):
1878 return xen_api_success(self._get_VDI(vdi_ref).name_label)
1880 def VDI_get_name_description(self, session, vdi_ref):
1881 return xen_api_success(self._get_VDI(vdi_ref).name_description)
1883 def VDI_get_SR(self, session, vdi_ref):
1884 return xen_api_success(self._get_VDI(vdi_ref).sr_uuid)
1886 def VDI_get_virtual_size(self, session, vdi_ref):
1887 return xen_api_success(self._get_VDI(vdi_ref).virtual_size)
1889 def VDI_get_sharable(self, session, vdi_ref):
1890 return xen_api_success(self._get_VDI(vdi_ref).sharable)
1892 def VDI_get_read_only(self, session, vdi_ref):
1893 return xen_api_success(self._get_VDI(vdi_ref).read_only)
1895 def VDI_set_name_label(self, session, vdi_ref, value):
1896 self._get_VDI(vdi_ref).name_label = value
1897 return xen_api_success_void()
1899 def VDI_set_name_description(self, session, vdi_ref, value):
1900 self._get_VDI(vdi_ref).name_description = value
1901 return xen_api_success_void()
1903 def VDI_set_virtual_size(self, session, vdi_ref, value):
1904 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1906 def VDI_set_sharable(self, session, vdi_ref, value):
1907 self._get_VDI(vdi_ref).sharable = bool(value)
1908 return xen_api_success_void()
1910 def VDI_set_read_only(self, session, vdi_ref, value):
1911 self._get_VDI(vdi_ref).read_only = bool(value)
1912 return xen_api_success_void()
1914 def VDI_get_other_config(self, session, vdi_ref):
1915 return xen_api_success(
1916 self._get_VDI(vdi_ref).other_config)
1918 def VDI_set_other_config(self, session, vdi_ref, other_config):
1919 self._get_VDI(vdi_ref).other_config = other_config
1920 return xen_api_success_void()
1922 # Object Methods
1923 def VDI_snapshot(self, session, vdi_ref):
1924 return xen_api_todo()
1926 def VDI_destroy(self, session, vdi_ref):
1927 sr = XendNode.instance().get_sr_containing_vdi(vdi_ref)
1928 sr.destroy_vdi(vdi_ref)
1929 return xen_api_success_void()
1931 def VDI_get_record(self, session, vdi_ref):
1932 image = XendNode.instance().get_vdi_by_uuid(vdi_ref)
1933 return xen_api_success({
1934 'uuid': vdi_ref,
1935 'name_label': image.name_label,
1936 'name_description': image.name_description,
1937 'SR': image.sr_uuid,
1938 'VBDs': image.getVBDs(),
1939 'virtual_size': image.virtual_size,
1940 'physical_utilisation': image.physical_utilisation,
1941 'type': image.type,
1942 'sharable': image.sharable,
1943 'read_only': image.read_only,
1944 'other_config': image.other_config
1945 })
1947 # Class Functions
1948 def VDI_create(self, session, vdi_struct):
1949 sr_ref = vdi_struct.get('SR')
1950 xennode = XendNode.instance()
1951 if not xennode.is_valid_sr(sr_ref):
1952 return xen_api_error(['HANDLE_INVALID', 'SR', sr_ref])
1954 vdi_uuid = xennode.srs[sr_ref].create_vdi(vdi_struct)
1955 return xen_api_success(vdi_uuid)
1957 def VDI_get_all(self, session):
1958 xennode = XendNode.instance()
1959 vdis = [sr.get_vdis() for sr in xennode.srs.values()]
1960 return xen_api_success(reduce(lambda x, y: x + y, vdis))
1962 def VDI_get_by_name_label(self, session, name):
1963 xennode = XendNode.instance()
1964 return xen_api_success(xennode.get_vdi_by_name_label(name))
1967 # Xen API: Class VTPM
1968 # ----------------------------------------------------------------
1970 VTPM_attr_rw = [ ]
1971 VTPM_attr_ro = ['VM',
1972 'backend']
1974 VTPM_attr_inst = VTPM_attr_rw
1976 VTPM_funcs = [('create', 'VTPM')]
1978 # object methods
1979 def VTPM_get_record(self, session, vtpm_ref):
1980 xendom = XendDomain.instance()
1981 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
1982 if not vm:
1983 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
1984 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
1985 if not cfg:
1986 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
1987 valid_vtpm_keys = self.VTPM_attr_ro + self.VTPM_attr_rw + \
1988 self.Base_attr_ro + self.Base_attr_rw
1989 return_cfg = {}
1990 for k in cfg.keys():
1991 if k in valid_vtpm_keys:
1992 return_cfg[k] = cfg[k]
1994 return xen_api_success(return_cfg)
1996 # Class Functions
1997 def VTPM_get_backend(self, session, vtpm_ref):
1998 xendom = XendDomain.instance()
1999 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
2000 if not vm:
2001 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
2002 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
2003 if not cfg:
2004 return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
2005 if not cfg.has_key('backend'):
2006 return xen_api_error(['VTPM backend not set'])
2007 return xen_api_success(cfg['backend'])
2009 def VTPM_get_VM(self, session, vtpm_ref):
2010 xendom = XendDomain.instance()
2011 return xen_api_success(xendom.get_dev_property_by_uuid('vtpm',
2012 vtpm_ref, 'VM'))
2014 def VTPM_destroy(self, session, vtpm_ref):
2015 xendom = XendDomain.instance()
2016 dom = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
2017 if dom:
2018 if dom.state != XEN_API_VM_POWER_STATE_HALTED:
2019 vm_ref = dom.get_dev_property('vtpm', vtpm_ref, 'VM')
2020 return xen_api_error(['VM_BAD_POWER_STATE', vm_ref,
2021 XendDomain.POWER_STATE_NAMES[XEN_API_VM_POWER_STATE_HALTED],
2022 XendDomain.POWER_STATE_NAMES[dom.state]])
2023 from xen.xend.server import tpmif
2024 tpmif.destroy_vtpmstate(dom.getName())
2025 return xen_api_success_void()
2026 else:
2027 return xen_api_error(['HANDLE_INVALID', 'VM', vtpm_struct['VM']])
2029 # class methods
2030 def VTPM_create(self, session, vtpm_struct):
2031 xendom = XendDomain.instance()
2032 if xendom.is_valid_vm(vtpm_struct['VM']):
2033 dom = xendom.get_vm_by_uuid(vtpm_struct['VM'])
2034 try:
2035 vtpm_ref = dom.create_vtpm(vtpm_struct)
2036 xendom.managed_config_save(dom)
2037 return xen_api_success(vtpm_ref)
2038 except XendError:
2039 return xen_api_error(XEND_ERROR_TODO)
2040 else:
2041 return xen_api_error(['HANDLE_INVALID', 'VM', vtpm_struct['VM']])
2043 def VTPM_get_all(self, session):
2044 xendom = XendDomain.instance()
2045 vtpms = [d.get_vtpms() for d in XendDomain.instance().list('all')]
2046 vtpms = reduce(lambda x, y: x + y, vtpms)
2047 return xen_api_success(vtpms)
2049 # Xen API: Class console
2050 # ----------------------------------------------------------------
2053 console_attr_ro = ['location', 'protocol', 'VM']
2054 console_attr_rw = ['other_config']
2055 console_funcs = [('create', 'console')]
2057 def console_get_all(self, session):
2058 xendom = XendDomain.instance()
2059 cons = [d.get_consoles() for d in XendDomain.instance().list('all')]
2060 cons = reduce(lambda x, y: x + y, cons)
2061 return xen_api_success(cons)
2063 def console_get_location(self, session, console_ref):
2064 return xen_api_success(xendom.get_dev_property_by_uuid('console',
2065 console_ref,
2066 'location'))
2068 def console_get_protocol(self, session, console_ref):
2069 return xen_api_success(xendom.get_dev_property_by_uuid('console',
2070 console_ref,
2071 'protocol'))
2073 def console_get_VM(self, session, console_ref):
2074 xendom = XendDomain.instance()
2075 vm = xendom.get_vm_with_dev_uuid('console', console_ref)
2076 return xen_api_success(vm.get_uuid())
2078 # object methods
2079 def console_get_record(self, session, console_ref):
2080 xendom = XendDomain.instance()
2081 vm = xendom.get_vm_with_dev_uuid('console', console_ref)
2082 if not vm:
2083 return xen_api_error(['HANDLE_INVALID', 'console', console_ref])
2084 cfg = vm.get_dev_xenapi_config('console', console_ref)
2085 if not cfg:
2086 return xen_api_error(['HANDLE_INVALID', 'console', console_ref])
2088 valid_console_keys = self.console_attr_ro + self.console_attr_rw + \
2089 self.Base_attr_ro + self.Base_attr_rw
2091 return_cfg = {}
2092 for k in cfg.keys():
2093 if k in valid_console_keys:
2094 return_cfg[k] = cfg[k]
2096 return xen_api_success(return_cfg)
2098 def console_create(self, session, console_struct):
2099 xendom = XendDomain.instance()
2100 if not xendom.is_valid_vm(console_struct['VM']):
2101 return xen_api_error(['HANDLE_INVALID', 'VM',
2102 console_struct['VM']])
2104 dom = xendom.get_vm_by_uuid(console_struct['VM'])
2105 try:
2106 if 'protocol' not in console_struct:
2107 return xen_api_error(['CONSOLE_PROTOCOL_INVALID',
2108 'No protocol specified'])
2110 console_ref = dom.create_console(console_struct)
2111 xendom.managed_config_save(dom)
2112 return xen_api_success(console_ref)
2113 except XendError, e:
2114 return xen_api_error([XEND_ERROR_TODO, str(e)])
2116 # Xen API: Class SR
2117 # ----------------------------------------------------------------
2118 SR_attr_ro = ['VDIs',
2119 'virtual_allocation',
2120 'physical_utilisation',
2121 'physical_size',
2122 'type',
2123 'location']
2125 SR_attr_rw = ['name_label',
2126 'name_description']
2128 SR_attr_inst = ['physical_size',
2129 'type',
2130 'location',
2131 'name_label',
2132 'name_description']
2134 SR_methods = [('clone', 'SR')]
2135 SR_funcs = [('get_by_name_label', 'Set(SR)'),
2136 ('get_by_uuid', 'SR')]
2138 # Class Functions
2139 def SR_get_all(self, session):
2140 return xen_api_success(XendNode.instance().get_all_sr_uuid())
2142 def SR_get_by_name_label(self, session, label):
2143 return xen_api_success(XendNode.instance().get_sr_by_name(label))
2145 def SR_create(self, session):
2146 return xen_api_error(XEND_ERROR_UNSUPPORTED)
2148 # Class Methods
2149 def SR_clone(self, session, sr_ref):
2150 return xen_api_error(XEND_ERROR_UNSUPPORTED)
2152 def SR_destroy(self, session, sr_ref):
2153 return xen_api_error(XEND_ERROR_UNSUPPORTED)
2155 def SR_get_record(self, session, sr_ref):
2156 sr = XendNode.instance().get_sr(sr_ref)
2157 if sr:
2158 return xen_api_success(sr.get_record())
2159 return xen_api_error(['HANDLE_INVALID', 'SR', sr_ref])
2161 # Attribute acceess
2163 def _get_SR_func(self, sr_ref, func):
2164 return xen_api_success(getattr(XendNode.instance().get_sr(sr_ref),
2165 func)())
2167 def _get_SR_attr(self, sr_ref, attr):
2168 return xen_api_success(getattr(XendNode.instance().get_sr(sr_ref),
2169 attr))
2171 def SR_get_VDIs(self, _, ref):
2172 return self._get_SR_func(ref, 'list_images')
2174 def SR_get_virtual_allocation(self, _, ref):
2175 return self._get_SR_func(ref, 'virtual_allocation')
2177 def SR_get_physical_utilisation(self, _, ref):
2178 return self._get_SR_func(ref, 'physical_utilisation')
2180 def SR_get_physical_size(self, _, ref):
2181 return self._get_SR_func(ref, 'physical_size')
2183 def SR_get_type(self, _, ref):
2184 return self._get_SR_attr(ref, 'type')
2186 def SR_get_location(self, _, ref):
2187 return self._get_SR_attr(ref, 'location')
2189 def SR_get_name_label(self, _, ref):
2190 return self._get_SR_attr(ref, 'name_label')
2192 def SR_get_name_description(self, _, ref):
2193 return self._get_SR_attr(ref, 'name_description')
2195 def SR_set_name_label(self, session, sr_ref, value):
2196 sr = XendNode.instance.get_sr(sr_ref)
2197 if sr:
2198 sr.name_label = value
2199 XendNode.instance().save()
2200 return xen_api_success_void()
2202 def SR_set_name_description(self, session, sr_ref, value):
2203 sr = XendNode.instance.get_sr(sr_ref)
2204 if sr:
2205 sr.name_description = value
2206 XendNode.instance().save()
2207 return xen_api_success_void()
2210 # Xen API: Class debug
2211 # ----------------------------------------------------------------
2213 debug_methods = [('destroy', None),
2214 ('get_record', 'debug')]
2215 debug_funcs = [('wait', None),
2216 ('return_failure', None)]
2218 def debug_wait(self, session, wait_secs):
2219 import time
2220 prog_units = 100/float(wait_secs)
2221 for i in range(int(wait_secs)):
2222 XendTask.log_progress(prog_units * i, prog_units * (i + 1),
2223 time.sleep, 1)
2224 return xen_api_success_void()
2227 def debug_return_failure(self, session):
2228 return xen_api_error(['DEBUG_FAIL', session])
2230 def debug_create(self, session):
2231 debug_uuid = uuid.createString()
2232 self._debug[debug_uuid] = None
2233 return xen_api_success(debug_uuid)
2235 def debug_destroy(self, session, debug_ref):
2236 del self._debug[debug_ref]
2237 return xen_api_success_void()
2239 def debug_get_record(self, session, debug_ref):
2240 return xen_api_success({'uuid': debug_ref})
2243 def list_all_methods(self, _):
2244 def _funcs():
2245 return [getattr(XendAPI, x) for x in XendAPI.__dict__]
2247 return xen_api_success([x.api for x in _funcs()
2248 if hasattr(x, 'api')])
2249 list_all_methods.api = '_UNSUPPORTED_list_all_methods'
2252 class XendAPIAsyncProxy:
2253 """ A redirector for Async.Class.function calls to XendAPI
2254 but wraps the call for use with the XendTaskManager.
2256 @ivar xenapi: Xen API instance
2257 @ivar method_map: Mapping from XMLRPC method name to callable objects.
2258 """
2260 method_prefix = 'Async.'
2262 def __init__(self, xenapi):
2263 """Initialises the Async Proxy by making a map of all
2264 implemented Xen API methods for use with XendTaskManager.
2266 @param xenapi: XendAPI instance
2267 """
2268 self.xenapi = xenapi
2269 self.method_map = {}
2270 for method_name in dir(self.xenapi):
2271 method = getattr(self.xenapi, method_name)
2272 if method_name[0] != '_' and hasattr(method, 'async') \
2273 and method.async == True:
2274 self.method_map[method.api] = method
2276 def _dispatch(self, method, args):
2277 """Overridden method so that SimpleXMLRPCServer will
2278 resolve methods through this method rather than through
2279 inspection.
2281 @param method: marshalled method name from XMLRPC.
2282 @param args: marshalled arguments from XMLRPC.
2283 """
2285 # Only deal with method names that start with "Async."
2286 if not method.startswith(self.method_prefix):
2287 return xen_api_error(['MESSAGE_METHOD_UNKNOWN', method])
2289 # Lookup synchronous version of the method
2290 synchronous_method_name = method[len(self.method_prefix):]
2291 if synchronous_method_name not in self.method_map:
2292 return xen_api_error(['MESSAGE_METHOD_UNKNOWN', method])
2294 method = self.method_map[synchronous_method_name]
2296 # Check that we've got enough arguments before issuing a task ID.
2297 needed = argcounts[method.api]
2298 if len(args) != needed:
2299 return xen_api_error(['MESSAGE_PARAMETER_COUNT_MISMATCH',
2300 self.method_prefix + method.api, needed,
2301 len(args)])
2303 # Validate the session before proceeding
2304 session = args[0]
2305 if not auth_manager().is_session_valid(session):
2306 return xen_api_error(['SESSION_INVALID', session])
2308 # create and execute the task, and return task_uuid
2309 return_type = getattr(method, 'return_type', None)
2310 task_uuid = XendTaskManager.create_task(method, args,
2311 synchronous_method_name,
2312 return_type,
2313 synchronous_method_name,
2314 session)
2315 return xen_api_success(task_uuid)
2318 # Auto generate some stubs based on XendAPI introspection
2320 if __name__ == "__main__":
2321 def output(line):
2322 print ' ' + line
2324 classes = ['VDI', 'SR']
2325 for cls in classes:
2326 ro_attrs = getattr(XendAPI, '%s_attr_ro' % cls, [])
2327 rw_attrs = getattr(XendAPI, '%s_attr_rw' % cls, [])
2328 methods = getattr(XendAPI, '%s_methods' % cls, [])
2329 funcs = getattr(XendAPI, '%s_funcs' % cls, [])
2331 ref = '%s_ref' % cls
2333 for attr_name in ro_attrs + rw_attrs + XendAPI.Base_attr_ro:
2334 getter_name = '%s_get_%s' % (cls, attr_name)
2335 output('def %s(self, session, %s):' % (getter_name, ref))
2336 output(' return xen_api_todo()')
2338 for attr_name in rw_attrs + XendAPI.Base_attr_rw:
2339 setter_name = '%s_set_%s' % (cls, attr_name)
2340 output('def %s(self, session, %s, value):' % (setter_name, ref))
2341 output(' return xen_api_todo()')
2343 for method_name in methods + XendAPI.Base_methods:
2344 method_full_name = '%s_%s' % (cls,method_name)
2345 output('def %s(self, session, %s):' % (method_full_name, ref))
2346 output(' return xen_api_todo()')
2348 for func_name in funcs + XendAPI.Base_funcs:
2349 func_full_name = '%s_%s' % (cls, func_name)
2350 output('def %s(self, session):' % func_full_name)
2351 output(' return xen_api_todo()')