From 58dc54f52a0282d433f78a5294d30f6a3d06d5ce Mon Sep 17 00:00:00 2001 From: Abhishek Raut Date: Fri, 19 Aug 2016 21:57:57 -0700 Subject: [PATCH] NSXv3: Fix tap-flow-create to use floating IP of destination port This patch changes the workflow for L3 SPAN such that the destination port must have a L3 reachable IP address i.e. a floating IP so that L3 SPAN can work. Unit tests will be added in a separate patch. Change-Id: Ie0c2aed71988cbbd9cba60bb1fcb1ec30d0b4bc4 --- vmware_nsx/plugins/nsx_v3/plugin.py | 12 ++++++++++++ .../services/neutron_taas/nsx_v3/driver.py | 18 ++++++++++++------ .../services/neutron_taas/test_nsxv3_driver.py | 3 +++ 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/vmware_nsx/plugins/nsx_v3/plugin.py b/vmware_nsx/plugins/nsx_v3/plugin.py index afc2dcd85c..dda69dbb31 100644 --- a/vmware_nsx/plugins/nsx_v3/plugin.py +++ b/vmware_nsx/plugins/nsx_v3/plugin.py @@ -2593,6 +2593,18 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, if floatingip['floatingip']['port_id'] else const.FLOATINGIP_STATUS_DOWN)) + def get_floatingips(self, context, filters=None, fields=None, + sorts=None, limit=None, marker=None, + page_reverse=False): + #NOTE(abhiraut): Although this method does not do anything fancy + # we have defined it here so that TaaS driver + # can retrieve floating IP for a particular port ID + # using filters. + return super(NsxV3Plugin, self).get_floatingips( + context, filters=filters, fields=fields, + sorts=sorts, limit=limit, marker=marker, + page_reverse=page_reverse) + def create_floatingip(self, context, floatingip): new_fip = self._create_floating_ip_wrapper(context, floatingip) router_id = new_fip['router_id'] diff --git a/vmware_nsx/services/neutron_taas/nsx_v3/driver.py b/vmware_nsx/services/neutron_taas/nsx_v3/driver.py index 52d2d12f71..724170b149 100644 --- a/vmware_nsx/services/neutron_taas/nsx_v3/driver.py +++ b/vmware_nsx/services/neutron_taas/nsx_v3/driver.py @@ -195,22 +195,28 @@ class NsxV3Driver(base_driver.TaasBaseDriver, tags): """Create a PortMirroring SwitchingProfile for L3SPAN.""" tf = context.tap_flow - dest_port = self._get_port_details(context._plugin_context, - dest_port_id) + # Verify whether destination port is L3 reachable. i.e. destination + # port has a floating IP address. + fips = self._nsx_plugin.get_floatingips( + context._plugin_context, filters={'port_id': dest_port_id}) + if not fips: + msg = (_("Destination port %s must have a floating IP for " + "L3 SPAN") % dest_port_id) + raise nsx_exc.NsxTaaSDriverException(msg=msg) destinations = [] # Retrieve destination port's IP addresses and add it to the list # since the backend expects a list of IP addresses. - for fixed_ip in dest_port['fixed_ips']: + for fip in fips: # NOTE(abhiraut): nsx-v3 doesn't seem to handle ipv6 addresses # currently so for now we remove them here and do not pass # them to the backend which would raise an error. - if netaddr.IPNetwork(fixed_ip['ip_address']).version == 6: + if netaddr.IPNetwork(fip['floating_ip_address']).version == 6: LOG.warning(_LW("Skipping IPv6 address %(ip)s for L3SPAN " "tap flow: %(tap_flow)s"), {'tap_flow': tf['id'], - 'ip': fixed_ip['ip_address']}) + 'ip': fip['floating_ip_address']}) continue - destinations.append(fixed_ip['ip_address']) + destinations.append(fip['floating_ip_address']) # Create a switch profile in the backend. try: port_mirror_profile = (self._nsx_plugin._switching_profiles. diff --git a/vmware_nsx/tests/unit/services/neutron_taas/test_nsxv3_driver.py b/vmware_nsx/tests/unit/services/neutron_taas/test_nsxv3_driver.py index 32295b8563..a1dd8b2afd 100644 --- a/vmware_nsx/tests/unit/services/neutron_taas/test_nsxv3_driver.py +++ b/vmware_nsx/tests/unit/services/neutron_taas/test_nsxv3_driver.py @@ -45,6 +45,9 @@ class TestNsxV3TaaSDriver(test_taas_db.TaaSDbTestCase, return_value=mock.MagicMock()).start() self.taas_plugin = taas_plugin.TaasPlugin() self.core_plugin = importutils.import_object(NSX_V3_PLUGIN_CLASS) + mock.patch( + 'vmware_nsx.plugins.nsx_v3.plugin.NsxV3Plugin.get_floatingips', + return_value=([{'floating_ip_address': '172.10.10.10'}])).start() self.ctx = context.get_admin_context() def test_validate_tap_flow_same_network_same_port_fail(self):