mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
bitkeeper revision 1.1051 (40ed377bW0cMKaeeMSXfQOknw3iMaw)
Documentation.
This commit is contained in:
1 parent
e7b2e4a624
commit
d18cda81eb
3 files changed
+221
-76
No files matched your search
@@ -29,8 +29,12 @@ class BlkifControllerFactory(controller.ControllerFactory):
|
||||
def createInstance(self, dom, recreate=0):
|
||||
"""Create a block device controller for a domain.
|
||||
|
||||
dom domain
|
||||
recreate if true it's a recreate (after xend restart)
|
||||
@param dom: domain
|
||||
@type dom: int
|
||||
@param recreate: if true it's a recreate (after xend restart)
|
||||
@type recreate: bool
|
||||
@return: deferred
|
||||
@rtype: twisted.internet.defer.Deferred
|
||||
"""
|
||||
d = defer.Deferred()
|
||||
blkif = self.getInstanceByDom(dom)
|
||||
@@ -51,9 +55,10 @@ class BlkifControllerFactory(controller.ControllerFactory):
|
||||
def getDomainDevices(self, dom):
|
||||
"""Get the block devices for a domain.
|
||||
|
||||
dom domain
|
||||
|
||||
returns devices
|
||||
@param dom: domain
|
||||
@type dom: int
|
||||
@return: devices
|
||||
@rtype: [device]
|
||||
"""
|
||||
blkif = self.getInstanceByDom(dom)
|
||||
return (blkif and blkif.getDevices()) or []
|
||||
@@ -61,10 +66,12 @@ class BlkifControllerFactory(controller.ControllerFactory):
|
||||
def getDomainDevice(self, dom, vdev):
|
||||
"""Get a block device from a domain.
|
||||
|
||||
dom domain
|
||||
vdev device index
|
||||
|
||||
returns device
|
||||
@param dom: domain
|
||||
@type dom: int
|
||||
@param vdev: device index
|
||||
@type vedv: int
|
||||
@return: device
|
||||
@rtype: device
|
||||
"""
|
||||
blkif = self.getInstanceByDom(dom)
|
||||
return (blkif and blkif.getDevice(vdev)) or None
|
||||
@@ -72,8 +79,10 @@ class BlkifControllerFactory(controller.ControllerFactory):
|
||||
def setControlDomain(self, dom, recreate=0):
|
||||
"""Set the back-end block device controller domain.
|
||||
|
||||
dom domain
|
||||
recreate if true it's a recreate (after xend restart)
|
||||
@param dom: domain
|
||||
@type dom: int
|
||||
@param recreate: if true it's a recreate (after xend restart)
|
||||
@type recreate: int
|
||||
"""
|
||||
if self.dom == dom: return
|
||||
self.deregisterChannel()
|
||||
@@ -84,14 +93,19 @@ class BlkifControllerFactory(controller.ControllerFactory):
|
||||
|
||||
def getControlDomain(self):
|
||||
"""Get the back-end block device controller domain.
|
||||
|
||||
@return: domain
|
||||
@rtype: int
|
||||
"""
|
||||
return self.dom
|
||||
|
||||
def reattachDevice(self, dom, vdev):
|
||||
"""Reattach a device (on changing control domain).
|
||||
|
||||
dom domain
|
||||
vdev device index
|
||||
@param dom: domain
|
||||
@type dom: int
|
||||
@param vdev: device index
|
||||
@type vdev: int
|
||||
"""
|
||||
blkif = self.getInstanceByDom(dom)
|
||||
if blkif:
|
||||
@@ -102,6 +116,9 @@ class BlkifControllerFactory(controller.ControllerFactory):
|
||||
|
||||
def devicesAttached(self):
|
||||
"""Check if all devices are attached.
|
||||
|
||||
@return: true if all devices attached
|
||||
@rtype: bool
|
||||
"""
|
||||
attached = 1
|
||||
for blkif in self.getInstances():
|
||||
@@ -111,19 +128,32 @@ class BlkifControllerFactory(controller.ControllerFactory):
|
||||
return attached
|
||||
|
||||
def reattached(self):
|
||||
"""Notify all block interface we have been reattached
|
||||
"""Notify all block interfaces we have been reattached
|
||||
(after changing control domain).
|
||||
"""
|
||||
for blkif in self.getInstances():
|
||||
blkif.reattached()
|
||||
|
||||
def respond_be_create(self, msg, d):
|
||||
"""Response handler for a be_create message.
|
||||
Calls I{d} with the block interface created.
|
||||
|
||||
@param msg: message
|
||||
@type msg: xu message
|
||||
@param d: deferred to call
|
||||
@type d: Deferred
|
||||
"""
|
||||
print 'respond_be_create>'
|
||||
val = unpackMsg('blkif_be_create_t', msg)
|
||||
blkif = self.getInstanceByDom(val['domid'])
|
||||
d.callback(blkif)
|
||||
|
||||
def respond_be_connect(self, msg):
|
||||
"""Response handler for a be_connect message.
|
||||
|
||||
@param msg: message
|
||||
@type msg: xu message
|
||||
"""
|
||||
print 'respond_be_connect>', self
|
||||
val = unpackMsg('blkif_be_connect_t', msg)
|
||||
blkif = self.getInstanceByDom(val['domid'])
|
||||
@@ -133,6 +163,15 @@ class BlkifControllerFactory(controller.ControllerFactory):
|
||||
pass
|
||||
|
||||
def respond_be_vbd_create(self, msg, d):
|
||||
"""Response handler for a be_vbd_create message.
|
||||
Tries to grow the vbd, and passes the deferred I{d} on for
|
||||
the grow to call.
|
||||
|
||||
@param msg: message
|
||||
@type msg: xu message
|
||||
@param d: deferred to call
|
||||
@type d: Deferred
|
||||
"""
|
||||
print 'recv_be_vbd_create>', self
|
||||
val = unpackMsg('blkif_be_vbd_create_t', msg)
|
||||
blkif = self.getInstanceByDom(val['domid'])
|
||||
@@ -145,6 +184,13 @@ class BlkifControllerFactory(controller.ControllerFactory):
|
||||
pass
|
||||
|
||||
def respond_be_vbd_grow(self, msg, d):
|
||||
"""Response handler for a be_vbd_grow message.
|
||||
|
||||
@param msg: message
|
||||
@type msg: xu message
|
||||
@param d: deferred to call
|
||||
@type d: Deferred or None
|
||||
"""
|
||||
print 'recv_be_vbd_grow>', self
|
||||
val = unpackMsg('blkif_be_vbd_grow_t', msg)
|
||||
# Check status?
|
||||
@@ -155,6 +201,13 @@ class BlkifControllerFactory(controller.ControllerFactory):
|
||||
self.reattachDevice(val['domid'], val['vdevice'])
|
||||
|
||||
def recv_be_driver_status_changed(self, msg, req):
|
||||
"""Request handler for be_driver_status_changed messages.
|
||||
|
||||
@param msg: message
|
||||
@type msg: xu message
|
||||
@param req: request flag (true if the msg is a request)
|
||||
@type req: bool
|
||||
"""
|
||||
print 'recv_be_driver_status_changed>', self, req
|
||||
val = unpackMsg('blkif_be_driver_status_changed_t', msg)
|
||||
status = val['status']
|
||||
@@ -222,6 +275,17 @@ class BlkifController(controller.Controller):
|
||||
return self.devices.get(vdev)
|
||||
|
||||
def addDevice(self, vdev, mode, segment):
|
||||
"""Add a device to the device table.
|
||||
|
||||
@param vdev: device index
|
||||
@type vdev: int
|
||||
@param mode: read/write mode
|
||||
@type mode: string
|
||||
@param segment: segment
|
||||
@type segment: int
|
||||
@return: device
|
||||
@rtype: BlkDev
|
||||
"""
|
||||
if vdev in self.devices: return None
|
||||
dev = BlkDev(self, vdev, mode, segment)
|
||||
self.devices[vdev] = dev
|
||||
@@ -230,12 +294,16 @@ class BlkifController(controller.Controller):
|
||||
def attachDevice(self, vdev, mode, segment, recreate=0):
|
||||
"""Attach a device to the specified interface.
|
||||
|
||||
vdev device index
|
||||
mode read/write mode
|
||||
segment segment
|
||||
recreate if true it's being recreated (after xend restart)
|
||||
|
||||
returns deferred
|
||||
@param vdev: device index
|
||||
@type vdev: int
|
||||
@param mode: read/write mode
|
||||
@type mode: string
|
||||
@param segment: segment
|
||||
@type segment: int
|
||||
@param recreate: if true it's being recreated (after xend restart)
|
||||
@type recreate: bool
|
||||
@return: deferred
|
||||
@rtype: Deferred
|
||||
"""
|
||||
dev = self.addDevice(vdev, mode, segment)
|
||||
if not dev: return -1
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import xen.lowlevel.xc; xc = xen.lowlevel.xc.new()
|
||||
from xen.lowlevel import xu
|
||||
from messages import msgTypeName
|
||||
from messages import msgTypeName, printMsg
|
||||
|
||||
VIRQ_MISDIRECT = 0 # Catch-all interrupt for unbound VIRQs.
|
||||
VIRQ_TIMER = 1 # Timebase update, and/or requested timeout.
|
||||
@@ -222,12 +222,18 @@ class Channel(BaseChannel):
|
||||
|
||||
def getLocalPort(self):
|
||||
"""Get the local port.
|
||||
|
||||
@return: local port
|
||||
@rtype: int
|
||||
"""
|
||||
if self.closed: return -1
|
||||
return self.port.local_port
|
||||
|
||||
def getRemotePort(self):
|
||||
"""Get the remote port.
|
||||
|
||||
@return: remote port
|
||||
@rtype: int
|
||||
"""
|
||||
if self.closed: return -1
|
||||
return self.port.remote_port
|
||||
@@ -248,8 +254,9 @@ class Channel(BaseChannel):
|
||||
def registerDevice(self, types, dev):
|
||||
"""Register a device controller.
|
||||
|
||||
@param types message types the controller handles
|
||||
@param dev device controller
|
||||
@param types: message types the controller handles
|
||||
@type types: array of ints
|
||||
@param dev: device controller
|
||||
"""
|
||||
if self.closed: return
|
||||
self.devs.append(dev)
|
||||
@@ -259,7 +266,7 @@ class Channel(BaseChannel):
|
||||
def deregisterDevice(self, dev):
|
||||
"""Remove the registration for a device controller.
|
||||
|
||||
@param dev device controller
|
||||
@param dev: device controller
|
||||
"""
|
||||
if dev in self.devs:
|
||||
self.devs.remove(dev)
|
||||
@@ -270,13 +277,20 @@ class Channel(BaseChannel):
|
||||
def getDevice(self, type):
|
||||
"""Get the device controller handling a message type.
|
||||
|
||||
@param type message type
|
||||
@returns controller or None
|
||||
@param type: message type
|
||||
@type type: int
|
||||
@return: controller or None
|
||||
@rtype: device controller
|
||||
"""
|
||||
return self.devs_by_type.get(type)
|
||||
|
||||
def getMessageType(self, msg):
|
||||
"""Get a 2-tuple of the message type and subtype.
|
||||
|
||||
@param msg: message
|
||||
@type msg: xu message
|
||||
@return: type info
|
||||
@rtype: (int, int)
|
||||
"""
|
||||
hdr = msg.get_header()
|
||||
return (hdr['type'], hdr.get('subtype'))
|
||||
|
||||
@@ -1,53 +1,80 @@
|
||||
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
|
||||
"""General support for controllers, which handle devices
|
||||
for a domain.
|
||||
"""
|
||||
|
||||
from twisted.internet import defer
|
||||
defer.Deferred.debug = 1
|
||||
|
||||
import channel
|
||||
from messages import msgTypeName
|
||||
from messages import msgTypeName, printMsg
|
||||
|
||||
DEBUG=0
|
||||
DEBUG = 0
|
||||
|
||||
class OutOfOrderError(RuntimeError):
|
||||
"""Error reported when a response arrives out of order.
|
||||
"""Error reported when a response message arrives out of order.
|
||||
"""
|
||||
pass
|
||||
|
||||
class Responder:
|
||||
"""Handler for a response to a message.
|
||||
"""Handler for a response to a message with a specified id.
|
||||
"""
|
||||
|
||||
def __init__(self, mid, deferred):
|
||||
"""Create a responder.
|
||||
|
||||
mid message id of response to handle
|
||||
deferred deferred object holding the callbacks
|
||||
@param mid: message id of response to handle
|
||||
@type mid: int
|
||||
@param deferred: deferred object holding the callbacks
|
||||
@type deferred: Deferred
|
||||
"""
|
||||
self.mid = mid
|
||||
self.deferred = deferred
|
||||
|
||||
def responseReceived(self, msg):
|
||||
"""Entry point called when a response message with the right id arrives.
|
||||
Calls callback on I{self.deferred} with the message.
|
||||
|
||||
@param msg: response message
|
||||
@type msg: xu message
|
||||
"""
|
||||
if self.deferred.called: return
|
||||
self.deferred.callback(msg)
|
||||
|
||||
def error(self, err):
|
||||
"""Entry point called when there has been an error.
|
||||
Calls errback on I{self.deferred} with the error.
|
||||
|
||||
@param err: error
|
||||
@type err: Exception
|
||||
"""
|
||||
if self.deferred.called: return
|
||||
self.deferred.errback(err)
|
||||
|
||||
class CtrlMsgRcvr:
|
||||
"""Abstract class for things that deal with a control interface to a domain.
|
||||
Once I{registerChannel} has been called, our message types are registered
|
||||
with the channel to the domain. The channel will call I{requestReceived}
|
||||
when a request arrives, or I{responseReceived} when a response arrives,
|
||||
if they have one of our message types.
|
||||
|
||||
Instance variables:
|
||||
|
||||
dom : the domain we are a control interface for
|
||||
majorTypes: list of major message types we are interested in
|
||||
subTypes : mapping of message subtypes to methods
|
||||
@ivar dom: the domain we are a control interface for
|
||||
@type dom: int
|
||||
@ivar majorTypes: major message types we are interested in
|
||||
@type majorTypes: [int]
|
||||
@ivar subTypes: mapping of message subtypes to methods
|
||||
@ivar subTypes: {int:method}
|
||||
@ivar timeout: timeout (in seconds) for message handlers
|
||||
@type timeout: int
|
||||
|
||||
channel : channel to the domain
|
||||
idx : channel index
|
||||
@ivar channel: channel to the domain
|
||||
@type channel: Channel
|
||||
@ivar idx: channel index
|
||||
@ivar idx: string
|
||||
@ivar responders: table of message response handlers
|
||||
@type responders: {int:Responder}
|
||||
"""
|
||||
|
||||
|
||||
def __init__(self):
|
||||
self.channelFactory = channel.channelFactory()
|
||||
self.majorTypes = [ ]
|
||||
@@ -56,22 +83,25 @@ class CtrlMsgRcvr:
|
||||
self.channel = None
|
||||
self.idx = None
|
||||
self.responders = []
|
||||
# Timeout (in seconds) for deferreds.
|
||||
self.timeout = 10
|
||||
|
||||
def setTimeout(self, timeout):
|
||||
self.timeout = timeout
|
||||
|
||||
def requestReceived(self, msg, type, subtype):
|
||||
"""Dispatch a request to handlers.
|
||||
"""Dispatch a request message to handlers.
|
||||
Called by the channel for requests with one of our types.
|
||||
|
||||
msg message
|
||||
type major message type
|
||||
subtype minor message type
|
||||
@param msg: message
|
||||
@type msg: xu message
|
||||
@param type: major message type
|
||||
@type type: int
|
||||
@param subtype: minor message type
|
||||
@type subtype: int
|
||||
"""
|
||||
msgid = msg.get_header()['id']
|
||||
if DEBUG:
|
||||
print 'requestReceived>', self, msgid, msgTypeName(type, subtype)
|
||||
print 'requestReceived>',
|
||||
printMsg(msg, all=1)
|
||||
method = self.subTypes.get(subtype)
|
||||
if method:
|
||||
method(msg, 1)
|
||||
@@ -81,14 +111,23 @@ class CtrlMsgRcvr:
|
||||
|
||||
def responseReceived(self, msg, type, subtype):
|
||||
"""Dispatch a response to handlers.
|
||||
Called by the channel for responses with one of our types.
|
||||
|
||||
First looks for a message responder for the message's id.
|
||||
See L{callResponders}, L{addResponder}.
|
||||
If there is no responder, looks for a message handler for
|
||||
the message type/subtype.
|
||||
|
||||
msg message
|
||||
type major message type
|
||||
subtype minor message type
|
||||
@param msg: message
|
||||
@type msg: xu message
|
||||
@param type: major message type
|
||||
@type type: int
|
||||
@param subtype: minor message type
|
||||
@type subtype: int
|
||||
"""
|
||||
msgid = msg.get_header()['id']
|
||||
if DEBUG:
|
||||
print 'responseReceived>', self, msgid, msgTypeName(type, subtype)
|
||||
print 'responseReceived>',
|
||||
printMsg(msg, all=1)
|
||||
if self.callResponders(msg):
|
||||
return
|
||||
method = self.subTypes.get(subtype)
|
||||
@@ -100,16 +139,21 @@ class CtrlMsgRcvr:
|
||||
|
||||
def addResponder(self, mid, deferred):
|
||||
"""Add a responder for a message id.
|
||||
The deferred is called with callback(msg) when a response
|
||||
with the given message id arrives. Responses are expected
|
||||
The I{deferred} is called with callback(msg) when a response
|
||||
with message id I{mid} arrives. Responses are expected
|
||||
to arrive in order of message id. When a response arrives,
|
||||
waiting responders for messages with lower id have errback
|
||||
called with an OutOfOrder error.
|
||||
|
||||
mid message id of response expected
|
||||
deferred a Deferred to handle the response
|
||||
Responders have a timeout set and I{deferred} will error
|
||||
on expiry.
|
||||
|
||||
returns Responder
|
||||
@param mid: message id of response expected
|
||||
@type mid: int
|
||||
@param deferred: handler for the response
|
||||
@type deferred: Deferred
|
||||
@return: responder
|
||||
@rtype: Responder
|
||||
"""
|
||||
if self.timeout > 0:
|
||||
deferred.setTimeout(self.timeout)
|
||||
@@ -119,10 +163,13 @@ class CtrlMsgRcvr:
|
||||
|
||||
def callResponders(self, msg):
|
||||
"""Call any waiting responders for a response message.
|
||||
Looks for a responder registered for the message's id.
|
||||
See L{addResponder}.
|
||||
|
||||
msg response message
|
||||
|
||||
returns 1 if there was a responder for the message, 0 otherwise
|
||||
@param msg: response message
|
||||
@type msg: xu message
|
||||
@return: 1 if there was a responder for the message, 0 otherwise
|
||||
@rtype : bool
|
||||
"""
|
||||
hdr = msg.get_header()
|
||||
mid = hdr['id']
|
||||
@@ -133,7 +180,7 @@ class CtrlMsgRcvr:
|
||||
break
|
||||
self.responders.pop()
|
||||
if resp.mid < mid:
|
||||
print 'handleResponse> Out of order:', resp.mid, mid
|
||||
print 'callResponders> Out of order:', resp.mid, mid
|
||||
resp.error(OutOfOrderError())
|
||||
else:
|
||||
handled = 1
|
||||
@@ -148,7 +195,8 @@ class CtrlMsgRcvr:
|
||||
|
||||
def registerChannel(self):
|
||||
"""Register interest in our major message types with the
|
||||
channel to our domain.
|
||||
channel to our domain. Once we have registered, the channel
|
||||
will call requestReceived or responseReceived for our messages.
|
||||
"""
|
||||
self.channel = self.channelFactory.domChannel(self.dom)
|
||||
self.idx = self.channel.getIndex()
|
||||
@@ -157,7 +205,8 @@ class CtrlMsgRcvr:
|
||||
|
||||
def deregisterChannel(self):
|
||||
"""Deregister interest in our major message types with the
|
||||
channel to our domain.
|
||||
channel to our domain. After this the channel won't call
|
||||
us any more.
|
||||
"""
|
||||
if self.channel:
|
||||
self.channel.deregisterDevice(self)
|
||||
@@ -166,18 +215,23 @@ class CtrlMsgRcvr:
|
||||
def produceRequests(self):
|
||||
"""Produce any queued requests.
|
||||
|
||||
return number produced
|
||||
@return: number produced
|
||||
@rtype: int
|
||||
"""
|
||||
return 0
|
||||
|
||||
def writeRequest(self, msg, response=None):
|
||||
"""Write a request to the channel.
|
||||
|
||||
msg message
|
||||
response Deferred to handle the response (optional)
|
||||
@param msg: request message
|
||||
@type msg: xu message
|
||||
@param response: response handler
|
||||
@type response: Deferred
|
||||
"""
|
||||
if self.channel:
|
||||
if DEBUG: print 'CtrlMsgRcvr>writeRequest>', self, msg
|
||||
if DEBUG:
|
||||
print 'CtrlMsgRcvr>writeRequest>',
|
||||
printMsg(msg, all=1)
|
||||
if response:
|
||||
self.addResponder(msg.get_header()['id'], response)
|
||||
self.channel.writeRequest(msg)
|
||||
@@ -185,29 +239,33 @@ class CtrlMsgRcvr:
|
||||
print 'CtrlMsgRcvr>writeRequest>', 'no channel!', self
|
||||
|
||||
def writeResponse(self, msg):
|
||||
"""Write a response to the channel.
|
||||
"""Write a response to the channel. This acknowledges
|
||||
a request message.
|
||||
|
||||
@param msg: message
|
||||
@type msg: xu message
|
||||
"""
|
||||
if self.channel:
|
||||
if DEBUG: print 'CtrlMsgRcvr>writeResponse>', self, msg
|
||||
if DEBUG:
|
||||
print 'CtrlMsgRcvr>writeResponse>',
|
||||
printMsg(msg, all=0)
|
||||
self.channel.writeResponse(msg)
|
||||
else:
|
||||
print 'CtrlMsgRcvr>writeResponse>', 'no channel!', self
|
||||
|
||||
class ControllerFactory(CtrlMsgRcvr):
|
||||
"""Abstract class for factories creating controllers.
|
||||
"""Abstract class for factories creating controllers for a domain.
|
||||
Maintains a table of instances.
|
||||
|
||||
Instance variables:
|
||||
|
||||
instances : mapping of index to controller instance
|
||||
dlist : list of deferreds
|
||||
dom : domain
|
||||
@ivar instances: mapping of index to controller instance
|
||||
@type instances: {int: Controller}
|
||||
@ivar dom: domain
|
||||
@type dom: int
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
CtrlMsgRcvr.__init__(self)
|
||||
self.instances = {}
|
||||
self.dlist = []
|
||||
self.dom = 0
|
||||
|
||||
def addInstance(self, instance):
|
||||
@@ -241,6 +299,11 @@ class ControllerFactory(CtrlMsgRcvr):
|
||||
|
||||
def createInstance(self, dom, recreate=0):
|
||||
"""Create an instance. Define in a subclass.
|
||||
|
||||
@param dom: domain
|
||||
@type dom: int
|
||||
@param recreate: true if the instance is being recreated (after xend restart)
|
||||
@type recreate: int
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||