xen-vtx-unstable
annotate tools/python/xen/xend/server/controller.py @ 6131:f056b0cc171e
xm block-create doesn't work. It seems like this command hasn't even
been tested (perhaps since the un-Twisting?). This particular problem
was that one function was being called with self instead of the right
argument and another function's return value was being used when it
didn't actually return anything.
This patch also improves the error handling a bit by making sure we
don't thrown an exception on a log statement with a None value. In
general, one should always use the % formatter instead of concatination
for strings in Python (even though this is not what this patch does).
Signed-off-by: Anthony Liguori
been tested (perhaps since the un-Twisting?). This particular problem
was that one function was being called with self instead of the right
argument and another function's return value was being used when it
didn't actually return anything.
This patch also improves the error handling a bit by making sure we
don't thrown an exception on a log statement with a None value. In
general, one should always use the % formatter instead of concatination
for strings in Python (even though this is not what this patch does).
Signed-off-by: Anthony Liguori
author | kaf24@firebug.cl.cam.ac.uk |
---|---|
date | Sat Aug 13 09:06:20 2005 +0000 (2005-08-13) |
parents | f40c6650152e |
children | 058e8087d36a |
rev | line source |
---|---|
kaf24@6064 | 1 #============================================================================ |
kaf24@6064 | 2 # This library is free software; you can redistribute it and/or |
kaf24@6064 | 3 # modify it under the terms of version 2.1 of the GNU Lesser General Public |
kaf24@6064 | 4 # License as published by the Free Software Foundation. |
kaf24@6064 | 5 # |
kaf24@6064 | 6 # This library is distributed in the hope that it will be useful, |
kaf24@6064 | 7 # but WITHOUT ANY WARRANTY; without even the implied warranty of |
kaf24@6064 | 8 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
kaf24@6064 | 9 # Lesser General Public License for more details. |
kaf24@6064 | 10 # |
kaf24@6064 | 11 # You should have received a copy of the GNU Lesser General Public |
kaf24@6064 | 12 # License along with this library; if not, write to the Free Software |
kaf24@6064 | 13 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
kaf24@6064 | 14 #============================================================================ |
kaf24@6064 | 15 # Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com> |
kaf24@6064 | 16 #============================================================================ |
kaf24@6064 | 17 |
mjw@1719 | 18 """General support for controllers, which handle devices |
mjw@1719 | 19 for a domain. |
mjw@1719 | 20 """ |
mjw@1654 | 21 |
mjw@4580 | 22 from xen.xend.XendError import XendError |
cl349@5388 | 23 from xen.xend.xenstore import DBVar |
cl349@5336 | 24 from xen.xend.server.messages import msgTypeName, printMsg, getMessageType |
mjw@1623 | 25 |
mjw@2397 | 26 DEBUG = 0 |
mjw@1677 | 27 |
mjw@4580 | 28 class CtrlMsgRcvr: |
mjw@4668 | 29 """Utility class to dispatch messages on a control channel. |
mjw@4580 | 30 Once I{registerChannel} has been called, our message types are registered |
mjw@4580 | 31 with the channel. The channel will call I{requestReceived} |
mjw@4580 | 32 when a request arrives if it has one of our message types. |
mjw@4580 | 33 |
mjw@4580 | 34 @ivar channel: channel to a domain |
mjw@4580 | 35 @type channel: Channel |
mjw@4580 | 36 @ivar majorTypes: major message types we are interested in |
mjw@4580 | 37 @type majorTypes: {int:{int:method}} |
mjw@4580 | 38 |
mjw@1677 | 39 """ |
mjw@1677 | 40 |
mjw@4580 | 41 def __init__(self, channel): |
mjw@4580 | 42 self.majorTypes = {} |
mjw@4580 | 43 self.channel = channel |
mjw@1677 | 44 |
mjw@4580 | 45 def getHandler(self, type, subtype): |
mjw@2224 | 46 """Get the method for a type and subtype. |
mjw@2224 | 47 |
mjw@2224 | 48 @param type: major message type |
mjw@2224 | 49 @param subtype: minor message type |
mjw@2224 | 50 @return: method or None |
mjw@2224 | 51 """ |
mjw@2224 | 52 method = None |
mjw@2224 | 53 subtypes = self.majorTypes.get(type) |
mjw@2224 | 54 if subtypes: |
mjw@2224 | 55 method = subtypes.get(subtype) |
mjw@2224 | 56 return method |
mjw@2224 | 57 |
mjw@4580 | 58 def addHandler(self, type, subtype, method): |
mjw@2224 | 59 """Add a method to handle a message type and subtype. |
mjw@2224 | 60 |
mjw@2224 | 61 @param type: major message type |
mjw@2224 | 62 @param subtype: minor message type |
mjw@2224 | 63 @param method: method |
mjw@2224 | 64 """ |
mjw@2224 | 65 subtypes = self.majorTypes.get(type) |
mjw@2224 | 66 if not subtypes: |
mjw@2224 | 67 subtypes = {} |
mjw@2224 | 68 self.majorTypes[type] = subtypes |
mjw@2224 | 69 subtypes[subtype] = method |
mjw@2224 | 70 |
mjw@2224 | 71 def getMajorTypes(self): |
mjw@2224 | 72 """Get the list of major message types handled. |
mjw@2224 | 73 """ |
mjw@2224 | 74 return self.majorTypes.keys() |
mjw@2224 | 75 |
mjw@1623 | 76 def requestReceived(self, msg, type, subtype): |
mjw@1719 | 77 """Dispatch a request message to handlers. |
mjw@1719 | 78 Called by the channel for requests with one of our types. |
mjw@1654 | 79 |
mjw@1719 | 80 @param msg: message |
mjw@1719 | 81 @type msg: xu message |
mjw@1719 | 82 @param type: major message type |
mjw@1719 | 83 @type type: int |
mjw@1719 | 84 @param subtype: minor message type |
mjw@1719 | 85 @type subtype: int |
mjw@1654 | 86 """ |
mjw@1677 | 87 if DEBUG: |
mjw@1719 | 88 print 'requestReceived>', |
mjw@4580 | 89 printMsg(msg, all=True) |
mjw@2265 | 90 responded = 0 |
mjw@4580 | 91 method = self.getHandler(type, subtype) |
mjw@1623 | 92 if method: |
mjw@4580 | 93 responded = method(msg) |
mjw@1677 | 94 elif DEBUG: |
mjw@1623 | 95 print ('requestReceived> No handler: Message type %s %d:%d' |
mjw@1623 | 96 % (msgTypeName(type, subtype), type, subtype)), self |
mjw@2265 | 97 return responded |
mjw@1623 | 98 |
mjw@1677 | 99 |
mjw@1623 | 100 def lostChannel(self): |
mjw@1654 | 101 """Called when the channel to the domain is lost. |
mjw@1654 | 102 """ |
mjw@4617 | 103 if DEBUG: |
mjw@4617 | 104 print 'CtrlMsgRcvr>lostChannel>', |
mjw@4580 | 105 self.channel = None |
mjw@1623 | 106 |
mjw@1623 | 107 def registerChannel(self): |
mjw@1654 | 108 """Register interest in our major message types with the |
mjw@1719 | 109 channel to our domain. Once we have registered, the channel |
mjw@4580 | 110 will call requestReceived for our messages. |
mjw@1654 | 111 """ |
mjw@4580 | 112 if DEBUG: |
mjw@4580 | 113 print 'CtrlMsgRcvr>registerChannel>', self.channel, self.getMajorTypes() |
mjw@4580 | 114 if self.channel: |
mjw@2224 | 115 self.channel.registerDevice(self.getMajorTypes(), self) |
mjw@1623 | 116 |
mjw@1623 | 117 def deregisterChannel(self): |
mjw@1654 | 118 """Deregister interest in our major message types with the |
mjw@1719 | 119 channel to our domain. After this the channel won't call |
mjw@1719 | 120 us any more. |
mjw@1654 | 121 """ |
mjw@1623 | 122 if self.channel: |
mjw@1623 | 123 self.channel.deregisterDevice(self) |
mjw@1623 | 124 |
mjw@4580 | 125 class DevControllerTable: |
mjw@4668 | 126 """Table of device controller classes, indexed by type name. |
mjw@2332 | 127 """ |
mjw@2332 | 128 |
mjw@2332 | 129 def __init__(self): |
mjw@4668 | 130 self.controllerClasses = {} |
mjw@4580 | 131 |
mjw@4668 | 132 def getDevControllerClass(self, type): |
mjw@4668 | 133 return self.controllerClasses.get(type) |
mjw@4580 | 134 |
cl349@5346 | 135 def addDevControllerClass(self, cls): |
cl349@5346 | 136 self.controllerClasses[cls.getType()] = cls |
mjw@2332 | 137 |
mjw@4668 | 138 def delDevControllerClass(self, type): |
mjw@4668 | 139 if type in self.controllerClasses: |
mjw@4668 | 140 del self.controllerClasses[type] |
mjw@2332 | 141 |
mjw@4580 | 142 def createDevController(self, type, vm, recreate=False): |
cl349@5346 | 143 cls = self.getDevControllerClass(type) |
cl349@5346 | 144 if not cls: |
kaf24@6131 | 145 raise XendError("unknown device type: " + str(type)) |
cl349@5346 | 146 return cls.createDevController(vm, recreate=recreate) |
mjw@2332 | 147 |
mjw@4580 | 148 def getDevControllerTable(): |
mjw@4668 | 149 """Singleton constructor for the controller table. |
mjw@4668 | 150 """ |
mjw@4580 | 151 global devControllerTable |
mjw@4580 | 152 try: |
mjw@4580 | 153 devControllerTable |
mjw@4580 | 154 except: |
mjw@4580 | 155 devControllerTable = DevControllerTable() |
mjw@4580 | 156 return devControllerTable |
mjw@1623 | 157 |
cl349@5346 | 158 def addDevControllerClass(name, cls): |
mjw@4668 | 159 """Add a device controller class to the controller table. |
mjw@4668 | 160 """ |
cl349@5346 | 161 cls.type = name |
cl349@5346 | 162 getDevControllerTable().addDevControllerClass(cls) |
mjw@4580 | 163 |
mjw@4580 | 164 def createDevController(name, vm, recreate=False): |
mjw@4580 | 165 return getDevControllerTable().createDevController(name, vm, recreate=recreate) |
mjw@4580 | 166 |
mjw@4580 | 167 class DevController: |
mjw@4580 | 168 """Abstract class for a device controller attached to a domain. |
mjw@4580 | 169 A device controller manages all the devices of a given type for a domain. |
mjw@4580 | 170 There is exactly one device controller for each device type for |
mjw@4580 | 171 a domain. |
mjw@2332 | 172 |
mjw@4580 | 173 """ |
mjw@4580 | 174 |
cl349@5388 | 175 # State: |
cl349@5388 | 176 # controller/<type> : for controller |
cl349@5388 | 177 # device/<type>/<id> : for each device |
cl349@5388 | 178 |
cl349@5346 | 179 def createDevController(cls, vm, recreate=False): |
mjw@4668 | 180 """Class method to create a dev controller. |
mjw@4668 | 181 """ |
cl349@5346 | 182 ctrl = cls(vm, recreate=recreate) |
mjw@4668 | 183 ctrl.initController(recreate=recreate) |
cl349@5388 | 184 ctrl.exportToDB() |
mjw@4668 | 185 return ctrl |
mjw@4668 | 186 |
mjw@4668 | 187 createDevController = classmethod(createDevController) |
mjw@4668 | 188 |
cl349@5346 | 189 def getType(cls): |
cl349@5346 | 190 return cls.type |
mjw@4668 | 191 |
mjw@4668 | 192 getType = classmethod(getType) |
mjw@4668 | 193 |
cl349@5388 | 194 __exports__ = [ |
cl349@5388 | 195 DBVar('type', 'str'), |
cl349@5388 | 196 DBVar('destroyed', 'bool'), |
cl349@5388 | 197 ] |
cl349@5388 | 198 |
cl349@5346 | 199 # Set when registered. |
cl349@5346 | 200 type = None |
cl349@5346 | 201 |
mjw@4668 | 202 def __init__(self, vm, recreate=False): |
mjw@4580 | 203 self.destroyed = False |
mjw@4580 | 204 self.vm = vm |
cl349@5388 | 205 self.db = self.getDB() |
mjw@4580 | 206 self.deviceId = 0 |
mjw@4580 | 207 self.devices = {} |
mjw@4580 | 208 self.device_order = [] |
mjw@2332 | 209 |
cl349@5388 | 210 def getDB(self): |
cl349@5388 | 211 """Get the db node to use for a controller. |
cl349@5388 | 212 """ |
cl349@5388 | 213 return self.vm.db.addChild("/controller/%s" % self.getType()) |
cl349@5388 | 214 |
cl349@5388 | 215 def getDevDB(self, id): |
cl349@5388 | 216 """Get the db node to use for a device. |
cl349@5388 | 217 """ |
cl349@5388 | 218 return self.vm.db.addChild("/device/%s/%s" % (self.getType(), id)) |
cl349@5388 | 219 |
cl349@5388 | 220 def exportToDB(self, save=False): |
cl349@5388 | 221 self.db.exportToDB(self, fields=self.__exports__, save=save) |
cl349@5388 | 222 |
cl349@5388 | 223 def importFromDB(self): |
cl349@5388 | 224 self.db.importFromDB(self, fields=self.__exports__) |
cl349@5388 | 225 |
mjw@4580 | 226 def getDevControllerType(self): |
mjw@4580 | 227 return self.dctype |
mjw@2332 | 228 |
mjw@4580 | 229 def getDomain(self): |
mjw@4580 | 230 return self.vm.getDomain() |
mjw@4580 | 231 |
mjw@4580 | 232 def getDomainName(self): |
mjw@4580 | 233 return self.vm.getName() |
mjw@2332 | 234 |
mjw@4580 | 235 def getChannel(self): |
mjw@4580 | 236 chan = self.vm.getChannel() |
mjw@4580 | 237 return chan |
mjw@4580 | 238 |
mjw@4580 | 239 def getDomainInfo(self): |
mjw@4580 | 240 return self.vm |
mjw@2332 | 241 |
mjw@4580 | 242 #---------------------------------------------------------------------------- |
mjw@4580 | 243 # Subclass interface. |
mjw@4580 | 244 # Subclasses should define the unimplemented methods.. |
mjw@4580 | 245 # Redefinitions must have the same arguments. |
mjw@2332 | 246 |
mjw@4580 | 247 def initController(self, recreate=False, reboot=False): |
mjw@4668 | 248 """Initialise the controller. Called when the controller is |
mjw@4668 | 249 first created, and again after the domain is rebooted (with reboot True). |
mjw@4668 | 250 If called with recreate True (and reboot False) the controller is being |
mjw@4668 | 251 recreated after a xend restart. |
mjw@4668 | 252 |
mjw@4668 | 253 As this can be a re-init (after reboot) any controller state should |
mjw@4668 | 254 be reset. For example the destroyed flag. |
mjw@4668 | 255 """ |
mjw@4580 | 256 self.destroyed = False |
mjw@4580 | 257 if reboot: |
mjw@4580 | 258 self.rebootDevices() |
mjw@4580 | 259 |
mjw@4580 | 260 def newDevice(self, id, config, recreate=False): |
mjw@4580 | 261 """Create a device with the given config. |
mjw@4580 | 262 Must be defined in subclass. |
mjw@4668 | 263 Called with recreate True when the device is being recreated after a |
mjw@4668 | 264 xend restart. |
mjw@4580 | 265 |
mjw@4580 | 266 @return device |
mjw@2332 | 267 """ |
mjw@2332 | 268 raise NotImplementedError() |
mjw@2332 | 269 |
mjw@4580 | 270 def createDevice(self, config, recreate=False, change=False): |
mjw@4668 | 271 """Create a device and attach to its front- and back-ends. |
mjw@4668 | 272 If recreate is true the device is being recreated after a xend restart. |
mjw@4668 | 273 If change is true the device is a change to an existing domain, |
mjw@4668 | 274 i.e. it is being added at runtime rather than when the domain is created. |
mjw@4668 | 275 """ |
cl349@5388 | 276 dev = self.newDevice(self.nextDeviceId(), config, recreate=recreate) |
cl349@5388 | 277 if self.vm.recreate: |
cl349@5388 | 278 dev.importFromDB() |
mjw@4580 | 279 dev.init(recreate=recreate) |
mjw@4580 | 280 self.addDevice(dev) |
cl349@5388 | 281 if not recreate: |
cl349@5388 | 282 dev.exportToDB() |
mjw@4580 | 283 dev.attach(recreate=recreate, change=change) |
cl349@5388 | 284 dev.exportToDB() |
mjw@4580 | 285 |
kaf24@6131 | 286 return dev |
kaf24@6131 | 287 |
mjw@4580 | 288 def configureDevice(self, id, config, change=False): |
mjw@4580 | 289 """Reconfigure an existing device. |
mjw@4580 | 290 May be defined in subclass.""" |
cl349@5338 | 291 dev = self.getDevice(id, error=True) |
mjw@4580 | 292 dev.configure(config, change=change) |
mjw@2267 | 293 |
mjw@4580 | 294 def destroyDevice(self, id, change=False, reboot=False): |
mjw@4580 | 295 """Destroy a device. |
mjw@4668 | 296 May be defined in subclass. |
mjw@4668 | 297 |
mjw@4668 | 298 If reboot is true the device is being destroyed for a domain reboot. |
mjw@4668 | 299 |
mjw@4668 | 300 The device is not deleted, since it may be recreated later. |
mjw@4668 | 301 """ |
cl349@5338 | 302 dev = self.getDevice(id, error=True) |
mjw@4580 | 303 dev.destroy(change=change, reboot=reboot) |
mjw@4580 | 304 return dev |
mjw@4580 | 305 |
mjw@4580 | 306 def deleteDevice(self, id, change=True): |
mjw@4668 | 307 """Destroy a device and delete it. |
mjw@4668 | 308 Normally called to remove a device from a domain at runtime. |
mjw@4668 | 309 """ |
mjw@4580 | 310 dev = self.destroyDevice(id, change=change) |
mjw@4580 | 311 self.removeDevice(dev) |
mjw@4580 | 312 |
mjw@4580 | 313 def destroyController(self, reboot=False): |
mjw@4580 | 314 """Destroy all devices and clean up. |
mjw@4668 | 315 May be defined in subclass. |
mjw@4668 | 316 If reboot is true the controller is being destroyed for a domain reboot. |
mjw@4668 | 317 Called at domain shutdown. |
mjw@4668 | 318 """ |
mjw@4580 | 319 self.destroyed = True |
mjw@4580 | 320 self.destroyDevices(reboot=reboot) |
mjw@4580 | 321 |
mjw@4580 | 322 #---------------------------------------------------------------------------- |
mjw@4580 | 323 |
mjw@4580 | 324 def isDestroyed(self): |
mjw@4580 | 325 return self.destroyed |
mjw@4580 | 326 |
cl349@5338 | 327 def getDevice(self, id, error=False): |
cl349@5338 | 328 dev = self.devices.get(id) |
cl349@5338 | 329 if error and not dev: |
kaf24@6131 | 330 raise XendError("invalid device id: " + str(id)) |
cl349@5338 | 331 return dev |
mjw@4580 | 332 |
mjw@4580 | 333 def getDeviceIds(self): |
mjw@4580 | 334 return [ dev.getId() for dev in self.device_order ] |
mjw@4580 | 335 |
mjw@4580 | 336 def getDevices(self): |
mjw@4580 | 337 return self.device_order |
mjw@4580 | 338 |
mjw@4580 | 339 def getDeviceConfig(self, id): |
mjw@4580 | 340 return self.getDevice(id).getConfig() |
mjw@4580 | 341 |
mjw@4580 | 342 def getDeviceConfigs(self): |
mjw@4580 | 343 return [ dev.getConfig() for dev in self.device_order ] |
mjw@4580 | 344 |
mjw@4580 | 345 def getDeviceSxprs(self): |
mjw@4580 | 346 return [ dev.sxpr() for dev in self.device_order ] |
mjw@4580 | 347 |
mjw@4580 | 348 def addDevice(self, dev): |
mjw@4580 | 349 self.devices[dev.getId()] = dev |
mjw@4580 | 350 self.device_order.append(dev) |
mjw@4580 | 351 return dev |
mjw@4580 | 352 |
mjw@4580 | 353 def removeDevice(self, dev): |
mjw@4580 | 354 if dev.getId() in self.devices: |
mjw@4580 | 355 del self.devices[dev.getId()] |
mjw@4580 | 356 if dev in self.device_order: |
mjw@4580 | 357 self.device_order.remove(dev) |
mjw@4580 | 358 |
mjw@4580 | 359 def rebootDevices(self): |
mjw@4580 | 360 for dev in self.getDevices(): |
mjw@4580 | 361 dev.reboot() |
mjw@4580 | 362 |
mjw@4580 | 363 def destroyDevices(self, reboot=False): |
mjw@4580 | 364 """Destroy all devices. |
mjw@4580 | 365 """ |
mjw@4580 | 366 for dev in self.getDevices(): |
mjw@4580 | 367 dev.destroy(reboot=reboot) |
mjw@2225 | 368 |
mjw@4580 | 369 def getMaxDeviceId(self): |
mjw@4580 | 370 maxid = 0 |
mjw@4580 | 371 for id in self.devices: |
mjw@4580 | 372 if id > maxid: |
mjw@4580 | 373 maxid = id |
mjw@4580 | 374 return maxid |
mjw@4580 | 375 |
mjw@4580 | 376 def nextDeviceId(self): |
mjw@4580 | 377 id = self.deviceId |
mjw@4580 | 378 self.deviceId += 1 |
mjw@4580 | 379 return id |
mjw@4580 | 380 |
mjw@4580 | 381 def getDeviceCount(self): |
mjw@4580 | 382 return len(self.devices) |
mjw@4580 | 383 |
mjw@4580 | 384 class Dev: |
mjw@4580 | 385 """Abstract class for a device attached to a device controller. |
mjw@2332 | 386 |
mjw@4580 | 387 @ivar id: identifier |
mjw@4580 | 388 @type id: int |
mjw@4580 | 389 @ivar controller: device controller |
mjw@4580 | 390 @type controller: DevController |
mjw@4580 | 391 """ |
mjw@4580 | 392 |
cl349@5388 | 393 # ./status : need 2: actual and requested? |
cl349@5388 | 394 # down-down: initial. |
cl349@5388 | 395 # up-up: fully up. |
cl349@5388 | 396 # down-up: down requested, still up. Watch front and back, when both |
cl349@5388 | 397 # down go to down-down. But what if one (or both) is not connected? |
cl349@5388 | 398 # Still have front/back trees with status? Watch front/status, back/status? |
cl349@5388 | 399 # up-down: up requested, still down. |
cl349@5388 | 400 # Back-end watches ./status, front/status |
cl349@5388 | 401 # Front-end watches ./status, back/status |
cl349@5388 | 402 # i.e. each watches the other 2. |
cl349@5388 | 403 # Each is status/request status/actual? |
cl349@5388 | 404 # |
cl349@5388 | 405 # backend? |
cl349@5388 | 406 # frontend? |
cl349@5388 | 407 |
cl349@5388 | 408 __exports__ = [ |
cl349@5388 | 409 DBVar('id', ty='int'), |
cl349@5388 | 410 DBVar('type', ty='str'), |
cl349@5388 | 411 DBVar('config', ty='sxpr'), |
cl349@5388 | 412 DBVar('destroyed', ty='bool'), |
cl349@5388 | 413 ] |
cl349@5388 | 414 |
mjw@4580 | 415 def __init__(self, controller, id, config, recreate=False): |
mjw@4580 | 416 self.controller = controller |
mjw@4580 | 417 self.id = id |
mjw@4580 | 418 self.config = config |
mjw@4580 | 419 self.destroyed = False |
cl349@5388 | 420 self.type = self.getType() |
cl349@5388 | 421 |
cl349@5388 | 422 self.db = controller.getDevDB(id) |
cl349@5388 | 423 |
cl349@5388 | 424 def exportToDB(self, save=False): |
cl349@5388 | 425 self.db.exportToDB(self, fields=self.__exports__, save=save) |
cl349@5388 | 426 |
cl349@5388 | 427 def importFromDB(self): |
cl349@5388 | 428 self.db.importFromDB(self, fields=self.__exports__) |
mjw@4580 | 429 |
mjw@4580 | 430 def getDomain(self): |
mjw@4580 | 431 return self.controller.getDomain() |
mjw@4580 | 432 |
mjw@4580 | 433 def getDomainName(self): |
mjw@4580 | 434 return self.controller.getDomainName() |
mjw@4580 | 435 |
mjw@4580 | 436 def getChannel(self): |
mjw@4580 | 437 return self.controller.getChannel() |
mjw@4580 | 438 |
mjw@4580 | 439 def getDomainInfo(self): |
mjw@4580 | 440 return self.controller.getDomainInfo() |
mjw@4580 | 441 |
mjw@4580 | 442 def getController(self): |
mjw@4580 | 443 return self.controller |
mjw@4580 | 444 |
mjw@4580 | 445 def getType(self): |
mjw@4580 | 446 return self.controller.getType() |
mjw@2332 | 447 |
mjw@4580 | 448 def getId(self): |
mjw@4580 | 449 return self.id |
mjw@4580 | 450 |
mjw@4580 | 451 def getConfig(self): |
mjw@4580 | 452 return self.config |
mjw@4580 | 453 |
mjw@4580 | 454 def isDestroyed(self): |
mjw@4580 | 455 return self.destroyed |
mjw@4580 | 456 |
mjw@4580 | 457 #---------------------------------------------------------------------------- |
mjw@4580 | 458 # Subclass interface. |
mjw@4580 | 459 # Define methods in subclass as needed. |
mjw@4580 | 460 # Redefinitions must have the same arguments. |
mjw@4580 | 461 |
mjw@4580 | 462 def init(self, recreate=False, reboot=False): |
mjw@4580 | 463 """Initialization. Called on initial create (when reboot is False) |
mjw@4580 | 464 and on reboot (when reboot is True). When xend is restarting is |
mjw@4580 | 465 called with recreate True. Define in subclass if needed. |
mjw@4668 | 466 |
mjw@4668 | 467 Device instance variables must be defined in the class constructor, |
mjw@4668 | 468 but given null or default values. The real values should be initialised |
mjw@4668 | 469 in this method. This allows devices to be re-initialised. |
mjw@4668 | 470 |
mjw@4668 | 471 Since this can be called to re-initialise a device any state flags |
mjw@4668 | 472 should be reset. |
mjw@4580 | 473 """ |
mjw@4580 | 474 self.destroyed = False |
mjw@2332 | 475 |
mjw@4580 | 476 def attach(self, recreate=False, change=False): |
mjw@4580 | 477 """Attach the device to its front and back ends. |
mjw@4580 | 478 Define in subclass if needed. |
mjw@4580 | 479 """ |
mjw@4580 | 480 pass |
mjw@4580 | 481 |
mjw@4580 | 482 def reboot(self): |
mjw@4668 | 483 """Reconnect the device when the domain is rebooted. |
mjw@4580 | 484 """ |
mjw@4580 | 485 self.init(reboot=True) |
mjw@4580 | 486 self.attach() |
mjw@2332 | 487 |
mjw@4580 | 488 def sxpr(self): |
mjw@4580 | 489 """Get the s-expression for the deivice. |
mjw@4580 | 490 Implement in a subclass if needed. |
mjw@2332 | 491 |
mjw@4580 | 492 @return: sxpr |
mjw@4580 | 493 """ |
mjw@4580 | 494 return self.getConfig() |
mjw@4580 | 495 |
mjw@4580 | 496 def configure(self, config, change=False): |
mjw@4580 | 497 """Reconfigure the device. |
mjw@4580 | 498 |
mjw@4580 | 499 Implement in subclass. |
mjw@2332 | 500 """ |
mjw@2332 | 501 raise NotImplementedError() |
mjw@2332 | 502 |
mjw@4580 | 503 def refresh(self): |
mjw@4580 | 504 """Refresh the device.. |
mjw@4580 | 505 Default no-op. Define in subclass if needed. |
mjw@2520 | 506 """ |
mjw@4580 | 507 pass |
mjw@2185 | 508 |
mjw@4580 | 509 def destroy(self, change=False, reboot=False): |
mjw@4580 | 510 """Destroy the device. |
mjw@4580 | 511 If change is True notify destruction (runtime change). |
mjw@4580 | 512 If reboot is True the device is being destroyed for a reboot. |
mjw@4580 | 513 Redefine in subclass if needed. |
mjw@4668 | 514 |
mjw@4668 | 515 Called at domain shutdown and when a device is deleted from |
mjw@4668 | 516 a running domain (with change True). |
mjw@4580 | 517 """ |
mjw@4580 | 518 self.destroyed = True |
mjw@4580 | 519 pass |
mjw@1654 | 520 |
mjw@4580 | 521 #---------------------------------------------------------------------------- |