xenserver: Hoist identical bridge and vswitch functions into common code.
[sliver-openvswitch.git] / xenserver / opt_xensource_libexec_InterfaceReconfigureVswitch.py
index c083859..41acf58 100644 (file)
@@ -1,5 +1,5 @@
 # Copyright (c) 2008,2009 Citrix Systems, Inc.
 # Copyright (c) 2008,2009 Citrix Systems, Inc.
-# Copyright (c) 2009 Nicira Networks.
+# Copyright (c) 2009,2010 Nicira Networks.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU Lesser General Public License as published
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU Lesser General Public License as published
@@ -36,27 +36,6 @@ def netdev_up(netdev, mtu=None):
 
     run_command(["/sbin/ifconfig", netdev, 'up'] + mtu)
 
 
     run_command(["/sbin/ifconfig", netdev, 'up'] + mtu)
 
-#
-# Bridges
-#
-
-def pif_bridge_name(pif):
-    """Return the bridge name of a pif.
-
-    PIF must not be a VLAN and must be a bridged PIF."""
-
-    pifrec = db().get_pif_record(pif)
-
-    if pif_is_vlan(pif):
-        raise Error("PIF %(uuid)s cannot be a bridge, VLAN is %(VLAN)s" % pifrec)
-
-    nwrec = db().get_network_record(pifrec['network'])
-
-    if nwrec['bridge']:
-        return nwrec['bridge']
-    else:
-        raise Error("PIF %(uuid)s does not have a bridge name" % pifrec)
-
 #
 # PIF miscellanea
 #
 #
 # PIF miscellanea
 #
@@ -89,8 +68,9 @@ def pif_currently_in_use(pif):
 
 def pif_datapath(pif):
     """Return the datapath PIF associated with PIF.
 
 def pif_datapath(pif):
     """Return the datapath PIF associated with PIF.
-For a non-VLAN PIF, the datapath name is the bridge name.
-For a VLAN PIF, the datapath name is the bridge name for the PIF's VLAN slave.
+A non-VLAN PIF is its own datapath PIF, except that a bridgeless PIF has
+no datapath PIF at all.
+A VLAN PIF's datapath PIF is its VLAN slave's datapath PIF.
 """
     if pif_is_vlan(pif):
         return pif_datapath(pif_get_vlan_slave(pif))
 """
     if pif_is_vlan(pif):
         return pif_datapath(pif_get_vlan_slave(pif))
@@ -118,11 +98,11 @@ A VLAN PIF cannot be a datapath PIF.
         return [pif]
 
 def datapath_deconfigure_physical(netdev):
         return [pif]
 
 def datapath_deconfigure_physical(netdev):
-    return ['--', '--if-exists', 'del-port', netdev]
+    return ['--', '--with-iface', '--if-exists', 'del-port', netdev]
 
 def datapath_configure_bond(pif,slaves):
     bridge = pif_bridge_name(pif)
 
 def datapath_configure_bond(pif,slaves):
     bridge = pif_bridge_name(pif)
-    pifrec = db.get_pif_record(pif)
+    pifrec = db().get_pif_record(pif)
     interface = pif_netdev_name(pif)
 
     argv = ['--', '--fake-iface', 'add-bond', bridge, interface]
     interface = pif_netdev_name(pif)
 
     argv = ['--', '--fake-iface', 'add-bond', bridge, interface]
@@ -155,16 +135,15 @@ def datapath_configure_bond(pif,slaves):
     return argv
 
 def datapath_deconfigure_bond(netdev):
     return argv
 
 def datapath_deconfigure_bond(netdev):
-    return ['--', '--if-exists', 'del-port', netdev]
+    return ['--', '--with-iface', '--if-exists', 'del-port', netdev]
 
 def datapath_deconfigure_ipdev(interface):
 
 def datapath_deconfigure_ipdev(interface):
-    return ['--', '--if-exists', 'del-port', interface]
+    return ['--', '--with-iface', '--if-exists', 'del-port', interface]
 
 def datapath_modify_config(commands):
 
 def datapath_modify_config(commands):
-    if debug_mode():
-        log("modifying configuration:")
-        for c in commands:
-            log("  %s" % c)
+    #log("modifying configuration:")
+    #for c in commands:
+    #    log("  %s" % c)
             
     rc = run_command(['/usr/bin/ovs-vsctl'] + ['--timeout=20']
                      + [c for c in commands if not c.startswith('#')])
             
     rc = run_command(['/usr/bin/ovs-vsctl'] + ['--timeout=20']
                      + [c for c in commands if not c.startswith('#')])
@@ -176,7 +155,7 @@ def datapath_modify_config(commands):
 # Toplevel Datapath Configuration.
 #
 
 # Toplevel Datapath Configuration.
 #
 
-def configure_datapath(pif):
+def configure_datapath(pif, parent=None, vlan=None):
     """Bring up the datapath configuration for PIF.
 
     Should be careful not to glitch existing users of the datapath, e.g. other VLANs etc.
     """Bring up the datapath configuration for PIF.
 
     Should be careful not to glitch existing users of the datapath, e.g. other VLANs etc.
@@ -265,16 +244,21 @@ def configure_datapath(pif):
         vsctl_argv += ['# deconfigure physical port %s' % dev]
         vsctl_argv += datapath_deconfigure_physical(dev)
 
         vsctl_argv += ['# deconfigure physical port %s' % dev]
         vsctl_argv += datapath_deconfigure_physical(dev)
 
+    if parent and datapath:
+        vsctl_argv += ['--', '--may-exist', 'add-br', bridge, parent, vlan]
+    else:
+        vsctl_argv += ['--', '--may-exist', 'add-br', bridge]
+
     if len(physical_devices) > 1:
         vsctl_argv += ['# deconfigure bond %s' % pif_netdev_name(pif)]
         vsctl_argv += datapath_deconfigure_bond(pif_netdev_name(pif))
         vsctl_argv += ['# configure bond %s' % pif_netdev_name(pif)]
         vsctl_argv += datapath_configure_bond(pif, physical_devices)
         extra_up_ports += [pif_netdev_name(pif)]
     if len(physical_devices) > 1:
         vsctl_argv += ['# deconfigure bond %s' % pif_netdev_name(pif)]
         vsctl_argv += datapath_deconfigure_bond(pif_netdev_name(pif))
         vsctl_argv += ['# configure bond %s' % pif_netdev_name(pif)]
         vsctl_argv += datapath_configure_bond(pif, physical_devices)
         extra_up_ports += [pif_netdev_name(pif)]
-     else:
+    else:
         iface = pif_netdev_name(physical_devices[0])
         vsctl_argv += ['# add physical device %s' % iface]
         iface = pif_netdev_name(physical_devices[0])
         vsctl_argv += ['# add physical device %s' % iface]
-        vsctl_argv += ['--', 'add-port', bridge, iface]
+        vsctl_argv += ['--', '--may-exist', 'add-port', bridge, iface]
 
     return vsctl_argv,extra_up_ports
 
 
     return vsctl_argv,extra_up_ports
 
@@ -326,19 +310,18 @@ class DatapathVswitch(Datapath):
         extra_ports = []
 
         pifrec = db().get_pif_record(self._pif)
         extra_ports = []
 
         pifrec = db().get_pif_record(self._pif)
+        dprec = db().get_pif_record(self._dp)
 
         ipdev = self._ipdev
         bridge = pif_bridge_name(self._dp)
 
         ipdev = self._ipdev
         bridge = pif_bridge_name(self._dp)
-        c,e = configure_datapath(self._dp)
+        if pif_is_vlan(self._pif):
+            datapath = pif_datapath(self._pif)
+            c,e = configure_datapath(self._dp, datapath, pifrec['VLAN'])
+        else:
+            c,e = configure_datapath(self._dp)
         vsctl_argv += c
         extra_ports += e
 
         vsctl_argv += c
         extra_ports += e
 
-        if pif_is_vlan(pif):
-            datapath = pif_datapath(pif)
-            vsctl_argv += ['--', 'add-br', bridge, datapath, pifrec['VLAN']]
-        else:
-            vsctl_argv += ['--', 'add-br', bridge]
-
         xs_network_uuids = []
         for nwpif in db().get_pifs_by_device(db().get_pif_record(self._pif)['device']):
             rec = db().get_pif_record(nwpif)
         xs_network_uuids = []
         for nwpif in db().get_pifs_by_device(db().get_pif_record(self._pif)['device']):
             rec = db().get_pif_record(nwpif)
@@ -356,16 +339,17 @@ class DatapathVswitch(Datapath):
         vsctl_argv += ['--', 'br-set-external-id', bridge,
                 'xs-network-uuids', ';'.join(xs_network_uuids)]
 
         vsctl_argv += ['--', 'br-set-external-id', bridge,
                 'xs-network-uuids', ';'.join(xs_network_uuids)]
 
-        vsctl_argv += ["# deconfigure ipdev %s" % ipdev]
-        vsctl_argv += datapath_deconfigure_ipdev(ipdev)
-        vsctl_argv += ["# reconfigure ipdev %s" % ipdev]
-        vsctl_argv += ['--', 'add-port', bridge, ipdev]
+        if ipdev != bridge:
+            vsctl_argv += ["# deconfigure ipdev %s" % ipdev]
+            vsctl_argv += datapath_deconfigure_ipdev(ipdev)
+            vsctl_argv += ["# reconfigure ipdev %s" % ipdev]
+            vsctl_argv += ['--', 'add-port', bridge, ipdev]
 
         # XXX Needs support in ovs-vsctl
         #if bridge == ipdev:
 
         # XXX Needs support in ovs-vsctl
         #if bridge == ipdev:
-        #    vsctl_argv += ['--add=bridge.%s.mac=%s' % (bridge, pifrec['MAC'])]
+        #    vsctl_argv += ['--add=bridge.%s.mac=%s' % (bridge, dprec['MAC'])]
         #else:
         #else:
-        #    vsctl_argv += ['--add=iface.%s.mac=%s' % (ipdev, pifrec['MAC'])]
+        #    vsctl_argv += ['--add=iface.%s.mac=%s' % (ipdev, dprec['MAC'])]
 
         self._vsctl_argv = vsctl_argv
         self._extra_ports = extra_ports
 
         self._vsctl_argv = vsctl_argv
         self._extra_ports = extra_ports