Merge "added feature topology manager shell"
[controller.git] / opendaylight / topologymanager / implementation / src / main / java / org / opendaylight / controller / topologymanager / internal / TopologyManagerImpl.java
index b0570fb7f9b6eed29384ac4c0280202df1fd4a5f..b0e87c48f3e0812fd2e33c7789e5e916479f6465 100644 (file)
@@ -36,7 +36,9 @@ import org.opendaylight.controller.clustering.services.CacheExistException;
 import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
 import org.opendaylight.controller.clustering.services.IClusterContainerServices;
 import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.configuration.ConfigurationObject;
 import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+import org.opendaylight.controller.configuration.IConfigurationContainerService;
 import org.opendaylight.controller.sal.core.Edge;
 import org.opendaylight.controller.sal.core.Host;
 import org.opendaylight.controller.sal.core.Node;
@@ -47,17 +49,15 @@ import org.opendaylight.controller.sal.core.UpdateType;
 import org.opendaylight.controller.sal.topology.IListenTopoUpdates;
 import org.opendaylight.controller.sal.topology.ITopologyService;
 import org.opendaylight.controller.sal.topology.TopoEdgeUpdate;
-import org.opendaylight.controller.sal.utils.GlobalConstants;
 import org.opendaylight.controller.sal.utils.IObjectReader;
 import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
-import org.opendaylight.controller.sal.utils.ObjectReader;
-import org.opendaylight.controller.sal.utils.ObjectWriter;
 import org.opendaylight.controller.sal.utils.Status;
 import org.opendaylight.controller.sal.utils.StatusCode;
 import org.opendaylight.controller.switchmanager.ISwitchManager;
 import org.opendaylight.controller.topologymanager.ITopologyManager;
 import org.opendaylight.controller.topologymanager.ITopologyManagerAware;
 import org.opendaylight.controller.topologymanager.ITopologyManagerClusterWideAware;
+import org.opendaylight.controller.topologymanager.ITopologyManagerShell;
 import org.opendaylight.controller.topologymanager.TopologyUserLinkConfig;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.FrameworkUtil;
@@ -72,6 +72,7 @@ import org.slf4j.LoggerFactory;
 public class TopologyManagerImpl implements
         ICacheUpdateAware<Object, Object>,
         ITopologyManager,
+        ITopologyManagerShell,
         IConfigurationContainerAware,
         IListenTopoUpdates,
         IObjectReader,
@@ -80,9 +81,11 @@ public class TopologyManagerImpl implements
     protected static final String TOPOHOSTSDB = "topologymanager.hostsDB";
     protected static final String TOPONODECONNECTORDB = "topologymanager.nodeConnectorDB";
     protected static final String TOPOUSERLINKSDB = "topologymanager.userLinksDB";
+    private static final String USER_LINKS_FILE_NAME = "userTopology.conf";
     private static final Logger log = LoggerFactory.getLogger(TopologyManagerImpl.class);
     private ITopologyService topoService;
     private IClusterContainerServices clusterContainerService;
+    private IConfigurationContainerService configurationService;
     private ISwitchManager switchManager;
     // DB of all the Edges with properties which constitute our topology
     private ConcurrentMap<Edge, Set<Property>> edgesDB;
@@ -97,8 +100,6 @@ public class TopologyManagerImpl implements
     // Topology Manager Aware listeners - for clusterwide updates
     private Set<ITopologyManagerClusterWideAware> topologyManagerClusterWideAware =
             new CopyOnWriteArraySet<ITopologyManagerClusterWideAware>();
-    private static String ROOT = GlobalConstants.STARTUPHOME.toString();
-    private String userLinksFileName;
     private ConcurrentMap<String, TopologyUserLinkConfig> userLinksDB;
     private BlockingQueue<TopoEdgeUpdate> notifyQ = new LinkedBlockingQueue<TopoEdgeUpdate>();
     private volatile Boolean shuttingDown = false;
@@ -164,6 +165,16 @@ public class TopologyManagerImpl implements
         }
     }
 
+    public void setConfigurationContainerService(IConfigurationContainerService service) {
+        log.trace("Got configuration service set request {}", service);
+        this.configurationService = service;
+    }
+
+    public void unsetConfigurationContainerService(IConfigurationContainerService service) {
+        log.trace("Got configuration service UNset request");
+        this.configurationService = null;
+    }
+
     void setSwitchManager(ISwitchManager s) {
         log.debug("Adding ISwitchManager: {}", s);
         this.switchManager = s;
@@ -193,11 +204,9 @@ public class TopologyManagerImpl implements
             containerName = "UNKNOWN";
         }
 
-        userLinksFileName = ROOT + "userTopology_" + containerName + ".conf";
         registerWithOSGIConsole();
-        if ((clusterContainerService != null) && (clusterContainerService.amICoordinator())) {
-            loadConfiguration();
-        }
+        loadConfiguration();
+
         // Restore the shuttingDown status on init of the component
         shuttingDown = false;
         notifyThread = new Thread(new TopologyNotify(notifyQ));
@@ -292,16 +301,9 @@ public class TopologyManagerImpl implements
         notifyThread = null;
     }
 
-    @SuppressWarnings("unchecked")
     private void loadConfiguration() {
-        ObjectReader objReader = new ObjectReader();
-        ConcurrentMap<String, TopologyUserLinkConfig> confList =
-                (ConcurrentMap<String, TopologyUserLinkConfig>) objReader.read(this, userLinksFileName);
-
-        if (confList != null) {
-            for (TopologyUserLinkConfig conf : confList.values()) {
-                addUserLink(conf);
-            }
+        for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, USER_LINKS_FILE_NAME)) {
+            addUserLink((TopologyUserLinkConfig) conf);
         }
     }
 
@@ -311,12 +313,10 @@ public class TopologyManagerImpl implements
     }
 
     public Status saveConfigInternal() {
-        ObjectWriter objWriter = new ObjectWriter();
+        Status saveStatus = configurationService.persistConfiguration(
+                new ArrayList<ConfigurationObject>(userLinksDB.values()), USER_LINKS_FILE_NAME);
 
-        Status saveStatus = objWriter.write(
-                new ConcurrentHashMap<String, TopologyUserLinkConfig>(userLinksDB), userLinksFileName);
-
-        if (! saveStatus.isSuccess()) {
+        if (!saveStatus.isSuccess()) {
             return new Status(StatusCode.INTERNALERROR, "Topology save failed: " + saveStatus.getDescription());
         }
         return saveStatus;
@@ -524,7 +524,7 @@ public class TopologyManagerImpl implements
     }
 
     @Override
-    public void updateHostLink(NodeConnector port, Host h, UpdateType t, Set<Property> props) {
+    public synchronized void updateHostLink(NodeConnector port, Host h, UpdateType t, Set<Property> props) {
 
         // Clone the property set in case non null else just
         // create an empty one. Caches allocated via infinispan
@@ -575,6 +575,13 @@ public class TopologyManagerImpl implements
         switch (type) {
         case ADDED:
 
+
+            if (this.edgesDB.containsKey(e)) {
+                // Avoid redundant updates (e.g. cluster switch-over) as notifications trigger expensive tasks
+                log.trace("Skipping redundant edge addition: {}", e);
+                return null;
+            }
+
             // Make sure the props are non-null or create a copy
             if (props == null) {
                 props = new HashSet<Property>();
@@ -582,19 +589,6 @@ public class TopologyManagerImpl implements
                 props = new HashSet<Property>(props);
             }
 
-            Set<Property> currentProps = this.edgesDB.get(e);
-            if (currentProps != null) {
-
-                if (currentProps.equals(props)) {
-                    // Avoid redundant updates as notifications trigger expensive tasks
-                    log.trace("Skipping redundant edge addition: {}", e);
-                    return null;
-                }
-
-                // In case of node switch-over to a different cluster controller,
-                // let's retain edge props (e.g. creation time)
-                props.addAll(currentProps);
-            }
 
             // Ensure that head node connector exists
             if (!headNodeConnectorExist(e)) {
@@ -656,10 +650,9 @@ public class TopologyManagerImpl implements
         case CHANGED:
             Set<Property> oldProps = this.edgesDB.get(e);
 
-            // When property changes lets make sure we can change it
+            // When property(s) changes lets make sure we can change it
             // all except the creation time stamp because that should
-            // be changed only when the edge is destroyed and created
-            // again
+            // be set only when the edge is created
             TimeStamp timeStamp = null;
             for (Property prop : oldProps) {
                 if (prop instanceof TimeStamp) {
@@ -1019,4 +1012,82 @@ public class TopologyManagerImpl implements
             }
         }
     }
+
+    public List<String> printUserLink() {
+        List<String> result = new ArrayList<String>();
+        for (String name : this.userLinksDB.keySet()) {
+            TopologyUserLinkConfig linkConfig = userLinksDB.get(name);
+            result.add("Name : " + name);
+            result.add(linkConfig.toString());
+            result.add("Edge " + getLinkTuple(linkConfig));
+            result.add("Reverse Edge " + getReverseLinkTuple(linkConfig));
+        }
+        return result;
+    }
+
+    public List<String> addUserLink(String name, String ncStr1, String ncStr2) {
+        List<String> result = new ArrayList<String>();
+        if ((name == null)) {
+            result.add("Please enter a valid Name");
+            return result;
+        }
+
+        if (ncStr1 == null) {
+            result.add("Please enter two node connector strings");
+            return result;
+        }
+        if (ncStr2 == null) {
+            result.add("Please enter second node connector string");
+            return result;
+        }
+
+        NodeConnector nc1 = NodeConnector.fromString(ncStr1);
+        if (nc1 == null) {
+            result.add("Invalid input node connector 1 string: " + ncStr1);
+            return result;
+        }
+        NodeConnector nc2 = NodeConnector.fromString(ncStr2);
+        if (nc2 == null) {
+            result.add("Invalid input node connector 2 string: " + ncStr2);
+            return result;
+        }
+
+        TopologyUserLinkConfig config = new TopologyUserLinkConfig(name, ncStr1, ncStr2);
+        result.add(this.addUserLink(config).toString());
+        return result;
+    }
+
+    public List<String> deleteUserLinkShell(String name) {
+        List<String> result = new ArrayList<String>();
+        if ((name == null)) {
+            result.add("Please enter a valid Name");
+            return result;
+        }
+        this.deleteUserLink(name);
+        return result;
+    }
+
+    public List<String> printNodeEdges() {
+        List<String> result = new ArrayList<String>();
+        Map<Node, Set<Edge>> nodeEdges = getNodeEdges();
+        if (nodeEdges == null) {
+            return result;
+        }
+        Set<Node> nodeSet = nodeEdges.keySet();
+        if (nodeSet == null) {
+            return result;
+        }
+        result.add("        Node                                         Edge");
+        for (Node node : nodeSet) {
+            Set<Edge> edgeSet = nodeEdges.get(node);
+            if (edgeSet == null) {
+                continue;
+            }
+            for (Edge edge : edgeSet) {
+                result.add(node + "             " + edge);
+            }
+        }
+        return result;
+    }
+
 }