ia64/xen-unstable

view tools/python/xen/xend/server/blkif.py @ 13014:ef5e6df3ba9e

[Xend] Add a --force option to detach operations.

In some situations triggered by errors found on guest side,
the device will be held forever, due to the online flag being still
on. Detach operations mostly fails from this point on, as the backend
will not see frontend's state change anymore.

Signed-off-by: Glauber de Oliveira Costa <gcosta@redhat.com>
author kfraser@localhost.localdomain
date Thu Dec 14 10:17:37 2006 +0000 (2006-12-14)
parents 0c1e2abc1888
children bf605c314a91
line source
1 #============================================================================
2 # This library is free software; you can redistribute it and/or
3 # modify it under the terms of version 2.1 of the GNU Lesser General Public
4 # License as published by the Free Software Foundation.
5 #
6 # This library is distributed in the hope that it will be useful,
7 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 # Lesser General Public License for more details.
10 #
11 # You should have received a copy of the GNU Lesser General Public
12 # License along with this library; if not, write to the Free Software
13 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14 #============================================================================
15 # Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
16 # Copyright (C) 2005, 2006 XenSource Inc.
17 #============================================================================
19 import re
20 import string
22 from xen.util import blkif
23 from xen.util import security
24 from xen.xend.XendError import VmError
25 from xen.xend.server.DevController import DevController
27 class BlkifController(DevController):
28 """Block device interface controller. Handles all block devices
29 for a domain.
30 """
32 def __init__(self, vm):
33 """Create a block device controller.
34 """
35 DevController.__init__(self, vm)
37 def getDeviceDetails(self, config):
38 """@see DevController.getDeviceDetails"""
39 uname = config.get('uname', '')
40 dev = config.get('dev', '')
42 if 'ioemu:' in dev:
43 (_, dev) = string.split(dev, ':', 1)
44 try:
45 (dev, dev_type) = string.split(dev, ':', 1)
46 except ValueError:
47 dev_type = "disk"
49 if uname is None:
50 if dev_type == 'cdrom':
51 (typ, params) = ("", "")
52 else:
53 raise VmError(
54 'Block device must have physical details specified')
55 else:
56 try:
57 (typ, params) = string.split(uname, ':', 1)
58 except ValueError:
59 (typ, params) = ("", "")
61 mode = config.get('mode', 'r')
62 if mode not in ('r', 'w', 'w!'):
63 raise VmError('Invalid mode')
65 back = {'dev' : dev,
66 'type' : typ,
67 'params' : params,
68 'mode' : mode,
69 }
71 uuid = config.get('uuid')
72 if uuid:
73 back['uuid'] = uuid
75 if security.on():
76 (label, ssidref, policy) = security.get_res_security_details(uname)
77 back.update({'acm_label' : label,
78 'acm_ssidref': str(ssidref),
79 'acm_policy' : policy})
81 devid = blkif.blkdev_name_to_number(dev)
82 if devid is None:
83 raise VmError('Unable to find number for device (%s)' % (dev))
85 front = { 'virtual-device' : "%i" % devid,
86 'device-type' : dev_type
87 }
89 return (devid, back, front)
92 def reconfigureDevice(self, _, config):
93 """@see DevController.reconfigureDevice"""
94 (devid, new_back, new_front) = self.getDeviceDetails(config)
96 (dev, mode) = self.readBackend(devid, 'dev', 'mode')
97 dev_type = self.readFrontend(devid, 'device-type')
99 if (dev_type == 'cdrom' and new_front['device-type'] == 'cdrom' and
100 dev == new_back['dev'] and mode == 'r'):
101 self.writeBackend(devid,
102 'type', new_back['type'],
103 'params', new_back['params'])
104 else:
105 raise VmError('Refusing to reconfigure device %s:%d to %s' %
106 (self.deviceClass, devid, config))
109 def getDeviceConfiguration(self, devid):
110 """Returns the configuration of a device.
112 @note: Similar to L{configuration} except it returns a dict.
113 @return: dict
114 """
115 config = DevController.getDeviceConfiguration(self, devid)
116 devinfo = self.readBackend(devid, 'dev', 'type', 'params', 'mode',
117 'uuid')
118 dev, typ, params, mode, uuid = devinfo
120 if dev:
121 dev_type = self.readFrontend(devid, 'device-type')
122 if dev_type:
123 dev += ':' + dev_type
124 config['dev'] = dev
125 if typ and params:
126 config['uname'] = typ +':' + params
127 else:
128 config['uname'] = None
129 if mode:
130 config['mode'] = mode
131 if uuid:
132 config['uuid'] = uuid
134 return config
136 def destroyDevice(self, devid, force):
137 """@see DevController.destroyDevice"""
139 # If we are given a device name, then look up the device ID from it,
140 # and destroy that ID instead. If what we are given is an integer,
141 # then assume it's a device ID and pass it straight through to our
142 # superclass's method.
144 try:
145 DevController.destroyDevice(self, int(devid), force)
146 except ValueError:
147 devid_end = type(devid) is str and devid.split('/')[-1] or None
149 for i in self.deviceIDs():
150 d = self.readBackend(i, 'dev')
151 if d == devid or (devid_end and d == devid_end):
152 DevController.destroyDevice(self, i, force)
153 return
154 raise VmError("Device %s not connected" % devid)