bitkeeper revision 1.1041.3.1 (40e3fe2a5JO0HpkIeSaP8q6IITbNAQ)

Documentation and a couple of tidies.
This commit is contained in:
mjw@wray-m-3.hpl.hp.com committed 2004-07-01 12:06:02 +00:00
1 parent 50b66608c9
commit 76e8d2ff6a
8 files changed
+265 -96

No files matched your search

+15 -5
View File
@@ -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>')
+42 -17
View File
@@ -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,
+8 -4
View File
@@ -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()
+3 -21
View File
@@ -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
+79 -8
View File
@@ -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()
+21
View File
@@ -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)
+27
View File
@@ -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
+70 -41
View File
@@ -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]
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.