xen-vtx-unstable

annotate tools/python/xen/xend/server/controller.py @ 4580:c69fbe48a357

bitkeeper revision 1.1327.2.1 (4266169fT9qqykPCJWENnvnqwf71kQ)

Refactor domain construction and device controllers to
remove use of twisted. Use threads to dispatch channel
input. Move device controllers into domains.

Signed-off-by: Mike Wray <mike.wray@hp.com>
author mjw@wray-m-3.hpl.hp.com
date Wed Apr 20 08:45:19 2005 +0000 (2005-04-20)
parents 0a4b76b6b5a0
children a838a908e38e
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
mjw@4580 7 from messages import msgTypeName, printMsg, getMessageType
mjw@1623 8
mjw@2397 9 DEBUG = 0
mjw@1677 10
mjw@4580 11 class CtrlMsgRcvr:
mjw@4580 12 """Dispatcher class for 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@4580 86 print 'CtrlMsgRcvr>lostChannel>',
mjw@4580 87 self.channel = None
mjw@1623 88
mjw@1623 89 def registerChannel(self):
mjw@1654 90 """Register interest in our major message types with the
mjw@1719 91 channel to our domain. Once we have registered, the channel
mjw@4580 92 will call requestReceived for our messages.
mjw@1654 93 """
mjw@4580 94 if DEBUG:
mjw@4580 95 print 'CtrlMsgRcvr>registerChannel>', self.channel, self.getMajorTypes()
mjw@4580 96 if self.channel:
mjw@2224 97 self.channel.registerDevice(self.getMajorTypes(), self)
mjw@1623 98
mjw@1623 99 def deregisterChannel(self):
mjw@1654 100 """Deregister interest in our major message types with the
mjw@1719 101 channel to our domain. After this the channel won't call
mjw@1719 102 us any more.
mjw@1654 103 """
mjw@1623 104 if self.channel:
mjw@1623 105 self.channel.deregisterDevice(self)
mjw@1623 106
mjw@4580 107 class DevControllerType:
mjw@4580 108 """Abstract class for device controller types.
mjw@1623 109 """
mjw@1623 110
mjw@4580 111 def __init__(self, type):
mjw@4580 112 self.type = type
mjw@1623 113
mjw@4580 114 def getType(self):
mjw@4580 115 """Get the device controller type name.
mjw@1654 116 """
mjw@4580 117 return self.type
mjw@2185 118
mjw@4580 119 def createDevController(self, vm, recreate=False):
mjw@4580 120 """Create a device controller for a domain.
mjw@4580 121 Must be implemented in subclass.
mjw@1654 122 """
mjw@1623 123 raise NotImplementedError()
mjw@1623 124
mjw@4580 125 class SimpleDevControllerType(DevControllerType):
mjw@4580 126 """Device controller type that simply wraps a controller
mjw@4580 127 class and uses its constructor to create instances.
mjw@4580 128 """
mjw@4580 129
mjw@4580 130 def __init__(self, type, devControllerClass):
mjw@4580 131 DevControllerType.__init__(self, type)
mjw@4580 132 self.devControllerClass = devControllerClass
mjw@2185 133
mjw@4580 134 def createDevController(self, vm, recreate=False):
mjw@4580 135 """Create a device controller for a domain.
mjw@4580 136 """
mjw@4580 137 ctrl = self.devControllerClass(self, vm, recreate=recreate)
mjw@4580 138 ctrl.initController(recreate=recreate)
mjw@4580 139 return ctrl
mjw@1623 140
mjw@4580 141 class DevControllerTable:
mjw@4580 142 """Table of device controller types, indexed by type name.
mjw@2332 143 """
mjw@2332 144
mjw@2332 145 def __init__(self):
mjw@4580 146 self.controllerTypes = {}
mjw@4580 147
mjw@4580 148 def getDevControllerType(self, type):
mjw@4580 149 return self.controllerTypes.get(type)
mjw@4580 150
mjw@4580 151 def addDevControllerType(self, dctype):
mjw@4580 152 self.controllerTypes[dctype.getType()] = dctype
mjw@4580 153 return dctype
mjw@2332 154
mjw@4580 155 def delDevControllerType(self, type):
mjw@4580 156 if type in self.controllerTypes:
mjw@4580 157 del self.controllerTypes[type]
mjw@2332 158
mjw@4580 159 def createDevController(self, type, vm, recreate=False):
mjw@4580 160 dctype = self.getDevControllerType(type)
mjw@4580 161 if not dctype:
mjw@4580 162 raise XendError("unknown device type: " + type)
mjw@4580 163 return dctype.createDevController(vm, recreate=recreate)
mjw@2332 164
mjw@4580 165 def getDevControllerTable():
mjw@4580 166 global devControllerTable
mjw@4580 167 try:
mjw@4580 168 devControllerTable
mjw@4580 169 except:
mjw@4580 170 devControllerTable = DevControllerTable()
mjw@4580 171 return devControllerTable
mjw@1623 172
mjw@4580 173 def addDevControllerType(dctype):
mjw@4580 174 return getDevControllerTable().addDevControllerType(dctype)
mjw@4580 175
mjw@4580 176 def addDevControllerClass(name, klass):
mjw@4580 177 ty = SimpleDevControllerType(name, klass)
mjw@4580 178 return addDevControllerType(ty)
mjw@4580 179
mjw@4580 180 def createDevController(name, vm, recreate=False):
mjw@4580 181 return getDevControllerTable().createDevController(name, vm, recreate=recreate)
mjw@4580 182
mjw@4580 183 class DevController:
mjw@4580 184 """Abstract class for a device controller attached to a domain.
mjw@4580 185 A device controller manages all the devices of a given type for a domain.
mjw@4580 186 There is exactly one device controller for each device type for
mjw@4580 187 a domain.
mjw@2332 188
mjw@4580 189 """
mjw@4580 190
mjw@4580 191 def __init__(self, dctype, vm, recreate=False):
mjw@4580 192 self.dctype = dctype
mjw@4580 193 self.destroyed = False
mjw@4580 194 self.vm = vm
mjw@4580 195 self.deviceId = 0
mjw@4580 196 self.devices = {}
mjw@4580 197 self.device_order = []
mjw@2332 198
mjw@4580 199 def getType(self):
mjw@4580 200 return self.dctype.getType()
mjw@4580 201
mjw@4580 202 def getDevControllerType(self):
mjw@4580 203 return self.dctype
mjw@2332 204
mjw@4580 205 def getDomain(self):
mjw@4580 206 return self.vm.getDomain()
mjw@4580 207
mjw@4580 208 def getDomainName(self):
mjw@4580 209 return self.vm.getName()
mjw@2332 210
mjw@4580 211 def getChannel(self):
mjw@4580 212 chan = self.vm.getChannel()
mjw@4580 213 return chan
mjw@4580 214
mjw@4580 215 def getDomainInfo(self):
mjw@4580 216 return self.vm
mjw@2332 217
mjw@4580 218 #----------------------------------------------------------------------------
mjw@4580 219 # Subclass interface.
mjw@4580 220 # Subclasses should define the unimplemented methods..
mjw@4580 221 # Redefinitions must have the same arguments.
mjw@2332 222
mjw@4580 223 def initController(self, recreate=False, reboot=False):
mjw@4580 224 self.destroyed = False
mjw@4580 225 if reboot:
mjw@4580 226 self.rebootDevices()
mjw@4580 227
mjw@4580 228 def newDevice(self, id, config, recreate=False):
mjw@4580 229 """Create a device with the given config.
mjw@4580 230 Must be defined in subclass.
mjw@4580 231
mjw@4580 232 @return device
mjw@2332 233 """
mjw@2332 234 raise NotImplementedError()
mjw@2332 235
mjw@4580 236 def createDevice(self, config, recreate=False, change=False):
mjw@4580 237 print 'DevController>createDevice>', 'config=', config, 'recreate=', recreate, 'change=', change
mjw@4580 238 dev = self.newDevice(self.nextDeviceId(), config, recreate=recreate)
mjw@4580 239 dev.init(recreate=recreate)
mjw@4580 240 self.addDevice(dev)
mjw@4580 241 idx = self.getDeviceIndex(dev)
mjw@4580 242 recreate = self.vm.get_device_recreate(self.getType(), idx)
mjw@4580 243 dev.attach(recreate=recreate, change=change)
mjw@4580 244 print 'DevController>createDevice<'
mjw@4580 245
mjw@4580 246 def configureDevice(self, id, config, change=False):
mjw@4580 247 """Reconfigure an existing device.
mjw@4580 248 May be defined in subclass."""
mjw@4580 249 dev = self.getDevice(id)
mjw@4580 250 if not dev:
mjw@4580 251 raise XendError("invalid device id: " + id)
mjw@4580 252 dev.configure(config, change=change)
mjw@2267 253
mjw@4580 254 def destroyDevice(self, id, change=False, reboot=False):
mjw@4580 255 """Destroy a device.
mjw@4580 256 May be defined in subclass."""
mjw@4580 257 dev = self.getDevice(id)
mjw@4580 258 if not dev:
mjw@4580 259 raise XendError("invalid device id: " + id)
mjw@4580 260 dev.destroy(change=change, reboot=reboot)
mjw@4580 261 return dev
mjw@4580 262
mjw@4580 263 def deleteDevice(self, id, change=True):
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@4580 269 May be defined in subclass."""
mjw@4580 270 self.destroyed = True
mjw@4580 271 self.destroyDevices(reboot=reboot)
mjw@4580 272
mjw@4580 273 #----------------------------------------------------------------------------
mjw@4580 274
mjw@4580 275 def isDestroyed(self):
mjw@4580 276 return self.destroyed
mjw@4580 277
mjw@4580 278 def getDevice(self, id):
mjw@4580 279 return self.devices.get(id)
mjw@2267 280
mjw@4580 281 def getDeviceByIndex(self, idx):
mjw@4580 282 if 0 <= idx < len(self.device_order):
mjw@4580 283 return self.device_order[idx]
mjw@4580 284 else:
mjw@4580 285 return None
mjw@4580 286
mjw@4580 287 def getDeviceIndex(self, dev):
mjw@4580 288 return self.device_order.index(dev)
mjw@4580 289
mjw@4580 290 def getDeviceIds(self):
mjw@4580 291 return [ dev.getId() for dev in self.device_order ]
mjw@4580 292
mjw@4580 293 def getDevices(self):
mjw@4580 294 return self.device_order
mjw@4580 295
mjw@4580 296 def getDeviceConfig(self, id):
mjw@4580 297 return self.getDevice(id).getConfig()
mjw@4580 298
mjw@4580 299 def getDeviceConfigs(self):
mjw@4580 300 return [ dev.getConfig() for dev in self.device_order ]
mjw@4580 301
mjw@4580 302 def getDeviceSxprs(self):
mjw@4580 303 return [ dev.sxpr() for dev in self.device_order ]
mjw@4580 304
mjw@4580 305 def addDevice(self, dev):
mjw@4580 306 self.devices[dev.getId()] = dev
mjw@4580 307 self.device_order.append(dev)
mjw@4580 308 return dev
mjw@4580 309
mjw@4580 310 def removeDevice(self, dev):
mjw@4580 311 if dev.getId() in self.devices:
mjw@4580 312 del self.devices[dev.getId()]
mjw@4580 313 if dev in self.device_order:
mjw@4580 314 self.device_order.remove(dev)
mjw@4580 315
mjw@4580 316 def rebootDevices(self):
mjw@4580 317 print 'DevController>rebootDevices>', self
mjw@4580 318 for dev in self.getDevices():
mjw@4580 319 dev.reboot()
mjw@4580 320
mjw@4580 321 def destroyDevices(self, reboot=False):
mjw@4580 322 """Destroy all devices.
mjw@4580 323 """
mjw@4580 324 for dev in self.getDevices():
mjw@4580 325 dev.destroy(reboot=reboot)
mjw@2225 326
mjw@4580 327 def getMaxDeviceId(self):
mjw@4580 328 maxid = 0
mjw@4580 329 for id in self.devices:
mjw@4580 330 if id > maxid:
mjw@4580 331 maxid = id
mjw@4580 332 return maxid
mjw@4580 333
mjw@4580 334 def nextDeviceId(self):
mjw@4580 335 id = self.deviceId
mjw@4580 336 self.deviceId += 1
mjw@4580 337 return id
mjw@4580 338
mjw@4580 339 def getDeviceCount(self):
mjw@4580 340 return len(self.devices)
mjw@4580 341
mjw@4580 342 class Dev:
mjw@4580 343 """Abstract class for a device attached to a device controller.
mjw@2332 344
mjw@4580 345 @ivar id: identifier
mjw@4580 346 @type id: int
mjw@4580 347 @ivar controller: device controller
mjw@4580 348 @type controller: DevController
mjw@4580 349 """
mjw@4580 350
mjw@4580 351 def __init__(self, controller, id, config, recreate=False):
mjw@4580 352 self.controller = controller
mjw@4580 353 self.id = id
mjw@4580 354 self.config = config
mjw@4580 355 self.destroyed = False
mjw@4580 356
mjw@4580 357 def getDomain(self):
mjw@4580 358 return self.controller.getDomain()
mjw@4580 359
mjw@4580 360 def getDomainName(self):
mjw@4580 361 return self.controller.getDomainName()
mjw@4580 362
mjw@4580 363 def getChannel(self):
mjw@4580 364 return self.controller.getChannel()
mjw@4580 365
mjw@4580 366 def getDomainInfo(self):
mjw@4580 367 return self.controller.getDomainInfo()
mjw@4580 368
mjw@4580 369 def getController(self):
mjw@4580 370 return self.controller
mjw@4580 371
mjw@4580 372 def getType(self):
mjw@4580 373 return self.controller.getType()
mjw@2332 374
mjw@4580 375 def getId(self):
mjw@4580 376 return self.id
mjw@4580 377
mjw@4580 378 def getIndex(self):
mjw@4580 379 return self.controller.getDeviceIndex(self)
mjw@4580 380
mjw@4580 381 def getConfig(self):
mjw@4580 382 return self.config
mjw@4580 383
mjw@4580 384 def isDestroyed(self):
mjw@4580 385 return self.destroyed
mjw@4580 386
mjw@4580 387 #----------------------------------------------------------------------------
mjw@4580 388 # Subclass interface.
mjw@4580 389 # Define methods in subclass as needed.
mjw@4580 390 # Redefinitions must have the same arguments.
mjw@4580 391
mjw@4580 392 def init(self, recreate=False, reboot=False):
mjw@4580 393 """Initialization. Called on initial create (when reboot is False)
mjw@4580 394 and on reboot (when reboot is True). When xend is restarting is
mjw@4580 395 called with recreate True. Define in subclass if needed.
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@4580 406 """Reconnect device when the domain is rebooted.
mjw@4580 407 """
mjw@4580 408 print 'Dev>reboot>', self
mjw@4580 409 self.init(reboot=True)
mjw@4580 410 self.attach()
mjw@2332 411
mjw@4580 412 def sxpr(self):
mjw@4580 413 """Get the s-expression for the deivice.
mjw@4580 414 Implement in a subclass if needed.
mjw@2332 415
mjw@4580 416 @return: sxpr
mjw@4580 417 """
mjw@4580 418 return self.getConfig()
mjw@4580 419
mjw@4580 420 def configure(self, config, change=False):
mjw@4580 421 """Reconfigure the device.
mjw@4580 422
mjw@4580 423 Implement in subclass.
mjw@2332 424 """
mjw@2332 425 raise NotImplementedError()
mjw@2332 426
mjw@4580 427 def refresh(self):
mjw@4580 428 """Refresh the device..
mjw@4580 429 Default no-op. Define in subclass if needed.
mjw@2520 430 """
mjw@4580 431 pass
mjw@2185 432
mjw@4580 433 def destroy(self, change=False, reboot=False):
mjw@4580 434 """Destroy the device.
mjw@4580 435 If change is True notify destruction (runtime change).
mjw@4580 436 If reboot is True the device is being destroyed for a reboot.
mjw@4580 437 Redefine in subclass if needed.
mjw@4580 438 """
mjw@4580 439 self.destroyed = True
mjw@4580 440 pass
mjw@1654 441
mjw@4580 442 #----------------------------------------------------------------------------