[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [blktap] Allow HVM booting from blktap device(s)
# HG changeset patch # User wim@xxxxxxxxxxxx # Date 1170895981 28800 # Node ID 6524e02edbeb8aebe65aa5400af4b09dfccb8729 # Parent 780f097b54c5f9161f7c6cf3f86b2bb72cc43587 [blktap] Allow HVM booting from blktap device(s) Signed-off-by: wim colgate <wim@xxxxxxxxxxxxx> --- tools/ioemu/xenstore.c | 60 +++++++++++++++++++++- tools/python/xen/xend/XendConfig.py | 41 +++++++++++++++ tools/python/xen/xend/XendDomainInfo.py | 56 ++++++++++++++++++++ tools/python/xen/xend/server/BlktapController.py | 62 +++++++++++++++++++++++ tools/python/xen/xend/server/DevController.py | 13 ++++ 5 files changed, 230 insertions(+), 2 deletions(-) diff -r 780f097b54c5 -r 6524e02edbeb tools/ioemu/xenstore.c --- a/tools/ioemu/xenstore.c Wed Feb 07 17:29:52 2007 +0000 +++ b/tools/ioemu/xenstore.c Wed Feb 07 16:53:01 2007 -0800 @@ -10,6 +10,7 @@ #include "vl.h" #include "block_int.h" +#include <unistd.h> static struct xs_handle *xsh = NULL; static char *hd_filename[MAX_DISKS]; @@ -52,11 +53,40 @@ void xenstore_check_new_media_present(in qemu_mod_timer(insert_timer, qemu_get_clock(rt_clock) + timeout); } +static int waitForDevice(char *path, char *field, char *desired) +{ + char *buf = NULL, *stat = NULL; + unsigned int len; + int val = 1; + + /* loop until we find a value in xenstore, return + * if it was what we wanted, or not + */ + while (1) { + if (pasprintf(&buf, "%s/%s", path, field) == -1) + goto done; + free(stat); + stat = xs_read(xsh, XBT_NULL, buf, &len); + if (stat == NULL) { + usleep(100000); /* 1/10th second, no path found */ + } else { + val = strcmp(stat, desired); + goto done; + } + } + +done: + free(stat); + free(buf); + return val; +} + void xenstore_parse_domain_config(int domid) { char **e = NULL; char *buf = NULL, *path; - char *bpath = NULL, *dev = NULL, *params = NULL, *type = NULL; + char *fpath = NULL, *bpath = NULL, + *dev = NULL, *params = NULL, *type = NULL; int i; unsigned int len, num, hd_index; @@ -120,7 +150,35 @@ void xenstore_parse_domain_config(int do hd_filename[hd_index] = params; /* strdup() */ params = NULL; /* don't free params on re-use */ } + /* + * check if device has a phantom vbd; the phantom is hooked + * to the frontend device (for ease of cleanup), so lookup + * the frontend device, and see if there is a phantom_vbd + * if there is, we will use resolution as the filename + */ + if (pasprintf(&buf, "%s/device/vbd/%s/phantom_vbd", path, e[i]) == -1) + continue; + free(fpath); + fpath = xs_read(xsh, XBT_NULL, buf, &len); + if (fpath != NULL) { + + if (waitForDevice(fpath, "hotplug-status", "connected")) { + continue; + } + + if (pasprintf(&buf, "%s/dev", fpath) == -1) + continue; + params = xs_read(xsh, XBT_NULL, buf , &len); + if (params != NULL) { + free(hd_filename[hd_index]); + hd_filename[hd_index] = params; + params = NULL; /* don't free params on re-use */ + } + } bs_table[hd_index] = bdrv_new(dev); + /* re-establish buf */ + if (pasprintf(&buf, "%s/params", bpath) == -1) + continue; /* check if it is a cdrom */ if (type && !strcmp(type, "cdrom")) { bdrv_set_type_hint(bs_table[hd_index], BDRV_TYPE_CDROM); diff -r 780f097b54c5 -r 6524e02edbeb tools/python/xen/xend/XendConfig.py --- a/tools/python/xen/xend/XendConfig.py Wed Feb 07 17:29:52 2007 +0000 +++ b/tools/python/xen/xend/XendConfig.py Wed Feb 07 16:53:01 2007 -0800 @@ -1148,6 +1148,47 @@ class XendConfig(dict): # no valid device to add return '' + def phantom_device_add(self, dev_type, cfg_xenapi = None, + target = None): + """Add a phantom tap device configuration in XenAPI struct format. + """ + + if target == None: + target = self + + if dev_type not in XendDevices.valid_devices() and \ + dev_type not in XendDevices.pseudo_devices(): + raise XendConfigError("XendConfig: %s not a valid device type" % + dev_type) + + if cfg_xenapi == None: + raise XendConfigError("XendConfig: device_add requires some " + "config.") + + if cfg_xenapi: + log.debug("XendConfig.phantom_device_add: %s" % str(cfg_xenapi)) + + if cfg_xenapi: + dev_info = {} + if dev_type in ('vbd', 'tap'): + if dev_type == 'vbd': + dev_info['uname'] = cfg_xenapi.get('image', '') + dev_info['dev'] = '%s:disk' % cfg_xenapi.get('device') + elif dev_type == 'tap': + if cfg_xenapi.get('image').find('tap:') == -1: + dev_info['uname'] = 'tap:qcow:%s' % cfg_xenapi.get('image') + dev_info['dev'] = '/dev/%s' % cfg_xenapi.get('device') + dev_info['uname'] = cfg_xenapi.get('image') + dev_info['mode'] = cfg_xenapi.get('mode') + dev_info['backend'] = '0' + dev_uuid = cfg_xenapi.get('uuid', uuid.createString()) + dev_info['uuid'] = dev_uuid + self['devices'][dev_uuid] = (dev_type, dev_info) + self['vbd_refs'].append(dev_uuid) + return dev_uuid + + return '' + def console_add(self, protocol, location, other_config = {}): dev_uuid = uuid.createString() if protocol == 'vt100': diff -r 780f097b54c5 -r 6524e02edbeb tools/python/xen/xend/XendDomainInfo.py --- a/tools/python/xen/xend/XendDomainInfo.py Wed Feb 07 17:29:52 2007 +0000 +++ b/tools/python/xen/xend/XendDomainInfo.py Wed Feb 07 16:53:01 2007 -0800 @@ -1565,18 +1565,53 @@ class XendDomainInfo: # VM Destroy # + def _prepare_phantom_paths(self): + # get associated devices to destroy + # build list of phantom devices to be removed after normal devices + plist = [] + from xen.xend.xenstore.xstransact import xstransact + t = xstransact("%s/device/vbd" % GetDomainPath(self.domid)) + for dev in t.list(): + backend_phantom_vbd = xstransact.Read("%s/device/vbd/%s/phantom_vbd" \ + % (self.dompath, dev)) + if backend_phantom_vbd is not None: + frontend_phantom_vbd = xstransact.Read("%s/frontend" \ + % backend_phantom_vbd) + plist.append(backend_phantom_vbd) + plist.append(frontend_phantom_vbd) + return plist + + def _cleanup_phantom_devs(self, plist): + # remove phantom devices + if not plist == []: + time.sleep(2) + for paths in plist: + if paths.find('backend') != -1: + from xen.xend.server import DevController + # Modify online status /before/ updating state (latter is watched by + # drivers, so this ordering avoids a race). + xstransact.Write(paths, 'online', "0") + xstransact.Write(paths, 'state', str(DevController.xenbusState['Closing'])) + # force + xstransact.Remove(paths) + def destroy(self): """Cleanup VM and destroy domain. Nothrow guarantee.""" log.debug("XendDomainInfo.destroy: domid=%s", str(self.domid)) + + paths = self._prepare_phantom_paths() self._cleanupVm() if self.dompath is not None: self.destroyDomain() + self._cleanup_phantom_devs(paths) def destroyDomain(self): log.debug("XendDomainInfo.destroyDomain(%s)", str(self.domid)) + + paths = self._prepare_phantom_paths() try: if self.domid is not None: @@ -1591,7 +1626,7 @@ class XendDomainInfo: XendDomain.instance().remove_domain(self) self.cleanupDomain() - + self._cleanup_phantom_devs(paths) def resumeDomain(self): log.debug("XendDomainInfo.resumeDomain(%s)", str(self.domid)) @@ -2211,6 +2246,25 @@ class XendDomainInfo: return dev_uuid + def create_phantom_vbd_with_vdi(self, xenapi_vbd, vdi_image_path): + """Create a VBD using a VDI from XendStorageRepository. + + @param xenapi_vbd: vbd struct from the Xen API + @param vdi_image_path: VDI UUID + @rtype: string + @return: uuid of the device + """ + xenapi_vbd['image'] = vdi_image_path + dev_uuid = self.info.phantom_device_add('tap', cfg_xenapi = xenapi_vbd) + if not dev_uuid: + raise XendError('Failed to create device') + + if self.state == XEN_API_VM_POWER_STATE_RUNNING: + _, config = self.info['devices'][dev_uuid] + config['devid'] = self.getDeviceController('tap').createDevice(config) + + return config['devid'] + def create_vif(self, xenapi_vif): """Create VIF device from the passed struct in Xen API format. diff -r 780f097b54c5 -r 6524e02edbeb tools/python/xen/xend/server/BlktapController.py --- a/tools/python/xen/xend/server/BlktapController.py Wed Feb 07 17:29:52 2007 +0000 +++ b/tools/python/xen/xend/server/BlktapController.py Wed Feb 07 16:53:01 2007 -0800 @@ -2,7 +2,10 @@ from xen.xend.server.blkif import BlkifController +from xen.xend.XendLogging import log +phantomDev = 0; +phantomId = 0; class BlktapController(BlkifController): def __init__(self, vm): @@ -12,3 +15,62 @@ class BlktapController(BlkifController): """@see DevController#frontendRoot""" return "%s/device/vbd" % self.vm.getDomainPath() + + def getDeviceDetails(self, config): + (devid, back, front) = BlkifController.getDeviceDetails(self, config) + + phantomDevid = 0 + wrapped = False + + try: + imagetype = self.vm.info['image']['type'] + except: + imagetype = "" + + if imagetype == 'hvm': + tdevname = back['dev'] + index = ['c', 'd', 'e', 'f', 'g', 'h', 'i', \ + 'j', 'l', 'm', 'n', 'o', 'p'] + while True: + global phantomDev + global phantomId + import os, stat + + phantomId = phantomId + 1 + if phantomId == 16: + if index[phantomDev] == index[-1]: + if wrapped: + raise VmError(" No loopback block \ + devices are available. ") + wrapped = True + phantomDev = 0 + else: + phantomDev = phantomDev + 1 + phantomId = 1 + devname = 'xvd%s%d' % (index[phantomDev], phantomId) + try: + info = os.stat('/dev/%s' % devname) + except: + break + + vbd = { 'mode': 'w', 'device': devname } + fn = 'tap:%s' % back['params'] + + # recurse ... by creating the vbd, then fallthrough + # and finish creating the original device + + from xen.xend import XendDomain + dom0 = XendDomain.instance().privilegedDomain() + phantomDevid = dom0.create_phantom_vbd_with_vdi(vbd, fn) + # we need to wait for this device at a higher level + # the vbd that gets created will have a link to us + # and will let them do it there + + # add a hook to point to the phantom device, + # root path is always the same (dom0 tap) + if phantomDevid != 0: + front['phantom_vbd'] = '/local/domain/0/backend/tap/0/%s' \ + % str(phantomDevid) + + return (devid, back, front) + diff -r 780f097b54c5 -r 6524e02edbeb tools/python/xen/xend/server/DevController.py --- a/tools/python/xen/xend/server/DevController.py Wed Feb 07 17:29:52 2007 +0000 +++ b/tools/python/xen/xend/server/DevController.py Wed Feb 07 16:53:01 2007 -0800 @@ -473,6 +473,19 @@ class DevController: def waitForBackend(self, devid): frontpath = self.frontendPath(devid) + # lookup a phantom + phantomPath = xstransact.Read(frontpath, 'phantom_vbd') + if phantomPath is not None: + log.debug("Waiting for %s's phantom %s.", devid, phantomPath) + statusPath = phantomPath + '/' + HOTPLUG_STATUS_NODE + ev = Event() + result = { 'status': Timeout } + xswatch(statusPath, hotplugStatusCallback, ev, result) + ev.wait(DEVICE_CREATE_TIMEOUT) + err = xstransact.Read(statusPath, HOTPLUG_ERROR_NODE) + if result['status'] != 'Connected': + return (result['status'], err) + backpath = xstransact.Read(frontpath, "backend") _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |