#! /usr/bin/python # # Copyright (c) 2009, 2010 Nicira Networks. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import getopt import os import re import subprocess import sys argv0 = sys.argv[0] BRCTL = "/usr/lib/openvswitch/xs-original/brctl" VSCTL = "/usr/bin/ovs-vsctl" OVSDB_SERVER = "unix:/var/run/openvswitch/db.sock" # Execute the real brctl program, passing the same arguments that were passed # to us. def delegate(): os.execl(BRCTL, BRCTL, *sys.argv[1:]) # execl should never return. We only arrive here if brctl failed to exec. sys.exit(1) def call_vsctl(cmd, arg=""): database = '--db=' + OVSDB_SERVER command = [VSCTL, database, cmd] if (arg): command.append(arg) return subprocess.Popen(command, stdout=subprocess.PIPE).communicate()[0].split() # Returns a list of all the bridges def get_bridges(): return call_vsctl('list-br') # Returns a list of all ports on 'bridge' def get_bridge_ports(bridge): return call_vsctl('list-ports', bridge) # Returns a list of all interfaces on 'bridge' def get_bridge_ifaces(bridge): return call_vsctl('list-ifaces', bridge) # Returns the parent of 'bridge'. If 'bridge' does not have a parent, # 'bridge' is returned. def get_bridge_parent(bridge): return call_vsctl('br-to-parent', bridge) # Returns the first line of the file named 'name', with the trailing new-line # (if any) stripped off. def read_first_line_of_file(name): file = None try: file = open(name, 'r') return file.readline().rstrip('\n') finally: if file != None: file.close() # Returns a bridge ID constructed from the MAC address of network device # 'netdev', in the format "8000.000102030405". def get_bridge_id(netdev): try: hwaddr = read_first_line_of_file("/sys/class/net/%s/address" % netdev) return "8000.%s" % (hwaddr.replace(":", "")) except: return "8000.002320ffffff" def cmd_show(): print "bridge name\tbridge id\t\tSTP enabled\tinterfaces" # Find all the bridges. bridges = get_bridges() # Find all the interfaces on each bridge. for bridge in bridges: bridge_ports = get_bridge_ports(bridge) parent = get_bridge_parent(bridge) if parent in bridge_ports: bridge_ports.remove(parent) bridge_ports.sort() bridge_id = get_bridge_id(bridge) first_port = "" if bridge_ports: first_port = bridge_ports[0] print "%s\t\t%s\t%s\t\t%s" % (bridge, bridge_id, "no", first_port) for port in bridge_ports[1:]: print "\t\t\t\t\t\t\t%s" % port def main(): # Check the network configuration mode. try: network_mode = read_first_line_of_file('/etc/xensource/network.conf') if network_mode == 'bridge': delegate() except: # File probably doesn't exist pass # Parse the command line. try: options, args = getopt.gnu_getopt(sys.argv[1:], "hV", ["help", "version"]) except getopt.GetoptError, msg: sys.stderr.write("%s: %s (use --help for help)\n" % (argv0, msg)) sys.exit(1) # Handle command-line options. for opt, optarg in options: if opt == "-h" or opt == "--help": delegate() elif opt == "-V" or opt == "--version": subprocess.call([BRCTL, "--version"]) print "Open vSwitch brctl wrapper" sys.exit(0) # Execute commands. Most commands are delegated to the brctl binary that # we are wrapping, but we implement the "show" command ourselves. if args and args[0] == "show": cmd_show() else: delegate() if __name__ == "__main__": main()