mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 18:21:39 +01:00
bitkeeper revision 1.1041.3.1 (40e3fe2a5JO0HpkIeSaP8q6IITbNAQ)
Documentation and a couple of tidies.
This commit is contained in:
1 parent
50b66608c9
commit
76e8d2ff6a
8 files changed
+265
-96
No files matched your search
@@ -1,5 +1,6 @@
|
||||
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
|
||||
|
||||
import traceback
|
||||
from StringIO import StringIO
|
||||
|
||||
from twisted.protocols import http
|
||||
@@ -24,6 +25,7 @@ class SrvDomainDir(SrvDir):
|
||||
val = None
|
||||
try:
|
||||
dom = self.xd.domain_get(x)
|
||||
if not dom: raise KeyError('No such domain')
|
||||
val = SrvDomain(dom)
|
||||
except KeyError, ex:
|
||||
print 'SrvDomainDir>', ex
|
||||
@@ -38,6 +40,9 @@ class SrvDomainDir(SrvDir):
|
||||
return v
|
||||
|
||||
def op_create(self, op, req):
|
||||
"""Create a domain.
|
||||
Expects the domain config in request parameter 'config' in SXP format.
|
||||
"""
|
||||
ok = 0
|
||||
try:
|
||||
configstring = req.args.get('config')[0]
|
||||
@@ -48,7 +53,8 @@ class SrvDomainDir(SrvDir):
|
||||
config = pin.get_val()
|
||||
ok = 1
|
||||
except Exception, ex:
|
||||
print 'op_create>', ex
|
||||
print 'op_create> Exception in config', ex
|
||||
traceback.print_exc()
|
||||
if not ok:
|
||||
req.setResponseCode(http.BAD_REQUEST, "Invalid configuration")
|
||||
return "Invalid configuration"
|
||||
@@ -60,10 +66,10 @@ class SrvDomainDir(SrvDir):
|
||||
deferred.addCallback(self._cb_op_create, configstring, req)
|
||||
return deferred
|
||||
except Exception, ex:
|
||||
raise
|
||||
#return ['err', str(ex) ]
|
||||
#req.setResponseCode(http.BAD_REQUEST, "Error creating domain")
|
||||
#return str(ex)
|
||||
print 'op_create> Exception creating domain:'
|
||||
traceback.print_exc()
|
||||
req.setResponseCode(http.BAD_REQUEST, "Error creating domain")
|
||||
return str(ex)
|
||||
#return error.ErrorPage(http.BAD_REQUEST,
|
||||
# "Error creating domain",
|
||||
# str(ex))
|
||||
@@ -90,6 +96,8 @@ class SrvDomainDir(SrvDir):
|
||||
return val
|
||||
|
||||
def op_restore(self, op, req):
|
||||
"""Restore a domain from file.
|
||||
"""
|
||||
fn = FormFn(self.xd.domain_restore,
|
||||
[['file', 'str']])
|
||||
val = fn(req.args)
|
||||
@@ -131,6 +139,8 @@ class SrvDomainDir(SrvDir):
|
||||
req.write('</ul>')
|
||||
|
||||
def form(self, req):
|
||||
"""Generate the form(s) for domain dir operations.
|
||||
"""
|
||||
req.write('<form method="post" action="%s" enctype="multipart/form-data">'
|
||||
% req.prePathURL())
|
||||
req.write('<button type="submit" name="op" value="create">Create Domain</button>')
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
|
||||
|
||||
from twisted.internet import defer
|
||||
|
||||
from xen.xend import sxp
|
||||
@@ -28,6 +30,11 @@ class BlkifControllerFactory(controller.ControllerFactory):
|
||||
self.registerChannel()
|
||||
|
||||
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)
|
||||
"""
|
||||
d = self.addDeferred()
|
||||
blkif = self.getInstanceByDom(dom)
|
||||
if blkif:
|
||||
@@ -42,29 +49,50 @@ class BlkifControllerFactory(controller.ControllerFactory):
|
||||
return d
|
||||
|
||||
def getDomainDevices(self, dom):
|
||||
"""Get the block devices for a domain.
|
||||
|
||||
dom domain
|
||||
|
||||
returns devices
|
||||
"""
|
||||
blkif = self.getInstanceByDom(dom)
|
||||
return (blkif and blkif.getDevices()) or []
|
||||
|
||||
def getDomainDevice(self, dom, vdev):
|
||||
"""Get a block device from a domain.
|
||||
|
||||
dom domain
|
||||
vdev device index
|
||||
|
||||
returns device
|
||||
"""
|
||||
blkif = self.getInstanceByDom(dom)
|
||||
return (blkif and blkif.getDevice(vdev)) or None
|
||||
|
||||
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)
|
||||
"""
|
||||
if self.dom == dom: return
|
||||
self.deregisterChannel()
|
||||
if not recreate:
|
||||
self.attached = 0
|
||||
self.dom = dom
|
||||
self.registerChannel()
|
||||
#
|
||||
#if xend.blkif.be_port:
|
||||
# xend.blkif.recovery = True
|
||||
#xend.blkif.be_port = xend.main.port_from_dom(dom)
|
||||
|
||||
def getControlDomain(self):
|
||||
"""Get the back-end block device controller domain.
|
||||
"""
|
||||
return self.dom
|
||||
|
||||
def reattachDevice(self, dom, vdev):
|
||||
"""Reattach a device (on changing control domain).
|
||||
|
||||
dom domain
|
||||
vdev device index
|
||||
"""
|
||||
blkif = self.getInstanceByDom(dom)
|
||||
if blkif:
|
||||
blkif.reattachDevice(vdev)
|
||||
@@ -83,6 +111,9 @@ class BlkifControllerFactory(controller.ControllerFactory):
|
||||
return attached
|
||||
|
||||
def reattached(self):
|
||||
"""Notify all block interface we have been reattached
|
||||
(after changing control domain).
|
||||
"""
|
||||
for blkif in self.getInstances():
|
||||
blkif.reattached()
|
||||
|
||||
@@ -147,7 +178,6 @@ class BlkDev(controller.Dev):
|
||||
return val
|
||||
|
||||
def destroy(self):
|
||||
print 'BlkDev>destroy>', self.vdev
|
||||
PrettyPrint.prettyprint(self.sxpr())
|
||||
self.controller.send_be_vbd_destroy(self.vdev)
|
||||
|
||||
@@ -157,7 +187,6 @@ class BlkifController(controller.Controller):
|
||||
"""
|
||||
|
||||
def __init__(self, factory, dom):
|
||||
#print 'BlkifController> dom=', dom
|
||||
controller.Controller.__init__(self, factory, dom)
|
||||
self.devices = {}
|
||||
|
||||
@@ -172,7 +201,6 @@ class BlkifController(controller.Controller):
|
||||
self.attached = 1
|
||||
self.evtchn = None
|
||||
self.registerChannel()
|
||||
#print 'BlkifController<', 'dom=', self.dom, 'idx=', self.idx
|
||||
|
||||
def sxpr(self):
|
||||
val = ['blkif', ['dom', self.dom]]
|
||||
@@ -183,8 +211,6 @@ class BlkifController(controller.Controller):
|
||||
return val
|
||||
|
||||
def lostChannel(self):
|
||||
print 'BlkifController>lostChannel>', 'dom=', self.dom
|
||||
#self.destroyDevices()
|
||||
controller.Controller.lostChannel(self)
|
||||
|
||||
def getDevices(self):
|
||||
@@ -201,8 +227,14 @@ 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
|
||||
"""
|
||||
#print 'BlkifController>attach_device>', self.dom, vdev, mode, segment
|
||||
dev = self.addDevice(vdev, mode, segment)
|
||||
if not dev: return -1
|
||||
if recreate:
|
||||
@@ -214,13 +246,11 @@ class BlkifController(controller.Controller):
|
||||
return d
|
||||
|
||||
def destroy(self):
|
||||
print 'BlkifController>destroy> dom=', self.dom
|
||||
def cb_destroy(val):
|
||||
self.send_be_destroy()
|
||||
d = self.factory.addDeferred()
|
||||
d.addCallback(cb_destroy)
|
||||
self.send_be_disconnect()
|
||||
#self.destroyDevices()
|
||||
|
||||
def destroyDevices(self):
|
||||
for dev in self.getDevices():
|
||||
@@ -276,11 +306,6 @@ class BlkifController(controller.Controller):
|
||||
self.factory.writeRequest(msg)
|
||||
pass
|
||||
|
||||
#def recv_fe_interface_status_changed(self, msg, req):
|
||||
# (hnd, status, chan) = unpackMsg('blkif_fe_interface_status_changed_t', msg)
|
||||
# print 'recv_fe_interface_status_changed>', hnd, status, chan
|
||||
# pass
|
||||
|
||||
def send_fe_interface_status_changed(self):
|
||||
msg = packMsg('blkif_fe_interface_status_changed_t',
|
||||
{ 'handle' : 0,
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
|
||||
|
||||
import xen.lowlevel.xc; xc = xen.lowlevel.xc.new()
|
||||
from xen.lowlevel import xu
|
||||
from messages import msgTypeName
|
||||
@@ -24,14 +26,11 @@ class ChannelFactory:
|
||||
self.notifier = xu.notifier()
|
||||
|
||||
def addChannel(self, channel):
|
||||
"""Add a channel.
|
||||
"""Add a channel. Registers with the notifier.
|
||||
"""
|
||||
idx = channel.idx
|
||||
self.channels[idx] = channel
|
||||
self.notifier.bind(idx)
|
||||
# Try to wake it up
|
||||
#self.notifier.unmask(idx)
|
||||
#channel.notify()
|
||||
|
||||
def getChannel(self, idx):
|
||||
"""Get the channel with the given index (if any).
|
||||
@@ -40,6 +39,7 @@ class ChannelFactory:
|
||||
|
||||
def delChannel(self, idx):
|
||||
"""Remove the channel with the given index (if any).
|
||||
Deregisters with the notifier.
|
||||
"""
|
||||
if idx in self.channels:
|
||||
del self.channels[idx]
|
||||
@@ -288,6 +288,8 @@ class Channel(BaseChannel):
|
||||
self.getRemotePort()))
|
||||
|
||||
def handleNotification(self):
|
||||
"""Process outstanding messages in repsonse to notification on the port.
|
||||
"""
|
||||
if self.closed:
|
||||
print 'handleNotification> Notification on closed channel', self
|
||||
return
|
||||
@@ -299,6 +301,8 @@ class Channel(BaseChannel):
|
||||
self.notify()
|
||||
|
||||
def notify(self):
|
||||
"""Notify the other end of the port that messages have been processed.
|
||||
"""
|
||||
if self.closed: return
|
||||
self.port.notify()
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
|
||||
|
||||
from twisted.internet import reactor
|
||||
from twisted.internet import protocol
|
||||
@@ -12,11 +13,6 @@ import controller
|
||||
from messages import *
|
||||
from params import *
|
||||
|
||||
"""Telnet binary option."""
|
||||
TRANSMIT_BINARY = '0'
|
||||
WILL = chr(251)
|
||||
IAC = chr(255)
|
||||
|
||||
class ConsoleProtocol(protocol.Protocol):
|
||||
"""Asynchronous handler for a console TCP socket.
|
||||
"""
|
||||
@@ -36,19 +32,12 @@ class ConsoleProtocol(protocol.Protocol):
|
||||
self.loseConnection()
|
||||
return
|
||||
else:
|
||||
# KAF: A nice quiet successful connect. Don't bother with telnet
|
||||
# control sequence -- telnet is not the appropriate protocol here.
|
||||
# KAF: A nice quiet successful connect.
|
||||
#self.transport.write("Connected to console %d on domain %d\n"
|
||||
# % (self.idx, self.controller.dom))
|
||||
#self.setTelnetTransmitBinary()
|
||||
eserver.inject('xend.console.connect',
|
||||
[self.idx, self.addr[0], self.addr[1]])
|
||||
|
||||
def setTelnetTransmitBinary(self):
|
||||
"""Send the sequence to set the telnet TRANSMIT-BINARY option.
|
||||
"""
|
||||
self.write(IAC + WILL + TRANSMIT_BINARY)
|
||||
|
||||
def dataReceived(self, data):
|
||||
if self.controller.handleInput(self, data):
|
||||
self.loseConnection()
|
||||
@@ -105,7 +94,6 @@ class ConsoleController(controller.Controller):
|
||||
"""
|
||||
|
||||
def __init__(self, factory, dom, console_port):
|
||||
#print 'ConsoleController> dom=', dom, type(dom)
|
||||
controller.Controller.__init__(self, factory, dom)
|
||||
self.majorTypes = [ CMSG_CONSOLE ]
|
||||
self.status = "new"
|
||||
@@ -118,7 +106,6 @@ class ConsoleController(controller.Controller):
|
||||
self.registerChannel()
|
||||
self.listener = None
|
||||
self.listen()
|
||||
#print 'ConsoleController<', 'dom=', self.dom, 'idx=', self.idx
|
||||
|
||||
def sxpr(self):
|
||||
val =['console',
|
||||
@@ -143,7 +130,6 @@ class ConsoleController(controller.Controller):
|
||||
|
||||
def close(self):
|
||||
try:
|
||||
#print 'ConsoleController> close dom=', self.dom
|
||||
self.status = "closed"
|
||||
if self.conn:
|
||||
self.conn.loseConnection()
|
||||
@@ -183,11 +169,11 @@ class ConsoleController(controller.Controller):
|
||||
self.listen()
|
||||
|
||||
def requestReceived(self, msg, type, subtype):
|
||||
#print '***Console', self.dom, msg.get_payload()
|
||||
self.rbuf.write(msg.get_payload())
|
||||
self.handleOutput()
|
||||
|
||||
def responseReceived(self, msg, type, subtype):
|
||||
# Just ignore responses.
|
||||
pass
|
||||
|
||||
def produceRequests(self):
|
||||
@@ -215,18 +201,14 @@ class ConsoleController(controller.Controller):
|
||||
Sends it to the connected console (if any).
|
||||
"""
|
||||
if self.closed():
|
||||
#print 'Console>handleOutput> closed'
|
||||
return -1
|
||||
if not self.conn:
|
||||
#print 'Console>handleOutput> not connected'
|
||||
return 0
|
||||
while not self.rbuf.empty():
|
||||
try:
|
||||
#print 'Console>handleOutput> writing...'
|
||||
bytes = self.conn.write(self.rbuf.peek())
|
||||
if bytes > 0:
|
||||
self.rbuf.discard(bytes)
|
||||
except socket.error, error:
|
||||
pass
|
||||
#print 'Console>handleOutput<'
|
||||
return 0
|
||||
@@ -1,3 +1,5 @@
|
||||
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
|
||||
|
||||
from twisted.internet import defer
|
||||
|
||||
import channel
|
||||
@@ -5,6 +7,15 @@ from messages import msgTypeName
|
||||
|
||||
class CtrlMsgRcvr:
|
||||
"""Abstract class for things that deal with a control interface to a domain.
|
||||
|
||||
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
|
||||
|
||||
channel : channel to the domain
|
||||
idx : channel index
|
||||
"""
|
||||
|
||||
|
||||
@@ -17,6 +28,12 @@ class CtrlMsgRcvr:
|
||||
self.idx = None
|
||||
|
||||
def requestReceived(self, msg, type, subtype):
|
||||
"""Dispatch a request to handlers.
|
||||
|
||||
msg message
|
||||
type major message type
|
||||
subtype minor message type
|
||||
"""
|
||||
method = self.subTypes.get(subtype)
|
||||
if method:
|
||||
method(msg, 1)
|
||||
@@ -25,6 +42,12 @@ class CtrlMsgRcvr:
|
||||
% (msgTypeName(type, subtype), type, subtype)), self
|
||||
|
||||
def responseReceived(self, msg, type, subtype):
|
||||
"""Dispatch a response to handlers.
|
||||
|
||||
msg message
|
||||
type major message type
|
||||
subtype minor message type
|
||||
"""
|
||||
method = self.subTypes.get(subtype)
|
||||
if method:
|
||||
method(msg, 0)
|
||||
@@ -33,9 +56,14 @@ class CtrlMsgRcvr:
|
||||
% (msgTypeName(type, subtype), type, subtype)), self
|
||||
|
||||
def lostChannel(self):
|
||||
"""Called when the channel to the domain is lost.
|
||||
"""
|
||||
pass
|
||||
|
||||
def registerChannel(self):
|
||||
"""Register interest in our major message types with the
|
||||
channel to our domain.
|
||||
"""
|
||||
#print 'CtrlMsgRcvr>registerChannel>', self
|
||||
self.channel = self.channelFactory.domChannel(self.dom)
|
||||
self.idx = self.channel.getIndex()
|
||||
@@ -43,21 +71,32 @@ class CtrlMsgRcvr:
|
||||
self.channel.registerDevice(self.majorTypes, self)
|
||||
|
||||
def deregisterChannel(self):
|
||||
"""Deregister interest in our major message types with the
|
||||
channel to our domain.
|
||||
"""
|
||||
#print 'CtrlMsgRcvr>deregisterChannel>', self
|
||||
if self.channel:
|
||||
self.channel.deregisterDevice(self)
|
||||
del self.channel
|
||||
|
||||
def produceRequests(self):
|
||||
"""Produce any queued requests.
|
||||
|
||||
return number produced
|
||||
"""
|
||||
return 0
|
||||
|
||||
def writeRequest(self, msg):
|
||||
"""Write a request to the channel.
|
||||
"""
|
||||
if self.channel:
|
||||
self.channel.writeRequest(msg)
|
||||
else:
|
||||
print 'CtrlMsgRcvr>writeRequest>', 'no channel!', self
|
||||
|
||||
def writeResponse(self, msg):
|
||||
"""Write a response to the channel.
|
||||
"""
|
||||
if self.channel:
|
||||
self.channel.writeResponse(msg)
|
||||
else:
|
||||
@@ -66,6 +105,13 @@ class CtrlMsgRcvr:
|
||||
class ControllerFactory(CtrlMsgRcvr):
|
||||
"""Abstract class for factories creating controllers.
|
||||
Maintains a table of instances.
|
||||
|
||||
Instance variables:
|
||||
|
||||
instances : mapping of index to controller instance
|
||||
dlist : list of deferreds
|
||||
dom : domain
|
||||
timeout : deferred timeout
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
@@ -77,34 +123,49 @@ class ControllerFactory(CtrlMsgRcvr):
|
||||
self.timeout = 10
|
||||
|
||||
def addInstance(self, instance):
|
||||
"""Add a controller instance (under its index).
|
||||
"""
|
||||
self.instances[instance.idx] = instance
|
||||
|
||||
def getInstance(self, idx):
|
||||
"""Get a controller instance from its index.
|
||||
"""
|
||||
return self.instances.get(idx)
|
||||
|
||||
def getInstances(self):
|
||||
"""Get a list of all controller instances.
|
||||
"""
|
||||
return self.instances.values()
|
||||
|
||||
def getInstanceByDom(self, dom):
|
||||
"""Get the controller instance for the given domain.
|
||||
"""
|
||||
for inst in self.instances.values():
|
||||
if inst.dom == dom:
|
||||
return inst
|
||||
return None
|
||||
|
||||
def delInstance(self, instance):
|
||||
#print 'ControllerFactory>delInstance>', instance.idx
|
||||
"""Delete an instance from the table.
|
||||
"""
|
||||
if instance.idx in self.instances:
|
||||
#print 'ControllerFactory>delInstance> remove', instance.idx
|
||||
del self.instances[instance.idx]
|
||||
|
||||
def createInstance(self, dom, recreate=0):
|
||||
"""Create an instance. Define in a subclass.
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
def instanceClosed(self, instance):
|
||||
#print 'ControllerFactory>instanceClosed>', instance.idx, instance
|
||||
"""Callback called when an instance is closed (usually by the instance).
|
||||
"""
|
||||
self.delInstance(instance)
|
||||
|
||||
def addDeferred(self):
|
||||
"""Add a deferred object.
|
||||
|
||||
returns deferred
|
||||
"""
|
||||
d = defer.Deferred()
|
||||
if self.timeout > 0:
|
||||
# The deferred will error if not called before timeout.
|
||||
@@ -113,11 +174,19 @@ class ControllerFactory(CtrlMsgRcvr):
|
||||
return d
|
||||
|
||||
def callDeferred(self, *args):
|
||||
"""Call the top deferred object
|
||||
|
||||
args arguments
|
||||
"""
|
||||
if self.dlist:
|
||||
d = self.dlist.pop(0)
|
||||
d.callback(*args)
|
||||
|
||||
def errDeferred(self, *args):
|
||||
"""Signal an error to the top deferred object.
|
||||
|
||||
args arguments
|
||||
"""
|
||||
if self.dlist:
|
||||
d = self.dlist.pop(0)
|
||||
d.errback(*args)
|
||||
@@ -134,15 +203,20 @@ class Controller(CtrlMsgRcvr):
|
||||
self.idx = None
|
||||
|
||||
def close(self):
|
||||
"""Close the controller.
|
||||
"""
|
||||
self.deregisterChannel()
|
||||
self.lostChannel()
|
||||
|
||||
def lostChannel(self):
|
||||
#print 'Controller>lostChannel>', self, self.factory
|
||||
"""The controller channel has been lost.
|
||||
"""
|
||||
self.factory.instanceClosed(self)
|
||||
|
||||
class Dev:
|
||||
|
||||
"""Abstract class for a device attached to a device controller.
|
||||
"""
|
||||
|
||||
def __init__(self, controller):
|
||||
self.controller = controller
|
||||
self.props = {}
|
||||
@@ -160,9 +234,6 @@ class Dev:
|
||||
if k in self.props:
|
||||
del self.props[k]
|
||||
|
||||
#def __repr__(self):
|
||||
# return str(self.sxpr())
|
||||
|
||||
def sxpr(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
|
||||
|
||||
import channel
|
||||
import controller
|
||||
from messages import *
|
||||
@@ -7,11 +9,23 @@ class DomainControllerFactory(controller.ControllerFactory):
|
||||
"""
|
||||
|
||||
def createInstance(self, dom):
|
||||
"""Create a domain controller.
|
||||
|
||||
dom domain
|
||||
|
||||
returns domain controller
|
||||
"""
|
||||
d = DomainController(self, dom)
|
||||
self.addInstance(d)
|
||||
return d
|
||||
|
||||
def getInstanceByDom(self, dom):
|
||||
"""Get a domain controller for a domain, creating if necessary.
|
||||
|
||||
dom domain
|
||||
|
||||
returns domain controller
|
||||
"""
|
||||
for inst in self.instances.values():
|
||||
if inst.dom == dom:
|
||||
return inst
|
||||
@@ -21,8 +35,11 @@ class DomainControllerFactory(controller.ControllerFactory):
|
||||
|
||||
class DomainController(controller.Controller):
|
||||
"""Generic controller for a domain.
|
||||
Used for domain shutdown.
|
||||
"""
|
||||
|
||||
"""Map shutdown reasons to the message type to use.
|
||||
"""
|
||||
reasons = {'poweroff' : 'shutdown_poweroff_t',
|
||||
'reboot' : 'shutdown_reboot_t',
|
||||
'suspend' : 'shutdown_suspend_t' }
|
||||
@@ -34,6 +51,10 @@ class DomainController(controller.Controller):
|
||||
print 'DomainController>', self, self.channel, self.idx
|
||||
|
||||
def shutdown(self, reason):
|
||||
"""Shutdown a domain.
|
||||
|
||||
reason shutdown reason
|
||||
"""
|
||||
msgtype = self.reasons.get(reason)
|
||||
if not msgtype:
|
||||
raise ValueError('invalid reason:' + reason)
|
||||
|
||||
@@ -148,6 +148,9 @@ netif_formats = {
|
||||
msg_formats.update(netif_formats)
|
||||
|
||||
#============================================================================
|
||||
# Domain shutdown message types.
|
||||
#============================================================================
|
||||
|
||||
CMSG_SHUTDOWN = 6
|
||||
|
||||
CMSG_SHUTDOWN_POWEROFF = 0
|
||||
@@ -177,6 +180,14 @@ class Msg:
|
||||
pass
|
||||
|
||||
def packMsg(ty, params):
|
||||
"""Pack a message.
|
||||
Any 'mac' parameter is passed in as an int[6] array and converted.
|
||||
|
||||
ty message type name
|
||||
params message parameter dict
|
||||
|
||||
returns xu message
|
||||
"""
|
||||
if DEBUG: print '>packMsg', ty, params
|
||||
(major, minor) = msg_formats[ty]
|
||||
args = {}
|
||||
@@ -194,6 +205,15 @@ def packMsg(ty, params):
|
||||
return msg
|
||||
|
||||
def unpackMsg(ty, msg):
|
||||
"""Unpack a message.
|
||||
Any mac addresses in the message are converted to int[6] array
|
||||
in the return dict.
|
||||
|
||||
ty message type
|
||||
msg xu message
|
||||
|
||||
returns parameter dict
|
||||
"""
|
||||
args = msg.get_payload()
|
||||
mac = [0, 0, 0, 0, 0, 0]
|
||||
macs = []
|
||||
@@ -212,6 +232,13 @@ def unpackMsg(ty, msg):
|
||||
return args
|
||||
|
||||
def msgTypeName(ty, subty):
|
||||
"""Convert a message type, subtype pair (ints) to a message type name (string).
|
||||
|
||||
ty integer message type
|
||||
subty integer message subtype
|
||||
|
||||
returns message type name (or None)
|
||||
"""
|
||||
for (name, info) in msg_formats.items():
|
||||
if info[0] == ty and info[1] == subty:
|
||||
return name
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
|
||||
|
||||
import random
|
||||
|
||||
from twisted.internet import defer
|
||||
@@ -30,8 +32,12 @@ class NetifControllerFactory(controller.ControllerFactory):
|
||||
|
||||
def createInstance(self, dom, recreate=0):
|
||||
"""Create or find the network interface controller for a domain.
|
||||
|
||||
dom domain
|
||||
recreate if true this is a recreate (xend restarted)
|
||||
|
||||
returns netif controller
|
||||
"""
|
||||
#print 'netif>createInstance> dom=', dom
|
||||
netif = self.getInstanceByDom(dom)
|
||||
if netif is None:
|
||||
netif = NetifController(self, dom)
|
||||
@@ -39,15 +45,31 @@ class NetifControllerFactory(controller.ControllerFactory):
|
||||
return netif
|
||||
|
||||
def getDomainDevices(self, dom):
|
||||
"""Get the network device controllers for a domain.
|
||||
|
||||
dom domain
|
||||
|
||||
returns netif controller
|
||||
"""
|
||||
netif = self.getInstanceByDom(dom)
|
||||
return (netif and netif.getDevices()) or []
|
||||
|
||||
def getDomainDevice(self, dom, vif):
|
||||
"""Get a virtual network interface device for a domain.
|
||||
|
||||
dom domain
|
||||
vif virtual interface index
|
||||
|
||||
returns NetDev
|
||||
"""
|
||||
netif = self.getInstanceByDom(dom)
|
||||
return (netif and netif.getDevice(vif)) or None
|
||||
|
||||
def setControlDomain(self, dom, recreate=0):
|
||||
"""Set the 'back-end' device driver domain.
|
||||
|
||||
dom domain
|
||||
recreate if true this is a recreate (xend restarted)
|
||||
"""
|
||||
if self.dom == dom: return
|
||||
self.deregisterChannel()
|
||||
@@ -55,13 +77,10 @@ class NetifControllerFactory(controller.ControllerFactory):
|
||||
self.attached = 0
|
||||
self.dom = dom
|
||||
self.registerChannel()
|
||||
#
|
||||
#if xend.netif.be_port.remote_dom != 0:
|
||||
# xend.netif.recovery = True
|
||||
# xend.netif.be_port = xend.main.port_from_dom(dom)
|
||||
#
|
||||
|
||||
def getControlDomain(self):
|
||||
"""Get the domain id of the back-end control domain.
|
||||
"""
|
||||
return self.dom
|
||||
|
||||
def recv_be_create(self, msg, req):
|
||||
@@ -88,23 +107,6 @@ class NetifControllerFactory(controller.ControllerFactory):
|
||||
netif.reattach_devices()
|
||||
self.attached = 1
|
||||
|
||||
## pl = msg.get_payload()
|
||||
## status = pl['status']
|
||||
## if status == NETIF_DRIVER_STATUS_UP:
|
||||
## if xend.netif.recovery:
|
||||
## print "New netif backend now UP, notifying guests:"
|
||||
## for netif_key in interface.list.keys():
|
||||
## netif = interface.list[netif_key]
|
||||
## netif.create()
|
||||
## print " Notifying %d" % netif.dom
|
||||
## msg = xu.message(
|
||||
## CMSG_NETIF_FE,
|
||||
## CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED, 0,
|
||||
## { 'handle' : 0, 'status' : 1 })
|
||||
## netif.ctrlif_tx_req(xend.main.port_from_dom(netif.dom),msg)
|
||||
## print "Done notifying guests"
|
||||
## recovery = False
|
||||
|
||||
class NetDev(controller.Dev):
|
||||
"""Info record for a network device.
|
||||
"""
|
||||
@@ -130,9 +132,13 @@ class NetDev(controller.Dev):
|
||||
return val
|
||||
|
||||
def get_vifname(self):
|
||||
"""Get the virtual interface device name.
|
||||
"""
|
||||
return "vif%d.%d" % (self.controller.dom, self.vif)
|
||||
|
||||
def get_mac(self):
|
||||
"""Get the MAC address as a string.
|
||||
"""
|
||||
return ':'.join(map(lambda x: "%x" % x, self.mac))
|
||||
|
||||
def vifctl_params(self):
|
||||
@@ -141,23 +147,30 @@ class NetDev(controller.Dev):
|
||||
'ipaddr': self.ipaddr }
|
||||
|
||||
def up(self, bridge=None, ipaddr=[]):
|
||||
"""Bring the device up.
|
||||
|
||||
bridge ethernet bridge to connect to
|
||||
ipaddr list of ipaddrs to filter using iptables
|
||||
"""
|
||||
self.bridge = bridge
|
||||
self.ipaddr = ipaddr
|
||||
Vifctl.up(self.get_vifname(), **self.vifctl_params())
|
||||
|
||||
def down(self):
|
||||
"""Bring the device down.
|
||||
"""
|
||||
Vifctl.down(self.get_vifname(), **self.vifctl_params())
|
||||
|
||||
def destroy(self):
|
||||
"""Destroy the device's resources and disconnect from the back-end
|
||||
device controller.
|
||||
"""
|
||||
def cb_destroy(val):
|
||||
self.controller.send_be_destroy(self.vif)
|
||||
print 'NetDev>destroy>', 'vif=', self.vif
|
||||
PrettyPrint.prettyprint(self.sxpr())
|
||||
self.down()
|
||||
d = self.controller.factory.addDeferred()
|
||||
d.addCallback(cb_destroy)
|
||||
self.controller.send_be_disconnect(self.vif)
|
||||
#self.controller.send_be_destroy(self.vif)
|
||||
|
||||
|
||||
class NetifController(controller.Controller):
|
||||
@@ -165,7 +178,6 @@ class NetifController(controller.Controller):
|
||||
"""
|
||||
|
||||
def __init__(self, factory, dom):
|
||||
#print 'NetifController> dom=', dom
|
||||
controller.Controller.__init__(self, factory, dom)
|
||||
self.devices = {}
|
||||
|
||||
@@ -178,21 +190,22 @@ class NetifController(controller.Controller):
|
||||
self.recv_fe_interface_connect,
|
||||
}
|
||||
self.registerChannel()
|
||||
#print 'NetifController<', 'dom=', self.dom, 'idx=', self.idx
|
||||
|
||||
def sxpr(self):
|
||||
val = ['netif', ['dom', self.dom]]
|
||||
return val
|
||||
|
||||
def randomMAC(self):
|
||||
# VIFs get a random MAC address with a "special" vendor id.
|
||||
#
|
||||
# NB. The vendor is currently an "obsolete" one that used to belong
|
||||
# to DEC (AA-00-00). Using it is probably a bit rude :-)
|
||||
#
|
||||
# NB2. The first bit of the first random octet is set to zero for
|
||||
# all dynamic MAC addresses. This may allow us to manually specify
|
||||
# MAC addresses for some VIFs with no fear of clashes.
|
||||
"""Generate a random MAC address.
|
||||
|
||||
The OUI (Organisation Unique Identifier) used is AA:00:00, which
|
||||
is a currently unassigned one that used to belong to DEC.
|
||||
|
||||
The remaining 3 fields are random, with the first bit of the first
|
||||
random field set 0.
|
||||
|
||||
returns array of 6 ints
|
||||
"""
|
||||
mac = [ 0xaa, 0x00, 0x00,
|
||||
random.randint(0x00, 0x7f),
|
||||
random.randint(0x00, 0xff),
|
||||
@@ -200,29 +213,46 @@ class NetifController(controller.Controller):
|
||||
return mac
|
||||
|
||||
def lostChannel(self):
|
||||
print 'NetifController>lostChannel>', 'dom=', self.dom
|
||||
#self.destroyDevices()
|
||||
"""Method called when the channel has been lost.
|
||||
"""
|
||||
controller.Controller.lostChannel(self)
|
||||
|
||||
def getDevices(self):
|
||||
"""Get a list of the devices.
|
||||
"""
|
||||
return self.devices.values()
|
||||
|
||||
def getDevice(self, vif):
|
||||
"""Get a device.
|
||||
|
||||
vif device index
|
||||
|
||||
returns device (or None)
|
||||
"""
|
||||
return self.devices.get(vif)
|
||||
|
||||
def addDevice(self, vif, vmac):
|
||||
"""Add a network interface. If vmac is None a random MAC is
|
||||
assigned. If specified, vmac must be a string of the form
|
||||
XX:XX:XX:XX:XX where X is hex digit.
|
||||
|
||||
vif device index
|
||||
vmac device MAC
|
||||
|
||||
returns device
|
||||
"""
|
||||
if vmac is None:
|
||||
mac = self.randomMAC()
|
||||
else:
|
||||
mac = [ int(x, 16) for x in vmac.split(':') ]
|
||||
if len(mac) != 6: raise ValueError("invalid mac")
|
||||
#print "attach_device>", "vif=", vif, "mac=", mac
|
||||
dev = NetDev(self, vif, mac)
|
||||
self.devices[vif] = dev
|
||||
return dev
|
||||
|
||||
def destroy(self):
|
||||
print 'NetifController>destroy>', 'dom=', self.dom
|
||||
"""Destroy the controller and all devices.
|
||||
"""
|
||||
self.destroyDevices()
|
||||
|
||||
def destroyDevices(self):
|
||||
@@ -306,7 +336,6 @@ class NetifController(controller.Controller):
|
||||
self.factory.writeRequest(msg)
|
||||
|
||||
def send_be_destroy(self, vif):
|
||||
print 'NetifController>send_be_destroy>', 'dom=', self.dom, 'vif=', vif
|
||||
PrettyPrint.prettyprint(self.sxpr())
|
||||
dev = self.devices[vif]
|
||||
del self.devices[vif]
|
||||
|
||||