From 595fe2e5ab7d7bc512390eb5c02b11c03e1d54a6 Mon Sep 17 00:00:00 2001
From: Gary Kotton <gkotton@vmware.com>
Date: Tue, 13 Feb 2018 03:52:40 -0800
Subject: [PATCH] NSX|V: treat edge case when spoofguard entry already exists

Treat a case where the spoofguard entry exists. One edge case may
be a reschedule and the port is not cleanued up.

Change-Id: I95fbbbd97d6ce1de55fe5a1f5016459e4fb200f9
---
 vmware_nsx/plugins/nsx_v/plugin.py                 | 10 +++++++---
 .../plugins/nsx_v/vshield/common/constants.py      |  1 +
 .../plugins/nsx_v/vshield/common/exceptions.py     |  4 ++++
 vmware_nsx/plugins/nsx_v/vshield/vcns.py           | 14 +++++++++++---
 4 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/vmware_nsx/plugins/nsx_v/plugin.py b/vmware_nsx/plugins/nsx_v/plugin.py
index c8224d7fd3..002de85d94 100644
--- a/vmware_nsx/plugins/nsx_v/plugin.py
+++ b/vmware_nsx/plugins/nsx_v/plugin.py
@@ -4509,9 +4509,13 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
             lla = str(netutils.get_ipv6_addr_by_EUI64(
                       constants.IPv6_LLA_PREFIX, mac_addr))
             approved_addrs.append(lla)
-        self.nsx_v.vcns.approve_assigned_addresses(
-            sg_policy_id, vnic_id, mac_addr, approved_addrs)
-        self.nsx_v.vcns.publish_assigned_addresses(sg_policy_id, vnic_id)
+        try:
+            self.nsx_v.vcns.approve_assigned_addresses(
+                sg_policy_id, vnic_id, mac_addr, approved_addrs)
+            self.nsx_v.vcns.publish_assigned_addresses(sg_policy_id, vnic_id)
+        except vsh_exc.AlreadyExists:
+            # Entry already configured on the NSX
+            pass
 
     def _is_compute_port(self, port):
         try:
diff --git a/vmware_nsx/plugins/nsx_v/vshield/common/constants.py b/vmware_nsx/plugins/nsx_v/vshield/common/constants.py
index 9331529254..1b43e2553c 100644
--- a/vmware_nsx/plugins/nsx_v/vshield/common/constants.py
+++ b/vmware_nsx/plugins/nsx_v/vshield/common/constants.py
@@ -43,6 +43,7 @@ PREPEND = 0
 APPEND = -1
 
 # error code
+NSX_ERROR_ALREADY_EXISTS = 210
 VCNS_ERROR_CODE_EDGE_NOT_RUNNING = 10013
 NSX_ERROR_DHCP_OVERLAPPING_IP = 12501
 NSX_ERROR_DHCP_DUPLICATE_HOSTNAME = 12504
diff --git a/vmware_nsx/plugins/nsx_v/vshield/common/exceptions.py b/vmware_nsx/plugins/nsx_v/vshield/common/exceptions.py
index 26a77b8761..4ffdfeea88 100644
--- a/vmware_nsx/plugins/nsx_v/vshield/common/exceptions.py
+++ b/vmware_nsx/plugins/nsx_v/vshield/common/exceptions.py
@@ -76,3 +76,7 @@ class ServiceUnavailable(VcnsApiException):
 
 class ServiceConflict(VcnsApiException):
     message = _("Concurrent object access error: %(uri)s")
+
+
+class AlreadyExists(VcnsApiException):
+    message = _("Resource %(resource)s already exists")
diff --git a/vmware_nsx/plugins/nsx_v/vshield/vcns.py b/vmware_nsx/plugins/nsx_v/vshield/vcns.py
index 749119e450..807298e3e5 100644
--- a/vmware_nsx/plugins/nsx_v/vshield/vcns.py
+++ b/vmware_nsx/plugins/nsx_v/vshield/vcns.py
@@ -826,9 +826,17 @@ class Vcns(object):
                   'approvedMacAddress': mac_addr,
                   'publishedIpAddress': addresses,
                   'publishedMacAddress': mac_addr}}}
-
-        return self.do_request(HTTP_POST, '%s?action=approve' % uri,
-                               body, format='xml', decode=False)
+        try:
+            return self.do_request(HTTP_POST, '%s?action=approve' % uri,
+                                   body, format='xml', decode=False)
+        except exceptions.VcnsApiException as e:
+            nsx_errcode = self.xmlapi_client._get_nsx_errorcode(e.response)
+            if nsx_errcode == constants.NSX_ERROR_ALREADY_EXISTS:
+                LOG.warning("Spoofguard entry for %s already exists",
+                            vnic_id)
+                raise exceptions.AlreadyExists(resource=vnic_id)
+            # raise original exception for retries
+            raise
 
     @retry_upon_exception(exceptions.RequestBad)
     def approve_assigned_addresses(self, policy_id,