[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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.