ia64/xen-unstable

changeset 7454:6a7253b1ce8a

Fix the recently-introduced failure to preserve uuid across a guest reboot.
Store the uuid in string form inside XendDomainInfo, to aid this.

Add restart-squelching logic to ensure that runaway domains to restart
indefinitely. The logic here could be cleverer, say including a backoff for
retrying, in case a network block device has gone away, but for now this will
do to stop the pathological behaviour. Fixes bug #275.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author emellor@leeni.uk.xensource.com
date Thu Oct 20 12:34:50 2005 +0100 (2005-10-20)
parents fb265175f47c
children 1e7bbbdff402
files tools/python/xen/xend/XendDomainInfo.py
line diff
     1.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Wed Oct 19 18:18:30 2005 +0100
     1.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Thu Oct 20 12:34:50 2005 +0100
     1.3 @@ -87,6 +87,10 @@ VMROOT  = '/vm/'
     1.4  
     1.5  ZOMBIE_PREFIX = 'Zombie-'
     1.6  
     1.7 +"""Minimum time between domain restarts in seconds."""
     1.8 +MINIMUM_RESTART_TIME = 20
     1.9 +
    1.10 +
    1.11  xc = xen.lowlevel.xc.new()
    1.12  xroot = XendRoot.instance()
    1.13  
    1.14 @@ -102,6 +106,7 @@ log = logging.getLogger("xend.XendDomain
    1.15  # file, so those are handled separately.
    1.16  ROUNDTRIPPING_CONFIG_ENTRIES = [
    1.17          ('name',         str),
    1.18 +        ('uuid',         str),
    1.19          ('ssidref',      int),
    1.20          ('vcpus',        int),
    1.21          ('vcpu_avail',   int),
    1.22 @@ -141,7 +146,7 @@ def create(config):
    1.23  
    1.24      log.debug("XendDomainInfo.create(%s)", config)
    1.25  
    1.26 -    vm = XendDomainInfo(uuid.create(), parseConfig(config))
    1.27 +    vm = XendDomainInfo(parseConfig(config))
    1.28      try:
    1.29          vm.construct()
    1.30          vm.initDomain()
    1.31 @@ -166,10 +171,13 @@ def recreate(xeninfo, priv):
    1.32  
    1.33      domid = xeninfo['dom']
    1.34      uuid1 = xeninfo['handle']
    1.35 +    xeninfo['uuid'] = uuid.toString(uuid1)
    1.36      dompath = GetDomainPath(domid)
    1.37      if not dompath:
    1.38          raise XendError(
    1.39              'No domain path in store for existing domain %d' % domid)
    1.40 +
    1.41 +    log.info("Recreating domain %d, UUID %s.", domid, xeninfo['uuid'])
    1.42      try:
    1.43          vmpath = xstransact.Read(dompath, "vm")
    1.44          if not vmpath:
    1.45 @@ -185,19 +193,15 @@ def recreate(xeninfo, priv):
    1.46          if uuid1 != uuid2:
    1.47              raise XendError(
    1.48                  'Uuid in store does not match uuid for existing domain %d: '
    1.49 -                '%s != %s' % (domid, uuid2_str, uuid.toString(uuid1)))
    1.50 +                '%s != %s' % (domid, uuid2_str, xeninfo['uuid']))
    1.51  
    1.52 -        log.info("Recreating domain %d, UUID %s.", domid, uuid2_str)
    1.53 -
    1.54 -        vm = XendDomainInfo(uuid1, xeninfo, domid, dompath, True)
    1.55 +        vm = XendDomainInfo(xeninfo, domid, dompath, True)
    1.56  
    1.57      except Exception, exn:
    1.58 -        log.warn(str(exn))
    1.59 +        if True:
    1.60 +            log.warn(str(exn))
    1.61  
    1.62 -        log.info("Recreating domain %d with UUID %s.", domid,
    1.63 -                 uuid.toString(uuid1))
    1.64 -
    1.65 -        vm = XendDomainInfo(uuid1, xeninfo, domid, dompath, True)
    1.66 +        vm = XendDomainInfo(xeninfo, domid, dompath, True)
    1.67          vm.removeDom()
    1.68          vm.removeVm()
    1.69          vm.storeVmDetails()
    1.70 @@ -215,8 +219,7 @@ def restore(config):
    1.71  
    1.72      log.debug("XendDomainInfo.restore(%s)", config)
    1.73  
    1.74 -    vm = XendDomainInfo(uuid.fromString(sxp.child_value(config, 'uuid')),
    1.75 -                        parseConfig(config))
    1.76 +    vm = XendDomainInfo(parseConfig(config))
    1.77      try:
    1.78          vm.construct()
    1.79          vm.storeVmDetails()
    1.80 @@ -335,19 +338,15 @@ def dom_get(dom):
    1.81      return None
    1.82  
    1.83  class XendDomainInfo:
    1.84 -    """Virtual machine object."""
    1.85 -
    1.86 -    """Minimum time between domain restarts in seconds.
    1.87 -    """
    1.88 -    MINIMUM_RESTART_TIME = 20
    1.89  
    1.90  
    1.91 -    def __init__(self, uuidbytes, info, domid = None, dompath = None,
    1.92 -                 augment = False):
    1.93 +    def __init__(self, info, domid = None, dompath = None, augment = False):
    1.94  
    1.95 -        self.uuidbytes = uuidbytes
    1.96          self.info = info
    1.97  
    1.98 +        if not self.infoIsSet('uuid'):
    1.99 +            self.info['uuid'] = uuid.toString(uuid.create())
   1.100 +
   1.101          if domid is not None:
   1.102              self.domid = domid
   1.103          elif 'dom' in info:
   1.104 @@ -355,7 +354,7 @@ class XendDomainInfo:
   1.105          else:
   1.106              self.domid = None
   1.107  
   1.108 -        self.vmpath  = VMROOT + uuid.toString(uuidbytes)
   1.109 +        self.vmpath  = VMROOT + self.info['uuid']
   1.110          self.dompath = dompath
   1.111  
   1.112          if augment:
   1.113 @@ -571,7 +570,7 @@ class XendDomainInfo:
   1.114  
   1.115      def storeVmDetails(self):
   1.116          to_store = {
   1.117 -            'uuid':               uuid.toString(self.uuidbytes),
   1.118 +            'uuid':               self.info['uuid'],
   1.119  
   1.120              # XXX
   1.121              'memory/target':      str(self.info['memory_KiB'])
   1.122 @@ -928,7 +927,6 @@ class XendDomainInfo:
   1.123      def sxpr(self):
   1.124          sxpr = ['domain',
   1.125                  ['domid',   self.domid],
   1.126 -                ['uuid',    uuid.toString(self.uuidbytes)],
   1.127                  ['memory',  self.info['memory_KiB'] / 1024]]
   1.128  
   1.129          for e in ROUNDTRIPPING_CONFIG_ENTRIES:
   1.130 @@ -1045,8 +1043,9 @@ class XendDomainInfo:
   1.131                    self.domid,
   1.132                    self.info['ssidref'])
   1.133  
   1.134 -        self.domid = xc.domain_create(dom = 0, ssidref = self.info['ssidref'],
   1.135 -                                      handle = self.uuidbytes)
   1.136 +        self.domid = xc.domain_create(
   1.137 +            dom = 0, ssidref = self.info['ssidref'],
   1.138 +            handle = uuid.fromString(self.info['uuid']))
   1.139  
   1.140          if self.domid < 0:
   1.141              raise VmError('Creating domain failed: name=%s' %
   1.142 @@ -1253,23 +1252,6 @@ class XendDomainInfo:
   1.143  
   1.144      ## private:
   1.145  
   1.146 -    def restart_check(self):
   1.147 -        """Check if domain restart is OK.
   1.148 -        To prevent restart loops, raise an error if it is
   1.149 -        less than MINIMUM_RESTART_TIME seconds since the last restart.
   1.150 -        """
   1.151 -        tnow = time.time()
   1.152 -        if self.restart_time is not None:
   1.153 -            tdelta = tnow - self.restart_time
   1.154 -            if tdelta < self.MINIMUM_RESTART_TIME:
   1.155 -                self.restart_cancel()
   1.156 -                msg = 'VM %s restarting too fast' % self.info['name']
   1.157 -                log.error(msg)
   1.158 -                raise VmError(msg)
   1.159 -        self.restart_time = tnow
   1.160 -        self.restart_count += 1
   1.161 -
   1.162 -
   1.163      def restart(self, rename = False):
   1.164          """Restart the domain after it has exited.
   1.165  
   1.166 @@ -1277,8 +1259,6 @@ class XendDomainInfo:
   1.167          False if it is to be destroyed.
   1.168          """
   1.169  
   1.170 -        #            self.restart_check()
   1.171 -
   1.172          config = self.sxpr()
   1.173  
   1.174          if self.readVm('xend/restart_in_progress'):
   1.175 @@ -1290,11 +1270,27 @@ class XendDomainInfo:
   1.176  
   1.177          self.writeVm('xend/restart_in_progress', 'True')
   1.178  
   1.179 +        now = time.time()
   1.180 +        rst = self.readVm('xend/previous_restart_time')
   1.181 +        log.error(rst)
   1.182 +        if rst:
   1.183 +            rst = float(rst)
   1.184 +            timeout = now - rst
   1.185 +            if timeout < MINIMUM_RESTART_TIME:
   1.186 +                log.error(
   1.187 +                    'VM %s restarting too fast (%f seconds since the last '
   1.188 +                    'restart).  Refusing to restart to avoid loops.',
   1.189 +                    self.info['name'], timeout)
   1.190 +            self.destroy()
   1.191 +            return
   1.192 +
   1.193 +        self.writeVm('xend/previous_restart_time', str(now))
   1.194 +
   1.195          try:
   1.196              if rename:
   1.197                  self.preserveForRestart()
   1.198              else:
   1.199 -                self.destroy()
   1.200 +                self.destroyDomain()
   1.201                  
   1.202              try:
   1.203                  xd = get_component('xen.xend.XendDomain')
   1.204 @@ -1321,15 +1317,14 @@ class XendDomainInfo:
   1.205          """
   1.206          
   1.207          new_name = self.generateUniqueName()
   1.208 -        new_uuid = uuid.create()
   1.209 -        new_uuid_str = uuid.toString(new_uuid)
   1.210 +        new_uuid = uuid.toString(uuid.create())
   1.211          log.info("Renaming dead domain %s (%d, %s) to %s (%s).",
   1.212 -                 self.info['name'], self.domid, uuid.toString(self.uuidbytes),
   1.213 -                 new_name, new_uuid_str)
   1.214 +                 self.info['name'], self.domid, self.info['uuid'],
   1.215 +                 new_name, new_uuid)
   1.216          self.release_devices()
   1.217          self.info['name'] = new_name
   1.218 -        self.uuidbytes = new_uuid
   1.219 -        self.vmpath = VMROOT + new_uuid_str
   1.220 +        self.info['uuid'] = new_uuid
   1.221 +        self.vmpath = VMROOT + new_uuid
   1.222          self.storeVmDetails()
   1.223          self.preserve()
   1.224