xen-vtx-unstable

annotate tools/python/xen/xend/server/controller.py @ 4668:369e382b2f81

bitkeeper revision 1.1327.2.9 (426f9bfcIjY9QAFCPqWBbFw35vclow)

Add support for unix-domain sockets on xend.
Remove some dead code.
Signed-off-by: Mike Wray <mike.wray@hp.com>
author mjw@wray-m-3.hpl.hp.com
date Wed Apr 27 14:04:44 2005 +0000 (2005-04-27)
parents a838a908e38e
children 16efdf7bbd57
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@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
mjw@4668 118 def addDevControllerClass(self, klass):
mjw@4668 119 self.controllerClasses[klass.getType()] = klass
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):
mjw@4668 126 klass = self.getDevControllerClass(type)
mjw@4668 127 if not klass:
mjw@4580 128 raise XendError("unknown device type: " + type)
mjw@4668 129 return klass.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
mjw@4580 141 def addDevControllerClass(name, klass):
mjw@4668 142 """Add a device controller class to the controller table.
mjw@4668 143 """
mjw@4668 144 klass.name = name
mjw@4668 145 getDevControllerTable().addDevControllerClass(klass)
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
mjw@4668 158 name = None
mjw@4668 159
mjw@4668 160 def createDevController(klass, vm, recreate=False):
mjw@4668 161 """Class method to create a dev controller.
mjw@4668 162 """
mjw@4668 163 ctrl = klass(vm, recreate=recreate)
mjw@4668 164 ctrl.initController(recreate=recreate)
mjw@4668 165 return ctrl
mjw@4668 166
mjw@4668 167 createDevController = classmethod(createDevController)
mjw@4668 168
mjw@4668 169 def getType(klass):
mjw@4668 170 return klass.name
mjw@4668 171
mjw@4668 172 getType = classmethod(getType)
mjw@4668 173
mjw@4668 174 def __init__(self, vm, recreate=False):
mjw@4580 175 self.destroyed = False
mjw@4580 176 self.vm = vm
mjw@4580 177 self.deviceId = 0
mjw@4580 178 self.devices = {}
mjw@4580 179 self.device_order = []
mjw@2332 180
mjw@4580 181 def getDevControllerType(self):
mjw@4580 182 return self.dctype
mjw@2332 183
mjw@4580 184 def getDomain(self):
mjw@4580 185 return self.vm.getDomain()
mjw@4580 186
mjw@4580 187 def getDomainName(self):
mjw@4580 188 return self.vm.getName()
mjw@2332 189
mjw@4580 190 def getChannel(self):
mjw@4580 191 chan = self.vm.getChannel()
mjw@4580 192 return chan
mjw@4580 193
mjw@4580 194 def getDomainInfo(self):
mjw@4580 195 return self.vm
mjw@2332 196
mjw@4580 197 #----------------------------------------------------------------------------
mjw@4580 198 # Subclass interface.
mjw@4580 199 # Subclasses should define the unimplemented methods..
mjw@4580 200 # Redefinitions must have the same arguments.
mjw@2332 201
mjw@4580 202 def initController(self, recreate=False, reboot=False):
mjw@4668 203 """Initialise the controller. Called when the controller is
mjw@4668 204 first created, and again after the domain is rebooted (with reboot True).
mjw@4668 205 If called with recreate True (and reboot False) the controller is being
mjw@4668 206 recreated after a xend restart.
mjw@4668 207
mjw@4668 208 As this can be a re-init (after reboot) any controller state should
mjw@4668 209 be reset. For example the destroyed flag.
mjw@4668 210 """
mjw@4580 211 self.destroyed = False
mjw@4580 212 if reboot:
mjw@4580 213 self.rebootDevices()
mjw@4580 214
mjw@4580 215 def newDevice(self, id, config, recreate=False):
mjw@4580 216 """Create a device with the given config.
mjw@4580 217 Must be defined in subclass.
mjw@4668 218 Called with recreate True when the device is being recreated after a
mjw@4668 219 xend restart.
mjw@4580 220
mjw@4580 221 @return device
mjw@2332 222 """
mjw@2332 223 raise NotImplementedError()
mjw@2332 224
mjw@4580 225 def createDevice(self, config, recreate=False, change=False):
mjw@4668 226 """Create a device and attach to its front- and back-ends.
mjw@4668 227 If recreate is true the device is being recreated after a xend restart.
mjw@4668 228 If change is true the device is a change to an existing domain,
mjw@4668 229 i.e. it is being added at runtime rather than when the domain is created.
mjw@4668 230 """
mjw@4580 231 dev = self.newDevice(self.nextDeviceId(), config, recreate=recreate)
mjw@4580 232 dev.init(recreate=recreate)
mjw@4580 233 self.addDevice(dev)
mjw@4580 234 idx = self.getDeviceIndex(dev)
mjw@4580 235 recreate = self.vm.get_device_recreate(self.getType(), idx)
mjw@4580 236 dev.attach(recreate=recreate, change=change)
mjw@4580 237
mjw@4580 238 def configureDevice(self, id, config, change=False):
mjw@4580 239 """Reconfigure an existing device.
mjw@4580 240 May be defined in subclass."""
mjw@4580 241 dev = self.getDevice(id)
mjw@4580 242 if not dev:
mjw@4580 243 raise XendError("invalid device id: " + id)
mjw@4580 244 dev.configure(config, change=change)
mjw@2267 245
mjw@4580 246 def destroyDevice(self, id, change=False, reboot=False):
mjw@4580 247 """Destroy a device.
mjw@4668 248 May be defined in subclass.
mjw@4668 249
mjw@4668 250 If reboot is true the device is being destroyed for a domain reboot.
mjw@4668 251
mjw@4668 252 The device is not deleted, since it may be recreated later.
mjw@4668 253 """
mjw@4580 254 dev = self.getDevice(id)
mjw@4580 255 if not dev:
mjw@4580 256 raise XendError("invalid device id: " + id)
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
mjw@4580 281 def getDevice(self, id):
mjw@4580 282 return self.devices.get(id)
mjw@2267 283
mjw@4580 284 def getDeviceByIndex(self, idx):
mjw@4580 285 if 0 <= idx < len(self.device_order):
mjw@4580 286 return self.device_order[idx]
mjw@4580 287 else:
mjw@4580 288 return None
mjw@4580 289
mjw@4580 290 def getDeviceIndex(self, dev):
mjw@4580 291 return self.device_order.index(dev)
mjw@4580 292
mjw@4580 293 def getDeviceIds(self):
mjw@4580 294 return [ dev.getId() for dev in self.device_order ]
mjw@4580 295
mjw@4617 296 def getDeviceIndexes(self):
mjw@4617 297 return range(0, len(self.device_order))
mjw@4617 298
mjw@4580 299 def getDevices(self):
mjw@4580 300 return self.device_order
mjw@4580 301
mjw@4580 302 def getDeviceConfig(self, id):
mjw@4580 303 return self.getDevice(id).getConfig()
mjw@4580 304
mjw@4580 305 def getDeviceConfigs(self):
mjw@4580 306 return [ dev.getConfig() for dev in self.device_order ]
mjw@4580 307
mjw@4580 308 def getDeviceSxprs(self):
mjw@4580 309 return [ dev.sxpr() for dev in self.device_order ]
mjw@4580 310
mjw@4580 311 def addDevice(self, dev):
mjw@4580 312 self.devices[dev.getId()] = dev
mjw@4580 313 self.device_order.append(dev)
mjw@4580 314 return dev
mjw@4580 315
mjw@4580 316 def removeDevice(self, dev):
mjw@4580 317 if dev.getId() in self.devices:
mjw@4580 318 del self.devices[dev.getId()]
mjw@4580 319 if dev in self.device_order:
mjw@4580 320 self.device_order.remove(dev)
mjw@4580 321
mjw@4580 322 def rebootDevices(self):
mjw@4580 323 for dev in self.getDevices():
mjw@4580 324 dev.reboot()
mjw@4580 325
mjw@4580 326 def destroyDevices(self, reboot=False):
mjw@4580 327 """Destroy all devices.
mjw@4580 328 """
mjw@4580 329 for dev in self.getDevices():
mjw@4580 330 dev.destroy(reboot=reboot)
mjw@2225 331
mjw@4580 332 def getMaxDeviceId(self):
mjw@4580 333 maxid = 0
mjw@4580 334 for id in self.devices:
mjw@4580 335 if id > maxid:
mjw@4580 336 maxid = id
mjw@4580 337 return maxid
mjw@4580 338
mjw@4580 339 def nextDeviceId(self):
mjw@4580 340 id = self.deviceId
mjw@4580 341 self.deviceId += 1
mjw@4580 342 return id
mjw@4580 343
mjw@4580 344 def getDeviceCount(self):
mjw@4580 345 return len(self.devices)
mjw@4580 346
mjw@4580 347 class Dev:
mjw@4580 348 """Abstract class for a device attached to a device controller.
mjw@2332 349
mjw@4580 350 @ivar id: identifier
mjw@4580 351 @type id: int
mjw@4580 352 @ivar controller: device controller
mjw@4580 353 @type controller: DevController
mjw@4580 354 """
mjw@4580 355
mjw@4580 356 def __init__(self, controller, id, config, recreate=False):
mjw@4580 357 self.controller = controller
mjw@4580 358 self.id = id
mjw@4580 359 self.config = config
mjw@4580 360 self.destroyed = False
mjw@4580 361
mjw@4580 362 def getDomain(self):
mjw@4580 363 return self.controller.getDomain()
mjw@4580 364
mjw@4580 365 def getDomainName(self):
mjw@4580 366 return self.controller.getDomainName()
mjw@4580 367
mjw@4580 368 def getChannel(self):
mjw@4580 369 return self.controller.getChannel()
mjw@4580 370
mjw@4580 371 def getDomainInfo(self):
mjw@4580 372 return self.controller.getDomainInfo()
mjw@4580 373
mjw@4580 374 def getController(self):
mjw@4580 375 return self.controller
mjw@4580 376
mjw@4580 377 def getType(self):
mjw@4580 378 return self.controller.getType()
mjw@2332 379
mjw@4580 380 def getId(self):
mjw@4580 381 return self.id
mjw@4580 382
mjw@4580 383 def getIndex(self):
mjw@4580 384 return self.controller.getDeviceIndex(self)
mjw@4580 385
mjw@4580 386 def getConfig(self):
mjw@4580 387 return self.config
mjw@4580 388
mjw@4580 389 def isDestroyed(self):
mjw@4580 390 return self.destroyed
mjw@4580 391
mjw@4580 392 #----------------------------------------------------------------------------
mjw@4580 393 # Subclass interface.
mjw@4580 394 # Define methods in subclass as needed.
mjw@4580 395 # Redefinitions must have the same arguments.
mjw@4580 396
mjw@4580 397 def init(self, recreate=False, reboot=False):
mjw@4580 398 """Initialization. Called on initial create (when reboot is False)
mjw@4580 399 and on reboot (when reboot is True). When xend is restarting is
mjw@4580 400 called with recreate True. Define in subclass if needed.
mjw@4668 401
mjw@4668 402 Device instance variables must be defined in the class constructor,
mjw@4668 403 but given null or default values. The real values should be initialised
mjw@4668 404 in this method. This allows devices to be re-initialised.
mjw@4668 405
mjw@4668 406 Since this can be called to re-initialise a device any state flags
mjw@4668 407 should be reset.
mjw@4580 408 """
mjw@4580 409 self.destroyed = False
mjw@2332 410
mjw@4580 411 def attach(self, recreate=False, change=False):
mjw@4580 412 """Attach the device to its front and back ends.
mjw@4580 413 Define in subclass if needed.
mjw@4580 414 """
mjw@4580 415 pass
mjw@4580 416
mjw@4580 417 def reboot(self):
mjw@4668 418 """Reconnect the device when the domain is rebooted.
mjw@4580 419 """
mjw@4580 420 self.init(reboot=True)
mjw@4580 421 self.attach()
mjw@2332 422
mjw@4580 423 def sxpr(self):
mjw@4580 424 """Get the s-expression for the deivice.
mjw@4580 425 Implement in a subclass if needed.
mjw@2332 426
mjw@4580 427 @return: sxpr
mjw@4580 428 """
mjw@4580 429 return self.getConfig()
mjw@4580 430
mjw@4580 431 def configure(self, config, change=False):
mjw@4580 432 """Reconfigure the device.
mjw@4580 433
mjw@4580 434 Implement in subclass.
mjw@2332 435 """
mjw@2332 436 raise NotImplementedError()
mjw@2332 437
mjw@4580 438 def refresh(self):
mjw@4580 439 """Refresh the device..
mjw@4580 440 Default no-op. Define in subclass if needed.
mjw@2520 441 """
mjw@4580 442 pass
mjw@2185 443
mjw@4580 444 def destroy(self, change=False, reboot=False):
mjw@4580 445 """Destroy the device.
mjw@4580 446 If change is True notify destruction (runtime change).
mjw@4580 447 If reboot is True the device is being destroyed for a reboot.
mjw@4580 448 Redefine in subclass if needed.
mjw@4668 449
mjw@4668 450 Called at domain shutdown and when a device is deleted from
mjw@4668 451 a running domain (with change True).
mjw@4580 452 """
mjw@4580 453 self.destroyed = True
mjw@4580 454 pass
mjw@1654 455
mjw@4580 456 #----------------------------------------------------------------------------