Squashed commit of the following:
[ovsdb.git] / openstack / net-virt / src / main / java / org / opendaylight / ovsdb / openstack / netvirt / LBaaSPoolMemberHandler.java
index eeac77ef4f8c14d240e40fa543de17ff641035e3..cb71f389cdf51ea13868e638f16111dd5a949a59 100755 (executable)
@@ -7,27 +7,30 @@
  *
  * Authors : Srini Seetharaman
  */
-
 package org.opendaylight.ovsdb.openstack.netvirt;
 
-import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerCRUD;
-import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerPoolCRUD;
-import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerPoolMemberAware;
-import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;
-import org.opendaylight.controller.networkconfig.neutron.NeutronLoadBalancer;
-import org.opendaylight.controller.networkconfig.neutron.NeutronLoadBalancerPool;
-import org.opendaylight.controller.networkconfig.neutron.NeutronLoadBalancerPoolMember;
-import org.opendaylight.controller.sal.core.Node;
-import org.opendaylight.controller.switchmanager.ISwitchManager;
+import org.opendaylight.neutron.spi.INeutronLoadBalancerCRUD;
+import org.opendaylight.neutron.spi.INeutronLoadBalancerPoolCRUD;
+import org.opendaylight.neutron.spi.INeutronLoadBalancerPoolMemberAware;
+import org.opendaylight.neutron.spi.INeutronNetworkCRUD;
+import org.opendaylight.neutron.spi.INeutronPortCRUD;
+import org.opendaylight.neutron.spi.INeutronSubnetCRUD;
+import org.opendaylight.neutron.spi.NeutronLoadBalancer;
+import org.opendaylight.neutron.spi.NeutronLoadBalancerPool;
+import org.opendaylight.neutron.spi.NeutronLoadBalancerPoolMember;
 import org.opendaylight.ovsdb.openstack.netvirt.api.Action;
 import org.opendaylight.ovsdb.openstack.netvirt.api.LoadBalancerConfiguration;
 import org.opendaylight.ovsdb.openstack.netvirt.api.LoadBalancerProvider;
+import org.opendaylight.ovsdb.openstack.netvirt.api.NodeCacheManager;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Preconditions;
 
 import java.net.HttpURLConnection;
+import java.util.List;
+import java.util.Map;
 
 /**
  * Handle requests for OpenStack Neutron v2.0 LBaaS API calls for
@@ -43,18 +46,21 @@ public class LBaaSPoolMemberHandler extends AbstractHandler
     private volatile INeutronLoadBalancerPoolCRUD neutronLBPoolCache;
     private volatile INeutronLoadBalancerCRUD neutronLBCache;
     private volatile INeutronPortCRUD neutronPortsCache;
+    private volatile INeutronNetworkCRUD neutronNetworkCache;
+    private volatile INeutronSubnetCRUD neutronSubnetCache;
     private volatile LoadBalancerProvider loadBalancerProvider;
-    private volatile ISwitchManager switchManager;
+    private volatile NodeCacheManager nodeCacheManager;
 
     @Override
     public int canCreateNeutronLoadBalancerPoolMember(NeutronLoadBalancerPoolMember neutronLBPoolMember) {
         LoadBalancerConfiguration lbConfig = extractLBConfiguration(neutronLBPoolMember);
-        if (lbConfig == null)
+        if (lbConfig == null) {
             return HttpURLConnection.HTTP_BAD_REQUEST;
-        else if (!lbConfig.isValid())
+        } else if (!lbConfig.isValid()) {
             return HttpURLConnection.HTTP_NOT_ACCEPTABLE;
-        else
+        } else {
             return HttpURLConnection.HTTP_OK;
+        }
     }
 
     @Override
@@ -71,30 +77,28 @@ public class LBaaSPoolMemberHandler extends AbstractHandler
     private void doNeutronLoadBalancerPoolMemberCreate(NeutronLoadBalancerPoolMember neutronLBPoolMember) {
         Preconditions.checkNotNull(loadBalancerProvider);
         LoadBalancerConfiguration lbConfig = extractLBConfiguration(neutronLBPoolMember);
+        final List<Node> nodes =
+                nodeCacheManager.getBridgeNodes();
         if (lbConfig == null) {
-            logger.trace("Neutron LB configuration invalid for member {} ", neutronLBPoolMember.getPoolMemberAddress());
+            logger.debug("Neutron LB configuration invalid for member {} ", neutronLBPoolMember.getPoolMemberAddress());
         } else if (lbConfig.getVip() == null) {
-            logger.trace("Neutron LB VIP not created yet for member {} ", neutronLBPoolMember.getPoolMemberID());
+            logger.debug("Neutron LB VIP not created yet for member {} ", neutronLBPoolMember.getPoolMemberID());
         } else if (!lbConfig.isValid()) {
-            logger.trace("Neutron LB pool configuration invalid for {} ", lbConfig.getName());
-        } else if (this.switchManager.getNodes().size() == 0) {
-            logger.trace("Noop with LB pool member {} creation because no nodes available.", neutronLBPoolMember.getPoolMemberID());
+            logger.debug("Neutron LB pool configuration invalid for {} ", lbConfig.getName());
+        } else if (nodes.isEmpty()) {
+            logger.debug("Noop with LB pool member {} creation because no nodes available.", neutronLBPoolMember.getPoolMemberID());
         } else {
-            for (Node node: this.switchManager.getNodes())
-                loadBalancerProvider.programLoadBalancerPoolMemberRules(node, lbConfig,
+            for (Node node : nodes) {
+                loadBalancerProvider.programLoadBalancerPoolMemberRules(node,
+                        lbConfig,
                         lbConfig.getMembers().get(neutronLBPoolMember.getPoolMemberID()), Action.ADD);
+            }
         }
     }
 
     @Override
     public int canUpdateNeutronLoadBalancerPoolMember(NeutronLoadBalancerPoolMember delta, NeutronLoadBalancerPoolMember original) {
-        LoadBalancerConfiguration lbConfig = extractLBConfiguration(delta);
-        if (lbConfig == null)
-            return HttpURLConnection.HTTP_BAD_REQUEST;
-        else if (!lbConfig.isValid())
-            return HttpURLConnection.HTTP_NOT_ACCEPTABLE;
-        else
-            return HttpURLConnection.HTTP_OK;
+        return HttpURLConnection.HTTP_NOT_IMPLEMENTED;
     }
 
     @Override
@@ -106,12 +110,13 @@ public class LBaaSPoolMemberHandler extends AbstractHandler
     @Override
     public int canDeleteNeutronLoadBalancerPoolMember(NeutronLoadBalancerPoolMember neutronLBPoolMember) {
         LoadBalancerConfiguration lbConfig = extractLBConfiguration(neutronLBPoolMember);
-        if (lbConfig == null)
+        if (lbConfig == null) {
             return HttpURLConnection.HTTP_BAD_REQUEST;
-        else if (!lbConfig.isValid())
+        } else if (!lbConfig.isValid()) {
             return HttpURLConnection.HTTP_NOT_ACCEPTABLE;
-        else
+        } else {
             return HttpURLConnection.HTTP_OK;
+        }
     }
 
     @Override
@@ -120,6 +125,33 @@ public class LBaaSPoolMemberHandler extends AbstractHandler
         enqueueEvent(new NorthboundEvent(neutronLBPoolMember, Action.DELETE));
     }
 
+    private void doNeutronLoadBalancerPoolMemberDelete(NeutronLoadBalancerPoolMember neutronLBPoolMember) {
+        Preconditions.checkNotNull(loadBalancerProvider);
+
+        LoadBalancerConfiguration lbConfig = extractLBConfiguration(neutronLBPoolMember);
+        final List<Node> nodes = nodeCacheManager.getBridgeNodes();
+        if (lbConfig == null) {
+            logger.debug("Neutron LB configuration invalid for member {} ", neutronLBPoolMember.getPoolMemberAddress());
+        } else if (lbConfig.getVip() == null) {
+            logger.debug("Neutron LB VIP not created yet for member {} ", neutronLBPoolMember.getPoolMemberID());
+        } else if (!lbConfig.isValid()) {
+            logger.debug("Neutron LB pool configuration invalid for {} ", lbConfig.getName());
+        } else if (nodes.isEmpty()) {
+            logger.debug("Noop with LB pool member {} deletion because no nodes available.", neutronLBPoolMember.getPoolMemberID());
+        } else {
+            /* As of now, deleting a member involves recomputing member indices.
+             * This is best done through a complete update of the load balancer instance.
+             */
+            LoadBalancerConfiguration newLBConfig = new LoadBalancerConfiguration(lbConfig);
+            newLBConfig.removeMember(neutronLBPoolMember.getPoolMemberID());
+
+            for (Node node : nodes) {
+                loadBalancerProvider.programLoadBalancerRules(node, lbConfig, Action.DELETE);
+                loadBalancerProvider.programLoadBalancerRules(node, newLBConfig, Action.ADD);
+            }
+        }
+    }
+
     /**
      * Process the event.
      *
@@ -128,6 +160,7 @@ public class LBaaSPoolMemberHandler extends AbstractHandler
      */
     @Override
     public void processEvent(AbstractEvent abstractEvent) {
+        logger.debug("Processing Loadbalancer member event " + abstractEvent);
         if (!(abstractEvent instanceof NorthboundEvent)) {
             logger.error("Unable to process abstract event " + abstractEvent);
             return;
@@ -138,22 +171,12 @@ public class LBaaSPoolMemberHandler extends AbstractHandler
                 doNeutronLoadBalancerPoolMemberCreate(ev.getLoadBalancerPoolMember());
                 break;
             case DELETE:
-                /* As of now, deleting a member involves recomputing member indices.
-                 * This is best done through a complete update of the load balancer instance.
-                 */
-                for (NeutronLoadBalancer neutronLB: neutronLBCache.getAllNeutronLoadBalancers()) {
-                    String loadBalancerSubnetID = neutronLB.getLoadBalancerVipSubnetID();
-                    if (ev.getLoadBalancerPoolMember()
-                                         .getPoolMemberSubnetID().equals(loadBalancerSubnetID)) {
-                        enqueueEvent(new NorthboundEvent(neutronLB, Action.UPDATE));
-                        break;
-                    }
-                }
+                doNeutronLoadBalancerPoolMemberDelete(ev.getLoadBalancerPoolMember());
                 break;
             case UPDATE:
                 /**
                  * Typical upgrade involves changing weights. Since weights are not
-                 * supported yet, updates are not supported either.
+                 * supported yet, updates are not supported either. TODO
                  */
                 logger.warn("Load balancer pool member update is not supported");
                 break;
@@ -170,28 +193,30 @@ public class LBaaSPoolMemberHandler extends AbstractHandler
     public LoadBalancerConfiguration extractLBConfiguration(NeutronLoadBalancerPoolMember neutronLBPoolMember) {
         String memberID = neutronLBPoolMember.getPoolMemberID();
         String memberIP = neutronLBPoolMember.getPoolMemberAddress();
-        String memberMAC = NeutronCacheUtils.getMacAddress(neutronPortsCache, memberIP);
-        if (memberMAC == null) {
-            logger.trace("Neutron LB pool member {} MAC address unavailable", memberID);
-            return null;
-        }
         String memberSubnetID = neutronLBPoolMember.getPoolMemberSubnetID();
         Integer memberPort = neutronLBPoolMember.getPoolMemberProtoPort();
         String memberPoolID = neutronLBPoolMember.getPoolID();
         String memberProtocol = null;
 
         if (memberSubnetID == null || memberID == null || memberPoolID == null) {
-            logger.trace("Neutron LB pool member details incomplete [id={}, pool_id={},subnet_id={}",
+            logger.debug("Neutron LB pool member details incomplete [id={}, pool_id={},subnet_id={}",
                     memberID, memberPoolID, memberSubnetID);
             return null;
         }
+        String memberMAC = NeutronCacheUtils.getMacAddress(neutronPortsCache, memberSubnetID, memberIP);
+        if (memberMAC == null) {
+            logger.debug("Neutron LB pool member {} MAC address unavailable", memberID);
+            return null;
+        }
         NeutronLoadBalancerPool neutronLBPool = neutronLBPoolCache.getNeutronLoadBalancerPool(memberPoolID);
         memberProtocol = neutronLBPool.getLoadBalancerPoolProtocol();
-        if (!(memberProtocol.equalsIgnoreCase(LoadBalancerConfiguration.PROTOCOL_HTTP) ||
-                memberProtocol.equalsIgnoreCase(LoadBalancerConfiguration.PROTOCOL_HTTPS)))
+        if (!(memberProtocol.equalsIgnoreCase(LoadBalancerConfiguration.PROTOCOL_TCP) ||
+                memberProtocol.equalsIgnoreCase(LoadBalancerConfiguration.PROTOCOL_HTTP) ||
+                memberProtocol.equalsIgnoreCase(LoadBalancerConfiguration.PROTOCOL_HTTPS))) {
             return null;
+        }
 
-        String loadBalancerSubnetID, loadBalancerVip=null, loadBalancerName=null;
+        String loadBalancerSubnetID=null, loadBalancerVip=null, loadBalancerName=null;
         for (NeutronLoadBalancer neutronLB: neutronLBCache.getAllNeutronLoadBalancers()) {
             loadBalancerSubnetID = neutronLB.getLoadBalancerVipSubnetID();
             if (memberSubnetID.equals(loadBalancerSubnetID)) {
@@ -200,11 +225,48 @@ public class LBaaSPoolMemberHandler extends AbstractHandler
                 break;
             }
         }
+
         /**
          * It is possible that the VIP has not been created yet.
          * In that case, we create dummy configuration that will not program rules.
          */
         LoadBalancerConfiguration lbConfig = new LoadBalancerConfiguration(loadBalancerName, loadBalancerVip);
+        Map.Entry<String,String> providerInfo = NeutronCacheUtils.getProviderInformation(neutronNetworkCache, neutronSubnetCache, memberSubnetID);
+        if (providerInfo != null) {
+            lbConfig.setProviderNetworkType(providerInfo.getKey());
+            lbConfig.setProviderSegmentationId(providerInfo.getValue());
+        }
+        lbConfig.setVmac(NeutronCacheUtils.getMacAddress(neutronPortsCache, loadBalancerSubnetID, loadBalancerVip));
+
+        /* Extract all other active members and include in LB config
+         */
+        String otherMemberID, otherMemberSubnetID, otherMemberIP, otherMemberMAC, otherMemberProtocol;
+        Boolean otherMemberAdminStateIsUp;
+        Integer otherMemberPort;
+
+        for (NeutronLoadBalancerPoolMember otherMember: neutronLBPool.getLoadBalancerPoolMembers()) {
+            otherMemberID = otherMember.getPoolMemberID();
+            if (otherMemberID.equals(memberID)) {
+                continue; //skip
+            }
+
+            otherMemberIP = otherMember.getPoolMemberAddress();
+            otherMemberAdminStateIsUp = otherMember.getPoolMemberAdminStateIsUp();
+            otherMemberSubnetID = otherMember.getPoolMemberSubnetID();
+            otherMemberPort = otherMember.getPoolMemberProtoPort();
+            otherMemberProtocol = memberProtocol;
+
+            if (otherMemberIP == null || otherMemberSubnetID == null || otherMemberAdminStateIsUp == null) {
+                continue;
+            } else if (otherMemberAdminStateIsUp.booleanValue()) {
+                otherMemberMAC = NeutronCacheUtils.getMacAddress(neutronPortsCache, otherMemberSubnetID, otherMemberIP);
+                if (otherMemberMAC == null) {
+                    continue;
+                }
+                lbConfig.addMember(otherMemberID, otherMemberIP, otherMemberMAC, otherMemberProtocol, otherMemberPort);
+            }
+        }
+
         lbConfig.addMember(memberID, memberIP, memberMAC, memberProtocol, memberPort);
         return lbConfig;
     }