ia64/xen-unstable

view tools/python/xen/xend/XendAPI.py @ 13207:51ea6202c4f2

Fix return types for VBD.get_record and VIF.get_record.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author Ewan Mellor <ewan@xensource.com>
date Thu Dec 28 15:23:31 2006 +0000 (2006-12-28)
parents a8e853aecb3e
children 615109616bb6
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
24 from xen.xend import XendDomain, XendDomainInfo, XendNode
25 from xen.xend import XendLogging
27 from xen.xend.XendAuthSessions import instance as auth_manager
28 from xen.xend.XendError import *
29 from xen.xend.XendClient import ERROR_INVALID_DOMAIN
30 from xen.xend.XendLogging import log
32 from xen.xend.XendAPIConstants import *
33 from xen.util.xmlrpclib2 import stringify
35 AUTH_NONE = 'none'
36 AUTH_PAM = 'pam'
38 argcounts = {}
40 # ------------------------------------------
41 # Utility Methods for Xen API Implementation
42 # ------------------------------------------
44 def xen_api_success(value):
45 """Wraps a return value in XenAPI format."""
46 if value is None:
47 s = ''
48 else:
49 s = stringify(value)
50 return {"Status": "Success", "Value": s}
52 def xen_api_success_void():
53 """Return success, but caller expects no return value."""
54 return xen_api_success("")
56 def xen_api_error(error):
57 """Wraps an error value in XenAPI format."""
58 if type(error) == tuple:
59 error = list(error)
60 if type(error) != list:
61 error = [error]
62 if len(error) == 0:
63 error = ['INTERNAL_ERROR', 'Empty list given to xen_api_error']
65 return { "Status": "Failure",
66 "ErrorDescription": [str(x) for x in error] }
69 def xen_api_todo():
70 """Temporary method to make sure we track down all the TODOs"""
71 return {"Status": "Error", "ErrorDescription": XEND_ERROR_TODO}
73 # ---------------------------------------------------
74 # Python Method Decorators for input value validation
75 # ---------------------------------------------------
77 def trace(func, api_name = ''):
78 """Decorator to trace XMLRPC Xen API methods.
80 @param func: function with any parameters
81 @param api_name: name of the api call for debugging.
82 """
83 if hasattr(func, 'api'):
84 api_name = func.api
85 def trace_func(self, *args, **kwargs):
86 log.debug('%s: %s' % (api_name, args))
87 return func(self, *args, **kwargs)
88 trace_func.api = api_name
89 return trace_func
92 def catch_typeerror(func):
93 """Decorator to catch any TypeErrors and translate them into Xen-API
94 errors.
96 @param func: function with params: (self, ...)
97 @rtype: callable object
98 """
99 def f(self, *args, **kwargs):
100 try:
101 return func(self, *args, **kwargs)
102 except TypeError, exn:
103 #log.exception('catch_typeerror')
104 if hasattr(func, 'api') and func.api in argcounts:
105 # Assume that if the exception was thrown inside this
106 # file, then it is due to an invalid call from the client,
107 # but if it was thrown elsewhere, then it's an internal
108 # error (which will be handled further up).
109 tb = sys.exc_info()[2]
110 try:
111 sourcefile = traceback.extract_tb(tb)[-1][0]
112 if sourcefile == inspect.getsourcefile(XendAPI):
113 return xen_api_error(
114 ['MESSAGE_PARAMETER_COUNT_MISMATCH',
115 func.api, argcounts[func.api],
116 len(args) + len(kwargs)])
117 finally:
118 del tb
119 raise
121 return f
124 def session_required(func):
125 """Decorator to verify if session is valid before calling method.
127 @param func: function with params: (self, session, ...)
128 @rtype: callable object
129 """
130 def check_session(self, session, *args, **kwargs):
131 if auth_manager().is_session_valid(session):
132 return func(self, session, *args, **kwargs)
133 else:
134 return xen_api_error(['SESSION_INVALID', session])
136 return check_session
139 def _is_valid_ref(ref, validator):
140 return type(ref) == str and validator(ref)
142 def _check_ref(validator, errcode, func, api, session, ref, *args, **kwargs):
143 if _is_valid_ref(ref, validator):
144 return func(api, session, ref, *args, **kwargs)
145 else:
146 return xen_api_error([errcode, ref])
149 def valid_host(func):
150 """Decorator to verify if host_ref is valid before calling method.
152 @param func: function with params: (self, session, host_ref, ...)
153 @rtype: callable object
154 """
155 return lambda *args, **kwargs: \
156 _check_ref(XendNode.instance().is_valid_host,
157 'HOST_HANDLE_INVALID', func, *args, **kwargs)
159 def valid_host_cpu(func):
160 """Decorator to verify if host_cpu_ref is valid before calling method.
162 @param func: function with params: (self, session, host_cpu_ref, ...)
163 @rtype: callable object
164 """
165 return lambda *args, **kwargs: \
166 _check_ref(XendNode.instance().is_valid_cpu,
167 'HOST_CPU_HANDLE_INVALID', func, *args, **kwargs)
169 def valid_vm(func):
170 """Decorator to verify if vm_ref is valid before calling method.
172 @param func: function with params: (self, session, vm_ref, ...)
173 @rtype: callable object
174 """
175 return lambda *args, **kwargs: \
176 _check_ref(XendDomain.instance().is_valid_vm,
177 'VM_HANDLE_INVALID', func, *args, **kwargs)
179 def valid_network(func):
180 """Decorator to verify if network_ref is valid before calling method.
182 @param func: function with params: (self, session, network_ref, ...)
183 @rtype: callable object
184 """
185 return lambda *args, **kwargs: \
186 _check_ref(XendNode.instance().is_valid_network,
187 'NETWORK_HANDLE_INVALID', func, *args, **kwargs)
189 def valid_vbd(func):
190 """Decorator to verify if vbd_ref is valid before calling method.
192 @param func: function with params: (self, session, vbd_ref, ...)
193 @rtype: callable object
194 """
195 return lambda *args, **kwargs: \
196 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vbd', r),
197 'VBD_HANDLE_INVALID', func, *args, **kwargs)
199 def valid_vif(func):
200 """Decorator to verify if vif_ref is valid before calling method.
202 @param func: function with params: (self, session, vif_ref, ...)
203 @rtype: callable object
204 """
205 return lambda *args, **kwargs: \
206 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vif', r),
207 'VIF_HANDLE_INVALID', func, *args, **kwargs)
209 def valid_vdi(func):
210 """Decorator to verify if vdi_ref is valid before calling method.
212 @param func: function with params: (self, session, vdi_ref, ...)
213 @rtype: callable object
214 """
215 return lambda *args, **kwargs: \
216 _check_ref(XendNode.instance().get_sr().is_valid_vdi,
217 'VDI_HANDLE_INVALID', func, *args, **kwargs)
219 def valid_vtpm(func):
220 """Decorator to verify if vtpm_ref is valid before calling method.
222 @param func: function with params: (self, session, vtpm_ref, ...)
223 @rtype: callable object
224 """
225 return lambda *args, **kwargs: \
226 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vtpm', r),
227 'VTPM_HANDLE_INVALID', func, *args, **kwargs)
229 def valid_sr(func):
230 """Decorator to verify if sr_ref is valid before calling method.
232 @param func: function with params: (self, session, sr_ref, ...)
233 @rtype: callable object
234 """
235 return lambda *args, **kwargs: \
236 _check_ref(lambda r: XendNode.instance().get_sr().uuid == r,
237 'SR_HANDLE_INVALID', func, *args, **kwargs)
239 def valid_pif(func):
240 """Decorator to verify if sr_ref is valid before calling
241 method.
243 @param func: function with params: (self, session, sr_ref)
244 @rtype: callable object
245 """
246 return lambda *args, **kwargs: \
247 _check_ref(lambda r: r in XendNode.instance().pifs,
248 'PIF_HANDLE_INVALID', func, *args, **kwargs)
250 # -----------------------------
251 # Bridge to Legacy XM API calls
252 # -----------------------------
254 def do_vm_func(fn_name, vm_ref, *args, **kwargs):
255 """Helper wrapper func to abstract away from repetitive code.
257 @param fn_name: function name for XendDomain instance
258 @type fn_name: string
259 @param vm_ref: vm_ref
260 @type vm_ref: string
261 @param *args: more arguments
262 @type *args: tuple
263 """
264 try:
265 xendom = XendDomain.instance()
266 fn = getattr(xendom, fn_name)
267 xendom.do_legacy_api_with_uuid(fn, vm_ref, *args, **kwargs)
268 return xen_api_success_void()
269 except VMBadState, exn:
270 return xen_api_error(['VM_BAD_POWER_STATE', vm_ref, exn.expected,
271 exn.actual])
274 class XendAPI:
275 """Implementation of the Xen-API in Xend. Expects to be
276 used via XMLRPCServer.
278 All methods that need a valid session are marked with
279 a L{session_required} decorator that will
280 transparently perform the required session authentication.
282 We need to support Python <2.4, so we use the old decorator syntax.
284 All XMLRPC accessible methods require an 'api' attribute and
285 is set to the XMLRPC function name which the method implements.
286 """
288 def __init__(self, auth):
289 self.auth = auth
292 Base_attr_ro = ['uuid']
293 Base_attr_rw = []
294 Base_methods = ['destroy', 'get_by_uuid', 'get_record']
295 Base_funcs = ['create', 'get_all']
297 # Xen API: Class Session
298 # ----------------------------------------------------------------
299 # NOTE: Left unwrapped by __init__
301 session_attr_ro = ['this_host', 'this_user']
302 session_methods = ['logout']
303 # session_funcs = ['login_with_password']
305 def session_login_with_password(self, *args):
306 if len(args) != 2:
307 return xen_api_error(
308 ['MESSAGE_PARAMETER_COUNT_MISMATCH',
309 'session.login_with_password', 2, len(args)])
310 username = args[0]
311 password = args[1]
312 try:
313 session = (self.auth == AUTH_NONE and
314 auth_manager().login_unconditionally(username) or
315 auth_manager().login_with_password(username, password))
316 return xen_api_success(session)
317 except XendError, e:
318 return xen_api_error(['SESSION_AUTHENTICATION_FAILED'])
319 session_login_with_password.api = 'session.login_with_password'
322 # object methods
323 def session_logout(self, session):
324 auth_manager().logout(session)
325 return xen_api_success_void()
326 def session_destroy(self, session):
327 return xen_api_error(XEND_ERROR_UNSUPPORTED)
328 def session_get_record(self, session):
329 record = {'this_host': XendNode.instance().uuid,
330 'this_user': auth_manager().get_user(session)}
331 return xen_api_success(record)
333 # attributes (ro)
334 def session_get_this_host(self, session):
335 return xen_api_success(XendNode.instance().uuid)
336 def session_get_this_user(self, session):
337 user = auth_manager().get_user(session)
338 if user:
339 return xen_api_success(user)
340 return xen_api_error(['SESSION_INVALID', session])
343 # Xen API: Class User
344 # ----------------------------------------------------------------
345 # TODO: NOT IMPLEMENTED YET
347 # Xen API: Class Tasks
348 # ----------------------------------------------------------------
349 # TODO: NOT IMPLEMENTED YET
351 # Xen API: Class Host
352 # ----------------------------------------------------------------
354 host_attr_ro = ['software_version',
355 'resident_VMs',
356 'host_CPUs']
358 host_attr_rw = ['name_label',
359 'name_description']
361 host_methods = ['disable',
362 'enable',
363 'reboot',
364 'shutdown']
366 host_funcs = ['get_by_name_label']
368 # attributes
369 def host_get_name_label(self, session, host_ref):
370 return xen_api_success(XendNode.instance().name)
371 def host_set_name_label(self, session, host_ref, new_name):
372 XendNode.instance().set_name(new_name)
373 return xen_api_success_void()
374 def host_get_name_description(self, session, host_ref):
375 return xen_api_success(XendNode.instance().description)
376 def host_set_name_description(self, session, host_ref, new_desc):
377 XendNode.instance().set_description(new_desc)
378 return xen_api_success_void()
379 def host_get_software_version(self, session, host_ref):
380 return xen_api_success(XendNode.instance().xen_version())
381 def host_get_resident_VMs(self, session, host_ref):
382 return xen_api_success(XendDomain.instance().get_domain_refs())
383 def host_get_host_CPUs(self, session, host_ref):
384 return xen_api_success(XendNode.instance().get_host_cpu_refs())
386 # object methods
387 def host_destroy(self, session, host_ref):
388 return xen_api_error(XEND_ERROR_UNSUPPORTED)
389 def host_disable(self, session, host_ref):
390 XendDomain.instance().set_allow_new_domains(False)
391 return xen_api_success_void()
392 def host_enable(self, session, host_ref):
393 XendDomain.instance().set_allow_new_domains(True)
394 return xen_api_success_void()
395 def host_reboot(self, session, host_ref):
396 if not XendDomain.instance().allow_new_domains():
397 return xen_api_error(XEND_ERROR_HOST_RUNNING)
398 return xen_api_error(XEND_ERROR_UNSUPPORTED)
399 def host_shutdown(self, session, host_ref):
400 if not XendDomain.instance().allow_new_domains():
401 return xen_api_error(XEND_ERROR_HOST_RUNNING)
402 return xen_api_error(XEND_ERROR_UNSUPPORTED)
403 def host_get_record(self, session, host_ref):
404 node = XendNode.instance()
405 dom = XendDomain.instance()
406 record = {'uuid': node.uuid,
407 'name_label': node.name,
408 'name_description': '',
409 'software_version': node.xen_version(),
410 'resident_VMs': dom.get_domain_refs(),
411 'host_CPUs': node.get_host_cpu_refs()}
412 return xen_api_success(record)
414 # class methods
415 def host_get_all(self, session):
416 return xen_api_success((XendNode.instance().uuid,))
417 def host_create(self, session, struct):
418 return xen_api_error(XEND_ERROR_UNSUPPORTED)
420 # Xen API: Class Host_CPU
421 # ----------------------------------------------------------------
423 host_cpu_attr_ro = ['host',
424 'number',
425 'features',
426 'utilisation']
428 # attributes
429 def host_cpu_get_uuid(self, session, host_cpu_ref):
430 uuid = XendNode.instance().get_host_cpu_uuid(host_cpu_ref)
431 return xen_api_success(uuid)
432 def host_cpu_get_host(self, session, host_cpu_ref):
433 return xen_api_success(XendNode.instance().uuid)
434 def host_cpu_get_features(self, session, host_cpu_ref):
435 features = XendNode.instance().get_host_cpu_features(host_cpu_ref)
436 return xen_api_success(features)
437 def host_cpu_get_utilisation(self, session, host_cpu_ref):
438 util = XendNode.instance().get_host_cpu_load(host_cpu_ref)
439 return xen_api_success(util)
440 def host_cpu_get_number(self, session, host_cpu_ref):
441 num = XendNode.instance().get_host_cpu_number(host_cpu_ref)
442 return xen_api_success(num)
444 # object methods
445 def host_cpu_destroy(self, session, host_cpu_ref):
446 return xen_api_error(XEND_ERROR_UNSUPPORTED)
447 def host_cpu_get_record(self, session, host_cpu_ref):
448 node = XendNode.instance()
449 record = {'uuid': host_cpu_ref,
450 'host': node.uuid,
451 'number': node.get_host_cpu_number(host_cpu_ref),
452 'features': node.get_host_cpu_features(host_cpu_ref),
453 'utilisation': node.get_host_cpu_load(host_cpu_ref)}
454 return xen_api_success(record)
456 # class methods
457 def host_cpu_get_all(self, session):
458 return xen_api_success(XendNode.instance().get_host_cpu_refs())
459 def host_cpu_create(self, session, struct):
460 return xen_api_error(XEND_ERROR_UNSUPPORTED)
463 # Xen API: Class network
464 # ----------------------------------------------------------------
466 network_attr_ro = ['VIFs', 'PIFs']
467 network_attr_rw = ['name_label',
468 'name_description',
469 'default_gateway',
470 'default_netmask']
472 def network_create(self, _, name_label, name_description,
473 default_gateway, default_netmask):
474 return xen_api_success(
475 XendNode.instance().network_create(name_label, name_description,
476 default_gateway,
477 default_netmask))
479 def network_destroy(self, _, ref):
480 return xen_api_success(XendNode.instance().network_destroy(ref))
482 def _get_network(self, ref):
483 return XendNode.instance().get_network(ref)
485 def network_get_all(self, _):
486 return xen_api_success(XendNode.instance().get_network_refs())
488 def network_get_record(self, _, ref):
489 return xen_api_success(
490 XendNode.instance().get_network(ref).get_record())
492 def network_get_name_label(self, _, ref):
493 return xen_api_success(self._get_network(ref).name_label)
495 def network_get_name_description(self, _, ref):
496 return xen_api_success(self._get_network(ref).name_description)
498 def network_get_default_gateway(self, _, ref):
499 return xen_api_success(self._get_network(ref).default_gateway)
501 def network_get_default_netmask(self, _, ref):
502 return xen_api_success(self._get_network(ref).default_netmask)
504 def network_get_VIFs(self, _, ref):
505 return xen_api_success(self._get_network(ref).get_VIF_UUIDs())
507 def network_get_PIFs(self, session, ref):
508 return xen_api_success(self._get_network(ref).get_PIF_UUIDs())
510 def network_set_name_label(self, _, ref, val):
511 return xen_api_success(self._get_network(ref).set_name_label(val))
513 def network_set_name_description(self, _, ref, val):
514 return xen_api_success(self._get_network(ref).set_name_description(val))
516 def network_set_default_gateway(self, _, ref, val):
517 return xen_api_success(self._get_network(ref).set_default_gateway(val))
519 def network_set_default_netmask(self, _, ref, val):
520 return xen_api_success(self._get_network(ref).set_default_netmask(val))
523 # Xen API: Class PIF
524 # ----------------------------------------------------------------
526 PIF_attr_ro = ['io_read_kbs',
527 'io_write_kbs']
528 PIF_attr_rw = ['name',
529 'network',
530 'host',
531 'MAC',
532 'MTU',
533 'VLAN']
535 PIF_attr_inst = PIF_attr_rw
537 PIF_methods = ['create_VLAN']
539 def _get_PIF(self, ref):
540 return XendNode.instance().pifs[ref]
542 def PIF_create(self, _, name, network_uuid, host_uuid, mac, mtu, vlan):
543 node = XendNode.instance()
544 if host_uuid != node.uuid:
545 return xen_api_error([HOST_HANDLE_INVALID, host_uuid])
547 elif _is_valid_ref(network_uuid, node.is_valid_network):
548 network = node.get_network(network_uuid)
549 return xen_api_success(node.PIF_create(name, mtu, vlan, mac,
550 network))
551 else:
552 return xen_api_error([NETWORK_HANDLE_INVALID, network_uuid])
554 def PIF_destroy(self, _, ref):
555 return xen_api_success(XendNode.instance().PIF_destroy(ref))
557 # object methods
558 def PIF_get_record(self, _, ref):
559 return xen_api_success(self._get_PIF(ref).get_record())
561 def PIF_get_all(self, _):
562 return xen_api_success(XendNode.instance().pifs.keys())
564 def PIF_get_name(self, _, ref):
565 return xen_api_success(self._get_PIF(ref).name)
567 def PIF_get_network(self, _, ref):
568 return xen_api_success(self._get_PIF(ref).network.uuid)
570 def PIF_get_host(self, _, ref):
571 return xen_api_success(self._get_PIF(ref).host.uuid)
573 def PIF_get_MAC(self, _, ref):
574 return xen_api_success(self._get_PIF(ref).mac)
576 def PIF_get_MTU(self, _, ref):
577 return xen_api_success(self._get_PIF(ref).mtu)
579 def PIF_get_VLAN(self, _, ref):
580 return xen_api_success(self._get_PIF(ref).vlan)
582 def PIF_get_io_read_kbs(self, _, ref):
583 return xen_api_success(self._get_PIF(ref).get_io_read_kbs())
585 def PIF_get_io_write_kbs(self, _, ref):
586 return xen_api_success(self._get_PIF(ref).get_io_write_kbs())
588 def PIF_set_name(self, _, ref, name):
589 return xen_api_success(self._get_PIF(ref).set_name(name))
591 def PIF_set_MAC(self, _, ref, mac):
592 return xen_api_success(self._get_PIF(ref).set_mac(name))
594 def PIF_set_MTU(self, _, ref, mtu):
595 return xen_api_success(self._get_PIF(ref).set_mtu(name))
597 def PIF_create_VLAN(self, _, ref, network, vlan):
598 if _is_valid_ref(network, XendNode.instance().is_valid_network):
599 return xen_api_success(XendNode.instance().PIF_create_VLAN(
600 ref, network, vlan))
601 else:
602 return xen_api_error([NETWORK_HANDLE_INVALID, network_uuid])
605 # Xen API: Class VM
606 # ----------------------------------------------------------------
608 VM_attr_ro = ['power_state',
609 'resident_on',
610 'memory_actual',
611 'memory_static_max',
612 'memory_static_min',
613 'VCPUs_number',
614 'VCPUs_utilisation',
615 'VCPUs_features_required',
616 'VCPUs_can_use',
617 'consoles',
618 'VIFs',
619 'VBDs',
620 'VTPMs',
621 'PCI_bus',
622 'tools_version',
623 ]
625 VM_attr_rw = ['name_label',
626 'name_description',
627 'user_version',
628 'is_a_template',
629 'auto_power_on',
630 'memory_dynamic_max',
631 'memory_dynamic_min',
632 'VCPUs_policy',
633 'VCPUs_params',
634 'VCPUs_features_force_on',
635 'VCPUs_features_force_off',
636 'actions_after_shutdown',
637 'actions_after_reboot',
638 'actions_after_suspend',
639 'actions_after_crash',
640 'PV_bootloader',
641 'PV_kernel',
642 'PV_ramdisk',
643 'PV_args',
644 'PV_bootloader_args',
645 'HVM_boot',
646 'platform_std_VGA',
647 'platform_serial',
648 'platform_localtime',
649 'platform_clock_offset',
650 'platform_enable_audio',
651 'platform_keymap',
652 'otherConfig']
654 VM_methods = ['clone',
655 'start',
656 'pause',
657 'unpause',
658 'clean_shutdown',
659 'clean_reboot',
660 'hard_shutdown',
661 'hard_reboot',
662 'suspend',
663 'resume']
665 VM_funcs = ['get_by_name_label']
667 # parameters required for _create()
668 VM_attr_inst = [
669 'name_label',
670 'name_description',
671 'user_version',
672 'is_a_template',
673 'memory_static_max',
674 'memory_dynamic_max',
675 'memory_dynamic_min',
676 'memory_static_min',
677 'VCPUs_policy',
678 'VCPUs_params',
679 'VCPUs_features_required',
680 'VCPUs_features_can_use',
681 'VCPUs_features_force_on',
682 'VCPUs_features_force_off',
683 'actions_after_shutdown',
684 'actions_after_reboot',
685 'actions_after_suspend',
686 'actions_after_crash',
687 'PV_bootloader',
688 'PV_kernel',
689 'PV_ramdisk',
690 'PV_args',
691 'PV_bootloader_args',
692 'HVM_boot',
693 'platform_std_VGA',
694 'platform_serial',
695 'platform_localtime',
696 'platform_clock_offset',
697 'platform_enable_audio',
698 'platform_keymap',
699 'grub_cmdline',
700 'PCI_bus',
701 'otherConfig']
703 def VM_get(self, name, session, vm_ref):
704 return xen_api_success(
705 XendDomain.instance().get_vm_by_uuid(vm_ref).info[name])
707 def VM_set(self, name, session, vm_ref, value):
708 xd = XendDomain.instance()
709 dominfo = xd.get_vm_by_uuid(vm_ref)
710 dominfo.info[name] = value
711 xd.managed_config_save(dominfo)
712 return xen_api_success_void()
714 # attributes (ro)
715 def VM_get_power_state(self, session, vm_ref):
716 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
717 return xen_api_success(dom.get_power_state())
719 def VM_get_resident_on(self, session, vm_ref):
720 return xen_api_success(XendNode.instance().uuid)
722 def VM_get_memory_actual(self, session, vm_ref):
723 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
724 return xen_api_todo() # unsupported by xc
726 def VM_get_memory_static_max(self, session, vm_ref):
727 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
728 return xen_api_success(dom.get_memory_static_max())
730 def VM_get_memory_static_min(self, session, vm_ref):
731 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
732 return xen_api_success(dom.get_memory_static_min())
734 def VM_get_VCPUs_number(self, session, vm_ref):
735 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
736 return xen_api_success(dom.getVCpuCount())
738 def VM_get_VCPUs_utilisation(self, session, vm_ref):
739 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
740 return xen_api_success(dom.get_vcpus_util())
742 def VM_get_VCPUs_features_required(self, session, vm_ref):
743 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
744 return xen_api_todo() # unsupported by xc
746 def VM_get_VCPUs_can_use(self, session, vm_ref):
747 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
748 return xen_api_todo() # unsupported by xc
750 def VM_get_VIFs(self, session, vm_ref):
751 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
752 return xen_api_success(dom.get_vifs())
754 def VM_get_VBDs(self, session, vm_ref):
755 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
756 return xen_api_success(dom.get_vbds())
758 def VM_get_VTPMs(self, session, vm_ref):
759 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
760 return xen_api_success(dom.get_vtpms())
762 def VM_get_PCI_bus(self, session, vm_ref):
763 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
764 return xen_api_todo() # unsupported by xc
766 def VM_get_tools_version(self, session, vm_ref):
767 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
768 return xen_api_todo()
770 # attributes (rw)
771 def VM_get_name_label(self, session, vm_ref):
772 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
773 return xen_api_success(dom.getName())
775 def VM_get_name_description(self, session, vm_ref):
776 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
777 return xen_api_todo()
779 def VM_get_user_version(self, session, vm_ref):
780 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
781 return xen_api_todo()
783 def VM_get_is_a_template(self, session, vm_ref):
784 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
785 return xen_api_todo()
787 def VM_get_memory_dynamic_max(self, session, vm_ref):
788 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
789 return xen_api_success(dom.get_memory_dynamic_max())
791 def VM_get_memory_dynamic_min(self, session, vm_ref):
792 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
793 return xen_api_success(dom.get_memory_dynamic_min())
795 def VM_get_VCPUs_policy(self, session, vm_ref):
796 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
797 return xen_api_todo() # need to access scheduler
799 def VM_get_VCPUs_params(self, session, vm_ref):
800 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
801 return xen_api_todo() # need access to scheduler
803 def VM_get_VCPUs_features_force_on(self, session, vm_ref):
804 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
805 return xen_api_todo()
807 def VM_get_VCPUs_features_force_off(self, session, vm_ref):
808 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
809 return xen_api_todo()
811 def VM_get_actions_after_shutdown(self, session, vm_ref):
812 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
813 return xen_api_success(dom.get_on_shutdown())
815 def VM_get_actions_after_reboot(self, session, vm_ref):
816 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
817 return xen_api_success(dom.get_on_reboot())
819 def VM_get_actions_after_suspend(self, session, vm_ref):
820 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
821 return xen_api_success(dom.get_on_suspend())
823 def VM_get_actions_after_crash(self, session, vm_ref):
824 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
825 return xen_api_success(dom.get_on_crash())
827 def VM_get_PV_bootloader(self, session, vm_ref):
828 return self.VM_get('PV_bootloader', session, vm_ref)
830 def VM_get_PV_kernel(self, session, vm_ref):
831 return self.VM_get('PV_kernel', session, vm_ref)
833 def VM_get_PV_ramdisk(self, session, vm_ref):
834 return self.VM_get('PV_ramdisk', session, vm_ref)
836 def VM_get_PV_args(self, session, vm_ref):
837 return self.VM_get('PV_args', session, vm_ref)
839 def VM_get_PV_bootloader_args(self, session, vm_ref):
840 return self.VM_get('PV_bootloader_args', session, vm_ref)
842 def VM_get_HVM_boot(self, session, vm_ref):
843 return self.VM_get('HVM_boot', session, vm_ref)
845 def VM_get_platform_std_VGA(self, session, vm_ref):
846 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
847 return xen_api_todo()
849 def VM_get_platform_serial(self, session, vm_ref):
850 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
851 return xen_api_todo()
853 def VM_get_platform_localtime(self, session, vm_ref):
854 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
855 return xen_api_todo()
857 def VM_get_platform_clock_offset(self, session, vm_ref):
858 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
859 return xen_api_todo()
861 def VM_get_platform_enable_audio(self, session, vm_ref):
862 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
863 return xen_api_todo()
865 def VM_get_platform_keymap(self, session, vm_ref):
866 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
867 return xen_api_todo()
869 def VM_get_otherConfig(self, session, vm_ref):
870 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
871 return xen_api_todo()
873 def VM_set_name_label(self, session, vm_ref, label):
874 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
875 dom.setName(label)
876 return xen_api_success_void()
878 def VM_set_name_description(self, session, vm_ref, desc):
879 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
880 return xen_api_todo()
882 def VM_set_user_version(self, session, vm_ref, ver):
883 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
884 return xen_api_todo()
886 def VM_set_is_a_template(self, session, vm_ref, is_template):
887 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
888 return xen_api_todo()
890 def VM_set_memory_dynamic_max(self, session, vm_ref, mem):
891 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
892 return xen_api_todo()
894 def VM_set_memory_dynamic_min(self, session, vm_ref, mem):
895 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
896 return xen_api_todo()
898 def VM_set_VCPUs_policy(self, session, vm_ref, policy):
899 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
900 return xen_api_todo()
902 def VM_set_VCPUs_params(self, session, vm_ref, params):
903 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
904 return xen_api_todo()
906 def VM_set_VCPUs_features_force_on(self, session, vm_ref, features):
907 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
908 return xen_api_todo()
910 def VM_set_VCPUs_features_force_off(self, session, vm_ref, features):
911 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
912 return xen_api_todo()
914 def VM_set_actions_after_shutdown(self, session, vm_ref, action):
915 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
916 return xen_api_todo()
918 def VM_set_actions_after_reboot(self, session, vm_ref, action):
919 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
920 return xen_api_todo()
922 def VM_set_actions_after_suspend(self, session, vm_ref, action):
923 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
924 return xen_api_todo()
926 def VM_set_actions_after_crash(self, session, vm_ref, action):
927 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
928 return xen_api_success_void()
930 def VM_set_HVM_boot(self, session, vm_ref, value):
931 return self.VM_set('HVM_boot', session, vm_ref, value)
933 def VM_set_PV_bootloader(self, session, vm_ref, value):
934 return self.VM_set('PV_bootloader', session, vm_ref, value)
936 def VM_set_PV_kernel(self, session, vm_ref, value):
937 return self.VM_set('PV_kernel', session, vm_ref, value)
939 def VM_set_PV_ramdisk(self, session, vm_ref, value):
940 return self.VM_set('PV_ramdisk', session, vm_ref, value)
942 def VM_set_PV_args(self, session, vm_ref, value):
943 return self.VM_set('PV_args', session, vm_ref, value)
945 def VM_set_PV_bootloader_args(self, session, vm_ref, value):
946 return self.VM_set('PV_bootloader_args', session, vm_ref, value)
948 def VM_set_platform_std_VGA(self, session, vm_ref):
949 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
950 return xen_api_todo()
952 def VM_set_platform_serial(self, session, vm_ref, serial):
953 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
954 return xen_api_todo()
956 def VM_set_platform_localtime(self, session, vm_ref, localtime):
957 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
958 return xen_api_todo()
960 def VM_set_platform_clock_offset(self, session, vm_ref, clock_offset):
961 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
962 return xen_api_todo()
964 def VM_set_platform_enable_audio(self, session, vm_ref, enable_audio):
965 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
966 return xen_api_todo()
968 def VM_set_otherConfig(self, session, vm_ref):
969 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
970 return xen_api_todo()
972 # class methods
973 def VM_get_all(self, session):
974 refs = [d.get_uuid() for d in XendDomain.instance().list('all')]
975 return xen_api_success(refs)
977 def VM_get_by_name_label(self, session, label):
978 xendom = XendDomain.instance()
979 dom = xendom.domain_lookup_nr(label)
980 if dom:
981 return xen_api_success([dom.get_uuid()])
982 return xen_api_success([])
984 def VM_create(self, session, vm_struct):
985 xendom = XendDomain.instance()
986 domuuid = xendom.create_domain(vm_struct)
987 return xen_api_success(domuuid)
989 # object methods
990 def VM_get_record(self, session, vm_ref):
991 xendom = XendDomain.instance()
992 xeninfo = xendom.get_vm_by_uuid(vm_ref)
993 if not xeninfo:
994 return xen_api_error(['VM_HANDLE_INVALID', vm_ref])
996 record = {
997 'uuid': xeninfo.get_uuid(),
998 'power_state': xeninfo.get_power_state(),
999 'name_label': xeninfo.getName(),
1000 'name_description': xeninfo.getName(),
1001 'user_version': 1,
1002 'is_a_template': False,
1003 'auto_power_on': False,
1004 'resident_on': XendNode.instance().uuid,
1005 'memory_static_min': xeninfo.get_memory_static_min(),
1006 'memory_static_max': xeninfo.get_memory_static_max(),
1007 'memory_dynamic_min': xeninfo.get_memory_dynamic_min(),
1008 'memory_dynamic_max': xeninfo.get_memory_dynamic_max(),
1009 'memory_actual': xeninfo.get_memory_static_min(),
1010 'VCPUs_policy': xeninfo.get_vcpus_policy(),
1011 'VCPUs_params': xeninfo.get_vcpus_params(),
1012 'VCPUs_number': xeninfo.getVCpuCount(),
1013 'VCPUs_utilisation': xeninfo.get_vcpus_util(),
1014 'VCPUs_features_required': [],
1015 'VCPUs_features_can_use': [],
1016 'VCPUs_features_force_on': [],
1017 'VCPUs_features_force_off': [],
1018 'actions_after_shutdown': xeninfo.get_on_shutdown(),
1019 'actions_after_reboot': xeninfo.get_on_reboot(),
1020 'actions_after_suspend': xeninfo.get_on_suspend(),
1021 'actions_after_crash': xeninfo.get_on_crash(),
1022 'consoles': xeninfo.get_consoles(),
1023 'VIFs': xeninfo.get_vifs(),
1024 'VBDs': xeninfo.get_vbds(),
1025 'VTPMs': xeninfo.get_vtpms(),
1026 'PV_bootloader': xeninfo.info.get('PV_bootloader'),
1027 'PV_kernel': xeninfo.info.get('PV_kernel'),
1028 'PV_ramdisk': xeninfo.info.get('PV_ramdisk'),
1029 'PV_args': xeninfo.info.get('PV_args'),
1030 'PV_bootloader_args': xeninfo.info.get('PV_bootloader_args'),
1031 'HVM_boot': xeninfo.info.get('HVM_boot'),
1032 'platform_std_VGA': xeninfo.get_platform_std_vga(),
1033 'platform_serial': xeninfo.get_platform_serial(),
1034 'platform_localtime': xeninfo.get_platform_localtime(),
1035 'platform_clock_offset': xeninfo.get_platform_clock_offset(),
1036 'platform_enable_audio': xeninfo.get_platform_enable_audio(),
1037 'platform_keymap': xeninfo.get_platform_keymap(),
1038 'PCI_bus': xeninfo.get_pci_bus(),
1039 'tools_version': xeninfo.get_tools_version(),
1040 'otherConfig': xeninfo.get_other_config()
1042 return xen_api_success(record)
1044 def VM_clean_reboot(self, session, vm_ref):
1045 xendom = XendDomain.instance()
1046 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1047 xeninfo.shutdown("reboot")
1048 return xen_api_success_void()
1049 def VM_clean_shutdown(self, session, vm_ref):
1050 xendom = XendDomain.instance()
1051 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1052 xeninfo.shutdown("poweroff")
1053 return xen_api_success_void()
1054 def VM_clone(self, session, vm_ref):
1055 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1056 def VM_destroy(self, session, vm_ref):
1057 return do_vm_func("domain_delete", vm_ref)
1058 def VM_hard_reboot(self, session, vm_ref):
1059 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1060 def VM_hard_shutdown(self, session, vm_ref):
1061 return do_vm_func("domain_destroy", vm_ref)
1062 def VM_pause(self, session, vm_ref):
1063 return do_vm_func("domain_pause", vm_ref)
1064 def VM_resume(self, session, vm_ref, start_paused):
1065 return do_vm_func("domain_resume", vm_ref, start_paused = start_paused)
1066 def VM_start(self, session, vm_ref, start_paused):
1067 return do_vm_func("domain_start", vm_ref, start_paused = start_paused)
1068 def VM_suspend(self, session, vm_ref):
1069 return do_vm_func("domain_suspend", vm_ref)
1070 def VM_unpause(self, session, vm_ref):
1071 return do_vm_func("domain_unpause", vm_ref)
1073 # Xen API: Class VBD
1074 # ----------------------------------------------------------------
1075 # Note: accepts a non-API standard 'image' attribute to emulate
1076 # regular xm created VBDs
1078 VBD_attr_ro = ['image',
1079 'io_read_kbs',
1080 'io_write_kbs']
1081 VBD_attr_rw = ['VM',
1082 'VDI',
1083 'device',
1084 'mode',
1085 'driver']
1087 VBD_attr_inst = VBD_attr_rw + ['image']
1089 VBD_methods = ['media_change']
1091 # object methods
1092 def VBD_get_record(self, session, vbd_ref):
1093 xendom = XendDomain.instance()
1094 vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1095 if not vm:
1096 return xen_api_error(['VBD_HANDLE_INVALID', vbd_ref])
1097 cfg = vm.get_dev_xenapi_config('vbd', vbd_ref)
1098 if not cfg:
1099 return xen_api_error(['VBD_HANDLE_INVALID', vbd_ref])
1101 valid_vbd_keys = self.VBD_attr_ro + self.VBD_attr_rw + \
1102 self.Base_attr_ro + self.Base_attr_rw
1104 return_cfg = {}
1105 for k in cfg.keys():
1106 if k in valid_vbd_keys:
1107 return_cfg[k] = str(cfg[k])
1109 return xen_api_success(return_cfg)
1111 def VBD_media_change(self, session, vbd_ref, vdi_ref):
1112 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1114 # class methods
1115 def VBD_create(self, session, vbd_struct):
1116 xendom = XendDomain.instance()
1117 if not xendom.is_valid_vm(vbd_struct['VM']):
1118 return xen_api_error(['VM_HANDLE_INVALID', vbd_struct['VM']])
1120 dom = xendom.get_vm_by_uuid(vbd_struct['VM'])
1121 vbd_ref = ''
1122 try:
1123 if not vbd_struct.get('VDI', None):
1124 # this is a traditional VBD without VDI and SR
1125 vbd_ref = dom.create_vbd(vbd_struct)
1126 else:
1127 # new VBD via VDI/SR
1128 vdi_ref = vbd_struct.get('VDI')
1129 sr = XendNode.instance().get_sr()
1130 vdi_image = sr.xen_api_get_by_uuid(vdi_ref)
1131 if not vdi_image:
1132 return xen_api_error(['VDI_HANDLE_INVALID', vdi_ref])
1133 vdi_image = vdi_image.qcow_path
1134 vbd_ref = dom.create_vbd_with_vdi(vbd_struct, vdi_image)
1135 except XendError:
1136 return xen_api_todo()
1138 xendom.managed_config_save(dom)
1139 return xen_api_success(vbd_ref)
1141 # attributes (rw)
1142 def VBD_get_VM(self, session, vbd_ref):
1143 xendom = XendDomain.instance()
1144 return xen_api_success(xendom.get_dev_property('vbd', vbd_ref, 'VM'))
1146 def VBD_get_VDI(self, session, vbd_ref):
1147 return xen_api_todo()
1149 def VBD_get_device(self, session, vbd_ref):
1150 xendom = XendDomain.instance()
1151 return xen_api_success(xendom.get_dev_property('vbd', vbd_ref,
1152 'device'))
1153 def VBD_get_mode(self, session, vbd_ref):
1154 xendom = XendDomain.instance()
1155 return xen_api_success(xendom.get_dev_property('vbd', vbd_ref,
1156 'mode'))
1157 def VBD_get_driver(self, session, vbd_ref):
1158 xendom = XendDomain.instance()
1159 return xen_api_success(xendom.get_dev_property('vbd', vbd_ref,
1160 'driver'))
1162 # Xen API: Class VIF
1163 # ----------------------------------------------------------------
1165 VIF_attr_ro = ['io_read_kbs',
1166 'io_write_kbs']
1167 VIF_attr_rw = ['name',
1168 'type',
1169 'device',
1170 'network',
1171 'VM',
1172 'MAC',
1173 'MTU']
1175 VIF_attr_inst = VIF_attr_rw
1177 # object methods
1178 def VIF_get_record(self, session, vif_ref):
1179 xendom = XendDomain.instance()
1180 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
1181 if not vm:
1182 return xen_api_error(['VIF_HANDLE_INVALID', vif_ref])
1183 cfg = vm.get_dev_xenapi_config('vif', vif_ref)
1184 if not cfg:
1185 return xen_api_error(['VIF_HANDLE_INVALID', vif_ref])
1187 valid_vif_keys = self.VIF_attr_ro + self.VIF_attr_rw + \
1188 self.Base_attr_ro + self.Base_attr_rw
1190 return_cfg = {}
1191 for k in cfg.keys():
1192 if k in valid_vif_keys:
1193 return_cfg[k] = str(cfg[k])
1195 return xen_api_success(return_cfg)
1197 # class methods
1198 def VIF_create(self, session, vif_struct):
1199 xendom = XendDomain.instance()
1200 if xendom.is_valid_vm(vif_struct['VM']):
1201 dom = xendom.get_vm_by_uuid(vif_struct['VM'])
1202 try:
1203 vif_ref = dom.create_vif(vif_struct)
1204 xendom.managed_config_save(dom)
1205 return xen_api_success(vif_ref)
1206 except XendError:
1207 return xen_api_error(XEND_ERROR_TODO)
1208 else:
1209 return xen_api_error(['VM_HANDLE_INVALID', vif_struct['VM']])
1212 # Xen API: Class VDI
1213 # ----------------------------------------------------------------
1214 VDI_attr_ro = ['VBDs',
1215 'physical_utilisation',
1216 'sector_size',
1217 'type',
1218 'parent',
1219 'children']
1220 VDI_attr_rw = ['name_label',
1221 'name_description',
1222 'SR',
1223 'virtual_size',
1224 'sharable',
1225 'read_only']
1226 VDI_attr_inst = VDI_attr_ro + VDI_attr_rw
1228 VDI_methods = ['snapshot']
1229 VDI_funcs = ['get_by_name_label']
1231 def _get_VDI(self, ref):
1232 return XendNode.instance().get_sr().xen_api_get_by_uuid(ref)
1234 def VDI_get_VBDs(self, session, vdi_ref):
1235 return xen_api_todo()
1237 def VDI_get_physical_utilisation(self, session, vdi_ref):
1238 return xen_api_success(self._get_VDI(vdi_ref).
1239 get_physical_utilisation())
1241 def VDI_get_sector_size(self, session, vdi_ref):
1242 return xen_api_success(self._get_VDI(vdi_ref).sector_size)
1244 def VDI_get_type(self, session, vdi_ref):
1245 return xen_api_success(self._get_VDI(vdi_ref).type)
1247 def VDI_get_parent(self, session, vdi_ref):
1248 return xen_api_success(self._get_VDI(vdi_ref).parent)
1250 def VDI_get_children(self, session, vdi_ref):
1251 return xen_api_success(self._get_VDI(vdi_ref).children)
1253 def VDI_get_name_label(self, session, vdi_ref):
1254 return xen_api_success(self._get_VDI(vdi_ref).name_label)
1256 def VDI_get_name_description(self, session, vdi_ref):
1257 return xen_api_success(self._get_VDI(vdi_ref).name_description)
1259 def VDI_get_SR(self, session, vdi_ref):
1260 sr = XendNode.instance().get_sr()
1261 return xen_api_success(sr.uuid)
1263 def VDI_get_virtual_size(self, session, vdi_ref):
1264 return xen_api_success(self._get_VDI(vdi_ref).virtual_size)
1266 def VDI_get_sharable(self, session, vdi_ref):
1267 return xen_api_success(self._get_VDI(vdi_ref).sharable)
1269 def VDI_get_read_only(self, session, vdi_ref):
1270 return xen_api_success(self._get_VDI(vdi_ref).read_only)
1272 def VDI_set_name_label(self, session, vdi_ref, value):
1273 self._get_VDI(vdi_ref).name_label = value
1274 return xen_api_success_void()
1276 def VDI_set_name_description(self, session, vdi_ref, value):
1277 self._get_VDI(vdi_ref).name_description = value
1278 return xen_api_success_void()
1280 def VDI_set_SR(self, session, vdi_ref, value):
1281 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1283 def VDI_set_virtual_size(self, session, vdi_ref, value):
1284 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1286 def VDI_set_sharable(self, session, vdi_ref, value):
1287 self._get_VDI(vdi_ref).sharable = bool(value)
1288 return xen_api_success_void()
1290 def VDI_set_read_only(self, session, vdi_ref, value):
1291 self._get_VDI(vdi_ref).read_only = bool(value)
1292 return xen_api_success_void()
1294 # Object Methods
1295 def VDI_snapshot(self, session, vdi_ref):
1296 return xen_api_todo()
1298 def VDI_destroy(self, session, vdi_ref):
1299 sr = XendNode.instance().get_sr()
1300 sr.destroy_image(vdi_ref)
1301 return xen_api_success_void()
1303 def VDI_get_record(self, session, vdi_ref):
1304 sr = XendNode.instance().get_sr()
1305 image = sr.xen_api_get_by_uuid(vdi_ref)
1306 return xen_api_success({
1307 'uuid': vdi_ref,
1308 'name_label': image.name_label,
1309 'name_description': image.name_description,
1310 'SR': sr.uuid,
1311 'VBDs': [], # TODO
1312 'virtual_size': image.virtual_size,
1313 'physical_utilisation': image.physical_utilisation,
1314 'sector_size': image.sector_size,
1315 'type': image.type,
1316 'parent': image.parent,
1317 'children': image.children,
1318 'sharable': image.sharable,
1319 'read_only': image.read_only,
1320 })
1322 # Class Functions
1323 def VDI_create(self, session, vdi_struct):
1324 sr = XendNode.instance().get_sr()
1325 sr_ref = vdi_struct['SR']
1326 if sr.uuid != sr_ref:
1327 return xen_api_error(['SR_HANDLE_INVALID', vdi_struct['SR']])
1329 vdi_uuid = sr.create_image(vdi_struct)
1330 return xen_api_success(vdi_uuid)
1332 def VDI_get_all(self, session):
1333 sr = XendNode.instance().get_sr()
1334 return xen_api_success(sr.list_images())
1336 def VDI_get_by_name_label(self, session, name):
1337 sr = XendNode.instance().get_sr()
1338 image_uuid = sr.xen_api_get_by_name_label(name)
1339 if image_uuid:
1340 return xen_api_success([image_uuid])
1341 return xen_api_success([])
1344 # Xen API: Class VTPM
1345 # ----------------------------------------------------------------
1347 VTPM_attr_rw = [ ]
1348 VTPM_attr_ro = ['VM',
1349 'backend',
1350 'instance',
1351 'driver']
1353 VTPM_attr_inst = VTPM_attr_rw
1355 # object methods
1356 def VTPM_get_record(self, session, vtpm_ref):
1357 xendom = XendDomain.instance()
1358 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
1359 if not vm:
1360 return xen_api_error(['VTPM_HANDLE_INVALID', vtpm_ref])
1361 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
1362 if not cfg:
1363 return xen_api_error(['VTPM_HANDLE_INVALID', vtpm_ref])
1364 valid_vtpm_keys = self.VTPM_attr_ro + self.VTPM_attr_rw + \
1365 self.Base_attr_ro + self.Base_attr_rw
1366 for k in cfg.keys():
1367 if k not in valid_vtpm_keys:
1368 del cfg[k]
1370 return xen_api_success(cfg)
1372 # Class Functions
1373 def VTPM_get_instance(self, session, vtpm_ref):
1374 xendom = XendDomain.instance()
1375 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
1376 if not vm:
1377 return xen_api_error(['VTPM_HANDLE_INVALID', vtpm_ref])
1378 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
1379 if not cfg:
1380 return xen_api_error(['VTPM_HANDLE_INVALID', vtpm_ref])
1381 if cfg.has_key('instance'):
1382 instance = cfg['instance']
1383 else:
1384 instance = -1
1385 return xen_api_success(instance)
1387 def VTPM_get_driver(self, session, vtpm_ref):
1388 xendom = XendDomain.instance()
1389 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
1390 if not vm:
1391 return xen_api_error(['VTPM_HANDLE_INVALID', vtpm_ref])
1392 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
1393 if not cfg:
1394 return xen_api_error(['VTPM_HANDLE_INVALID', vtpm_ref])
1395 if cfg.has_key('type'):
1396 driver = cfg['type']
1397 else:
1398 driver = "Unknown"
1399 return xen_api_success(driver)
1401 def VTPM_get_backend(self, session, vtpm_ref):
1402 xendom = XendDomain.instance()
1403 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
1404 if not vm:
1405 return xen_api_error(['VTPM_HANDLE_INVALID', vtpm_ref])
1406 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
1407 if not cfg:
1408 return xen_api_error(['VTPM_HANDLE_INVALID', vtpm_ref])
1409 if cfg.has_key('backend'):
1410 backend = cfg['backend']
1411 else:
1412 backend = "Domain-0"
1413 return xen_api_success(backend)
1415 def VTPM_get_VM(self, session, vtpm_ref):
1416 xendom = XendDomain.instance()
1417 return xen_api_success(xendom.get_dev_property('vtpm', vtpm_ref, 'VM'))
1419 # class methods
1420 def VTPM_create(self, session, vtpm_struct):
1421 xendom = XendDomain.instance()
1422 if xendom.is_valid_vm(vtpm_struct['VM']):
1423 dom = xendom.get_vm_by_uuid(vtpm_struct['VM'])
1424 try:
1425 vtpm_ref = dom.create_vtpm(vtpm_struct)
1426 xendom.managed_config_save(dom)
1427 return xen_api_success(vtpm_ref)
1428 except XendError:
1429 return xen_api_error(XEND_ERROR_TODO)
1430 else:
1431 return xen_api_error(['VM_HANDLE_INVALID', vtpm_struct['VM']])
1434 # Xen API: Class SR
1435 # ----------------------------------------------------------------
1436 SR_attr_ro = ['VDIs',
1437 'virtual_allocation',
1438 'physical_utilisation',
1439 'physical_size',
1440 'type',
1441 'location']
1443 SR_attr_rw = ['name_label',
1444 'name_description']
1446 SR_attr_inst = ['physical_size',
1447 'type',
1448 'location',
1449 'name_label',
1450 'name_description']
1452 SR_methods = ['clone']
1453 SR_funcs = ['get_by_name_label']
1455 # Class Functions
1456 def SR_get_all(self, session):
1457 sr = XendNode.instance().get_sr()
1458 return xen_api_success([sr.uuid])
1460 def SR_get_by_name_label(self, session, label):
1461 sr = XendNode.instance().get_sr()
1462 if sr.name_label != label:
1463 return xen_api_success([])
1464 return xen_api_success([sr.uuid])
1466 def SR_create(self, session):
1467 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1469 def SR_get_by_uuid(self, session):
1470 return xen_api_success(XendNode.instance().get_sr().uuid)
1472 # Class Methods
1473 def SR_clone(self, session, sr_ref):
1474 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1476 def SR_destroy(self, session, sr_ref):
1477 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1479 def SR_get_record(self, session, sr_ref):
1480 sr = XendNode.instance().get_sr()
1481 return xen_api_success(sr.get_record())
1483 # Attribute acceess
1485 def _get_SR_func(self, _, func, conv = None):
1486 result = getattr(XendNode.instance().get_sr(), func)()
1487 if conv:
1488 result = conv(result)
1489 return xen_api_success(result)
1491 def _get_SR_attr(self, _, attr):
1492 return xen_api_success(str(getattr(XendNode.instance().get_sr(),
1493 attr)))
1495 def SR_get_VDIs(self, _, ref):
1496 return self._get_SR_func(ref, 'list_images')
1498 def SR_get_virtual_allocation(self, _, ref):
1499 return self._get_SR_func(ref, 'virtual_allocation', str)
1501 def SR_get_physical_utilisation(self, _, ref):
1502 return self._get_SR_func(ref, 'used_space_bytes', str)
1504 def SR_get_physical_size(self, _, ref):
1505 return self._get_SR_func(ref, 'total_space_bytes', str)
1507 def SR_get_type(self, _, ref):
1508 return self._get_SR_attr(ref, 'type')
1510 def SR_get_location(self, _, ref):
1511 return self._get_SR_attr(ref, 'location')
1513 def SR_get_name_label(self, _, ref):
1514 return self._get_SR_attr(ref, 'name_label')
1516 def SR_get_name_description(self, _, ref):
1517 return self._get_SR_attr(ref, 'name_description')
1519 def SR_set_name_label(self, session, sr_ref, value):
1520 sr = XendNode.instance().get_sr()
1521 sr.name_label = value
1522 XendNode.instance().save()
1523 return xen_api_success_void()
1525 def SR_set_name_description(self, session, sr_ref, value):
1526 sr = XendNode.instance().get_sr()
1527 sr.name_description = value
1528 XendNode.instance().save()
1529 return xen_api_success_void()
1532 def _decorate():
1533 """Initialise Xen API wrapper by making sure all functions
1534 have the correct validation decorators such as L{valid_host}
1535 and L{session_required}.
1536 """
1538 global_validators = [session_required, catch_typeerror]
1539 classes = {
1540 'session' : None,
1541 'host' : valid_host,
1542 'host_cpu': valid_host_cpu,
1543 'network' : valid_network,
1544 'VM' : valid_vm,
1545 'VBD' : valid_vbd,
1546 'VIF' : valid_vif,
1547 'VDI' : valid_vdi,
1548 'VTPM' : valid_vtpm,
1549 'SR' : valid_sr,
1550 'PIF' : valid_pif
1553 # Cheat methods
1554 # -------------
1555 # Methods that have a trivial implementation for all classes.
1556 # 1. get_by_uuid == getting by ref, so just return uuid for
1557 # all get_by_uuid() methods.
1559 for cls in classes.keys():
1560 get_by_uuid = '%s_get_by_uuid' % cls
1561 get_uuid = '%s_get_uuid' % cls
1562 def _get_by_uuid(_1, _2, ref):
1563 return xen_api_success(ref)
1565 def _get_uuid(_1, _2, ref):
1566 return xen_api_success(ref)
1568 setattr(XendAPI, get_by_uuid, _get_by_uuid)
1569 setattr(XendAPI, get_uuid, _get_uuid)
1571 # 2. get_record is just getting all the attributes, so provide
1572 # a fake template implementation.
1574 # TODO: ...
1577 # Wrapping validators around XMLRPC calls
1578 # ---------------------------------------
1580 for cls, validator in classes.items():
1581 def doit(n, takes_instance):
1582 n_ = n.replace('.', '_')
1583 try:
1584 f = getattr(XendAPI, n_)
1585 argcounts[n] = f.func_code.co_argcount - 1
1587 validators = takes_instance and validator and [validator] \
1588 or []
1589 validators += global_validators
1590 for v in validators:
1591 f = v(f)
1592 f.api = n
1593 setattr(XendAPI, n_, f)
1594 except AttributeError:
1595 log.warn("API call: %s not found" % n)
1598 ro_attrs = getattr(XendAPI, '%s_attr_ro' % cls, [])
1599 rw_attrs = getattr(XendAPI, '%s_attr_rw' % cls, [])
1600 methods = getattr(XendAPI, '%s_methods' % cls, [])
1601 funcs = getattr(XendAPI, '%s_funcs' % cls, [])
1603 # wrap validators around readable class attributes
1604 for attr_name in ro_attrs + rw_attrs + XendAPI.Base_attr_ro:
1605 doit('%s.get_%s' % (cls, attr_name), True)
1607 # wrap validators around writable class attrributes
1608 for attr_name in rw_attrs + XendAPI.Base_attr_rw:
1609 doit('%s.set_%s' % (cls, attr_name), True)
1611 # wrap validators around methods
1612 for method_name in methods + XendAPI.Base_methods:
1613 doit('%s.%s' % (cls, method_name), True)
1615 # wrap validators around class functions
1616 for func_name in funcs + XendAPI.Base_funcs:
1617 doit('%s.%s' % (cls, func_name), False)
1619 _decorate()
1623 # Auto generate some stubs based on XendAPI introspection
1625 if __name__ == "__main__":
1626 def output(line):
1627 print ' ' + line
1629 classes = ['VDI', 'SR']
1630 for cls in classes:
1631 ro_attrs = getattr(XendAPI, '%s_attr_ro' % cls, [])
1632 rw_attrs = getattr(XendAPI, '%s_attr_rw' % cls, [])
1633 methods = getattr(XendAPI, '%s_methods' % cls, [])
1634 funcs = getattr(XendAPI, '%s_funcs' % cls, [])
1636 ref = '%s_ref' % cls
1638 for attr_name in ro_attrs + rw_attrs + XendAPI.Base_attr_ro:
1639 getter_name = '%s_get_%s' % (cls, attr_name)
1640 output('def %s(self, session, %s):' % (getter_name, ref))
1641 output(' return xen_api_todo()')
1643 for attr_name in rw_attrs + XendAPI.Base_attr_rw:
1644 setter_name = '%s_set_%s' % (cls, attr_name)
1645 output('def %s(self, session, %s, value):' % (setter_name, ref))
1646 output(' return xen_api_todo()')
1648 for method_name in methods + XendAPI.Base_methods:
1649 method_full_name = '%s_%s' % (cls,method_name)
1650 output('def %s(self, session, %s):' % (method_full_name, ref))
1651 output(' return xen_api_todo()')
1653 for func_name in funcs + XendAPI.Base_funcs:
1654 func_full_name = '%s_%s' % (cls, func_name)
1655 output('def %s(self, session):' % func_full_name)
1656 output(' return xen_api_todo()')