ia64/xen-unstable

view tools/python/xen/xend/XendAPI.py @ 13219:bfa793180cb9

Fix xmlrpclib2's stringify to cope with floats and longs, removing the need
for explicit type conversions in XendAPI.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author Ewan Mellor <ewan@xensource.com>
date Thu Dec 28 16:30:47 2006 +0000 (2006-12-28)
parents 615109616bb6
children 58efd34d0837
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 try:
544 node = XendNode.instance()
545 if host_uuid != node.uuid:
546 return xen_api_error([HOST_HANDLE_INVALID, host_uuid])
548 elif _is_valid_ref(network_uuid, node.is_valid_network):
549 network = node.get_network(network_uuid)
550 return xen_api_success(node.PIF_create(name, mtu, vlan, mac,
551 network))
552 else:
553 return xen_api_error([NETWORK_HANDLE_INVALID, network_uuid])
554 except NetworkAlreadyConnected, exn:
555 return xen_api_error(['NETWORK_ALREADY_CONNECTED',
556 network_uuid, exn.pif_uuid])
558 def PIF_destroy(self, _, ref):
559 return xen_api_success(XendNode.instance().PIF_destroy(ref))
561 # object methods
562 def PIF_get_record(self, _, ref):
563 return xen_api_success(self._get_PIF(ref).get_record())
565 def PIF_get_all(self, _):
566 return xen_api_success(XendNode.instance().pifs.keys())
568 def PIF_get_name(self, _, ref):
569 return xen_api_success(self._get_PIF(ref).name)
571 def PIF_get_network(self, _, ref):
572 return xen_api_success(self._get_PIF(ref).network.uuid)
574 def PIF_get_host(self, _, ref):
575 return xen_api_success(self._get_PIF(ref).host.uuid)
577 def PIF_get_MAC(self, _, ref):
578 return xen_api_success(self._get_PIF(ref).mac)
580 def PIF_get_MTU(self, _, ref):
581 return xen_api_success(self._get_PIF(ref).mtu)
583 def PIF_get_VLAN(self, _, ref):
584 return xen_api_success(self._get_PIF(ref).vlan)
586 def PIF_get_io_read_kbs(self, _, ref):
587 return xen_api_success(self._get_PIF(ref).get_io_read_kbs())
589 def PIF_get_io_write_kbs(self, _, ref):
590 return xen_api_success(self._get_PIF(ref).get_io_write_kbs())
592 def PIF_set_name(self, _, ref, name):
593 return xen_api_success(self._get_PIF(ref).set_name(name))
595 def PIF_set_MAC(self, _, ref, mac):
596 return xen_api_success(self._get_PIF(ref).set_mac(name))
598 def PIF_set_MTU(self, _, ref, mtu):
599 return xen_api_success(self._get_PIF(ref).set_mtu(name))
601 def PIF_create_VLAN(self, _, ref, network, vlan):
602 try:
603 if _is_valid_ref(network, XendNode.instance().is_valid_network):
604 return xen_api_success(XendNode.instance().PIF_create_VLAN(
605 ref, network, vlan))
606 else:
607 return xen_api_error([NETWORK_HANDLE_INVALID, network])
608 except NetworkAlreadyConnected, exn:
609 return xen_api_error(['NETWORK_ALREADY_CONNECTED',
610 network, exn.pif_uuid])
613 # Xen API: Class VM
614 # ----------------------------------------------------------------
616 VM_attr_ro = ['power_state',
617 'resident_on',
618 'memory_actual',
619 'memory_static_max',
620 'memory_static_min',
621 'VCPUs_number',
622 'VCPUs_utilisation',
623 'VCPUs_features_required',
624 'VCPUs_can_use',
625 'consoles',
626 'VIFs',
627 'VBDs',
628 'VTPMs',
629 'PCI_bus',
630 'tools_version',
631 ]
633 VM_attr_rw = ['name_label',
634 'name_description',
635 'user_version',
636 'is_a_template',
637 'auto_power_on',
638 'memory_dynamic_max',
639 'memory_dynamic_min',
640 'VCPUs_policy',
641 'VCPUs_params',
642 'VCPUs_features_force_on',
643 'VCPUs_features_force_off',
644 'actions_after_shutdown',
645 'actions_after_reboot',
646 'actions_after_suspend',
647 'actions_after_crash',
648 'PV_bootloader',
649 'PV_kernel',
650 'PV_ramdisk',
651 'PV_args',
652 'PV_bootloader_args',
653 'HVM_boot',
654 'platform_std_VGA',
655 'platform_serial',
656 'platform_localtime',
657 'platform_clock_offset',
658 'platform_enable_audio',
659 'platform_keymap',
660 'otherConfig']
662 VM_methods = ['clone',
663 'start',
664 'pause',
665 'unpause',
666 'clean_shutdown',
667 'clean_reboot',
668 'hard_shutdown',
669 'hard_reboot',
670 'suspend',
671 'resume']
673 VM_funcs = ['get_by_name_label']
675 # parameters required for _create()
676 VM_attr_inst = [
677 'name_label',
678 'name_description',
679 'user_version',
680 'is_a_template',
681 'memory_static_max',
682 'memory_dynamic_max',
683 'memory_dynamic_min',
684 'memory_static_min',
685 'VCPUs_policy',
686 'VCPUs_params',
687 'VCPUs_features_required',
688 'VCPUs_features_can_use',
689 'VCPUs_features_force_on',
690 'VCPUs_features_force_off',
691 'actions_after_shutdown',
692 'actions_after_reboot',
693 'actions_after_suspend',
694 'actions_after_crash',
695 'PV_bootloader',
696 'PV_kernel',
697 'PV_ramdisk',
698 'PV_args',
699 'PV_bootloader_args',
700 'HVM_boot',
701 'platform_std_VGA',
702 'platform_serial',
703 'platform_localtime',
704 'platform_clock_offset',
705 'platform_enable_audio',
706 'platform_keymap',
707 'grub_cmdline',
708 'PCI_bus',
709 'otherConfig']
711 def VM_get(self, name, session, vm_ref):
712 return xen_api_success(
713 XendDomain.instance().get_vm_by_uuid(vm_ref).info[name])
715 def VM_set(self, name, session, vm_ref, value):
716 xd = XendDomain.instance()
717 dominfo = xd.get_vm_by_uuid(vm_ref)
718 dominfo.info[name] = value
719 xd.managed_config_save(dominfo)
720 return xen_api_success_void()
722 # attributes (ro)
723 def VM_get_power_state(self, session, vm_ref):
724 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
725 return xen_api_success(dom.get_power_state())
727 def VM_get_resident_on(self, session, vm_ref):
728 return xen_api_success(XendNode.instance().uuid)
730 def VM_get_memory_actual(self, session, vm_ref):
731 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
732 return xen_api_todo() # unsupported by xc
734 def VM_get_memory_static_max(self, session, vm_ref):
735 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
736 return xen_api_success(dom.get_memory_static_max())
738 def VM_get_memory_static_min(self, session, vm_ref):
739 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
740 return xen_api_success(dom.get_memory_static_min())
742 def VM_get_VCPUs_number(self, session, vm_ref):
743 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
744 return xen_api_success(dom.getVCpuCount())
746 def VM_get_VCPUs_utilisation(self, session, vm_ref):
747 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
748 return xen_api_success(dom.get_vcpus_util())
750 def VM_get_VCPUs_features_required(self, session, vm_ref):
751 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
752 return xen_api_todo() # unsupported by xc
754 def VM_get_VCPUs_can_use(self, session, vm_ref):
755 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
756 return xen_api_todo() # unsupported by xc
758 def VM_get_VIFs(self, session, vm_ref):
759 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
760 return xen_api_success(dom.get_vifs())
762 def VM_get_VBDs(self, session, vm_ref):
763 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
764 return xen_api_success(dom.get_vbds())
766 def VM_get_VTPMs(self, session, vm_ref):
767 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
768 return xen_api_success(dom.get_vtpms())
770 def VM_get_PCI_bus(self, session, vm_ref):
771 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
772 return xen_api_todo() # unsupported by xc
774 def VM_get_tools_version(self, session, vm_ref):
775 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
776 return xen_api_todo()
778 # attributes (rw)
779 def VM_get_name_label(self, session, vm_ref):
780 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
781 return xen_api_success(dom.getName())
783 def VM_get_name_description(self, session, vm_ref):
784 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
785 return xen_api_todo()
787 def VM_get_user_version(self, session, vm_ref):
788 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
789 return xen_api_todo()
791 def VM_get_is_a_template(self, session, vm_ref):
792 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
793 return xen_api_todo()
795 def VM_get_memory_dynamic_max(self, session, vm_ref):
796 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
797 return xen_api_success(dom.get_memory_dynamic_max())
799 def VM_get_memory_dynamic_min(self, session, vm_ref):
800 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
801 return xen_api_success(dom.get_memory_dynamic_min())
803 def VM_get_VCPUs_policy(self, session, vm_ref):
804 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
805 return xen_api_todo() # need to access scheduler
807 def VM_get_VCPUs_params(self, session, vm_ref):
808 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
809 return xen_api_todo() # need access to scheduler
811 def VM_get_VCPUs_features_force_on(self, session, vm_ref):
812 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
813 return xen_api_todo()
815 def VM_get_VCPUs_features_force_off(self, session, vm_ref):
816 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
817 return xen_api_todo()
819 def VM_get_actions_after_shutdown(self, session, vm_ref):
820 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
821 return xen_api_success(dom.get_on_shutdown())
823 def VM_get_actions_after_reboot(self, session, vm_ref):
824 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
825 return xen_api_success(dom.get_on_reboot())
827 def VM_get_actions_after_suspend(self, session, vm_ref):
828 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
829 return xen_api_success(dom.get_on_suspend())
831 def VM_get_actions_after_crash(self, session, vm_ref):
832 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
833 return xen_api_success(dom.get_on_crash())
835 def VM_get_PV_bootloader(self, session, vm_ref):
836 return self.VM_get('PV_bootloader', session, vm_ref)
838 def VM_get_PV_kernel(self, session, vm_ref):
839 return self.VM_get('PV_kernel', session, vm_ref)
841 def VM_get_PV_ramdisk(self, session, vm_ref):
842 return self.VM_get('PV_ramdisk', session, vm_ref)
844 def VM_get_PV_args(self, session, vm_ref):
845 return self.VM_get('PV_args', session, vm_ref)
847 def VM_get_PV_bootloader_args(self, session, vm_ref):
848 return self.VM_get('PV_bootloader_args', session, vm_ref)
850 def VM_get_HVM_boot(self, session, vm_ref):
851 return self.VM_get('HVM_boot', session, vm_ref)
853 def VM_get_platform_std_VGA(self, session, vm_ref):
854 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
855 return xen_api_todo()
857 def VM_get_platform_serial(self, session, vm_ref):
858 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
859 return xen_api_todo()
861 def VM_get_platform_localtime(self, session, vm_ref):
862 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
863 return xen_api_todo()
865 def VM_get_platform_clock_offset(self, session, vm_ref):
866 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
867 return xen_api_todo()
869 def VM_get_platform_enable_audio(self, session, vm_ref):
870 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
871 return xen_api_todo()
873 def VM_get_platform_keymap(self, session, vm_ref):
874 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
875 return xen_api_todo()
877 def VM_get_otherConfig(self, session, vm_ref):
878 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
879 return xen_api_todo()
881 def VM_set_name_label(self, session, vm_ref, label):
882 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
883 dom.setName(label)
884 return xen_api_success_void()
886 def VM_set_name_description(self, session, vm_ref, desc):
887 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
888 return xen_api_todo()
890 def VM_set_user_version(self, session, vm_ref, ver):
891 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
892 return xen_api_todo()
894 def VM_set_is_a_template(self, session, vm_ref, is_template):
895 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
896 return xen_api_todo()
898 def VM_set_memory_dynamic_max(self, session, vm_ref, mem):
899 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
900 return xen_api_todo()
902 def VM_set_memory_dynamic_min(self, session, vm_ref, mem):
903 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
904 return xen_api_todo()
906 def VM_set_VCPUs_policy(self, session, vm_ref, policy):
907 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
908 return xen_api_todo()
910 def VM_set_VCPUs_params(self, session, vm_ref, params):
911 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
912 return xen_api_todo()
914 def VM_set_VCPUs_features_force_on(self, session, vm_ref, features):
915 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
916 return xen_api_todo()
918 def VM_set_VCPUs_features_force_off(self, session, vm_ref, features):
919 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
920 return xen_api_todo()
922 def VM_set_actions_after_shutdown(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_reboot(self, session, vm_ref, action):
927 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
928 return xen_api_todo()
930 def VM_set_actions_after_suspend(self, session, vm_ref, action):
931 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
932 return xen_api_todo()
934 def VM_set_actions_after_crash(self, session, vm_ref, action):
935 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
936 return xen_api_success_void()
938 def VM_set_HVM_boot(self, session, vm_ref, value):
939 return self.VM_set('HVM_boot', session, vm_ref, value)
941 def VM_set_PV_bootloader(self, session, vm_ref, value):
942 return self.VM_set('PV_bootloader', session, vm_ref, value)
944 def VM_set_PV_kernel(self, session, vm_ref, value):
945 return self.VM_set('PV_kernel', session, vm_ref, value)
947 def VM_set_PV_ramdisk(self, session, vm_ref, value):
948 return self.VM_set('PV_ramdisk', session, vm_ref, value)
950 def VM_set_PV_args(self, session, vm_ref, value):
951 return self.VM_set('PV_args', session, vm_ref, value)
953 def VM_set_PV_bootloader_args(self, session, vm_ref, value):
954 return self.VM_set('PV_bootloader_args', session, vm_ref, value)
956 def VM_set_platform_std_VGA(self, session, vm_ref):
957 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
958 return xen_api_todo()
960 def VM_set_platform_serial(self, session, vm_ref, serial):
961 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
962 return xen_api_todo()
964 def VM_set_platform_localtime(self, session, vm_ref, localtime):
965 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
966 return xen_api_todo()
968 def VM_set_platform_clock_offset(self, session, vm_ref, clock_offset):
969 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
970 return xen_api_todo()
972 def VM_set_platform_enable_audio(self, session, vm_ref, enable_audio):
973 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
974 return xen_api_todo()
976 def VM_set_otherConfig(self, session, vm_ref):
977 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
978 return xen_api_todo()
980 # class methods
981 def VM_get_all(self, session):
982 refs = [d.get_uuid() for d in XendDomain.instance().list('all')]
983 return xen_api_success(refs)
985 def VM_get_by_name_label(self, session, label):
986 xendom = XendDomain.instance()
987 dom = xendom.domain_lookup_nr(label)
988 if dom:
989 return xen_api_success([dom.get_uuid()])
990 return xen_api_success([])
992 def VM_create(self, session, vm_struct):
993 xendom = XendDomain.instance()
994 domuuid = xendom.create_domain(vm_struct)
995 return xen_api_success(domuuid)
997 # object methods
998 def VM_get_record(self, session, vm_ref):
999 xendom = XendDomain.instance()
1000 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1001 if not xeninfo:
1002 return xen_api_error(['VM_HANDLE_INVALID', vm_ref])
1004 record = {
1005 'uuid': xeninfo.get_uuid(),
1006 'power_state': xeninfo.get_power_state(),
1007 'name_label': xeninfo.getName(),
1008 'name_description': xeninfo.getName(),
1009 'user_version': 1,
1010 'is_a_template': False,
1011 'auto_power_on': False,
1012 'resident_on': XendNode.instance().uuid,
1013 'memory_static_min': xeninfo.get_memory_static_min(),
1014 'memory_static_max': xeninfo.get_memory_static_max(),
1015 'memory_dynamic_min': xeninfo.get_memory_dynamic_min(),
1016 'memory_dynamic_max': xeninfo.get_memory_dynamic_max(),
1017 'memory_actual': xeninfo.get_memory_static_min(),
1018 'VCPUs_policy': xeninfo.get_vcpus_policy(),
1019 'VCPUs_params': xeninfo.get_vcpus_params(),
1020 'VCPUs_number': xeninfo.getVCpuCount(),
1021 'VCPUs_utilisation': xeninfo.get_vcpus_util(),
1022 'VCPUs_features_required': [],
1023 'VCPUs_features_can_use': [],
1024 'VCPUs_features_force_on': [],
1025 'VCPUs_features_force_off': [],
1026 'actions_after_shutdown': xeninfo.get_on_shutdown(),
1027 'actions_after_reboot': xeninfo.get_on_reboot(),
1028 'actions_after_suspend': xeninfo.get_on_suspend(),
1029 'actions_after_crash': xeninfo.get_on_crash(),
1030 'consoles': xeninfo.get_consoles(),
1031 'VIFs': xeninfo.get_vifs(),
1032 'VBDs': xeninfo.get_vbds(),
1033 'VTPMs': xeninfo.get_vtpms(),
1034 'PV_bootloader': xeninfo.info.get('PV_bootloader'),
1035 'PV_kernel': xeninfo.info.get('PV_kernel'),
1036 'PV_ramdisk': xeninfo.info.get('PV_ramdisk'),
1037 'PV_args': xeninfo.info.get('PV_args'),
1038 'PV_bootloader_args': xeninfo.info.get('PV_bootloader_args'),
1039 'HVM_boot': xeninfo.info.get('HVM_boot'),
1040 'platform_std_VGA': xeninfo.get_platform_std_vga(),
1041 'platform_serial': xeninfo.get_platform_serial(),
1042 'platform_localtime': xeninfo.get_platform_localtime(),
1043 'platform_clock_offset': xeninfo.get_platform_clock_offset(),
1044 'platform_enable_audio': xeninfo.get_platform_enable_audio(),
1045 'platform_keymap': xeninfo.get_platform_keymap(),
1046 'PCI_bus': xeninfo.get_pci_bus(),
1047 'tools_version': xeninfo.get_tools_version(),
1048 'otherConfig': xeninfo.get_other_config()
1050 return xen_api_success(record)
1052 def VM_clean_reboot(self, session, vm_ref):
1053 xendom = XendDomain.instance()
1054 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1055 xeninfo.shutdown("reboot")
1056 return xen_api_success_void()
1057 def VM_clean_shutdown(self, session, vm_ref):
1058 xendom = XendDomain.instance()
1059 xeninfo = xendom.get_vm_by_uuid(vm_ref)
1060 xeninfo.shutdown("poweroff")
1061 return xen_api_success_void()
1062 def VM_clone(self, session, vm_ref):
1063 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1064 def VM_destroy(self, session, vm_ref):
1065 return do_vm_func("domain_delete", vm_ref)
1066 def VM_hard_reboot(self, session, vm_ref):
1067 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1068 def VM_hard_shutdown(self, session, vm_ref):
1069 return do_vm_func("domain_destroy", vm_ref)
1070 def VM_pause(self, session, vm_ref):
1071 return do_vm_func("domain_pause", vm_ref)
1072 def VM_resume(self, session, vm_ref, start_paused):
1073 return do_vm_func("domain_resume", vm_ref, start_paused = start_paused)
1074 def VM_start(self, session, vm_ref, start_paused):
1075 return do_vm_func("domain_start", vm_ref, start_paused = start_paused)
1076 def VM_suspend(self, session, vm_ref):
1077 return do_vm_func("domain_suspend", vm_ref)
1078 def VM_unpause(self, session, vm_ref):
1079 return do_vm_func("domain_unpause", vm_ref)
1081 # Xen API: Class VBD
1082 # ----------------------------------------------------------------
1083 # Note: accepts a non-API standard 'image' attribute to emulate
1084 # regular xm created VBDs
1086 VBD_attr_ro = ['image',
1087 'io_read_kbs',
1088 'io_write_kbs']
1089 VBD_attr_rw = ['VM',
1090 'VDI',
1091 'device',
1092 'mode',
1093 'driver']
1095 VBD_attr_inst = VBD_attr_rw + ['image']
1097 VBD_methods = ['media_change']
1099 # object methods
1100 def VBD_get_record(self, session, vbd_ref):
1101 xendom = XendDomain.instance()
1102 vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1103 if not vm:
1104 return xen_api_error(['VBD_HANDLE_INVALID', vbd_ref])
1105 cfg = vm.get_dev_xenapi_config('vbd', vbd_ref)
1106 if not cfg:
1107 return xen_api_error(['VBD_HANDLE_INVALID', vbd_ref])
1109 valid_vbd_keys = self.VBD_attr_ro + self.VBD_attr_rw + \
1110 self.Base_attr_ro + self.Base_attr_rw
1112 return_cfg = {}
1113 for k in cfg.keys():
1114 if k in valid_vbd_keys:
1115 return_cfg[k] = cfg[k]
1117 return xen_api_success(return_cfg)
1119 def VBD_media_change(self, session, vbd_ref, vdi_ref):
1120 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1122 # class methods
1123 def VBD_create(self, session, vbd_struct):
1124 xendom = XendDomain.instance()
1125 if not xendom.is_valid_vm(vbd_struct['VM']):
1126 return xen_api_error(['VM_HANDLE_INVALID', vbd_struct['VM']])
1128 dom = xendom.get_vm_by_uuid(vbd_struct['VM'])
1129 vbd_ref = ''
1130 try:
1131 if not vbd_struct.get('VDI', None):
1132 # this is a traditional VBD without VDI and SR
1133 vbd_ref = dom.create_vbd(vbd_struct)
1134 else:
1135 # new VBD via VDI/SR
1136 vdi_ref = vbd_struct.get('VDI')
1137 sr = XendNode.instance().get_sr()
1138 vdi_image = sr.xen_api_get_by_uuid(vdi_ref)
1139 if not vdi_image:
1140 return xen_api_error(['VDI_HANDLE_INVALID', vdi_ref])
1141 vdi_image = vdi_image.qcow_path
1142 vbd_ref = dom.create_vbd_with_vdi(vbd_struct, vdi_image)
1143 except XendError:
1144 return xen_api_todo()
1146 xendom.managed_config_save(dom)
1147 return xen_api_success(vbd_ref)
1149 # attributes (rw)
1150 def VBD_get_VM(self, session, vbd_ref):
1151 xendom = XendDomain.instance()
1152 return xen_api_success(xendom.get_dev_property('vbd', vbd_ref, 'VM'))
1154 def VBD_get_VDI(self, session, vbd_ref):
1155 return xen_api_todo()
1157 def VBD_get_device(self, session, vbd_ref):
1158 xendom = XendDomain.instance()
1159 return xen_api_success(xendom.get_dev_property('vbd', vbd_ref,
1160 'device'))
1161 def VBD_get_mode(self, session, vbd_ref):
1162 xendom = XendDomain.instance()
1163 return xen_api_success(xendom.get_dev_property('vbd', vbd_ref,
1164 'mode'))
1165 def VBD_get_driver(self, session, vbd_ref):
1166 xendom = XendDomain.instance()
1167 return xen_api_success(xendom.get_dev_property('vbd', vbd_ref,
1168 'driver'))
1170 # Xen API: Class VIF
1171 # ----------------------------------------------------------------
1173 VIF_attr_ro = ['io_read_kbs',
1174 'io_write_kbs']
1175 VIF_attr_rw = ['name',
1176 'type',
1177 'device',
1178 'network',
1179 'VM',
1180 'MAC',
1181 'MTU']
1183 VIF_attr_inst = VIF_attr_rw
1185 # object methods
1186 def VIF_get_record(self, session, vif_ref):
1187 xendom = XendDomain.instance()
1188 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
1189 if not vm:
1190 return xen_api_error(['VIF_HANDLE_INVALID', vif_ref])
1191 cfg = vm.get_dev_xenapi_config('vif', vif_ref)
1192 if not cfg:
1193 return xen_api_error(['VIF_HANDLE_INVALID', vif_ref])
1195 valid_vif_keys = self.VIF_attr_ro + self.VIF_attr_rw + \
1196 self.Base_attr_ro + self.Base_attr_rw
1198 return_cfg = {}
1199 for k in cfg.keys():
1200 if k in valid_vif_keys:
1201 return_cfg[k] = cfg[k]
1203 return xen_api_success(return_cfg)
1205 # class methods
1206 def VIF_create(self, session, vif_struct):
1207 xendom = XendDomain.instance()
1208 if xendom.is_valid_vm(vif_struct['VM']):
1209 dom = xendom.get_vm_by_uuid(vif_struct['VM'])
1210 try:
1211 vif_ref = dom.create_vif(vif_struct)
1212 xendom.managed_config_save(dom)
1213 return xen_api_success(vif_ref)
1214 except XendError:
1215 return xen_api_error(XEND_ERROR_TODO)
1216 else:
1217 return xen_api_error(['VM_HANDLE_INVALID', vif_struct['VM']])
1220 # Xen API: Class VDI
1221 # ----------------------------------------------------------------
1222 VDI_attr_ro = ['VBDs',
1223 'physical_utilisation',
1224 'sector_size',
1225 'type',
1226 'parent',
1227 'children']
1228 VDI_attr_rw = ['name_label',
1229 'name_description',
1230 'SR',
1231 'virtual_size',
1232 'sharable',
1233 'read_only']
1234 VDI_attr_inst = VDI_attr_ro + VDI_attr_rw
1236 VDI_methods = ['snapshot']
1237 VDI_funcs = ['get_by_name_label']
1239 def _get_VDI(self, ref):
1240 return XendNode.instance().get_sr().xen_api_get_by_uuid(ref)
1242 def VDI_get_VBDs(self, session, vdi_ref):
1243 return xen_api_todo()
1245 def VDI_get_physical_utilisation(self, session, vdi_ref):
1246 return xen_api_success(self._get_VDI(vdi_ref).
1247 get_physical_utilisation())
1249 def VDI_get_sector_size(self, session, vdi_ref):
1250 return xen_api_success(self._get_VDI(vdi_ref).sector_size)
1252 def VDI_get_type(self, session, vdi_ref):
1253 return xen_api_success(self._get_VDI(vdi_ref).type)
1255 def VDI_get_parent(self, session, vdi_ref):
1256 return xen_api_success(self._get_VDI(vdi_ref).parent)
1258 def VDI_get_children(self, session, vdi_ref):
1259 return xen_api_success(self._get_VDI(vdi_ref).children)
1261 def VDI_get_name_label(self, session, vdi_ref):
1262 return xen_api_success(self._get_VDI(vdi_ref).name_label)
1264 def VDI_get_name_description(self, session, vdi_ref):
1265 return xen_api_success(self._get_VDI(vdi_ref).name_description)
1267 def VDI_get_SR(self, session, vdi_ref):
1268 sr = XendNode.instance().get_sr()
1269 return xen_api_success(sr.uuid)
1271 def VDI_get_virtual_size(self, session, vdi_ref):
1272 return xen_api_success(self._get_VDI(vdi_ref).virtual_size)
1274 def VDI_get_sharable(self, session, vdi_ref):
1275 return xen_api_success(self._get_VDI(vdi_ref).sharable)
1277 def VDI_get_read_only(self, session, vdi_ref):
1278 return xen_api_success(self._get_VDI(vdi_ref).read_only)
1280 def VDI_set_name_label(self, session, vdi_ref, value):
1281 self._get_VDI(vdi_ref).name_label = value
1282 return xen_api_success_void()
1284 def VDI_set_name_description(self, session, vdi_ref, value):
1285 self._get_VDI(vdi_ref).name_description = value
1286 return xen_api_success_void()
1288 def VDI_set_SR(self, session, vdi_ref, value):
1289 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1291 def VDI_set_virtual_size(self, session, vdi_ref, value):
1292 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1294 def VDI_set_sharable(self, session, vdi_ref, value):
1295 self._get_VDI(vdi_ref).sharable = bool(value)
1296 return xen_api_success_void()
1298 def VDI_set_read_only(self, session, vdi_ref, value):
1299 self._get_VDI(vdi_ref).read_only = bool(value)
1300 return xen_api_success_void()
1302 # Object Methods
1303 def VDI_snapshot(self, session, vdi_ref):
1304 return xen_api_todo()
1306 def VDI_destroy(self, session, vdi_ref):
1307 sr = XendNode.instance().get_sr()
1308 sr.destroy_image(vdi_ref)
1309 return xen_api_success_void()
1311 def VDI_get_record(self, session, vdi_ref):
1312 sr = XendNode.instance().get_sr()
1313 image = sr.xen_api_get_by_uuid(vdi_ref)
1314 return xen_api_success({
1315 'uuid': vdi_ref,
1316 'name_label': image.name_label,
1317 'name_description': image.name_description,
1318 'SR': sr.uuid,
1319 'VBDs': [], # TODO
1320 'virtual_size': image.virtual_size,
1321 'physical_utilisation': image.physical_utilisation,
1322 'sector_size': image.sector_size,
1323 'type': image.type,
1324 'parent': image.parent,
1325 'children': image.children,
1326 'sharable': image.sharable,
1327 'read_only': image.read_only,
1328 })
1330 # Class Functions
1331 def VDI_create(self, session, vdi_struct):
1332 sr = XendNode.instance().get_sr()
1333 sr_ref = vdi_struct['SR']
1334 if sr.uuid != sr_ref:
1335 return xen_api_error(['SR_HANDLE_INVALID', vdi_struct['SR']])
1337 vdi_uuid = sr.create_image(vdi_struct)
1338 return xen_api_success(vdi_uuid)
1340 def VDI_get_all(self, session):
1341 sr = XendNode.instance().get_sr()
1342 return xen_api_success(sr.list_images())
1344 def VDI_get_by_name_label(self, session, name):
1345 sr = XendNode.instance().get_sr()
1346 image_uuid = sr.xen_api_get_by_name_label(name)
1347 if image_uuid:
1348 return xen_api_success([image_uuid])
1349 return xen_api_success([])
1352 # Xen API: Class VTPM
1353 # ----------------------------------------------------------------
1355 VTPM_attr_rw = [ ]
1356 VTPM_attr_ro = ['VM',
1357 'backend',
1358 'instance',
1359 'driver']
1361 VTPM_attr_inst = VTPM_attr_rw
1363 # object methods
1364 def VTPM_get_record(self, session, vtpm_ref):
1365 xendom = XendDomain.instance()
1366 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
1367 if not vm:
1368 return xen_api_error(['VTPM_HANDLE_INVALID', vtpm_ref])
1369 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
1370 if not cfg:
1371 return xen_api_error(['VTPM_HANDLE_INVALID', vtpm_ref])
1372 valid_vtpm_keys = self.VTPM_attr_ro + self.VTPM_attr_rw + \
1373 self.Base_attr_ro + self.Base_attr_rw
1374 for k in cfg.keys():
1375 if k not in valid_vtpm_keys:
1376 del cfg[k]
1378 return xen_api_success(cfg)
1380 # Class Functions
1381 def VTPM_get_instance(self, session, vtpm_ref):
1382 xendom = XendDomain.instance()
1383 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
1384 if not vm:
1385 return xen_api_error(['VTPM_HANDLE_INVALID', vtpm_ref])
1386 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
1387 if not cfg:
1388 return xen_api_error(['VTPM_HANDLE_INVALID', vtpm_ref])
1389 if cfg.has_key('instance'):
1390 instance = cfg['instance']
1391 else:
1392 instance = -1
1393 return xen_api_success(instance)
1395 def VTPM_get_driver(self, session, vtpm_ref):
1396 xendom = XendDomain.instance()
1397 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
1398 if not vm:
1399 return xen_api_error(['VTPM_HANDLE_INVALID', vtpm_ref])
1400 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
1401 if not cfg:
1402 return xen_api_error(['VTPM_HANDLE_INVALID', vtpm_ref])
1403 if cfg.has_key('type'):
1404 driver = cfg['type']
1405 else:
1406 driver = "Unknown"
1407 return xen_api_success(driver)
1409 def VTPM_get_backend(self, session, vtpm_ref):
1410 xendom = XendDomain.instance()
1411 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
1412 if not vm:
1413 return xen_api_error(['VTPM_HANDLE_INVALID', vtpm_ref])
1414 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
1415 if not cfg:
1416 return xen_api_error(['VTPM_HANDLE_INVALID', vtpm_ref])
1417 if cfg.has_key('backend'):
1418 backend = cfg['backend']
1419 else:
1420 backend = "Domain-0"
1421 return xen_api_success(backend)
1423 def VTPM_get_VM(self, session, vtpm_ref):
1424 xendom = XendDomain.instance()
1425 return xen_api_success(xendom.get_dev_property('vtpm', vtpm_ref, 'VM'))
1427 # class methods
1428 def VTPM_create(self, session, vtpm_struct):
1429 xendom = XendDomain.instance()
1430 if xendom.is_valid_vm(vtpm_struct['VM']):
1431 dom = xendom.get_vm_by_uuid(vtpm_struct['VM'])
1432 try:
1433 vtpm_ref = dom.create_vtpm(vtpm_struct)
1434 xendom.managed_config_save(dom)
1435 return xen_api_success(vtpm_ref)
1436 except XendError:
1437 return xen_api_error(XEND_ERROR_TODO)
1438 else:
1439 return xen_api_error(['VM_HANDLE_INVALID', vtpm_struct['VM']])
1442 # Xen API: Class SR
1443 # ----------------------------------------------------------------
1444 SR_attr_ro = ['VDIs',
1445 'virtual_allocation',
1446 'physical_utilisation',
1447 'physical_size',
1448 'type',
1449 'location']
1451 SR_attr_rw = ['name_label',
1452 'name_description']
1454 SR_attr_inst = ['physical_size',
1455 'type',
1456 'location',
1457 'name_label',
1458 'name_description']
1460 SR_methods = ['clone']
1461 SR_funcs = ['get_by_name_label']
1463 # Class Functions
1464 def SR_get_all(self, session):
1465 sr = XendNode.instance().get_sr()
1466 return xen_api_success([sr.uuid])
1468 def SR_get_by_name_label(self, session, label):
1469 sr = XendNode.instance().get_sr()
1470 if sr.name_label != label:
1471 return xen_api_success([])
1472 return xen_api_success([sr.uuid])
1474 def SR_create(self, session):
1475 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1477 def SR_get_by_uuid(self, session):
1478 return xen_api_success(XendNode.instance().get_sr().uuid)
1480 # Class Methods
1481 def SR_clone(self, session, sr_ref):
1482 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1484 def SR_destroy(self, session, sr_ref):
1485 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1487 def SR_get_record(self, session, sr_ref):
1488 sr = XendNode.instance().get_sr()
1489 return xen_api_success(sr.get_record())
1491 # Attribute acceess
1493 def _get_SR_func(self, _, func):
1494 return xen_api_success(getattr(XendNode.instance().get_sr(), func)())
1496 def _get_SR_attr(self, _, attr):
1497 return xen_api_success(getattr(XendNode.instance().get_sr(), attr))
1499 def SR_get_VDIs(self, _, ref):
1500 return self._get_SR_func(ref, 'list_images')
1502 def SR_get_virtual_allocation(self, _, ref):
1503 return self._get_SR_func(ref, 'virtual_allocation')
1505 def SR_get_physical_utilisation(self, _, ref):
1506 return self._get_SR_func(ref, 'used_space_bytes')
1508 def SR_get_physical_size(self, _, ref):
1509 return self._get_SR_func(ref, 'total_space_bytes')
1511 def SR_get_type(self, _, ref):
1512 return self._get_SR_attr(ref, 'type')
1514 def SR_get_location(self, _, ref):
1515 return self._get_SR_attr(ref, 'location')
1517 def SR_get_name_label(self, _, ref):
1518 return self._get_SR_attr(ref, 'name_label')
1520 def SR_get_name_description(self, _, ref):
1521 return self._get_SR_attr(ref, 'name_description')
1523 def SR_set_name_label(self, session, sr_ref, value):
1524 sr = XendNode.instance().get_sr()
1525 sr.name_label = value
1526 XendNode.instance().save()
1527 return xen_api_success_void()
1529 def SR_set_name_description(self, session, sr_ref, value):
1530 sr = XendNode.instance().get_sr()
1531 sr.name_description = value
1532 XendNode.instance().save()
1533 return xen_api_success_void()
1536 def _decorate():
1537 """Initialise Xen API wrapper by making sure all functions
1538 have the correct validation decorators such as L{valid_host}
1539 and L{session_required}.
1540 """
1542 global_validators = [session_required, catch_typeerror]
1543 classes = {
1544 'session' : None,
1545 'host' : valid_host,
1546 'host_cpu': valid_host_cpu,
1547 'network' : valid_network,
1548 'VM' : valid_vm,
1549 'VBD' : valid_vbd,
1550 'VIF' : valid_vif,
1551 'VDI' : valid_vdi,
1552 'VTPM' : valid_vtpm,
1553 'SR' : valid_sr,
1554 'PIF' : valid_pif
1557 # Cheat methods
1558 # -------------
1559 # Methods that have a trivial implementation for all classes.
1560 # 1. get_by_uuid == getting by ref, so just return uuid for
1561 # all get_by_uuid() methods.
1563 for cls in classes.keys():
1564 get_by_uuid = '%s_get_by_uuid' % cls
1565 get_uuid = '%s_get_uuid' % cls
1566 def _get_by_uuid(_1, _2, ref):
1567 return xen_api_success(ref)
1569 def _get_uuid(_1, _2, ref):
1570 return xen_api_success(ref)
1572 setattr(XendAPI, get_by_uuid, _get_by_uuid)
1573 setattr(XendAPI, get_uuid, _get_uuid)
1575 # 2. get_record is just getting all the attributes, so provide
1576 # a fake template implementation.
1578 # TODO: ...
1581 # Wrapping validators around XMLRPC calls
1582 # ---------------------------------------
1584 for cls, validator in classes.items():
1585 def doit(n, takes_instance):
1586 n_ = n.replace('.', '_')
1587 try:
1588 f = getattr(XendAPI, n_)
1589 argcounts[n] = f.func_code.co_argcount - 1
1591 validators = takes_instance and validator and [validator] \
1592 or []
1593 validators += global_validators
1594 for v in validators:
1595 f = v(f)
1596 f.api = n
1597 setattr(XendAPI, n_, f)
1598 except AttributeError:
1599 log.warn("API call: %s not found" % n)
1602 ro_attrs = getattr(XendAPI, '%s_attr_ro' % cls, [])
1603 rw_attrs = getattr(XendAPI, '%s_attr_rw' % cls, [])
1604 methods = getattr(XendAPI, '%s_methods' % cls, [])
1605 funcs = getattr(XendAPI, '%s_funcs' % cls, [])
1607 # wrap validators around readable class attributes
1608 for attr_name in ro_attrs + rw_attrs + XendAPI.Base_attr_ro:
1609 doit('%s.get_%s' % (cls, attr_name), True)
1611 # wrap validators around writable class attrributes
1612 for attr_name in rw_attrs + XendAPI.Base_attr_rw:
1613 doit('%s.set_%s' % (cls, attr_name), True)
1615 # wrap validators around methods
1616 for method_name in methods + XendAPI.Base_methods:
1617 doit('%s.%s' % (cls, method_name), True)
1619 # wrap validators around class functions
1620 for func_name in funcs + XendAPI.Base_funcs:
1621 doit('%s.%s' % (cls, func_name), False)
1623 _decorate()
1627 # Auto generate some stubs based on XendAPI introspection
1629 if __name__ == "__main__":
1630 def output(line):
1631 print ' ' + line
1633 classes = ['VDI', 'SR']
1634 for cls in classes:
1635 ro_attrs = getattr(XendAPI, '%s_attr_ro' % cls, [])
1636 rw_attrs = getattr(XendAPI, '%s_attr_rw' % cls, [])
1637 methods = getattr(XendAPI, '%s_methods' % cls, [])
1638 funcs = getattr(XendAPI, '%s_funcs' % cls, [])
1640 ref = '%s_ref' % cls
1642 for attr_name in ro_attrs + rw_attrs + XendAPI.Base_attr_ro:
1643 getter_name = '%s_get_%s' % (cls, attr_name)
1644 output('def %s(self, session, %s):' % (getter_name, ref))
1645 output(' return xen_api_todo()')
1647 for attr_name in rw_attrs + XendAPI.Base_attr_rw:
1648 setter_name = '%s_set_%s' % (cls, attr_name)
1649 output('def %s(self, session, %s, value):' % (setter_name, ref))
1650 output(' return xen_api_todo()')
1652 for method_name in methods + XendAPI.Base_methods:
1653 method_full_name = '%s_%s' % (cls,method_name)
1654 output('def %s(self, session, %s):' % (method_full_name, ref))
1655 output(' return xen_api_todo()')
1657 for func_name in funcs + XendAPI.Base_funcs:
1658 func_full_name = '%s_%s' % (cls, func_name)
1659 output('def %s(self, session):' % func_full_name)
1660 output(' return xen_api_todo()')