BUG 5164 Cleanup Floating IP Rules when VM is deleted.
authorVictor Pickard <vpickard@redhat.com>
Wed, 10 Feb 2016 13:55:40 +0000 (08:55 -0500)
committerAnil Vishnoi <vishnoianil@gmail.com>
Thu, 11 Feb 2016 23:36:06 +0000 (23:36 +0000)
Patch set 3: Address review comments.

Patch set 2: Fixed unit test.

When a VM is deleted, Neutron does not send a notification
to update/delete any floatingip that may have been associated
with a port. As a result, openflow rules for the floating ip
are left installed.

Neutron team says this is expected behavior for floating ip.
So, to cleanup, use neutron port delete event, and find
any associated floating ip, and cleanup installed OF
rules.

Change-Id: If9e2ffc5b16f0da636b3e9b6b1c4fbfd46fd6aff
Signed-off-by: Victor Pickard <vpickard@redhat.com>
openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/impl/NeutronL3Adapter.java
openstack/net-virt/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/impl/NeutronL3AdapterTest.java

index 37321159912cdd68279275a0408cb452cc06f4b4..9ff86c021143df34ea8ba9268021261a59609d7a 100644 (file)
@@ -429,6 +429,11 @@ public class NeutronL3Adapter extends AbstractHandler implements GatewayMacResol
 
         final boolean isDelete = action == Action.DELETE;
 
+        if (action == Action.DELETE) {
+            // Bug 5164: Cleanup Floating IP OpenFlow Rules when port is deleted.
+            this.cleanupFloatingIPRules(neutronPort);
+        }
+
         if (neutronPort.getDeviceOwner().equalsIgnoreCase(OWNER_ROUTER_GATEWAY)){
             if (!isDelete) {
                 LOG.info("Port {} is network router gateway interface, "
@@ -1448,6 +1453,19 @@ public class NeutronL3Adapter extends AbstractHandler implements GatewayMacResol
          }
      }
 
+    private void cleanupFloatingIPRules(final NeutronPort neutronPort) {
+
+        List<NeutronFloatingIP> neutronFloatingIps = neutronFloatingIpCache.getAllFloatingIPs();
+        if (neutronFloatingIps != null && !neutronFloatingIps.isEmpty()) {
+            for (NeutronFloatingIP neutronFloatingIP : neutronFloatingIps) {
+                if (neutronFloatingIP.getPortUUID().equals(neutronPort.getPortUUID())) {
+                    handleNeutronFloatingIPEvent(neutronFloatingIP, Action.DELETE);
+                }
+            }
+        }
+    }
+
+
     private void triggerGatewayMacResolver(final NeutronPort gatewayPort){
 
         Preconditions.checkNotNull(gatewayPort);
index cf6545d9fb53a6a9191979d39a8269017e972877..09bf52ab69aa019f1aa00eb03066dc93f9c3623c 100644 (file)
@@ -42,6 +42,7 @@ import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronRouter;
 import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronRouter_Interface;
 import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronSubnet;
 import org.opendaylight.ovsdb.openstack.netvirt.translator.Neutron_IPs;
+import org.opendaylight.ovsdb.openstack.netvirt.translator.crud.INeutronFloatingIPCRUD;
 import org.opendaylight.ovsdb.openstack.netvirt.translator.crud.INeutronNetworkCRUD;
 import org.opendaylight.ovsdb.openstack.netvirt.translator.crud.INeutronPortCRUD;
 import org.opendaylight.ovsdb.openstack.netvirt.translator.crud.INeutronSubnetCRUD;
@@ -148,12 +149,14 @@ public class NeutronL3AdapterTest {
         NeutronPort neutronPort = mock(NeutronPort.class);
         when(neutronPort.getDeviceOwner()).thenReturn(OWNER_ROUTER_INTERFACE);
         when(neutronPort.getFixedIPs()).thenReturn(list_neutronIP);
+        INeutronFloatingIPCRUD neutronFloatingIpCache = mock(INeutronFloatingIPCRUD.class);
 
         // init instance variables
         MemberModifier.field(NeutronL3Adapter.class, "neutronPortCache").set(neutronL3Adapter , mock(INeutronPortCRUD.class));
         subnetIdToRouterInterfaceCache.put(UUID, mock(NeutronRouter_Interface.class));
         MemberModifier.field(NeutronL3Adapter.class, "subnetIdToRouterInterfaceCache").set(neutronL3Adapter , subnetIdToRouterInterfaceCache);
         MemberModifier.field(NeutronL3Adapter.class, "portCleanupCache").set(neutronL3Adapter , portCleanupCache);
+        MemberModifier.field(NeutronL3Adapter.class, "neutronFloatingIpCache").set(neutronL3Adapter , neutronFloatingIpCache);
 
         // Suppress the called to these functions
         MemberModifier.suppress(MemberMatcher.method(NeutronL3Adapter.class, "updateL3ForNeutronPort", NeutronPort.class, boolean.class));