[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] Fix the recently-introduced failure to preserve uuid across a guest reboot.



# HG changeset patch
# User emellor@xxxxxxxxxxxxxxxxxxxxxx
# Node ID 6a7253b1ce8ad357698219910ee6628be4a2efb9
# Parent  fb265175f47c53ca193e6e264570981e228dacd0
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@xxxxxxxxxxxxx>

diff -r fb265175f47c -r 6a7253b1ce8a tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py   Wed Oct 19 17:18:30 2005
+++ b/tools/python/xen/xend/XendDomainInfo.py   Thu Oct 20 11:34:50 2005
@@ -87,6 +87,10 @@
 
 ZOMBIE_PREFIX = 'Zombie-'
 
+"""Minimum time between domain restarts in seconds."""
+MINIMUM_RESTART_TIME = 20
+
+
 xc = xen.lowlevel.xc.new()
 xroot = XendRoot.instance()
 
@@ -102,6 +106,7 @@
 # file, so those are handled separately.
 ROUNDTRIPPING_CONFIG_ENTRIES = [
         ('name',         str),
+        ('uuid',         str),
         ('ssidref',      int),
         ('vcpus',        int),
         ('vcpu_avail',   int),
@@ -141,7 +146,7 @@
 
     log.debug("XendDomainInfo.create(%s)", config)
 
-    vm = XendDomainInfo(uuid.create(), parseConfig(config))
+    vm = XendDomainInfo(parseConfig(config))
     try:
         vm.construct()
         vm.initDomain()
@@ -166,10 +171,13 @@
 
     domid = xeninfo['dom']
     uuid1 = xeninfo['handle']
+    xeninfo['uuid'] = uuid.toString(uuid1)
     dompath = GetDomainPath(domid)
     if not dompath:
         raise XendError(
             'No domain path in store for existing domain %d' % domid)
+
+    log.info("Recreating domain %d, UUID %s.", domid, xeninfo['uuid'])
     try:
         vmpath = xstransact.Read(dompath, "vm")
         if not vmpath:
@@ -185,19 +193,15 @@
         if uuid1 != uuid2:
             raise XendError(
                 'Uuid in store does not match uuid for existing domain %d: '
-                '%s != %s' % (domid, uuid2_str, uuid.toString(uuid1)))
-
-        log.info("Recreating domain %d, UUID %s.", domid, uuid2_str)
-
-        vm = XendDomainInfo(uuid1, xeninfo, domid, dompath, True)
+                '%s != %s' % (domid, uuid2_str, xeninfo['uuid']))
+
+        vm = XendDomainInfo(xeninfo, domid, dompath, True)
 
     except Exception, exn:
-        log.warn(str(exn))
-
-        log.info("Recreating domain %d with UUID %s.", domid,
-                 uuid.toString(uuid1))
-
-        vm = XendDomainInfo(uuid1, xeninfo, domid, dompath, True)
+        if True:
+            log.warn(str(exn))
+
+        vm = XendDomainInfo(xeninfo, domid, dompath, True)
         vm.removeDom()
         vm.removeVm()
         vm.storeVmDetails()
@@ -215,8 +219,7 @@
 
     log.debug("XendDomainInfo.restore(%s)", config)
 
-    vm = XendDomainInfo(uuid.fromString(sxp.child_value(config, 'uuid')),
-                        parseConfig(config))
+    vm = XendDomainInfo(parseConfig(config))
     try:
         vm.construct()
         vm.storeVmDetails()
@@ -335,18 +338,14 @@
     return None
 
 class XendDomainInfo:
-    """Virtual machine object."""
-
-    """Minimum time between domain restarts in seconds.
-    """
-    MINIMUM_RESTART_TIME = 20
-
-
-    def __init__(self, uuidbytes, info, domid = None, dompath = None,
-                 augment = False):
-
-        self.uuidbytes = uuidbytes
+
+
+    def __init__(self, info, domid = None, dompath = None, augment = False):
+
         self.info = info
+
+        if not self.infoIsSet('uuid'):
+            self.info['uuid'] = uuid.toString(uuid.create())
 
         if domid is not None:
             self.domid = domid
@@ -355,7 +354,7 @@
         else:
             self.domid = None
 
-        self.vmpath  = VMROOT + uuid.toString(uuidbytes)
+        self.vmpath  = VMROOT + self.info['uuid']
         self.dompath = dompath
 
         if augment:
@@ -571,7 +570,7 @@
 
     def storeVmDetails(self):
         to_store = {
-            'uuid':               uuid.toString(self.uuidbytes),
+            'uuid':               self.info['uuid'],
 
             # XXX
             'memory/target':      str(self.info['memory_KiB'])
@@ -928,7 +927,6 @@
     def sxpr(self):
         sxpr = ['domain',
                 ['domid',   self.domid],
-                ['uuid',    uuid.toString(self.uuidbytes)],
                 ['memory',  self.info['memory_KiB'] / 1024]]
 
         for e in ROUNDTRIPPING_CONFIG_ENTRIES:
@@ -1045,8 +1043,9 @@
                   self.domid,
                   self.info['ssidref'])
 
-        self.domid = xc.domain_create(dom = 0, ssidref = self.info['ssidref'],
-                                      handle = self.uuidbytes)
+        self.domid = xc.domain_create(
+            dom = 0, ssidref = self.info['ssidref'],
+            handle = uuid.fromString(self.info['uuid']))
 
         if self.domid < 0:
             raise VmError('Creating domain failed: name=%s' %
@@ -1253,31 +1252,12 @@
 
     ## private:
 
-    def restart_check(self):
-        """Check if domain restart is OK.
-        To prevent restart loops, raise an error if it is
-        less than MINIMUM_RESTART_TIME seconds since the last restart.
-        """
-        tnow = time.time()
-        if self.restart_time is not None:
-            tdelta = tnow - self.restart_time
-            if tdelta < self.MINIMUM_RESTART_TIME:
-                self.restart_cancel()
-                msg = 'VM %s restarting too fast' % self.info['name']
-                log.error(msg)
-                raise VmError(msg)
-        self.restart_time = tnow
-        self.restart_count += 1
-
-
     def restart(self, rename = False):
         """Restart the domain after it has exited.
 
         @param rename True if the old domain is to be renamed and preserved,
         False if it is to be destroyed.
         """
-
-        #            self.restart_check()
 
         config = self.sxpr()
 
@@ -1290,11 +1270,27 @@
 
         self.writeVm('xend/restart_in_progress', 'True')
 
+        now = time.time()
+        rst = self.readVm('xend/previous_restart_time')
+        log.error(rst)
+        if rst:
+            rst = float(rst)
+            timeout = now - rst
+            if timeout < MINIMUM_RESTART_TIME:
+                log.error(
+                    'VM %s restarting too fast (%f seconds since the last '
+                    'restart).  Refusing to restart to avoid loops.',
+                    self.info['name'], timeout)
+            self.destroy()
+            return
+
+        self.writeVm('xend/previous_restart_time', str(now))
+
         try:
             if rename:
                 self.preserveForRestart()
             else:
-                self.destroy()
+                self.destroyDomain()
                 
             try:
                 xd = get_component('xen.xend.XendDomain')
@@ -1321,15 +1317,14 @@
         """
         
         new_name = self.generateUniqueName()
-        new_uuid = uuid.create()
-        new_uuid_str = uuid.toString(new_uuid)
+        new_uuid = uuid.toString(uuid.create())
         log.info("Renaming dead domain %s (%d, %s) to %s (%s).",
-                 self.info['name'], self.domid, uuid.toString(self.uuidbytes),
-                 new_name, new_uuid_str)
+                 self.info['name'], self.domid, self.info['uuid'],
+                 new_name, new_uuid)
         self.release_devices()
         self.info['name'] = new_name
-        self.uuidbytes = new_uuid
-        self.vmpath = VMROOT + new_uuid_str
+        self.info['uuid'] = new_uuid
+        self.vmpath = VMROOT + new_uuid
         self.storeVmDetails()
         self.preserve()
 

_______________________________________________
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®.