ia64/xen-unstable
changeset 16236:e8905caa47b5
pv-qemu 9/10: XenD device model re-factoring
This patches adapts XenD so that it is capable of starting a qemu-dm
device model for both paravirt and fullyvirt guests. A paravirt guest
will only be given a device model if it has a VFB configured, or the
user explicitly include the device_model option in the config
config. This avoids unnecessary overhead for those wanting a minimal
paravirt guest.
The bulk of this patch involves moving code from the HVMImageHandler
into the base ImageHandler class. The HVMImageHandler and
LinuxImageHandler subclasses now merely containing a couple of
overrides to set some specific command line flags. The most important
is -M xenpv, vs -M xenfv.
The XenConfig class has a minor refactoring to add a has_rfb() method
to avoid duplicating code in a couple of places. Instead of hardcoding
DEFAULT_DM it now uses the xen.util.auxbin APIs to locate it - this
works on platforms where qemu-dm is in /usr/lib64 instead of
/usr/lib. As before paravirt only gets a default qemu-dm if using a
VFB.
The vfbif.py class is trimmed out since it no longer needs to spawn a
daemon. A few other misc fixes deal with qemu-dm interactions when
saving/restoring, and in particular recovering from save failures (or
checkpointing).
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
This patches adapts XenD so that it is capable of starting a qemu-dm
device model for both paravirt and fullyvirt guests. A paravirt guest
will only be given a device model if it has a VFB configured, or the
user explicitly include the device_model option in the config
config. This avoids unnecessary overhead for those wanting a minimal
paravirt guest.
The bulk of this patch involves moving code from the HVMImageHandler
into the base ImageHandler class. The HVMImageHandler and
LinuxImageHandler subclasses now merely containing a couple of
overrides to set some specific command line flags. The most important
is -M xenpv, vs -M xenfv.
The XenConfig class has a minor refactoring to add a has_rfb() method
to avoid duplicating code in a couple of places. Instead of hardcoding
DEFAULT_DM it now uses the xen.util.auxbin APIs to locate it - this
works on platforms where qemu-dm is in /usr/lib64 instead of
/usr/lib. As before paravirt only gets a default qemu-dm if using a
VFB.
The vfbif.py class is trimmed out since it no longer needs to spawn a
daemon. A few other misc fixes deal with qemu-dm interactions when
saving/restoring, and in particular recovering from save failures (or
checkpointing).
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
author | Keir Fraser <keir@xensource.com> |
---|---|
date | Thu Oct 25 14:45:07 2007 +0100 (2007-10-25) |
parents | b34ba3bcab0b |
children | a4df9c0c33fd |
files | tools/python/xen/xend/XendCheckpoint.py tools/python/xen/xend/XendConfig.py tools/python/xen/xend/XendDomainInfo.py tools/python/xen/xend/image.py tools/python/xen/xend/server/vfbif.py |
line diff
1.1 --- a/tools/python/xen/xend/XendCheckpoint.py Thu Oct 25 14:42:40 2007 +0100 1.2 +++ b/tools/python/xen/xend/XendCheckpoint.py Thu Oct 25 14:45:07 2007 +0100 1.3 @@ -6,6 +6,7 @@ 1.4 # this archive for more details. 1.5 1.6 import os 1.7 +import os.path 1.8 import re 1.9 import string 1.10 import threading 1.11 @@ -108,7 +109,7 @@ def save(fd, dominfo, network, live, dst 1.12 forkHelper(cmd, fd, saveInputHandler, False) 1.13 1.14 # put qemu device model state 1.15 - if hvm: 1.16 + if os.path.exists("/var/lib/xen/qemu-save.%d" % dominfo.getDomid()): 1.17 write_exact(fd, QEMU_SIGNATURE, "could not write qemu signature") 1.18 qemu_fd = os.open("/var/lib/xen/qemu-save.%d" % dominfo.getDomid(), 1.19 os.O_RDONLY) 1.20 @@ -245,6 +246,8 @@ def restore(xd, fd, dominfo = None, paus 1.21 raise XendError('Could not read console MFN') 1.22 1.23 # get qemu state and create a tmp file for dm restore 1.24 + # Even PV guests may have QEMU stat, but its not currently 1.25 + # used so only bother with HVM currently. 1.26 if is_hvm: 1.27 qemu_signature = read_exact(fd, len(QEMU_SIGNATURE), 1.28 "invalid device model signature read")
2.1 --- a/tools/python/xen/xend/XendConfig.py Thu Oct 25 14:42:40 2007 +0100 2.2 +++ b/tools/python/xen/xend/XendConfig.py Thu Oct 25 14:45:07 2007 +0100 2.3 @@ -32,6 +32,7 @@ from xen.xend.server.BlktapController im 2.4 from xen.xend.server.netif import randomMAC 2.5 from xen.util.blkif import blkdev_name_to_number 2.6 from xen.util import xsconstants 2.7 +import xen.util.auxbin 2.8 2.9 log = logging.getLogger("xend.XendConfig") 2.10 log.setLevel(logging.WARN) 2.11 @@ -234,8 +235,6 @@ LEGACY_XENSTORE_VM_PARAMS = [ 2.12 'on_xend_stop', 2.13 ] 2.14 2.15 -DEFAULT_DM = '/usr/lib/xen/bin/qemu-dm' 2.16 - 2.17 ## 2.18 ## Config Choices 2.19 ## 2.20 @@ -393,13 +392,14 @@ class XendConfig(dict): 2.21 self['name_label'] = 'Domain-' + self['uuid'] 2.22 2.23 def _platform_sanity_check(self): 2.24 - if self.is_hvm(): 2.25 - if 'keymap' not in self['platform'] and XendOptions.instance().get_keymap(): 2.26 - self['platform']['keymap'] = XendOptions.instance().get_keymap() 2.27 + if 'keymap' not in self['platform'] and XendOptions.instance().get_keymap(): 2.28 + self['platform']['keymap'] = XendOptions.instance().get_keymap() 2.29 2.30 + if self.is_hvm() or self.has_rfb(): 2.31 if 'device_model' not in self['platform']: 2.32 - self['platform']['device_model'] = DEFAULT_DM 2.33 + self['platform']['device_model'] = xen.util.auxbin.pathTo("qemu-dm") 2.34 2.35 + if self.is_hvm(): 2.36 # Compatibility hack, can go away soon. 2.37 if 'soundhw' not in self['platform'] and \ 2.38 self['platform'].get('enable_audio'): 2.39 @@ -744,16 +744,7 @@ class XendConfig(dict): 2.40 # coalesce hvm vnc frame buffer with vfb config 2.41 if self.is_hvm() and int(self['platform'].get('vnc', 0)) != 0: 2.42 # add vfb device if it isn't there already 2.43 - has_rfb = False 2.44 - for console_uuid in self['console_refs']: 2.45 - if self['devices'][console_uuid][1].get('protocol') == 'rfb': 2.46 - has_rfb = True 2.47 - break 2.48 - if self['devices'][console_uuid][0] == 'vfb': 2.49 - has_rfb = True 2.50 - break 2.51 - 2.52 - if not has_rfb: 2.53 + if not self.has_rfb(): 2.54 dev_config = ['vfb'] 2.55 dev_config.append(['type', 'vnc']) 2.56 # copy VNC related params from platform config to vfb dev conf 2.57 @@ -765,6 +756,14 @@ class XendConfig(dict): 2.58 self.device_add('vfb', cfg_sxp = dev_config) 2.59 2.60 2.61 + def has_rfb(self): 2.62 + for console_uuid in self['console_refs']: 2.63 + if self['devices'][console_uuid][1].get('protocol') == 'rfb': 2.64 + return True 2.65 + if self['devices'][console_uuid][0] == 'vfb': 2.66 + return True 2.67 + return False 2.68 + 2.69 def _sxp_to_xapi_unsupported(self, sxp_cfg): 2.70 """Read in an SXP configuration object and populate 2.71 values are that not related directly supported in
3.1 --- a/tools/python/xen/xend/XendDomainInfo.py Thu Oct 25 14:42:40 2007 +0100 3.2 +++ b/tools/python/xen/xend/XendDomainInfo.py Thu Oct 25 14:45:07 2007 +0100 3.3 @@ -1455,10 +1455,16 @@ class XendDomainInfo: 3.4 3.5 def _releaseDevices(self, suspend = False): 3.6 """Release all domain's devices. Nothrow guarantee.""" 3.7 - if suspend and self.image: 3.8 - self.image.destroy(suspend) 3.9 - return 3.10 - 3.11 + if self.image: 3.12 + try: 3.13 + log.debug("Destroying device model") 3.14 + self.image.destroyDeviceModel() 3.15 + except Exception, e: 3.16 + log.exception("Device model destroy failed %s" % str(e)) 3.17 + else: 3.18 + log.debug("No device model") 3.19 + 3.20 + log.debug("Releasing devices") 3.21 t = xstransact("%s/device" % self.dompath) 3.22 for devclass in XendDevices.valid_devices(): 3.23 for dev in t.list(devclass): 3.24 @@ -1709,11 +1715,6 @@ class XendDomainInfo: 3.25 bootloader_tidy(self) 3.26 3.27 if self.image: 3.28 - try: 3.29 - self.image.destroy() 3.30 - except: 3.31 - log.exception( 3.32 - "XendDomainInfo.cleanup: image.destroy() failed.") 3.33 self.image = None 3.34 3.35 try: 3.36 @@ -1881,8 +1882,8 @@ class XendDomainInfo: 3.37 ResumeDomain(self.domid) 3.38 except: 3.39 log.exception("XendDomainInfo.resume: xc.domain_resume failed on domain %s." % (str(self.domid))) 3.40 - if self.is_hvm(): 3.41 - self.image.resumeDeviceModel() 3.42 + self.image.resumeDeviceModel() 3.43 + log.debug("XendDomainInfo.resumeDomain: completed") 3.44 3.45 3.46 #
4.1 --- a/tools/python/xen/xend/image.py Thu Oct 25 14:42:40 2007 +0100 4.2 +++ b/tools/python/xen/xend/image.py Thu Oct 25 14:45:07 2007 +0100 4.3 @@ -56,10 +56,9 @@ class ImageHandler: 4.4 defining in a subclass. 4.5 4.6 The method createDeviceModel() is called to create the domain device 4.7 - model if it needs one. The default is to do nothing. 4.8 + model. 4.9 4.10 - The method destroy() is called when the domain is destroyed. 4.11 - The default is to do nothing. 4.12 + The method destroyDeviceModel() is called to reap the device model 4.13 """ 4.14 4.15 ostype = None 4.16 @@ -91,6 +90,15 @@ class ImageHandler: 4.17 ("image/cmdline", self.cmdline), 4.18 ("image/ramdisk", self.ramdisk)) 4.19 4.20 + self.dmargs = self.parseDeviceModelArgs(vmConfig) 4.21 + self.device_model = vmConfig['platform'].get('device_model') 4.22 + 4.23 + self.display = vmConfig['platform'].get('display') 4.24 + self.xauthority = vmConfig['platform'].get('xauthority') 4.25 + self.vncconsole = vmConfig['platform'].get('vncconsole') 4.26 + self.pid = None 4.27 + 4.28 + 4.29 4.30 def cleanupBootloading(self): 4.31 if self.bootloader: 4.32 @@ -173,216 +181,13 @@ class ImageHandler: 4.33 """Build the domain. Define in subclass.""" 4.34 raise NotImplementedError() 4.35 4.36 - def createDeviceModel(self, restore = False): 4.37 - """Create device model for the domain (define in subclass if needed).""" 4.38 - pass 4.39 - 4.40 - def saveDeviceModel(self): 4.41 - """Save device model for the domain (define in subclass if needed).""" 4.42 - pass 4.43 - 4.44 - def resumeDeviceModel(self): 4.45 - """Unpause device model for the domain (define in subclass if needed).""" 4.46 - pass 4.47 - 4.48 - def destroy(self): 4.49 - """Extra cleanup on domain destroy (define in subclass if needed).""" 4.50 - pass 4.51 - 4.52 - 4.53 - def recreate(self): 4.54 - pass 4.55 - 4.56 - 4.57 -class LinuxImageHandler(ImageHandler): 4.58 - 4.59 - ostype = "linux" 4.60 - flags = 0 4.61 - vhpt = 0 4.62 - 4.63 - def buildDomain(self): 4.64 - store_evtchn = self.vm.getStorePort() 4.65 - console_evtchn = self.vm.getConsolePort() 4.66 - 4.67 - mem_mb = self.getRequiredInitialReservation() / 1024 4.68 - 4.69 - log.debug("domid = %d", self.vm.getDomid()) 4.70 - log.debug("memsize = %d", mem_mb) 4.71 - log.debug("image = %s", self.kernel) 4.72 - log.debug("store_evtchn = %d", store_evtchn) 4.73 - log.debug("console_evtchn = %d", console_evtchn) 4.74 - log.debug("cmdline = %s", self.cmdline) 4.75 - log.debug("ramdisk = %s", self.ramdisk) 4.76 - log.debug("vcpus = %d", self.vm.getVCpuCount()) 4.77 - log.debug("features = %s", self.vm.getFeatures()) 4.78 - if arch.type == "ia64": 4.79 - log.debug("vhpt = %d", self.flags) 4.80 - 4.81 - return xc.linux_build(domid = self.vm.getDomid(), 4.82 - memsize = mem_mb, 4.83 - image = self.kernel, 4.84 - store_evtchn = store_evtchn, 4.85 - console_evtchn = console_evtchn, 4.86 - cmdline = self.cmdline, 4.87 - ramdisk = self.ramdisk, 4.88 - features = self.vm.getFeatures(), 4.89 - flags = self.flags, 4.90 - vhpt = self.vhpt) 4.91 - 4.92 -class PPC_LinuxImageHandler(LinuxImageHandler): 4.93 - 4.94 - ostype = "linux" 4.95 - 4.96 - def getRequiredShadowMemory(self, shadow_mem_kb, maxmem_kb): 4.97 - """@param shadow_mem_kb The configured shadow memory, in KiB. 4.98 - @param maxmem_kb The configured maxmem, in KiB. 4.99 - @return The corresponding required amount of shadow memory, also in 4.100 - KiB. 4.101 - PowerPC currently uses "shadow memory" to refer to the hash table.""" 4.102 - return max(maxmem_kb / 64, shadow_mem_kb) 4.103 - 4.104 - 4.105 - 4.106 -class HVMImageHandler(ImageHandler): 4.107 - 4.108 - ostype = "hvm" 4.109 - 4.110 - def __init__(self, vm, vmConfig): 4.111 - ImageHandler.__init__(self, vm, vmConfig) 4.112 - self.shutdownWatch = None 4.113 - self.rebootFeatureWatch = None 4.114 - 4.115 - def configure(self, vmConfig): 4.116 - ImageHandler.configure(self, vmConfig) 4.117 - 4.118 - if not self.kernel: 4.119 - self.kernel = '/usr/lib/xen/boot/hvmloader' 4.120 - 4.121 - info = xc.xeninfo() 4.122 - if 'hvm' not in info['xen_caps']: 4.123 - raise HVMRequired() 4.124 - 4.125 - self.dmargs = self.parseDeviceModelArgs(vmConfig) 4.126 - self.device_model = vmConfig['platform'].get('device_model') 4.127 - if not self.device_model: 4.128 - raise VmError("hvm: missing device model") 4.129 - 4.130 - self.display = vmConfig['platform'].get('display') 4.131 - self.xauthority = vmConfig['platform'].get('xauthority') 4.132 - self.vncconsole = vmConfig['platform'].get('vncconsole') 4.133 - 4.134 - rtc_timeoffset = vmConfig['platform'].get('rtc_timeoffset') 4.135 - 4.136 - self.vm.storeVm(("image/dmargs", " ".join(self.dmargs)), 4.137 - ("image/device-model", self.device_model), 4.138 - ("image/display", self.display)) 4.139 - self.vm.storeVm(("rtc/timeoffset", rtc_timeoffset)) 4.140 - 4.141 - self.pid = None 4.142 - 4.143 - self.apic = int(vmConfig['platform'].get('apic', 0)) 4.144 - self.acpi = int(vmConfig['platform'].get('acpi', 0)) 4.145 - 4.146 - 4.147 - def buildDomain(self): 4.148 - store_evtchn = self.vm.getStorePort() 4.149 - 4.150 - mem_mb = self.getRequiredInitialReservation() / 1024 4.151 - 4.152 - log.debug("domid = %d", self.vm.getDomid()) 4.153 - log.debug("image = %s", self.kernel) 4.154 - log.debug("store_evtchn = %d", store_evtchn) 4.155 - log.debug("memsize = %d", mem_mb) 4.156 - log.debug("vcpus = %d", self.vm.getVCpuCount()) 4.157 - log.debug("acpi = %d", self.acpi) 4.158 - log.debug("apic = %d", self.apic) 4.159 - 4.160 - rc = xc.hvm_build(domid = self.vm.getDomid(), 4.161 - image = self.kernel, 4.162 - memsize = mem_mb, 4.163 - vcpus = self.vm.getVCpuCount(), 4.164 - acpi = self.acpi, 4.165 - apic = self.apic) 4.166 - 4.167 - rc['notes'] = { 'SUSPEND_CANCEL': 1 } 4.168 - 4.169 - rc['store_mfn'] = xc.hvm_get_param(self.vm.getDomid(), 4.170 - HVM_PARAM_STORE_PFN) 4.171 - xc.hvm_set_param(self.vm.getDomid(), HVM_PARAM_STORE_EVTCHN, 4.172 - store_evtchn) 4.173 - 4.174 - return rc 4.175 - 4.176 # Return a list of cmd line args to the device models based on the 4.177 # xm config file 4.178 def parseDeviceModelArgs(self, vmConfig): 4.179 - dmargs = [ 'boot', 'fda', 'fdb', 'soundhw', 4.180 - 'localtime', 'serial', 'stdvga', 'isa', 4.181 - 'acpi', 'usb', 'usbdevice', 'keymap', 'pci' ] 4.182 - 4.183 - ret = ['-vcpus', str(self.vm.getVCpuCount())] 4.184 - 4.185 - for a in dmargs: 4.186 - v = vmConfig['platform'].get(a) 4.187 - 4.188 - # python doesn't allow '-' in variable names 4.189 - if a == 'stdvga': a = 'std-vga' 4.190 - if a == 'keymap': a = 'k' 4.191 - 4.192 - # Handle booleans gracefully 4.193 - if a in ['localtime', 'std-vga', 'isa', 'usb', 'acpi']: 4.194 - try: 4.195 - if v != None: v = int(v) 4.196 - if v: ret.append("-%s" % a) 4.197 - except (ValueError, TypeError): 4.198 - pass # if we can't convert it to a sane type, ignore it 4.199 - else: 4.200 - if v: 4.201 - ret.append("-%s" % a) 4.202 - ret.append("%s" % v) 4.203 - 4.204 - if a in ['fda', 'fdb']: 4.205 - if v: 4.206 - if not os.path.isabs(v): 4.207 - raise VmError("Floppy file %s does not exist." % v) 4.208 - log.debug("args: %s, val: %s" % (a,v)) 4.209 + ret = ["-domain-name", str(self.vm.info['name_label'])] 4.210 4.211 - # Handle disk/network related options 4.212 - mac = None 4.213 - ret = ret + ["-domain-name", str(self.vm.info['name_label'])] 4.214 - nics = 0 4.215 - 4.216 - for devuuid in vmConfig['vbd_refs']: 4.217 - devinfo = vmConfig['devices'][devuuid][1] 4.218 - uname = devinfo.get('uname') 4.219 - if uname is not None and 'file:' in uname: 4.220 - (_, vbdparam) = string.split(uname, ':', 1) 4.221 - if not os.path.isfile(vbdparam): 4.222 - raise VmError('Disk image does not exist: %s' % 4.223 - vbdparam) 4.224 - 4.225 - for devuuid in vmConfig['vif_refs']: 4.226 - devinfo = vmConfig['devices'][devuuid][1] 4.227 - dtype = devinfo.get('type', 'ioemu') 4.228 - if dtype != 'ioemu': 4.229 - continue 4.230 - nics += 1 4.231 - mac = devinfo.get('mac') 4.232 - if mac is None: 4.233 - raise VmError("MAC address not specified or generated.") 4.234 - bridge = devinfo.get('bridge', 'xenbr0') 4.235 - model = devinfo.get('model', 'rtl8139') 4.236 - ret.append("-net") 4.237 - ret.append("nic,vlan=%d,macaddr=%s,model=%s" % 4.238 - (nics, mac, model)) 4.239 - ret.append("-net") 4.240 - ret.append("tap,vlan=%d,bridge=%s" % (nics, bridge)) 4.241 - 4.242 - 4.243 - # 4.244 # Find RFB console device, and if it exists, make QEMU enable 4.245 # the VNC console. 4.246 - # 4.247 if int(vmConfig['platform'].get('nographic', 0)) != 0: 4.248 # skip vnc init if nographic is set 4.249 ret.append('-nographic') 4.250 @@ -398,6 +203,11 @@ class HVMImageHandler(ImageHandler): 4.251 has_vnc = True 4.252 break 4.253 4.254 + keymap = vmConfig['platform'].get("keymap") 4.255 + if keymap: 4.256 + ret.append("-k") 4.257 + ret.append(keymap) 4.258 + 4.259 if has_vnc: 4.260 if not vnc_config: 4.261 for key in ('vncunused', 'vnclisten', 'vncdisplay', 4.262 @@ -435,20 +245,20 @@ class HVMImageHandler(ImageHandler): 4.263 ret = ret + ['-monitor', 'vc'] 4.264 return ret 4.265 4.266 + def getDeviceModelArgs(self, restore = False): 4.267 + args = [self.device_model] 4.268 + args = args + ([ "-d", "%d" % self.vm.getDomid() ]) 4.269 + args = args + self.dmargs 4.270 + return args 4.271 + 4.272 def createDeviceModel(self, restore = False): 4.273 + if self.device_model is None: 4.274 + return 4.275 if self.pid: 4.276 return 4.277 # Execute device model. 4.278 #todo: Error handling 4.279 - args = [self.device_model] 4.280 - args = args + ([ "-d", "%d" % self.vm.getDomid() ]) 4.281 - if arch.type == "ia64": 4.282 - args = args + ([ "-m", "%s" % 4.283 - (self.getRequiredInitialReservation() / 1024) ]) 4.284 - args = args + self.dmargs 4.285 - if restore: 4.286 - args = args + ([ "-loadvm", "/var/lib/xen/qemu-save.%d" % 4.287 - self.vm.getDomid() ]) 4.288 + args = self.getDeviceModelArgs(restore) 4.289 env = dict(os.environ) 4.290 if self.display: 4.291 env['DISPLAY'] = self.display 4.292 @@ -463,6 +273,8 @@ class HVMImageHandler(ImageHandler): 4.293 log.info("device model pid: %d", self.pid) 4.294 4.295 def saveDeviceModel(self): 4.296 + if self.device_model is None: 4.297 + return 4.298 # Signal the device model to pause itself and save its state 4.299 xstransact.Store("/local/domain/0/device-model/%i" 4.300 % self.vm.getDomid(), ('command', 'save')) 4.301 @@ -479,15 +291,21 @@ class HVMImageHandler(ImageHandler): 4.302 raise VmError('Timed out waiting for device model to save') 4.303 4.304 def resumeDeviceModel(self): 4.305 + if self.device_model is None: 4.306 + return 4.307 # Signal the device model to resume activity after pausing to save. 4.308 xstransact.Store("/local/domain/0/device-model/%i" 4.309 % self.vm.getDomid(), ('command', 'continue')) 4.310 4.311 def recreate(self): 4.312 + if self.device_model is None: 4.313 + return 4.314 self.pid = self.vm.gatherDom(('image/device-model-pid', int)) 4.315 4.316 - def destroy(self, suspend = False): 4.317 - if self.pid and not suspend: 4.318 + def destroyDeviceModel(self): 4.319 + if self.device_model is None: 4.320 + return 4.321 + if self.pid: 4.322 try: 4.323 os.kill(self.pid, signal.SIGKILL) 4.324 except OSError, exn: 4.325 @@ -504,6 +322,201 @@ class HVMImageHandler(ImageHandler): 4.326 % self.vm.getDomid()) 4.327 4.328 4.329 +class LinuxImageHandler(ImageHandler): 4.330 + 4.331 + ostype = "linux" 4.332 + flags = 0 4.333 + vhpt = 0 4.334 + 4.335 + def buildDomain(self): 4.336 + store_evtchn = self.vm.getStorePort() 4.337 + console_evtchn = self.vm.getConsolePort() 4.338 + 4.339 + mem_mb = self.getRequiredInitialReservation() / 1024 4.340 + 4.341 + log.debug("domid = %d", self.vm.getDomid()) 4.342 + log.debug("memsize = %d", mem_mb) 4.343 + log.debug("image = %s", self.kernel) 4.344 + log.debug("store_evtchn = %d", store_evtchn) 4.345 + log.debug("console_evtchn = %d", console_evtchn) 4.346 + log.debug("cmdline = %s", self.cmdline) 4.347 + log.debug("ramdisk = %s", self.ramdisk) 4.348 + log.debug("vcpus = %d", self.vm.getVCpuCount()) 4.349 + log.debug("features = %s", self.vm.getFeatures()) 4.350 + if arch.type == "ia64": 4.351 + log.debug("vhpt = %d", self.flags) 4.352 + 4.353 + return xc.linux_build(domid = self.vm.getDomid(), 4.354 + memsize = mem_mb, 4.355 + image = self.kernel, 4.356 + store_evtchn = store_evtchn, 4.357 + console_evtchn = console_evtchn, 4.358 + cmdline = self.cmdline, 4.359 + ramdisk = self.ramdisk, 4.360 + features = self.vm.getFeatures(), 4.361 + flags = self.flags, 4.362 + vhpt = self.vhpt) 4.363 + 4.364 + def parseDeviceModelArgs(self, vmConfig): 4.365 + ret = ImageHandler.parseDeviceModelArgs(self, vmConfig) 4.366 + # Equivalent to old xenconsoled behaviour. Should make 4.367 + # it configurable in future 4.368 + ret = ret + ["-serial", "pty"] 4.369 + return ret 4.370 + 4.371 + def getDeviceModelArgs(self, restore = False): 4.372 + args = ImageHandler.getDeviceModelArgs(self, restore) 4.373 + args = args + ([ "-M", "xenpv"]) 4.374 + return args 4.375 + 4.376 + 4.377 +class PPC_LinuxImageHandler(LinuxImageHandler): 4.378 + 4.379 + ostype = "linux" 4.380 + 4.381 + def getRequiredShadowMemory(self, shadow_mem_kb, maxmem_kb): 4.382 + """@param shadow_mem_kb The configured shadow memory, in KiB. 4.383 + @param maxmem_kb The configured maxmem, in KiB. 4.384 + @return The corresponding required amount of shadow memory, also in 4.385 + KiB. 4.386 + PowerPC currently uses "shadow memory" to refer to the hash table.""" 4.387 + return max(maxmem_kb / 64, shadow_mem_kb) 4.388 + 4.389 + 4.390 + 4.391 +class HVMImageHandler(ImageHandler): 4.392 + 4.393 + ostype = "hvm" 4.394 + 4.395 + def __init__(self, vm, vmConfig): 4.396 + ImageHandler.__init__(self, vm, vmConfig) 4.397 + self.shutdownWatch = None 4.398 + self.rebootFeatureWatch = None 4.399 + 4.400 + def configure(self, vmConfig): 4.401 + ImageHandler.configure(self, vmConfig) 4.402 + 4.403 + if not self.kernel: 4.404 + self.kernel = '/usr/lib/xen/boot/hvmloader' 4.405 + 4.406 + info = xc.xeninfo() 4.407 + if 'hvm' not in info['xen_caps']: 4.408 + raise HVMRequired() 4.409 + 4.410 + rtc_timeoffset = vmConfig['platform'].get('rtc_timeoffset') 4.411 + 4.412 + self.vm.storeVm(("image/dmargs", " ".join(self.dmargs)), 4.413 + ("image/device-model", self.device_model), 4.414 + ("image/display", self.display)) 4.415 + self.vm.storeVm(("rtc/timeoffset", rtc_timeoffset)) 4.416 + 4.417 + self.apic = int(vmConfig['platform'].get('apic', 0)) 4.418 + self.acpi = int(vmConfig['platform'].get('acpi', 0)) 4.419 + 4.420 + # Return a list of cmd line args to the device models based on the 4.421 + # xm config file 4.422 + def parseDeviceModelArgs(self, vmConfig): 4.423 + ret = ImageHandler.parseDeviceModelArgs(self, vmConfig) 4.424 + ret = ret + ['-vcpus', str(self.vm.getVCpuCount())] 4.425 + 4.426 + dmargs = [ 'boot', 'fda', 'fdb', 'soundhw', 4.427 + 'localtime', 'serial', 'stdvga', 'isa', 4.428 + 'acpi', 'usb', 'usbdevice', 'pci' ] 4.429 + 4.430 + for a in dmargs: 4.431 + v = vmConfig['platform'].get(a) 4.432 + 4.433 + # python doesn't allow '-' in variable names 4.434 + if a == 'stdvga': a = 'std-vga' 4.435 + if a == 'keymap': a = 'k' 4.436 + 4.437 + # Handle booleans gracefully 4.438 + if a in ['localtime', 'std-vga', 'isa', 'usb', 'acpi']: 4.439 + try: 4.440 + if v != None: v = int(v) 4.441 + if v: ret.append("-%s" % a) 4.442 + except (ValueError, TypeError): 4.443 + pass # if we can't convert it to a sane type, ignore it 4.444 + else: 4.445 + if v: 4.446 + ret.append("-%s" % a) 4.447 + ret.append("%s" % v) 4.448 + 4.449 + if a in ['fda', 'fdb']: 4.450 + if v: 4.451 + if not os.path.isabs(v): 4.452 + raise VmError("Floppy file %s does not exist." % v) 4.453 + log.debug("args: %s, val: %s" % (a,v)) 4.454 + 4.455 + # Handle disk/network related options 4.456 + mac = None 4.457 + nics = 0 4.458 + 4.459 + for devuuid in vmConfig['vbd_refs']: 4.460 + devinfo = vmConfig['devices'][devuuid][1] 4.461 + uname = devinfo.get('uname') 4.462 + if uname is not None and 'file:' in uname: 4.463 + (_, vbdparam) = string.split(uname, ':', 1) 4.464 + if not os.path.isfile(vbdparam): 4.465 + raise VmError('Disk image does not exist: %s' % 4.466 + vbdparam) 4.467 + 4.468 + for devuuid in vmConfig['vif_refs']: 4.469 + devinfo = vmConfig['devices'][devuuid][1] 4.470 + dtype = devinfo.get('type', 'ioemu') 4.471 + if dtype != 'ioemu': 4.472 + continue 4.473 + nics += 1 4.474 + mac = devinfo.get('mac') 4.475 + if mac is None: 4.476 + raise VmError("MAC address not specified or generated.") 4.477 + bridge = devinfo.get('bridge', 'xenbr0') 4.478 + model = devinfo.get('model', 'rtl8139') 4.479 + ret.append("-net") 4.480 + ret.append("nic,vlan=%d,macaddr=%s,model=%s" % 4.481 + (nics, mac, model)) 4.482 + ret.append("-net") 4.483 + ret.append("tap,vlan=%d,bridge=%s" % (nics, bridge)) 4.484 + 4.485 + return ret 4.486 + 4.487 + def getDeviceModelArgs(self, restore = False): 4.488 + args = ImageHandler.getDeviceModelArgs(self, restore) 4.489 + args = args + ([ "-M", "xenfv"]) 4.490 + if restore: 4.491 + args = args + ([ "-loadvm", "/var/lib/xen/qemu-save.%d" % 4.492 + self.vm.getDomid() ]) 4.493 + return args 4.494 + 4.495 + def buildDomain(self): 4.496 + store_evtchn = self.vm.getStorePort() 4.497 + 4.498 + mem_mb = self.getRequiredInitialReservation() / 1024 4.499 + 4.500 + log.debug("domid = %d", self.vm.getDomid()) 4.501 + log.debug("image = %s", self.kernel) 4.502 + log.debug("store_evtchn = %d", store_evtchn) 4.503 + log.debug("memsize = %d", mem_mb) 4.504 + log.debug("vcpus = %d", self.vm.getVCpuCount()) 4.505 + log.debug("acpi = %d", self.acpi) 4.506 + log.debug("apic = %d", self.apic) 4.507 + 4.508 + rc = xc.hvm_build(domid = self.vm.getDomid(), 4.509 + image = self.kernel, 4.510 + memsize = mem_mb, 4.511 + vcpus = self.vm.getVCpuCount(), 4.512 + acpi = self.acpi, 4.513 + apic = self.apic) 4.514 + rc['notes'] = { 'SUSPEND_CANCEL': 1 } 4.515 + 4.516 + rc['store_mfn'] = xc.hvm_get_param(self.vm.getDomid(), 4.517 + HVM_PARAM_STORE_PFN) 4.518 + xc.hvm_set_param(self.vm.getDomid(), HVM_PARAM_STORE_EVTCHN, 4.519 + store_evtchn) 4.520 + 4.521 + return rc 4.522 + 4.523 + 4.524 class IA64_HVM_ImageHandler(HVMImageHandler): 4.525 4.526 def configure(self, vmConfig): 4.527 @@ -529,6 +542,13 @@ class IA64_HVM_ImageHandler(HVMImageHand 4.528 # Explicit shadow memory is not a concept 4.529 return 0 4.530 4.531 + def getDeviceModelArgs(self, restore = False): 4.532 + args = HVMImageHandler.getDeviceModelArgs(self, restore) 4.533 + args = args + ([ "-m", "%s" % 4.534 + (self.getRequiredInitialReservation() / 1024) ]) 4.535 + return args 4.536 + 4.537 + 4.538 class IA64_Linux_ImageHandler(LinuxImageHandler): 4.539 4.540 def configure(self, vmConfig):
5.1 --- a/tools/python/xen/xend/server/vfbif.py Thu Oct 25 14:42:40 2007 +0100 5.2 +++ b/tools/python/xen/xend/server/vfbif.py Thu Oct 25 14:45:07 2007 +0100 5.3 @@ -5,14 +5,6 @@ from xen.xend.XendError import VmError 5.4 import xen.xend 5.5 import os 5.6 5.7 -def spawn_detached(path, args, env): 5.8 - p = os.fork() 5.9 - if p == 0: 5.10 - os.spawnve(os.P_NOWAIT, path, args, env) 5.11 - os._exit(0) 5.12 - else: 5.13 - os.waitpid(p, 0) 5.14 - 5.15 CONFIG_ENTRIES = ['type', 'vncdisplay', 'vnclisten', 'vncpasswd', 'vncunused', 5.16 'display', 'xauthority', 'keymap', 5.17 'uuid', 'location', 'protocol'] 5.18 @@ -43,65 +35,9 @@ class VfbifController(DevController): 5.19 for i in range(len(CONFIG_ENTRIES)) 5.20 if devinfo[i] is not None]) 5.21 5.22 - 5.23 - def createDevice(self, config): 5.24 - DevController.createDevice(self, config) 5.25 - if self.vm.info.is_hvm(): 5.26 - # is HVM, so qemu-dm will handle the vfb. 5.27 - return 5.28 - 5.29 - args = [ xen.util.auxbin.pathTo("qemu-dm"), 5.30 - "-M", "xenpv", 5.31 - "-d", "%d" % self.vm.getDomid(), 5.32 - "-domain-name", self.vm.getName() ] 5.33 - t = config.get("type", None) 5.34 - if t == "vnc": 5.35 - passwd = None 5.36 - if config.has_key("vncpasswd"): 5.37 - passwd = config["vncpasswd"] 5.38 - else: 5.39 - passwd = xen.xend.XendOptions.instance().get_vncpasswd_default() 5.40 - if passwd: 5.41 - self.vm.storeVm("vncpasswd", passwd) 5.42 - log.debug("Stored a VNC password for vfb access") 5.43 - else: 5.44 - log.debug("No VNC passwd configured for vfb access") 5.45 - 5.46 - vnclisten = config.get('vnclisten', 5.47 - xen.xend.XendOptions.instance().get_vnclisten_address()) 5.48 - vncdisplay = config.get('vncdisplay', 0) 5.49 - args += ['-vnc', "%s:%d" % (vnclisten, vncdisplay)] 5.50 - 5.51 - if config.get('vncunused', 0): 5.52 - args += ['-vncunused'] 5.53 - 5.54 - if config.has_key("keymap"): 5.55 - args += ["-k", "%s" % config["keymap"]] 5.56 - else: 5.57 - xoptions = xen.xend.XendOptions.instance() 5.58 - if xoptions.get_keymap(): 5.59 - args += ["-k", "%s" % xoptions.get_keymap()] 5.60 - 5.61 - spawn_detached(args[0], args, os.environ) 5.62 - elif t == "sdl": 5.63 - env = dict(os.environ) 5.64 - if config.has_key("display"): 5.65 - env['DISPLAY'] = config["display"] 5.66 - if config.has_key("xauthority"): 5.67 - env['XAUTHORITY'] = config["xauthority"] 5.68 - spawn_detached(args[0], args, env) 5.69 - else: 5.70 - raise VmError('Unknown vfb type %s (%s)' % (t, repr(config))) 5.71 - 5.72 - 5.73 def waitForDevice(self, devid): 5.74 - if self.vm.info.get('HVM_boot_policy'): 5.75 - log.debug('skip waiting for HVM vfb') 5.76 - # is a qemu-dm managed device, don't wait for hotplug for these. 5.77 - return 5.78 - 5.79 - DevController.waitForDevice(self, devid) 5.80 - 5.81 + # is a qemu-dm managed device, don't wait for hotplug for these. 5.82 + return 5.83 5.84 def reconfigureDevice(self, _, config): 5.85 """ Only allow appending location information of vnc port into 5.86 @@ -115,19 +51,16 @@ class VfbifController(DevController): 5.87 raise VmError('Refusing to reconfigure device vfb:%d' % devid) 5.88 5.89 def destroyDevice(self, devid, force): 5.90 - if self.vm.info.get('HVM_boot_policy'): 5.91 - # remove the backend xenstore entries for HVM guests no matter 5.92 - # what 5.93 - DevController.destroyDevice(self, devid, True) 5.94 - else: 5.95 - DevController.destroyDevice(self, devid, force) 5.96 + # remove the backend xenstore entries no matter what 5.97 + # because we kill qemu-dm with extreme prejudice 5.98 + # not giving it a chance to remove them itself 5.99 + DevController.destroyDevice(self, devid, True) 5.100 5.101 5.102 def migrate(self, deviceConfig, network, dst, step, domName): 5.103 - if self.vm.info.get('HVM_boot_policy'): 5.104 - return 0 5.105 - return DevController.migrate(self, deviceConfig, network, dst, step, 5.106 - domName) 5.107 + # Handled by qemu-dm so no action needed 5.108 + return 0 5.109 + 5.110 5.111 class VkbdifController(DevController): 5.112 """Virtual keyboard controller. Handles all vkbd devices for a domain. 5.113 @@ -141,22 +74,15 @@ class VkbdifController(DevController): 5.114 return (devid, back, front) 5.115 5.116 def waitForDevice(self, config): 5.117 - if self.vm.info.get('HVM_boot_policy'): 5.118 - # is a qemu-dm managed device, don't wait for hotplug for these. 5.119 - return 5.120 - 5.121 - DevController.waitForDevice(self, config) 5.122 + # is a qemu-dm managed device, don't wait for hotplug for these. 5.123 + return 5.124 5.125 def destroyDevice(self, devid, force): 5.126 - if self.vm.info.get('HVM_boot_policy'): 5.127 - # remove the backend xenstore entries for HVM guests no matter 5.128 - # what 5.129 - DevController.destroyDevice(self, devid, True) 5.130 - else: 5.131 - DevController.destroyDevice(self, devid, force) 5.132 + # remove the backend xenstore entries no matter what 5.133 + # because we kill qemu-dm with extreme prejudice 5.134 + # not giving it a chance to remove them itself 5.135 + DevController.destroyDevice(self, devid, True) 5.136 5.137 def migrate(self, deviceConfig, network, dst, step, domName): 5.138 - if self.vm.info.get('HVM_boot_policy'): 5.139 - return 0 5.140 - return DevController.migrate(self, deviceConfig, network, dst, step, 5.141 - domName) 5.142 + # Handled by qemu-dm so no action needed 5.143 + return 0