debuggers.hg

view tools/python/xen/xend/XendAPI.py @ 13654:b111908dd70b

[XEND] Preliminary console support in Xen API

Made serial/vnc consoles a 'fake' device so that we can take advantage
of storing state information in xenstore.

Signed-off-by: Alastair Tse <atse@xensource.com>
author Alastair Tse <atse@xensource.com>
date Thu Jan 25 18:54:25 2007 +0000 (2007-01-25)
parents a94363b85e19
children b97780b7080d
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 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
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, errcode, 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([errcode, 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_HANDLE_INVALID', func, *args, **kwargs)
161 def valid_host_cpu(func):
162 """Decorator to verify if host_cpu_ref is valid before calling method.
164 @param func: function with params: (self, session, host_cpu_ref, ...)
165 @rtype: callable object
166 """
167 return lambda *args, **kwargs: \
168 _check_ref(XendNode.instance().is_valid_cpu,
169 'HOST_CPU_HANDLE_INVALID', func, *args, **kwargs)
171 def valid_vm(func):
172 """Decorator to verify if vm_ref is valid before calling method.
174 @param func: function with params: (self, session, vm_ref, ...)
175 @rtype: callable object
176 """
177 return lambda *args, **kwargs: \
178 _check_ref(XendDomain.instance().is_valid_vm,
179 'VM_HANDLE_INVALID', func, *args, **kwargs)
181 def valid_network(func):
182 """Decorator to verify if network_ref is valid before calling method.
184 @param func: function with params: (self, session, network_ref, ...)
185 @rtype: callable object
186 """
187 return lambda *args, **kwargs: \
188 _check_ref(XendNode.instance().is_valid_network,
189 'NETWORK_HANDLE_INVALID', func, *args, **kwargs)
191 def valid_vbd(func):
192 """Decorator to verify if vbd_ref is valid before calling method.
194 @param func: function with params: (self, session, vbd_ref, ...)
195 @rtype: callable object
196 """
197 return lambda *args, **kwargs: \
198 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vbd', r),
199 'VBD_HANDLE_INVALID', func, *args, **kwargs)
201 def valid_vif(func):
202 """Decorator to verify if vif_ref is valid before calling method.
204 @param func: function with params: (self, session, vif_ref, ...)
205 @rtype: callable object
206 """
207 return lambda *args, **kwargs: \
208 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vif', r),
209 'VIF_HANDLE_INVALID', func, *args, **kwargs)
211 def valid_vdi(func):
212 """Decorator to verify if vdi_ref is valid before calling method.
214 @param func: function with params: (self, session, vdi_ref, ...)
215 @rtype: callable object
216 """
217 return lambda *args, **kwargs: \
218 _check_ref(XendNode.instance().is_valid_vdi,
219 'VDI_HANDLE_INVALID', func, *args, **kwargs)
221 def valid_vtpm(func):
222 """Decorator to verify if vtpm_ref is valid before calling method.
224 @param func: function with params: (self, session, vtpm_ref, ...)
225 @rtype: callable object
226 """
227 return lambda *args, **kwargs: \
228 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vtpm', r),
229 'VTPM_HANDLE_INVALID', func, *args, **kwargs)
232 def valid_console(func):
233 """Decorator to verify if console_ref is valid before calling method.
235 @param func: function with params: (self, session, console_ref, ...)
236 @rtype: callable object
237 """
238 return lambda *args, **kwargs: \
239 _check_ref(lambda r: XendDomain.instance().is_valid_dev('console',
240 r),
241 'CONSOLE_HANDLE_INVALID', func, *args, **kwargs)
243 def valid_sr(func):
244 """Decorator to verify if sr_ref is valid before calling method.
246 @param func: function with params: (self, session, sr_ref, ...)
247 @rtype: callable object
248 """
249 return lambda *args, **kwargs: \
250 _check_ref(lambda r: XendNode.instance().is_valid_sr,
251 'SR_HANDLE_INVALID', func, *args, **kwargs)
253 def valid_pif(func):
254 """Decorator to verify if pif_ref is valid before calling
255 method.
257 @param func: function with params: (self, session, pif_ref)
258 @rtype: callable object
259 """
260 return lambda *args, **kwargs: \
261 _check_ref(lambda r: r in XendNode.instance().pifs,
262 'PIF_HANDLE_INVALID', func, *args, **kwargs)
264 def valid_task(func):
265 """Decorator to verify if task_ref is valid before calling
266 method.
268 @param func: function with params: (self, session, task_ref)
269 @rtype: callable object
270 """
271 return lambda *args, **kwargs: \
272 _check_ref(XendTaskManager.get_task,
273 'TASK_HANDLE_INVALID', func, *args, **kwargs)
275 def valid_debug(func):
276 """Decorator to verify if task_ref is valid before calling
277 method.
279 @param func: function with params: (self, session, task_ref)
280 @rtype: callable object
281 """
282 return lambda *args, **kwargs: \
283 _check_ref(lambda r: r in XendAPI._debug,
284 'TASK_HANDLE_INVALID', func, *args, **kwargs)
286 # -----------------------------
287 # Bridge to Legacy XM API calls
288 # -----------------------------
290 def do_vm_func(fn_name, vm_ref, *args, **kwargs):
291 """Helper wrapper func to abstract away from repetitive code.
293 @param fn_name: function name for XendDomain instance
294 @type fn_name: string
295 @param vm_ref: vm_ref
296 @type vm_ref: string
297 @param *args: more arguments
298 @type *args: tuple
299 """
300 try:
301 xendom = XendDomain.instance()
302 fn = getattr(xendom, fn_name)
303 xendom.do_legacy_api_with_uuid(fn, vm_ref, *args, **kwargs)
304 return xen_api_success_void()
305 except VMBadState, exn:
306 return xen_api_error(['VM_BAD_POWER_STATE', vm_ref, exn.expected,
307 exn.actual])
310 class XendAPI(object):
311 """Implementation of the Xen-API in Xend. Expects to be
312 used via XMLRPCServer.
314 All methods that need a valid session are marked with
315 a L{session_required} decorator that will
316 transparently perform the required session authentication.
318 We need to support Python <2.4, so we use the old decorator syntax.
320 All XMLRPC accessible methods require an 'api' attribute and
321 is set to the XMLRPC function name which the method implements.
322 """
324 __decorated__ = False
325 __init_lock__ = threading.Lock()
326 _debug = {}
328 def __new__(cls, *args, **kwds):
329 """ Override __new__ to decorate the class only once.
331 Lock to make sure the classes are not decorated twice.
332 """
333 cls.__init_lock__.acquire()
334 try:
335 if not cls.__decorated__:
336 cls._decorate()
337 cls.__decorated__ = True
339 return object.__new__(cls, *args, **kwds)
340 finally:
341 cls.__init_lock__.release()
343 def _decorate(cls):
344 """ Decorate all the object methods to have validators
345 and appropriate function attributes.
347 This should only be executed once for the duration of the
348 server.
349 """
350 global_validators = [session_required, catch_typeerror]
351 classes = {
352 'session' : None,
353 'host' : valid_host,
354 'host_cpu': valid_host_cpu,
355 'network' : valid_network,
356 'VM' : valid_vm,
357 'VBD' : valid_vbd,
358 'VIF' : valid_vif,
359 'VDI' : valid_vdi,
360 'VTPM' : valid_vtpm,
361 'console' : valid_console,
362 'SR' : valid_sr,
363 'PIF' : valid_pif,
364 'task' : valid_task,
365 'debug' : valid_debug,
366 }
368 # Cheat methods
369 # -------------
370 # Methods that have a trivial implementation for all classes.
371 # 1. get_by_uuid == getting by ref, so just return uuid for
372 # all get_by_uuid() methods.
374 for api_cls in classes.keys():
375 get_by_uuid = '%s_get_by_uuid' % api_cls
376 get_uuid = '%s_get_uuid' % api_cls
377 def _get_by_uuid(_1, _2, ref):
378 return xen_api_success(ref)
380 def _get_uuid(_1, _2, ref):
381 return xen_api_success(ref)
383 setattr(cls, get_by_uuid, _get_by_uuid)
384 setattr(cls, get_uuid, _get_uuid)
386 # Wrapping validators around XMLRPC calls
387 # ---------------------------------------
389 for api_cls, validator in classes.items():
390 def doit(n, takes_instance, async_support = False,
391 return_type = None):
392 n_ = n.replace('.', '_')
393 try:
394 f = getattr(cls, n_)
395 argcounts[n] = f.func_code.co_argcount - 1
397 validators = takes_instance and validator and \
398 [validator] or []
400 validators += global_validators
401 for v in validators:
402 f = v(f)
403 f.api = n
404 f.async = async_support
405 if return_type:
406 f.return_type = return_type
408 setattr(cls, n_, f)
409 except AttributeError:
410 log.warn("API call: %s not found" % n)
413 ro_attrs = getattr(cls, '%s_attr_ro' % api_cls, [])
414 rw_attrs = getattr(cls, '%s_attr_rw' % api_cls, [])
415 methods = getattr(cls, '%s_methods' % api_cls, [])
416 funcs = getattr(cls, '%s_funcs' % api_cls, [])
418 # wrap validators around readable class attributes
419 for attr_name in ro_attrs + rw_attrs + cls.Base_attr_ro:
420 doit('%s.get_%s' % (api_cls, attr_name), True,
421 async_support = False)
423 # wrap validators around writable class attrributes
424 for attr_name in rw_attrs + cls.Base_attr_rw:
425 doit('%s.set_%s' % (api_cls, attr_name), True,
426 async_support = False)
428 # wrap validators around methods
429 for method_name, return_type in methods + cls.Base_methods:
430 doit('%s.%s' % (api_cls, method_name), True,
431 async_support = True)
433 # wrap validators around class functions
434 for func_name, return_type in funcs + cls.Base_funcs:
435 doit('%s.%s' % (api_cls, func_name), False, async_support = True,
436 return_type = return_type)
438 _decorate = classmethod(_decorate)
440 def __init__(self, auth):
441 self.auth = auth
443 Base_attr_ro = ['uuid']
444 Base_attr_rw = []
445 Base_methods = [('destroy', None), ('get_record', 'Struct')]
446 Base_funcs = [('get_all', 'Set'), ('get_by_uuid', None)]
448 # Xen API: Class Session
449 # ----------------------------------------------------------------
450 # NOTE: Left unwrapped by __init__
452 session_attr_ro = ['this_host', 'this_user']
453 session_methods = [('logout', None)]
454 # session_funcs = ['login_with_password']
456 def session_login_with_password(self, *args):
457 if len(args) != 2:
458 return xen_api_error(
459 ['MESSAGE_PARAMETER_COUNT_MISMATCH',
460 'session.login_with_password', 2, len(args)])
461 username = args[0]
462 password = args[1]
463 try:
464 session = (self.auth == AUTH_NONE and
465 auth_manager().login_unconditionally(username) or
466 auth_manager().login_with_password(username, password))
467 return xen_api_success(session)
468 except XendError, e:
469 return xen_api_error(['SESSION_AUTHENTICATION_FAILED'])
470 session_login_with_password.api = 'session.login_with_password'
472 # object methods
473 def session_logout(self, session):
474 auth_manager().logout(session)
475 return xen_api_success_void()
476 def session_destroy(self, session):
477 return xen_api_error(XEND_ERROR_UNSUPPORTED)
478 def session_get_record(self, session):
479 record = {'this_host': XendNode.instance().uuid,
480 'this_user': auth_manager().get_user(session)}
481 return xen_api_success(record)
482 def session_get_all(self):
483 return xen_api_error(XEND_ERROR_UNSUPPORTED)
485 # attributes (ro)
486 def session_get_this_host(self, session):
487 return xen_api_success(XendNode.instance().uuid)
488 def session_get_this_user(self, session):
489 user = auth_manager().get_user(session)
490 if user:
491 return xen_api_success(user)
492 return xen_api_error(['SESSION_INVALID', session])
495 # Xen API: Class User
496 # ----------------------------------------------------------------
497 # TODO: NOT IMPLEMENTED YET
499 # Xen API: Class Tasks
500 # ----------------------------------------------------------------
502 task_attr_ro = ['status',
503 'progress',
504 'eta',
505 'type',
506 'result',
507 'error_code',
508 'error_info']
510 task_attr_rw = ['name_label',
511 'name_description']
513 task_funcs = [('get_by_name_label', 'Set(task)')]
515 def task_get_status(self, session, task_ref):
516 task = XendTaskManager.get_task(task_ref)
517 return xen_api_success(task.get_status())
519 def task_get_progress(self, session, task_ref):
520 task = XendTaskManager.get_task(task_ref)
521 return xen_api_success(task.progress)
523 def task_get_eta(self, session, task_ref):
524 task = XendTaskManager.get_task(task_ref)
525 return xen_api_success(task.eta)
527 def task_get_type(self, session, task_ref):
528 task = XendTaskManager.get_task(task_ref)
529 return xen_api_success(task.type)
531 def task_get_result(self, session, task_ref):
532 task = XendTaskManager.get_task(task_ref)
533 return xen_api_success(task.result)
535 def task_get_error_code(self, session, task_ref):
536 task = XendTaskManager.get_task(task_ref)
537 return xen_api_success(task.error_code)
539 def task_get_error_info(self, session, task_ref):
540 task = XendTaskManager.get_task(task_ref)
541 return xen_api_success(task.error_info)
543 def task_get_name_label(self, session, task_ref):
544 task = XendTaskManager.get_task(task_ref)
545 return xen_api_success(task.name_label)
547 def task_get_name_description(self, session, task_ref):
548 task = XendTaskManager.get_task(task_ref)
549 return xen_api_success(task.name_description)
551 def task_set_name_label(self, session, task_ref, label):
552 task = XendTaskManager.get_task(task_ref)
553 task.name_label = label
554 return xen_api_success_void()
556 def task_set_name_description(self, session, task_ref, desc):
557 task = XendTaskManager.get_task(task_ref)
558 task.name_description = desc
559 return xen_api_success_void()
561 def task_get_all(self, session):
562 tasks = XendTaskManager.get_all_tasks()
563 return xen_api_success(tasks)
565 def task_destroy(self, session, task_uuid):
566 XendTaskManager.destroy_task(task_uuid)
567 return xen_api_success_void()
569 def task_get_record(self, session, task_ref):
570 task = XendTaskManager.get_task(task_ref)
571 return xen_api_success(task.get_record())
573 def task_get_by_name_label(self, session, name):
574 return xen_api_success(XendTaskManager.get_task_by_name(name))
576 # Xen API: Class Host
577 # ----------------------------------------------------------------
579 host_attr_ro = ['software_version',
580 'resident_VMs',
581 'host_CPUs']
583 host_attr_rw = ['name_label',
584 'name_description']
586 host_methods = [('disable', None),
587 ('enable', None),
588 ('reboot', None),
589 ('shutdown', None)]
591 host_funcs = [('get_by_name_label', 'Set(host)')]
593 # attributes
594 def host_get_name_label(self, session, host_ref):
595 return xen_api_success(XendNode.instance().name)
596 def host_set_name_label(self, session, host_ref, new_name):
597 XendNode.instance().set_name(new_name)
598 return xen_api_success_void()
599 def host_get_name_description(self, session, host_ref):
600 return xen_api_success(XendNode.instance().description)
601 def host_set_name_description(self, session, host_ref, new_desc):
602 XendNode.instance().set_description(new_desc)
603 return xen_api_success_void()
604 def host_get_software_version(self, session, host_ref):
605 return xen_api_success(XendNode.instance().xen_version())
606 def host_get_resident_VMs(self, session, host_ref):
607 return xen_api_success(XendDomain.instance().get_domain_refs())
608 def host_get_host_CPUs(self, session, host_ref):
609 return xen_api_success(XendNode.instance().get_host_cpu_refs())
611 # object methods
612 def host_destroy(self, session, host_ref):
613 return xen_api_error(XEND_ERROR_UNSUPPORTED)
614 def host_disable(self, session, host_ref):
615 XendDomain.instance().set_allow_new_domains(False)
616 return xen_api_success_void()
617 def host_enable(self, session, host_ref):
618 XendDomain.instance().set_allow_new_domains(True)
619 return xen_api_success_void()
620 def host_reboot(self, session, host_ref):
621 if not XendDomain.instance().allow_new_domains():
622 return xen_api_error(XEND_ERROR_HOST_RUNNING)
623 return xen_api_error(XEND_ERROR_UNSUPPORTED)
624 def host_shutdown(self, session, host_ref):
625 if not XendDomain.instance().allow_new_domains():
626 return xen_api_error(XEND_ERROR_HOST_RUNNING)
627 return xen_api_error(XEND_ERROR_UNSUPPORTED)
628 def host_get_record(self, session, host_ref):
629 node = XendNode.instance()
630 dom = XendDomain.instance()
631 record = {'uuid': node.uuid,
632 'name_label': node.name,
633 'name_description': '',
634 'software_version': node.xen_version(),
635 'resident_VMs': dom.get_domain_refs(),
636 'host_CPUs': node.get_host_cpu_refs()}
637 return xen_api_success(record)
639 # class methods
640 def host_get_all(self, session):
641 return xen_api_success((XendNode.instance().uuid,))
642 def host_create(self, session, struct):
643 return xen_api_error(XEND_ERROR_UNSUPPORTED)
644 def host_get_by_name_label(self, session, name):
645 if XendNode.instance().name == name:
646 return xen_api_success((XendNode.instance().uuid,))
647 return xen_api_success([])
650 # Xen API: Class Host_CPU
651 # ----------------------------------------------------------------
653 host_cpu_attr_ro = ['host',
654 'number',
655 'features',
656 'utilisation']
658 # attributes
659 def host_cpu_get_host(self, session, host_cpu_ref):
660 return xen_api_success(XendNode.instance().uuid)
661 def host_cpu_get_features(self, session, host_cpu_ref):
662 features = XendNode.instance().get_host_cpu_features(host_cpu_ref)
663 return xen_api_success(features)
664 def host_cpu_get_utilisation(self, session, host_cpu_ref):
665 util = XendNode.instance().get_host_cpu_load(host_cpu_ref)
666 return xen_api_success(util)
667 def host_cpu_get_number(self, session, host_cpu_ref):
668 num = XendNode.instance().get_host_cpu_number(host_cpu_ref)
669 return xen_api_success(num)
671 # object methods
672 def host_cpu_destroy(self, session, host_cpu_ref):
673 return xen_api_error(XEND_ERROR_UNSUPPORTED)
674 def host_cpu_get_record(self, session, host_cpu_ref):
675 node = XendNode.instance()
676 record = {'uuid': host_cpu_ref,
677 'host': node.uuid,
678 'number': node.get_host_cpu_number(host_cpu_ref),
679 'features': node.get_host_cpu_features(host_cpu_ref),
680 'utilisation': node.get_host_cpu_load(host_cpu_ref)}
681 return xen_api_success(record)
683 # class methods
684 def host_cpu_get_all(self, session):
685 return xen_api_success(XendNode.instance().get_host_cpu_refs())
688 # Xen API: Class network
689 # ----------------------------------------------------------------
691 network_attr_ro = ['VIFs', 'PIFs']
692 network_attr_rw = ['name_label',
693 'name_description',
694 'default_gateway',
695 'default_netmask']
697 network_funcs = [('create', 'network')]
699 def network_create(self, _, name_label, name_description,
700 default_gateway, default_netmask):
701 return xen_api_success(
702 XendNode.instance().network_create(name_label, name_description,
703 default_gateway,
704 default_netmask))
706 def network_destroy(self, _, ref):
707 return xen_api_success(XendNode.instance().network_destroy(ref))
709 def _get_network(self, ref):
710 return XendNode.instance().get_network(ref)
712 def network_get_all(self, _):
713 return xen_api_success(XendNode.instance().get_network_refs())
715 def network_get_record(self, _, ref):
716 return xen_api_success(
717 XendNode.instance().get_network(ref).get_record())
719 def network_get_name_label(self, _, ref):
720 return xen_api_success(self._get_network(ref).name_label)
722 def network_get_name_description(self, _, ref):
723 return xen_api_success(self._get_network(ref).name_description)
725 def network_get_default_gateway(self, _, ref):
726 return xen_api_success(self._get_network(ref).default_gateway)
728 def network_get_default_netmask(self, _, ref):
729 return xen_api_success(self._get_network(ref).default_netmask)
731 def network_get_VIFs(self, _, ref):
732 return xen_api_success(self._get_network(ref).get_VIF_UUIDs())
734 def network_get_PIFs(self, session, ref):
735 return xen_api_success(self._get_network(ref).get_PIF_UUIDs())
737 def network_set_name_label(self, _, ref, val):
738 return xen_api_success(self._get_network(ref).set_name_label(val))
740 def network_set_name_description(self, _, ref, val):
741 return xen_api_success(self._get_network(ref).set_name_description(val))
743 def network_set_default_gateway(self, _, ref, val):
744 return xen_api_success(self._get_network(ref).set_default_gateway(val))
746 def network_set_default_netmask(self, _, ref, val):
747 return xen_api_success(self._get_network(ref).set_default_netmask(val))
750 # Xen API: Class PIF
751 # ----------------------------------------------------------------
753 PIF_attr_ro = ['io_read_kbs',
754 'io_write_kbs']
755 PIF_attr_rw = ['name',
756 'network',
757 'host',
758 'MAC',
759 'MTU',
760 'VLAN']
762 PIF_attr_inst = PIF_attr_rw
764 PIF_methods = [('create_VLAN', 'int')]
766 def _get_PIF(self, ref):
767 return XendNode.instance().pifs[ref]
769 def PIF_create(self, _, name, network_uuid, host_uuid, mac, mtu, vlan):
770 try:
771 node = XendNode.instance()
772 if host_uuid != node.uuid:
773 return xen_api_error(['HOST_HANDLE_INVALID', host_uuid])
775 elif _is_valid_ref(network_uuid, node.is_valid_network):
776 network = node.get_network(network_uuid)
777 return xen_api_success(node.PIF_create(name, mtu, vlan, mac,
778 network))
779 else:
780 return xen_api_error(['NETWORK_HANDLE_INVALID', network_uuid])
781 except NetworkAlreadyConnected, exn:
782 return xen_api_error(['NETWORK_ALREADY_CONNECTED',
783 network_uuid, exn.pif_uuid])
785 def PIF_destroy(self, _, ref):
786 return xen_api_success(XendNode.instance().PIF_destroy(ref))
788 # object methods
789 def PIF_get_record(self, _, ref):
790 return xen_api_success(self._get_PIF(ref).get_record())
792 def PIF_get_all(self, _):
793 return xen_api_success(XendNode.instance().pifs.keys())
795 def PIF_get_name(self, _, ref):
796 return xen_api_success(self._get_PIF(ref).name)
798 def PIF_get_network(self, _, ref):
799 return xen_api_success(self._get_PIF(ref).network.uuid)
801 def PIF_get_host(self, _, ref):
802 return xen_api_success(self._get_PIF(ref).host.uuid)
804 def PIF_get_MAC(self, _, ref):
805 return xen_api_success(self._get_PIF(ref).mac)
807 def PIF_get_MTU(self, _, ref):
808 return xen_api_success(self._get_PIF(ref).mtu)
810 def PIF_get_VLAN(self, _, ref):
811 return xen_api_success(self._get_PIF(ref).vlan)
813 def PIF_get_io_read_kbs(self, _, ref):
814 return xen_api_success(self._get_PIF(ref).get_io_read_kbs())
816 def PIF_get_io_write_kbs(self, _, ref):
817 return xen_api_success(self._get_PIF(ref).get_io_write_kbs())
819 def PIF_set_name(self, _, ref, name):
820 return xen_api_success(self._get_PIF(ref).set_name(name))
822 def PIF_set_MAC(self, _, ref, mac):
823 return xen_api_success(self._get_PIF(ref).set_mac(mac))
825 def PIF_set_MTU(self, _, ref, mtu):
826 return xen_api_success(self._get_PIF(ref).set_mtu(mtu))
828 def PIF_create_VLAN(self, _, ref, network, vlan):
829 try:
830 if _is_valid_ref(network, XendNode.instance().is_valid_network):
831 return xen_api_success(XendNode.instance().PIF_create_VLAN(
832 ref, network, vlan))
833 else:
834 return xen_api_error(['NETWORK_HANDLE_INVALID', network])
835 except NetworkAlreadyConnected, exn:
836 return xen_api_error(['NETWORK_ALREADY_CONNECTED',
837 network, exn.pif_uuid])
840 # Xen API: Class VM
841 # ----------------------------------------------------------------
843 VM_attr_ro = ['power_state',
844 'resident_on',
845 'memory_actual',
846 'memory_static_max',
847 'memory_static_min',
848 'VCPUs_number',
849 'VCPUs_utilisation',
850 'VCPUs_features_required',
851 'VCPUs_can_use',
852 'consoles',
853 'VIFs',
854 'VBDs',
855 'VTPMs',
856 'PCI_bus',
857 'tools_version',
858 ]
860 VM_attr_rw = ['name_label',
861 'name_description',
862 'user_version',
863 'is_a_template',
864 'auto_power_on',
865 'memory_dynamic_max',
866 'memory_dynamic_min',
867 'VCPUs_policy',
868 'VCPUs_params',
869 'VCPUs_features_force_on',
870 'VCPUs_features_force_off',
871 'actions_after_shutdown',
872 'actions_after_reboot',
873 'actions_after_suspend',
874 'actions_after_crash',
875 'PV_bootloader',
876 'PV_kernel',
877 'PV_ramdisk',
878 'PV_args',
879 'PV_bootloader_args',
880 'HVM_boot',
881 'platform_std_VGA',
882 'platform_serial',
883 'platform_localtime',
884 'platform_clock_offset',
885 'platform_enable_audio',
886 'platform_keymap',
887 'otherConfig']
889 VM_methods = [('clone', 'VM'),
890 ('start', None),
891 ('pause', None),
892 ('unpause', None),
893 ('clean_shutdown', None),
894 ('clean_reboot', None),
895 ('hard_shutdown', None),
896 ('hard_reboot', None),
897 ('suspend', None),
898 ('resume', None),
899 ('add_to_otherConfig', None),
900 ('remove_from_otherConfig', None)]
902 VM_funcs = [('create', 'VM'),
903 ('get_by_name_label', 'Set(VM)')]
905 # parameters required for _create()
906 VM_attr_inst = [
907 'name_label',
908 'name_description',
909 'user_version',
910 'is_a_template',
911 'memory_static_max',
912 'memory_dynamic_max',
913 'memory_dynamic_min',
914 'memory_static_min',
915 'VCPUs_policy',
916 'VCPUs_params',
917 'VCPUs_features_required',
918 'VCPUs_features_can_use',
919 'VCPUs_features_force_on',
920 'VCPUs_features_force_off',
921 'actions_after_shutdown',
922 'actions_after_reboot',
923 'actions_after_suspend',
924 'actions_after_crash',
925 'PV_bootloader',
926 'PV_kernel',
927 'PV_ramdisk',
928 'PV_args',
929 'PV_bootloader_args',
930 'HVM_boot',
931 'platform_std_VGA',
932 'platform_serial',
933 'platform_localtime',
934 'platform_clock_offset',
935 'platform_enable_audio',
936 'platform_keymap',
937 'grub_cmdline',
938 'PCI_bus',
939 'otherConfig']
941 def VM_get(self, name, session, vm_ref):
942 return xen_api_success(
943 XendDomain.instance().get_vm_by_uuid(vm_ref).info[name])
945 def VM_set(self, name, session, vm_ref, value):
946 xd = XendDomain.instance()
947 dominfo = xd.get_vm_by_uuid(vm_ref)
948 dominfo.info[name] = value
949 xd.managed_config_save(dominfo)
950 return xen_api_success_void()
952 # attributes (ro)
953 def VM_get_power_state(self, session, vm_ref):
954 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
955 return xen_api_success(dom.get_power_state())
957 def VM_get_resident_on(self, session, vm_ref):
958 return xen_api_success(XendNode.instance().uuid)
960 def VM_get_memory_actual(self, session, vm_ref):
961 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
962 return xen_api_todo() # unsupported by xc
964 def VM_get_memory_static_max(self, session, vm_ref):
965 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
966 return xen_api_success(dom.get_memory_static_max())
968 def VM_get_memory_static_min(self, session, vm_ref):
969 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
970 return xen_api_success(dom.get_memory_static_min())
972 def VM_get_VCPUs_number(self, session, vm_ref):
973 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
974 return xen_api_success(dom.getVCpuCount())
976 def VM_get_VCPUs_utilisation(self, session, vm_ref):
977 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
978 return xen_api_success(dom.get_vcpus_util())
980 def VM_get_VCPUs_features_required(self, session, vm_ref):
981 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
982 return xen_api_todo() # unsupported by xc
984 def VM_get_VCPUs_can_use(self, session, vm_ref):
985 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
986 return xen_api_todo() # unsupported by xc
988 def VM_get_VIFs(self, session, vm_ref):
989 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
990 return xen_api_success(dom.get_vifs())
992 def VM_get_VBDs(self, session, vm_ref):
993 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
994 return xen_api_success(dom.get_vbds())
996 def VM_get_VTPMs(self, session, vm_ref):
997 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
998 return xen_api_success(dom.get_vtpms())
1000 def VM_get_consoles(self, session, vm_ref):
1001 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1002 return xen_api_success(dom.get_consoles())
1004 def VM_get_PCI_bus(self, session, vm_ref):
1005 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1006 return dom.get_pci_bus()
1008 def VM_get_tools_version(self, session, vm_ref):
1009 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1010 return dom.get_tools_version()
1012 # attributes (rw)
1013 def VM_get_name_label(self, session, vm_ref):
1014 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1015 return xen_api_success(dom.getName())
1017 def VM_get_name_description(self, session, vm_ref):
1018 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1019 return xen_api_todo()
1021 def VM_get_user_version(self, session, vm_ref):
1022 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1023 return xen_api_todo()
1025 def VM_get_is_a_template(self, session, vm_ref):
1026 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1027 return xen_api_todo()
1029 def VM_get_memory_dynamic_max(self, session, vm_ref):
1030 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1031 return xen_api_success(dom.get_memory_dynamic_max())
1033 def VM_get_memory_dynamic_min(self, session, vm_ref):
1034 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1035 return xen_api_success(dom.get_memory_dynamic_min())
1037 def VM_get_VCPUs_policy(self, session, vm_ref):
1038 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1039 return dom.get_vcpus_policy()
1041 def VM_get_VCPUs_params(self, session, vm_ref):
1042 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1043 return xen_api_todo() # need access to scheduler
1045 def VM_get_VCPUs_features_force_on(self, session, vm_ref):
1046 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1047 return xen_api_todo()
1049 def VM_get_VCPUs_features_force_off(self, session, vm_ref):
1050 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1051 return xen_api_todo()
1053 def VM_get_actions_after_shutdown(self, session, vm_ref):
1054 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1055 return xen_api_success(dom.get_on_shutdown())
1057 def VM_get_actions_after_reboot(self, session, vm_ref):
1058 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1059 return xen_api_success(dom.get_on_reboot())
1061 def VM_get_actions_after_suspend(self, session, vm_ref):
1062 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1063 return xen_api_success(dom.get_on_suspend())
1065 def VM_get_actions_after_crash(self, session, vm_ref):
1066 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1067 return xen_api_success(dom.get_on_crash())
1069 def VM_get_PV_bootloader(self, session, vm_ref):
1070 return self.VM_get('PV_bootloader', session, vm_ref)
1072 def VM_get_PV_kernel(self, session, vm_ref):
1073 return self.VM_get('PV_kernel', session, vm_ref)
1075 def VM_get_PV_ramdisk(self, session, vm_ref):
1076 return self.VM_get('PV_ramdisk', session, vm_ref)
1078 def VM_get_PV_args(self, session, vm_ref):
1079 return self.VM_get('PV_args', session, vm_ref)
1081 def VM_get_PV_bootloader_args(self, session, vm_ref):
1082 return self.VM_get('PV_bootloader_args', session, vm_ref)
1084 def VM_get_HVM_boot(self, session, vm_ref):
1085 return self.VM_get('HVM_boot', session, vm_ref)
1087 def VM_get_platform_std_VGA(self, session, vm_ref):
1088 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1089 return xen_api_success(dom.get_platform_std_vga())
1091 def VM_get_platform_serial(self, session, vm_ref):
1092 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1093 return xen_api_success(dom.get_platform_serial())
1095 def VM_get_platform_localtime(self, session, vm_ref):
1096 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1097 return xen_api_success(dom.get_platform_localtime())
1099 def VM_get_platform_clock_offset(self, session, vm_ref):
1100 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1101 return xen_api_success(dom.get_platform_clock_offset())
1103 def VM_get_platform_enable_audio(self, session, vm_ref):
1104 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1105 return xen_api_success(dom.get_platform_enable_audio())
1107 def VM_get_platform_keymap(self, session, vm_ref):
1108 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1109 return xen_api_success(dom.get_platform_keymap())
1111 def VM_get_otherConfig(self, session, vm_ref):
1112 return self.VM_get('otherConfig', session, vm_ref)
1114 def VM_set_name_label(self, session, vm_ref, label):
1115 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1116 dom.setName(label)
1117 return xen_api_success_void()
1119 def VM_set_name_description(self, session, vm_ref, desc):
1120 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1121 return xen_api_todo()
1123 def VM_set_user_version(self, session, vm_ref, ver):
1124 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1125 return xen_api_todo()
1127 def VM_set_is_a_template(self, session, vm_ref, is_template):
1128 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1129 return xen_api_todo()
1131 def VM_set_memory_dynamic_max(self, session, vm_ref, mem):
1132 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1133 return xen_api_todo()
1135 def VM_set_memory_dynamic_min(self, session, vm_ref, mem):
1136 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1137 return xen_api_todo()
1139 def VM_set_VCPUs_policy(self, session, vm_ref, policy):
1140 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1141 return xen_api_todo()
1143 def VM_set_VCPUs_params(self, session, vm_ref, params):
1144 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1145 return xen_api_todo()
1147 def VM_set_VCPUs_features_force_on(self, session, vm_ref, features):
1148 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1149 return xen_api_todo()
1151 def VM_set_VCPUs_features_force_off(self, session, vm_ref, features):
1152 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1153 return xen_api_todo()
1155 def VM_set_actions_after_shutdown(self, session, vm_ref, action):
1156 if action not in XEN_API_ON_NORMAL_EXIST:
1157 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1158 return self.VM_set('actions_after_shutdown', session, vm_ref, action)
1160 def VM_set_actions_after_reboot(self, session, vm_ref, action):
1161 if action not in XEN_API_ON_NORMAL_EXIST:
1162 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1163 return self.VM_set('actions_after_reboot', session, vm_ref, action)
1165 def VM_set_actions_after_suspend(self, session, vm_ref, action):
1166 if action not in XEN_API_ON_NORMAL_EXIT:
1167 return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
1168 return self.VM_set('actions_after_suspend', session, vm_ref, action)
1170 def VM_set_actions_after_crash(self, session, vm_ref, action):
1171 if action not in XEN_API_ON_CRASH_BEHAVIOUR:
1172 return xen_api_error(['VM_ON_CRASH_BEHAVIOUR_INVALID', vm_ref])
1173 return self.VM_set('actions_after_crash', session, vm_ref, action)
1175 def VM_set_HVM_boot(self, session, vm_ref, value):
1176 return self.VM_set('HVM_boot', session, vm_ref, value)
1178 def VM_set_PV_bootloader(self, session, vm_ref, value):
1179 return self.VM_set('PV_bootloader', session, vm_ref, value)
1181 def VM_set_PV_kernel(self, session, vm_ref, value):
1182 return self.VM_set('PV_kernel', session, vm_ref, value)
1184 def VM_set_PV_ramdisk(self, session, vm_ref, value):
1185 return self.VM_set('PV_ramdisk', session, vm_ref, value)
1187 def VM_set_PV_args(self, session, vm_ref, value):
1188 return self.VM_set('PV_args', session, vm_ref, value)
1190 def VM_set_PV_bootloader_args(self, session, vm_ref, value):
1191 return self.VM_set('PV_bootloader_args', session, vm_ref, value)
1193 def VM_set_platform_std_VGA(self, session, vm_ref, value):
1194 return self.VM_set('platform_std_vga', session, vm_ref, value)
1196 def VM_set_platform_serial(self, session, vm_ref, value):
1197 return self.VM_set('platform_serial', session, vm_ref, value)
1199 def VM_set_platform_keymap(self, session, vm_ref, value):
1200 return self.VM_set('platform_keymap', session, vm_ref, value)
1202 def VM_set_platform_localtime(self, session, vm_ref, value):
1203 return self.VM_set('platform_localtime', session, vm_ref, value)
1205 def VM_set_platform_clock_offset(self, session, vm_ref, value):
1206 return self.VM_set('platform_clock_offset', session, vm_ref, value)
1208 def VM_set_platform_enable_audio(self, session, vm_ref, value):
1209 return self.VM_set('platform_enable_audio', session, vm_ref, value)
1211 def VM_set_otherConfig(self, session, vm_ref, value):
1212 return self.VM_set('otherconfig', session, vm_ref, value)
1214 def VM_add_to_otherConfig(self, session, vm_ref, key, value):
1215 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1216 if dom and 'otherconfig' in dom.info:
1217 dom.info['otherconfig'][key] = value
1218 return xen_api_success_void()
1220 def VM_remove_from_otherConfig(self, session, vm_ref, key):
1221 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
1222 if dom and 'otherconfig' in dom.info \
1223 and key in dom.info['otherconfig']:
1224 del dom.info['otherconfig'][key]
1225 return xen_api_success_void()
1227 # class methods
1228 def VM_get_all(self, session):
1229 refs = [d.get_uuid() for d in XendDomain.instance().list('all')]
1230 return xen_api_success(refs)
1232 def VM_get_by_name_label(self, session, label):
1233 xendom = XendDomain.instance()
1234 dom = xendom.domain_lookup_nr(label)
1235 if dom:
1236 return xen_api_success([dom.get_uuid()])
1237 return xen_api_success([])
1239 def VM_create(self, session, vm_struct):
1240 xendom = XendDomain.instance()
1241 domuuid = XendTask.log_progress(0, 100,
1242 xendom.create_domain, vm_struct)
1243 return xen_api_success(domuuid)
1245 # object methods
1246 def VM_get_record(self, session, vm_ref):
1247 xendom = XendDomain.instance()
1248 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1249 if not xeninfo:
1250 return xen_api_error(['VM_HANDLE_INVALID', vm_ref])
1252 record = {
1253 'uuid': xeninfo.get_uuid(),
1254 'power_state': xeninfo.get_power_state(),
1255 'name_label': xeninfo.getName(),
1256 'name_description': xeninfo.getName(),
1257 'user_version': 1,
1258 'is_a_template': False,
1259 'auto_power_on': False,
1260 'resident_on': XendNode.instance().uuid,
1261 'memory_static_min': xeninfo.get_memory_static_min(),
1262 'memory_static_max': xeninfo.get_memory_static_max(),
1263 'memory_dynamic_min': xeninfo.get_memory_dynamic_min(),
1264 'memory_dynamic_max': xeninfo.get_memory_dynamic_max(),
1265 'memory_actual': xeninfo.get_memory_static_min(),
1266 'VCPUs_policy': xeninfo.get_vcpus_policy(),
1267 'VCPUs_params': xeninfo.get_vcpus_params(),
1268 'VCPUs_number': xeninfo.getVCpuCount(),
1269 'VCPUs_utilisation': xeninfo.get_vcpus_util(),
1270 'VCPUs_features_required': [],
1271 'VCPUs_features_can_use': [],
1272 'VCPUs_features_force_on': [],
1273 'VCPUs_features_force_off': [],
1274 'actions_after_shutdown': xeninfo.get_on_shutdown(),
1275 'actions_after_reboot': xeninfo.get_on_reboot(),
1276 'actions_after_suspend': xeninfo.get_on_suspend(),
1277 'actions_after_crash': xeninfo.get_on_crash(),
1278 'consoles': xeninfo.get_consoles(),
1279 'VIFs': xeninfo.get_vifs(),
1280 'VBDs': xeninfo.get_vbds(),
1281 'VTPMs': xeninfo.get_vtpms(),
1282 'PV_bootloader': xeninfo.info.get('PV_bootloader'),
1283 'PV_kernel': xeninfo.info.get('PV_kernel'),
1284 'PV_ramdisk': xeninfo.info.get('PV_ramdisk'),
1285 'PV_args': xeninfo.info.get('PV_args'),
1286 'PV_bootloader_args': xeninfo.info.get('PV_bootloader_args'),
1287 'HVM_boot': xeninfo.info.get('HVM_boot'),
1288 'platform_std_VGA': xeninfo.get_platform_std_vga(),
1289 'platform_serial': xeninfo.get_platform_serial(),
1290 'platform_localtime': xeninfo.get_platform_localtime(),
1291 'platform_clock_offset': xeninfo.get_platform_clock_offset(),
1292 'platform_enable_audio': xeninfo.get_platform_enable_audio(),
1293 'platform_keymap': xeninfo.get_platform_keymap(),
1294 'PCI_bus': xeninfo.get_pci_bus(),
1295 'tools_version': xeninfo.get_tools_version(),
1296 'otherConfig': xeninfo.info.get('otherconfig'),
1298 return xen_api_success(record)
1300 def VM_clean_reboot(self, session, vm_ref):
1301 xendom = XendDomain.instance()
1302 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1303 XendTask.log_progress(0, 100, xeninfo.shutdown, "reboot")
1304 return xen_api_success_void()
1306 def VM_clean_shutdown(self, session, vm_ref):
1307 xendom = XendDomain.instance()
1308 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1309 XendTask.log_progress(0, 100, xeninfo.shutdown, "poweroff")
1310 return xen_api_success_void()
1312 def VM_clone(self, session, vm_ref):
1313 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1315 def VM_destroy(self, session, vm_ref):
1316 return XendTask.log_progress(0, 100, do_vm_func,
1317 "domain_delete", vm_ref)
1319 def VM_hard_reboot(self, session, vm_ref):
1320 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1322 def VM_hard_shutdown(self, session, vm_ref):
1323 return XendTask.log_progress(0, 100, do_vm_func,
1324 "domain_destroy", vm_ref)
1325 def VM_pause(self, session, vm_ref):
1326 return XendTask.log_progress(0, 100, do_vm_func,
1327 "domain_pause", vm_ref)
1329 def VM_resume(self, session, vm_ref, start_paused):
1330 return XendTask.log_progress(0, 100, do_vm_func,
1331 "domain_resume", vm_ref,
1332 start_paused = start_paused)
1334 def VM_start(self, session, vm_ref, start_paused):
1335 return XendTask.log_progress(0, 100, do_vm_func,
1336 "domain_start", vm_ref,
1337 start_paused = start_paused)
1339 def VM_suspend(self, session, vm_ref):
1340 return XendTask.log_progress(0, 100, do_vm_func,
1341 "domain_suspend", vm_ref)
1343 def VM_unpause(self, session, vm_ref):
1344 return XendTask.log_progress(0, 100, do_vm_func,
1345 "domain_unpause", vm_ref)
1347 # Xen API: Class VBD
1348 # ----------------------------------------------------------------
1350 VBD_attr_ro = ['io_read_kbs',
1351 'io_write_kbs']
1352 VBD_attr_rw = ['VM',
1353 'VDI',
1354 'device',
1355 'mode',
1356 'type',
1357 'driver']
1359 VBD_attr_inst = VBD_attr_rw
1361 VBD_methods = [('media_change', None)]
1362 VBD_funcs = [('create', 'VBD')]
1364 # object methods
1365 def VBD_get_record(self, session, vbd_ref):
1366 xendom = XendDomain.instance()
1367 vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1368 if not vm:
1369 return xen_api_error(['VBD_HANDLE_INVALID', vbd_ref])
1370 cfg = vm.get_dev_xenapi_config('vbd', vbd_ref)
1371 if not cfg:
1372 return xen_api_error(['VBD_HANDLE_INVALID', vbd_ref])
1374 valid_vbd_keys = self.VBD_attr_ro + self.VBD_attr_rw + \
1375 self.Base_attr_ro + self.Base_attr_rw
1377 return_cfg = {}
1378 for k in cfg.keys():
1379 if k in valid_vbd_keys:
1380 return_cfg[k] = cfg[k]
1382 return xen_api_success(return_cfg)
1384 def VBD_media_change(self, session, vbd_ref, vdi_ref):
1385 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1387 # class methods
1388 def VBD_create(self, session, vbd_struct):
1389 xendom = XendDomain.instance()
1390 if not xendom.is_valid_vm(vbd_struct['VM']):
1391 return xen_api_error(['VM_HANDLE_INVALID', vbd_struct['VM']])
1393 dom = xendom.get_vm_by_uuid(vbd_struct['VM'])
1394 vbd_ref = ''
1395 try:
1396 # new VBD via VDI/SR
1397 vdi_ref = vbd_struct.get('VDI')
1398 vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
1399 if not vdi:
1400 return xen_api_error(['VDI_HANDLE_INVALID', vdi_ref])
1401 vdi_image = vdi.get_image_uri()
1402 vbd_ref = XendTask.log_progress(0, 100,
1403 dom.create_vbd,
1404 vbd_struct, vdi_image)
1405 except XendError:
1406 return xen_api_todo()
1408 xendom.managed_config_save(dom)
1409 return xen_api_success(vbd_ref)
1412 def VBD_destroy(self, session, vbd_ref):
1413 xendom = XendDomain.instance()
1414 vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1415 if not vm:
1416 return xen_api_error(['VBD_HANDLE_INVALID', vbd_ref])
1418 XendTask.log_progress(0, 100, vm.destroy_vbd, vbd_ref)
1419 return xen_api_success_void()
1421 # attributes (rw)
1422 def VBD_get_VM(self, session, vbd_ref):
1423 xendom = XendDomain.instance()
1424 return xen_api_success(xendom.get_dev_property_by_uuid('vbd',
1425 vbd_ref, 'VM'))
1427 def VBD_get_VDI(self, session, vbd_ref):
1428 xendom = XendDomain.instance()
1429 return xen_api_success(xendom.get_dev_property_by_uuid('vbd',
1430 vbd_ref, 'VDI'))
1432 def VBD_get_device(self, session, vbd_ref):
1433 xendom = XendDomain.instance()
1434 return xen_api_success(xendom.get_dev_property_by_uuid('vbd', vbd_ref,
1435 'device'))
1436 def VBD_get_mode(self, session, vbd_ref):
1437 xendom = XendDomain.instance()
1438 return xen_api_success(xendom.get_dev_property_by_uuid('vbd', vbd_ref,
1439 'mode'))
1440 def VBD_get_driver(self, session, vbd_ref):
1441 xendom = XendDomain.instance()
1442 return xen_api_success(xendom.get_dev_property_by_uuid('vbd', vbd_ref,
1443 'driver'))
1445 def VBD_get_type(self, session, vbd_ref):
1446 xendom = XendDomain.instance()
1447 return xen_api_success(xendom.get_dev_property_by_uuid('vbd', vbd_ref,
1448 'type'))
1450 def VBD_get_io_read_kbs(self, session, vbd_ref):
1451 return xen_api_todo()
1453 def VBD_get_io_write_kbs(self, session, vbd_ref):
1454 return xen_api_todo()
1456 def VBD_get_all(self, session):
1457 xendom = XendDomain.instance()
1458 vbds = [d.get_vbds() for d in XendDomain.instance().list('all')]
1459 vbds = reduce(lambda x, y: x + y, vbds)
1460 return xen_api_success(vbds)
1462 # Xen API: Class VIF
1463 # ----------------------------------------------------------------
1465 VIF_attr_ro = ['io_read_kbs',
1466 'io_write_kbs']
1467 VIF_attr_rw = ['name',
1468 'type',
1469 'device',
1470 'network',
1471 'VM',
1472 'MAC',
1473 'MTU']
1475 VIF_attr_inst = VIF_attr_rw
1477 VIF_funcs = [('create', 'VIF')]
1480 # object methods
1481 def VIF_get_record(self, session, vif_ref):
1482 xendom = XendDomain.instance()
1483 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
1484 if not vm:
1485 return xen_api_error(['VIF_HANDLE_INVALID', vif_ref])
1486 cfg = vm.get_dev_xenapi_config('vif', vif_ref)
1487 if not cfg:
1488 return xen_api_error(['VIF_HANDLE_INVALID', vif_ref])
1490 valid_vif_keys = self.VIF_attr_ro + self.VIF_attr_rw + \
1491 self.Base_attr_ro + self.Base_attr_rw
1493 return_cfg = {}
1494 for k in cfg.keys():
1495 if k in valid_vif_keys:
1496 return_cfg[k] = cfg[k]
1498 return xen_api_success(return_cfg)
1500 # class methods
1501 def VIF_create(self, session, vif_struct):
1502 xendom = XendDomain.instance()
1503 if xendom.is_valid_vm(vif_struct['VM']):
1504 dom = xendom.get_vm_by_uuid(vif_struct['VM'])
1505 try:
1506 vif_ref = dom.create_vif(vif_struct)
1507 xendom.managed_config_save(dom)
1508 return xen_api_success(vif_ref)
1509 except XendError:
1510 return xen_api_error(XEND_ERROR_TODO)
1511 else:
1512 return xen_api_error(['VM_HANDLE_INVALID', vif_struct['VM']])
1515 def VIF_destroy(self, session, vif_ref):
1516 xendom = XendDomain.instance()
1517 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
1518 if not vm:
1519 return xen_api_error(['VIF_HANDLE_INVALID', vif_ref])
1521 vm.destroy_vif(vif_ref)
1522 return xen_api_success_void()
1524 # getters/setters
1525 def VIF_get_VM(self, session, vif_ref):
1526 xendom = XendDomain.instance()
1527 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
1528 return xen_api_success(vm.get_uuid())
1530 def VIF_get_name(self, session, vif_ref):
1531 xendom = XendDomain.instance()
1532 return xen_api_success(xendom.get_dev_property_by_uuid('vif', vif_ref,
1533 'name'))
1534 def VIF_get_MTU(self, session, vif_ref):
1535 xendom = XendDomain.instance()
1536 return xen_api_success(xendom.get_dev_property_by_uuid('vif', vif_ref,
1537 'MTU'))
1538 def VIF_get_MAC(self, session, vif_ref):
1539 xendom = XendDomain.instance()
1540 return xen_api_success(xendom.get_dev_property_by_uuid('vif', vif_ref,
1541 'MAC'))
1543 def VIF_get_type(self, session, vif_ref):
1544 xendom = XendDomain.instance()
1545 return xen_api_success(xendom.get_dev_property_by_uuid('vif', vif_ref,
1546 'type'))
1549 def VIF_get_device(self, session, vif_ref):
1550 xendom = XendDomain.instance()
1551 return xen_api_success(xendom.get_dev_property_by_uuid('vif', vif_ref,
1552 'device'))
1555 def VIF_get_io_read_kbs(self, session, vif_ref):
1556 return xen_api_todo()
1558 def VIF_get_io_write_kbs(self, session, vif_ref):
1559 return xen_api_todo()
1561 def VIF_get_all(self, session):
1562 xendom = XendDomain.instance()
1563 vifs = [d.get_vifs() for d in XendDomain.instance().list('all')]
1564 vifs = reduce(lambda x, y: x + y, vifs)
1565 return xen_api_success(vifs)
1568 # Xen API: Class VDI
1569 # ----------------------------------------------------------------
1570 VDI_attr_ro = ['VBDs',
1571 'physical_utilisation',
1572 'sector_size',
1573 'type',
1574 'parent',
1575 'children']
1576 VDI_attr_rw = ['name_label',
1577 'name_description',
1578 'SR',
1579 'virtual_size',
1580 'sharable',
1581 'read_only']
1582 VDI_attr_inst = VDI_attr_ro + VDI_attr_rw
1584 VDI_methods = [('snapshot', 'VDI')]
1585 VDI_funcs = [('create', 'VDI'),
1586 ('get_by_name_label', 'Set(VDI)')]
1588 def _get_VDI(self, ref):
1589 return XendNode.instance().get_vdi_by_uuid(ref)
1591 def VDI_get_VBDs(self, session, vdi_ref):
1592 return xen_api_todo()
1594 def VDI_get_physical_utilisation(self, session, vdi_ref):
1595 return xen_api_success(self._get_VDI(vdi_ref).
1596 get_physical_utilisation())
1598 def VDI_get_sector_size(self, session, vdi_ref):
1599 return xen_api_success(self._get_VDI(vdi_ref).sector_size)
1601 def VDI_get_type(self, session, vdi_ref):
1602 return xen_api_success(self._get_VDI(vdi_ref).type)
1604 def VDI_get_parent(self, session, vdi_ref):
1605 return xen_api_success(self._get_VDI(vdi_ref).parent)
1607 def VDI_get_children(self, session, vdi_ref):
1608 return xen_api_success(self._get_VDI(vdi_ref).children)
1610 def VDI_get_name_label(self, session, vdi_ref):
1611 return xen_api_success(self._get_VDI(vdi_ref).name_label)
1613 def VDI_get_name_description(self, session, vdi_ref):
1614 return xen_api_success(self._get_VDI(vdi_ref).name_description)
1616 def VDI_get_SR(self, session, vdi_ref):
1617 return xen_api_success(self._get_VDI(vdi_ref).sr_uuid)
1619 def VDI_get_virtual_size(self, session, vdi_ref):
1620 return xen_api_success(self._get_VDI(vdi_ref).virtual_size)
1622 def VDI_get_sharable(self, session, vdi_ref):
1623 return xen_api_success(self._get_VDI(vdi_ref).sharable)
1625 def VDI_get_read_only(self, session, vdi_ref):
1626 return xen_api_success(self._get_VDI(vdi_ref).read_only)
1628 def VDI_set_name_label(self, session, vdi_ref, value):
1629 self._get_VDI(vdi_ref).name_label = value
1630 return xen_api_success_void()
1632 def VDI_set_name_description(self, session, vdi_ref, value):
1633 self._get_VDI(vdi_ref).name_description = value
1634 return xen_api_success_void()
1636 def VDI_set_SR(self, session, vdi_ref, value):
1637 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1639 def VDI_set_virtual_size(self, session, vdi_ref, value):
1640 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1642 def VDI_set_sharable(self, session, vdi_ref, value):
1643 self._get_VDI(vdi_ref).sharable = bool(value)
1644 return xen_api_success_void()
1646 def VDI_set_read_only(self, session, vdi_ref, value):
1647 self._get_VDI(vdi_ref).read_only = bool(value)
1648 return xen_api_success_void()
1650 # Object Methods
1651 def VDI_snapshot(self, session, vdi_ref):
1652 return xen_api_todo()
1654 def VDI_destroy(self, session, vdi_ref):
1655 sr = XendNode.instance().get_sr_containing_vdi(vdi_ref)
1656 sr.destroy_vdi(vdi_ref)
1657 return xen_api_success_void()
1659 def VDI_get_record(self, session, vdi_ref):
1660 image = XendNode.instance().get_vdi_by_uuid(vdi_ref)
1661 return xen_api_success({
1662 'uuid': vdi_ref,
1663 'name_label': image.name_label,
1664 'name_description': image.name_description,
1665 'SR': image.sr_uuid,
1666 'VBDs': [], # TODO
1667 'virtual_size': image.virtual_size,
1668 'physical_utilisation': image.physical_utilisation,
1669 'sector_size': image.sector_size,
1670 'type': image.type,
1671 'parent': image.parent,
1672 'children': image.children,
1673 'sharable': image.sharable,
1674 'read_only': image.read_only,
1675 })
1677 # Class Functions
1678 def VDI_create(self, session, vdi_struct):
1679 sr_ref = vdi_struct.get('SR')
1680 xennode = XendNode.instance()
1681 if not xennode.is_valid_sr(sr_ref):
1682 return xen_api_error(['SR_HANDLE_INVALID', sr_ref])
1684 vdi_uuid = xennode.srs[sr_ref].create_vdi(vdi_struct)
1685 return xen_api_success(vdi_uuid)
1687 def VDI_get_all(self, session):
1688 xennode = XendNode.instance()
1689 vdis = [sr.get_vdis() for sr in xennode.srs.values()]
1690 return xen_api_success(reduce(lambda x, y: x + y, vdis))
1692 def VDI_get_by_name_label(self, session, name):
1693 xennode = XendNode.instance()
1694 return xen_api_success(xennode.get_vdi_by_name_label(name))
1697 # Xen API: Class VTPM
1698 # ----------------------------------------------------------------
1700 VTPM_attr_rw = [ ]
1701 VTPM_attr_ro = ['VM',
1702 'backend',
1703 'instance',
1704 'driver']
1706 VTPM_attr_inst = VTPM_attr_rw
1708 VTPM_funcs = [('create', 'VTPM')]
1710 # object methods
1711 def VTPM_get_record(self, session, vtpm_ref):
1712 xendom = XendDomain.instance()
1713 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
1714 if not vm:
1715 return xen_api_error(['VTPM_HANDLE_INVALID', vtpm_ref])
1716 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
1717 if not cfg:
1718 return xen_api_error(['VTPM_HANDLE_INVALID', vtpm_ref])
1719 valid_vtpm_keys = self.VTPM_attr_ro + self.VTPM_attr_rw + \
1720 self.Base_attr_ro + self.Base_attr_rw
1721 for k in cfg.keys():
1722 if k not in valid_vtpm_keys:
1723 del cfg[k]
1725 return xen_api_success(cfg)
1727 # Class Functions
1728 def VTPM_get_instance(self, session, vtpm_ref):
1729 xendom = XendDomain.instance()
1730 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
1731 if not vm:
1732 return xen_api_error(['VTPM_HANDLE_INVALID', vtpm_ref])
1733 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
1734 if not cfg:
1735 return xen_api_error(['VTPM_HANDLE_INVALID', vtpm_ref])
1736 if cfg.has_key('instance'):
1737 instance = cfg['instance']
1738 else:
1739 instance = -1
1740 return xen_api_success(instance)
1742 def VTPM_get_driver(self, session, vtpm_ref):
1743 xendom = XendDomain.instance()
1744 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
1745 if not vm:
1746 return xen_api_error(['VTPM_HANDLE_INVALID', vtpm_ref])
1747 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
1748 if not cfg:
1749 return xen_api_error(['VTPM_HANDLE_INVALID', vtpm_ref])
1750 if cfg.has_key('type'):
1751 driver = cfg['type']
1752 else:
1753 driver = "Unknown"
1754 return xen_api_success(driver)
1756 def VTPM_get_backend(self, session, vtpm_ref):
1757 xendom = XendDomain.instance()
1758 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
1759 if not vm:
1760 return xen_api_error(['VTPM_HANDLE_INVALID', vtpm_ref])
1761 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
1762 if not cfg:
1763 return xen_api_error(['VTPM_HANDLE_INVALID', vtpm_ref])
1764 if cfg.has_key('backend'):
1765 backend = cfg['backend']
1766 else:
1767 backend = "Domain-0"
1768 return xen_api_success(backend)
1770 def VTPM_get_VM(self, session, vtpm_ref):
1771 xendom = XendDomain.instance()
1772 return xen_api_success(xendom.get_dev_property_by_uuid('vtpm',
1773 vtpm_ref, 'VM'))
1775 def VTPM_destroy(self, session, vtpm_ref):
1776 xendom = XendDomain.instance()
1777 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
1778 if not vm:
1779 return xen_api_error(['VTPM_HANDLE_INVALID', vtpm_ref])
1781 vm.destroy_vtpm(vtpm_ref)
1782 return xen_api_success_void()
1784 # class methods
1785 def VTPM_create(self, session, vtpm_struct):
1786 xendom = XendDomain.instance()
1787 if xendom.is_valid_vm(vtpm_struct['VM']):
1788 dom = xendom.get_vm_by_uuid(vtpm_struct['VM'])
1789 try:
1790 vtpm_ref = dom.create_vtpm(vtpm_struct)
1791 xendom.managed_config_save(dom)
1792 return xen_api_success(vtpm_ref)
1793 except XendError:
1794 return xen_api_error(XEND_ERROR_TODO)
1795 else:
1796 return xen_api_error(['VM_HANDLE_INVALID', vtpm_struct['VM']])
1798 def VTPM_get_all(self, session):
1799 xendom = XendDomain.instance()
1800 vtpms = [d.get_vtpms() for d in XendDomain.instance().list('all')]
1801 vtpms = reduce(lambda x, y: x + y, vtpms)
1802 return xen_api_success(vtpms)
1804 # Xen API: Class console
1805 # ----------------------------------------------------------------
1808 console_attr_ro = ['uri', 'protocol', 'VM']
1809 console_attr_rw = []
1811 def console_get_all(self, session):
1812 xendom = XendDomain.instance()
1813 cons = [d.get_consoles() for d in XendDomain.instance().list('all')]
1814 cons = reduce(lambda x, y: x + y, cons)
1815 return xen_api_success(cons)
1817 def console_get_uri(self, session, console_ref):
1818 return xen_api_success(xendom.get_dev_property_by_uuid('console',
1819 console_ref,
1820 'uri'))
1822 def console_get_protocol(self, session, console_ref):
1823 return xen_api_success(xendom.get_dev_property_by_uuid('console',
1824 console_ref,
1825 'protocol'))
1827 def console_get_VM(self, session, console_ref):
1828 xendom = XendDomain.instance()
1829 vm = xendom.get_vm_with_dev_uuid('console', console_ref)
1830 return xen_api_success(vm.get_uuid())
1832 # object methods
1833 def console_get_record(self, session, console_ref):
1834 xendom = XendDomain.instance()
1835 vm = xendom.get_vm_with_dev_uuid('console', console_ref)
1836 if not vm:
1837 return xen_api_error(['CONSOLE_HANDLE_INVALID', console_ref])
1838 cfg = vm.get_dev_xenapi_config('console', console_ref)
1839 if not cfg:
1840 return xen_api_error(['CONSOLE_HANDLE_INVALID', console_ref])
1842 valid_console_keys = self.console_attr_ro + self.console_attr_rw + \
1843 self.Base_attr_ro + self.Base_attr_rw
1845 return_cfg = {}
1846 for k in cfg.keys():
1847 if k in valid_console_keys:
1848 return_cfg[k] = cfg[k]
1850 return xen_api_success(return_cfg)
1853 # Xen API: Class SR
1854 # ----------------------------------------------------------------
1855 SR_attr_ro = ['VDIs',
1856 'virtual_allocation',
1857 'physical_utilisation',
1858 'physical_size',
1859 'type',
1860 'location']
1862 SR_attr_rw = ['name_label',
1863 'name_description']
1865 SR_attr_inst = ['physical_size',
1866 'type',
1867 'location',
1868 'name_label',
1869 'name_description']
1871 SR_methods = [('clone', 'SR')]
1872 SR_funcs = [('get_by_name_label', 'Set(SR)'),
1873 ('get_by_uuid', 'SR')]
1875 # Class Functions
1876 def SR_get_all(self, session):
1877 return xen_api_success(XendNode.instance().get_all_sr_uuid())
1879 def SR_get_by_name_label(self, session, label):
1880 return xen_api_success(XendNode.instance().get_sr_by_name(label))
1882 def SR_create(self, session):
1883 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1885 # Class Methods
1886 def SR_clone(self, session, sr_ref):
1887 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1889 def SR_destroy(self, session, sr_ref):
1890 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1892 def SR_get_record(self, session, sr_ref):
1893 sr = XendNode.instance().get_sr(sr_ref)
1894 if sr:
1895 return xen_api_success(sr.get_record())
1896 return xen_api_error(['SR_HANDLE_INVALID', sr_ref])
1898 # Attribute acceess
1900 def _get_SR_func(self, sr_ref, func):
1901 return xen_api_success(getattr(XendNode.instance().get_sr(sr_ref),
1902 func)())
1904 def _get_SR_attr(self, sr_ref, attr):
1905 return xen_api_success(getattr(XendNode.instance().get_sr(sr_ref),
1906 attr))
1908 def SR_get_VDIs(self, _, ref):
1909 return self._get_SR_func(ref, 'list_images')
1911 def SR_get_virtual_allocation(self, _, ref):
1912 return self._get_SR_func(ref, 'virtual_allocation')
1914 def SR_get_physical_utilisation(self, _, ref):
1915 return self._get_SR_func(ref, 'physical_utilisation')
1917 def SR_get_physical_size(self, _, ref):
1918 return self._get_SR_func(ref, 'physical_size')
1920 def SR_get_type(self, _, ref):
1921 return self._get_SR_attr(ref, 'type')
1923 def SR_get_location(self, _, ref):
1924 return self._get_SR_attr(ref, 'location')
1926 def SR_get_name_label(self, _, ref):
1927 return self._get_SR_attr(ref, 'name_label')
1929 def SR_get_name_description(self, _, ref):
1930 return self._get_SR_attr(ref, 'name_description')
1932 def SR_set_name_label(self, session, sr_ref, value):
1933 sr = XendNode.instance.get_sr(sr_ref)
1934 if sr:
1935 sr.name_label = value
1936 XendNode.instance().save()
1937 return xen_api_success_void()
1939 def SR_set_name_description(self, session, sr_ref, value):
1940 sr = XendNode.instance.get_sr(sr_ref)
1941 if sr:
1942 sr.name_description = value
1943 XendNode.instance().save()
1944 return xen_api_success_void()
1947 # Xen API: Class debug
1948 # ----------------------------------------------------------------
1950 debug_methods = [('destroy', None),
1951 ('get_record', 'debug')]
1952 debug_funcs = [('wait', None),
1953 ('return_failure', None)]
1955 def debug_wait(self, session, wait_secs):
1956 import time
1957 prog_units = 100/float(wait_secs)
1958 for i in range(int(wait_secs)):
1959 XendTask.log_progress(prog_units * i, prog_units * (i + 1),
1960 time.sleep, 1)
1961 return xen_api_success_void()
1964 def debug_return_failure(self, session):
1965 return xen_api_error(['DEBUG_FAIL', session])
1967 def debug_create(self, session):
1968 debug_uuid = uuid.createString()
1969 self._debug[debug_uuid] = None
1970 return xen_api_success(debug_uuid)
1972 def debug_destroy(self, session, debug_ref):
1973 del self._debug[debug_ref]
1974 return xen_api_success_void()
1976 def debug_get_record(self, session, debug_ref):
1977 return xen_api_success({'uuid': debug_ref})
1981 class XendAPIAsyncProxy:
1982 """ A redirector for Async.Class.function calls to XendAPI
1983 but wraps the call for use with the XendTaskManager.
1985 @ivar xenapi: Xen API instance
1986 @ivar method_map: Mapping from XMLRPC method name to callable objects.
1987 """
1989 method_prefix = 'Async.'
1991 def __init__(self, xenapi):
1992 """Initialises the Async Proxy by making a map of all
1993 implemented Xen API methods for use with XendTaskManager.
1995 @param xenapi: XendAPI instance
1996 """
1997 self.xenapi = xenapi
1998 self.method_map = {}
1999 for method_name in dir(self.xenapi):
2000 method = getattr(self.xenapi, method_name)
2001 if method_name[0] != '_' and hasattr(method, 'async') \
2002 and method.async == True:
2003 self.method_map[method.api] = method
2005 def _dispatch(self, method, args):
2006 """Overridden method so that SimpleXMLRPCServer will
2007 resolve methods through this method rather than through
2008 inspection.
2010 @param method: marshalled method name from XMLRPC.
2011 @param args: marshalled arguments from XMLRPC.
2012 """
2014 # Only deal with method names that start with "Async."
2015 if not method.startswith(self.method_prefix):
2016 raise Exception('Method %s not supported' % method)
2018 # Require 'session' argument to be present.
2019 if len(args) < 1:
2020 raise Exception('Not enough arguments')
2022 # Lookup synchronous version of the method
2023 synchronous_method_name = method[len(self.method_prefix):]
2024 if synchronous_method_name not in self.method_map:
2025 raise Exception('Method %s not supported' % method)
2027 method = self.method_map[synchronous_method_name]
2029 # Validate the session before proceeding
2030 session = args[0]
2031 if not auth_manager().is_session_valid(session):
2032 return xen_api_error(['SESSION_INVALID', session])
2034 # create and execute the task, and return task_uuid
2035 return_type = getattr(method, 'return_type', None)
2036 task_uuid = XendTaskManager.create_task(method, args,
2037 synchronous_method_name,
2038 return_type,
2039 synchronous_method_name)
2040 return xen_api_success(task_uuid)
2043 # Auto generate some stubs based on XendAPI introspection
2045 if __name__ == "__main__":
2046 def output(line):
2047 print ' ' + line
2049 classes = ['VDI', 'SR']
2050 for cls in classes:
2051 ro_attrs = getattr(XendAPI, '%s_attr_ro' % cls, [])
2052 rw_attrs = getattr(XendAPI, '%s_attr_rw' % cls, [])
2053 methods = getattr(XendAPI, '%s_methods' % cls, [])
2054 funcs = getattr(XendAPI, '%s_funcs' % cls, [])
2056 ref = '%s_ref' % cls
2058 for attr_name in ro_attrs + rw_attrs + XendAPI.Base_attr_ro:
2059 getter_name = '%s_get_%s' % (cls, attr_name)
2060 output('def %s(self, session, %s):' % (getter_name, ref))
2061 output(' return xen_api_todo()')
2063 for attr_name in rw_attrs + XendAPI.Base_attr_rw:
2064 setter_name = '%s_set_%s' % (cls, attr_name)
2065 output('def %s(self, session, %s, value):' % (setter_name, ref))
2066 output(' return xen_api_todo()')
2068 for method_name in methods + XendAPI.Base_methods:
2069 method_full_name = '%s_%s' % (cls,method_name)
2070 output('def %s(self, session, %s):' % (method_full_name, ref))
2071 output(' return xen_api_todo()')
2073 for func_name in funcs + XendAPI.Base_funcs:
2074 func_full_name = '%s_%s' % (cls, func_name)
2075 output('def %s(self, session):' % func_full_name)
2076 output(' return xen_api_todo()')