[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] Deprecate XendDomainInfo.state - now use _stateGet() to get the live
# HG changeset patch # User Tom Wilkie <tom.wilkie@xxxxxxxxx> # Date 1177088188 -3600 # Node ID 55135bf6eb4459fb130e9d27f7ccbeb89b86637b # Parent 53b1cfcf129fd89139723512c3560dac22961aff Deprecate XendDomainInfo.state - now use _stateGet() to get the live state of a domain. Should still call _stateSet() to notify others when you expect the state has changed. Also some changes to locking in save/suspend, restore/resume and migrate Passes xm-test against XenAPI... signed-off-by: Tom Wilkie <tom.wilkie@xxxxxxxxx> --- tools/python/xen/xend/XendCheckpoint.py | 24 +++++++ tools/python/xen/xend/XendConfig.py | 2 tools/python/xen/xend/XendDomain.py | 29 ++++----- tools/python/xen/xend/XendDomainInfo.py | 97 +++++++++++++++++++++++--------- 4 files changed, 108 insertions(+), 44 deletions(-) diff -r 53b1cfcf129f -r 55135bf6eb44 tools/python/xen/xend/XendCheckpoint.py --- a/tools/python/xen/xend/XendCheckpoint.py Fri Apr 20 17:51:10 2007 +0100 +++ b/tools/python/xen/xend/XendCheckpoint.py Fri Apr 20 17:56:28 2007 +0100 @@ -253,8 +253,28 @@ def restore(xd, fd, dominfo = None, paus os.read(fd, 1) # Wait for source to close connection dominfo.completeRestore(handler.store_mfn, handler.console_mfn) - - dominfo.waitForDevices() # Wait for backends to set up + + # + # We shouldn't hold the domains_lock over a waitForDevices + # As this function sometime gets called holding this lock, + # we must release it and re-acquire it appropriately + # + from xen.xend import XendDomain + + lock = True; + try: + XendDomain.instance().domains_lock.release() + except: + lock = False; + + try: + dominfo.waitForDevices() # Wait for backends to set up + except Exception, exn: + log.exception(exn) + + if lock: + XendDomain.instance().domains_lock.acquire() + if not paused: dominfo.unpause() diff -r 53b1cfcf129f -r 55135bf6eb44 tools/python/xen/xend/XendConfig.py --- a/tools/python/xen/xend/XendConfig.py Fri Apr 20 17:51:10 2007 +0100 +++ b/tools/python/xen/xend/XendConfig.py Fri Apr 20 17:56:28 2007 +0100 @@ -870,7 +870,7 @@ class XendConfig(dict): sxpr.append([legacy, self[legacy]]) sxpr.append(['image', self.image_sxpr()]) - sxpr.append(['status', domain.state]) + sxpr.append(['status', domain._stateGet()]) if domain.getDomid() is not None: sxpr.append(['state', self._get_old_state_string()]) diff -r 53b1cfcf129f -r 55135bf6eb44 tools/python/xen/xend/XendDomain.py --- a/tools/python/xen/xend/XendDomain.py Fri Apr 20 17:51:10 2007 +0100 +++ b/tools/python/xen/xend/XendDomain.py Fri Apr 20 17:56:28 2007 +0100 @@ -45,6 +45,7 @@ from xen.xend.XendConstants import DOM_S from xen.xend.XendConstants import DOM_STATE_SHUTDOWN, DOM_STATE_UNKNOWN from xen.xend.XendConstants import TRIGGER_TYPE from xen.xend.XendDevices import XendDevices +from xen.xend.XendAPIConstants import * from xen.xend.xenstore.xstransact import xstransact from xen.xend.xenstore.xswatch import xswatch @@ -457,7 +458,7 @@ class XendDomain: if domid == None: domid = info.getDomid() - if info.state != DOM_STATE_HALTED: + if info._stateGet() != DOM_STATE_HALTED: info.cleanupDomain() if domid in self.domains: @@ -577,7 +578,7 @@ class XendDomain: self.domains_lock.acquire() try: for dom_uuid, dom in self.managed_domains.items(): - if dom and dom.state == DOM_STATE_HALTED: + if dom and dom._stateGet() == DOM_STATE_HALTED: on_xend_start = dom.info.get('on_xend_start', 'ignore') auto_power_on = dom.info.get('auto_power_on', False) should_start = (on_xend_start == 'start') or auto_power_on @@ -602,7 +603,7 @@ class XendDomain: if dom.getName() == DOM0_NAME: continue - if dom.state == DOM_STATE_RUNNING: + if dom._stateGet() == DOM_STATE_RUNNING: shutdownAction = dom.info.get('on_xend_stop', 'ignore') if shutdownAction == 'shutdown': log.debug('Shutting down domain: %s' % dom.getName()) @@ -780,7 +781,7 @@ class XendDomain: return active_domains + inactive_domains else: return filter(lambda x: - POWER_STATE_NAMES[x.state].lower() == state, + POWER_STATE_NAMES[x._stateGet()].lower() == state, active_domains + inactive_domains) finally: self.domains_lock.release() @@ -825,10 +826,10 @@ class XendDomain: if dominfo.getDomid() == DOM0_ID: raise XendError("Cannot save privileged domain %s" % domname) - if dominfo.state != DOM_STATE_RUNNING: + if dominfo._stateGet() != DOM_STATE_RUNNING: raise VMBadState("Domain is not running", POWER_STATE_NAMES[DOM_STATE_RUNNING], - POWER_STATE_NAMES[dominfo.state]) + POWER_STATE_NAMES[dominfo._stateGet()]) dom_uuid = dominfo.get_uuid() @@ -869,8 +870,8 @@ class XendDomain: if dominfo.getDomid() == DOM0_ID: raise XendError("Cannot save privileged domain %s" % domname) - if dominfo.state != DOM_STATE_HALTED: - raise XendError("Cannot resume domain that is not halted.") + if dominfo._stateGet() != XEN_API_VM_POWER_STATE_SUSPENDED: + raise XendError("Cannot resume domain that is not suspended.") dom_uuid = dominfo.get_uuid() chkpath = self._managed_check_point_path(dom_uuid) @@ -879,7 +880,7 @@ class XendDomain: # Restore that replaces the existing XendDomainInfo try: - log.debug('Current DomainInfo state: %d' % dominfo.state) + log.debug('Current DomainInfo state: %d' % dominfo._stateGet()) oflags = os.O_RDONLY if hasattr(os, "O_LARGEFILE"): oflags |= os.O_LARGEFILE @@ -974,10 +975,10 @@ class XendDomain: if not dominfo: raise XendInvalidDomain(str(domid)) - if dominfo.state != DOM_STATE_HALTED: + if dominfo._stateGet() != DOM_STATE_HALTED: raise VMBadState("Domain is already running", POWER_STATE_NAMES[DOM_STATE_HALTED], - POWER_STATE_NAMES[dominfo.state]) + POWER_STATE_NAMES[dominfo._stateGet()]) dominfo.start(is_managed = True) finally: @@ -1003,10 +1004,10 @@ class XendDomain: if not dominfo: raise XendInvalidDomain(str(domid)) - if dominfo.state != DOM_STATE_HALTED: - raise VMBadState("Domain is still running", + if dominfo._stateGet() != XEN_API_VM_POWER_STATE_HALTED: + raise VMBadState("Domain is not halted.", POWER_STATE_NAMES[DOM_STATE_HALTED], - POWER_STATE_NAMES[dominfo.state]) + POWER_STATE_NAMES[dominfo._stateGet()]) self._domain_delete_by_info(dominfo) except Exception, ex: diff -r 53b1cfcf129f -r 55135bf6eb44 tools/python/xen/xend/XendDomainInfo.py --- a/tools/python/xen/xend/XendDomainInfo.py Fri Apr 20 17:51:10 2007 +0100 +++ b/tools/python/xen/xend/XendDomainInfo.py Fri Apr 20 17:56:28 2007 +0100 @@ -30,6 +30,7 @@ import re import re import copy import os +import traceback from types import StringTypes import xen.lowlevel.xc @@ -309,8 +310,8 @@ class XendDomainInfo: @type shutdownWatch: xen.xend.xenstore.xswatch @ivar shutdownStartTime: UNIX Time when domain started shutting down. @type shutdownStartTime: float or None - @ivar state: Domain state - @type state: enum(DOM_STATE_HALTED, DOM_STATE_RUNNING, ...) +# @ivar state: Domain state +# @type state: enum(DOM_STATE_HALTED, DOM_STATE_RUNNING, ...) @ivar state_updated: lock for self.state @type state_updated: threading.Condition @ivar refresh_shutdown_lock: lock for polling shutdown state @@ -361,9 +362,9 @@ class XendDomainInfo: self.shutdownStartTime = None self._resume = resume - self.state = DOM_STATE_HALTED self.state_updated = threading.Condition() self.refresh_shutdown_lock = threading.Condition() + self._stateSet(DOM_STATE_HALTED) self._deviceControllers = {} @@ -389,7 +390,7 @@ class XendDomainInfo: """ from xen.xend import XendDomain - if self.state == DOM_STATE_HALTED: + if self._stateGet() in (XEN_API_VM_POWER_STATE_HALTED, XEN_API_VM_POWER_STATE_SUSPENDED): try: XendTask.log_progress(0, 30, self._constructDomain) XendTask.log_progress(31, 60, self._initDomain) @@ -420,7 +421,8 @@ class XendDomainInfo: def resume(self): """Resumes a domain that has come back from suspension.""" - if self.state in (DOM_STATE_HALTED, DOM_STATE_SUSPENDED): + state = self._stateGet() + if state in (DOM_STATE_SUSPENDED, DOM_STATE_HALTED): try: self._constructDomain() self._storeVmDetails() @@ -433,12 +435,13 @@ class XendDomainInfo: self.destroy() raise else: - raise XendError('VM already running') + raise XendError('VM is not susupened; it is %s' + % XEN_API_VM_POWER_STATE[state]) def shutdown(self, reason): """Shutdown a domain by signalling this via xenstored.""" log.debug('XendDomainInfo.shutdown(%s)', reason) - if self.state in (DOM_STATE_SHUTDOWN, DOM_STATE_HALTED,): + if self._stateGet() in (DOM_STATE_SHUTDOWN, DOM_STATE_HALTED,): raise XendError('Domain cannot be shutdown') if self.domid == 0: @@ -558,8 +561,7 @@ class XendDomainInfo: return self.getDeviceController(deviceClass).destroyDevice(devid, force) def getDeviceSxprs(self, deviceClass): - if self.state == DOM_STATE_RUNNING \ - or self.state == DOM_STATE_PAUSED: + if self._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED): return self.getDeviceController(deviceClass).sxprs() else: sxprs = [] @@ -1579,11 +1581,10 @@ class XendDomainInfo: def waitForShutdown(self): self.state_updated.acquire() try: - while self.state in (DOM_STATE_RUNNING,DOM_STATE_PAUSED): + while self._stateGet() in (DOM_STATE_RUNNING,DOM_STATE_PAUSED): self.state_updated.wait() finally: self.state_updated.release() - # # TODO: recategorise - called from XendCheckpoint @@ -1980,17 +1981,59 @@ class XendDomainInfo: # Utility functions # + def __getattr__(self, name): + if name == "state": + log.warn("Somebody tried to read XendDomainInfo.state... should us _stateGet()!!!") + log.warn("".join(traceback.format_stack())) + return self._stateGet() + else: + raise AttributeError() + + def __setattr__(self, name, value): + if name == "state": + log.warn("Somebody tried to set XendDomainInfo.state... should us _stateGet()!!!") + log.warn("".join(traceback.format_stack())) + self._stateSet(value) + else: + self.__dict__[name] = value + def _stateSet(self, state): self.state_updated.acquire() try: - if self.state != state: - self.state = state + # TODO Not sure this is correct... + # _stateGet is live now. Why not fire event + # even when it hasn't changed? + if self._stateGet() != state: self.state_updated.notifyAll() import XendAPI XendAPI.event_dispatch('mod', 'VM', self.info['uuid'], 'power_state') finally: self.state_updated.release() + + def _stateGet(self): + # Lets try and reconsitute the state from xc + # first lets try and get the domain info + # from xc - this will tell us if the domain + # exists + info = dom_get(self.getDomid()) + if info is None or info['shutdown']: + # We are either HALTED or SUSPENDED + # check saved image exists + from xen.xend import XendDomain + managed_config_path = \ + XendDomain.instance()._managed_check_point_path( \ + self.get_uuid()) + if os.path.exists(managed_config_path): + return XEN_API_VM_POWER_STATE_SUSPENDED + else: + return XEN_API_VM_POWER_STATE_HALTED + else: + # We are either RUNNING or PAUSED + if info['paused']: + return XEN_API_VM_POWER_STATE_PAUSED + else: + return XEN_API_VM_POWER_STATE_RUNNING def _infoIsSet(self, name): return name in self.info and self.info[name] is not None @@ -2107,7 +2150,7 @@ class XendDomainInfo: retval = xc.sched_credit_domain_get(self.getDomid()) return retval def get_power_state(self): - return XEN_API_VM_POWER_STATE[self.state] + return XEN_API_VM_POWER_STATE[self._stateGet()] def get_platform(self): return self.info.get('platform', {}) def get_pci_bus(self): @@ -2156,7 +2199,7 @@ class XendDomainInfo: # shortcut if the domain isn't started because # the devcontrollers will have no better information # than XendConfig. - if self.state in (XEN_API_VM_POWER_STATE_HALTED,): + if self._stateGet() in (XEN_API_VM_POWER_STATE_HALTED,): if dev_config: return copy.deepcopy(dev_config) return None @@ -2215,7 +2258,7 @@ class XendDomainInfo: config['MTU'] = 1500 # TODO - if self.state not in (XEN_API_VM_POWER_STATE_HALTED,): + if self._stateGet() not in (XEN_API_VM_POWER_STATE_HALTED,): xennode = XendNode.instance() rx_bps, tx_bps = xennode.get_vif_util(self.domid, devid) config['io_read_kbs'] = rx_bps/1024 @@ -2226,7 +2269,7 @@ class XendDomainInfo: if dev_class == 'vbd': - if self.state not in (XEN_API_VM_POWER_STATE_HALTED,): + if self._stateGet() not in (XEN_API_VM_POWER_STATE_HALTED,): controller = self.getDeviceController(dev_class) devid, _1, _2 = controller.getDeviceDetails(config) xennode = XendNode.instance() @@ -2312,8 +2355,8 @@ class XendDomainInfo: if not dev_uuid: raise XendError('Failed to create device') - if self.state == XEN_API_VM_POWER_STATE_RUNNING or \ - self.state == XEN_API_VM_POWER_STATE_PAUSED: + if self._stateGet() in (XEN_API_VM_POWER_STATE_RUNNING, + XEN_API_VM_POWER_STATE_PAUSED): _, config = self.info['devices'][dev_uuid] if vdi_image_path.startswith('tap'): @@ -2347,7 +2390,7 @@ class XendDomainInfo: if not dev_uuid: raise XendError('Failed to create device') - if self.state == XEN_API_VM_POWER_STATE_RUNNING: + if self._stateGet() == XEN_API_VM_POWER_STATE_RUNNING: _, config = self.info['devices'][dev_uuid] config['devid'] = self.getDeviceController('tap').createDevice(config) @@ -2364,8 +2407,8 @@ class XendDomainInfo: if not dev_uuid: raise XendError('Failed to create device') - if self.state == XEN_API_VM_POWER_STATE_RUNNING \ - or self.state == XEN_API_VM_POWER_STATE_PAUSED: + if self._stateGet() in (XEN_API_VM_POWER_STATE_RUNNING, + XEN_API_VM_POWER_STATE_PAUSED): _, config = self.info['devices'][dev_uuid] dev_control = self.getDeviceController('vif') @@ -2390,7 +2433,7 @@ class XendDomainInfo: @rtype: string """ - if self.state not in (DOM_STATE_HALTED,): + if self._stateGet() not in (DOM_STATE_HALTED,): raise VmError("Can only add vTPM to a halted domain.") if self.get_vtpms() != []: raise VmError('Domain already has a vTPM.') @@ -2406,7 +2449,7 @@ class XendDomainInfo: @return: uuid of device @rtype: string """ - if self.state not in (DOM_STATE_HALTED,): + if self._stateGet() not in (DOM_STATE_HALTED,): raise VmError("Can only add console to a halted domain.") dev_uuid = self.info.device_add('console', cfg_xenapi = xenapi_console) @@ -2420,8 +2463,8 @@ class XendDomainInfo: raise XendError('Device does not exist') try: - if self.state == XEN_API_VM_POWER_STATE_RUNNING \ - or self.state == XEN_API_VM_POWER_STATE_PAUSED: + if self._stateGet() in (XEN_API_VM_POWER_STATE_RUNNING, + XEN_API_VM_POWER_STATE_PAUSED): _, config = self.info['devices'][dev_uuid] devid = config.get('devid') if devid != None: @@ -2448,7 +2491,7 @@ class XendDomainInfo: def __str__(self): return '<domain id=%s name=%s memory=%s state=%s>' % \ (str(self.domid), self.info['name_label'], - str(self.info['memory_dynamic_max']), DOM_STATES[self.state]) + str(self.info['memory_dynamic_max']), DOM_STATES[self._stateGet()]) __repr__ = __str__ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |