debuggers.hg

annotate tools/python/xen/xend/XendDomain.py @ 16675:9b37cabe0485

xend: Indicate a resume operation

Indicate that the domain is created as part of a resume operation
rather than a 'create'.

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