WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] [blktap] Allow HVM booting from blktap de

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] [blktap] Allow HVM booting from blktap device(s)
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Thu, 08 Feb 2007 08:50:07 -0800
Delivery-date: Thu, 08 Feb 2007 08:50:47 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# 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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] [blktap] Allow HVM booting from blktap device(s), Xen patchbot-unstable <=