[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] blktap2: Port Xend to the tap-ctl interface.



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1275980743 -3600
# Node ID 6fe6d5b4cd078b8af930eba79169da70a8ab7d9a
# Parent  63d0f5348af242e6046e1e30d22841ba20f8e6d6
blktap2: Port Xend to the tap-ctl interface.

Signed-off-by: Jake Wires <jake.wires@xxxxxxxxxx>
---
 tools/python/xen/xend/XendDomainInfo.py          |   26 ---
 tools/python/xen/xend/server/BlktapController.py |  178 +++++++++++++++--------
 2 files changed, 124 insertions(+), 80 deletions(-)

diff -r 63d0f5348af2 -r 6fe6d5b4cd07 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py   Tue Jun 08 08:05:09 2010 +0100
+++ b/tools/python/xen/xend/XendDomainInfo.py   Tue Jun 08 08:05:43 2010 +0100
@@ -63,7 +63,7 @@ from xen.xend.XendAPIConstants import *
 from xen.xend.XendAPIConstants import *
 from xen.xend.XendCPUPool import XendCPUPool
 from xen.xend.server.DevConstants import xenbusState
-from xen.xend.server.BlktapController import TAPDISK_DEVICE, parseDeviceString
+from xen.xend.server.BlktapController import TapdiskController
 
 from xen.xend.XendVMMetrics import XendVMMetrics
 
@@ -549,15 +549,8 @@ class XendDomainInfo:
                 dev =  xstransact.List(self.vmpath + '/device/tap2')
                 for x in dev:
                     path = self.getDeviceController('tap2').readBackend(x, 
'params')
-                    if path and path.startswith(TAPDISK_DEVICE):
-                        try:
-                            _minor, _dev, ctrl = parseDeviceString(path)
-                            #pause the disk
-                            f = open(ctrl + '/pause', 'w')
-                            f.write('pause');
-                            f.close()
-                        except:
-                            pass
+                    if path and path.startswith(TapdiskController.TAP_DEV):
+                        TapdiskController.pause(path)
         except Exception, ex:
             log.warn('Could not pause blktap disk.');
 
@@ -578,17 +571,8 @@ class XendDomainInfo:
                 dev =  xstransact.List(self.vmpath + '/device/tap2')
                 for x in dev:
                     path = self.getDeviceController('tap2').readBackend(x, 
'params')
-                    if path and path.startswith(TAPDISK_DEVICE):
-                        try:
-                            #Figure out the sysfs path.
-                            _minor, _dev, ctrl = parseDeviceString(path)
-                            #unpause the disk
-                            if(os.path.exists(ctrl + '/resume')):              
    
-                                f = open(ctrl + '/resume', 'w');
-                                f.write('resume');
-                                f.close();
-                        except:
-                            pass
+                    if path and path.startswith(TapdiskController.TAP_DEV):
+                        TapdiskController.unpause(path)
 
         except Exception, ex:
             log.warn('Could not unpause blktap disk: %s' % str(ex));
diff -r 63d0f5348af2 -r 6fe6d5b4cd07 
tools/python/xen/xend/server/BlktapController.py
--- a/tools/python/xen/xend/server/BlktapController.py  Tue Jun 08 08:05:09 
2010 +0100
+++ b/tools/python/xen/xend/server/BlktapController.py  Tue Jun 08 08:05:43 
2010 +0100
@@ -1,5 +1,5 @@
 # Copyright (c) 2005, XenSource Ltd.
-import string, re
+import string, re, os
 
 from xen.xend.server.blkif import BlkifController
 from xen.xend.XendLogging import log
@@ -7,11 +7,6 @@ from xen.util.xpopen import xPopen3
 
 phantomDev = 0;
 phantomId = 0;
-
-TAPDISK_SYSFS   = '/sys/class/blktap2'
-TAPDISK_BINARY  = '/usr/sbin/tapdisk2'
-TAPDISK_DEVICE  = '/dev/xen/blktap-2/tapdev'
-TAPDISK_CONTROL = TAPDISK_SYSFS + '/blktap'
 
 blktap1_disk_types = [
     'aio',
@@ -42,20 +37,6 @@ def doexec(args, inputtext=None):
     stderr = proc.childerr
     rc = proc.wait()
     return (rc,stdout,stderr)
-
-def parseDeviceString(device):
-    if device.find('/dev') == -1:
-        raise Exception, 'invalid tap device: ' + device
-
-    pattern = re.compile(TAPDISK_DEVICE + '(\d+)$')
-    groups  = pattern.search(device)
-    if not groups:
-        raise Exception, 'malformed tap device: ' + device
-
-    minor   = groups.group(1)
-    control = TAPDISK_CONTROL + minor
-
-    return minor, device, control
 
 # blktap1 device controller
 class BlktapController(BlkifController):
@@ -179,18 +160,10 @@ class Blktap2Controller(BlktapController
             (typ, params, file) = string.split(uname, ':', 2)
             subtyp = 'tapdisk'
 
-        #check for blktap2 installation.
-        blktap2_installed=0;
-        (rc,stdout, stderr) = doexec("cat /proc/devices");
-        out = stdout.read();
-        stdout.close();
-        stderr.close();
-        if( out.find("blktap2") >= 0 ):
-            blktap2_installed=1;
-
         if typ in ('tap'):
             if subtyp in ('tapdisk', 'ioemu'):
-                if params not in blktap2_disk_types or not blktap2_installed:
+                if params not in blktap2_disk_types or \
+                        TapdiskController.check():
                     # pass this device off to BlktapController
                     log.warn('WARNING: using deprecated blktap module')
                     self.deviceClass = 'tap'
@@ -198,22 +171,7 @@ class Blktap2Controller(BlktapController
                     self.deviceClass = 'tap2'
                     return devid
 
-        if self.vm.image and self.vm.image.memory_sharing:
-            cmd = [ TAPDISK_BINARY, '-n', '%s:%s' % (params, file), '-s', '%d' 
% self.vm.getDomid() ]
-        else:
-            cmd = [ TAPDISK_BINARY, '-n', '%s:%s' % (params, file) ]
-        (rc,stdout,stderr) = doexec(cmd)
-
-        if rc != 0:
-            err = stderr.read();
-            out = stdout.read();
-            stdout.close();
-            stderr.close();
-            raise Exception, 'Failed to create device.\n    stdout: %s\n    
stderr: %s\nCheck that target \"%s\" exists and that blktap2 driver installed 
in dom0.' % (out.rstrip(), err.rstrip(), file);
-
-        minor, device, control = parseDeviceString(stdout.readline())
-        stdout.close();
-        stderr.close();
+        device = TapdiskController.create(params, file)
 
         # modify the configutration to create a blkback for the underlying
         # blktap2 device. Note: we need to preserve the original tapdisk uname
@@ -226,8 +184,7 @@ class Blktap2Controller(BlktapController
         config.pop('tapdisk_uname')
         return devid
 
-    # The new blocktap implementation requires a sysfs signal to close
-    # out disks.  This function is called from a thread when the
+    # This function is called from a thread when the
     # domain is detached from the disk.
     def finishDeviceCleanup(self, backpath, path):
         """Perform any device specific cleanup
@@ -239,14 +196,117 @@ class Blktap2Controller(BlktapController
 
         #Figure out what we're going to wait on.
         self.waitForBackend_destroy(backpath)
-
-        #Figure out the sysfs path.
-        minor, dev, ctrl = parseDeviceString(path)
-
-        #Close out the disk
-        f = open(ctrl + '/remove', 'w')
-        f.write('remove');
-        f.close()
-
-        return
-
+        TapdiskController.destroy(path)
+
+class TapdiskException(Exception):
+    pass
+
+class TapdiskController(object):
+    '''class which encapsulates all tapdisk control operations'''
+
+    TAP_CTL = 'tap-ctl'
+    TAP_DEV = '/dev/xen/blktap-2/tapdev'
+
+    class Tapdisk(object):
+        def __init__(self, pid=None, minor=-1, state=None,
+                     dtype='', image=None, device=None):
+            self.pid = pid
+            self.minor = minor
+            self.state = state
+            self.dtype = dtype
+            self.image = image
+            self.device = device
+
+        def __str__(self):
+            return 'image=%s pid=%s minor=%s state=%s type=%s device=%s' \
+                % (self.image, self.pid, self.minor, self.state, self.dtype,
+                   self.device)
+
+    @staticmethod
+    def exc(*args):
+        rc, stdout, stderr = doexec([TapdiskController.TAP_CTL] + list(args))
+        out, err = stdout.read().strip(), stderr.read().strip()
+        stdout.close()
+        stderr.close()
+        if rc:
+            raise TapdiskException('%s failed (%s %s %s)' % \
+                                       (args, rc, out, err))
+        return out
+
+    @staticmethod
+    def check():
+        try:
+            TapdiskController.exc('check')
+            return 0
+        except Exception, e:
+            log.warn("tapdisk2 check failed: %s" % e)
+            return -1
+
+    @staticmethod
+    def list():
+        tapdisks = []
+
+        _list = TapdiskController.exc('list')
+        if not _list: return []
+
+        for line in _list.split('\n'):
+            tapdisk = TapdiskController.Tapdisk()
+
+            for pair in line.split():
+                key, value = pair.split('=')
+                if key == 'pid':
+                    tapdisk.pid = value
+                elif key == 'minor':
+                    tapdisk.minor = int(value)
+                    if tapdisk.minor >= 0:
+                        tapdisk.device = '%s%s' % \
+                            (TapdiskController.TAP_DEV, tapdisk.minor)
+                elif key == 'state':
+                    tapdisk.state = value
+                elif key == 'args' and value.find(':') != -1:
+                    tapdisk.dtype, tapdisk.image = value.split(':')
+
+            tapdisks.append(tapdisk)
+
+        return tapdisks
+
+    @staticmethod
+    def fromDevice(device):
+        if device.startswith(TapdiskController.TAP_DEV):
+            minor = os.minor(os.stat(device).st_rdev)
+            tapdisks = filter(lambda x: x.minor == minor,
+                              TapdiskController.list())
+            if len(tapdisks) == 1:
+                return tapdisks[0]
+        return None
+
+    @staticmethod
+    def create(dtype, image):
+        return TapdiskController.exc('create', '-a%s:%s' % (dtype, image))
+
+    @staticmethod
+    def destroy(device):
+        tapdisk = TapdiskController.fromDevice(device)
+        if tapdisk:
+            if tapdisk.pid:
+                TapdiskController.exc('destroy',
+                                      '-p%s' % tapdisk.pid,
+                                      '-m%s' % tapdisk.minor)
+            else:
+                TapdiskController.exc('free', '-m%s' % tapdisk.minor)
+
+    @staticmethod
+    def pause(device):
+        tapdisk = TapdiskController.fromDevice(device)
+        if tapdisk and tapdisk.pid:
+            TapdiskController.exc('pause',
+                                  '-p%s' % tapdisk.pid,
+                                  '-m%s' % tapdisk.minor)
+
+    @staticmethod
+    def unpause(device):
+        tapdisk = TapdiskController.fromDevice(device)
+        if tapdisk and tapdisk.pid:
+            TapdiskController.exc('unpause',
+                                  '-p%s' % tapdisk.pid,
+                                  '-m%s' % tapdisk.minor)

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.