debuggers.hg

view tools/python/xen/xend/XendAPI.py @ 13615:4f5772324e67

[XEND] Strip suffix from device name and add support for 'VBD.type'

Signed-off-by: Alastair Tse <atse@xensource.com>
author Alastair Tse <atse@xensource.com>
date Wed Jan 24 12:07:54 2007 +0000 (2007-01-24)
parents bffe67212133
children 248a9c36d816
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(mac))
598 def PIF_set_MTU(self, _, ref, mtu):
599 return xen_api_success(self._get_PIF(ref).set_mtu(mtu))
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 'type',
1094 'driver']
1096 VBD_attr_inst = VBD_attr_rw + ['image']
1098 VBD_methods = ['media_change']
1100 # object methods
1101 def VBD_get_record(self, session, vbd_ref):
1102 xendom = XendDomain.instance()
1103 vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
1104 if not vm:
1105 return xen_api_error(['VBD_HANDLE_INVALID', vbd_ref])
1106 cfg = vm.get_dev_xenapi_config('vbd', vbd_ref)
1107 if not cfg:
1108 return xen_api_error(['VBD_HANDLE_INVALID', vbd_ref])
1110 valid_vbd_keys = self.VBD_attr_ro + self.VBD_attr_rw + \
1111 self.Base_attr_ro + self.Base_attr_rw
1113 return_cfg = {}
1114 for k in cfg.keys():
1115 if k in valid_vbd_keys:
1116 return_cfg[k] = cfg[k]
1118 return xen_api_success(return_cfg)
1120 def VBD_media_change(self, session, vbd_ref, vdi_ref):
1121 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1123 # class methods
1124 def VBD_create(self, session, vbd_struct):
1125 xendom = XendDomain.instance()
1126 if not xendom.is_valid_vm(vbd_struct['VM']):
1127 return xen_api_error(['VM_HANDLE_INVALID', vbd_struct['VM']])
1129 dom = xendom.get_vm_by_uuid(vbd_struct['VM'])
1130 vbd_ref = ''
1131 try:
1132 if not vbd_struct.get('VDI', None):
1133 # this is a traditional VBD without VDI and SR
1134 vbd_ref = dom.create_vbd(vbd_struct)
1135 else:
1136 # new VBD via VDI/SR
1137 vdi_ref = vbd_struct.get('VDI')
1138 sr = XendNode.instance().get_sr()
1139 vdi_image = sr.xen_api_get_by_uuid(vdi_ref)
1140 if not vdi_image:
1141 return xen_api_error(['VDI_HANDLE_INVALID', vdi_ref])
1142 vdi_image = vdi_image.qcow_path
1143 vbd_ref = dom.create_vbd_with_vdi(vbd_struct, vdi_image)
1144 except XendError:
1145 return xen_api_todo()
1147 xendom.managed_config_save(dom)
1148 return xen_api_success(vbd_ref)
1150 # attributes (rw)
1151 def VBD_get_VM(self, session, vbd_ref):
1152 xendom = XendDomain.instance()
1153 return xen_api_success(xendom.get_dev_property_by_uuid('vbd',
1154 vbd_ref, 'VM'))
1156 def VBD_get_VDI(self, session, vbd_ref):
1157 xendom = XendDomain.instance()
1158 return xen_api_success(xendom.get_dev_property_by_uuid('vbd',
1159 vbd_ref, 'VDI'))
1161 def VBD_get_device(self, session, vbd_ref):
1162 xendom = XendDomain.instance()
1163 return xen_api_success(xendom.get_dev_property_by_uuid('vbd', vbd_ref,
1164 'device'))
1165 def VBD_get_mode(self, session, vbd_ref):
1166 xendom = XendDomain.instance()
1167 return xen_api_success(xendom.get_dev_property_by_uuid('vbd', vbd_ref,
1168 'mode'))
1169 def VBD_get_driver(self, session, vbd_ref):
1170 xendom = XendDomain.instance()
1171 return xen_api_success(xendom.get_dev_property_by_uuid('vbd', vbd_ref,
1172 'driver'))
1174 def VBD_get_type(self, session, vbd_ref):
1175 xendom = XendDomain.instance()
1176 return xen_api_success(xendom.get_dev_property_by_uuid('vbd', vbd_ref,
1177 'type'))
1179 # Xen API: Class VIF
1180 # ----------------------------------------------------------------
1182 VIF_attr_ro = ['io_read_kbs',
1183 'io_write_kbs']
1184 VIF_attr_rw = ['name',
1185 'type',
1186 'device',
1187 'network',
1188 'VM',
1189 'MAC',
1190 'MTU']
1192 VIF_attr_inst = VIF_attr_rw
1194 # object methods
1195 def VIF_get_record(self, session, vif_ref):
1196 xendom = XendDomain.instance()
1197 vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
1198 if not vm:
1199 return xen_api_error(['VIF_HANDLE_INVALID', vif_ref])
1200 cfg = vm.get_dev_xenapi_config('vif', vif_ref)
1201 if not cfg:
1202 return xen_api_error(['VIF_HANDLE_INVALID', vif_ref])
1204 valid_vif_keys = self.VIF_attr_ro + self.VIF_attr_rw + \
1205 self.Base_attr_ro + self.Base_attr_rw
1207 return_cfg = {}
1208 for k in cfg.keys():
1209 if k in valid_vif_keys:
1210 return_cfg[k] = cfg[k]
1212 return xen_api_success(return_cfg)
1214 # class methods
1215 def VIF_create(self, session, vif_struct):
1216 xendom = XendDomain.instance()
1217 if xendom.is_valid_vm(vif_struct['VM']):
1218 dom = xendom.get_vm_by_uuid(vif_struct['VM'])
1219 try:
1220 vif_ref = dom.create_vif(vif_struct)
1221 xendom.managed_config_save(dom)
1222 return xen_api_success(vif_ref)
1223 except XendError:
1224 return xen_api_error(XEND_ERROR_TODO)
1225 else:
1226 return xen_api_error(['VM_HANDLE_INVALID', vif_struct['VM']])
1229 # Xen API: Class VDI
1230 # ----------------------------------------------------------------
1231 VDI_attr_ro = ['VBDs',
1232 'physical_utilisation',
1233 'sector_size',
1234 'type',
1235 'parent',
1236 'children']
1237 VDI_attr_rw = ['name_label',
1238 'name_description',
1239 'SR',
1240 'virtual_size',
1241 'sharable',
1242 'read_only']
1243 VDI_attr_inst = VDI_attr_ro + VDI_attr_rw
1245 VDI_methods = ['snapshot']
1246 VDI_funcs = ['get_by_name_label']
1248 def _get_VDI(self, ref):
1249 return XendNode.instance().get_sr().xen_api_get_by_uuid(ref)
1251 def VDI_get_VBDs(self, session, vdi_ref):
1252 return xen_api_todo()
1254 def VDI_get_physical_utilisation(self, session, vdi_ref):
1255 return xen_api_success(self._get_VDI(vdi_ref).
1256 get_physical_utilisation())
1258 def VDI_get_sector_size(self, session, vdi_ref):
1259 return xen_api_success(self._get_VDI(vdi_ref).sector_size)
1261 def VDI_get_type(self, session, vdi_ref):
1262 return xen_api_success(self._get_VDI(vdi_ref).type)
1264 def VDI_get_parent(self, session, vdi_ref):
1265 return xen_api_success(self._get_VDI(vdi_ref).parent)
1267 def VDI_get_children(self, session, vdi_ref):
1268 return xen_api_success(self._get_VDI(vdi_ref).children)
1270 def VDI_get_name_label(self, session, vdi_ref):
1271 return xen_api_success(self._get_VDI(vdi_ref).name_label)
1273 def VDI_get_name_description(self, session, vdi_ref):
1274 return xen_api_success(self._get_VDI(vdi_ref).name_description)
1276 def VDI_get_SR(self, session, vdi_ref):
1277 sr = XendNode.instance().get_sr()
1278 return xen_api_success(sr.uuid)
1280 def VDI_get_virtual_size(self, session, vdi_ref):
1281 return xen_api_success(self._get_VDI(vdi_ref).virtual_size)
1283 def VDI_get_sharable(self, session, vdi_ref):
1284 return xen_api_success(self._get_VDI(vdi_ref).sharable)
1286 def VDI_get_read_only(self, session, vdi_ref):
1287 return xen_api_success(self._get_VDI(vdi_ref).read_only)
1289 def VDI_set_name_label(self, session, vdi_ref, value):
1290 self._get_VDI(vdi_ref).name_label = value
1291 return xen_api_success_void()
1293 def VDI_set_name_description(self, session, vdi_ref, value):
1294 self._get_VDI(vdi_ref).name_description = value
1295 return xen_api_success_void()
1297 def VDI_set_SR(self, session, vdi_ref, value):
1298 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1300 def VDI_set_virtual_size(self, session, vdi_ref, value):
1301 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1303 def VDI_set_sharable(self, session, vdi_ref, value):
1304 self._get_VDI(vdi_ref).sharable = bool(value)
1305 return xen_api_success_void()
1307 def VDI_set_read_only(self, session, vdi_ref, value):
1308 self._get_VDI(vdi_ref).read_only = bool(value)
1309 return xen_api_success_void()
1311 # Object Methods
1312 def VDI_snapshot(self, session, vdi_ref):
1313 return xen_api_todo()
1315 def VDI_destroy(self, session, vdi_ref):
1316 sr = XendNode.instance().get_sr()
1317 sr.destroy_image(vdi_ref)
1318 return xen_api_success_void()
1320 def VDI_get_record(self, session, vdi_ref):
1321 sr = XendNode.instance().get_sr()
1322 image = sr.xen_api_get_by_uuid(vdi_ref)
1323 return xen_api_success({
1324 'uuid': vdi_ref,
1325 'name_label': image.name_label,
1326 'name_description': image.name_description,
1327 'SR': sr.uuid,
1328 'VBDs': [], # TODO
1329 'virtual_size': image.virtual_size,
1330 'physical_utilisation': image.physical_utilisation,
1331 'sector_size': image.sector_size,
1332 'type': image.type,
1333 'parent': image.parent,
1334 'children': image.children,
1335 'sharable': image.sharable,
1336 'read_only': image.read_only,
1337 })
1339 # Class Functions
1340 def VDI_create(self, session, vdi_struct):
1341 sr = XendNode.instance().get_sr()
1342 sr_ref = vdi_struct['SR']
1343 if sr.uuid != sr_ref:
1344 return xen_api_error(['SR_HANDLE_INVALID', vdi_struct['SR']])
1346 vdi_uuid = sr.create_image(vdi_struct)
1347 return xen_api_success(vdi_uuid)
1349 def VDI_get_all(self, session):
1350 sr = XendNode.instance().get_sr()
1351 return xen_api_success(sr.list_images())
1353 def VDI_get_by_name_label(self, session, name):
1354 sr = XendNode.instance().get_sr()
1355 image_uuid = sr.xen_api_get_by_name_label(name)
1356 if image_uuid:
1357 return xen_api_success([image_uuid])
1358 return xen_api_success([])
1361 # Xen API: Class VTPM
1362 # ----------------------------------------------------------------
1364 VTPM_attr_rw = [ ]
1365 VTPM_attr_ro = ['VM',
1366 'backend',
1367 'instance',
1368 'driver']
1370 VTPM_attr_inst = VTPM_attr_rw
1372 # object methods
1373 def VTPM_get_record(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 valid_vtpm_keys = self.VTPM_attr_ro + self.VTPM_attr_rw + \
1382 self.Base_attr_ro + self.Base_attr_rw
1383 for k in cfg.keys():
1384 if k not in valid_vtpm_keys:
1385 del cfg[k]
1387 return xen_api_success(cfg)
1389 # Class Functions
1390 def VTPM_get_instance(self, session, vtpm_ref):
1391 xendom = XendDomain.instance()
1392 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
1393 if not vm:
1394 return xen_api_error(['VTPM_HANDLE_INVALID', vtpm_ref])
1395 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
1396 if not cfg:
1397 return xen_api_error(['VTPM_HANDLE_INVALID', vtpm_ref])
1398 if cfg.has_key('instance'):
1399 instance = cfg['instance']
1400 else:
1401 instance = -1
1402 return xen_api_success(instance)
1404 def VTPM_get_driver(self, session, vtpm_ref):
1405 xendom = XendDomain.instance()
1406 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
1407 if not vm:
1408 return xen_api_error(['VTPM_HANDLE_INVALID', vtpm_ref])
1409 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
1410 if not cfg:
1411 return xen_api_error(['VTPM_HANDLE_INVALID', vtpm_ref])
1412 if cfg.has_key('type'):
1413 driver = cfg['type']
1414 else:
1415 driver = "Unknown"
1416 return xen_api_success(driver)
1418 def VTPM_get_backend(self, session, vtpm_ref):
1419 xendom = XendDomain.instance()
1420 vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
1421 if not vm:
1422 return xen_api_error(['VTPM_HANDLE_INVALID', vtpm_ref])
1423 cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
1424 if not cfg:
1425 return xen_api_error(['VTPM_HANDLE_INVALID', vtpm_ref])
1426 if cfg.has_key('backend'):
1427 backend = cfg['backend']
1428 else:
1429 backend = "Domain-0"
1430 return xen_api_success(backend)
1432 def VTPM_get_VM(self, session, vtpm_ref):
1433 xendom = XendDomain.instance()
1434 return xen_api_success(xendom.get_dev_property_by_uuid('vtpm',
1435 vtpm_ref, 'VM'))
1437 # class methods
1438 def VTPM_create(self, session, vtpm_struct):
1439 xendom = XendDomain.instance()
1440 if xendom.is_valid_vm(vtpm_struct['VM']):
1441 dom = xendom.get_vm_by_uuid(vtpm_struct['VM'])
1442 try:
1443 vtpm_ref = dom.create_vtpm(vtpm_struct)
1444 xendom.managed_config_save(dom)
1445 return xen_api_success(vtpm_ref)
1446 except XendError:
1447 return xen_api_error(XEND_ERROR_TODO)
1448 else:
1449 return xen_api_error(['VM_HANDLE_INVALID', vtpm_struct['VM']])
1452 # Xen API: Class SR
1453 # ----------------------------------------------------------------
1454 SR_attr_ro = ['VDIs',
1455 'virtual_allocation',
1456 'physical_utilisation',
1457 'physical_size',
1458 'type',
1459 'location']
1461 SR_attr_rw = ['name_label',
1462 'name_description']
1464 SR_attr_inst = ['physical_size',
1465 'type',
1466 'location',
1467 'name_label',
1468 'name_description']
1470 SR_methods = ['clone']
1471 SR_funcs = ['get_by_name_label']
1473 # Class Functions
1474 def SR_get_all(self, session):
1475 sr = XendNode.instance().get_sr()
1476 return xen_api_success([sr.uuid])
1478 def SR_get_by_name_label(self, session, label):
1479 sr = XendNode.instance().get_sr()
1480 if sr.name_label != label:
1481 return xen_api_success([])
1482 return xen_api_success([sr.uuid])
1484 def SR_create(self, session):
1485 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1487 def SR_get_by_uuid(self, session):
1488 return xen_api_success(XendNode.instance().get_sr().uuid)
1490 # Class Methods
1491 def SR_clone(self, session, sr_ref):
1492 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1494 def SR_destroy(self, session, sr_ref):
1495 return xen_api_error(XEND_ERROR_UNSUPPORTED)
1497 def SR_get_record(self, session, sr_ref):
1498 sr = XendNode.instance().get_sr()
1499 return xen_api_success(sr.get_record())
1501 # Attribute acceess
1503 def _get_SR_func(self, _, func):
1504 return xen_api_success(getattr(XendNode.instance().get_sr(), func)())
1506 def _get_SR_attr(self, _, attr):
1507 return xen_api_success(getattr(XendNode.instance().get_sr(), attr))
1509 def SR_get_VDIs(self, _, ref):
1510 return self._get_SR_func(ref, 'list_images')
1512 def SR_get_virtual_allocation(self, _, ref):
1513 return self._get_SR_func(ref, 'virtual_allocation')
1515 def SR_get_physical_utilisation(self, _, ref):
1516 return self._get_SR_func(ref, 'used_space_bytes')
1518 def SR_get_physical_size(self, _, ref):
1519 return self._get_SR_func(ref, 'total_space_bytes')
1521 def SR_get_type(self, _, ref):
1522 return self._get_SR_attr(ref, 'type')
1524 def SR_get_location(self, _, ref):
1525 return self._get_SR_attr(ref, 'location')
1527 def SR_get_name_label(self, _, ref):
1528 return self._get_SR_attr(ref, 'name_label')
1530 def SR_get_name_description(self, _, ref):
1531 return self._get_SR_attr(ref, 'name_description')
1533 def SR_set_name_label(self, session, sr_ref, value):
1534 sr = XendNode.instance().get_sr()
1535 sr.name_label = value
1536 XendNode.instance().save()
1537 return xen_api_success_void()
1539 def SR_set_name_description(self, session, sr_ref, value):
1540 sr = XendNode.instance().get_sr()
1541 sr.name_description = value
1542 XendNode.instance().save()
1543 return xen_api_success_void()
1546 def _decorate():
1547 """Initialise Xen API wrapper by making sure all functions
1548 have the correct validation decorators such as L{valid_host}
1549 and L{session_required}.
1550 """
1552 global_validators = [session_required, catch_typeerror]
1553 classes = {
1554 'session' : None,
1555 'host' : valid_host,
1556 'host_cpu': valid_host_cpu,
1557 'network' : valid_network,
1558 'VM' : valid_vm,
1559 'VBD' : valid_vbd,
1560 'VIF' : valid_vif,
1561 'VDI' : valid_vdi,
1562 'VTPM' : valid_vtpm,
1563 'SR' : valid_sr,
1564 'PIF' : valid_pif
1567 # Cheat methods
1568 # -------------
1569 # Methods that have a trivial implementation for all classes.
1570 # 1. get_by_uuid == getting by ref, so just return uuid for
1571 # all get_by_uuid() methods.
1573 for cls in classes.keys():
1574 get_by_uuid = '%s_get_by_uuid' % cls
1575 get_uuid = '%s_get_uuid' % cls
1576 def _get_by_uuid(_1, _2, ref):
1577 return xen_api_success(ref)
1579 def _get_uuid(_1, _2, ref):
1580 return xen_api_success(ref)
1582 setattr(XendAPI, get_by_uuid, _get_by_uuid)
1583 setattr(XendAPI, get_uuid, _get_uuid)
1585 # 2. get_record is just getting all the attributes, so provide
1586 # a fake template implementation.
1588 # TODO: ...
1591 # Wrapping validators around XMLRPC calls
1592 # ---------------------------------------
1594 for cls, validator in classes.items():
1595 def doit(n, takes_instance):
1596 n_ = n.replace('.', '_')
1597 try:
1598 f = getattr(XendAPI, n_)
1599 argcounts[n] = f.func_code.co_argcount - 1
1601 validators = takes_instance and validator and [validator] \
1602 or []
1603 validators += global_validators
1604 for v in validators:
1605 f = v(f)
1606 f.api = n
1607 setattr(XendAPI, n_, f)
1608 except AttributeError:
1609 log.warn("API call: %s not found" % n)
1612 ro_attrs = getattr(XendAPI, '%s_attr_ro' % cls, [])
1613 rw_attrs = getattr(XendAPI, '%s_attr_rw' % cls, [])
1614 methods = getattr(XendAPI, '%s_methods' % cls, [])
1615 funcs = getattr(XendAPI, '%s_funcs' % cls, [])
1617 # wrap validators around readable class attributes
1618 for attr_name in ro_attrs + rw_attrs + XendAPI.Base_attr_ro:
1619 doit('%s.get_%s' % (cls, attr_name), True)
1621 # wrap validators around writable class attrributes
1622 for attr_name in rw_attrs + XendAPI.Base_attr_rw:
1623 doit('%s.set_%s' % (cls, attr_name), True)
1625 # wrap validators around methods
1626 for method_name in methods + XendAPI.Base_methods:
1627 doit('%s.%s' % (cls, method_name), True)
1629 # wrap validators around class functions
1630 for func_name in funcs + XendAPI.Base_funcs:
1631 doit('%s.%s' % (cls, func_name), False)
1633 _decorate()
1637 # Auto generate some stubs based on XendAPI introspection
1639 if __name__ == "__main__":
1640 def output(line):
1641 print ' ' + line
1643 classes = ['VDI', 'SR']
1644 for cls in classes:
1645 ro_attrs = getattr(XendAPI, '%s_attr_ro' % cls, [])
1646 rw_attrs = getattr(XendAPI, '%s_attr_rw' % cls, [])
1647 methods = getattr(XendAPI, '%s_methods' % cls, [])
1648 funcs = getattr(XendAPI, '%s_funcs' % cls, [])
1650 ref = '%s_ref' % cls
1652 for attr_name in ro_attrs + rw_attrs + XendAPI.Base_attr_ro:
1653 getter_name = '%s_get_%s' % (cls, attr_name)
1654 output('def %s(self, session, %s):' % (getter_name, ref))
1655 output(' return xen_api_todo()')
1657 for attr_name in rw_attrs + XendAPI.Base_attr_rw:
1658 setter_name = '%s_set_%s' % (cls, attr_name)
1659 output('def %s(self, session, %s, value):' % (setter_name, ref))
1660 output(' return xen_api_todo()')
1662 for method_name in methods + XendAPI.Base_methods:
1663 method_full_name = '%s_%s' % (cls,method_name)
1664 output('def %s(self, session, %s):' % (method_full_name, ref))
1665 output(' return xen_api_todo()')
1667 for func_name in funcs + XendAPI.Base_funcs:
1668 func_full_name = '%s_%s' % (cls, func_name)
1669 output('def %s(self, session):' % func_full_name)
1670 output(' return xen_api_todo()')