xen-vtx-unstable

annotate tools/python/xen/xend/server/controller.py @ 5346:cf712d7c809c

bitkeeper revision 1.1662.1.9 (42a485d0ePlJLabsERQDyPFBJ1tF9Q)

controller.py:
Rename name -> type and use cls instead of klass.
XendDomainInfo.py:
g/c unneeded code.
Use vm.id after setdom.
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Mon Jun 06 17:20:16 2005 +0000 (2005-06-06)
parents c3febeed5ba7
children cb9679a15acd
rev   line source
mjw@1654 1 # Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
mjw@1719 2 """General support for controllers, which handle devices
mjw@1719 3 for a domain.
mjw@1719 4 """
mjw@1654 5
mjw@4580 6 from xen.xend.XendError import XendError
cl349@5336 7 from xen.xend.server.messages import msgTypeName, printMsg, getMessageType
mjw@1623 8
mjw@2397 9 DEBUG = 0
mjw@1677 10
mjw@4580 11 class CtrlMsgRcvr:
mjw@4668 12 """Utility class to dispatch messages on a control channel.
mjw@4580 13 Once I{registerChannel} has been called, our message types are registered
mjw@4580 14 with the channel. The channel will call I{requestReceived}
mjw@4580 15 when a request arrives if it has one of our message types.
mjw@4580 16
mjw@4580 17 @ivar channel: channel to a domain
mjw@4580 18 @type channel: Channel
mjw@4580 19 @ivar majorTypes: major message types we are interested in
mjw@4580 20 @type majorTypes: {int:{int:method}}
mjw@4580 21
mjw@1677 22 """
mjw@1677 23
mjw@4580 24 def __init__(self, channel):
mjw@4580 25 self.majorTypes = {}
mjw@4580 26 self.channel = channel
mjw@1677 27
mjw@4580 28 def getHandler(self, type, subtype):
mjw@2224 29 """Get the method for a type and subtype.
mjw@2224 30
mjw@2224 31 @param type: major message type
mjw@2224 32 @param subtype: minor message type
mjw@2224 33 @return: method or None
mjw@2224 34 """
mjw@2224 35 method = None
mjw@2224 36 subtypes = self.majorTypes.get(type)
mjw@2224 37 if subtypes:
mjw@2224 38 method = subtypes.get(subtype)
mjw@2224 39 return method
mjw@2224 40
mjw@4580 41 def addHandler(self, type, subtype, method):
mjw@2224 42 """Add a method to handle a message type and subtype.
mjw@2224 43
mjw@2224 44 @param type: major message type
mjw@2224 45 @param subtype: minor message type
mjw@2224 46 @param method: method
mjw@2224 47 """
mjw@2224 48 subtypes = self.majorTypes.get(type)
mjw@2224 49 if not subtypes:
mjw@2224 50 subtypes = {}
mjw@2224 51 self.majorTypes[type] = subtypes
mjw@2224 52 subtypes[subtype] = method
mjw@2224 53
mjw@2224 54 def getMajorTypes(self):
mjw@2224 55 """Get the list of major message types handled.
mjw@2224 56 """
mjw@2224 57 return self.majorTypes.keys()
mjw@2224 58
mjw@1623 59 def requestReceived(self, msg, type, subtype):
mjw@1719 60 """Dispatch a request message to handlers.
mjw@1719 61 Called by the channel for requests with one of our types.
mjw@1654 62
mjw@1719 63 @param msg: message
mjw@1719 64 @type msg: xu message
mjw@1719 65 @param type: major message type
mjw@1719 66 @type type: int
mjw@1719 67 @param subtype: minor message type
mjw@1719 68 @type subtype: int
mjw@1654 69 """
mjw@1677 70 if DEBUG:
mjw@1719 71 print 'requestReceived>',
mjw@4580 72 printMsg(msg, all=True)
mjw@2265 73 responded = 0
mjw@4580 74 method = self.getHandler(type, subtype)
mjw@1623 75 if method:
mjw@4580 76 responded = method(msg)
mjw@1677 77 elif DEBUG:
mjw@1623 78 print ('requestReceived> No handler: Message type %s %d:%d'
mjw@1623 79 % (msgTypeName(type, subtype), type, subtype)), self
mjw@2265 80 return responded
mjw@1623 81
mjw@1677 82
mjw@1623 83 def lostChannel(self):
mjw@1654 84 """Called when the channel to the domain is lost.
mjw@1654 85 """
mjw@4617 86 if DEBUG:
mjw@4617 87 print 'CtrlMsgRcvr>lostChannel>',
mjw@4580 88 self.channel = None
mjw@1623 89
mjw@1623 90 def registerChannel(self):
mjw@1654 91 """Register interest in our major message types with the
mjw@1719 92 channel to our domain. Once we have registered, the channel
mjw@4580 93 will call requestReceived for our messages.
mjw@1654 94 """
mjw@4580 95 if DEBUG:
mjw@4580 96 print 'CtrlMsgRcvr>registerChannel>', self.channel, self.getMajorTypes()
mjw@4580 97 if self.channel:
mjw@2224 98 self.channel.registerDevice(self.getMajorTypes(), self)
mjw@1623 99
mjw@1623 100 def deregisterChannel(self):
mjw@1654 101 """Deregister interest in our major message types with the
mjw@1719 102 channel to our domain. After this the channel won't call
mjw@1719 103 us any more.
mjw@1654 104 """
mjw@1623 105 if self.channel:
mjw@1623 106 self.channel.deregisterDevice(self)
mjw@1623 107
mjw@4580 108 class DevControllerTable:
mjw@4668 109 """Table of device controller classes, indexed by type name.
mjw@2332 110 """
mjw@2332 111
mjw@2332 112 def __init__(self):
mjw@4668 113 self.controllerClasses = {}
mjw@4580 114
mjw@4668 115 def getDevControllerClass(self, type):
mjw@4668 116 return self.controllerClasses.get(type)
mjw@4580 117
cl349@5346 118 def addDevControllerClass(self, cls):
cl349@5346 119 self.controllerClasses[cls.getType()] = cls
mjw@2332 120
mjw@4668 121 def delDevControllerClass(self, type):
mjw@4668 122 if type in self.controllerClasses:
mjw@4668 123 del self.controllerClasses[type]
mjw@2332 124
mjw@4580 125 def createDevController(self, type, vm, recreate=False):
cl349@5346 126 cls = self.getDevControllerClass(type)
cl349@5346 127 if not cls:
mjw@4580 128 raise XendError("unknown device type: " + type)
cl349@5346 129 return cls.createDevController(vm, recreate=recreate)
mjw@2332 130
mjw@4580 131 def getDevControllerTable():
mjw@4668 132 """Singleton constructor for the controller table.
mjw@4668 133 """
mjw@4580 134 global devControllerTable
mjw@4580 135 try:
mjw@4580 136 devControllerTable
mjw@4580 137 except:
mjw@4580 138 devControllerTable = DevControllerTable()
mjw@4580 139 return devControllerTable
mjw@1623 140
cl349@5346 141 def addDevControllerClass(name, cls):
mjw@4668 142 """Add a device controller class to the controller table.
mjw@4668 143 """
cl349@5346 144 cls.type = name
cl349@5346 145 getDevControllerTable().addDevControllerClass(cls)
mjw@4580 146
mjw@4580 147 def createDevController(name, vm, recreate=False):
mjw@4580 148 return getDevControllerTable().createDevController(name, vm, recreate=recreate)
mjw@4580 149
mjw@4580 150 class DevController:
mjw@4580 151 """Abstract class for a device controller attached to a domain.
mjw@4580 152 A device controller manages all the devices of a given type for a domain.
mjw@4580 153 There is exactly one device controller for each device type for
mjw@4580 154 a domain.
mjw@2332 155
mjw@4580 156 """
mjw@4580 157
cl349@5346 158 def createDevController(cls, vm, recreate=False):
mjw@4668 159 """Class method to create a dev controller.
mjw@4668 160 """
cl349@5346 161 ctrl = cls(vm, recreate=recreate)
mjw@4668 162 ctrl.initController(recreate=recreate)
mjw@4668 163 return ctrl
mjw@4668 164
mjw@4668 165 createDevController = classmethod(createDevController)
mjw@4668 166
cl349@5346 167 def getType(cls):
cl349@5346 168 return cls.type
mjw@4668 169
mjw@4668 170 getType = classmethod(getType)
mjw@4668 171
cl349@5346 172 # Set when registered.
cl349@5346 173 type = None
cl349@5346 174
mjw@4668 175 def __init__(self, vm, recreate=False):
mjw@4580 176 self.destroyed = False
mjw@4580 177 self.vm = vm
mjw@4580 178 self.deviceId = 0
mjw@4580 179 self.devices = {}
mjw@4580 180 self.device_order = []
mjw@2332 181
mjw@4580 182 def getDevControllerType(self):
mjw@4580 183 return self.dctype
mjw@2332 184
mjw@4580 185 def getDomain(self):
mjw@4580 186 return self.vm.getDomain()
mjw@4580 187
mjw@4580 188 def getDomainName(self):
mjw@4580 189 return self.vm.getName()
mjw@2332 190
mjw@4580 191 def getChannel(self):
mjw@4580 192 chan = self.vm.getChannel()
mjw@4580 193 return chan
mjw@4580 194
mjw@4580 195 def getDomainInfo(self):
mjw@4580 196 return self.vm
mjw@2332 197
mjw@4580 198 #----------------------------------------------------------------------------
mjw@4580 199 # Subclass interface.
mjw@4580 200 # Subclasses should define the unimplemented methods..
mjw@4580 201 # Redefinitions must have the same arguments.
mjw@2332 202
mjw@4580 203 def initController(self, recreate=False, reboot=False):
mjw@4668 204 """Initialise the controller. Called when the controller is
mjw@4668 205 first created, and again after the domain is rebooted (with reboot True).
mjw@4668 206 If called with recreate True (and reboot False) the controller is being
mjw@4668 207 recreated after a xend restart.
mjw@4668 208
mjw@4668 209 As this can be a re-init (after reboot) any controller state should
mjw@4668 210 be reset. For example the destroyed flag.
mjw@4668 211 """
mjw@4580 212 self.destroyed = False
mjw@4580 213 if reboot:
mjw@4580 214 self.rebootDevices()
mjw@4580 215
mjw@4580 216 def newDevice(self, id, config, recreate=False):
mjw@4580 217 """Create a device with the given config.
mjw@4580 218 Must be defined in subclass.
mjw@4668 219 Called with recreate True when the device is being recreated after a
mjw@4668 220 xend restart.
mjw@4580 221
mjw@4580 222 @return device
mjw@2332 223 """
mjw@2332 224 raise NotImplementedError()
mjw@2332 225
mjw@4580 226 def createDevice(self, config, recreate=False, change=False):
mjw@4668 227 """Create a device and attach to its front- and back-ends.
mjw@4668 228 If recreate is true the device is being recreated after a xend restart.
mjw@4668 229 If change is true the device is a change to an existing domain,
mjw@4668 230 i.e. it is being added at runtime rather than when the domain is created.
mjw@4668 231 """
cl349@5338 232 # skanky hack: we use the device ids to maybe find the savedinfo
cl349@5338 233 # of the device...
cl349@5338 234 id = self.nextDeviceId()
cl349@5338 235 if recreate:
cl349@5338 236 recreate = self.vm.get_device_savedinfo(self.getType(), id)
cl349@5338 237 dev = self.newDevice(id, config, recreate=recreate)
mjw@4580 238 dev.init(recreate=recreate)
mjw@4580 239 self.addDevice(dev)
mjw@4580 240 dev.attach(recreate=recreate, change=change)
mjw@4580 241
mjw@4580 242 def configureDevice(self, id, config, change=False):
mjw@4580 243 """Reconfigure an existing device.
mjw@4580 244 May be defined in subclass."""
cl349@5338 245 dev = self.getDevice(id, error=True)
mjw@4580 246 dev.configure(config, change=change)
mjw@2267 247
mjw@4580 248 def destroyDevice(self, id, change=False, reboot=False):
mjw@4580 249 """Destroy a device.
mjw@4668 250 May be defined in subclass.
mjw@4668 251
mjw@4668 252 If reboot is true the device is being destroyed for a domain reboot.
mjw@4668 253
mjw@4668 254 The device is not deleted, since it may be recreated later.
mjw@4668 255 """
cl349@5338 256 dev = self.getDevice(id, error=True)
mjw@4580 257 dev.destroy(change=change, reboot=reboot)
mjw@4580 258 return dev
mjw@4580 259
mjw@4580 260 def deleteDevice(self, id, change=True):
mjw@4668 261 """Destroy a device and delete it.
mjw@4668 262 Normally called to remove a device from a domain at runtime.
mjw@4668 263 """
mjw@4580 264 dev = self.destroyDevice(id, change=change)
mjw@4580 265 self.removeDevice(dev)
mjw@4580 266
mjw@4580 267 def destroyController(self, reboot=False):
mjw@4580 268 """Destroy all devices and clean up.
mjw@4668 269 May be defined in subclass.
mjw@4668 270 If reboot is true the controller is being destroyed for a domain reboot.
mjw@4668 271 Called at domain shutdown.
mjw@4668 272 """
mjw@4580 273 self.destroyed = True
mjw@4580 274 self.destroyDevices(reboot=reboot)
mjw@4580 275
mjw@4580 276 #----------------------------------------------------------------------------
mjw@4580 277
mjw@4580 278 def isDestroyed(self):
mjw@4580 279 return self.destroyed
mjw@4580 280
cl349@5338 281 def getDevice(self, id, error=False):
cl349@5338 282 dev = self.devices.get(id)
cl349@5338 283 if error and not dev:
cl349@5338 284 raise XendError("invalid device id: " + id)
cl349@5338 285 return dev
mjw@4580 286
mjw@4580 287 def getDeviceIds(self):
mjw@4580 288 return [ dev.getId() for dev in self.device_order ]
mjw@4580 289
mjw@4580 290 def getDevices(self):
mjw@4580 291 return self.device_order
mjw@4580 292
mjw@4580 293 def getDeviceConfig(self, id):
mjw@4580 294 return self.getDevice(id).getConfig()
mjw@4580 295
mjw@4580 296 def getDeviceConfigs(self):
mjw@4580 297 return [ dev.getConfig() for dev in self.device_order ]
mjw@4580 298
mjw@4580 299 def getDeviceSxprs(self):
mjw@4580 300 return [ dev.sxpr() for dev in self.device_order ]
mjw@4580 301
mjw@4580 302 def addDevice(self, dev):
mjw@4580 303 self.devices[dev.getId()] = dev
mjw@4580 304 self.device_order.append(dev)
mjw@4580 305 return dev
mjw@4580 306
mjw@4580 307 def removeDevice(self, dev):
mjw@4580 308 if dev.getId() in self.devices:
mjw@4580 309 del self.devices[dev.getId()]
mjw@4580 310 if dev in self.device_order:
mjw@4580 311 self.device_order.remove(dev)
mjw@4580 312
mjw@4580 313 def rebootDevices(self):
mjw@4580 314 for dev in self.getDevices():
mjw@4580 315 dev.reboot()
mjw@4580 316
mjw@4580 317 def destroyDevices(self, reboot=False):
mjw@4580 318 """Destroy all devices.
mjw@4580 319 """
mjw@4580 320 for dev in self.getDevices():
mjw@4580 321 dev.destroy(reboot=reboot)
mjw@2225 322
mjw@4580 323 def getMaxDeviceId(self):
mjw@4580 324 maxid = 0
mjw@4580 325 for id in self.devices:
mjw@4580 326 if id > maxid:
mjw@4580 327 maxid = id
mjw@4580 328 return maxid
mjw@4580 329
mjw@4580 330 def nextDeviceId(self):
mjw@4580 331 id = self.deviceId
mjw@4580 332 self.deviceId += 1
mjw@4580 333 return id
mjw@4580 334
mjw@4580 335 def getDeviceCount(self):
mjw@4580 336 return len(self.devices)
mjw@4580 337
mjw@4580 338 class Dev:
mjw@4580 339 """Abstract class for a device attached to a device controller.
mjw@2332 340
mjw@4580 341 @ivar id: identifier
mjw@4580 342 @type id: int
mjw@4580 343 @ivar controller: device controller
mjw@4580 344 @type controller: DevController
mjw@4580 345 """
mjw@4580 346
mjw@4580 347 def __init__(self, controller, id, config, recreate=False):
mjw@4580 348 self.controller = controller
mjw@4580 349 self.id = id
mjw@4580 350 self.config = config
mjw@4580 351 self.destroyed = False
mjw@4580 352
mjw@4580 353 def getDomain(self):
mjw@4580 354 return self.controller.getDomain()
mjw@4580 355
mjw@4580 356 def getDomainName(self):
mjw@4580 357 return self.controller.getDomainName()
mjw@4580 358
mjw@4580 359 def getChannel(self):
mjw@4580 360 return self.controller.getChannel()
mjw@4580 361
mjw@4580 362 def getDomainInfo(self):
mjw@4580 363 return self.controller.getDomainInfo()
mjw@4580 364
mjw@4580 365 def getController(self):
mjw@4580 366 return self.controller
mjw@4580 367
mjw@4580 368 def getType(self):
mjw@4580 369 return self.controller.getType()
mjw@2332 370
mjw@4580 371 def getId(self):
mjw@4580 372 return self.id
mjw@4580 373
mjw@4580 374 def getConfig(self):
mjw@4580 375 return self.config
mjw@4580 376
mjw@4580 377 def isDestroyed(self):
mjw@4580 378 return self.destroyed
mjw@4580 379
mjw@4580 380 #----------------------------------------------------------------------------
mjw@4580 381 # Subclass interface.
mjw@4580 382 # Define methods in subclass as needed.
mjw@4580 383 # Redefinitions must have the same arguments.
mjw@4580 384
mjw@4580 385 def init(self, recreate=False, reboot=False):
mjw@4580 386 """Initialization. Called on initial create (when reboot is False)
mjw@4580 387 and on reboot (when reboot is True). When xend is restarting is
mjw@4580 388 called with recreate True. Define in subclass if needed.
mjw@4668 389
mjw@4668 390 Device instance variables must be defined in the class constructor,
mjw@4668 391 but given null or default values. The real values should be initialised
mjw@4668 392 in this method. This allows devices to be re-initialised.
mjw@4668 393
mjw@4668 394 Since this can be called to re-initialise a device any state flags
mjw@4668 395 should be reset.
mjw@4580 396 """
mjw@4580 397 self.destroyed = False
mjw@2332 398
mjw@4580 399 def attach(self, recreate=False, change=False):
mjw@4580 400 """Attach the device to its front and back ends.
mjw@4580 401 Define in subclass if needed.
mjw@4580 402 """
mjw@4580 403 pass
mjw@4580 404
mjw@4580 405 def reboot(self):
mjw@4668 406 """Reconnect the device when the domain is rebooted.
mjw@4580 407 """
mjw@4580 408 self.init(reboot=True)
mjw@4580 409 self.attach()
mjw@2332 410
mjw@4580 411 def sxpr(self):
mjw@4580 412 """Get the s-expression for the deivice.
mjw@4580 413 Implement in a subclass if needed.
mjw@2332 414
mjw@4580 415 @return: sxpr
mjw@4580 416 """
mjw@4580 417 return self.getConfig()
mjw@4580 418
mjw@4580 419 def configure(self, config, change=False):
mjw@4580 420 """Reconfigure the device.
mjw@4580 421
mjw@4580 422 Implement in subclass.
mjw@2332 423 """
mjw@2332 424 raise NotImplementedError()
mjw@2332 425
mjw@4580 426 def refresh(self):
mjw@4580 427 """Refresh the device..
mjw@4580 428 Default no-op. Define in subclass if needed.
mjw@2520 429 """
mjw@4580 430 pass
mjw@2185 431
mjw@4580 432 def destroy(self, change=False, reboot=False):
mjw@4580 433 """Destroy the device.
mjw@4580 434 If change is True notify destruction (runtime change).
mjw@4580 435 If reboot is True the device is being destroyed for a reboot.
mjw@4580 436 Redefine in subclass if needed.
mjw@4668 437
mjw@4668 438 Called at domain shutdown and when a device is deleted from
mjw@4668 439 a running domain (with change True).
mjw@4580 440 """
mjw@4580 441 self.destroyed = True
mjw@4580 442 pass
mjw@1654 443
mjw@4580 444 #----------------------------------------------------------------------------