ia64/xen-unstable
changeset 7231:6f71824a45c1
Fix the handling of VCPUs, specifically wrt the broken VCPU hotplugging, bug
#280. The cpu/<id>/availability paths had moved into /vm, but that is not
easily accessible by the hotplugging driver, so I have created a /vm entry
called vcpu_avail, so that the setting migrates along with the domain, and
moved the cpu/<id> ones back to /local/domain.
Don't try and destroy the domain twice if it fails within construct. This
wasn't harming anything, but there's no need.
Signed-off-by: Ewan Mellor <ewan@xensource.com>
#280. The cpu/<id>/availability paths had moved into /vm, but that is not
easily accessible by the hotplugging driver, so I have created a /vm entry
called vcpu_avail, so that the setting migrates along with the domain, and
moved the cpu/<id> ones back to /local/domain.
Don't try and destroy the domain twice if it fails within construct. This
wasn't harming anything, but there's no need.
Signed-off-by: Ewan Mellor <ewan@xensource.com>
author | emellor@ewan |
---|---|
date | Wed Oct 05 18:06:42 2005 +0100 (2005-10-05) |
parents | 6e5463aec499 |
children | c3d9b7013b14 971e7c7411b3 |
files | tools/python/xen/xend/XendDomainInfo.py |
line diff
1.1 --- a/tools/python/xen/xend/XendDomainInfo.py Wed Oct 05 17:48:36 2005 +0100 1.2 +++ b/tools/python/xen/xend/XendDomainInfo.py Wed Oct 05 18:06:42 2005 +0100 1.3 @@ -111,6 +111,8 @@ xroot = XendRoot.instance() 1.4 ROUNDTRIPPING_CONFIG_ENTRIES = [ 1.5 ('name', str), 1.6 ('ssidref', int), 1.7 + ('vcpus', int), 1.8 + ('vcpu_avail', int), 1.9 ('cpu_weight', float), 1.10 ('bootloader', str), 1.11 ('on_poweroff', str), 1.12 @@ -119,6 +121,27 @@ ROUNDTRIPPING_CONFIG_ENTRIES = [ 1.13 ] 1.14 1.15 1.16 +# 1.17 +# There are a number of CPU-related fields: 1.18 +# 1.19 +# vcpus: the number of virtual CPUs this domain is configured to use. 1.20 +# vcpu_avail: a bitmap telling the guest domain whether it may use each of 1.21 +# its VCPUs. This is translated to 1.22 +# <dompath>/cpu/<id>/availability = {online,offline} for use 1.23 +# by the guest domain. 1.24 +# vcpu_to_cpu: the current mapping between virtual CPUs and the physical 1.25 +# CPU it is using. 1.26 +# cpumap: a list of bitmaps, one for each VCPU, giving the physical 1.27 +# CPUs that that VCPU may use. 1.28 +# cpu: a configuration setting requesting that VCPU 0 is pinned to 1.29 +# the specified physical CPU. 1.30 +# 1.31 +# vcpus and vcpu_avail settings persist with the VM (i.e. they are persistent 1.32 +# across save, restore, migrate, and restart). The other settings are only 1.33 +# specific to the domain, so are lost when the VM moves. 1.34 +# 1.35 + 1.36 + 1.37 def create(config): 1.38 """Create a VM from a configuration. 1.39 1.40 @@ -134,6 +157,7 @@ def create(config): 1.41 vm.refreshShutdown() 1.42 return vm 1.43 except: 1.44 + log.exception('Domain construction failed') 1.45 vm.destroy() 1.46 raise 1.47 1.48 @@ -200,7 +224,7 @@ def restore(config): 1.49 raise VmError('Invalid ssidref in config: %s' % exn) 1.50 1.51 domid = xc.domain_create(ssidref = ssidref) 1.52 - if domid <= 0: 1.53 + if domid < 0: 1.54 raise VmError('Creating domain failed for restore') 1.55 try: 1.56 vm = XendDomainInfo(uuid, parseConfig(config), domid) 1.57 @@ -240,12 +264,12 @@ def parseConfig(config): 1.58 for e in ROUNDTRIPPING_CONFIG_ENTRIES: 1.59 result[e[0]] = get_cfg(e[0], e[1]) 1.60 1.61 - result['memory'] = get_cfg('memory', int) 1.62 - result['mem_kb'] = get_cfg('mem_kb', int) 1.63 - result['maxmem'] = get_cfg('maxmem', int) 1.64 - result['maxmem_kb'] = get_cfg('maxmem_kb', int) 1.65 - result['cpu'] = get_cfg('cpu', int) 1.66 - result['image'] = get_cfg('image') 1.67 + result['memory'] = get_cfg('memory', int) 1.68 + result['mem_kb'] = get_cfg('mem_kb', int) 1.69 + result['maxmem'] = get_cfg('maxmem', int) 1.70 + result['maxmem_kb'] = get_cfg('maxmem_kb', int) 1.71 + result['cpu'] = get_cfg('cpu', int) 1.72 + result['image'] = get_cfg('image') 1.73 1.74 try: 1.75 if result['image']: 1.76 @@ -338,7 +362,7 @@ class XendDomainInfo: 1.77 self.uuid = uuid 1.78 self.info = info 1.79 1.80 - if domid: 1.81 + if domid is not None: 1.82 self.domid = domid 1.83 elif 'dom' in info: 1.84 self.domid = int(info['dom']) 1.85 @@ -382,6 +406,8 @@ class XendDomainInfo: 1.86 ("on_reboot", str), 1.87 ("on_crash", str), 1.88 ("image", str), 1.89 + ("vcpus", int), 1.90 + ("vcpu_avail", int), 1.91 ("start_time", float)) 1.92 1.93 from_store = self.gatherVm(*params) 1.94 @@ -393,13 +419,13 @@ class XendDomainInfo: 1.95 devconfig = self.getDeviceConfigurations(c) 1.96 if devconfig: 1.97 device.extend(map(lambda x: (c, x), devconfig)) 1.98 - 1.99 useIfNeeded('device', device) 1.100 1.101 1.102 def validateInfo(self): 1.103 """Validate and normalise the info block. This has either been parsed 1.104 - by parseConfig, or received from xc through recreate. 1.105 + by parseConfig, or received from xc through recreate and augmented by 1.106 + the current store contents. 1.107 """ 1.108 def defaultInfo(name, val): 1.109 if not self.infoIsSet(name): 1.110 @@ -413,6 +439,8 @@ class XendDomainInfo: 1.111 defaultInfo('on_crash', lambda: "restart") 1.112 defaultInfo('cpu', lambda: None) 1.113 defaultInfo('cpu_weight', lambda: 1.0) 1.114 + defaultInfo('vcpus', lambda: 1) 1.115 + defaultInfo('vcpu_avail', lambda: (1 << self.info['vcpus']) - 1) 1.116 defaultInfo('bootloader', lambda: None) 1.117 defaultInfo('backend', lambda: []) 1.118 defaultInfo('device', lambda: []) 1.119 @@ -499,12 +527,6 @@ class XendDomainInfo: 1.120 raise VmError('invalid restart event: %s = %s' % 1.121 (event, str(self.info[event]))) 1.122 1.123 - if 'cpumap' not in self.info: 1.124 - if [self.info['vcpus'] == 1]: 1.125 - self.info['cpumap'] = [1]; 1.126 - else: 1.127 - raise VmError('Cannot create CPU map') 1.128 - 1.129 except KeyError, exn: 1.130 log.exception(exn) 1.131 raise VmError('Unspecified domain detail: %s' % str(exn)) 1.132 @@ -552,7 +574,8 @@ class XendDomainInfo: 1.133 if self.infoIsSet('image'): 1.134 to_store['image'] = sxp.to_string(self.info['image']) 1.135 1.136 - for k in ['name', 'ssidref', 'on_poweroff', 'on_reboot', 'on_crash']: 1.137 + for k in ['name', 'ssidref', 'on_poweroff', 'on_reboot', 'on_crash', 1.138 + 'vcpus', 'vcpu_avail']: 1.139 if self.infoIsSet(k): 1.140 to_store[k] = str(self.info[k]) 1.141 1.142 @@ -573,6 +596,15 @@ class XendDomainInfo: 1.143 if v: 1.144 to_store[k] = str(v) 1.145 1.146 + def availability(n): 1.147 + if self.info['vcpu_avail'] & (1 << n): 1.148 + return 'online' 1.149 + else: 1.150 + return 'offline' 1.151 + 1.152 + for v in range(0, self.info['vcpus']): 1.153 + to_store["cpu/%d/availability" % v] = availability(v) 1.154 + 1.155 log.debug("Storing domain details: %s" % str(to_store)) 1.156 1.157 self.writeDom(to_store) 1.158 @@ -916,7 +948,8 @@ class XendDomainInfo: 1.159 if self.infoIsSet('cpu_time'): 1.160 sxpr.append(['cpu_time', self.info['cpu_time']/1e9]) 1.161 sxpr.append(['vcpus', self.info['vcpus']]) 1.162 - sxpr.append(['cpumap', self.info['cpumap']]) 1.163 + if self.infoIsSet('cpumap'): 1.164 + sxpr.append(['cpumap', self.info['cpumap']]) 1.165 if self.infoIsSet('vcpu_to_cpu'): 1.166 sxpr.append(['cpu', self.info['vcpu_to_cpu'][0]]) 1.167 sxpr.append(['vcpu_to_cpu', self.prettyVCpuMap()]) 1.168 @@ -986,27 +1019,21 @@ class XendDomainInfo: 1.169 1.170 self.domid = xc.domain_create(dom = 0, ssidref = self.info['ssidref']) 1.171 1.172 - if self.domid <= 0: 1.173 + if self.domid < 0: 1.174 raise VmError('Creating domain failed: name=%s' % 1.175 self.info['name']) 1.176 1.177 - try: 1.178 - self.dompath = DOMROOT + str(self.domid) 1.179 + self.dompath = DOMROOT + str(self.domid) 1.180 1.181 - # Ensure that the domain entry is clean. This prevents a stale 1.182 - # shutdown_start_time from killing the domain, for example. 1.183 - self.removeDom() 1.184 + # Ensure that the domain entry is clean. This prevents a stale 1.185 + # shutdown_start_time from killing the domain, for example. 1.186 + self.removeDom() 1.187 1.188 - self.initDomain() 1.189 - self.construct_image() 1.190 - self.configure() 1.191 - self.storeVmDetails() 1.192 - self.storeDomDetails() 1.193 - except: 1.194 - log.exception('Domain construction failed') 1.195 - self.destroy() 1.196 - raise VmError('Creating domain failed: name=%s' % 1.197 - self.info['name']) 1.198 + self.initDomain() 1.199 + self.construct_image() 1.200 + self.configure() 1.201 + self.storeVmDetails() 1.202 + self.storeDomDetails() 1.203 1.204 1.205 def initDomain(self): 1.206 @@ -1041,13 +1068,6 @@ class XendDomainInfo: 1.207 self.domid, self.info['name'], self.info['memory_KiB']) 1.208 1.209 1.210 - def configure_vcpus(self): 1.211 - d = {} 1.212 - for v in range(0, self.info['vcpus']): 1.213 - d["cpu/%d/availability" % v] = "online" 1.214 - self.writeVm(d) 1.215 - 1.216 - 1.217 def construct_image(self): 1.218 """Construct the boot image for the domain. 1.219 """ 1.220 @@ -1055,7 +1075,6 @@ class XendDomainInfo: 1.221 self.image.createImage() 1.222 IntroduceDomain(self.domid, self.store_mfn, 1.223 self.store_channel.port1, self.dompath) 1.224 - self.configure_vcpus() 1.225 1.226 1.227 ## public: 1.228 @@ -1376,10 +1395,13 @@ class XendDomainInfo: 1.229 log.error("Invalid VCPU %d" % vcpu) 1.230 return 1.231 if int(state) == 0: 1.232 + self.info['vcpu_avail'] &= ~(1 << vcpu) 1.233 availability = "offline" 1.234 else: 1.235 + self.info['vcpu_avail'] &= (1 << vcpu) 1.236 availability = "online" 1.237 - self.storeVm("cpu/%d/availability" % vcpu, availability) 1.238 + self.storeVm('vcpu_avail', self.info['vcpu_avail']) 1.239 + self.storeDom("cpu/%d/availability" % vcpu, availability) 1.240 1.241 def send_sysrq(self, key=0): 1.242 self.storeDom("control/sysrq", '%c' % key) 1.243 @@ -1397,7 +1419,6 @@ class XendDomainInfo: 1.244 pass 1.245 else: 1.246 raise 1.247 - self.configure_vcpus() 1.248 1.249 1.250 def dom0_enforce_vcpus(self):