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>
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