diff options
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/xenmgr/lib/XendBridge.py | 182 | ||||
| -rw-r--r-- | tools/xenmgr/lib/XendDomain.py | 2 | ||||
| -rw-r--r-- | tools/xenmgr/lib/XendDomainInfo.py | 30 | ||||
| -rw-r--r-- | tools/xenmgr/lib/server/SrvConsoleServer.py | 8 | ||||
| -rw-r--r-- | tools/xenmgr/lib/server/SrvServer.py | 11 | ||||
| -rwxr-xr-x | tools/xenmgr/lib/server/blkif.py | 14 | ||||
| -rwxr-xr-x | tools/xenmgr/lib/server/netif.py | 44 | ||||
| -rw-r--r-- | tools/xenmgr/netfix | 124 |
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() |
