xen-vtx-unstable
annotate tools/python/xen/xend/server/controller.py @ 2267:45db83f2cdd0
bitkeeper revision 1.1159.38.3 (4123550cLBAC07otAj8ftsT6MzujHQ)
Make backend domain a per-device parameter.
Restructure device controllers and adjust
config handling.
Make backend domain a per-device parameter.
Restructure device controllers and adjust
config handling.
author | mjw@wray-m-3.hpl.hp.com |
---|---|
date | Wed Aug 18 13:09:32 2004 +0000 (2004-08-18) |
parents | af0729973950 |
children | 703b333dc90c |
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@1623 | 277 Maintains a table of instances. |
mjw@1654 | 278 |
mjw@1719 | 279 @ivar instances: mapping of index to controller instance |
mjw@2185 | 280 @type instances: {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@1623 | 286 self.instances = {} |
mjw@2225 | 287 self.backends = {} |
mjw@1623 | 288 self.dom = 0 |
mjw@1623 | 289 |
mjw@1623 | 290 def addInstance(self, instance): |
mjw@1654 | 291 """Add a controller instance (under its index). |
mjw@1654 | 292 """ |
mjw@1623 | 293 self.instances[instance.idx] = instance |
mjw@1623 | 294 |
mjw@1623 | 295 def getInstance(self, idx): |
mjw@1654 | 296 """Get a controller instance from its index. |
mjw@1654 | 297 """ |
mjw@1623 | 298 return self.instances.get(idx) |
mjw@1623 | 299 |
mjw@1623 | 300 def getInstances(self): |
mjw@1654 | 301 """Get a list of all controller instances. |
mjw@1654 | 302 """ |
mjw@1623 | 303 return self.instances.values() |
mjw@1623 | 304 |
mjw@1623 | 305 def getInstanceByDom(self, dom): |
mjw@1654 | 306 """Get the controller instance for the given domain. |
mjw@2185 | 307 |
mjw@2185 | 308 @param dom: domain id |
mjw@2185 | 309 @type dom: int |
mjw@2185 | 310 @return: controller or None |
mjw@1654 | 311 """ |
mjw@1623 | 312 for inst in self.instances.values(): |
mjw@1623 | 313 if inst.dom == dom: |
mjw@1623 | 314 return inst |
mjw@1623 | 315 return None |
mjw@1623 | 316 |
mjw@1623 | 317 def delInstance(self, instance): |
mjw@2185 | 318 """Delete a controller instance from the table. |
mjw@2185 | 319 |
mjw@2185 | 320 @param instance: controller instance |
mjw@1654 | 321 """ |
mjw@1623 | 322 if instance.idx in self.instances: |
mjw@1623 | 323 del self.instances[instance.idx] |
mjw@1623 | 324 |
mjw@1623 | 325 def createInstance(self, dom, recreate=0): |
mjw@1654 | 326 """Create an instance. Define in a subclass. |
mjw@1719 | 327 |
mjw@1719 | 328 @param dom: domain |
mjw@1719 | 329 @type dom: int |
mjw@1719 | 330 @param recreate: true if the instance is being recreated (after xend restart) |
mjw@1719 | 331 @type recreate: 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@1623 | 337 def instanceClosed(self, instance): |
mjw@1654 | 338 """Callback called when an instance is closed (usually by the instance). |
mjw@2185 | 339 |
mjw@2185 | 340 @param instance: controller instance |
mjw@1654 | 341 """ |
mjw@1623 | 342 self.delInstance(instance) |
mjw@1623 | 343 |
mjw@1623 | 344 class Controller(CtrlMsgRcvr): |
mjw@1623 | 345 """Abstract class for a device controller attached to a domain. |
mjw@2185 | 346 |
mjw@2185 | 347 @ivar factory: controller factory |
mjw@2185 | 348 @type factory: ControllerFactory |
mjw@2185 | 349 @ivar dom: domain |
mjw@2185 | 350 @type dom: int |
mjw@2185 | 351 @ivar channel: channel to the domain |
mjw@2185 | 352 @type channel: Channel |
mjw@2185 | 353 @ivar idx: channel index |
mjw@2185 | 354 @type idx: String |
mjw@1623 | 355 """ |
mjw@1623 | 356 |
mjw@1623 | 357 def __init__(self, factory, dom): |
mjw@1623 | 358 CtrlMsgRcvr.__init__(self) |
mjw@1623 | 359 self.factory = factory |
mjw@1623 | 360 self.dom = int(dom) |
mjw@1623 | 361 self.channel = None |
mjw@1623 | 362 self.idx = None |
mjw@1623 | 363 |
mjw@1623 | 364 def close(self): |
mjw@1654 | 365 """Close the controller. |
mjw@1654 | 366 """ |
mjw@1623 | 367 self.lostChannel() |
mjw@1623 | 368 |
mjw@1623 | 369 def lostChannel(self): |
mjw@1654 | 370 """The controller channel has been lost. |
mjw@1654 | 371 """ |
mjw@1664 | 372 self.deregisterChannel() |
mjw@1623 | 373 self.factory.instanceClosed(self) |
mjw@1623 | 374 |
mjw@2267 | 375 class BackendController(CtrlMsgRcvr): |
mjw@2267 | 376 """Abstract class for a backend device controller attached to a domain. |
mjw@2267 | 377 |
mjw@2267 | 378 @ivar controller: frontend controller |
mjw@2267 | 379 @type controller: Controller |
mjw@2267 | 380 @ivar dom: domain |
mjw@2267 | 381 @type dom: int |
mjw@2267 | 382 @ivar channel: channel to the domain |
mjw@2267 | 383 @type channel: Channel |
mjw@2267 | 384 """ |
mjw@2267 | 385 |
mjw@2225 | 386 |
mjw@2267 | 387 def __init__(self, controller, dom, handle): |
mjw@2267 | 388 CtrlMsgRcvr.__init__(self) |
mjw@2267 | 389 self.controller = controller |
mjw@2267 | 390 self.dom = int(dom) |
mjw@2267 | 391 self.handle = handle |
mjw@2267 | 392 self.channel = None |
mjw@2267 | 393 |
mjw@2267 | 394 def close(self): |
mjw@2267 | 395 self.lostChannel() |
mjw@2225 | 396 |
mjw@2267 | 397 def lostChannel(self): |
mjw@2267 | 398 self.deregisterChannel() |
mjw@2267 | 399 self.controller.backendClosed(self) |
mjw@2267 | 400 |
mjw@2267 | 401 class SplitController(Controller): |
mjw@2267 | 402 """Abstract class for a device controller attached to a domain. |
mjw@2267 | 403 A SplitController manages a BackendController for each backend domain |
mjw@2267 | 404 it has at least one device for. |
mjw@2267 | 405 """ |
mjw@2225 | 406 |
mjw@2267 | 407 def __init__(self, factory, dom): |
mjw@2267 | 408 Controller.__init__(self, factory, dom) |
mjw@2267 | 409 self.backends = {} |
mjw@2267 | 410 self.backendHandle = 0 |
mjw@2225 | 411 |
mjw@2267 | 412 def getBackends(self): |
mjw@2267 | 413 return self.backends.values() |
mjw@2267 | 414 |
mjw@2267 | 415 def getBackendByHandle(self, handle): |
mjw@2267 | 416 for b in self.getBackends(): |
mjw@2267 | 417 if b.handle == handle: |
mjw@2267 | 418 return b |
mjw@2267 | 419 return None |
mjw@2267 | 420 |
mjw@2267 | 421 def getBackendByDomain(self, dom): |
mjw@2267 | 422 return self.backends.get(dom) |
mjw@2267 | 423 |
mjw@2267 | 424 def getBackend(self, dom): |
mjw@2225 | 425 """Get the backend controller for a domain. |
mjw@2225 | 426 |
mjw@2225 | 427 @param dom: domain |
mjw@2225 | 428 @return: backend controller |
mjw@2225 | 429 """ |
mjw@2267 | 430 b = self.getBackendByDomain(dom) |
mjw@2267 | 431 if b is None: |
mjw@2267 | 432 handle = self.backendHandle |
mjw@2267 | 433 self.backendHandle += 1 |
mjw@2267 | 434 b = self.createBackend(dom, handle) |
mjw@2267 | 435 self.backends[b.dom] = b |
mjw@2267 | 436 return b |
mjw@2225 | 437 |
mjw@2267 | 438 def createBackend(self, dom, handle): |
mjw@2225 | 439 """Create a backend controller. Define in a subclass. |
mjw@2225 | 440 |
mjw@2225 | 441 @param dom: domain |
mjw@2267 | 442 @param handle: controller handle |
mjw@2225 | 443 """ |
mjw@2225 | 444 raise NotImplementedError() |
mjw@2225 | 445 |
mjw@2267 | 446 def delBackend(self, ctrlr): |
mjw@2225 | 447 """Remove a backend controller. |
mjw@2225 | 448 |
mjw@2225 | 449 @param ctrlr: backend controller |
mjw@2225 | 450 """ |
mjw@2225 | 451 if ctrlr.dom in self.backends: |
mjw@2225 | 452 del self.backends[ctrlr.dom] |
mjw@2225 | 453 |
mjw@2267 | 454 def backendClosed(self, ctrlr): |
mjw@2225 | 455 """Callback called when a backend is closed. |
mjw@2225 | 456 """ |
mjw@2267 | 457 self.delBackend(ctrlr) |
mjw@2225 | 458 |
mjw@1623 | 459 class Dev: |
mjw@1654 | 460 """Abstract class for a device attached to a device controller. |
mjw@2185 | 461 |
mjw@2185 | 462 @ivar idx: identifier |
mjw@2185 | 463 @type idx: String |
mjw@2185 | 464 @ivar controller: device controller |
mjw@2185 | 465 @type controller: DeviceController |
mjw@2185 | 466 @ivar props: property table |
mjw@2185 | 467 @type props: { String: value } |
mjw@1654 | 468 """ |
mjw@1654 | 469 |
mjw@1975 | 470 def __init__(self, idx, controller): |
mjw@1975 | 471 self.idx = str(idx) |
mjw@1623 | 472 self.controller = controller |
mjw@1623 | 473 self.props = {} |
mjw@1623 | 474 |
mjw@1975 | 475 def getidx(self): |
mjw@1975 | 476 return self.idx |
mjw@1975 | 477 |
mjw@1623 | 478 def setprop(self, k, v): |
mjw@1623 | 479 self.props[k] = v |
mjw@1623 | 480 |
mjw@1623 | 481 def getprop(self, k, v=None): |
mjw@1623 | 482 return self.props.get(k, v) |
mjw@1623 | 483 |
mjw@1623 | 484 def hasprop(self, k): |
mjw@1623 | 485 return k in self.props |
mjw@1623 | 486 |
mjw@1623 | 487 def delprop(self, k): |
mjw@1623 | 488 if k in self.props: |
mjw@1623 | 489 del self.props[k] |
mjw@1623 | 490 |
mjw@1623 | 491 def sxpr(self): |
mjw@2185 | 492 """Get the s-expression for the deivice. |
mjw@2185 | 493 Implement in a subclass. |
mjw@2185 | 494 |
mjw@2185 | 495 @return: sxpr |
mjw@2185 | 496 """ |
mjw@1623 | 497 raise NotImplementedError() |
mjw@1623 | 498 |
mjw@2267 | 499 class SplitDev(Dev): |
mjw@2267 | 500 |
mjw@2267 | 501 def __init__(self, idx, controller): |
mjw@2267 | 502 Dev.__init__(self, idx, controller) |
mjw@2267 | 503 self.backendDomain = 0 |
mjw@2267 | 504 |
mjw@2267 | 505 def getBackend(self): |
mjw@2267 | 506 return self.controller.getBackend(self.backendDomain) |
mjw@2267 | 507 |
mjw@2267 | 508 |
mjw@2267 | 509 |
mjw@1623 | 510 |