xen-vtx-unstable

annotate tools/python/xen/xend/server/controller.py @ 2332:df63447093dc

bitkeeper revision 1.1159.50.1 (4129e2eeyO6KrwYWOMXPMAjegVEpTA)

Restructure code dealing with backends to use a backend controller
and separate backend interfaces on each front-end domain.
author mjw@wray-m-3.hpl.hp.com
date Mon Aug 23 12:28:30 2004 +0000 (2004-08-23)
parents a6d73a771367
children fc11d71ea64d
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@1623 6 from twisted.internet import defer
mjw@1721 7 #defer.Deferred.debug = 1
mjw@1623 8
mjw@1623 9 import channel
mjw@1719 10 from messages import msgTypeName, printMsg
mjw@1623 11
mjw@2224 12 DEBUG = 1
mjw@1677 13
mjw@1677 14 class Responder:
mjw@1719 15 """Handler for a response to a message with a specified id.
mjw@1677 16 """
mjw@1677 17
mjw@1677 18 def __init__(self, mid, deferred):
mjw@1677 19 """Create a responder.
mjw@1677 20
mjw@1719 21 @param mid: message id of response to handle
mjw@1719 22 @type mid: int
mjw@1719 23 @param deferred: deferred object holding the callbacks
mjw@1719 24 @type deferred: Deferred
mjw@1677 25 """
mjw@1677 26 self.mid = mid
mjw@1677 27 self.deferred = deferred
mjw@1677 28
mjw@1677 29 def responseReceived(self, msg):
mjw@1719 30 """Entry point called when a response message with the right id arrives.
mjw@1719 31 Calls callback on I{self.deferred} with the message.
mjw@1719 32
mjw@1719 33 @param msg: response message
mjw@1719 34 @type msg: xu message
mjw@1719 35 """
mjw@1677 36 if self.deferred.called: return
mjw@1677 37 self.deferred.callback(msg)
mjw@1677 38
mjw@1677 39 def error(self, err):
mjw@1719 40 """Entry point called when there has been an error.
mjw@1719 41 Calls errback on I{self.deferred} with the error.
mjw@1719 42
mjw@1719 43 @param err: error
mjw@1719 44 @type err: Exception
mjw@1719 45 """
mjw@1677 46 if self.deferred.called: return
mjw@1677 47 self.deferred.errback(err)
mjw@1677 48
mjw@1623 49 class CtrlMsgRcvr:
mjw@1623 50 """Abstract class for things that deal with a control interface to a domain.
mjw@1719 51 Once I{registerChannel} has been called, our message types are registered
mjw@1719 52 with the channel to the domain. The channel will call I{requestReceived}
mjw@1719 53 when a request arrives, or I{responseReceived} when a response arrives,
mjw@1719 54 if they have one of our message types.
mjw@1654 55
mjw@1719 56 @ivar dom: the domain we are a control interface for
mjw@1719 57 @type dom: int
mjw@1719 58 @ivar majorTypes: major message types we are interested in
mjw@2224 59 @type majorTypes: {int:{int:method}}
mjw@1719 60 @ivar timeout: timeout (in seconds) for message handlers
mjw@1719 61 @type timeout: int
mjw@1654 62
mjw@1719 63 @ivar channel: channel to the domain
mjw@1719 64 @type channel: Channel
mjw@1719 65 @ivar idx: channel index
mjw@1719 66 @ivar idx: string
mjw@1719 67 @ivar responders: table of message response handlers
mjw@1719 68 @type responders: {int:Responder}
mjw@1623 69 """
mjw@1623 70
mjw@1623 71 def __init__(self):
mjw@1623 72 self.channelFactory = channel.channelFactory()
mjw@2224 73 self.majorTypes = {}
mjw@1623 74 self.dom = None
mjw@1623 75 self.channel = None
mjw@1623 76 self.idx = None
mjw@1728 77 self.responders = {}
mjw@1677 78 self.timeout = 10
mjw@1677 79
mjw@1677 80 def setTimeout(self, timeout):
mjw@1677 81 self.timeout = timeout
mjw@1623 82
mjw@2224 83 def getMethod(self, type, subtype):
mjw@2224 84 """Get the method for a type and subtype.
mjw@2224 85
mjw@2224 86 @param type: major message type
mjw@2224 87 @param subtype: minor message type
mjw@2224 88 @return: method or None
mjw@2224 89 """
mjw@2224 90 method = None
mjw@2224 91 subtypes = self.majorTypes.get(type)
mjw@2224 92 if subtypes:
mjw@2224 93 method = subtypes.get(subtype)
mjw@2224 94 return method
mjw@2224 95
mjw@2224 96 def addMethod(self, type, subtype, method):
mjw@2224 97 """Add a method to handle a message type and subtype.
mjw@2224 98
mjw@2224 99 @param type: major message type
mjw@2224 100 @param subtype: minor message type
mjw@2224 101 @param method: method
mjw@2224 102 """
mjw@2224 103 subtypes = self.majorTypes.get(type)
mjw@2224 104 if not subtypes:
mjw@2224 105 subtypes = {}
mjw@2224 106 self.majorTypes[type] = subtypes
mjw@2224 107 subtypes[subtype] = method
mjw@2224 108
mjw@2224 109 def getMajorTypes(self):
mjw@2224 110 """Get the list of major message types handled.
mjw@2224 111 """
mjw@2224 112 return self.majorTypes.keys()
mjw@2224 113
mjw@1623 114 def requestReceived(self, msg, type, subtype):
mjw@1719 115 """Dispatch a request message to handlers.
mjw@1719 116 Called by the channel for requests with one of our types.
mjw@1654 117
mjw@1719 118 @param msg: message
mjw@1719 119 @type msg: xu message
mjw@1719 120 @param type: major message type
mjw@1719 121 @type type: int
mjw@1719 122 @param subtype: minor message type
mjw@1719 123 @type subtype: int
mjw@1654 124 """
mjw@1677 125 if DEBUG:
mjw@1719 126 print 'requestReceived>',
mjw@1719 127 printMsg(msg, all=1)
mjw@2265 128 responded = 0
mjw@2224 129 method = self.getMethod(type, subtype)
mjw@1623 130 if method:
mjw@2265 131 responded = method(msg, 1)
mjw@1677 132 elif DEBUG:
mjw@1623 133 print ('requestReceived> No handler: Message type %s %d:%d'
mjw@1623 134 % (msgTypeName(type, subtype), type, subtype)), self
mjw@2265 135 return responded
mjw@1623 136
mjw@1623 137 def responseReceived(self, msg, type, subtype):
mjw@1654 138 """Dispatch a response to handlers.
mjw@1719 139 Called by the channel for responses with one of our types.
mjw@1719 140
mjw@1719 141 First looks for a message responder for the message's id.
mjw@1719 142 See L{callResponders}, L{addResponder}.
mjw@1719 143 If there is no responder, looks for a message handler for
mjw@1719 144 the message type/subtype.
mjw@1654 145
mjw@1719 146 @param msg: message
mjw@1719 147 @type msg: xu message
mjw@1719 148 @param type: major message type
mjw@1719 149 @type type: int
mjw@1719 150 @param subtype: minor message type
mjw@1719 151 @type subtype: int
mjw@1654 152 """
mjw@1677 153 if DEBUG:
mjw@1719 154 print 'responseReceived>',
mjw@1719 155 printMsg(msg, all=1)
mjw@1677 156 if self.callResponders(msg):
mjw@1677 157 return
mjw@2224 158 method = self.getMethod(type, subtype)
mjw@1623 159 if method:
mjw@1623 160 method(msg, 0)
mjw@1677 161 elif DEBUG:
mjw@1623 162 print ('responseReceived> No handler: Message type %s %d:%d'
mjw@1623 163 % (msgTypeName(type, subtype), type, subtype)), self
mjw@1623 164
mjw@1677 165 def addResponder(self, mid, deferred):
mjw@1677 166 """Add a responder for a message id.
mjw@1719 167 The I{deferred} is called with callback(msg) when a response
mjw@1728 168 with message id I{mid} arrives.
mjw@1677 169
mjw@1719 170 Responders have a timeout set and I{deferred} will error
mjw@1719 171 on expiry.
mjw@1677 172
mjw@1719 173 @param mid: message id of response expected
mjw@1719 174 @type mid: int
mjw@1719 175 @param deferred: handler for the response
mjw@1719 176 @type deferred: Deferred
mjw@1719 177 @return: responder
mjw@1719 178 @rtype: Responder
mjw@1677 179 """
mjw@1728 180 resp = Responder(mid, deferred)
mjw@1728 181 self.responders[resp.mid] = resp
mjw@1677 182 if self.timeout > 0:
mjw@1677 183 deferred.setTimeout(self.timeout)
mjw@1677 184 return resp
mjw@1677 185
mjw@1677 186 def callResponders(self, msg):
mjw@1677 187 """Call any waiting responders for a response message.
mjw@1719 188 Looks for a responder registered for the message's id.
mjw@1719 189 See L{addResponder}.
mjw@1677 190
mjw@1719 191 @param msg: response message
mjw@1719 192 @type msg: xu message
mjw@1719 193 @return: 1 if there was a responder for the message, 0 otherwise
mjw@1719 194 @rtype : bool
mjw@1677 195 """
mjw@1677 196 hdr = msg.get_header()
mjw@1677 197 mid = hdr['id']
mjw@1677 198 handled = 0
mjw@1728 199 resp = self.responders.get(mid)
mjw@1728 200 if resp:
mjw@1728 201 handled = 1
mjw@1728 202 resp.responseReceived(msg)
mjw@1728 203 del self.responders[mid]
mjw@1728 204 # Clean up called responders.
mjw@1728 205 for resp in self.responders.values():
mjw@1728 206 if resp.deferred.called:
mjw@1728 207 del self.responders[resp.mid]
mjw@1677 208 return handled
mjw@1677 209
mjw@1623 210 def lostChannel(self):
mjw@1654 211 """Called when the channel to the domain is lost.
mjw@1654 212 """
mjw@1623 213 pass
mjw@1623 214
mjw@1623 215 def registerChannel(self):
mjw@1654 216 """Register interest in our major message types with the
mjw@1719 217 channel to our domain. Once we have registered, the channel
mjw@1719 218 will call requestReceived or responseReceived for our messages.
mjw@1654 219 """
mjw@1623 220 self.channel = self.channelFactory.domChannel(self.dom)
mjw@1623 221 self.idx = self.channel.getIndex()
mjw@1623 222 if self.majorTypes:
mjw@2224 223 self.channel.registerDevice(self.getMajorTypes(), self)
mjw@1623 224
mjw@1623 225 def deregisterChannel(self):
mjw@1654 226 """Deregister interest in our major message types with the
mjw@1719 227 channel to our domain. After this the channel won't call
mjw@1719 228 us any more.
mjw@1654 229 """
mjw@1623 230 if self.channel:
mjw@1623 231 self.channel.deregisterDevice(self)
mjw@1893 232 self.channel = None
mjw@1623 233
mjw@1623 234 def produceRequests(self):
mjw@1654 235 """Produce any queued requests.
mjw@1654 236
mjw@1719 237 @return: number produced
mjw@1719 238 @rtype: int
mjw@1654 239 """
mjw@1623 240 return 0
mjw@1623 241
mjw@1677 242 def writeRequest(self, msg, response=None):
mjw@1654 243 """Write a request to the channel.
mjw@1677 244
mjw@1719 245 @param msg: request message
mjw@1719 246 @type msg: xu message
mjw@1719 247 @param response: response handler
mjw@1719 248 @type response: Deferred
mjw@1654 249 """
mjw@1623 250 if self.channel:
mjw@1719 251 if DEBUG:
mjw@1719 252 print 'CtrlMsgRcvr>writeRequest>',
mjw@1719 253 printMsg(msg, all=1)
mjw@1677 254 if response:
mjw@1677 255 self.addResponder(msg.get_header()['id'], response)
mjw@1623 256 self.channel.writeRequest(msg)
mjw@1623 257 else:
mjw@1623 258 print 'CtrlMsgRcvr>writeRequest>', 'no channel!', self
mjw@1623 259
mjw@1623 260 def writeResponse(self, msg):
mjw@1719 261 """Write a response to the channel. This acknowledges
mjw@1719 262 a request message.
mjw@1719 263
mjw@1719 264 @param msg: message
mjw@1719 265 @type msg: xu message
mjw@1654 266 """
mjw@1623 267 if self.channel:
mjw@1719 268 if DEBUG:
mjw@1719 269 print 'CtrlMsgRcvr>writeResponse>',
mjw@1719 270 printMsg(msg, all=0)
mjw@1623 271 self.channel.writeResponse(msg)
mjw@1623 272 else:
mjw@1623 273 print 'CtrlMsgRcvr>writeResponse>', 'no channel!', self
mjw@1623 274
mjw@2225 275 class ControllerFactory:
mjw@1719 276 """Abstract class for factories creating controllers for a domain.
mjw@2332 277 Maintains a table of controllers.
mjw@1654 278
mjw@2332 279 @ivar controllers: mapping of index to controller instance
mjw@2332 280 @type controllers: {String: Controller}
mjw@1719 281 @ivar dom: domain
mjw@1719 282 @type dom: int
mjw@1623 283 """
mjw@1623 284
mjw@1623 285 def __init__(self):
mjw@2332 286 self.controllers = {}
mjw@1623 287
mjw@2332 288 def addController(self, controller):
mjw@1654 289 """Add a controller instance (under its index).
mjw@1654 290 """
mjw@2332 291 self.controllers[controller.idx] = controller
mjw@1623 292
mjw@2332 293 def getControllers(self):
mjw@2332 294 """Get a list of all controllers.
mjw@1654 295 """
mjw@2332 296 return self.controllers.values()
mjw@1623 297
mjw@2332 298 def getControllerByIndex(self, idx):
mjw@2332 299 """Get a controller from its index.
mjw@1654 300 """
mjw@2332 301 return self.controllers.get(idx)
mjw@1623 302
mjw@2332 303 def getControllerByDom(self, dom):
mjw@2332 304 """Get the controller for the given domain.
mjw@2185 305
mjw@2185 306 @param dom: domain id
mjw@2185 307 @type dom: int
mjw@2185 308 @return: controller or None
mjw@1654 309 """
mjw@2332 310 for inst in self.controllers.values():
mjw@1623 311 if inst.dom == dom:
mjw@1623 312 return inst
mjw@1623 313 return None
mjw@1623 314
mjw@2332 315 def getController(self, dom):
mjw@2332 316 """Create or find the controller for a domain.
mjw@2185 317
mjw@2332 318 @param dom: domain
mjw@2332 319 @return: controller
mjw@1654 320 """
mjw@2332 321 ctrl = self.getControllerByDom(dom)
mjw@2332 322 if ctrl is None:
mjw@2332 323 ctrl = self.createController(dom)
mjw@2332 324 self.addController(ctrl)
mjw@2332 325 return ctrl
mjw@2332 326
mjw@2332 327 def createController(self, dom):
mjw@2332 328 """Create a controller. Define in a subclass.
mjw@1719 329
mjw@1719 330 @param dom: domain
mjw@1719 331 @type dom: int
mjw@2185 332 @return: controller instance
mjw@2185 333 @rtype: Controller (or subclass)
mjw@1654 334 """
mjw@1623 335 raise NotImplementedError()
mjw@1623 336
mjw@2332 337 def delController(self, controller):
mjw@2332 338 """Delete a controller instance from the table.
mjw@2332 339
mjw@2332 340 @param controller: controller instance
mjw@2332 341 """
mjw@2332 342 if controller.idx in self.controllers:
mjw@2332 343 del self.controllers[controller.idx]
mjw@2332 344
mjw@2332 345 def controllerClosed(self, controller):
mjw@2332 346 """Callback called when a controller is closed (usually by the controller).
mjw@2185 347
mjw@2332 348 @param controller: controller instance
mjw@1654 349 """
mjw@2332 350 self.delController(controller)
mjw@1623 351
mjw@1623 352 class Controller(CtrlMsgRcvr):
mjw@1623 353 """Abstract class for a device controller attached to a domain.
mjw@2185 354
mjw@2185 355 @ivar factory: controller factory
mjw@2185 356 @type factory: ControllerFactory
mjw@2185 357 @ivar dom: domain
mjw@2185 358 @type dom: int
mjw@2185 359 @ivar channel: channel to the domain
mjw@2185 360 @type channel: Channel
mjw@2185 361 @ivar idx: channel index
mjw@2185 362 @type idx: String
mjw@1623 363 """
mjw@1623 364
mjw@1623 365 def __init__(self, factory, dom):
mjw@1623 366 CtrlMsgRcvr.__init__(self)
mjw@1623 367 self.factory = factory
mjw@1623 368 self.dom = int(dom)
mjw@1623 369 self.channel = None
mjw@1623 370 self.idx = None
mjw@1623 371
mjw@1623 372 def close(self):
mjw@1654 373 """Close the controller.
mjw@1654 374 """
mjw@1623 375 self.lostChannel()
mjw@1623 376
mjw@1623 377 def lostChannel(self):
mjw@1654 378 """The controller channel has been lost.
mjw@1654 379 """
mjw@1664 380 self.deregisterChannel()
mjw@2332 381 self.factory.controllerClosed(self)
mjw@2332 382
mjw@2332 383 class SplitControllerFactory(ControllerFactory):
mjw@2332 384 """Abstract class for factories creating split controllers for a domain.
mjw@2332 385 Maintains a table of backend controllers.
mjw@2332 386 """
mjw@2332 387
mjw@2332 388 def __init__(self):
mjw@2332 389 ControllerFactory.__init__(self)
mjw@2332 390 self.backendControllers = {}
mjw@2332 391
mjw@2332 392 def getBackendControllers(self):
mjw@2332 393 return self.backendControllers.values()
mjw@2332 394
mjw@2332 395 def getBackendControllerByDomain(self, dom):
mjw@2332 396 """Get the backend controller for a domain if there is one.
mjw@2332 397
mjw@2332 398 @param dom: backend domain
mjw@2332 399 @return: backend controller
mjw@2332 400 """
mjw@2332 401 return self.backendControllers.get(dom)
mjw@2332 402
mjw@2332 403 def getBackendController(self, dom):
mjw@2332 404 """Get the backend controller for a domain, creating
mjw@2332 405 if necessary.
mjw@1623 406
mjw@2332 407 @param dom: backend domain
mjw@2332 408 @return: backend controller
mjw@2332 409 """
mjw@2332 410 b = self.getBackendControllerByDomain(dom)
mjw@2332 411 if b is None:
mjw@2332 412 b = self.createBackendController(dom)
mjw@2332 413 self.backendControllers[b.dom] = b
mjw@2332 414 return b
mjw@2332 415
mjw@2332 416 def createBackendController(self, dom):
mjw@2332 417 """Create a backend controller. Define in a subclass.
mjw@2332 418
mjw@2332 419 @param dom: backend domain
mjw@2332 420 @return: backend controller
mjw@2332 421 """
mjw@2332 422 raise NotImplementedError()
mjw@2332 423
mjw@2332 424 def delBackendController(self, ctrlr):
mjw@2332 425 """Remove a backend controller.
mjw@2332 426
mjw@2332 427 @param ctrlr: backend controller
mjw@2332 428 """
mjw@2332 429 if ctrlr.dom in self.backendControllers:
mjw@2332 430 del self.backendControllers[ctrlr.dom]
mjw@2332 431
mjw@2332 432 def backendControllerClosed(self, ctrlr):
mjw@2332 433 """Callback called when a backend is closed.
mjw@2332 434 """
mjw@2332 435 self.delBackendController(ctrlr)
mjw@2332 436
mjw@2332 437 def createBackendInterface(self, ctrl, dom, handle):
mjw@2332 438 """Create a backend interface. Define in a subclass.
mjw@2332 439
mjw@2332 440 @param ctrl: frontend controller
mjw@2332 441 @param dom: backend domain
mjw@2332 442 @return: backend interface
mjw@2332 443 """
mjw@2332 444 raise NotImplementedError()
mjw@2332 445
mjw@2332 446 class BackendController(Controller):
mjw@2267 447 """Abstract class for a backend device controller attached to a domain.
mjw@2267 448
mjw@2332 449 @ivar factory: backend controller factory
mjw@2332 450 @type factory: BackendControllerFactory
mjw@2332 451 @ivar dom: backend domain
mjw@2267 452 @type dom: int
mjw@2267 453 @ivar channel: channel to the domain
mjw@2267 454 @type channel: Channel
mjw@2267 455 """
mjw@2267 456
mjw@2225 457
mjw@2332 458 def __init__(self, factory, dom):
mjw@2267 459 CtrlMsgRcvr.__init__(self)
mjw@2332 460 self.factory = factory
mjw@2267 461 self.dom = int(dom)
mjw@2267 462 self.channel = None
mjw@2332 463 self.backendInterfaces = {}
mjw@2267 464
mjw@2267 465 def close(self):
mjw@2267 466 self.lostChannel()
mjw@2225 467
mjw@2267 468 def lostChannel(self):
mjw@2267 469 self.deregisterChannel()
mjw@2332 470 self.backend.backendClosed(self)
mjw@2332 471
mjw@2332 472 def registerInterface(self, intf):
mjw@2332 473 key = intf.getInterfaceKey()
mjw@2332 474 self.backendInterfaces[key] = intf
mjw@2332 475
mjw@2332 476 def deregisterInterface(self, intf):
mjw@2332 477 key = intf.getInterfaceKey()
mjw@2332 478 if key in self.backendInterfaces:
mjw@2332 479 del self.backendInterfaces[key]
mjw@2332 480
mjw@2332 481 def getInterface(self, dom, handle):
mjw@2332 482 key = (dom, handle)
mjw@2332 483 return self.backendInterfaces.get(key)
mjw@2332 484
mjw@2332 485
mjw@2332 486 def createBackendInterface(self, ctrl, dom, handle):
mjw@2332 487 """Create a backend interface. Define in a subclass.
mjw@2332 488
mjw@2332 489 @param ctrl: controller
mjw@2332 490 @param dom: backend domain
mjw@2332 491 @param handle: backend handle
mjw@2332 492 """
mjw@2332 493 raise NotImplementedError()
mjw@2332 494
mjw@2332 495
mjw@2332 496 class BackendInterface:
mjw@2332 497 """Abstract class for a domain's interface onto a backend controller.
mjw@2332 498 """
mjw@2332 499
mjw@2332 500 def __init__(self, controller, dom, handle):
mjw@2332 501 """
mjw@2332 502
mjw@2332 503 @param controller: front-end controller
mjw@2332 504 @param dom: back-end domain
mjw@2332 505 @param handle: back-end interface handle
mjw@2332 506 """
mjw@2332 507 self.factory = controller.factory
mjw@2332 508 self.controller = controller
mjw@2332 509 self.dom = int(dom)
mjw@2332 510 self.handle = handle
mjw@2332 511 self.backend = self.getBackendController()
mjw@2332 512
mjw@2332 513 def registerInterface(self):
mjw@2332 514 self.backend.registerInterface(self)
mjw@2332 515
mjw@2332 516 def getInterfaceKey(self):
mjw@2332 517 return (self.controller.dom, self.handle)
mjw@2332 518
mjw@2332 519 def getBackendController(self):
mjw@2332 520 return self.factory.getBackendController(self.dom)
mjw@2332 521
mjw@2332 522 def writeRequest(self, msg, response=None):
mjw@2332 523 return self.backend.writeRequest(msg, response=response)
mjw@2332 524
mjw@2332 525 def close(self):
mjw@2332 526 self.backend.deregisterInterface(self)
mjw@2332 527 self.controller.backendInterfaceClosed(self)
mjw@2267 528
mjw@2267 529 class SplitController(Controller):
mjw@2267 530 """Abstract class for a device controller attached to a domain.
mjw@2332 531 A SplitController manages a BackendInterface for each backend domain
mjw@2267 532 it has at least one device for.
mjw@2267 533 """
mjw@2225 534
mjw@2267 535 def __init__(self, factory, dom):
mjw@2267 536 Controller.__init__(self, factory, dom)
mjw@2332 537 self.backendInterfaces = {}
mjw@2267 538 self.backendHandle = 0
mjw@2225 539
mjw@2332 540 def getBackendInterfaces(self):
mjw@2332 541 return self.backendInterfaces.values()
mjw@2267 542
mjw@2332 543 def getBackendInterfaceByHandle(self, handle):
mjw@2332 544 for b in self.getBackendInterfaces():
mjw@2267 545 if b.handle == handle:
mjw@2267 546 return b
mjw@2267 547 return None
mjw@2267 548
mjw@2332 549 def getBackendInterfaceByDomain(self, dom):
mjw@2332 550 return self.backendInterfaces.get(dom)
mjw@2267 551
mjw@2332 552 def getBackendInterface(self, dom):
mjw@2332 553 """Get the backend interface for a domain.
mjw@2225 554
mjw@2225 555 @param dom: domain
mjw@2225 556 @return: backend controller
mjw@2225 557 """
mjw@2332 558 b = self.getBackendInterfaceByDomain(dom)
mjw@2267 559 if b is None:
mjw@2267 560 handle = self.backendHandle
mjw@2267 561 self.backendHandle += 1
mjw@2332 562 b = self.factory.createBackendInterface(self, dom, handle)
mjw@2332 563 b.registerInterface()
mjw@2332 564 self.backendInterfaces[b.dom] = b
mjw@2267 565 return b
mjw@2225 566
mjw@2332 567 def delBackendInterface(self, ctrlr):
mjw@2225 568 """Remove a backend controller.
mjw@2225 569
mjw@2225 570 @param ctrlr: backend controller
mjw@2225 571 """
mjw@2332 572 if ctrlr.dom in self.backendInterfaces:
mjw@2332 573 del self.backendInterfaces[ctrlr.dom]
mjw@2225 574
mjw@2332 575 def backendInterfaceClosed(self, ctrlr):
mjw@2225 576 """Callback called when a backend is closed.
mjw@2225 577 """
mjw@2332 578 self.delBackendInterface(ctrlr)
mjw@2225 579
mjw@1623 580 class Dev:
mjw@1654 581 """Abstract class for a device attached to a device controller.
mjw@2185 582
mjw@2185 583 @ivar idx: identifier
mjw@2185 584 @type idx: String
mjw@2185 585 @ivar controller: device controller
mjw@2185 586 @type controller: DeviceController
mjw@2185 587 @ivar props: property table
mjw@2185 588 @type props: { String: value }
mjw@1654 589 """
mjw@1654 590
mjw@1975 591 def __init__(self, idx, controller):
mjw@1975 592 self.idx = str(idx)
mjw@1623 593 self.controller = controller
mjw@1623 594 self.props = {}
mjw@1623 595
mjw@1975 596 def getidx(self):
mjw@1975 597 return self.idx
mjw@1975 598
mjw@1623 599 def setprop(self, k, v):
mjw@1623 600 self.props[k] = v
mjw@1623 601
mjw@1623 602 def getprop(self, k, v=None):
mjw@1623 603 return self.props.get(k, v)
mjw@1623 604
mjw@1623 605 def hasprop(self, k):
mjw@1623 606 return k in self.props
mjw@1623 607
mjw@1623 608 def delprop(self, k):
mjw@1623 609 if k in self.props:
mjw@1623 610 del self.props[k]
mjw@1623 611
mjw@1623 612 def sxpr(self):
mjw@2185 613 """Get the s-expression for the deivice.
mjw@2185 614 Implement in a subclass.
mjw@2185 615
mjw@2185 616 @return: sxpr
mjw@2185 617 """
mjw@1623 618 raise NotImplementedError()
mjw@1623 619
mjw@2267 620 class SplitDev(Dev):
mjw@2267 621
mjw@2267 622 def __init__(self, idx, controller):
mjw@2267 623 Dev.__init__(self, idx, controller)
mjw@2267 624 self.backendDomain = 0
mjw@2267 625
mjw@2332 626 def getBackendInterface(self):
mjw@2332 627 return self.controller.getBackendInterface(self.backendDomain)
mjw@2267 628
mjw@2267 629
mjw@2267 630
mjw@1623 631