ia64/xen-unstable

view tools/python/xen/xend/server/BlktapController.py @ 19700:e7b63b30ae3d

blktap2: human readable output for tapdisk2 creation problems

This patch fixes the "file object has no attribute find" failure
we've been seeing when starting blktap2 devices and adds more
meaningful error output to conditions where the tapdisk2 process is
unable to create a blktap2 device.

Signed-off-by: Dutch Meyer <dmeyer@cs.ubc.ca>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Jun 03 11:10:07 2009 +0100 (2009-06-03)
parents ef6911934b6f
children 2cbedd22149a
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 (typ, subtyp, params, file) = string.split(uname, ':', 3)
125 if typ in ('tap'):
126 if subtyp in ('tapdisk'):
127 if params in ('ioemu', 'qcow2', 'vmdk', 'sync'):
128 log.warn('WARNING: using deprecated blktap module');
129 return BlkifController.createDevice(self, config);
131 cmd = [ TAPDISK_BINARY, '-n', '%s:%s' % (params, file) ]
132 (rc,stdout,stderr) = doexec(cmd)
134 if rc != 0:
135 err = stderr.read();
136 out = stdout.read();
137 stdout.close();
138 stderr.close();
139 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);
141 minor, device, control = parseDeviceString(stdout.readline())
142 stdout.close();
143 stderr.close();
145 #modify the configuration to attach as a vbd, now that the
146 #device is configured. Then continue to create the device
147 config.update({'uname' : 'phy:' + device.rstrip()})
148 self.deviceClass='vbd'
150 return BlkifController.createDevice(self, config);