direct-io.hg

changeset 12486:645ef4726bce

[XEND] Fix missing domains on domU reboot.

Fixed regression with rebooting domU caused by the change in handling
syncing state from Xen and Xend.

Added missing implementation for XendDomainInfo.unwatchVm() which
disappeared during a merge.

Added protection for console/vnc-port reading for managed domains.

Signed-off-by: Alastair Tse <atse@xensource.com>
author Alastair Tse <atse@xensource.com>
date Fri Nov 17 15:53:29 2006 +0000 (2006-11-17)
parents 58f28e00001e
children 516821812322
files tools/python/xen/xend/XendConfig.py tools/python/xen/xend/XendDomain.py tools/python/xen/xend/XendDomainInfo.py
line diff
     1.1 --- a/tools/python/xen/xend/XendConfig.py	Fri Nov 17 14:00:45 2006 +0000
     1.2 +++ b/tools/python/xen/xend/XendConfig.py	Fri Nov 17 15:53:29 2006 +0000
     1.3 @@ -583,7 +583,7 @@ class XendConfig(dict):
     1.4          old_state = sxp.child_value(parsed, 'state')
     1.5          if old_state:
     1.6              for i in range(len(CONFIG_OLD_DOM_STATES)):
     1.7 -                cfg[CONFIG_OLD_DOM_STATES[i]] = (old_state[i] != '-')
     1.8 +                cfg[CONFIG_OLD_DOM_STATES[i]] = int(old_state[i] != '-')
     1.9  
    1.10          # Xen API extra cfgs
    1.11          # ------------------
     2.1 --- a/tools/python/xen/xend/XendDomain.py	Fri Nov 17 14:00:45 2006 +0000
     2.2 +++ b/tools/python/xen/xend/XendDomain.py	Fri Nov 17 15:53:29 2006 +0000
     2.3 @@ -33,7 +33,7 @@ import xen.lowlevel.xc
     2.4  from xen.xend import XendRoot, XendCheckpoint, XendDomainInfo
     2.5  from xen.xend.PrettyPrint import prettyprint
     2.6  from xen.xend.XendConfig import XendConfig
     2.7 -from xen.xend.XendError import XendError, XendInvalidDomain
     2.8 +from xen.xend.XendError import XendError, XendInvalidDomain, VmError
     2.9  from xen.xend.XendLogging import log
    2.10  from xen.xend.XendConstants import XS_VMROOT
    2.11  from xen.xend.XendConstants import DOM_STATE_HALTED, DOM_STATE_RUNNING
    2.12 @@ -65,7 +65,6 @@ class XendDomain:
    2.13      @type domains_lock: threaading.RLock
    2.14      @ivar _allow_new_domains: Flag to set that allows creating of new domains.
    2.15      @type _allow_new_domains: boolean
    2.16 -    
    2.17      """
    2.18  
    2.19      def __init__(self):
    2.20 @@ -281,9 +280,13 @@ class XendDomain:
    2.21                  sxp_cache_file = open(self._managed_config_path(dom_uuid),'w')
    2.22                  prettyprint(dominfo.sxpr(), sxp_cache_file, width = 78)
    2.23                  sxp_cache_file.close()
    2.24 -            except IOError:
    2.25 -                log.error("Error occurred saving configuration file to %s" %
    2.26 -                          domain_config_dir)
    2.27 +            except:
    2.28 +                log.exception("Error occurred saving configuration file " +
    2.29 +                              "to %s" % domain_config_dir)
    2.30 +                try:
    2.31 +                    self._managed_domain_remove(dom_uuid)
    2.32 +                except:
    2.33 +                    pass
    2.34                  raise XendError("Failed to save configuration file to: %s" %
    2.35                                  domain_config_dir)
    2.36          else:
    2.37 @@ -377,19 +380,33 @@ class XendDomain:
    2.38          # update information for all running domains
    2.39          # - like cpu_time, status, dying, etc.
    2.40          running = self._running_domains()
    2.41 +        running_domids = [d['domid'] for d in running if d['dying'] != 1]
    2.42 +
    2.43 +        # remove domains that are not running from active domain list.
    2.44 +        # The list might have changed by now, because the update call may
    2.45 +        # cause new domains to be added, if the domain has rebooted.  We get
    2.46 +        # the list again.        
    2.47 +        for domid, dom in self.domains.items():
    2.48 +            if domid not in running_domids and domid != DOM0_ID:
    2.49 +                self._remove_domain(dom, domid)
    2.50 +
    2.51 +        # Add domains that are not already tracked but running in Xen,
    2.52 +        # and update domain state for those that are running and tracked.
    2.53          for dom in running:
    2.54              domid = dom['domid']
    2.55              if domid in self.domains and dom['dying'] != 1:
    2.56                  self.domains[domid].update(dom)
    2.57 -
    2.58 -        # remove domains that are not running from active domain list.
    2.59 -        # The list might have changed by now, because the update call may
    2.60 -        # cause new domains to be added, if the domain has rebooted.  We get
    2.61 -        # the list again.
    2.62 -        running_domids = [d['domid'] for d in running if d['dying'] != 1]
    2.63 -        for domid, dom in self.domains.items():
    2.64 -            if domid not in running_domids and domid != DOM0_ID:
    2.65 -                self._remove_domain(dom, domid)
    2.66 +            elif domid not in self.domains and dom['dying'] != 1:
    2.67 +                try:
    2.68 +                    new_dom = XendDomainInfo.recreate(dom, False)
    2.69 +                    self._add_domain(new_dom)                    
    2.70 +                except VmError:
    2.71 +                    log.exception("Unable to recreate domain")
    2.72 +                    try:
    2.73 +                        xc.domain_destroy(domid)
    2.74 +                    except:
    2.75 +                        log.exception("Hard destruction of domain failed: %d" %
    2.76 +                                      domid)
    2.77  
    2.78  
    2.79      def _add_domain(self, info):
    2.80 @@ -409,7 +426,6 @@ class XendDomain:
    2.81          @param info: XendDomainInfo of a domain to be removed.
    2.82          @type info: XendDomainInfo
    2.83          """
    2.84 -
    2.85          if info:
    2.86              if domid == None:
    2.87                  domid = info.getDomid()
     3.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Fri Nov 17 14:00:45 2006 +0000
     3.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Fri Nov 17 15:53:29 2006 +0000
     3.3 @@ -403,7 +403,7 @@ class XendDomainInfo:
     3.4          self.vmWatch = None
     3.5          self.shutdownWatch = None
     3.6          self.shutdownStartTime = None
     3.7 -        
     3.8 +
     3.9          self.state = DOM_STATE_HALTED
    3.10          self.state_updated = threading.Condition()
    3.11          self.refresh_shutdown_lock = threading.Condition()
    3.12 @@ -430,7 +430,7 @@ class XendDomainInfo:
    3.13          initialisation if it not started.
    3.14          """
    3.15          from xen.xend import XendDomain
    3.16 -        
    3.17 +
    3.18          if self.state == DOM_STATE_HALTED:
    3.19              try:
    3.20                  self._constructDomain()
    3.21 @@ -443,7 +443,6 @@ class XendDomainInfo:
    3.22  
    3.23                  # save running configuration if XendDomains believe domain is
    3.24                  # persistent
    3.25 -                #
    3.26                  if is_managed:
    3.27                      xendomains = XendDomain.instance()
    3.28                      xendomains.managed_config_save(self)
    3.29 @@ -475,6 +474,9 @@ class XendDomainInfo:
    3.30          log.debug('XendDomainInfo.shutdown')
    3.31          if self.state in (DOM_STATE_SHUTDOWN, DOM_STATE_HALTED,):
    3.32              raise XendError('Domain cannot be shutdown')
    3.33 +
    3.34 +        if self.domid == 0:
    3.35 +            raise XendError('Domain 0 cannot be shutdown')
    3.36          
    3.37          if not reason in DOMAIN_SHUTDOWN_REASONS.values():
    3.38              raise XendError('Invalid reason: %s' % reason)
    3.39 @@ -920,7 +922,7 @@ class XendDomainInfo:
    3.40                          # the VM path now, otherwise we will end up with one
    3.41                          # watch for the old domain, and one for the new.
    3.42                          self._unwatchVm()
    3.43 -                    elif reason in ['poweroff', 'reboot']:
    3.44 +                    elif reason in ('poweroff', 'reboot'):
    3.45                          restart_reason = reason
    3.46                      else:
    3.47                          self.destroy()
    3.48 @@ -1521,6 +1523,14 @@ class XendDomainInfo:
    3.49      def _unwatchVm(self):
    3.50          """Remove the watch on the VM path, if any.  Idempotent.  Nothrow
    3.51          guarantee."""
    3.52 +        try:
    3.53 +            try:
    3.54 +                if self.vmWatch:
    3.55 +                    self.vmWatch.unwatch()
    3.56 +            finally:
    3.57 +                self.vmWatch = None
    3.58 +        except:
    3.59 +            log.exception("Unwatching VM path failed.")
    3.60  
    3.61      def testDeviceComplete(self):
    3.62          """ For Block IO migration safety we must ensure that
    3.63 @@ -1663,7 +1673,7 @@ class XendDomainInfo:
    3.64          result = self.info.get_sxp(domain = self,
    3.65                                     ignore_devices = ignore_store)
    3.66  
    3.67 -        if not ignore_store:
    3.68 +        if not ignore_store and self.dompath:
    3.69              vnc_port = self._readDom('console/vnc-port')
    3.70              if vnc_port is not None:
    3.71                  result.append(['device',