diff options
author | Jenkins <jenkins@review.openstack.org> | 2013-06-26 22:22:08 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2013-06-26 22:22:08 +0000 |
commit | ad9e7a83de4e57c44bf9d5e089a548c2f8820867 (patch) | |
tree | f814fb2013e0924d423c06a714677896ef05f5e9 /nova | |
parent | 698a56bcb4e5aaf1546957c05042edff7cca718c (diff) | |
parent | 6caadd1c1badee8da046a42c796490d010e4e83f (diff) | |
download | nova-ad9e7a83de4e57c44bf9d5e089a548c2f8820867.tar.gz nova-ad9e7a83de4e57c44bf9d5e089a548c2f8820867.tar.xz nova-ad9e7a83de4e57c44bf9d5e089a548c2f8820867.zip |
Merge "Adds support for the Indigo Virtual Switch (IVS)"
Diffstat (limited to 'nova')
-rw-r--r-- | nova/network/linux_net.py | 12 | ||||
-rw-r--r-- | nova/network/model.py | 1 | ||||
-rw-r--r-- | nova/tests/virt/libvirt/test_libvirt_vif.py | 80 | ||||
-rw-r--r-- | nova/virt/libvirt/vif.py | 131 |
4 files changed, 218 insertions, 6 deletions
diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index 15be3d3c4..db008cc93 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -1260,6 +1260,18 @@ def delete_ovs_vif_port(bridge, dev): delete_net_dev(dev) +def create_ivs_vif_port(dev, iface_id, mac, instance_id): + utils.execute('ivs-ctl', 'add-port', + dev, run_as_root=True) + + +def delete_ivs_vif_port(dev): + utils.execute('ivs-ctl', 'del-port', dev, + run_as_root=True) + utils.execute('ip', 'link', 'delete', dev, + run_as_root=True) + + def create_tap_dev(dev, mac_address=None): if not device_exists(dev): try: diff --git a/nova/network/model.py b/nova/network/model.py index 4efa70ab6..ce8aa123b 100644 --- a/nova/network/model.py +++ b/nova/network/model.py @@ -30,6 +30,7 @@ def ensure_string_keys(d): # Constants for the 'vif_type' field in VIF class VIF_TYPE_OVS = 'ovs' +VIF_TYPE_IVS = 'ivs' VIF_TYPE_BRIDGE = 'bridge' VIF_TYPE_802_QBG = '802.1qbg' VIF_TYPE_802_QBH = '802.1qbh' diff --git a/nova/tests/virt/libvirt/test_libvirt_vif.py b/nova/tests/virt/libvirt/test_libvirt_vif.py index c9c6aef12..7cbf67b07 100644 --- a/nova/tests/virt/libvirt/test_libvirt_vif.py +++ b/nova/tests/virt/libvirt/test_libvirt_vif.py @@ -103,6 +103,17 @@ class LibvirtVifTestCase(test.TestCase): 'ovs_interfaceid': 'aaa-bbb-ccc', } + mapping_ivs = { + 'mac': 'ca:fe:de:ad:be:ef', + 'gateway_v6': net_ovs['gateway_v6'], + 'ips': [{'ip': '101.168.1.9'}], + 'dhcp_server': '191.168.1.1', + 'vif_uuid': 'vif-xxx-yyy-zzz', + 'vif_devname': 'tap-xxx-yyy-zzz', + 'vif_type': network_model.VIF_TYPE_IVS, + 'ivs_interfaceid': 'aaa-bbb-ccc', + } + mapping_ovs_legacy = { 'mac': 'ca:fe:de:ad:be:ef', 'gateway_v6': net_ovs['gateway_v6'], @@ -411,6 +422,24 @@ class LibvirtVifTestCase(test.TestCase): self.mapping_bridge_quantum, br_want) + def _check_ivs_ethernet_driver(self, d, net, mapping, dev_prefix): + self.flags(firewall_driver="nova.virt.firewall.NoopFirewallDriver") + xml = self._get_instance_xml(d, net, mapping) + + doc = etree.fromstring(xml) + ret = doc.findall('./devices/interface') + self.assertEqual(len(ret), 1) + node = ret[0] + ret = node.findall("filterref") + self.assertEqual(len(ret), 0) + self.assertEqual(node.get("type"), "ethernet") + dev_name = node.find("target").get("dev") + self.assertTrue(dev_name.startswith(dev_prefix)) + mac = node.find("mac").get("address") + self.assertEqual(mac, self.mapping_ivs['mac']) + script = node.find("script").get("path") + self.assertEquals(script, "") + def _check_ovs_ethernet_driver(self, d, net, mapping, dev_prefix): self.flags(firewall_driver="nova.virt.firewall.NoopFirewallDriver") xml = self._get_instance_xml(d, net, mapping) @@ -451,6 +480,33 @@ class LibvirtVifTestCase(test.TestCase): self.mapping_ovs, "tap") + def test_ivs_ethernet_driver(self): + def get_connection(): + return fakelibvirt.Connection("qemu:///session", + False, + 9010) + d = vif.LibvirtGenericVIFDriver(get_connection) + self._check_ivs_ethernet_driver(d, + self.net_ovs, + self.mapping_ivs, + "tap") + + def _check_ivs_virtualport_driver(self, d, net, mapping, want_iface_id): + self.flags(firewall_driver="nova.virt.firewall.NoopFirewallDriver") + xml = self._get_instance_xml(d, net, mapping) + doc = etree.fromstring(xml) + ret = doc.findall('./devices/interface') + self.assertEqual(len(ret), 1) + node = ret[0] + ret = node.findall("filterref") + self.assertEqual(len(ret), 0) + self.assertEqual(node.get("type"), "ethernet") + + tap_name = node.find("target").get("dev") + self.assertEqual(tap_name, mapping['vif_devname']) + mac = node.find("mac").get("address") + self.assertEqual(mac, mapping['mac']) + def _check_ovs_virtualport_driver(self, d, net, mapping, want_iface_id): self.flags(firewall_driver="nova.virt.firewall.NoopFirewallDriver") xml = self._get_instance_xml(d, net, mapping) @@ -502,6 +558,18 @@ class LibvirtVifTestCase(test.TestCase): self.mapping_ovs, want_iface_id) + def test_generic_ivs_virtualport_driver(self): + def get_connection(): + return fakelibvirt.Connection("qemu:///session", + False, + 9011) + d = vif.LibvirtGenericVIFDriver(get_connection) + want_iface_id = self.mapping_ivs['ivs_interfaceid'] + self._check_ivs_virtualport_driver(d, + self.net_ovs, + self.mapping_ivs, + want_iface_id) + def _check_quantum_hybrid_driver(self, d, net, mapping, br_want): self.flags(firewall_driver="nova.virt.firewall.IptablesFirewallDriver") xml = self._get_instance_xml(d, net, mapping) @@ -542,6 +610,18 @@ class LibvirtVifTestCase(test.TestCase): self.mapping_ovs, br_want) + def test_ivs_hybrid_driver(self): + def get_connection(): + return fakelibvirt.Connection("qemu:///session", + False) + d = vif.LibvirtGenericVIFDriver(get_connection) + br_want = "qbr" + self.mapping_ivs['vif_uuid'] + br_want = br_want[:network_model.NIC_NAME_LEN] + self._check_quantum_hybrid_driver(d, + self.net_ovs, + self.mapping_ivs, + br_want) + def test_generic_8021qbh_driver(self): def get_connection(): return fakelibvirt.Connection("qemu:///session", diff --git a/nova/virt/libvirt/vif.py b/nova/virt/libvirt/vif.py index d0a2283e7..9b33a12fe 100644 --- a/nova/virt/libvirt/vif.py +++ b/nova/virt/libvirt/vif.py @@ -228,6 +228,36 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): mapping, image_meta) + def get_config_ivs_hybrid(self, instance, network, mapping, image_meta): + newnet = copy.deepcopy(network) + newnet['bridge'] = self.get_br_name(mapping['vif_uuid']) + return self.get_config_bridge(instance, + newnet, + mapping, + image_meta) + + def get_config_ivs_ethernet(self, instance, network, mapping, image_meta): + conf = super(LibvirtGenericVIFDriver, + self).get_config(instance, + network, + mapping, + image_meta) + + dev = self.get_vif_devname(mapping) + designer.set_vif_host_backend_ethernet_config(conf, dev) + + return conf + + def get_config_ivs(self, instance, network, mapping, image_meta): + if self.get_firewall_required(): + return self.get_config_ivs_hybrid(instance, network, + mapping, + image_meta) + else: + return self.get_config_ivs_ethernet(instance, network, + mapping, + image_meta) + def get_config_802qbg(self, instance, network, mapping, image_meta): conf = super(LibvirtGenericVIFDriver, self).get_config(instance, @@ -271,8 +301,7 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): raise exception.NovaException( _("vif_type parameter must be present " "for this vif_driver implementation")) - - if vif_type == network_model.VIF_TYPE_BRIDGE: + elif vif_type == network_model.VIF_TYPE_BRIDGE: return self.get_config_bridge(instance, network, mapping, image_meta) @@ -288,6 +317,10 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): return self.get_config_802qbh(instance, network, mapping, image_meta) + elif vif_type == network_model.VIF_TYPE_IVS: + return self.get_config_ivs(instance, + network, mapping, + image_meta) else: raise exception.NovaException( _("Unexpected vif_type=%s") % vif_type) @@ -372,6 +405,51 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): else: self.plug_ovs_ethernet(instance, vif) + def plug_ivs_ethernet(self, instance, vif): + super(LibvirtGenericVIFDriver, + self).plug(instance, vif) + + network, mapping = vif + iface_id = self.get_ovs_interfaceid(mapping) + dev = self.get_vif_devname(mapping) + linux_net.create_tap_dev(dev) + linux_net.create_ivs_vif_port(dev, iface_id, mapping['mac'], + instance['uuid']) + + def plug_ivs_hybrid(self, instance, vif): + """Plug using hybrid strategy (same as OVS) + + Create a per-VIF linux bridge, then link that bridge to the OVS + integration bridge via a veth device, setting up the other end + of the veth device just like a normal IVS port. Then boot the + VIF on the linux bridge using standard libvirt mechanisms. + """ + super(LibvirtGenericVIFDriver, + self).plug(instance, vif) + + network, mapping = vif + iface_id = self.get_ovs_interfaceid(mapping) + br_name = self.get_br_name(mapping['vif_uuid']) + v1_name, v2_name = self.get_veth_pair_names(mapping['vif_uuid']) + + if not linux_net.device_exists(br_name): + utils.execute('brctl', 'addbr', br_name, run_as_root=True) + utils.execute('brctl', 'setfd', br_name, 0, run_as_root=True) + utils.execute('brctl', 'stp', br_name, 'off', run_as_root=True) + + if not linux_net.device_exists(v2_name): + linux_net._create_veth_pair(v1_name, v2_name) + utils.execute('ip', 'link', 'set', br_name, 'up', run_as_root=True) + utils.execute('brctl', 'addif', br_name, v1_name, run_as_root=True) + linux_net.create_ivs_vif_port(v2_name, iface_id, mapping['mac'], + instance['uuid']) + + def plug_ivs(self, instance, vif): + if self.get_firewall_required(): + self.plug_ivs_hybrid(instance, vif) + else: + self.plug_ivs_ethernet(instance, vif) + def plug_802qbg(self, instance, vif): super(LibvirtGenericVIFDriver, self).plug(instance, vif) @@ -393,8 +471,7 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): raise exception.NovaException( _("vif_type parameter must be present " "for this vif_driver implementation")) - - if vif_type == network_model.VIF_TYPE_BRIDGE: + elif vif_type == network_model.VIF_TYPE_BRIDGE: self.plug_bridge(instance, vif) elif vif_type == network_model.VIF_TYPE_OVS: self.plug_ovs(instance, vif) @@ -402,6 +479,8 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): self.plug_802qbg(instance, vif) elif vif_type == network_model.VIF_TYPE_802_QBH: self.plug_802qbh(instance, vif) + elif vif_type == network_model.VIF_TYPE_IVS: + self.plug_ivs(instance, vif) else: raise exception.NovaException( _("Unexpected vif_type=%s") % vif_type) @@ -460,6 +539,45 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): else: self.unplug_ovs_ethernet(instance, vif) + def unplug_ivs_ethernet(self, instance, vif): + """Unplug the VIF by deleting the port from the bridge.""" + super(LibvirtGenericVIFDriver, + self).unplug(instance, vif) + + try: + network, mapping = vif + linux_net.delete_ivs_vif_port(self.get_vif_devname(mapping)) + except exception.ProcessExecutionError: + LOG.exception(_("Failed while unplugging vif"), instance=instance) + + def unplug_ivs_hybrid(self, instance, vif): + """UnPlug using hybrid strategy (same as OVS) + + Unhook port from IVS, unhook port from bridge, delete + bridge, and delete both veth devices. + """ + super(LibvirtGenericVIFDriver, + self).unplug(instance, vif) + + try: + network, mapping = vif + br_name = self.get_br_name(mapping['vif_uuid']) + v1_name, v2_name = self.get_veth_pair_names(mapping['vif_uuid']) + + utils.execute('brctl', 'delif', br_name, v1_name, run_as_root=True) + utils.execute('ip', 'link', 'set', br_name, 'down', + run_as_root=True) + utils.execute('brctl', 'delbr', br_name, run_as_root=True) + linux_net.delete_ivs_vif_port(v2_name) + except exception.ProcessExecutionError: + LOG.exception(_("Failed while unplugging vif"), instance=instance) + + def unplug_ivs(self, instance, vif): + if self.get_firewall_required(): + self.unplug_ovs_hybrid(instance, vif) + else: + self.unplug_ovs_ethernet(instance, vif) + def unplug_802qbg(self, instance, vif): super(LibvirtGenericVIFDriver, self).unplug(instance, vif) @@ -481,8 +599,7 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): raise exception.NovaException( _("vif_type parameter must be present " "for this vif_driver implementation")) - - if vif_type == network_model.VIF_TYPE_BRIDGE: + elif vif_type == network_model.VIF_TYPE_BRIDGE: self.unplug_bridge(instance, vif) elif vif_type == network_model.VIF_TYPE_OVS: self.unplug_ovs(instance, vif) @@ -490,6 +607,8 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): self.unplug_802qbg(instance, vif) elif vif_type == network_model.VIF_TYPE_802_QBH: self.unplug_802qbh(instance, vif) + elif vif_type == network_model.VIF_TYPE_IVS: + self.unplug_ivs(instance, vif) else: raise exception.NovaException( _("Unexpected vif_type=%s") % vif_type) |