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>
final boolean isDelete = action == Action.DELETE;
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, "
if (neutronPort.getDeviceOwner().equalsIgnoreCase(OWNER_ROUTER_GATEWAY)){
if (!isDelete) {
LOG.info("Port {} is network router gateway interface, "
+ 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);
private void triggerGatewayMacResolver(final NeutronPort gatewayPort){
Preconditions.checkNotNull(gatewayPort);
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.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;
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;
NeutronPort neutronPort = mock(NeutronPort.class);
when(neutronPort.getDeviceOwner()).thenReturn(OWNER_ROUTER_INTERFACE);
when(neutronPort.getFixedIPs()).thenReturn(list_neutronIP);
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);
// 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));
// Suppress the called to these functions
MemberModifier.suppress(MemberMatcher.method(NeutronL3Adapter.class, "updateL3ForNeutronPort", NeutronPort.class, boolean.class));