summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2012-03-05 19:21:21 +0000
committerGerrit Code Review <review@openstack.org>2012-03-05 19:21:21 +0000
commit84dc739b289a81848134184f8bfadfe69835feee (patch)
treeb43c51547f29ead5306d94f62cd218abf30d847b
parentf31d94d27248afef8b5fecddb1249a01a9112bf3 (diff)
parent3c62c9d65deb463782546afee257af6183cc0928 (diff)
Merge "bug #941794 VIF and intf drivers for Quantum Linux Bridge plugin"
-rw-r--r--Authors1
-rwxr-xr-xnova/network/linux_net.py82
-rwxr-xr-xnova/rootwrap/compute.py1
-rwxr-xr-xnova/rootwrap/network.py1
-rw-r--r--nova/tests/test_libvirt_vif.py22
-rw-r--r--nova/virt/libvirt/vif.py29
6 files changed, 135 insertions, 1 deletions
diff --git a/Authors b/Authors
index dc83d82e8..b6526470b 100644
--- a/Authors
+++ b/Authors
@@ -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