ia64/xen-unstable

view tools/python/xen/xend/server/vscsiif.py @ 17993:bd97e45e073a

pvSCSI: fix xend

Previous "xend" assumed initial Xenbus state would be "Connected" when
LUN hot-plug starts. However it was not guaranteed in general, and it
may cause some problems.

Signed-off-by: Tomonari Horikoshi <t.horikoshi@jp.fujitsu.com>
Signed-off-by: Jun Kamada <kama@jp.fujitsu.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Jul 08 09:28:50 2008 +0100 (2008-07-08)
parents 6ae87b27ccea
children 9404bcb6d32e
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) 2007 FUJITSU Limited
16 # Based on the blkif.py
17 #============================================================================
20 """Support for VSCSI Devices.
21 """
22 import re
23 import string
25 import types
27 from xen.xend import sxp
28 from xen.xend.XendError import VmError
29 from xen.xend.XendLogging import log
31 from xen.xend.server.DevController import DevController, xenbusState
32 from xen.xend.xenstore.xstransact import xstransact
34 class VSCSIController(DevController):
35 """VSCSI Devices.
36 """
37 def __init__(self, vm):
38 """Create a VSCSI Devices.
39 """
40 DevController.__init__(self, vm)
43 def sxprs(self):
44 """@see DevController.sxprs"""
45 devslist = []
46 for devid in self.deviceIDs():
47 vscsi_devs = self.readBackendList(devid, "vscsi-devs")
48 vscsipath = "vscsi-devs/"
49 devs = []
50 vscsi_config = []
51 for dev in vscsi_devs:
52 devpath = vscsipath + dev
53 backstate = self.readBackend(devid, devpath + '/state')
54 pdev = self.readBackend(devid, devpath + '/p-dev')
55 pdevname = self.readBackend(devid, devpath + '/p-devname')
56 vdev = self.readBackend(devid, devpath + '/v-dev')
57 localdevid = self.readBackend(devid, devpath + '/devid')
58 frontstate = self.readFrontend(devid, devpath + '/state')
59 devs.append(['dev', \
60 ['state', backstate], \
61 ['devid', localdevid], \
62 ['p-dev', pdev], \
63 ['p-devname', pdevname], \
64 ['v-dev', vdev], \
65 ['frontstate', frontstate] ])
67 vscsi_config.append(['devs', devs])
68 state = self.readFrontend(devid, 'state')
69 vscsi_config.append(['state', state])
70 backid = self.readFrontend(devid, 'backend-id')
71 vscsi_config.append(['backend-id', backid])
72 backpath = self.readFrontend(devid, 'backend')
73 vscsi_config.append(['backend', backpath])
75 devslist.append([devid, vscsi_config])
77 return devslist
80 def getDeviceDetails(self, config):
81 """@see DevController.getDeviceDetails"""
82 back = {}
83 vscsipath = "vscsi-devs/"
84 for vscsi_config in config.get('devs', []):
85 localdevid = self.allocateDeviceID()
86 # vscsi-devs/dev-0
87 devpath = vscsipath + 'dev-%i' % localdevid
88 back[devpath] = ""
89 pdev = vscsi_config.get('p-dev', '')
90 back[devpath + '/p-dev'] = pdev
91 pdevname = vscsi_config.get('p-devname', '')
92 back[devpath + '/p-devname'] = pdevname
93 vdev = vscsi_config.get('v-dev', '')
94 back[devpath + '/v-dev'] = vdev
95 state = vscsi_config.get('state', '')
96 back[devpath + '/state'] = str(xenbusState[state])
97 devid = vscsi_config.get('devid', '')
98 back[devpath + '/devid'] = str(devid)
100 back['uuid'] = config.get('uuid','')
101 devid = int(devid)
102 return (devid, back, {})
105 def readBackendList(self, devid, *args):
106 frontpath = self.frontendPath(devid)
107 backpath = xstransact.Read(frontpath + "/backend")
108 if backpath:
109 paths = map(lambda x: backpath + "/" + x, args)
110 return xstransact.List(*paths)
113 def getDeviceConfiguration(self, devid, transaction = None):
114 config = DevController.getDeviceConfiguration(self, devid, transaction)
116 vscsi_devs = []
118 devs = self.readBackendList(devid, "vscsi-devs")
119 vscsipath = "vscsi-devs/"
120 for dev in devs:
121 devpath = vscsipath + dev
122 pdev = self.readBackend(devid, devpath + '/p-dev')
123 pdevname = self.readBackend(devid, devpath + '/p-devname')
124 vdev = self.readBackend(devid, devpath + '/v-dev')
125 state = self.readBackend(devid, devpath + '/state')
126 localdevid = self.readBackend(devid, devpath + '/devid')
127 dev_dict = {'p-dev': pdev,
128 'p-devname': pdevname,
129 'v-dev': pdevname,
130 'state': state,
131 'devid': localdevid }
132 vscsi_devs.append(dev_dict)
134 config['devs'] = vscsi_devs
135 config['uuid'] = self.readBackend(devid, 'uuid')
136 return config
139 def configuration(self, devid, transaction = None):
140 """Returns SXPR for devices on domain.
141 @note: we treat this dict especially to convert to
142 SXP because it is not a straight dict of strings."""
144 configDict = self.getDeviceConfiguration(devid, transaction)
145 sxpr = [self.deviceClass]
147 # remove devs
148 devs = configDict.pop('devs', [])
150 for dev in devs:
151 dev_sxpr = ['dev']
152 for dev_item in dev.items():
153 dev_sxpr.append(list(dev_item))
154 sxpr.append(dev_sxpr)
156 for key, val in configDict.items():
157 if type(val) == type(list()):
158 for v in val:
159 sxpr.append([key, v])
160 else:
161 sxpr.append([key, val])
163 return sxpr
166 def reconfigureDevice(self, _, config):
167 """@see DevController.reconfigureDevice"""
168 (devid, back, front) = self.getDeviceDetails(config)
169 devid = int(devid)
170 vscsi_config = config['devs'][0]
171 states = config.get('states', [])
172 driver_state = self.readBackend(devid, 'state')
173 if str(xenbusState['Connected']) != driver_state:
174 raise VmError("Driver status is not connected")
176 uuid = self.readBackend(devid, 'uuid')
177 if states[0] == 'Initialising':
178 back['uuid'] = uuid
179 self.writeBackend(devid, back)
181 elif states[0] == 'Closing':
182 found = False
183 devs = self.readBackendList(devid, "vscsi-devs")
184 vscsipath = "vscsi-devs/"
185 vdev = vscsi_config.get('v-dev', '')
187 for dev in devs:
188 devpath = vscsipath + dev
189 old_vdev = self.readBackend(devid, devpath + '/v-dev')
190 if vdev == old_vdev:
191 found = True
192 self.writeBackend(devid, devpath + '/state', \
193 str(xenbusState['Closing']))
194 break
196 if not found:
197 raise VmError("Device %s not connected" % vdev)
199 else:
200 raise XendError('Error configuring device invalid state %s'
201 % state)
203 self.writeBackend(devid, 'state', str(xenbusState['Reconfiguring']))
204 return self.readBackend(devid, 'uuid')
207 def cleanupDevice(self, devid):
208 devs = self.readBackendList(devid, "vscsi-devs")
209 vscsipath = "vscsi-devs/"
210 new_num_devs = 0
212 for dev in devs:
213 new_num_devs = new_num_devs + 1
214 devpath = vscsipath + dev
215 devstate = self.readBackend(devid, devpath + '/state')
217 if str(xenbusState['Closed']) == devstate:
218 self.removeBackend(devid, devpath)
219 frontpath = self.frontendPath(devid)
220 xstransact.Remove(frontpath + '/' + devpath)
221 new_num_devs = new_num_devs - 1
223 frontpath = self.frontendPath(devid)
224 front_devstate = xstransact.Read(frontpath + '/' + devpath)
225 if front_devstate is not None:
226 if str(xenbusState['Closed']) == front_devstate:
227 self.removeBackend(devid, devpath)
228 xstransact.Remove(frontpath + '/' + devpath)
229 new_num_devs = new_num_devs - 1
231 return new_num_devs