From b448aba9b8d1f399b4e0d9c14de5d0261d3fc009 Mon Sep 17 00:00:00 2001
From: Gary Kotton <gkotton@vmware.com>
Date: Sun, 14 Jan 2018 00:58:30 -0800
Subject: [PATCH] NSX|V: enable binding floating ip's per AZ

Enable admin to enable this config variable per AZ.

Change-Id: I19ee2b4adf49e9bcd3e6004dc76d61761bb81b92
---
 .../bind-floating-ips-per-az-142f0de7ebfae1c8.yaml     | 10 ++++++++++
 vmware_nsx/common/config.py                            |  6 ++++++
 vmware_nsx/plugins/nsx_v/availability_zones.py         |  6 ++++++
 .../plugins/nsx_v/drivers/abstract_router_driver.py    |  2 ++
 .../plugins/nsx_v/drivers/shared_router_driver.py      |  7 +++++--
 vmware_nsx/plugins/nsx_v/vshield/edge_utils.py         |  7 +++++--
 6 files changed, 34 insertions(+), 4 deletions(-)
 create mode 100644 releasenotes/notes/bind-floating-ips-per-az-142f0de7ebfae1c8.yaml

diff --git a/releasenotes/notes/bind-floating-ips-per-az-142f0de7ebfae1c8.yaml b/releasenotes/notes/bind-floating-ips-per-az-142f0de7ebfae1c8.yaml
new file mode 100644
index 0000000000..8d3f53770d
--- /dev/null
+++ b/releasenotes/notes/bind-floating-ips-per-az-142f0de7ebfae1c8.yaml
@@ -0,0 +1,10 @@
+---
+prelude: >
+    Enable 'bind_floatingip_to_all_interfaces' to be configured per
+    availability zone.
+features:
+  - |
+    Enable 'bind_floatingip_to_all_interfaces' to be configured per
+    availability zone. This will enable an admin to ensure that an AZ
+    can have flotaing IP's configured on all edge vNICS. This enables VM's
+    on the same subnet to communicate via floating IP's.
diff --git a/vmware_nsx/common/config.py b/vmware_nsx/common/config.py
index 4fb959994f..4ff7d993f6 100644
--- a/vmware_nsx/common/config.py
+++ b/vmware_nsx/common/config.py
@@ -777,6 +777,12 @@ nsxv_az_opts = [
     cfg.BoolOpt('exclusive_dhcp_edge',
                 default=False,
                 help=_("(Optional) Have exclusive DHCP edge per network.")),
+    cfg.BoolOpt('bind_floatingip_to_all_interfaces', default=False,
+                help=_("If set to False, router will associate floating ip "
+                       "with external interface of only, thus denying "
+                       "connectivity between hosts on same network via "
+                       "their floating ips. If True, floating ip will "
+                       "be associated with all router interfaces.")),
 ]
 
 # define the configuration of each NSX-V3 availability zone.
diff --git a/vmware_nsx/plugins/nsx_v/availability_zones.py b/vmware_nsx/plugins/nsx_v/availability_zones.py
index 4679c27f3a..6df37d8264 100644
--- a/vmware_nsx/plugins/nsx_v/availability_zones.py
+++ b/vmware_nsx/plugins/nsx_v/availability_zones.py
@@ -67,6 +67,8 @@ class NsxVAvailabilityZone(common_az.ConfiguredAvailabilityZone):
         self.dvs_id = cfg.CONF.nsxv.dvs_id
         self.edge_host_groups = cfg.CONF.nsxv.edge_host_groups
         self.exclusive_dhcp_edge = cfg.CONF.nsxv.exclusive_dhcp_edge
+        self.bind_floatingip_to_all_interfaces = (
+            cfg.CONF.nsxv.bind_floatingip_to_all_interfaces)
 
         # No support for metadata per az
         self.az_metadata_support = False
@@ -135,6 +137,8 @@ class NsxVAvailabilityZone(common_az.ConfiguredAvailabilityZone):
             self.edge_host_groups = cfg.CONF.nsxv.edge_host_groups
 
         self.exclusive_dhcp_edge = az_info.get('exclusive_dhcp_edge', False)
+        self.bind_floatingip_to_all_interfaces = az_info.get(
+            'bind_floatingip_to_all_interfaces', False)
 
         # Support for metadata per az only if configured, and different
         # from the global one
@@ -195,6 +199,8 @@ class NsxVAvailabilityZone(common_az.ConfiguredAvailabilityZone):
         self.dvs_id = cfg.CONF.nsxv.dvs_id
         self.edge_host_groups = cfg.CONF.nsxv.edge_host_groups
         self.exclusive_dhcp_edge = cfg.CONF.nsxv.exclusive_dhcp_edge
+        self.bind_floatingip_to_all_interfaces = (
+            cfg.CONF.nsxv.bind_floatingip_to_all_interfaces)
 
     def supports_metadata(self):
         # Return True if this az has it's own metadata configuration
diff --git a/vmware_nsx/plugins/nsx_v/drivers/abstract_router_driver.py b/vmware_nsx/plugins/nsx_v/drivers/abstract_router_driver.py
index 6c42b60bd1..6fe8ade8ae 100644
--- a/vmware_nsx/plugins/nsx_v/drivers/abstract_router_driver.py
+++ b/vmware_nsx/plugins/nsx_v/drivers/abstract_router_driver.py
@@ -24,6 +24,7 @@ from neutron_lib.callbacks import registry
 from vmware_nsx._i18n import _
 from vmware_nsx.common import exceptions as nsxv_exc
 from vmware_nsx.common import nsxv_constants
+from vmware_nsx.plugins.nsx_v import availability_zones as nsx_az
 from vmware_nsx.plugins.nsx_v.vshield import edge_utils
 
 
@@ -76,6 +77,7 @@ class RouterBaseDriver(RouterAbstractDriver):
         self.nsx_v = plugin.nsx_v
         self.edge_manager = plugin.edge_manager
         self.vcns = self.nsx_v.vcns
+        self._availability_zones = nsx_az.NsxVAvailabilityZones()
 
     def _notify_after_router_edge_association(self, context, router):
         registry.notify(nsxv_constants.SERVICE_EDGE, events.AFTER_CREATE,
diff --git a/vmware_nsx/plugins/nsx_v/drivers/shared_router_driver.py b/vmware_nsx/plugins/nsx_v/drivers/shared_router_driver.py
index 8d53eb33f6..b4ea4c9fb9 100644
--- a/vmware_nsx/plugins/nsx_v/drivers/shared_router_driver.py
+++ b/vmware_nsx/plugins/nsx_v/drivers/shared_router_driver.py
@@ -211,6 +211,9 @@ class RouterSharedDriver(router_driver.RouterBaseDriver):
 
     def _update_nat_rules_on_routers(self, context,
                                      target_router_id, router_ids):
+        edge_id, az_name = self.plugin._get_edge_id_and_az_by_rtr_id(
+            context, target_router_id)
+        az = self._availability_zones.get_availability_zone(az_name)
         snats = []
         dnats = []
         vnics_by_router = self._get_all_routers_vnic_indices(
@@ -222,7 +225,7 @@ class RouterSharedDriver(router_driver.RouterBaseDriver):
                 snat, dnat = self.plugin._get_nat_rules(context, router)
                 snats.extend(snat)
                 dnats.extend(dnat)
-                if (not cfg.CONF.nsxv.bind_floatingip_to_all_interfaces and
+                if (not az.bind_floatingip_to_all_interfaces and
                     len(dnat) > 0):
                     # Copy each DNAT rule to all vnics of the other routers,
                     # to allow NAT-ed traffic between routers
@@ -241,7 +244,7 @@ class RouterSharedDriver(router_driver.RouterBaseDriver):
                             dnats.extend([new_rule])
 
         edge_utils.update_nat_rules(
-            self.nsx_v, context, target_router_id, snats, dnats)
+            self.nsx_v, context, target_router_id, snats, dnats, az=az)
 
     def _update_external_interface_on_routers(self, context,
                                               target_router_id, router_ids):
diff --git a/vmware_nsx/plugins/nsx_v/vshield/edge_utils.py b/vmware_nsx/plugins/nsx_v/vshield/edge_utils.py
index 18f68ea96a..e25ca2875f 100644
--- a/vmware_nsx/plugins/nsx_v/vshield/edge_utils.py
+++ b/vmware_nsx/plugins/nsx_v/vshield/edge_utils.py
@@ -2393,10 +2393,13 @@ def delete_interface(nsxv_manager, context, router_id, network_id, dist=False):
             context.session, edge_id, network_id)
 
 
-def update_nat_rules(nsxv_manager, context, router_id, snat, dnat):
+def update_nat_rules(nsxv_manager, context, router_id, snat, dnat, az=None):
     binding = nsxv_db.get_nsxv_router_binding(context.session, router_id)
     if binding:
-        bind_to_all = cfg.CONF.nsxv.bind_floatingip_to_all_interfaces
+        if not az:
+            azs = nsx_az.NsxVAvailabilityZones()
+            az = azs.get_availability_zone(binding['availability_zone'])
+        bind_to_all = az.bind_floatingip_to_all_interfaces
 
         indices = None
         if bind_to_all: