diff options
| author | Jenkins <jenkins@review.openstack.org> | 2012-03-05 19:21:21 +0000 |
|---|---|---|
| committer | Gerrit Code Review <review@openstack.org> | 2012-03-05 19:21:21 +0000 |
| commit | 84dc739b289a81848134184f8bfadfe69835feee (patch) | |
| tree | b43c51547f29ead5306d94f62cd218abf30d847b | |
| parent | f31d94d27248afef8b5fecddb1249a01a9112bf3 (diff) | |
| parent | 3c62c9d65deb463782546afee257af6183cc0928 (diff) | |
Merge "bug #941794 VIF and intf drivers for Quantum Linux Bridge plugin"
| -rw-r--r-- | Authors | 1 | ||||
| -rwxr-xr-x | nova/network/linux_net.py | 82 | ||||
| -rwxr-xr-x | nova/rootwrap/compute.py | 1 | ||||
| -rwxr-xr-x | nova/rootwrap/network.py | 1 | ||||
| -rw-r--r-- | nova/tests/test_libvirt_vif.py | 22 | ||||
| -rw-r--r-- | nova/virt/libvirt/vif.py | 29 |
6 files changed, 135 insertions, 1 deletions
@@ -163,6 +163,7 @@ Scott Moser <smoser@ubuntu.com> Soren Hansen <soren.hansen@rackspace.com> Stanislaw Pitucha <stanislaw.pitucha@hp.com> Stephanie Reese <reese.sm@gmail.com> +Sumit Naiksatam <snaiksat@cisco.com> Thierry Carrez <thierry@openstack.org> Tim Simpson <tim.simpson@rackspace.com> Todd Willey <todd@ansolabs.com> diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index 230755b81..17d1da7b3 100755 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -1125,5 +1125,87 @@ class LinuxOVSInterfaceDriver(LinuxNetInterfaceDriver): dev = "gw-" + str(network['uuid'][0:11]) return dev + +# plugs interfaces using Linux Bridge when using QuantumManager +class QuantumLinuxBridgeInterfaceDriver(LinuxNetInterfaceDriver): + + BRIDGE_NAME_PREFIX = "brq" + GATEWAY_INTERFACE_PREFIX = "gw-" + + def plug(self, network, mac_address, gateway=True): + dev = self.get_dev(network) + bridge = self.get_bridge(network) + if not gateway: + # If we weren't instructed to act as a gateway then add the + # appropriate flows to block all non-dhcp traffic. + # .. and make sure iptbles won't forward it as well. + iptables_manager.ipv4['filter'].add_rule('FORWARD', + '--in-interface %s -j DROP' % bridge) + iptables_manager.ipv4['filter'].add_rule('FORWARD', + '--out-interface %s -j DROP' % bridge) + return bridge + else: + iptables_manager.ipv4['filter'].add_rule('FORWARD', + '--in-interface %s -j ACCEPT' % bridge) + iptables_manager.ipv4['filter'].add_rule('FORWARD', + '--out-interface %s -j ACCEPT' % bridge) + + QuantumLinuxBridgeInterfaceDriver.create_tap_dev(dev, mac_address) + + if not _device_exists(bridge): + LOG.debug(_("Starting bridge %s "), bridge) + utils.execute('brctl', 'addbr', bridge, run_as_root=True) + utils.execute('brctl', 'setfd', bridge, str(0), run_as_root=True) + utils.execute('brctl', 'stp', bridge, 'off', run_as_root=True) + utils.execute('ip', 'link', 'set', bridge, "address", mac_address, + run_as_root=True) + utils.execute('ip', 'link', 'set', bridge, 'up', run_as_root=True) + LOG.debug(_("Done starting bridge %s"), bridge) + + full_ip = '%s/%s' % (network['dhcp_server'], + network['cidr'].rpartition('/')[2]) + utils.execute('ip', 'address', 'add', full_ip, 'dev', bridge, + run_as_root=True) + + return dev + + def unplug(self, network): + dev = self.get_dev(network) + + if not _device_exists(dev): + return None + else: + try: + utils.execute('ip', 'link', 'delete', dev, run_as_root=True) + except exception.ProcessExecutionError: + LOG.warning(_("Failed unplugging gateway interface '%s'"), + dev) + raise + LOG.debug(_("Unplugged gateway interface '%s'"), dev) + return dev + + @classmethod + def create_tap_dev(_self, dev, mac_address=None): + if not _device_exists(dev): + try: + # First, try with 'ip' + utils.execute('ip', 'tuntap', 'add', dev, 'mode', 'tap', + run_as_root=True) + except exception.ProcessExecutionError: + # Second option: tunctl + utils.execute('tunctl', '-b', '-t', dev, run_as_root=True) + if mac_address: + utils.execute('ip', 'link', 'set', dev, "address", mac_address, + run_as_root=True) + utils.execute('ip', 'link', 'set', dev, 'up', run_as_root=True) + + def get_dev(self, network): + dev = self.GATEWAY_INTERFACE_PREFIX + str(network['uuid'][0:11]) + return dev + + def get_bridge(self, network): + bridge = self.BRIDGE_NAME_PREFIX + str(network['uuid'][0:11]) + return bridge + iptables_manager = IptablesManager() interface_driver = utils.import_object(FLAGS.linuxnet_interface_driver) diff --git a/nova/rootwrap/compute.py b/nova/rootwrap/compute.py index 445e797d4..31c0ad91d 100755 --- a/nova/rootwrap/compute.py +++ b/nova/rootwrap/compute.py @@ -98,6 +98,7 @@ filterlist = [ filters.CommandFilter("/sbin/ip", "root"), # nova/virt/libvirt/vif.py: 'tunctl', '-b', '-t', dev + # nova/network/linux_net.py: 'tunctl', '-b', '-t', dev filters.CommandFilter("/usr/sbin/tunctl", "root"), # nova/virt/libvirt/vif.py: 'ovs-vsctl', ... diff --git a/nova/rootwrap/network.py b/nova/rootwrap/network.py index 62fec18e4..f7ae62630 100755 --- a/nova/rootwrap/network.py +++ b/nova/rootwrap/network.py @@ -35,6 +35,7 @@ filterlist = [ # nova/network/linux_net.py: 'ip', 'addr', 'show', 'dev', interface, .. # nova/network/linux_net.py: 'ip', 'link', 'set', dev, "address", .. # nova/network/linux_net.py: 'ip', 'link', 'set', dev, 'up' + # nova/network/linux_net.py: 'ip', 'tuntap', 'add', dev, 'mode', 'tap' filters.CommandFilter("/sbin/ip", "root"), # nova/network/linux_net.py: 'ip[6]tables-save' % (cmd,), '-t', ... diff --git a/nova/tests/test_libvirt_vif.py b/nova/tests/test_libvirt_vif.py index 3f9b8e168..8e0d6627b 100644 --- a/nova/tests/test_libvirt_vif.py +++ b/nova/tests/test_libvirt_vif.py @@ -23,7 +23,9 @@ from nova.virt import firewall from nova.virt import vif from nova.virt.libvirt import connection from nova.virt.libvirt.vif import LibvirtBridgeDriver, \ - LibvirtOpenVswitchDriver, LibvirtOpenVswitchVirtualPortDriver + LibvirtOpenVswitchDriver, \ + LibvirtOpenVswitchVirtualPortDriver, \ + QuantumLinuxBridgeVIFDriver FLAGS = flags.FLAGS @@ -157,3 +159,21 @@ class LibvirtVifTestCase(test.TestCase): self.assertTrue(iface_id_found) d.unplug(None, self.net, self.mapping) + + def test_quantum_bridge_ethernet_driver(self): + d = QuantumLinuxBridgeVIFDriver() + xml = self._get_instance_xml(d, 'ethernet') + + doc = ElementTree.fromstring(xml) + ret = doc.findall('./devices/interface') + self.assertEqual(len(ret), 1) + node = ret[0] + self.assertEqual(node.get("type"), "ethernet") + dev_name = node.find("target").get("dev") + self.assertTrue(dev_name.startswith("tap")) + mac = node.find("mac").get("address") + self.assertEqual(mac, self.mapping['mac']) + script = node.find("script").get("path") + self.assertEquals(script, "") + + d.unplug(None, self.net, self.mapping) diff --git a/nova/virt/libvirt/vif.py b/nova/virt/libvirt/vif.py index ada4a7701..bcf564bce 100644 --- a/nova/virt/libvirt/vif.py +++ b/nova/virt/libvirt/vif.py @@ -172,3 +172,32 @@ class LibvirtOpenVswitchVirtualPortDriver(VIFDriver): def unplug(self, instance, network, mapping): """No action needed. Libvirt takes care of cleanup""" pass + + +class QuantumLinuxBridgeVIFDriver(VIFDriver): + """VIF driver for Linux Bridge when running Quantum.""" + + def get_dev_name(self, iface_id): + return "tap" + iface_id[0:11] + + def plug(self, instance, network, mapping): + iface_id = mapping['vif_uuid'] + dev = self.get_dev_name(iface_id) + linux_net.QuantumLinuxBridgeInterfaceDriver.create_tap_dev(dev) + + result = { + 'script': '', + 'name': dev, + 'mac_address': mapping['mac']} + return result + + def unplug(self, instance, network, mapping): + """Unplug the VIF from the network by deleting the port from + the bridge.""" + dev = self.get_dev_name(mapping['vif_uuid']) + try: + utils.execute('ip', 'link', 'delete', dev, run_as_root=True) + except exception.ProcessExecutionError: + LOG.warning(_("Failed while unplugging vif of instance '%s'"), + instance['name']) + raise |
