ia64/xen-unstable

view tools/python/xen/xend/server/BlktapController.py @ 19795:4f779d41b0ba

blktap: re-enable blktap1 if blktap2 is disabled

This patch re-enables a useful blktap1 for users who disable blktap2.
Itremoves tapdisk and blktapctrl from blktap2, both of which cause
problems with blktap operation. In addition, this patch modifies xend
to check for blktap2 installation. If the blktap2 driver isn't
running (hopefully because the dom0 kernel option wasn't selected) we
fall back to blktap.

Signed-off-by: Dutch Meyer <dmeyer@cs.ubc.ca>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Jun 18 10:29:58 2009 +0100 (2009-06-18)
parents 2cbedd22149a
children f3211c71e8f0
line source
1 # Copyright (c) 2005, XenSource Ltd.
2 import string, re
3 import popen2
5 from xen.xend.server.blkif import BlkifController
6 from xen.xend.XendLogging import log
8 phantomDev = 0;
9 phantomId = 0;
11 TAPDISK_SYSFS = '/sys/class/blktap2'
12 TAPDISK_BINARY = '/usr/sbin/tapdisk2'
13 TAPDISK_DEVICE = '/dev/xen/blktap-2/tapdev'
14 TAPDISK_CONTROL = TAPDISK_SYSFS + '/blktap'
16 blktap_disk_types = [
17 'aio',
18 'sync',
19 'vmdk',
20 'ram',
21 'qcow',
22 'qcow2',
23 'vhd',
24 'ioemu',
25 'tapdisk',
26 ]
28 def doexec(args, inputtext=None):
29 """Execute a subprocess, then return its return code, stdout and stderr"""
30 proc = popen2.Popen3(args, True)
31 if inputtext != None:
32 proc.tochild.write(inputtext)
33 stdout = proc.fromchild
34 stderr = proc.childerr
35 rc = proc.wait()
36 return (rc,stdout,stderr)
38 def parseDeviceString(device):
39 if device.find('/dev') == -1:
40 raise Exception, 'invalid tap device: ' + device
42 pattern = re.compile(TAPDISK_DEVICE + '(\d+)$')
43 groups = pattern.search(device)
44 if not groups:
45 raise Exception, 'malformed tap device: ' + device
47 minor = groups.group(1)
48 control = TAPDISK_CONTROL + minor
50 return minor, device, control
54 class BlktapController(BlkifController):
55 def __init__(self, vm):
56 BlkifController.__init__(self, vm)
58 def frontendRoot(self):
59 """@see DevController#frontendRoot"""
61 return "%s/device/vbd" % self.vm.getDomainPath()
63 def getDeviceDetails(self, config):
64 (devid, back, front) = BlkifController.getDeviceDetails(self, config)
66 phantomDevid = 0
67 wrapped = False
69 try:
70 imagetype = self.vm.info['image']['type']
71 except:
72 imagetype = ""
74 if imagetype == 'hvm':
75 tdevname = back['dev']
76 index = ['c', 'd', 'e', 'f', 'g', 'h', 'i', \
77 'j', 'l', 'm', 'n', 'o', 'p']
78 while True:
79 global phantomDev
80 global phantomId
81 import os, stat
83 phantomId = phantomId + 1
84 if phantomId == 16:
85 if index[phantomDev] == index[-1]:
86 if wrapped:
87 raise VmError(" No loopback block \
88 devices are available. ")
89 wrapped = True
90 phantomDev = 0
91 else:
92 phantomDev = phantomDev + 1
93 phantomId = 1
94 devname = 'xvd%s%d' % (index[phantomDev], phantomId)
95 try:
96 info = os.stat('/dev/%s' % devname)
97 except:
98 break
100 vbd = { 'mode': 'w', 'device': devname }
101 fn = 'tap:%s' % back['params']
103 # recurse ... by creating the vbd, then fallthrough
104 # and finish creating the original device
106 from xen.xend import XendDomain
107 dom0 = XendDomain.instance().privilegedDomain()
108 phantomDevid = dom0.create_phantom_vbd_with_vdi(vbd, fn)
109 # we need to wait for this device at a higher level
110 # the vbd that gets created will have a link to us
111 # and will let them do it there
113 # add a hook to point to the phantom device,
114 # root path is always the same (dom0 tap)
115 if phantomDevid != 0:
116 front['phantom_vbd'] = '/local/domain/0/backend/tap/0/%s' \
117 % str(phantomDevid)
119 return (devid, back, front)
121 def createDevice(self, config):
123 uname = config.get('uname', '')
124 try:
125 (typ, subtyp, params, file) = string.split(uname, ':', 3)
126 except:
127 (typ, params, file) = string.split(uname, ':', 2)
128 subtyp = 'tapdisk'
130 #check for blktap2 installation.
131 blktap2_installed=0;
132 (rc,stdout, stderr) = doexec("cat /proc/devices");
133 out = stdout.read();
134 stdout.close();
135 stderr.close();
136 if( out.find("blktap2") >= 0 ):
137 blktap2_installed=1;
139 if typ in ('tap'):
140 if subtyp in ('tapdisk'):
141 if params in ('ioemu', 'qcow2', 'vmdk', 'sync') or not blktap2_installed:
142 log.warn('WARNING: using deprecated blktap module');
143 return BlkifController.createDevice(self, config);
145 cmd = [ TAPDISK_BINARY, '-n', '%s:%s' % (params, file) ]
146 (rc,stdout,stderr) = doexec(cmd)
148 if rc != 0:
149 err = stderr.read();
150 out = stdout.read();
151 stdout.close();
152 stderr.close();
153 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);
155 minor, device, control = parseDeviceString(stdout.readline())
156 stdout.close();
157 stderr.close();
159 #modify the configuration to attach as a vbd, now that the
160 #device is configured. Then continue to create the device
161 config.update({'uname' : 'phy:' + device.rstrip()})
162 self.deviceClass='vbd'
164 return BlkifController.createDevice(self, config);