Fixing Bug 1858 and Bug 1673 with changes in net-virt package
[netvirt.git] / openstack / net-virt / src / main / java / org / opendaylight / ovsdb / openstack / netvirt / LBaaSHandler.java
old mode 100755 (executable)
new mode 100644 (file)
index ee67879..cfb39aa
@@ -11,6 +11,7 @@
 package org.opendaylight.ovsdb.openstack.netvirt;
 
 import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerAware;
+import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerCRUD;
 import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerPoolCRUD;
 import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerPoolMemberCRUD;
 import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;
@@ -18,6 +19,10 @@ 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.sal.core.NodeConnector;
+import org.opendaylight.controller.sal.core.Property;
+import org.opendaylight.controller.sal.core.UpdateType;
+import org.opendaylight.controller.switchmanager.IInventoryListener;
 import org.opendaylight.controller.switchmanager.ISwitchManager;
 import org.opendaylight.ovsdb.openstack.netvirt.api.Action;
 import org.opendaylight.ovsdb.openstack.netvirt.api.LoadBalancerConfiguration;
@@ -29,6 +34,7 @@ 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 /v2.0/loadbalancers.
@@ -37,11 +43,12 @@ import java.util.List;
 //TODO: Implement INeutronLoadBalancerHealthMonitorAware, INeutronLoadBalancerListenerAware, INeutronLoadBalancerPoolMemberAware,
 
 public class LBaaSHandler extends AbstractHandler
-        implements INeutronLoadBalancerAware {
+        implements INeutronLoadBalancerAware, IInventoryListener {
 
     private static final Logger logger = LoggerFactory.getLogger(LBaaSHandler.class);
 
     // The implementation for each of these services is resolved by the OSGi Service Manager
+    private volatile INeutronLoadBalancerCRUD neutronLBCache;
     private volatile INeutronLoadBalancerPoolCRUD neutronLBPoolCache;
     private volatile INeutronLoadBalancerPoolMemberCRUD neutronLBPoolMemberCache;
     private volatile INeutronPortCRUD neutronPortsCache;
@@ -57,23 +64,25 @@ public class LBaaSHandler extends AbstractHandler
             return HttpURLConnection.HTTP_OK;
     }
 
-    /**
-     * Assuming that the pool information is fully populated before this call is made,
-     * we go with creating the LoadBalancerConfiguration object for this call with
-     * all information that is necessary to insert flow_mods
-     */
     @Override
     public void neutronLoadBalancerCreated(NeutronLoadBalancer neutronLB) {
         logger.debug("Neutron LB Creation : {}", neutronLB.toString());
         enqueueEvent(new NorthboundEvent(neutronLB, Action.ADD));
     }
 
+    /**
+     * Assuming that the pool information is fully populated before this call is made,
+     * we go with creating the LoadBalancerConfiguration object for this call with
+     * all information that is necessary to insert flow_mods
+     */
     private void doNeutronLoadBalancerCreate(NeutronLoadBalancer neutronLB) {
         Preconditions.checkNotNull(loadBalancerProvider);
         LoadBalancerConfiguration lbConfig = extractLBConfiguration(neutronLB);
 
         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 {} creation because no nodes available.", lbConfig.getName());
         } else {
             for (Node node: this.switchManager.getNodes())
                 loadBalancerProvider.programLoadBalancerRules(node, lbConfig, Action.ADD);
@@ -82,19 +91,23 @@ public class LBaaSHandler extends AbstractHandler
 
     @Override
     public int canUpdateNeutronLoadBalancer(NeutronLoadBalancer delta, NeutronLoadBalancer original) {
-        return HttpURLConnection.HTTP_OK;
+        LoadBalancerConfiguration lbConfig = extractLBConfiguration(delta);
+        if (!lbConfig.isValid())
+            return HttpURLConnection.HTTP_NOT_ACCEPTABLE;
+        else
+            return HttpURLConnection.HTTP_OK;
     }
 
     @Override
     public void neutronLoadBalancerUpdated(NeutronLoadBalancer neutronLB) {
+        logger.debug("Neutron LB Update : {}", neutronLB.toString());
         enqueueEvent(new NorthboundEvent(neutronLB, Action.UPDATE));
-        return;
     }
 
     @Override
     public int canDeleteNeutronLoadBalancer(NeutronLoadBalancer neutronLB) {
         LoadBalancerConfiguration lbConfig = extractLBConfiguration(neutronLB);
-        if (!lbConfig.isValid())
+        if (lbConfig == null)
             return HttpURLConnection.HTTP_NOT_ACCEPTABLE;
         else
             return HttpURLConnection.HTTP_OK;
@@ -112,6 +125,8 @@ public class LBaaSHandler extends AbstractHandler
 
         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 {} deletion because no nodes available.", lbConfig.getName());
         } else {
             for (Node node: this.switchManager.getNodes())
                 loadBalancerProvider.programLoadBalancerRules(node, lbConfig, Action.DELETE);
@@ -126,6 +141,7 @@ public class LBaaSHandler extends AbstractHandler
      */
     @Override
     public void processEvent(AbstractEvent abstractEvent) {
+        logger.debug("Processing Loadbalancer event " + abstractEvent);
         if (!(abstractEvent instanceof NorthboundEvent)) {
             logger.error("Unable to process abstract event " + abstractEvent);
             return;
@@ -134,8 +150,14 @@ public class LBaaSHandler extends AbstractHandler
         switch (ev.getAction()) {
             case ADD:
                 doNeutronLoadBalancerCreate(ev.getLoadBalancer());
+                break;
             case DELETE:
+                try {
                 doNeutronLoadBalancerDelete(ev.getLoadBalancer());
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+                break;
             case UPDATE:
                 /**
                  * Currently member update requires delete and re-adding
@@ -160,13 +182,15 @@ public class LBaaSHandler extends AbstractHandler
         String loadBalancerSubnetID = neutronLB.getLoadBalancerVipSubnetID();
         LoadBalancerConfiguration lbConfig = new LoadBalancerConfiguration(loadBalancerName, loadBalancerVip);
 
-        String memberID, memberIP, memberMAC, memberProtocol;
+        String memberID, memberIP, memberMAC, memberProtocol, memberSubnetID;
         Integer memberPort;
+        Boolean memberAdminStateIsUp;
 
         for (NeutronLoadBalancerPool neutronLBPool: neutronLBPoolCache.getAllNeutronLoadBalancerPools()) {
-            List<? extends NeutronLoadBalancerPoolMember> members =
-                (List<? extends NeutronLoadBalancerPoolMember>)neutronLBPool.getLoadBalancerPoolMembers();
+            List<NeutronLoadBalancerPoolMember> members = neutronLBPool.getLoadBalancerPoolMembers();
             memberProtocol = neutronLBPool.getLoadBalancerPoolProtocol();
+            if (memberProtocol == null)
+                continue;
             /*
              * Only HTTP and HTTPS are supported as of this version
              * TODO: Support all TCP load-balancers
@@ -175,8 +199,11 @@ public class LBaaSHandler extends AbstractHandler
                   memberProtocol.equalsIgnoreCase(LoadBalancerConfiguration.PROTOCOL_HTTPS)))
                 continue;
             for (NeutronLoadBalancerPoolMember neutronLBPoolMember: members) {
-                if (neutronLBPoolMember.getPoolMemberSubnetID().equals(loadBalancerSubnetID) &&
-                    neutronLBPoolMember.getPoolMemberAdminStateIsUp()) {
+                memberAdminStateIsUp = neutronLBPoolMember.getPoolMemberAdminStateIsUp();
+                memberSubnetID = neutronLBPoolMember.getPoolMemberSubnetID();
+                if (memberSubnetID == null || memberAdminStateIsUp == null)
+                    continue;
+                else if (memberSubnetID.equals(loadBalancerSubnetID) && memberAdminStateIsUp.booleanValue()) {
                     memberID = neutronLBPoolMember.getPoolMemberID();
                     memberIP = neutronLBPoolMember.getPoolMemberAddress();
                     memberPort = neutronLBPoolMember.getPoolMemberProtoPort();
@@ -189,4 +216,33 @@ public class LBaaSHandler extends AbstractHandler
         }
         return lbConfig;
     }
+
+    /**
+     * On the addition of a new node, we iterate through all existing loadbalancer
+     * instances and program the node for all of them. It is sufficient to do that only
+     * when a node is added, and only for the LB instances (and not individual members).
+     */
+    @Override
+    public void notifyNode(Node node, UpdateType type, Map<String, Property> propMap) {
+        logger.debug("notifyNode: Node {} update {} from Controller's inventory Service", node, type);
+        Preconditions.checkNotNull(loadBalancerProvider);
+
+        for (NeutronLoadBalancer neutronLB: neutronLBCache.getAllNeutronLoadBalancers()) {
+            LoadBalancerConfiguration lbConfig = extractLBConfiguration(neutronLB);
+            if (!lbConfig.isValid())
+                logger.trace("Neutron LB configuration invalid for {} ", lbConfig.getName());
+            else {
+               if (type.equals(UpdateType.ADDED))
+                    loadBalancerProvider.programLoadBalancerRules(node, lbConfig, Action.ADD);
+               else if (type.equals(UpdateType.REMOVED))
+                    loadBalancerProvider.programLoadBalancerRules(node, lbConfig, Action.DELETE);
+            }
+        }
+    }
+
+    @Override
+    public void notifyNodeConnector(NodeConnector arg0, UpdateType arg1,
+            Map<String, Property> arg2) {
+        //NOOP
+    }
 }