Merge "Fix minor bug in FRM proactive flow code path"
[controller.git] / opendaylight / switchmanager / implementation / src / main / java / org / opendaylight / controller / switchmanager / internal / SwitchManagerImpl.java
index 7fd9bc17d1e4cf05c1a69d0bb169d3e6168ee90a..5d10620c4403f8c00829bd02927d5da39fa07178 100644 (file)
@@ -42,6 +42,7 @@ import org.opendaylight.controller.sal.core.Bandwidth;
 import org.opendaylight.controller.sal.core.Config;
 import org.opendaylight.controller.sal.core.ConstructionException;
 import org.opendaylight.controller.sal.core.Description;
+import org.opendaylight.controller.sal.core.ForwardingMode;
 import org.opendaylight.controller.sal.core.MacAddress;
 import org.opendaylight.controller.sal.core.Name;
 import org.opendaylight.controller.sal.core.Node;
@@ -58,7 +59,6 @@ import org.opendaylight.controller.sal.utils.HexEncode;
 import org.opendaylight.controller.sal.utils.IObjectReader;
 import org.opendaylight.controller.sal.utils.ObjectReader;
 import org.opendaylight.controller.sal.utils.ObjectWriter;
-import org.opendaylight.controller.sal.utils.ServiceHelper;
 import org.opendaylight.controller.sal.utils.Status;
 import org.opendaylight.controller.sal.utils.StatusCode;
 import org.opendaylight.controller.switchmanager.IInventoryListener;
@@ -94,13 +94,15 @@ CommandProvider {
     private String subnetFileName = null, spanFileName = null,
             switchConfigFileName = null;
     private final List<NodeConnector> spanNodeConnectors = new CopyOnWriteArrayList<NodeConnector>();
-    private ConcurrentMap<InetAddress, Subnet> subnets; // set of Subnets keyed by the InetAddress
+    // set of Subnets keyed by the InetAddress
+    private ConcurrentMap<InetAddress, Subnet> subnets;
     private ConcurrentMap<String, SubnetConfig> subnetsConfigList;
     private ConcurrentMap<SpanConfig, SpanConfig> spanConfigList;
-    private ConcurrentMap<String, SwitchConfig> nodeConfigList; // manually configured parameters for the node like name and tier
+    // manually configured parameters for the node such as name, tier, mode
+    private ConcurrentMap<String, SwitchConfig> nodeConfigList;
     private ConcurrentMap<Long, String> configSaveEvent;
-    private ConcurrentMap<Node, Map<String, Property>> nodeProps; // properties are maintained in global container only
-    private ConcurrentMap<NodeConnector, Map<String, Property>> nodeConnectorProps; // properties are maintained in global container only
+    private ConcurrentMap<Node, Map<String, Property>> nodeProps;
+    private ConcurrentMap<NodeConnector, Map<String, Property>> nodeConnectorProps;
     private ConcurrentMap<Node, Map<String, NodeConnector>> nodeConnectorNames;
     private IInventoryService inventoryService;
     private final Set<ISwitchManagerAware> switchManagerAware = Collections
@@ -663,41 +665,142 @@ CommandProvider {
             modeChange = true;
         }
 
-        try {
-            String nodeId = cfgObject.getNodeId();
-            Node node = Node.fromString(nodeId);
-            Map<String, Property> propMapCurr = nodeProps.get(node);
-            Map<String, Property> propMap = new HashMap<String, Property>();
-            if (propMapCurr != null) {
-                for (String s : propMapCurr.keySet()) {
-                    propMap.put(s, propMapCurr.get(s).clone());
+        String nodeId = cfgObject.getNodeId();
+        Node node = Node.fromString(nodeId);
+        Map<String, Property> propMapCurr = nodeProps.get(node);
+        if (propMapCurr == null) {
+            return;
+        }
+        Map<String, Property> propMap = new HashMap<String, Property>(propMapCurr);
+        Property desc = new Description(cfgObject.getNodeDescription());
+        propMap.put(desc.getName(), desc);
+        Property tier = new Tier(Integer.parseInt(cfgObject.getTier()));
+        propMap.put(tier.getName(), tier);
+
+        if (!nodeProps.replace(node, propMapCurr, propMap)) {
+            // TODO rollback using Transactionality
+            return;
+        }
+
+        log.info("Set Node {}'s Mode to {}", nodeId, cfgObject.getMode());
+
+        if (modeChange) {
+            notifyModeChange(node, cfgObject.isProactive());
+        }
+    }
+
+    @Override
+    public Status updateNodeConfig(SwitchConfig switchConfig) {
+        Status status = switchConfig.validate();
+        if (!status.isSuccess()) {
+            return status;
+        }
+
+        Map<String, Property> updateProperties = switchConfig.getNodeProperties();
+        String nodeId = switchConfig.getNodeId();
+        ForwardingMode mode = (ForwardingMode) updateProperties.get(ForwardingMode.name);
+        if (mode != null) {
+            if (isDefaultContainer) {
+                if (!mode.isValid()) {
+                    return new Status(StatusCode.NOTACCEPTABLE, "Invalid Forwarding Mode Value.");
                 }
+            } else {
+                return new Status(StatusCode.NOTACCEPTABLE,
+                        "Forwarding Mode modification is allowed only in default container");
             }
-            Property desc = new Description(cfgObject.getNodeDescription());
-            propMap.put(desc.getName(), desc);
-            Property tier = new Tier(Integer.parseInt(cfgObject.getTier()));
-            propMap.put(tier.getName(), tier);
-
-            if (propMapCurr == null) {
-                if (nodeProps.putIfAbsent(node, propMap) != null) {
-                    // TODO rollback using Transactionality
-                    return;
+        }
+        boolean modeChange = false;
+        SwitchConfig sc = nodeConfigList.get(nodeId);
+        Map<String, Property> prevNodeProperties = new HashMap<String, Property>();
+        if (sc == null) {
+            if ((mode != null) && mode.isProactive()) {
+                modeChange = true;
+            }
+            if (!updateProperties.isEmpty()) {
+                if (nodeConfigList.putIfAbsent(nodeId, switchConfig) != null) {
+                    return new Status(StatusCode.CONFLICT, "Cluster conflict: Unable to update node configuration");
+                }
+            }
+        } else {
+            prevNodeProperties = new HashMap<String, Property>(sc.getNodeProperties());
+            ForwardingMode prevMode = (ForwardingMode) sc.getProperty(ForwardingMode.name);
+            if (mode == null) {
+                if ((prevMode != null) && (prevMode.isProactive())) {
+                    modeChange = true;
                 }
             } else {
-                if (!nodeProps.replace(node, propMapCurr, propMap)) {
-                    // TODO rollback using Transactionality
-                    return;
+                if (((prevMode != null) && (prevMode.getValue() != mode.getValue()))
+                        || (prevMode == null && mode.isProactive())) {
+                    modeChange = true;
                 }
             }
+            if (updateProperties.isEmpty()) {
+                nodeConfigList.remove(nodeId);
+            } else {
+                if (!nodeConfigList.replace(nodeId, sc, switchConfig)) {
+                    return new Status(StatusCode.CONFLICT, "Cluster conflict: Unable to update node configuration");
+                }
+            }
+        }
+        Node node = Node.fromString(nodeId);
+        Map<String, Property> propMapCurr = nodeProps.get(node);
+        Map<String, Property> propMap = new HashMap<String, Property>(propMapCurr);
+        if (propMapCurr == null) {
+            return new Status(StatusCode.SUCCESS);
+        }
+        if (!prevNodeProperties.isEmpty()) {
+            for (String prop : prevNodeProperties.keySet()) {
+                if (!updateProperties.containsKey(prop)) {
+                    if (prop.equals(Description.propertyName)) {
+                        Map<Node, Map<String, Property>> nodeProp = this.inventoryService.getNodeProps();
+                        if (nodeProp.get(node) != null) {
+                            propMap.put(Description.propertyName, nodeProp.get(node).get(Description.propertyName));
+                            continue;
+                        }
+                    }
+                    propMap.remove(prop);
+                }
+            }
+        }
+        propMap.putAll(updateProperties);
+        if (!nodeProps.replace(node, propMapCurr, propMap)) {
+            // TODO rollback using Transactionality
+            return new Status(StatusCode.CONFLICT, "Cluster conflict: Unable to update node configuration.");
+        }
+        if (modeChange) {
+            notifyModeChange(node, (mode == null) ? false : mode.isProactive());
+        }
+        return new Status(StatusCode.SUCCESS);
+    }
 
-            log.info("Set Node {}'s Mode to {}", nodeId, cfgObject.getMode());
-
-            if (modeChange) {
-                notifyModeChange(node, cfgObject.isProactive());
+    @Override
+    public Status removeNodeConfig(String nodeId) {
+        if ((nodeId == null) || (nodeId.isEmpty())) {
+            return new Status(StatusCode.BADREQUEST, "nodeId cannot be empty.");
+        }
+        Map<String, Property> nodeProperties = getSwitchConfig(nodeId).getNodeProperties();
+        Node node = Node.fromString(nodeId);
+        Map<String, Property> propMapCurr = nodeProps.get(node);
+        if ((propMapCurr != null) && (nodeProperties != null) && (!nodeProperties.isEmpty())) {
+            Map<String, Property> propMap = new HashMap<String, Property>(propMapCurr);
+            for (String prop : nodeProperties.keySet()) {
+                if (prop.equals(Description.propertyName)) {
+                    Map<Node, Map<String, Property>> nodeProp = this.inventoryService.getNodeProps();
+                    if (nodeProp.get(node) != null) {
+                        propMap.put(Description.propertyName, nodeProp.get(node).get(Description.propertyName));
+                        continue;
+                    }
+                }
+                propMap.remove(prop);
+            }
+            if (!nodeProps.replace(node, propMapCurr, propMap)) {
+                return new Status(StatusCode.CONFLICT, "Cluster conflict: Unable to update node configuration.");
             }
-        } catch (Exception e) {
-            log.debug("updateSwitchConfig: {}", e.getMessage());
         }
+        if (nodeConfigList != null) {
+            nodeConfigList.remove(nodeId);
+        }
+        return new Status(StatusCode.SUCCESS);
     }
 
     @Override
@@ -800,12 +903,8 @@ CommandProvider {
         }
 
         Map<String, Property> propMapCurr = nodeProps.get(node);
-        Map<String, Property> propMap = new HashMap<String, Property>();
-        if (propMapCurr != null) {
-            for (String s : propMapCurr.keySet()) {
-                propMap.put(s, propMapCurr.get(s).clone());
-            }
-        }
+        Map<String, Property> propMap = (propMapCurr == null) ? new HashMap<String, Property>()
+                : new HashMap<String, Property>(propMapCurr);
 
         // copy node properties from plugin
         if (props != null) {
@@ -818,14 +917,13 @@ CommandProvider {
         boolean proactiveForwarding = false;
         if (nodeConfigList != null) {
             String nodeId = node.toString();
-            for (SwitchConfig conf : nodeConfigList.values()) {
-                if (conf.getNodeId().equals(nodeId)) {
-                    Property description = new Description(conf.getNodeDescription());
-                    propMap.put(description.getName(), description);
-                    Property tier = new Tier(Integer.parseInt(conf.getTier()));
-                    propMap.put(tier.getName(), tier);
-                    proactiveForwarding = conf.isProactive();
-                    break;
+            SwitchConfig conf = nodeConfigList.get(nodeId);
+            if (conf != null && (conf.getNodeProperties() != null)) {
+                Map<String, Property> nodeProperties = conf.getNodeProperties();
+                propMap.putAll(nodeProperties);
+                if (nodeProperties.get(ForwardingMode.name) != null) {
+                    ForwardingMode mode = (ForwardingMode) nodeProperties.get(ForwardingMode.name);
+                    proactiveForwarding = mode.isProactive();
                 }
             }
         }
@@ -840,8 +938,7 @@ CommandProvider {
         }
 
         if (!result) {
-            log.debug(
-                    "Cluster conflict: Conflict while adding the node properties. Node: {}  Properties: {}",
+            log.debug("Cluster conflict: Conflict while adding the node properties. Node: {}  Properties: {}",
                     node.getID(), props);
             addNodeProps(node, propMap);
         }
@@ -880,18 +977,12 @@ CommandProvider {
         }
 
         Map<String, Property> propMapCurr = nodeProps.get(node);
-        Map<String, Property> propMap = new HashMap<String, Property>();
-        if (propMapCurr != null) {
-            for (String s : propMapCurr.keySet()) {
-                propMap.put(s, propMapCurr.get(s).clone());
-            }
-        }
+        Map<String, Property> propMap = (propMapCurr == null) ? new HashMap<String, Property>()
+                : new HashMap<String, Property>(propMapCurr);
 
         // copy node properties from plugin
-        if (props != null) {
-            for (Property prop : props) {
-                propMap.put(prop.getName(), prop);
-            }
+        for (Property prop : props) {
+            propMap.put(prop.getName(), prop);
         }
 
         if (propMapCurr == null) {
@@ -934,7 +1025,6 @@ CommandProvider {
     @Override
     public void updateNodeConnector(NodeConnector nodeConnector,
             UpdateType type, Set<Property> props) {
-        Node node = nodeConnector.getNode();
         Map<String, Property> propMap = new HashMap<String, Property>();
 
         log.debug("updateNodeConnector: {} type {} props {} for container {}",
@@ -954,14 +1044,12 @@ CommandProvider {
                 }
             } else {
                 addNodeConnectorProp(nodeConnector, null);
-                addNodeProps(node, null);
             }
 
             addSpanPort(nodeConnector);
             break;
         case REMOVED:
             removeNodeConnectorAllProps(nodeConnector);
-            removeNodeProps(node);
 
             // clean up span config
             removeSpanPort(nodeConnector);
@@ -990,23 +1078,15 @@ CommandProvider {
      */
     @Override
     public Map<String, Property> getNodeProps(Node node) {
-        if (isDefaultContainer) {
-            Map<String, Property> rv = null;
-            if (this.nodeProps != null) {
-                rv = this.nodeProps.get(node);
-                if (rv != null) {
-                    /* make a copy of it */
-                    rv = new HashMap<String, Property>(rv);
-                }
+        Map<String, Property> rv = new HashMap<String, Property>();
+        if (this.nodeProps != null) {
+            rv = this.nodeProps.get(node);
+            if (rv != null) {
+                /* make a copy of it */
+                rv = new HashMap<String, Property>(rv);
             }
-            return rv;
-        } else {
-            // get it from default container
-            ISwitchManager defaultSwitchManager = (ISwitchManager) ServiceHelper
-                    .getInstance(ISwitchManager.class,
-                            GlobalConstants.DEFAULT.toString(), this);
-            return defaultSwitchManager.getNodeProps(node);
         }
+        return rv;
     }
 
     @Override
@@ -1025,18 +1105,14 @@ CommandProvider {
                 return;
             }
 
-            Map<String, Property> propMap = new HashMap<String, Property>();
-            for (String s : propMapCurr.keySet()) {
-                propMap.put(s, propMapCurr.get(s).clone());
-            }
-
+            Map<String, Property> propMap = new HashMap<String, Property>(propMapCurr);
             propMap.put(prop.getName(), prop);
 
             if (nodeProps.replace(node, propMapCurr, propMap)) {
                 return;
             }
             if (!propMapCurr.get(prop.getName()).equals(nodeProps.get(node).get(prop.getName()))) {
-                log.warn("Cluster conflict: Unable to add property {} to node {}.", prop.getName(), node.getID());
+                log.debug("Cluster conflict: Unable to add property {} to node {}.", prop.getName(), node.getID());
                 return;
             }
         }
@@ -1051,11 +1127,7 @@ CommandProvider {
                 if (!propMapCurr.containsKey(propName)) {
                     return new Status(StatusCode.SUCCESS);
                 }
-                Map<String, Property> propMap = new HashMap<String, Property>();
-                for (String s : propMapCurr.keySet()) {
-                    propMap.put(s, propMapCurr.get(s).clone());
-                }
-
+                Map<String, Property> propMap = new HashMap<String, Property>(propMapCurr);
                 propMap.remove(propName);
                 if (nodeProps.replace(node, propMapCurr, propMap)) {
                     return new Status(StatusCode.SUCCESS);
@@ -1135,24 +1207,15 @@ CommandProvider {
     }
 
     @Override
-    public Map<String, Property> getNodeConnectorProps(
-            NodeConnector nodeConnector) {
-        if (isDefaultContainer) {
-            Map<String, Property> rv = null;
-            if (this.nodeConnectorProps != null) {
-                rv = this.nodeConnectorProps.get(nodeConnector);
-                if (rv != null) {
-                    rv = new HashMap<String, Property>(rv);
-                }
+    public Map<String, Property> getNodeConnectorProps(NodeConnector nodeConnector) {
+        Map<String, Property> rv = new HashMap<String, Property>();
+        if (this.nodeConnectorProps != null) {
+            rv = this.nodeConnectorProps.get(nodeConnector);
+            if (rv != null) {
+                rv = new HashMap<String, Property>(rv);
             }
-            return rv;
-        } else {
-            // get it from default container
-            ISwitchManager defaultSwitchManager = (ISwitchManager) ServiceHelper
-                    .getInstance(ISwitchManager.class,
-                            GlobalConstants.DEFAULT.toString(), this);
-            return defaultSwitchManager.getNodeConnectorProps(nodeConnector);
         }
+        return rv;
     }
 
     @Override
@@ -1227,13 +1290,8 @@ CommandProvider {
     public Status addNodeConnectorProp(NodeConnector nodeConnector,
             Property prop) {
         Map<String, Property> propMapCurr = getNodeConnectorProps(nodeConnector);
-        Map<String, Property> propMap = new HashMap<String, Property>();
-
-        if (propMapCurr != null) {
-            for (String s : propMapCurr.keySet()) {
-                propMap.put(s, propMapCurr.get(s).clone());
-            }
-        }
+        Map<String, Property> propMap = (propMapCurr == null) ? new HashMap<String, Property>()
+                : new HashMap<String, Property>(propMapCurr);
 
         String msg = "Cluster conflict: Unable to add NodeConnector Property.";
         // Just add the nodeConnector if prop is not available (in a non-default
@@ -1313,12 +1371,7 @@ CommandProvider {
             return new Status(StatusCode.SUCCESS);
         }
 
-        Map<String, Property> propMap = new HashMap<String, Property>();
-
-        for (String s : propMapCurr.keySet()) {
-            propMap.put(s, propMapCurr.get(s).clone());
-        }
-
+        Map<String, Property> propMap = new HashMap<String, Property>(propMapCurr);
         propMap.remove(propName);
         boolean result = nodeConnectorProps.replace(nodeConnector, propMapCurr, propMap);
         String msg = "Cluster conflict: Unable to remove NodeConnector property.";
@@ -1590,7 +1643,8 @@ CommandProvider {
         for (Node node : getNodes()) {
             SwitchConfig sc = getSwitchConfig(node.toString());
             if ((sc != null) && isDefaultContainer) {
-                service.modeChangeNotify(node, sc.isProactive());
+                ForwardingMode mode = (ForwardingMode) sc.getProperty(ForwardingMode.name);
+                service.modeChangeNotify(node, (mode == null) ? false : mode.isProactive());
             }
         }
     }
@@ -1996,6 +2050,9 @@ CommandProvider {
             } else if (propName.equalsIgnoreCase(Bandwidth.BandwidthPropName)) {
                 long bw = Long.parseLong(propValue);
                 return new Bandwidth(bw);
+            } else if (propName.equalsIgnoreCase(ForwardingMode.name)) {
+                int mode = Integer.parseInt(propValue);
+                return new ForwardingMode(mode);
             } else {
                 log.debug("Not able to create {} property", propName);
             }