ia64/xen-unstable

view tools/python/xen/xend/XendDomain.py @ 15852:7dba4441bf92

xend: Fix error message for xm trigger command.

When I tested xm trigger command with a wrong argument, I saw the
following error message.

# xm trigger vm1 xyz
Error: __init__() takes exactly 2 arguments (3 given)
Usage: xm trigger <Domain> <nmi|reset|init> [<VCPU>]

Send a trigger to a domain.

This patch fixes the error message as follows.

# xm trigger vm1 xyz
Error: Invalid trigger: xyz
Usage: xm trigger <Domain> <nmi|reset|init> [<VCPU>]

Send a trigger to a domain.

The type of "TRIGGER_TYPE" is dictionary. domain_send_trigger()
refers to the keys of "TRIGGER_TYPE" without using keys() currently.
This patch adds keys() there.

Signed-off-by: Masaki Kanno <kanno.masaki@jp.fujitsu.com>
author kfraser@localhost.localdomain
date Fri Sep 07 11:24:28 2007 +0100 (2007-09-07)
parents 207582c8d88b
children 4cd10e49c3f8
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) 2004, 2005 Mike Wray <mike.wray@hp.com>
16 # Copyright (C) 2005 Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
17 # Copyright (C) 2005 XenSource Ltd
18 #============================================================================
20 """Handler for domain operations.
21 Nothing here is persistent (across reboots).
22 Needs to be persistent for one uptime.
23 """
25 import os
26 import stat
27 import shutil
28 import socket
29 import tempfile
30 import threading
32 import xen.lowlevel.xc
35 from xen.xend import XendOptions, XendCheckpoint, XendDomainInfo
36 from xen.xend.PrettyPrint import prettyprint
37 from xen.xend import XendConfig
38 from xen.xend.XendError import XendError, XendInvalidDomain, VmError
39 from xen.xend.XendError import VMBadState
40 from xen.xend.XendLogging import log
41 from xen.xend.XendAPIConstants import XEN_API_VM_POWER_STATE
42 from xen.xend.XendConstants import XS_VMROOT
43 from xen.xend.XendConstants import DOM_STATE_HALTED, DOM_STATE_PAUSED
44 from xen.xend.XendConstants import DOM_STATE_RUNNING, DOM_STATE_SUSPENDED
45 from xen.xend.XendConstants import DOM_STATE_SHUTDOWN, DOM_STATE_UNKNOWN
46 from xen.xend.XendConstants import TRIGGER_TYPE
47 from xen.xend.XendDevices import XendDevices
48 from xen.xend.XendAPIConstants import *
50 from xen.xend.xenstore.xstransact import xstransact
51 from xen.xend.xenstore.xswatch import xswatch
52 from xen.util import mkdir
53 from xen.xend import uuid
54 from xen.xend import sxp
56 xc = xen.lowlevel.xc.xc()
57 xoptions = XendOptions.instance()
59 __all__ = [ "XendDomain" ]
61 CACHED_CONFIG_FILE = 'config.sxp'
62 CHECK_POINT_FILE = 'checkpoint.chk'
63 DOM0_UUID = "00000000-0000-0000-0000-000000000000"
64 DOM0_NAME = "Domain-0"
65 DOM0_ID = 0
67 POWER_STATE_NAMES = dict([(x, XEN_API_VM_POWER_STATE[x])
68 for x in [DOM_STATE_HALTED,
69 DOM_STATE_PAUSED,
70 DOM_STATE_RUNNING,
71 DOM_STATE_SUSPENDED,
72 DOM_STATE_SHUTDOWN,
73 DOM_STATE_UNKNOWN]])
74 POWER_STATE_ALL = 'all'
77 class XendDomain:
78 """Index of all domains. Singleton.
80 @ivar domains: map of domains indexed by domid
81 @type domains: dict of XendDomainInfo
82 @ivar managed_domains: domains that are not running and managed by Xend
83 @type managed_domains: dict of XendDomainInfo indexed by uuid
84 @ivar domains_lock: lock that must be held when manipulating self.domains
85 @type domains_lock: threaading.RLock
86 @ivar _allow_new_domains: Flag to set that allows creating of new domains.
87 @type _allow_new_domains: boolean
88 """
90 def __init__(self):
91 self.domains = {}
92 self.managed_domains = {}
93 self.domains_lock = threading.RLock()
95 # xen api instance vars
96 # TODO: nothing uses this at the moment
97 self._allow_new_domains = True
99 # This must be called only the once, by instance() below. It is separate
100 # from the constructor because XendDomainInfo calls back into this class
101 # in order to check the uniqueness of domain names. This means that
102 # instance() must be able to return a valid instance of this class even
103 # during this initialisation.
104 def init(self):
105 """Singleton initialisation function."""
107 dom_path = self._managed_path()
108 mkdir.parents(dom_path, stat.S_IRWXU)
110 xstransact.Mkdir(XS_VMROOT)
111 xstransact.SetPermissions(XS_VMROOT, {'dom': DOM0_ID})
113 self.domains_lock.acquire()
114 try:
115 try:
116 dom0info = [d for d in self._running_domains() \
117 if d.get('domid') == DOM0_ID][0]
119 dom0info['name'] = DOM0_NAME
120 dom0 = XendDomainInfo.recreate(dom0info, True)
121 except IndexError:
122 raise XendError('Unable to find Domain 0')
124 self._setDom0CPUCount()
126 # This watch registration needs to be before the refresh call, so
127 # that we're sure that we haven't missed any releases, but inside
128 # the domains_lock, as we don't want the watch to fire until after
129 # the refresh call has completed.
130 xswatch("@introduceDomain", self._on_domains_changed)
131 xswatch("@releaseDomain", self._on_domains_changed)
133 self._init_domains()
134 finally:
135 self.domains_lock.release()
138 def _on_domains_changed(self, _):
139 """ Callback method when xenstore changes.
141 Calls refresh which will keep the local cache of domains
142 in sync.
144 @rtype: int
145 @return: 1
146 """
147 self.domains_lock.acquire()
148 try:
149 self._refresh()
150 finally:
151 self.domains_lock.release()
152 return 1
154 def _init_domains(self):
155 """Does the initial scan of managed and active domains to
156 populate self.domains.
158 Note: L{XendDomainInfo._checkName} will call back into XendDomain
159 to make sure domain name is not a duplicate.
161 """
162 self.domains_lock.acquire()
163 try:
164 running = self._running_domains()
165 managed = self._managed_domains()
167 # add all active domains
168 for dom in running:
169 if dom['dying'] == 1:
170 log.warn('Ignoring dying domain %d from now on' %
171 dom['domid'])
172 continue
174 if dom['domid'] != DOM0_ID:
175 try:
176 new_dom = XendDomainInfo.recreate(dom, False)
177 except Exception:
178 log.exception("Failed to create reference to running "
179 "domain id: %d" % dom['domid'])
181 # add all managed domains as dormant domains.
182 for dom in managed:
183 dom_uuid = dom.get('uuid')
184 if not dom_uuid:
185 continue
187 dom_name = dom.get('name_label', 'Domain-%s' % dom_uuid)
188 try:
189 running_dom = self.domain_lookup_nr(dom_name)
190 if not running_dom:
191 # instantiate domain if not started.
192 new_dom = XendDomainInfo.createDormant(dom)
193 self._managed_domain_register(new_dom)
194 else:
195 self._managed_domain_register(running_dom)
196 for key in XendConfig.XENAPI_CFG_TYPES.keys():
197 if key not in XendConfig.LEGACY_XENSTORE_VM_PARAMS and \
198 key in dom:
199 running_dom.info[key] = dom[key]
200 except Exception:
201 log.exception("Failed to create reference to managed "
202 "domain: %s" % dom_name)
204 finally:
205 self.domains_lock.release()
208 # -----------------------------------------------------------------
209 # Getting managed domains storage path names
211 def _managed_path(self, domuuid = None):
212 """Returns the path of the directory where managed domain
213 information is stored.
215 @keyword domuuid: If not None, will return the path to the domain
216 otherwise, will return the path containing
217 the directories which represent each domain.
218 @type: None or String.
219 @rtype: String
220 @return: Path.
221 """
222 dom_path = xoptions.get_xend_domains_path()
223 if domuuid:
224 dom_path = os.path.join(dom_path, domuuid)
225 return dom_path
227 def _managed_config_path(self, domuuid):
228 """Returns the path to the configuration file of a managed domain.
230 @param domname: Domain uuid
231 @type domname: String
232 @rtype: String
233 @return: path to config file.
234 """
235 return os.path.join(self._managed_path(domuuid), CACHED_CONFIG_FILE)
237 def _managed_check_point_path(self, domuuid):
238 """Returns absolute path to check point file for managed domain.
240 @param domuuid: Name of managed domain
241 @type domname: String
242 @rtype: String
243 @return: Path
244 """
245 return os.path.join(self._managed_path(domuuid), CHECK_POINT_FILE)
247 def _managed_config_remove(self, domuuid):
248 """Removes a domain configuration from managed list
250 @param domuuid: Name of managed domain
251 @type domname: String
252 @raise XendError: fails to remove the domain.
253 """
254 config_path = self._managed_path(domuuid)
255 try:
256 if os.path.exists(config_path) and os.path.isdir(config_path):
257 shutil.rmtree(config_path)
258 except IOError:
259 log.exception('managed_config_remove failed removing conf')
260 raise XendError("Unable to remove managed configuration"
261 " for domain: %s" % domuuid)
263 def managed_config_save(self, dominfo):
264 """Save a domain's configuration to disk
266 @param domninfo: Managed domain to save.
267 @type dominfo: XendDomainInfo
268 @raise XendError: fails to save configuration.
269 @rtype: None
270 """
271 if not self.is_domain_managed(dominfo):
272 return # refuse to save configuration this domain isn't managed
274 if dominfo:
275 domains_dir = self._managed_path()
276 dom_uuid = dominfo.get_uuid()
277 domain_config_dir = self._managed_path(dom_uuid)
279 def make_or_raise(path):
280 try:
281 mkdir.parents(path, stat.S_IRWXU)
282 except:
283 log.exception("%s could not be created." % path)
284 raise XendError("%s could not be created." % path)
286 make_or_raise(domains_dir)
287 make_or_raise(domain_config_dir)
289 try:
290 fd, fn = tempfile.mkstemp()
291 f = os.fdopen(fd, 'w+b')
292 try:
293 prettyprint(dominfo.sxpr(legacy_only = False), f,
294 width = 78)
295 finally:
296 f.close()
298 try:
299 shutil.move(fn, self._managed_config_path(dom_uuid))
300 except:
301 log.exception("Renaming %s to %s", fn,
302 self._managed_config_path(dom_uuid))
303 os.remove(fn)
304 except:
305 log.exception("Error occurred saving configuration file " +
306 "to %s" % domain_config_dir)
307 raise XendError("Failed to save configuration file to: %s" %
308 domain_config_dir)
309 else:
310 log.warn("Trying to save configuration for invalid domain")
313 def _managed_domains(self):
314 """ Returns list of domains that are managed.
316 Expects to be protected by domains_lock.
318 @rtype: list of XendConfig
319 @return: List of domain configurations that are managed.
320 """
321 dom_path = self._managed_path()
322 dom_uuids = os.listdir(dom_path)
323 doms = []
324 for dom_uuid in dom_uuids:
325 try:
326 cfg_file = self._managed_config_path(dom_uuid)
327 cfg = XendConfig.XendConfig(filename = cfg_file)
328 if cfg.get('uuid') != dom_uuid:
329 # something is wrong with the SXP
330 log.error("UUID mismatch in stored configuration: %s" %
331 cfg_file)
332 continue
333 doms.append(cfg)
334 except Exception:
335 log.exception('Unable to open or parse config.sxp: %s' % \
336 cfg_file)
337 return doms
339 def _managed_domain_unregister(self, dom):
340 try:
341 if self.is_domain_managed(dom):
342 self._managed_config_remove(dom.get_uuid())
343 del self.managed_domains[dom.get_uuid()]
344 except ValueError:
345 log.warn("Domain is not registered: %s" % dom.get_uuid())
347 def _managed_domain_register(self, dom):
348 self.managed_domains[dom.get_uuid()] = dom
350 def is_domain_managed(self, dom = None):
351 return (dom.get_uuid() in self.managed_domains)
353 # End of Managed Domain Access
354 # --------------------------------------------------------------------
356 def _running_domains(self):
357 """Get table of domains indexed by id from xc.
359 @requires: Expects to be protected by domains_lock.
360 @rtype: list of dicts
361 @return: A list of dicts representing the running domains.
362 """
363 try:
364 return xc.domain_getinfo()
365 except RuntimeError, e:
366 log.exception("Unable to get domain information.")
367 return {}
369 def _setDom0CPUCount(self):
370 """Sets the number of VCPUs dom0 has. Retreived from the
371 Xend configuration, L{XendOptions}.
373 @requires: Expects to be protected by domains_lock.
374 @rtype: None
375 """
376 dom0 = self.privilegedDomain()
378 # get max number of vcpus to use for dom0 from config
379 target = int(xoptions.get_dom0_vcpus())
380 log.debug("number of vcpus to use is %d", target)
382 # target == 0 means use all processors
383 if target > 0:
384 dom0.setVCpuCount(target)
387 def _refresh(self, refresh_shutdown = True):
388 """Refresh the domain list. Needs to be called when
389 either xenstore has changed or when a method requires
390 up to date information (like uptime, cputime stats).
392 Expects to be protected by the domains_lock.
394 @rtype: None
395 """
397 running = self._running_domains()
398 # Add domains that are not already tracked but running in Xen,
399 # and update domain state for those that are running and tracked.
400 for dom in running:
401 domid = dom['domid']
402 if domid in self.domains:
403 self.domains[domid].update(dom, refresh_shutdown)
404 elif domid not in self.domains and dom['dying'] != 1:
405 try:
406 new_dom = XendDomainInfo.recreate(dom, False)
407 except VmError:
408 log.exception("Unable to recreate domain")
409 try:
410 xc.domain_destroy(domid)
411 except:
412 log.exception("Hard destruction of domain failed: %d" %
413 domid)
415 # update information for all running domains
416 # - like cpu_time, status, dying, etc.
417 # remove domains that are not running from active domain list.
418 # The list might have changed by now, because the update call may
419 # cause new domains to be added, if the domain has rebooted. We get
420 # the list again.
421 running = self._running_domains()
422 running_domids = [d['domid'] for d in running if d['dying'] != 1]
423 for domid, dom in self.domains.items():
424 if domid not in running_domids and domid != DOM0_ID:
425 self._remove_domain(dom, domid)
428 def add_domain(self, info):
429 """Add a domain to the list of running domains
431 @requires: Expects to be protected by the domains_lock.
432 @param info: XendDomainInfo of a domain to be added.
433 @type info: XendDomainInfo
434 """
435 log.debug("Adding Domain: %s" % info.getDomid())
436 self.domains[info.getDomid()] = info
438 # update the managed domains with a new XendDomainInfo object
439 # if we are keeping track of it.
440 if info.get_uuid() in self.managed_domains:
441 self._managed_domain_register(info)
443 def remove_domain(self, info, domid = None):
444 """Remove the domain from the list of running domains, taking the
445 domains_lock first.
446 """
447 self.domains_lock.acquire()
448 try:
449 self._remove_domain(info, domid)
450 finally:
451 self.domains_lock.release()
453 def _remove_domain(self, info, domid = None):
454 """Remove the domain from the list of running domains
456 @requires: Expects to be protected by the domains_lock.
457 @param info: XendDomainInfo of a domain to be removed.
458 @type info: XendDomainInfo
459 """
460 if info:
461 if domid == None:
462 domid = info.getDomid()
464 if info._stateGet() != DOM_STATE_HALTED:
465 info.cleanupDomain()
467 if domid in self.domains:
468 del self.domains[domid]
469 else:
470 log.warning("Attempted to remove non-existent domain.")
472 def restore_(self, config):
473 """Create a domain as part of the restore process. This is called
474 only from L{XendCheckpoint}.
476 A restore request comes into XendDomain through L{domain_restore}
477 or L{domain_restore_fd}. That request is
478 forwarded immediately to XendCheckpoint which, when it is ready, will
479 call this method. It is necessary to come through here rather than go
480 directly to L{XendDomainInfo.restore} because we need to
481 serialise the domain creation process, but cannot lock
482 domain_restore_fd as a whole, otherwise we will deadlock waiting for
483 the old domain to die.
485 @param config: Configuration of domain to restore
486 @type config: SXP Object (eg. list of lists)
487 """
488 self.domains_lock.acquire()
489 try:
490 dominfo = XendDomainInfo.restore(config)
491 return dominfo
492 finally:
493 self.domains_lock.release()
496 def domain_lookup(self, domid):
497 """Look up given I{domid} in the list of managed and running
498 domains.
500 @note: Will cause a refresh before lookup up domains, for
501 a version that does not need to re-read xenstore
502 use L{domain_lookup_nr}.
504 @param domid: Domain ID or Domain Name.
505 @type domid: int or string
506 @return: Found domain.
507 @rtype: XendDomainInfo
508 @raise XendInvalidDomain: If domain is not found.
509 """
510 self.domains_lock.acquire()
511 try:
512 self._refresh(refresh_shutdown = False)
513 dom = self.domain_lookup_nr(domid)
514 if not dom:
515 raise XendInvalidDomain(str(domid))
516 return dom
517 finally:
518 self.domains_lock.release()
521 def domain_lookup_nr(self, domid):
522 """Look up given I{domid} in the list of managed and running
523 domains.
525 @param domid: Domain ID or Domain Name.
526 @type domid: int or string
527 @return: Found domain.
528 @rtype: XendDomainInfo or None
529 """
530 self.domains_lock.acquire()
531 try:
532 # lookup by name
533 match = [dom for dom in self.domains.values() \
534 if dom.getName() == domid]
535 if match:
536 return match[0]
538 match = [dom for dom in self.managed_domains.values() \
539 if dom.getName() == domid]
540 if match:
541 return match[0]
543 # lookup by id
544 try:
545 if int(domid) in self.domains:
546 return self.domains[int(domid)]
547 except ValueError:
548 pass
550 # lookup by uuid for running domains
551 match = [dom for dom in self.domains.values() \
552 if dom.get_uuid() == domid]
553 if match:
554 return match[0]
556 # lookup by uuid for inactive managed domains
557 if domid in self.managed_domains:
558 return self.managed_domains[domid]
560 return None
561 finally:
562 self.domains_lock.release()
564 def privilegedDomain(self):
565 """ Get the XendDomainInfo of a dom0
567 @rtype: XendDomainInfo
568 """
569 self.domains_lock.acquire()
570 try:
571 return self.domains[DOM0_ID]
572 finally:
573 self.domains_lock.release()
575 def autostart_domains(self):
576 """ Autostart managed domains that are marked as such. """
578 need_starting = []
580 self.domains_lock.acquire()
581 try:
582 for dom_uuid, dom in self.managed_domains.items():
583 if dom and dom._stateGet() == DOM_STATE_HALTED:
584 on_xend_start = dom.info.get('on_xend_start', 'ignore')
585 auto_power_on = dom.info.get('auto_power_on', False)
586 should_start = (on_xend_start == 'start') or auto_power_on
587 if should_start:
588 need_starting.append(dom_uuid)
589 finally:
590 self.domains_lock.release()
592 for dom_uuid in need_starting:
593 self.domain_start(dom_uuid, False)
595 def cleanup_domains(self):
596 """Clean up domains that are marked as autostop.
597 Should be called when Xend goes down. This is currently
598 called from L{xen.xend.servers.XMLRPCServer}.
600 """
601 log.debug('cleanup_domains')
602 self.domains_lock.acquire()
603 try:
604 for dom in self.domains.values():
605 if dom.getName() == DOM0_NAME:
606 continue
608 if dom._stateGet() == DOM_STATE_RUNNING:
609 shutdownAction = dom.info.get('on_xend_stop', 'ignore')
610 if shutdownAction == 'shutdown':
611 log.debug('Shutting down domain: %s' % dom.getName())
612 dom.shutdown("poweroff")
613 elif shutdownAction == 'suspend':
614 self.domain_suspend(dom.getName())
615 finally:
616 self.domains_lock.release()
620 # ----------------------------------------------------------------
621 # Xen API
624 def set_allow_new_domains(self, allow_new_domains):
625 self._allow_new_domains = allow_new_domains
627 def allow_new_domains(self):
628 return self._allow_new_domains
630 def get_domain_refs(self):
631 result = []
632 try:
633 self.domains_lock.acquire()
634 result = [d.get_uuid() for d in self.domains.values()]
635 for d in self.managed_domains.keys():
636 if d not in result:
637 result.append(d)
638 return result
639 finally:
640 self.domains_lock.release()
642 def get_all_vms(self):
643 self.domains_lock.acquire()
644 try:
645 result = self.domains.values()
646 result += [x for x in self.managed_domains.values() if
647 x not in result]
648 return result
649 finally:
650 self.domains_lock.release()
652 def get_vm_by_uuid(self, vm_uuid):
653 self.domains_lock.acquire()
654 try:
655 for dom in self.domains.values():
656 if dom.get_uuid() == vm_uuid:
657 return dom
659 if vm_uuid in self.managed_domains:
660 return self.managed_domains[vm_uuid]
662 return None
663 finally:
664 self.domains_lock.release()
666 def get_vm_with_dev_uuid(self, klass, dev_uuid):
667 self.domains_lock.acquire()
668 try:
669 for dom in self.domains.values() + self.managed_domains.values():
670 if dom.has_device(klass, dev_uuid):
671 return dom
672 return None
673 finally:
674 self.domains_lock.release()
676 def get_dev_property_by_uuid(self, klass, dev_uuid, field):
677 value = None
678 self.domains_lock.acquire()
680 try:
681 try:
682 dom = self.get_vm_with_dev_uuid(klass, dev_uuid)
683 if dom:
684 value = dom.get_dev_property(klass, dev_uuid, field)
685 except ValueError, e:
686 pass
687 finally:
688 self.domains_lock.release()
690 return value
692 def set_dev_property_by_uuid(self, klass, dev_uuid, field, value,
693 old_val = None):
694 rc = True
695 self.domains_lock.acquire()
697 try:
698 try:
699 dom = self.get_vm_with_dev_uuid(klass, dev_uuid)
700 if dom:
701 o_val = dom.get_dev_property(klass, dev_uuid, field)
702 log.info("o_val=%s, old_val=%s" % (o_val, old_val))
703 if old_val and old_val != o_val:
704 return False
706 dom.set_dev_property(klass, dev_uuid, field, value)
707 self.managed_config_save(dom)
708 except ValueError, e:
709 pass
710 finally:
711 self.domains_lock.release()
713 return rc
715 def is_valid_vm(self, vm_ref):
716 return (self.get_vm_by_uuid(vm_ref) != None)
718 def is_valid_dev(self, klass, dev_uuid):
719 return (self.get_vm_with_dev_uuid(klass, dev_uuid) != None)
721 def do_legacy_api_with_uuid(self, fn, vm_uuid, *args, **kwargs):
722 dom = self.uuid_to_dom(vm_uuid)
723 fn(dom, *args, **kwargs)
725 def uuid_to_dom(self, vm_uuid):
726 self.domains_lock.acquire()
727 try:
728 for domid, dom in self.domains.items():
729 if dom.get_uuid() == vm_uuid:
730 return domid
732 if vm_uuid in self.managed_domains:
733 domid = self.managed_domains[vm_uuid].getDomid()
734 if domid is None:
735 return self.managed_domains[vm_uuid].getName()
736 else:
737 return domid
739 raise XendInvalidDomain(vm_uuid)
740 finally:
741 self.domains_lock.release()
744 def create_domain(self, xenapi_vm):
745 self.domains_lock.acquire()
746 try:
747 try:
748 xeninfo = XendConfig.XendConfig(xapi = xenapi_vm)
749 dominfo = XendDomainInfo.createDormant(xeninfo)
750 log.debug("Creating new managed domain: %s: %s" %
751 (dominfo.getName(), dominfo.get_uuid()))
752 self._managed_domain_register(dominfo)
753 self.managed_config_save(dominfo)
754 return dominfo.get_uuid()
755 except XendError, e:
756 raise
757 except Exception, e:
758 raise XendError(str(e))
759 finally:
760 self.domains_lock.release()
762 def rename_domain(self, dom, new_name):
763 self.domains_lock.acquire()
764 try:
765 old_name = dom.getName()
766 dom.setName(new_name)
768 finally:
769 self.domains_lock.release()
772 #
773 # End of Xen API
774 # ----------------------------------------------------------------
776 # ------------------------------------------------------------
777 # Xen Legacy API
779 def list(self, state = DOM_STATE_RUNNING):
780 """Get list of domain objects.
782 @param: the state in which the VMs should be -- one of the
783 DOM_STATE_XYZ constants, or the corresponding name, or 'all'.
784 @return: domains
785 @rtype: list of XendDomainInfo
786 """
787 if type(state) == int:
788 state = POWER_STATE_NAMES[state]
789 state = state.lower()
791 self.domains_lock.acquire()
792 try:
793 self._refresh(refresh_shutdown = False)
795 # active domains
796 active_domains = self.domains.values()
797 active_uuids = [d.get_uuid() for d in active_domains]
799 # inactive domains
800 inactive_domains = []
801 for dom_uuid, dom in self.managed_domains.items():
802 if dom_uuid not in active_uuids:
803 inactive_domains.append(dom)
805 if state == POWER_STATE_ALL:
806 return active_domains + inactive_domains
807 else:
808 return filter(lambda x:
809 POWER_STATE_NAMES[x._stateGet()].lower() == state,
810 active_domains + inactive_domains)
811 finally:
812 self.domains_lock.release()
815 def list_sorted(self, state = DOM_STATE_RUNNING):
816 """Get list of domain objects, sorted by name.
818 @param: the state in which the VMs should be -- one of the
819 DOM_STATE_XYZ constants, or the corresponding name, or 'all'.
820 @return: domain objects
821 @rtype: list of XendDomainInfo
822 """
823 doms = self.list(state)
824 doms.sort(lambda x, y: cmp(x.getName(), y.getName()))
825 return doms
827 def list_names(self, state = DOM_STATE_RUNNING):
828 """Get list of domain names.
830 @param: the state in which the VMs should be -- one of the
831 DOM_STATE_XYZ constants, or the corresponding name, or 'all'.
832 @return: domain names
833 @rtype: list of strings.
834 """
835 return [d.getName() for d in self.list_sorted(state)]
837 def domain_suspend(self, domname):
838 """Suspends a domain that is persistently managed by Xend
840 @param domname: Domain Name
841 @type domname: string
842 @rtype: None
843 @raise XendError: Failure during checkpointing.
844 """
846 try:
847 dominfo = self.domain_lookup_nr(domname)
848 if not dominfo:
849 raise XendInvalidDomain(domname)
851 if dominfo.getDomid() == DOM0_ID:
852 raise XendError("Cannot save privileged domain %s" % domname)
854 if dominfo._stateGet() != DOM_STATE_RUNNING:
855 raise VMBadState("Domain is not running",
856 POWER_STATE_NAMES[DOM_STATE_RUNNING],
857 POWER_STATE_NAMES[dominfo._stateGet()])
859 dom_uuid = dominfo.get_uuid()
861 if not os.path.exists(self._managed_config_path(dom_uuid)):
862 raise XendError("Domain is not managed by Xend lifecycle " +
863 "support.")
865 path = self._managed_check_point_path(dom_uuid)
866 oflags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC
867 if hasattr(os, "O_LARGEFILE"):
868 oflags |= os.O_LARGEFILE
869 fd = os.open(path, oflags)
870 try:
871 # For now we don't support 'live checkpoint'
872 XendCheckpoint.save(fd, dominfo, False, False, path)
873 finally:
874 os.close(fd)
875 except OSError, ex:
876 raise XendError("can't write guest state file %s: %s" %
877 (path, ex[1]))
879 def domain_resume(self, domname, start_paused = False):
880 """Resumes a domain that is persistently managed by Xend.
882 @param domname: Domain Name
883 @type domname: string
884 @rtype: None
885 @raise XendError: If failed to restore.
886 """
887 self.domains_lock.acquire()
888 try:
889 try:
890 dominfo = self.domain_lookup_nr(domname)
892 if not dominfo:
893 raise XendInvalidDomain(domname)
895 if dominfo.getDomid() == DOM0_ID:
896 raise XendError("Cannot save privileged domain %s" % domname)
898 if dominfo._stateGet() != XEN_API_VM_POWER_STATE_SUSPENDED:
899 raise XendError("Cannot resume domain that is not suspended.")
901 dom_uuid = dominfo.get_uuid()
902 chkpath = self._managed_check_point_path(dom_uuid)
903 if not os.path.exists(chkpath):
904 raise XendError("Domain was not suspended by Xend")
906 # Restore that replaces the existing XendDomainInfo
907 try:
908 log.debug('Current DomainInfo state: %d' % dominfo._stateGet())
909 oflags = os.O_RDONLY
910 if hasattr(os, "O_LARGEFILE"):
911 oflags |= os.O_LARGEFILE
912 XendCheckpoint.restore(self,
913 os.open(chkpath, oflags),
914 dominfo,
915 paused = start_paused)
916 os.unlink(chkpath)
917 except OSError, ex:
918 raise XendError("Failed to read stored checkpoint file")
919 except IOError, ex:
920 raise XendError("Failed to delete checkpoint file")
921 except Exception, ex:
922 log.exception("Exception occurred when resuming")
923 raise XendError("Error occurred when resuming: %s" % str(ex))
924 finally:
925 self.domains_lock.release()
928 def domain_create(self, config):
929 """Create a domain from a configuration.
931 @param config: configuration
932 @type config: SXP Object (list of lists)
933 @rtype: XendDomainInfo
934 """
935 self.domains_lock.acquire()
936 try:
937 self._refresh()
939 dominfo = XendDomainInfo.create(config)
940 return dominfo
941 finally:
942 self.domains_lock.release()
945 def domain_create_from_dict(self, config_dict):
946 """Create a domain from a configuration dictionary.
948 @param config_dict: configuration
949 @rtype: XendDomainInfo
950 """
951 self.domains_lock.acquire()
952 try:
953 self._refresh()
955 dominfo = XendDomainInfo.create_from_dict(config_dict)
956 return dominfo
957 finally:
958 self.domains_lock.release()
961 def domain_new(self, config):
962 """Create a domain from a configuration but do not start it.
964 @param config: configuration
965 @type config: SXP Object (list of lists)
966 @rtype: XendDomainInfo
967 """
968 self.domains_lock.acquire()
969 try:
970 try:
971 domconfig = XendConfig.XendConfig(sxp_obj = config)
973 domains = self.list('all')
974 domains = map(lambda dom: dom.sxpr(), domains)
975 for dom in domains:
976 if sxp.child_value(config, 'uuid', None):
977 if domconfig['uuid'] == sxp.child_value(dom, 'uuid'):
978 if domconfig['name_label'] != sxp.child_value(dom, 'name'):
979 raise XendError("Domain UUID '%s' is already used." % \
980 domconfig['uuid'])
981 else:
982 # Update the config for that existing domain
983 # because it is same name and same UUID.
984 break
985 else:
986 if domconfig['name_label'] == sxp.child_value(dom, 'name'):
987 raise XendError("Domain name '%s' is already used." % \
988 domconfig['name_label'])
989 else:
990 if domconfig['name_label'] == sxp.child_value(dom, 'name'):
991 # Overwrite the auto-generated UUID by the UUID
992 # of the existing domain. And update the config
993 # for that existing domain.
994 domconfig['uuid'] = sxp.child_value(dom, 'uuid')
995 break
997 dominfo = XendDomainInfo.createDormant(domconfig)
998 log.debug("Creating new managed domain: %s" %
999 dominfo.getName())
1000 self._managed_domain_register(dominfo)
1001 self.managed_config_save(dominfo)
1002 # no return value because it isn't meaningful for client
1003 except XendError, e:
1004 raise
1005 except Exception, e:
1006 raise XendError(str(e))
1007 finally:
1008 self.domains_lock.release()
1010 def domain_start(self, domid, start_paused = True):
1011 """Start a managed domain
1013 @require: Domain must not be running.
1014 @param domid: Domain name or domain ID.
1015 @type domid: string or int
1016 @rtype: None
1017 @raise XendError: If domain is still running
1018 @rtype: None
1019 """
1020 self.domains_lock.acquire()
1021 try:
1022 self._refresh()
1024 dominfo = self.domain_lookup_nr(domid)
1025 if not dominfo:
1026 raise XendInvalidDomain(str(domid))
1028 if dominfo._stateGet() != DOM_STATE_HALTED:
1029 raise VMBadState("Domain is already running",
1030 POWER_STATE_NAMES[DOM_STATE_HALTED],
1031 POWER_STATE_NAMES[dominfo._stateGet()])
1033 dominfo.start(is_managed = True)
1034 finally:
1035 self.domains_lock.release()
1037 try:
1038 dominfo.waitForDevices()
1039 except Exception, ex:
1040 log.warn("Failed to setup devices for " + str(dominfo) + ": " + str(ex))
1041 dominfo.destroy()
1042 raise
1044 if not start_paused:
1045 dominfo.unpause()
1047 def domain_delete(self, domid):
1048 """Remove a managed domain from database
1050 @require: Domain must not be running.
1051 @param domid: Domain name or domain ID.
1052 @type domid: string or int
1053 @rtype: None
1054 @raise XendError: If domain is still running
1055 """
1056 self.domains_lock.acquire()
1057 try:
1058 try:
1059 dominfo = self.domain_lookup_nr(domid)
1060 if not dominfo:
1061 raise XendInvalidDomain(str(domid))
1063 if dominfo._stateGet() != XEN_API_VM_POWER_STATE_HALTED:
1064 raise VMBadState("Domain is not halted.",
1065 POWER_STATE_NAMES[DOM_STATE_HALTED],
1066 POWER_STATE_NAMES[dominfo._stateGet()])
1068 self._domain_delete_by_info(dominfo)
1069 except Exception, ex:
1070 raise XendError(str(ex))
1071 finally:
1072 self.domains_lock.release()
1075 def domain_delete_by_dominfo(self, dominfo):
1076 """Only for use by XendDomainInfo.
1077 """
1078 self.domains_lock.acquire()
1079 try:
1080 self._domain_delete_by_info(dominfo)
1081 finally:
1082 self.domains_lock.release()
1085 def _domain_delete_by_info(self, dominfo):
1086 """Expects to be protected by domains_lock.
1087 """
1088 log.info("Domain %s (%s) deleted." %
1089 (dominfo.getName(), dominfo.info.get('uuid')))
1091 self._managed_domain_unregister(dominfo)
1092 self._remove_domain(dominfo)
1093 XendDevices.destroy_device_state(dominfo)
1096 def domain_configure(self, config):
1097 """Configure an existing domain.
1099 @param vmconfig: vm configuration
1100 @type vmconfig: SXP Object (list of lists)
1101 @todo: Not implemented
1102 """
1103 # !!!
1104 raise XendError("Unsupported")
1106 def domain_restore(self, src, paused=False):
1107 """Restore a domain from file.
1109 @param src: filename of checkpoint file to restore from
1110 @type src: string
1111 @return: Restored domain
1112 @rtype: XendDomainInfo
1113 @raise XendError: Failure to restore domain
1114 """
1115 try:
1116 oflags = os.O_RDONLY
1117 if hasattr(os, "O_LARGEFILE"):
1118 oflags |= os.O_LARGEFILE
1119 fd = os.open(src, oflags)
1120 try:
1121 return self.domain_restore_fd(fd, paused=paused)
1122 finally:
1123 os.close(fd)
1124 except OSError, ex:
1125 raise XendError("can't read guest state file %s: %s" %
1126 (src, ex[1]))
1128 def domain_restore_fd(self, fd, paused=False):
1129 """Restore a domain from the given file descriptor.
1131 @param fd: file descriptor of the checkpoint file
1132 @type fd: File object
1133 @rtype: XendDomainInfo
1134 @raise XendError: if failed to restore
1135 """
1137 try:
1138 return XendCheckpoint.restore(self, fd, paused=paused)
1139 except XendError, e:
1140 log.exception("Restore failed")
1141 raise
1142 except:
1143 # I don't really want to log this exception here, but the error
1144 # handling in the relocation-socket handling code (relocate.py) is
1145 # poor, so we need to log this for debugging.
1146 log.exception("Restore failed")
1147 raise XendError("Restore failed")
1149 def domain_unpause(self, domid):
1150 """Unpause domain execution.
1152 @param domid: Domain ID or Name
1153 @type domid: int or string.
1154 @rtype: None
1155 @raise XendError: Failed to unpause
1156 @raise XendInvalidDomain: Domain is not valid
1157 """
1158 try:
1159 dominfo = self.domain_lookup_nr(domid)
1160 if not dominfo:
1161 raise XendInvalidDomain(str(domid))
1162 if dominfo.getDomid() == DOM0_ID:
1163 raise XendError("Cannot unpause privileged domain %s" % domid)
1164 if dominfo._stateGet() not in (DOM_STATE_PAUSED, DOM_STATE_RUNNING):
1165 raise VMBadState("Domain '%s' is not started" % domid,
1166 POWER_STATE_NAMES[DOM_STATE_PAUSED],
1167 POWER_STATE_NAMES[dominfo._stateGet()])
1168 log.info("Domain %s (%d) unpaused.", dominfo.getName(),
1169 int(dominfo.getDomid()))
1170 dominfo.unpause()
1171 except XendInvalidDomain:
1172 log.exception("domain_unpause")
1173 raise
1174 except Exception, ex:
1175 log.exception("domain_unpause")
1176 raise XendError(str(ex))
1178 def domain_pause(self, domid):
1179 """Pause domain execution.
1181 @param domid: Domain ID or Name
1182 @type domid: int or string.
1183 @rtype: None
1184 @raise XendError: Failed to pause
1185 @raise XendInvalidDomain: Domain is not valid
1186 """
1187 try:
1188 dominfo = self.domain_lookup_nr(domid)
1189 if not dominfo:
1190 raise XendInvalidDomain(str(domid))
1191 if dominfo.getDomid() == DOM0_ID:
1192 raise XendError("Cannot pause privileged domain %s" % domid)
1193 if dominfo._stateGet() not in (DOM_STATE_RUNNING, DOM_STATE_PAUSED):
1194 raise VMBadState("Domain '%s' is not started" % domid,
1195 POWER_STATE_NAMES[DOM_STATE_RUNNING],
1196 POWER_STATE_NAMES[dominfo._stateGet()])
1197 log.info("Domain %s (%d) paused.", dominfo.getName(),
1198 int(dominfo.getDomid()))
1199 dominfo.pause()
1200 except XendInvalidDomain:
1201 log.exception("domain_pause")
1202 raise
1203 except Exception, ex:
1204 log.exception("domain_pause")
1205 raise XendError(str(ex))
1207 def domain_dump(self, domid, filename, live, crash):
1208 """Dump domain core."""
1210 dominfo = self.domain_lookup_nr(domid)
1211 if not dominfo:
1212 raise XendInvalidDomain(str(domid))
1214 if dominfo.getDomid() == DOM0_ID:
1215 raise XendError("Cannot dump core for privileged domain %s" % domid)
1216 if dominfo._stateGet() not in (DOM_STATE_PAUSED, DOM_STATE_RUNNING):
1217 raise VMBadState("Domain '%s' is not started" % domid,
1218 POWER_STATE_NAMES[DOM_STATE_PAUSED],
1219 POWER_STATE_NAMES[dominfo._stateGet()])
1221 try:
1222 log.info("Domain core dump requested for domain %s (%d) "
1223 "live=%d crash=%d.",
1224 dominfo.getName(), dominfo.getDomid(), live, crash)
1225 return dominfo.dumpCore(filename)
1226 except Exception, ex:
1227 raise XendError(str(ex))
1229 def domain_destroy(self, domid):
1230 """Terminate domain immediately.
1232 @param domid: Domain ID or Name
1233 @type domid: int or string.
1234 @rtype: None
1235 @raise XendError: Failed to destroy
1236 @raise XendInvalidDomain: Domain is not valid
1237 """
1239 dominfo = self.domain_lookup_nr(domid)
1240 if dominfo and dominfo.getDomid() == DOM0_ID:
1241 raise XendError("Cannot destroy privileged domain %s" % domid)
1243 if dominfo:
1244 val = dominfo.destroy()
1245 else:
1246 try:
1247 val = xc.domain_destroy(int(domid))
1248 except ValueError:
1249 raise XendInvalidDomain(domid)
1250 except Exception, e:
1251 raise XendError(str(e))
1253 return val
1255 def domain_migrate(self, domid, dst, live=False, resource=0, port=0):
1256 """Start domain migration.
1258 @param domid: Domain ID or Name
1259 @type domid: int or string.
1260 @param dst: Destination IP address
1261 @type dst: string
1262 @keyword port: relocation port on destination
1263 @type port: int
1264 @keyword live: Live migration
1265 @type live: bool
1266 @keyword resource: not used??
1267 @rtype: None
1268 @raise XendError: Failed to migrate
1269 @raise XendInvalidDomain: Domain is not valid
1270 """
1272 dominfo = self.domain_lookup_nr(domid)
1273 if not dominfo:
1274 raise XendInvalidDomain(str(domid))
1276 if dominfo.getDomid() == DOM0_ID:
1277 raise XendError("Cannot migrate privileged domain %s" % domid)
1279 """ The following call may raise a XendError exception """
1280 dominfo.testMigrateDevices(True, dst)
1282 if live:
1283 """ Make sure there's memory free for enabling shadow mode """
1284 dominfo.checkLiveMigrateMemory()
1286 if port == 0:
1287 port = xoptions.get_xend_relocation_port()
1288 try:
1289 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1290 sock.connect((dst, port))
1291 except socket.error, err:
1292 raise XendError("can't connect: %s" % err[1])
1294 sock.send("receive\n")
1295 sock.recv(80)
1296 XendCheckpoint.save(sock.fileno(), dominfo, True, live, dst)
1297 sock.close()
1299 def domain_save(self, domid, dst, checkpoint=False):
1300 """Start saving a domain to file.
1302 @param domid: Domain ID or Name
1303 @type domid: int or string.
1304 @param dst: Destination filename
1305 @type dst: string
1306 @rtype: None
1307 @raise XendError: Failed to save domain
1308 @raise XendInvalidDomain: Domain is not valid
1309 """
1310 try:
1311 dominfo = self.domain_lookup_nr(domid)
1312 if not dominfo:
1313 raise XendInvalidDomain(str(domid))
1315 if dominfo.getDomid() == DOM0_ID:
1316 raise XendError("Cannot save privileged domain %s" % str(domid))
1317 if dominfo._stateGet() != DOM_STATE_RUNNING:
1318 raise VMBadState("Domain is not running",
1319 POWER_STATE_NAMES[DOM_STATE_RUNNING],
1320 POWER_STATE_NAMES[dominfo._stateGet()])
1322 oflags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC
1323 if hasattr(os, "O_LARGEFILE"):
1324 oflags |= os.O_LARGEFILE
1325 fd = os.open(dst, oflags)
1326 try:
1327 XendCheckpoint.save(fd, dominfo, False, False, dst,
1328 checkpoint=checkpoint)
1329 except Exception, e:
1330 os.close(fd)
1331 raise e
1332 os.close(fd)
1333 except OSError, ex:
1334 raise XendError("can't write guest state file %s: %s" %
1335 (dst, ex[1]))
1337 def domain_pincpu(self, domid, vcpu, cpumap):
1338 """Set which cpus vcpu can use
1340 @param domid: Domain ID or Name
1341 @type domid: int or string.
1342 @param vcpu: vcpu to pin to
1343 @type vcpu: int
1344 @param cpumap: string repr of usable cpus
1345 @type cpumap: string
1346 @rtype: 0
1347 """
1348 dominfo = self.domain_lookup_nr(domid)
1349 if not dominfo:
1350 raise XendInvalidDomain(str(domid))
1352 # if vcpu is keyword 'all', apply the cpumap to all vcpus
1353 vcpus = [ vcpu ]
1354 if str(vcpu).lower() == "all":
1355 vcpus = range(0, int(dominfo.getVCpuCount()))
1357 # set the same cpumask for all vcpus
1358 rc = 0
1359 for v in vcpus:
1360 try:
1361 rc = xc.vcpu_setaffinity(dominfo.getDomid(), int(v), cpumap)
1362 except Exception, ex:
1363 log.exception(ex)
1364 raise XendError("Cannot pin vcpu: %s to cpu: %s - %s" % \
1365 (v, cpumap, str(ex)))
1366 return rc
1368 def domain_cpu_sedf_set(self, domid, period, slice_, latency, extratime,
1369 weight):
1370 """Set Simple EDF scheduler parameters for a domain.
1372 @param domid: Domain ID or Name
1373 @type domid: int or string.
1374 @rtype: 0
1375 """
1376 dominfo = self.domain_lookup_nr(domid)
1377 if not dominfo:
1378 raise XendInvalidDomain(str(domid))
1379 try:
1380 return xc.sedf_domain_set(dominfo.getDomid(), period, slice_,
1381 latency, extratime, weight)
1382 except Exception, ex:
1383 raise XendError(str(ex))
1385 def domain_cpu_sedf_get(self, domid):
1386 """Get Simple EDF scheduler parameters for a domain.
1388 @param domid: Domain ID or Name
1389 @type domid: int or string.
1390 @rtype: SXP object
1391 @return: The parameters for Simple EDF schedule for a domain.
1392 """
1393 dominfo = self.domain_lookup_nr(domid)
1394 if not dominfo:
1395 raise XendInvalidDomain(str(domid))
1396 try:
1397 sedf_info = xc.sedf_domain_get(dominfo.getDomid())
1398 # return sxpr
1399 return ['sedf',
1400 ['domid', sedf_info['domid']],
1401 ['period', sedf_info['period']],
1402 ['slice', sedf_info['slice']],
1403 ['latency', sedf_info['latency']],
1404 ['extratime', sedf_info['extratime']],
1405 ['weight', sedf_info['weight']]]
1407 except Exception, ex:
1408 raise XendError(str(ex))
1410 def domain_shadow_control(self, domid, op):
1411 """Shadow page control.
1413 @param domid: Domain ID or Name
1414 @type domid: int or string.
1415 @param op: operation
1416 @type op: int
1417 @rtype: 0
1418 """
1419 dominfo = self.domain_lookup(domid)
1420 try:
1421 return xc.shadow_control(dominfo.getDomid(), op)
1422 except Exception, ex:
1423 raise XendError(str(ex))
1425 def domain_shadow_mem_get(self, domid):
1426 """Get shadow pagetable memory allocation.
1428 @param domid: Domain ID or Name
1429 @type domid: int or string.
1430 @rtype: int
1431 @return: shadow memory in MB
1432 """
1433 dominfo = self.domain_lookup(domid)
1434 try:
1435 return xc.shadow_mem_control(dominfo.getDomid())
1436 except Exception, ex:
1437 raise XendError(str(ex))
1439 def domain_shadow_mem_set(self, domid, mb):
1440 """Set shadow pagetable memory allocation.
1442 @param domid: Domain ID or Name
1443 @type domid: int or string.
1444 @param mb: shadow memory to set in MB
1445 @type: mb: int
1446 @rtype: int
1447 @return: shadow memory in MB
1448 """
1449 dominfo = self.domain_lookup(domid)
1450 try:
1451 return xc.shadow_mem_control(dominfo.getDomid(), mb=mb)
1452 except Exception, ex:
1453 raise XendError(str(ex))
1455 def domain_sched_credit_get(self, domid):
1456 """Get credit scheduler parameters for a domain.
1458 @param domid: Domain ID or Name
1459 @type domid: int or string.
1460 @rtype: dict with keys 'weight' and 'cap'
1461 @return: credit scheduler parameters
1462 """
1463 dominfo = self.domain_lookup_nr(domid)
1464 if not dominfo:
1465 raise XendInvalidDomain(str(domid))
1467 if dominfo._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED):
1468 try:
1469 return xc.sched_credit_domain_get(dominfo.getDomid())
1470 except Exception, ex:
1471 raise XendError(str(ex))
1472 else:
1473 return {'weight' : dominfo.getWeight(),
1474 'cap' : dominfo.getCap()}
1476 def domain_sched_credit_set(self, domid, weight = None, cap = None):
1477 """Set credit scheduler parameters for a domain.
1479 @param domid: Domain ID or Name
1480 @type domid: int or string.
1481 @type weight: int
1482 @type cap: int
1483 @rtype: 0
1484 """
1485 set_weight = False
1486 set_cap = False
1487 dominfo = self.domain_lookup_nr(domid)
1488 if not dominfo:
1489 raise XendInvalidDomain(str(domid))
1490 try:
1491 if weight is None:
1492 weight = int(0)
1493 elif weight < 1 or weight > 65535:
1494 raise XendError("weight is out of range")
1495 else:
1496 set_weight = True
1498 if cap is None:
1499 cap = int(~0)
1500 elif cap < 0 or cap > dominfo.getVCpuCount() * 100:
1501 raise XendError("cap is out of range")
1502 else:
1503 set_cap = True
1505 assert type(weight) == int
1506 assert type(cap) == int
1508 rc = 0
1509 if dominfo._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED):
1510 rc = xc.sched_credit_domain_set(dominfo.getDomid(), weight, cap)
1511 if rc == 0:
1512 if set_weight:
1513 dominfo.setWeight(weight)
1514 if set_cap:
1515 dominfo.setCap(cap)
1516 self.managed_config_save(dominfo)
1517 return rc
1518 except Exception, ex:
1519 log.exception(ex)
1520 raise XendError(str(ex))
1522 def domain_maxmem_set(self, domid, mem):
1523 """Set the memory limit for a domain.
1525 @param domid: Domain ID or Name
1526 @type domid: int or string.
1527 @param mem: memory limit (in MiB)
1528 @type mem: int
1529 @raise XendError: fail to set memory
1530 @rtype: 0
1531 """
1532 dominfo = self.domain_lookup_nr(domid)
1533 if not dominfo:
1534 raise XendInvalidDomain(str(domid))
1535 dominfo.setMemoryMaximum(mem)
1537 def domain_ioport_range_enable(self, domid, first, last):
1538 """Enable access to a range of IO ports for a domain
1540 @param first: first IO port
1541 @param last: last IO port
1542 @raise XendError: failed to set range
1543 @rtype: 0
1544 """
1545 dominfo = self.domain_lookup_nr(domid)
1546 if not dominfo:
1547 raise XendInvalidDomain(str(domid))
1548 nr_ports = last - first + 1
1549 try:
1550 return xc.domain_ioport_permission(dominfo.getDomid(),
1551 first_port = first,
1552 nr_ports = nr_ports,
1553 allow_access = 1)
1554 except Exception, ex:
1555 raise XendError(str(ex))
1557 def domain_ioport_range_disable(self, domid, first, last):
1558 """Disable access to a range of IO ports for a domain
1560 @param first: first IO port
1561 @param last: last IO port
1562 @raise XendError: failed to set range
1563 @rtype: 0
1564 """
1565 dominfo = self.domain_lookup_nr(domid)
1566 if not dominfo:
1567 raise XendInvalidDomain(str(domid))
1568 nr_ports = last - first + 1
1569 try:
1570 return xc.domain_ioport_permission(dominfo.getDomid(),
1571 first_port = first,
1572 nr_ports = nr_ports,
1573 allow_access = 0)
1574 except Exception, ex:
1575 raise XendError(str(ex))
1577 def domain_send_trigger(self, domid, trigger_name, vcpu = 0):
1578 """Send trigger to a domain.
1580 @param domid: Domain ID or Name
1581 @type domid: int or string.
1582 @param trigger_name: trigger type name
1583 @type trigger_name: string
1584 @param vcpu: VCPU to send trigger (default is 0)
1585 @type vcpu: int
1586 @raise XendError: failed to send trigger
1587 @raise XendInvalidDomain: Domain is not valid
1588 @rtype: 0
1589 """
1590 dominfo = self.domain_lookup_nr(domid)
1591 if not dominfo:
1592 raise XendInvalidDomain(str(domid))
1593 if dominfo._stateGet() not in (DOM_STATE_RUNNING, DOM_STATE_PAUSED):
1594 raise VMBadState("Domain '%s' is not started" % domid,
1595 POWER_STATE_NAMES[DOM_STATE_RUNNING],
1596 POWER_STATE_NAMES[dominfo._stateGet()])
1597 if trigger_name.lower() in TRIGGER_TYPE.keys():
1598 trigger = TRIGGER_TYPE[trigger_name.lower()]
1599 else:
1600 raise XendError("Invalid trigger: %s" % trigger_name)
1601 try:
1602 return xc.domain_send_trigger(dominfo.getDomid(),
1603 trigger,
1604 vcpu)
1605 except Exception, ex:
1606 raise XendError(str(ex))
1609 def instance():
1610 """Singleton constructor. Use this instead of the class constructor.
1611 """
1612 global inst
1613 try:
1614 inst
1615 except:
1616 inst = XendDomain()
1617 inst.init()
1618 return inst