xen-vtx-unstable
annotate tools/python/xen/xend/server/controller.py @ 6132:058e8087d36a
If block-create didn't work, then chances are block-destroy doesn't work
either right :-)
In this case, XendDomain.py is just calling a function that doesn't
exist (device_destroy instead of device_delete).
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
either right :-)
In this case, XendDomain.py is just calling a function that doesn't
exist (device_destroy instead of device_delete).
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
author | kaf24@firebug.cl.cam.ac.uk |
---|---|
date | Sat Aug 13 09:06:44 2005 +0000 (2005-08-13) |
parents | f056b0cc171e |
children | 8864f0be80c6 |
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): |
kaf24@6132 | 328 dev = self.devices.get(int(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 #---------------------------------------------------------------------------- |