aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/xenmgr/lib/XendBridge.py182
-rw-r--r--tools/xenmgr/lib/XendDomain.py2
-rw-r--r--tools/xenmgr/lib/XendDomainInfo.py30
-rw-r--r--tools/xenmgr/lib/server/SrvConsoleServer.py8
-rw-r--r--tools/xenmgr/lib/server/SrvServer.py11
-rwxr-xr-xtools/xenmgr/lib/server/blkif.py14
-rwxr-xr-xtools/xenmgr/lib/server/netif.py44
-rw-r--r--tools/xenmgr/netfix124
8 files changed, 290 insertions, 125 deletions
diff --git a/tools/xenmgr/lib/XendBridge.py b/tools/xenmgr/lib/XendBridge.py
new file mode 100644
index 0000000000..1be802477d
--- /dev/null
+++ b/tools/xenmgr/lib/XendBridge.py
@@ -0,0 +1,182 @@
+"""Bridge control utilities.
+"""
+import os
+import os.path
+import re
+import sys
+
+from xenmgr import XendRoot
+xroot = XendRoot.instance()
+
+os.defpath = os.defpath + ':/sbin:/usr/sbin:/usr/local/sbin'
+CMD_IFCONFIG = 'ifconfig'
+CMD_ROUTE = 'route'
+CMD_BRCTL = 'brctl'
+
+DEFAULT_BRIDGE = 'nbe-br'
+DEFAULT_INTERFACE = 'eth0'
+
+opts = None
+
+class Opts:
+
+ def __init__(self, defaults):
+ for (k, v) in defaults.items():
+ setattr(self, k, v)
+ pass
+
+def cmd(p, s):
+ """Print and execute command 'p' with args 's'.
+ """
+ global opts
+ c = p + ' ' + s
+ if opts.verbose: print c
+ if not opts.dryrun:
+ os.system(c)
+
+def default_bridge():
+ return xroot.get_config_value('bridge', DEFAULT_BRIDGE)
+
+def default_interface():
+ return xroot.get_config_value('interface', DEFAULT_INTERFACE)
+
+def vif_dev(dom, vif):
+ """Return the name of the network interface for vif on domain dom.
+ """
+ return "vif%d.%d" % (dom, vif)
+
+def vif_bridge_add(dom, vif, bridge=None):
+ """Add the network interface for vif on dom to a bridge.
+ """
+ if not bridge: bridge = default_bridge()
+ d = { 'bridge': bridge, 'vif': vif_dev(dom, vif) }
+ cmd(CMD_BRCTL, 'addif %(bridge)s %(vif)s' % d)
+ return bridge
+
+def vif_bridge_rem(dom, vif, bridge=None):
+ """Remove the network interface for vif on dom from a bridge.
+ """
+ if not bridge: bridge = default_bridge()
+ print 'vif_bridge_rem>', dom, vif, bridge
+ d = { 'bridge': bridge, 'vif': vif_dev(dom, vif) }
+ cmd(CMD_BRCTL, 'delif %(bridge)s %(vif)s' % d)
+
+def bridge_create(bridge=None, **kwd):
+ """Create a bridge.
+ Defaults hello time to 0, forward delay to 0 and stp off.
+ """
+ if not bridge: bridge = default_bridge()
+ cmd(CMD_BRCTL, 'addbr %s' % bridge)
+ if kwd.get('hello', None) is None:
+ kwd['hello'] = 0
+ if kwd.get('fd', None) is None:
+ kwd['fd'] = 0
+ if kwd.get('stp', None) is None:
+ kwd['stp'] = 'off'
+ bridge_set(bridge, **kwd)
+
+def bridge_set(bridge, hello=None, fd=None, stp=None):
+ """Set bridge parameters.
+ """
+ if hello is not None:
+ cmd(CMD_BRCTL, 'sethello %s %d' % (bridge, hello))
+ if fd is not None:
+ cmd(CMD_BRCTL, 'setfd %s %d' % (bridge, fd))
+ if stp is not None:
+ cmd(CMD_BRCTL, 'stp %s %s' % (bridge, stp))
+
+def bridge_del(bridge=None):
+ """Delete a bridge.
+ """
+ if not bridge: bridge = default_bridge()
+ cmd(CMD_BRCTL, 'delbr %s' % bridge)
+
+def routes():
+ """Return a list of the routes.
+ """
+ fin = os.popen(CMD_ROUTE + ' -n', 'r')
+ routes = []
+ for x in fin:
+ if x.startswith('Kernel'): continue
+ if x.startswith('Destination'): continue
+ x = x.strip()
+ y = x.split()
+ z = { 'destination': y[0],
+ 'gateway' : y[1],
+ 'mask' : y[2],
+ 'flags' : y[3],
+ 'metric' : y[4],
+ 'ref' : y[5],
+ 'use' : y[6],
+ 'interface' : y[7] }
+ routes.append(z)
+ return routes
+
+def ifconfig(interface):
+ """Return the ip config for an interface,
+ """
+ fin = os.popen(CMD_IFCONFIG + ' %s' % interface, 'r')
+ inetre = re.compile('\s*inet\s*addr:(?P<address>\S*)\s*Bcast:(?P<broadcast>\S*)\s*Mask:(?P<mask>\S*)')
+ info = None
+ for x in fin:
+ m = inetre.match(x)
+ if not m: continue
+ info = m.groupdict()
+ info['interface'] = interface
+ break
+ return info
+
+def reconfigure(interface=None, bridge=None):
+ """Reconfigure an interface to be attached to a bridge, and give the bridge
+ the IP address etc. from interface. Move the default route to the interface
+ to the bridge.
+
+ If opts.create is true, creates the bridge.
+ """
+ global opts
+ if not interface: interface = default_interface()
+ if not bridge: bridge = default_bridge()
+ intf_info = ifconfig(interface)
+ if not intf_info:
+ print 'Interface not found:', interface
+ return
+ if opts.create:
+ bridge_create(bridge)
+ #bridge_info = ifconfig(bridge)
+ #if not bridge_info:
+ # print 'Bridge not found:', bridge
+ # return
+ route_info = routes()
+ intf_info['bridge'] = bridge
+ intf_info['gateway'] = None
+ for r in route_info:
+ if (r['destination'] == '0.0.0.0' and
+ 'G' in r['flags'] and
+ r['interface'] == interface):
+ intf_info['gateway'] = r['gateway']
+ if not intf_info['gateway']:
+ print 'Gateway not found: ', interface
+ return
+ cmd(CMD_IFCONFIG,
+ '%(bridge)s %(address)s netmask %(mask)s broadcast %(broadcast)s up'
+ % intf_info)
+ cmd(CMD_ROUTE,
+ 'add default gateway %(gateway)s dev %(bridge)s'
+ % intf_info)
+ cmd(CMD_BRCTL, 'addif %(bridge)s %(interface)s' % intf_info)
+ cmd(CMD_IFCONFIG, '%(interface)s 0.0.0.0' % intf_info)
+
+defaults = {
+ 'interface': default_interface(),
+ 'bridge' : default_bridge(),
+ 'verbose' : 1,
+ 'dryrun' : 0,
+ 'create' : 0,
+ }
+
+opts = Opts(defaults)
+
+def set_opts(val):
+ global opts
+ opts = val
+ return opts
diff --git a/tools/xenmgr/lib/XendDomain.py b/tools/xenmgr/lib/XendDomain.py
index d3cddc4e75..f236a43d80 100644
--- a/tools/xenmgr/lib/XendDomain.py
+++ b/tools/xenmgr/lib/XendDomain.py
@@ -8,7 +8,6 @@ import sys
import Xc; xc = Xc.new()
import xenctl.ip
-import xenctl.vdisk
import sxp
import XendRoot
@@ -125,6 +124,7 @@ class XendDomain:
def _delete_domain(self, id, notify=1):
if id in self.domain:
+ self.domain[id].died()
if notify: eserver.inject('xend.domain.died', id)
del self.domain[id]
if id in self.domain_db:
diff --git a/tools/xenmgr/lib/XendDomainInfo.py b/tools/xenmgr/lib/XendDomainInfo.py
index 067f2f5d31..3828fcf2ec 100644
--- a/tools/xenmgr/lib/XendDomainInfo.py
+++ b/tools/xenmgr/lib/XendDomainInfo.py
@@ -17,7 +17,6 @@ import os
from twisted.internet import defer
import Xc; xc = Xc.new()
-
import xenctl.ip
import sxp
@@ -25,6 +24,8 @@ import sxp
import XendConsole
xendConsole = XendConsole.instance()
+import XendBridge
+
import server.SrvConsoleServer
xend = server.SrvConsoleServer.instance()
@@ -125,7 +126,7 @@ class XendDomainInfo:
sxpr.append(['state', state])
if self.info['shutdown']:
reasons = ["poweroff", "reboot", "suspend"]
- reason = reasons[info['shutdown_reason']]
+ reason = reasons[self.info['shutdown_reason']]
sxpr.append(['shutdown_reason', reason])
sxpr.append(['cpu', self.info['cpu']])
sxpr.append(['cpu_time', self.info['cpu_time']/1e9])
@@ -183,6 +184,18 @@ class XendDomainInfo:
return 0
return xc.domain_destroy(dom=self.dom)
+ def died(self):
+ print 'died>', self.dom
+ self.release_vifs()
+
+ def release_vifs(self):
+ print 'release_vifs>', self.dom
+ vifs = self.get_devices('vif')
+ for v in vifs:
+ vif = sxp.child_value(v, 'vif')
+ bridge = sxp.child_value(v, 'bridge')
+ XendBridge.vif_bridge_rem(self.dom, vif, bridge)
+
def show(self):
"""Print virtual machine info.
"""
@@ -264,7 +277,7 @@ def lookup_disk_uname( uname ):
segments = None
return segments
-def make_disk(dom, uname, dev, mode, sharing):
+def make_disk(dom, uname, dev, mode):
"""Create a virtual disk device for a domain.
@returns Deferred
@@ -689,10 +702,14 @@ def vm_dev_vif(vm, val, index):
raise VmError('vif: vif in control domain')
vif = index #todo
vmac = sxp.child_value(val, "mac")
- bridge = sxp.child_value(val, "bridge") # todo
defer = make_vif(vm.dom, vif, vmac)
def fn(id):
- dev = val + ['vif', vif]
+ bridge = sxp.child_value(val, "bridge")
+ bridge = XendBridge.vif_bridge_add(vm.dom, vif, bridge)
+ dev = ['vif', ['vif', vif], ['bridge', bridge] ]
+ netdev = xend.netif_dev(vm.dom, vif)
+ if netdev and netdev.mac:
+ dev += [ 'mac', netdev.mac ]
vm.add_device('vif', dev)
print 'vm_dev_vif> created', dev
return id
@@ -715,8 +732,7 @@ def vm_dev_vbd(vm, val, index):
if not dev:
raise VMError('vbd: Missing dev')
mode = sxp.child_value(val, 'mode', 'r')
- sharing = sxp.child_value(val, 'sharing', 'rr')
- defer = make_disk(vm.dom, uname, dev, mode, sharing)
+ defer = make_disk(vm.dom, uname, dev, mode)
def fn(vbd):
vm.add_device('vbd', val)
return vbd
diff --git a/tools/xenmgr/lib/server/SrvConsoleServer.py b/tools/xenmgr/lib/server/SrvConsoleServer.py
index 21d39140b2..7179a0d1d4 100644
--- a/tools/xenmgr/lib/server/SrvConsoleServer.py
+++ b/tools/xenmgr/lib/server/SrvConsoleServer.py
@@ -549,7 +549,7 @@ class Daemon:
self.listenEvent()
self.listenNotifier()
self.listenVirq()
- SrvServer.create()
+ SrvServer.create(bridge=1)
reactor.run()
def createFactories(self):
@@ -602,6 +602,9 @@ class Daemon:
d = self.blkifCF.createInstance(dom)
return d
+ def blkif_dev(self, dom, vdev):
+ return self.blkifCF.getDomainDevice(dom, vdev)
+
def blkif_dev_create(self, dom, vdev, mode, segment):
"""Create a block device.
@@ -641,6 +644,9 @@ class Daemon:
d = ctrl.attach_device(vif, vmac)
return d
+ def netif_dev(self, dom, vif):
+ return self.netifCF.getDomainDevice(dom, vif)
+
def console_create(self, dom, console_port=None):
"""Create a console for a domain.
"""
diff --git a/tools/xenmgr/lib/server/SrvServer.py b/tools/xenmgr/lib/server/SrvServer.py
index a42219b620..d507c2002b 100644
--- a/tools/xenmgr/lib/server/SrvServer.py
+++ b/tools/xenmgr/lib/server/SrvServer.py
@@ -32,17 +32,24 @@ from twisted.internet import reactor
from xenmgr import XendRoot
xroot = XendRoot.instance()
+from xenmgr import XendBridge
+
from SrvRoot import SrvRoot
-def create(port=None, interface=None):
+def create(port=None, interface=None, bridge=0):
if port is None: port = 8000
if interface is None: interface = ''
+ if bridge or xroot.rebooted:
+ init_bridge()
root = resource.Resource()
xend = SrvRoot()
root.putChild('xend', xend)
site = server.Site(root)
reactor.listenTCP(port, site, interface=interface)
-
+
+def init_bridge():
+ XendBridge.bridge_create()
+ XendBridge.reconfigure()
def main(port=None, interface=None):
create(port, interface)
diff --git a/tools/xenmgr/lib/server/blkif.py b/tools/xenmgr/lib/server/blkif.py
index 7ffa35179d..8da827baa9 100755
--- a/tools/xenmgr/lib/server/blkif.py
+++ b/tools/xenmgr/lib/server/blkif.py
@@ -33,6 +33,14 @@ class BlkifControllerFactory(controller.ControllerFactory):
blkif.send_be_create()
return d
+ def getDomainDevices(self, dom):
+ blkif = self.getInstanceByDom(dom)
+ return (blkif and blkif.getDevices()) or []
+
+ def getDomainDevice(self, dom, vdev):
+ blkif = self.getInstanceByDom(dom)
+ return (blkif and blkif.getDevice(vdev)) or None
+
def setControlDomain(self, dom):
if self.dom == dom: return
self.deregisterChannel()
@@ -146,6 +154,12 @@ class BlkifController(controller.Controller):
self.registerChannel()
#print 'BlkifController<', 'dom=', self.dom, 'idx=', self.idx
+ def getDevices(self):
+ return self.devices.values()
+
+ def getDevice(self, vdev):
+ return self.devices.get(vdev)
+
def attach_device(self, vdev, mode, segment):
"""Attach a device to the specified interface.
"""
diff --git a/tools/xenmgr/lib/server/netif.py b/tools/xenmgr/lib/server/netif.py
index 13bdd96486..f3da86ba82 100755
--- a/tools/xenmgr/lib/server/netif.py
+++ b/tools/xenmgr/lib/server/netif.py
@@ -31,6 +31,14 @@ class NetifControllerFactory(controller.ControllerFactory):
netif = NetifController(self, dom)
self.addInstance(netif)
return netif
+
+ def getDomainDevices(self, dom):
+ netif = self.getInstanceByDom(dom)
+ return (netif and netif.getDevices()) or []
+
+ def getDomainDevice(self, dom, vif):
+ netif = self.getInstanceByDom(dom)
+ return (netif and netif.getDevice(vif)) or None
def setControlDomain(self, dom):
"""Set the 'back-end' device driver domain.
@@ -98,6 +106,11 @@ class NetDev:
self.vif = vif
self.mac = mac
self.evtchn = None
+
+ def sxpr(self):
+ vif = str(self.vif)
+ mac = ':'.join(map(lambda x: "%x" % x, self.mac))
+ return ['netif', ['vif', vif], ['mac', mac]]
class NetifController(controller.Controller):
"""Network interface controller. Handles all network devices for a domain.
@@ -135,20 +148,37 @@ class NetifController(controller.Controller):
random.randint(0x00, 0xff) ]
return mac
- def attach_device(self, vif, vmac):
- """Attach a network device.
- If vmac is None a random mac address is assigned.
+ def lostChannel(self):
+ print 'NetifController>lostChannel>', 'dom=', self.dom
+ #for vif in self.devices:
+ # self.send_be_destroy(vif)
+ controller.Controller.lostChannel(self)
- @param vif interface index
- @param vmac mac address (string)
- """
+ def getDevices(self):
+ return self.devices.values()
+
+ def getDevice(self, vif):
+ return self.devices.get(vif)
+
+ def addDevice(self, vif, vmac):
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
- self.devices[vif] = NetDev(vif, mac)
+ dev = NetDev(vif, mac)
+ self.devices[vif] = dev
+ return dev
+
+ def attach_device(self, vif, vmac):
+ """Attach a network device.
+ If vmac is None a random mac address is assigned.
+
+ @param vif interface index
+ @param vmac mac address (string)
+ """
+ self.addDevice(vif, vmac)
d = self.factory.addDeferred()
self.send_be_create(vif)
return d
diff --git a/tools/xenmgr/netfix b/tools/xenmgr/netfix
index 65c354490d..998a78a0d9 100644
--- a/tools/xenmgr/netfix
+++ b/tools/xenmgr/netfix
@@ -3,102 +3,15 @@
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
#============================================================================
# Move the IP address from eth0 onto the Xen bridge (nbe-br).
-# Works best if the bridge control utils (brctl) have been installed.
+# Only works if the bridge control utils (brctl) have been installed.
#============================================================================
-import os
-import os.path
-import re
-import sys
from getopt import getopt
+from xenmgr.XendBridge import *
-os.defpath = os.defpath+':/sbin:/usr/sbin:/usr/local/sbin'
-CMD_IFCONFIG = 'ifconfig'
-CMD_ROUTE = 'route'
-CMD_BRCTL = 'brctl'
-
-def routes():
- """Return a list of the routes.
- """
- fin = os.popen(CMD_ROUTE + ' -n', 'r')
- routes = []
- for x in fin:
- if x.startswith('Kernel'): continue
- if x.startswith('Destination'): continue
- x = x.strip()
- y = x.split()
- z = { 'destination': y[0],
- 'gateway' : y[1],
- 'mask' : y[2],
- 'flags' : y[3],
- 'metric' : y[4],
- 'ref' : y[5],
- 'use' : y[6],
- 'interface' : y[7] }
- routes.append(z)
- return routes
-
-def cmd(p, s):
- """Print and execute command 'p' with args 's'.
- """
- global opts
- c = p + ' ' + s
- if opts.verbose: print c
- if not opts.dryrun:
- os.system(c)
-
-def ifconfig(interface):
- """Return the ip config for an interface,
- """
- fin = os.popen(CMD_IFCONFIG + ' %s' % interface, 'r')
- inetre = re.compile('\s*inet\s*addr:(?P<address>\S*)\s*Bcast:(?P<broadcast>\S*)\s*Mask:(?P<mask>\S*)')
- info = None
- for x in fin:
- m = inetre.match(x)
- if not m: continue
- info = m.groupdict()
- info['interface'] = interface
- break
- return info
-
-def reconfigure(interface, bridge):
- """Reconfigure an interface to be attached to a bridge, and give the bridge
- the IP address etc. from interface. Move the default route to the interface
- to the bridge.
- """
- intf_info = ifconfig(interface)
- if not intf_info:
- print 'Interface not found:', interface
- return
- #bridge_info = ifconfig(bridge)
- #if not bridge_info:
- # print 'Bridge not found:', bridge
- # return
- route_info = routes()
- intf_info['bridge'] = bridge
- intf_info['gateway'] = None
- for r in route_info:
- if (r['destination'] == '0.0.0.0' and
- 'G' in r['flags'] and
- r['interface'] == interface):
- intf_info['gateway'] = r['gateway']
- if not intf_info['gateway']:
- print 'Gateway not found: ', interface
- return
- cmd(CMD_IFCONFIG, '%(bridge)s %(address)s netmask %(mask)s broadcast %(broadcast)s up' % intf_info)
- cmd(CMD_ROUTE, 'add default gateway %(gateway)s dev %(bridge)s' % intf_info)
- cmd(CMD_BRCTL, 'addif %(bridge)s %(interface)s' % intf_info)
- cmd(CMD_IFCONFIG, '%(interface)s 0.0.0.0' % intf_info)
-
-defaults = {
- 'interface': 'eth0',
- 'bridge' : 'nbe-br',
- 'verbose' : 1,
- 'dryrun' : 0,
- }
-
-short_options = 'hvqni:b:'
-long_options = ['help', 'verbose', 'quiet', 'interface=', 'bridge=']
+short_options = 'hvqni:b:c'
+long_options = ['help', 'verbose', 'quiet',
+ 'interface=', 'bridge=', 'create']
def usage():
print """Usage:
@@ -107,12 +20,13 @@ def usage():
Reconfigure routing so that <bridge> has the IP address from
<interface>. This lets IP carry on working when <interface>
is attached to <bridge> for virtual networking.
- If brctl is available, <interface> is added to <bridge>,
+ Uses brctl to add <interface> to <bridge>,
so this can be run before any domains have been created.
""" % sys.argv[0]
print """
-i, --interface <interface> interface, default %(interface)s.
-b, --bridge <bridge> bridge, default %(bridge)s.
+ -c, --create create the bridge.
-v, --verbose Print commands.
-q, --quiet Don't print commands.
-n, --dry-run Don't execute commands.
@@ -120,32 +34,28 @@ def usage():
""" % defaults
sys.exit(1)
-class Opts:
-
- def __init__(self, defaults):
- for (k, v) in defaults.items():
- setattr(self, k, v)
- pass
def main():
- global opts
- opts = Opts(defaults)
+ lopts = set_opts(Opts(defaults))
+ lopts.dryrun = 0
(options, args) = getopt(sys.argv[1:], short_options, long_options)
if args: usage()
for k, v in options:
if k in ['-h', '--help']:
usage()
+ elif k in ['-c', '--create']:
+ lopts.create = 1
elif k in ['-i', '--interface']:
- opts.interface = v
+ lopts.interface = v
elif k in ['-b', '--bridge']:
- opts.bridge = v
+ lopts.bridge = v
elif k in ['-q', '--quiet']:
- opts.verbose = 0
+ lopts.verbose = 0
elif k in ['-v', '--verbose']:
- opts.verbose = 1
+ lopts.verbose = 1
elif k in ['-n', '--dry-run']:
- opts.dryrun = 1
- reconfigure(opts.interface, opts.bridge)
+ lopts.dryrun = 1
+ reconfigure(lopts.interface, lopts.bridge)
if __name__ == '__main__':
main()