direct-io.hg

view tools/python/xen/xend/server/DevController.py @ 7562:c774efa2aca8

Added doccomment.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author emellor@leeni.uk.xensource.com
date Sun Oct 30 17:19:35 2005 +0100 (2005-10-30)
parents e0ea9320c351
children 286946489e5d
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 XenSource Ltd
17 #============================================================================
20 from xen.xend import sxp
21 from xen.xend.XendError import VmError
22 from xen.xend.XendLogging import log
23 from xen.xend.xenstore.xstransact import xstransact
26 class DevController:
27 """Abstract base class for a device controller. Device controllers create
28 appropriate entries in the store to trigger the creation, reconfiguration,
29 and destruction of devices in guest domains. Each subclass of
30 DevController is responsible for a particular device-class, and
31 understands the details of configuration specific to that device-class.
33 DevController itself provides the functionality common to all device
34 creation tasks, as well as providing an interface to XendDomainInfo for
35 triggering those events themselves.
36 """
38 # Set when registered.
39 deviceClass = None
42 ## public:
44 def __init__(self, vm):
45 self.vm = vm
48 def createDevice(self, config):
49 """Trigger the creation of a device with the given configuration.
51 @return The ID for the newly created device.
52 """
53 (devid, back, front) = self.getDeviceDetails(config)
55 self.writeDetails(config, devid, back, front)
57 return devid
60 def reconfigureDevice(self, devid, config):
61 """Reconfigure the specified device.
63 The implementation here just raises VmError. This may be overridden
64 by those subclasses that can reconfigure their devices.
65 """
66 raise VmError('%s devices may not be reconfigured' % self.deviceClass)
69 def destroyDevice(self, devid):
70 """Destroy the specified device.
72 @param devid The device ID, or something device-specific from which
73 the device ID can be determined (such as a guest-side device name).
75 The implementation here simply deletes the appropriate paths from the
76 store. This may be overridden by subclasses who need to perform other
77 tasks on destruction. Further, the implementation here can only
78 accept integer device IDs, or values that can be converted to
79 integers. Subclasses may accept other values and convert them to
80 integers before passing them here.
81 """
83 devid = int(devid)
85 frontpath = self.frontendPath(devid)
86 backpath = xstransact.Read(frontpath, "backend")
88 xstransact.Remove(frontpath)
90 if backpath:
91 xstransact.Remove(backpath)
92 else:
93 raise VmError("Device %s not connected" % devid)
96 def configurations(self):
97 return map(self.configuration, self.deviceIDs())
100 def configuration(self, devid):
101 """@return an s-expression giving the current configuration of the
102 specified device. This would be suitable for giving to {@link
103 #createDevice} in order to recreate that device."""
105 backdomid = int(xstransact.Read(self.frontendPath(devid),
106 "backend-id"))
108 return [self.deviceClass, ['backend', backdomid]]
111 def sxprs(self):
112 """@return an s-expression describing all the devices of this
113 controller's device-class.
114 """
115 return xstransact.ListRecursive(self.frontendRoot())
118 def sxpr(self, devid):
119 """@return an s-expression describing the specified device.
120 """
121 return [self.deviceClass, ['dom', self.vm.getDomid(),
122 'id', devid]]
125 ## protected:
127 def getDeviceDetails(self, config):
128 """Compute the details for creation of a device corresponding to the
129 given configuration. These details consist of a tuple of (devID,
130 backDetails, frontDetails), where devID is the ID for the new device,
131 and backDetails and frontDetails are the device configuration
132 specifics for the backend and frontend respectively.
134 backDetails and frontDetails should be dictionaries, the keys and
135 values of which will be used as paths in the store. There is no need
136 for these dictionaries to include the references from frontend to
137 backend, nor vice versa, as these will be handled by DevController.
139 Abstract; must be implemented by every subclass.
141 @return (devID, backDetails, frontDetails), as specified above.
142 """
144 raise NotImplementedError()
147 def getDomid(self):
148 """Stub to {@link XendDomainInfo.getDomid}, for use by our
149 subclasses.
150 """
151 return self.vm.getDomid()
154 def allocateDeviceID(self):
155 """Allocate a device ID, allocating them consecutively on a
156 per-domain, per-device-class basis, and using the store to record the
157 next available ID.
159 This method is available to our subclasses, though it is not
160 compulsory to use it; subclasses may prefer to allocate IDs based upon
161 the device configuration instead.
162 """
163 path = self.frontendMiscPath()
164 while True:
165 t = xstransact(path)
166 try:
167 result = t.read("nextDeviceID")
168 if result:
169 result = int(result)
170 else:
171 result = 0
172 t.write("nextDeviceID", str(result + 1))
173 if t.commit():
174 return result
175 except:
176 t.abort()
177 raise
180 def readBackend(self, devid, *args):
181 frontpath = self.frontendPath(devid)
182 backpath = xstransact.Read(frontpath, "backend")
183 return xstransact.Read(backpath, *args)
186 def deviceIDs(self):
187 """@return The IDs of each of the devices currently configured for
188 this instance's deviceClass.
189 """
190 return map(int, xstransact.List(self.frontendRoot()))
193 ## private:
195 def writeDetails(self, config, devid, backDetails, frontDetails):
196 """Write the details in the store to trigger creation of a device.
197 The backend domain ID is taken from the given config, paths for
198 frontend and backend are computed, and these are written to the store
199 appropriately, including references from frontend to backend and vice
200 versa.
202 @param config The configuration of the device, as given to
203 {@link #createDevice}.
204 @param devid As returned by {@link #getDeviceDetails}.
205 @param backDetails As returned by {@link #getDeviceDetails}.
206 @param frontDetails As returned by {@link #getDeviceDetails}.
207 """
209 import xen.xend.XendDomain
210 xd = xen.xend.XendDomain.instance()
212 backdom_name = sxp.child_value(config, 'backend')
213 if backdom_name:
214 backdom = xd.domain_lookup_by_name_or_id_nr(backdom_name)
215 else:
216 backdom = xd.privilegedDomain()
218 if not backdom:
219 raise VmError("Cannot configure device for unknown backend %s" %
220 backdom_name)
222 frontpath = self.frontendPath(devid)
223 backpath = self.backendPath(backdom, devid)
225 frontDetails.update({
226 'backend' : backpath,
227 'backend-id' : "%i" % backdom.getDomid()
228 })
231 backDetails.update({
232 'domain' : self.vm.getName(),
233 'frontend' : frontpath,
234 'frontend-id' : "%i" % self.vm.getDomid()
235 })
237 log.debug('DevController: writing %s to %s.', str(frontDetails),
238 frontpath)
239 log.debug('DevController: writing %s to %s.', str(backDetails),
240 backpath)
242 xstransact.Write(frontpath, frontDetails)
243 xstransact.Write(backpath, backDetails)
246 def backendPath(self, backdom, devid):
247 """@param backdom [XendDomainInfo] The backend domain info."""
249 return "%s/backend/%s/%s/%d" % (backdom.getDomainPath(),
250 self.deviceClass,
251 self.vm.getDomid(), devid)
254 def frontendPath(self, devid):
255 return "%s/%d" % (self.frontendRoot(), devid)
258 def frontendRoot(self):
259 return "%s/device/%s" % (self.vm.getDomainPath(), self.deviceClass)
262 def frontendMiscPath(self):
263 return "%s/device-misc/%s" % (self.vm.getDomainPath(),
264 self.deviceClass)