-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
-import java.util.Collections;
+import java.util.ArrayList;
+import java.util.Date;
import java.util.Dictionary;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CopyOnWriteArraySet;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.felix.dm.Component;
import org.opendaylight.controller.clustering.services.IClusterContainerServices;
import org.opendaylight.controller.clustering.services.IClusterServices;
import org.opendaylight.controller.configuration.IConfigurationContainerAware;
-import org.opendaylight.controller.sal.core.ConstructionException;
import org.opendaylight.controller.sal.core.Edge;
import org.opendaylight.controller.sal.core.Host;
import org.opendaylight.controller.sal.core.Node;
import org.opendaylight.controller.sal.core.NodeConnector;
-import org.opendaylight.controller.sal.core.NodeConnector.NodeConnectorIDType;
import org.opendaylight.controller.sal.core.Property;
import org.opendaylight.controller.sal.core.TimeStamp;
import org.opendaylight.controller.sal.core.UpdateType;
-import org.opendaylight.controller.sal.core.Node.NodeIDType;
import org.opendaylight.controller.sal.topology.IListenTopoUpdates;
import org.opendaylight.controller.sal.topology.ITopologyService;
-import org.opendaylight.controller.sal.utils.StatusCode;
+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.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.topologymanager.ITopologyManager;
import org.opendaylight.controller.topologymanager.ITopologyManagerAware;
import org.opendaylight.controller.topologymanager.TopologyUserLinkConfig;
* topology database and notifies all the listeners of topology changes.
*/
public class TopologyManagerImpl implements ITopologyManager,
- IConfigurationContainerAware, IListenTopoUpdates, IObjectReader,
- CommandProvider {
- private static final Logger log = LoggerFactory
- .getLogger(TopologyManagerImpl.class);
- private ITopologyService topoService = null;
- private IClusterContainerServices clusterContainerService = null;
+IConfigurationContainerAware, IListenTopoUpdates, IObjectReader,
+CommandProvider {
+ private static final Logger log = LoggerFactory.getLogger(TopologyManagerImpl.class);
+ private static final String SAVE = "Save";
+ private ITopologyService topoService;
+ private IClusterContainerServices clusterContainerService;
// DB of all the Edges with properties which constitute our topology
- private ConcurrentMap<Edge, Set<Property>> edgesDB = null;
- // DB of all NodeConnector which are part of Edges, meaning they
- // are connected to another NodeConnector on the other side
- private ConcurrentMap<NodeConnector, Set<Property>> nodeConnectorsDB = null;
+ private ConcurrentMap<Edge, Set<Property>> edgesDB;
+ // DB of all NodeConnector which are part of ISL Edges, meaning they
+ // are connected to another NodeConnector on the other side of an ISL link.
+ // NodeConnector of a Production Edge is not part of this DB.
+ private ConcurrentMap<NodeConnector, Set<Property>> nodeConnectorsDB;
// DB of all the NodeConnectors with an Host attached to it
- private ConcurrentMap<NodeConnector, ImmutablePair<Host, Set<Property>>> hostsDB = null;
+ private ConcurrentMap<NodeConnector, ImmutablePair<Host, Set<Property>>> hostsDB;
// Topology Manager Aware listeners
- private Set<ITopologyManagerAware> topologyManagerAware = Collections
- .synchronizedSet(new HashSet<ITopologyManagerAware>());
+ private Set<ITopologyManagerAware> topologyManagerAware =
+ new CopyOnWriteArraySet<ITopologyManagerAware>();;
private static String ROOT = GlobalConstants.STARTUPHOME.toString();
- private String userLinksFileName = null;
- private ConcurrentMap<String, TopologyUserLinkConfig> userLinks;
-
+ private String userLinksFileName;
+ private ConcurrentMap<String, TopologyUserLinkConfig> userLinksDB;
+ private ConcurrentMap<Long, String> configSaveEvent;
+
+
void nonClusterObjectCreate() {
- edgesDB = new ConcurrentHashMap<Edge, Set<Property>>();
- hostsDB = new ConcurrentHashMap<NodeConnector, ImmutablePair<Host, Set<Property>>>();
- userLinks = new ConcurrentHashMap<String, TopologyUserLinkConfig>();
- nodeConnectorsDB = new ConcurrentHashMap<NodeConnector, Set<Property>>();
+ edgesDB = new ConcurrentHashMap<Edge, Set<Property>>();
+ hostsDB = new ConcurrentHashMap<NodeConnector, ImmutablePair<Host, Set<Property>>>();
+ nodeConnectorsDB = new ConcurrentHashMap<NodeConnector, Set<Property>>();
+ userLinksDB = new ConcurrentHashMap<String, TopologyUserLinkConfig>();
+ configSaveEvent = new ConcurrentHashMap<Long, String>();
}
-
void setTopologyManagerAware(ITopologyManagerAware s) {
if (this.topologyManagerAware != null) {
- log.debug("Adding ITopologyManagerAware: {}", s);
+ log.debug("Adding ITopologyManagerAware: {}", s);
this.topologyManagerAware.add(s);
}
}
void unsetTopologyManagerAware(ITopologyManagerAware s) {
if (this.topologyManagerAware != null) {
- log.debug("Removing ITopologyManagerAware: {}", s);
+ log.debug("Removing ITopologyManagerAware: {}", s);
this.topologyManagerAware.remove(s);
}
}
void setTopoService(ITopologyService s) {
- log.debug("Adding ITopologyService: {}", s);
+ log.debug("Adding ITopologyService: {}", s);
this.topoService = s;
}
void unsetTopoService(ITopologyService s) {
if (this.topoService == s) {
- log.debug("Removing ITopologyService: {}", s);
+ log.debug("Removing ITopologyService: {}", s);
this.topoService = null;
}
}
*
*/
void init(Component c) {
+
+ allocateCaches();
+ retrieveCaches();
+
String containerName = null;
- Dictionary props = c.getServiceProperties();
+ Dictionary<?, ?> props = c.getServiceProperties();
if (props != null) {
containerName = (String) props.get("containerName");
} else {
containerName = "UNKNOWN";
}
- if (this.clusterContainerService == null) {
- log.error("Cluster Services is null, not expected!");
- return;
- }
+ userLinksFileName = ROOT + "userTopology_" + containerName + ".conf";
+ registerWithOSGIConsole();
+ loadConfiguration();
+ }
- if (this.topoService == null) {
- log.error("Topology Services is null, not expected!");
+ @SuppressWarnings({ "unchecked", "deprecation" })
+ private void allocateCaches(){
+ if (this.clusterContainerService == null) {
+ nonClusterObjectCreate();
+ log.error("Cluster Services unavailable, allocated non-cluster caches!");
return;
}
try {
- this.edgesDB = (ConcurrentMap<Edge, Set<Property>>) this.clusterContainerService
- .createCache("topologymanager.edgesDB", EnumSet
- .of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+ this.edgesDB = (ConcurrentMap<Edge, Set<Property>>) this.clusterContainerService.createCache(
+ "topologymanager.edgesDB", EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
} catch (CacheExistException cee) {
- log.error("topologymanager.edgesDB Cache already exists - "
- + "destroy and recreate if needed");
+ log.debug("topologymanager.edgesDB Cache already exists - destroy and recreate if needed");
} catch (CacheConfigException cce) {
- log.error("topologymanager.edgesDB Cache configuration invalid - "
- + "check cache mode");
+ log.error("topologymanager.edgesDB Cache configuration invalid - check cache mode");
}
try {
this.hostsDB = (ConcurrentMap<NodeConnector, ImmutablePair<Host, Set<Property>>>) this.clusterContainerService
- .createCache("topologymanager.hostsDB", EnumSet
- .of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+ .createCache("topologymanager.hostsDB", EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
} catch (CacheExistException cee) {
- log.error("topologymanager.hostsDB Cache already exists - "
- + "destroy and recreate if needed");
+ log.debug("topologymanager.hostsDB Cache already exists - destroy and recreate if needed");
} catch (CacheConfigException cce) {
- log.error("topologymanager.hostsDB Cache configuration invalid - "
- + "check cache mode");
+ log.error("topologymanager.hostsDB Cache configuration invalid - check cache mode");
}
try {
this.nodeConnectorsDB = (ConcurrentMap<NodeConnector, Set<Property>>) this.clusterContainerService
- .createCache("topologymanager.nodeConnectorDB", EnumSet
- .of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+ .createCache("topologymanager.nodeConnectorDB", EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
} catch (CacheExistException cee) {
- log.error("topologymanager.nodeConnectorDB Cache already exists"
- + " - destroy and recreate if needed");
+ log.debug("topologymanager.nodeConnectorDB Cache already exists - destroy and recreate if needed");
} catch (CacheConfigException cce) {
- log.error("topologymanager.nodeConnectorDB Cache configuration "
- + "invalid - check cache mode");
+ log.error("topologymanager.nodeConnectorDB Cache configuration invalid - check cache mode");
}
- userLinks = new ConcurrentHashMap<String, TopologyUserLinkConfig>();
+ try {
+ this.userLinksDB = (ConcurrentMap<String, TopologyUserLinkConfig>) this.clusterContainerService
+ .createCache("topologymanager.userLinksDB", EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+ } catch (CacheExistException cee) {
+ log.debug("topologymanager.userLinksDB Cache already exists - destroy and recreate if needed");
+ } catch (CacheConfigException cce) {
+ log.error("topologymanager.userLinksDB Cache configuration invalid - check cache mode");
+ }
+
+ try {
+ this.configSaveEvent = (ConcurrentMap<Long, String>) this.clusterContainerService
+ .createCache("topologymanager.configSaveEvent", EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+ } catch (CacheExistException cee) {
+ log.debug("topologymanager.configSaveEvent Cache already exists - destroy and recreate if needed");
+ } catch (CacheConfigException cce) {
+ log.error("topologymanager.configSaveEvent Cache configuration invalid - check cache mode");
+ }
+
+ }
+
+ @SuppressWarnings({ "unchecked", "deprecation" })
+ private void retrieveCaches() {
+ if (this.clusterContainerService == null) {
+ log.error("Cluster Services is null, can't retrieve caches.");
+ return;
+ }
+
+ this.edgesDB = (ConcurrentMap<Edge, Set<Property>>) this.clusterContainerService
+ .getCache("topologymanager.edgesDB");
+ if (edgesDB == null) {
+ log.error("Failed to get cache for topologymanager.edgesDB");
+ }
+
+ this.hostsDB = (ConcurrentMap<NodeConnector, ImmutablePair<Host, Set<Property>>>) this.clusterContainerService
+ .getCache("topologymanager.hostsDB");
+ if (hostsDB == null) {
+ log.error("Failed to get cache for topologymanager.hostsDB");
+ }
+
+ this.nodeConnectorsDB = (ConcurrentMap<NodeConnector, Set<Property>>) this.clusterContainerService
+ .getCache("topologymanager.nodeConnectorDB");
+ if (nodeConnectorsDB == null) {
+ log.error("Failed to get cache for topologymanager.nodeConnectorDB");
+ }
+
+ this.userLinksDB = (ConcurrentMap<String, TopologyUserLinkConfig>) this.clusterContainerService
+ .getCache("topologymanager.userLinksDB");
+ if (userLinksDB == null) {
+ log.error("Failed to get cache for topologymanager.userLinksDB");
+ }
+
+ this.configSaveEvent = (ConcurrentMap<Long, String>) this.clusterContainerService
+ .getCache("topologymanager.configSaveEvent");
+ if (configSaveEvent == null) {
+ log.error("Failed to get cache for topologymanager.configSaveEvent");
+ }
- userLinksFileName = ROOT + "userTopology_" + containerName + ".conf";
- registerWithOSGIConsole();
- loadConfiguration();
}
/**
- * Function called after the topology manager has registered the
- * service in OSGi service registry.
+ * Function called after the topology manager has registered the service in
+ * OSGi service registry.
*
*/
void started() {
}
/**
- * Function called by the dependency manager when at least one
- * dependency become unsatisfied or when the component is shutting
- * down because for example bundle is being stopped.
+ * Function called by the dependency manager when at least one dependency
+ * become unsatisfied or when the component is shutting down because for
+ * example bundle is being stopped.
*
*/
void destroy() {
- if (this.clusterContainerService == null) {
- log.error("Cluster Services is null, not expected!");
- this.edgesDB = null;
- this.hostsDB = null;
- this.nodeConnectorsDB = null;
- return;
- }
- this.clusterContainerService.destroyCache("topologymanager.edgesDB");
- this.edgesDB = null;
- this.clusterContainerService.destroyCache("topologymanager.hostsDB");
- this.hostsDB = null;
- this.clusterContainerService
- .destroyCache("topologymanager.nodeConnectorDB");
- this.nodeConnectorsDB = null;
- log.debug("Topology Manager DB Deallocated");
}
@SuppressWarnings("unchecked")
private void loadConfiguration() {
ObjectReader objReader = new ObjectReader();
- ConcurrentMap<String, TopologyUserLinkConfig> confList = (ConcurrentMap<String, TopologyUserLinkConfig>) objReader
- .read(this, userLinksFileName);
-
- if (confList == null) {
- return;
- }
+ ConcurrentMap<String, TopologyUserLinkConfig> confList =
+ (ConcurrentMap<String, TopologyUserLinkConfig>) objReader.read(this, userLinksFileName);
- for (TopologyUserLinkConfig conf : confList.values()) {
- addUserLink(conf);
+ if (confList != null) {
+ for (TopologyUserLinkConfig conf : confList.values()) {
+ addUserLink(conf);
+ }
}
}
@Override
public Status saveConfig() {
- // Publish the save config event to the cluster nodes
- /**
- * Get the CLUSTERING SERVICES WORKING BEFORE TRYING THIS
-
- configSaveEvent.put(new Date().getTime(), SAVE);
- */
+ // Publish the save config event to the cluster
+ configSaveEvent.put(new Date().getTime(), SAVE );
return saveConfigInternal();
}
public Status saveConfigInternal() {
- Status retS;
ObjectWriter objWriter = new ObjectWriter();
- retS = objWriter.write(
- new ConcurrentHashMap<String, TopologyUserLinkConfig>(
- userLinks), userLinksFileName);
+ Status saveStatus = objWriter.write(
+ new ConcurrentHashMap<String, TopologyUserLinkConfig>(userLinksDB), userLinksFileName);
- if (retS.isSuccess()) {
- return retS;
- } else {
- return new Status(StatusCode.INTERNALERROR, "Save failed");
+ if (! saveStatus.isSuccess()) {
+ return new Status(StatusCode.INTERNALERROR, "Topology save failed: " + saveStatus.getDescription());
}
+ return saveStatus;
}
@Override
return null;
}
- HashMap<Node, Set<Edge>> res = new HashMap<Node, Set<Edge>>();
- for (Edge key : this.edgesDB.keySet()) {
+ Map<Node, Set<Edge>> res = new HashMap<Node, Set<Edge>>();
+ for (Edge edge : this.edgesDB.keySet()) {
// Lets analyze the tail
- Node node = key.getTailNodeConnector().getNode();
+ Node node = edge.getTailNodeConnector().getNode();
Set<Edge> nodeEdges = res.get(node);
if (nodeEdges == null) {
nodeEdges = new HashSet<Edge>();
+ res.put(node, nodeEdges);
}
- nodeEdges.add(key);
- // We need to re-add to the MAP even if the element was
- // already there so in case of clustered services the map
- // gets updated in the cluster
- res.put(node, nodeEdges);
+ nodeEdges.add(edge);
// Lets analyze the head
- node = key.getHeadNodeConnector().getNode();
+ node = edge.getHeadNodeConnector().getNode();
nodeEdges = res.get(node);
if (nodeEdges == null) {
nodeEdges = new HashSet<Edge>();
+ res.put(node, nodeEdges);
}
- nodeEdges.add(key);
- // We need to re-add to the MAP even if the element was
- // already there so in case of clustered services the map
- // gets updated in the cluster
- res.put(node, nodeEdges);
+ nodeEdges.add(edge);
}
return res;
}
/**
- * The Map returned is a copy of the current topology hence if the
- * topology changes the copy doesn't
+ * This method returns true if the edge is an ISL link.
*
- * @return A Map representing the current topology expressed as
- * edges of the network
+ * @param e
+ * The edge
+ * @return true if it is an ISL link
+ */
+ public boolean isISLink(Edge e) {
+ return (!isProductionLink(e));
+ }
+
+ /**
+ * This method returns true if the edge is a production link.
+ *
+ * @param e
+ * The edge
+ * @return true if it is a production link
+ */
+ public boolean isProductionLink(Edge e) {
+ return (e.getHeadNodeConnector().getType().equals(NodeConnector.NodeConnectorIDType.PRODUCTION)
+ || e.getTailNodeConnector().getType().equals(NodeConnector.NodeConnectorIDType.PRODUCTION));
+ }
+
+ /**
+ * The Map returned is a copy of the current topology hence if the topology
+ * changes the copy doesn't
+ *
+ * @return A Map representing the current topology expressed as edges of the
+ * network
*/
@Override
public Map<Edge, Set<Property>> getEdges() {
return null;
}
- HashMap<Edge, Set<Property>> res = new HashMap<Edge, Set<Property>>();
- for (Edge key : this.edgesDB.keySet()) {
+ Map<Edge, Set<Property>> edgeMap = new HashMap<Edge, Set<Property>>();
+ Set<Property> props;
+ for (Map.Entry<Edge, Set<Property>> edgeEntry : edgesDB.entrySet()) {
// Sets of props are copied because the composition of
// those properties could change with time
- HashSet<Property> prop = new HashSet<Property>(this.edgesDB
- .get(key));
+ props = new HashSet<Property>(edgeEntry.getValue());
// We can simply reuse the key because the object is
// immutable so doesn't really matter that we are
// referencing the only owned by a different table, the
// meaning is the same because doesn't change with time.
- res.put(key, prop);
+ edgeMap.put(edgeEntry.getKey(), props);
}
- return res;
- }
-
- // TODO remove with spring-dm removal
- /**
- * @param set the topologyAware to set
- */
- public void setTopologyAware(Set<Object> set) {
- for (Object s : set) {
- setTopologyManagerAware((ITopologyManagerAware) s);
- }
+ return edgeMap;
}
@Override
return null;
}
- return (this.hostsDB.keySet());
+ return (new HashSet<NodeConnector>(this.hostsDB.keySet()));
}
@Override
return null;
}
HashMap<Node, Set<NodeConnector>> res = new HashMap<Node, Set<NodeConnector>>();
-
- for (NodeConnector p : this.hostsDB.keySet()) {
- Node n = p.getNode();
- Set<NodeConnector> pSet = res.get(n);
- if (pSet == null) {
+ Node node;
+ Set<NodeConnector> portSet;
+ for (NodeConnector nc : this.hostsDB.keySet()) {
+ node = nc.getNode();
+ portSet = res.get(node);
+ if (portSet == null) {
// Create the HashSet if null
- pSet = new HashSet<NodeConnector>();
- res.put(n, pSet);
+ portSet = new HashSet<NodeConnector>();
+ res.put(node, portSet);
}
// Keep updating the HashSet, given this is not a
// clustered map we can just update the set without
// worrying to update the hashmap.
- pSet.add(p);
+ portSet.add(nc);
}
return (res);
}
@Override
- public Host getHostAttachedToNodeConnector(NodeConnector p) {
- if (this.hostsDB == null) {
+ public Host getHostAttachedToNodeConnector(NodeConnector port) {
+ ImmutablePair<Host, Set<Property>> host;
+ if (this.hostsDB == null || (host = this.hostsDB.get(port)) == null) {
return null;
}
-
- return (this.hostsDB.get(p).getLeft());
+ return host.getLeft();
}
@Override
- public void updateHostLink(NodeConnector p, Host h, UpdateType t,
- Set<Property> props) {
- if (this.hostsDB == null) {
- return;
+ public 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
+ // don't allow null values
+ if (props == null) {
+ props = new HashSet<Property>();
+ } else {
+ props = new HashSet<Property>(props);
}
-
+ ImmutablePair<Host, Set<Property>> thisHost = new ImmutablePair<Host, Set<Property>>(h, props);
+
switch (t) {
case ADDED:
case CHANGED:
- // Clone the property set in case non null else just
- // create an empty one. Caches allocated via infinispan
- // don't allow null values
- if (props == null) {
- props = new HashSet<Property>();
- } else {
- props = new HashSet<Property>(props);
- }
-
- this.hostsDB.put(p, new ImmutablePair(h, props));
+ this.hostsDB.put(port, thisHost);
break;
case REMOVED:
- this.hostsDB.remove(p);
+ //remove only if hasn't been concurrently modified
+ this.hostsDB.remove(port, thisHost);
break;
}
}
- @Override
- public void edgeUpdate(Edge e, UpdateType type, Set<Property> props) {
+ private TopoEdgeUpdate edgeUpdate(Edge e, UpdateType type, Set<Property> props) {
switch (type) {
case ADDED:
// Make sure the props are non-null
if (props == null) {
- props = (Set<Property>) new HashSet();
+ props = new HashSet<Property>();
} else {
- // Copy the set so noone is going to change the content
- props = (Set<Property>) new HashSet(props);
+ props = new HashSet<Property>(props);
}
- // Now make sure thre is the creation timestamp for the
- // edge, if not there timestamp with the first update
+ //in case of node switch-over to a different cluster controller,
+ //let's retain edge props
+ Set<Property> currentProps = this.edgesDB.get(e);
+ if (currentProps != null){
+ props.addAll(currentProps);
+ }
+
+ // Now make sure there is the creation timestamp for the
+ // edge, if not there, stamp with the first update
boolean found_create = false;
for (Property prop : props) {
if (prop instanceof TimeStamp) {
TimeStamp t = (TimeStamp) prop;
if (t.getTimeStampName().equals("creation")) {
found_create = true;
+ break;
}
}
}
if (!found_create) {
- TimeStamp t = new TimeStamp(System.currentTimeMillis(),
- "creation");
+ TimeStamp t = new TimeStamp(System.currentTimeMillis(), "creation");
props.add(t);
}
this.edgesDB.put(e, props);
// Now populate the DB of NodeConnectors
- // NOTE WELL: properties are empy sets, not really needed
+ // NOTE WELL: properties are empty sets, not really needed
// for now.
- this.nodeConnectorsDB.put(e.getHeadNodeConnector(),
- new HashSet<Property>());
- this.nodeConnectorsDB.put(e.getTailNodeConnector(),
- new HashSet<Property>());
+ // The DB only contains ISL ports
+ if (isISLink(e)) {
+ this.nodeConnectorsDB.put(e.getHeadNodeConnector(), new HashSet<Property>(1));
+ this.nodeConnectorsDB.put(e.getTailNodeConnector(), new HashSet<Property>(1));
+ }
log.trace("Edge {} {}", e.toString(), type.name());
break;
case REMOVED:
log.trace("Edge {} {}", e.toString(), type.name());
break;
case CHANGED:
- Set<Property> old_props = this.edgesDB.get(e);
+ Set<Property> oldProps = this.edgesDB.get(e);
// When property 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
- TimeStamp tc = null;
- for (Property prop : old_props) {
+ TimeStamp timeStamp = null;
+ for (Property prop : oldProps) {
if (prop instanceof TimeStamp) {
- TimeStamp t = (TimeStamp) prop;
- if (t.getTimeStampName().equals("creation")) {
- tc = t;
+ TimeStamp tsProp = (TimeStamp) prop;
+ if (tsProp.getTimeStampName().equals("creation")) {
+ timeStamp = tsProp;
+ break;
}
}
}
- // Now lest make sure new properties are non-null
- // Make sure the props are non-null
+ // Now lets make sure new properties are non-null
if (props == null) {
- props = (Set<Property>) new HashSet();
+ props = new HashSet<Property>();
} else {
// Copy the set so noone is going to change the content
- props = (Set<Property>) new HashSet(props);
+ props = new HashSet<Property>(props);
}
// Now lets remove the creation property if exist in the
TimeStamp t = (TimeStamp) prop;
if (t.getTimeStampName().equals("creation")) {
i.remove();
+ break;
}
}
}
// Now lets add the creation timestamp in it
- if (tc != null) {
- props.add(tc);
+ if (timeStamp != null) {
+ props.add(timeStamp);
}
// Finally update
log.trace("Edge {} {}", e.toString(), type.name());
break;
}
+ return new TopoEdgeUpdate(e, props, type);
+ }
+
+ @Override
+ public void edgeUpdate(List<TopoEdgeUpdate> topoedgeupdateList) {
+ List<TopoEdgeUpdate> teuList = new ArrayList<TopoEdgeUpdate>();
+ for (int i = 0; i < topoedgeupdateList.size(); i++) {
+ Edge e = topoedgeupdateList.get(i).getEdge();
+ Set<Property> p = topoedgeupdateList.get(i).getProperty();
+ UpdateType type = topoedgeupdateList.get(i).getUpdateType();
+ TopoEdgeUpdate teu = edgeUpdate(e, type, p);
+ teuList.add(teu);
+ }
// Now update the listeners
for (ITopologyManagerAware s : this.topologyManagerAware) {
try {
- s.edgeUpdate(e, type, props);
+ s.edgeUpdate(teuList);
} catch (Exception exc) {
- log.error("Exception on callback", exc);
+ log.error("Exception on edge update:", exc);
}
}
+
}
private Edge getReverseLinkTuple(TopologyUserLinkConfig link) {
- TopologyUserLinkConfig rLink = new TopologyUserLinkConfig(
- link.getName(), link.getDstNodeIDType(), link.getDstSwitchId(),
- link.getDstNodeConnectorIDType(), link.getDstPort(),
- link.getSrcNodeIDType(), link.getSrcSwitchId(),
- link.getSrcNodeConnectorIDType(), link.getSrcPort());
+ TopologyUserLinkConfig rLink = new TopologyUserLinkConfig(
+ link.getName(), link.getDstNodeConnector(), link.getSrcNodeConnector());
return getLinkTuple(rLink);
}
- private Edge getLinkTuple(TopologyUserLinkConfig link) {
- Edge linkTuple = null;
-
- // if atleast 1 link exists for the srcPort and atleast 1 link exists for the dstPort
- // that makes it ineligible for the Manual link addition
- // This is just an extra protection to avoid mis-programming.
- boolean srcLinkExists = false;
- boolean dstLinkExists = false;
- //TODO check a way to validate the port with inventory services
- //if (srcSw.getPorts().contains(srcPort) &&
- //dstSw.getPorts().contains(srcPort) &&
- if (!srcLinkExists && !dstLinkExists) {
- Node sNode = null;
- Node dNode = null;
- NodeConnector sPort = null;
- NodeConnector dPort = null;
- linkTuple = null;
- String srcNodeIDType = link.getSrcNodeIDType();
- String srcNodeConnectorIDType = link.getSrcNodeConnectorIDType();
- String dstNodeIDType = link.getDstNodeIDType();
- String dstNodeConnectorIDType = link.getDstNodeConnectorIDType();
- try {
- if (srcNodeIDType.equals(NodeIDType.OPENFLOW)) {
- sNode = new Node(srcNodeIDType, link.getSrcSwitchIDLong());
- } else {
- sNode = new Node(srcNodeIDType, link.getSrcSwitchId());
- }
-
- if (dstNodeIDType.equals(NodeIDType.OPENFLOW)) {
- dNode = new Node(dstNodeIDType, link.getDstSwitchIDLong());
- } else {
- dNode = new Node(dstNodeIDType, link.getDstSwitchId());
- }
-
- if (srcNodeConnectorIDType.equals(NodeConnectorIDType.OPENFLOW)) {
- Short srcPort = Short.valueOf((short) 0);
- if (!link.isSrcPortByName()) {
- srcPort = Short.parseShort(link.getSrcPort());
- }
- sPort = new NodeConnector(srcNodeConnectorIDType,
- srcPort, sNode);
- } else {
- sPort = new NodeConnector(srcNodeConnectorIDType,
- link.getSrcPort(), sNode);
- }
-
- if (dstNodeConnectorIDType.equals(NodeConnectorIDType.OPENFLOW)) {
- Short dstPort = Short.valueOf((short) 0);
- if (!link.isDstPortByName()) {
- dstPort = Short.parseShort(link.getDstPort());
- }
- dPort = new NodeConnector(dstNodeConnectorIDType,
- dstPort, dNode);
- } else {
- dPort = new NodeConnector(dstNodeConnectorIDType,
- link.getDstPort(), dNode);
- }
- linkTuple = new Edge(sPort, dPort);
- } catch (ConstructionException cex) {
- log.warn("Caught exception ", cex);
- }
- return linkTuple;
- }
- if (srcLinkExists && dstLinkExists) {
- link.setStatus(TopologyUserLinkConfig.STATUS.INCORRECT);
+ private Edge getLinkTuple(TopologyUserLinkConfig link) {
+ NodeConnector srcNodeConnector = NodeConnector.fromString(link.getSrcNodeConnector());
+ NodeConnector dstNodeConnector = NodeConnector.fromString(link.getDstNodeConnector());
+ try {
+ return new Edge(srcNodeConnector, dstNodeConnector);
+ } catch (Exception e) {
+ return null;
}
- return null;
}
@Override
public ConcurrentMap<String, TopologyUserLinkConfig> getUserLinks() {
- return userLinks;
+ return new ConcurrentHashMap<String, TopologyUserLinkConfig>(userLinksDB);
}
@Override
- public Status addUserLink(TopologyUserLinkConfig link) {
- if (!link.isValid()) {
- return new Status(StatusCode.BADREQUEST,
- "Configuration Invalid. Please check the parameters");
- }
- if (userLinks.get(link.getName()) != null) {
- return new Status(StatusCode.CONFLICT,
- "Link with name : " + link.getName()
- + " already exists. Please use another name");
+ public Status addUserLink(TopologyUserLinkConfig userLink) {
+ if (!userLink.isValid()) {
+ return new Status(StatusCode.BADREQUEST,
+ "User link configuration invalid.");
+ }
+ userLink.setStatus(TopologyUserLinkConfig.STATUS.LINKDOWN);
+
+ //Check if this link already configured
+ //NOTE: infinispan cache doesn't support Map.containsValue()
+ // (which is linear time in most ConcurrentMap impl anyway)
+ for (TopologyUserLinkConfig existingLink : userLinksDB.values()) {
+ if (existingLink.equals(userLink)) {
+ return new Status(StatusCode.CONFLICT, "Link configuration exists");
+ }
}
- if (userLinks.containsValue(link)) {
- return new Status(StatusCode.CONFLICT, "Link configuration exists");
+ //attempt put, if mapping for this key already existed return conflict
+ if (userLinksDB.putIfAbsent(userLink.getName(), userLink) != null) {
+ return new Status(StatusCode.CONFLICT, "Link with name : " + userLink.getName()
+ + " already exists. Please use another name");
}
- link.setStatus(TopologyUserLinkConfig.STATUS.LINKDOWN);
- userLinks.put(link.getName(), link);
-
- Edge linkTuple = getLinkTuple(link);
+ Edge linkTuple = getLinkTuple(userLink);
if (linkTuple != null) {
- try {
- linkTuple = getReverseLinkTuple(link);
- link.setStatus(TopologyUserLinkConfig.STATUS.SUCCESS);
- } catch (Exception e) {
- return new Status(StatusCode.INTERNALERROR,
- "Exception while adding custom link : " +
- e.getMessage());
+ if (!isProductionLink(linkTuple)) {
+ edgeUpdate(linkTuple, UpdateType.ADDED, new HashSet<Property>());
+ }
+
+ linkTuple = getReverseLinkTuple(userLink);
+ if (linkTuple != null) {
+ userLink.setStatus(TopologyUserLinkConfig.STATUS.SUCCESS);
+ if (!isProductionLink(linkTuple)) {
+ edgeUpdate(linkTuple, UpdateType.ADDED, new HashSet<Property>());
+ }
}
}
- return new Status(StatusCode.SUCCESS, null);
+ return new Status(StatusCode.SUCCESS);
}
@Override
public Status deleteUserLink(String linkName) {
if (linkName == null) {
- return new Status(StatusCode.BADREQUEST,
- "A valid linkName is required to Delete a link");
+ return new Status(StatusCode.BADREQUEST, "User link name cannot be null.");
}
- TopologyUserLinkConfig link = userLinks.get(linkName);
-
- Edge linkTuple = getLinkTuple(link);
- userLinks.remove(linkName);
- if (linkTuple != null) {
- try {
- //oneTopology.deleteUserConfiguredLink(linkTuple);
- } catch (Exception e) {
- log
- .warn("Harmless : Exception while Deleting User Configured link {} {}",
- link, e.toString());
+ TopologyUserLinkConfig link = userLinksDB.remove(linkName);
+ Edge linkTuple;
+ if (link != null && (linkTuple = getLinkTuple(link)) != null) {
+ if (! isProductionLink(linkTuple)) {
+ edgeUpdate(linkTuple, UpdateType.REMOVED, null);
}
+
linkTuple = getReverseLinkTuple(link);
- try {
- //oneTopology.deleteUserConfiguredLink(linkTuple);
- } catch (Exception e) {
- log
- .warn("Harmless : Exception while Deleting User Configured Reverse link {} {}",
- link, e.toString());
+ if (! isProductionLink(linkTuple)) {
+ edgeUpdate(linkTuple, UpdateType.REMOVED, null);
}
}
- return new Status(StatusCode.SUCCESS, null);
+ return new Status(StatusCode.SUCCESS);
}
private void registerWithOSGIConsole() {
public String getHelp() {
StringBuffer help = new StringBuffer();
help.append("---Topology Manager---\n");
- help.append("\t addTopo name <NodeIDType> <src-sw-id> <NodeConnectorIDType> <port-number> <NodeIDType> <dst-sw-id> <NodeConnectorIDType> <port-number>\n");
- help.append("\t delTopo name\n");
- help.append("\t printTopo\n");
+ help.append("\t addUserLink <name> <node connector string> <node connector string>\n");
+ help.append("\t deleteUserLink <name>\n");
+ help.append("\t printUserLink\n");
help.append("\t printNodeEdges\n");
return help.toString();
}
- public void _printTopo(CommandInterpreter ci) {
- for (String name : this.userLinks.keySet()) {
- TopologyUserLinkConfig linkConfig = userLinks.get(name);
+ public void _printUserLink(CommandInterpreter ci) {
+ for (String name : this.userLinksDB.keySet()) {
+ TopologyUserLinkConfig linkConfig = userLinksDB.get(name);
ci.println("Name : " + name);
ci.println(linkConfig);
- ci.println("Edge " + getLinkTuple(linkConfig));
- ci.println("Reverse Edge " + getReverseLinkTuple(linkConfig));
+ ci.println("Edge " + getLinkTuple(linkConfig));
+ ci.println("Reverse Edge " + getReverseLinkTuple(linkConfig));
}
}
- public void _addTopo(CommandInterpreter ci) {
+ public void _addUserLink(CommandInterpreter ci) {
String name = ci.nextArgument();
if ((name == null)) {
ci.println("Please enter a valid Name");
return;
}
- String srcNodeIDType = ci.nextArgument();
- if (srcNodeIDType == null) {
- ci.println("Null source node ID Type. Example: OF or PR");
- return;
- }
-
- String dpid = ci.nextArgument();
- if (dpid == null) {
- ci.println("Null source node id");
+ String ncStr1 = ci.nextArgument();
+ if (ncStr1 == null) {
+ ci.println("Please enter two node connector strings");
return;
}
-
- String srcNodeConnectorIDType = ci.nextArgument();
- if (srcNodeConnectorIDType == null) {
- ci.println("Null source node connector ID Type. Example: OF or PR");
- return;
- }
-
- String port = ci.nextArgument();
- if (port == null) {
- ci.println("Null source port number");
+ String ncStr2 = ci.nextArgument();
+ if (ncStr2 == null) {
+ ci.println("Please enter second node connector string");
return;
}
- String dstNodeIDType = ci.nextArgument();
- if (dstNodeIDType == null) {
- ci.println("Null destination node ID Type. Example: OF or PR");
+ NodeConnector nc1 = NodeConnector.fromString(ncStr1);
+ if (nc1 == null) {
+ ci.println("Invalid input node connector 1 string: " + ncStr1);
return;
}
-
- String ddpid = ci.nextArgument();
- if (ddpid == null) {
- ci.println("Null destination node ID");
- return;
- }
-
- String dstNodeConnectorIDType = ci.nextArgument();
- if (dstNodeConnectorIDType == null) {
- ci.println("Null destination node connector ID Type. Example: OF or PR");
+ NodeConnector nc2 = NodeConnector.fromString(ncStr2);
+ if (nc2 == null) {
+ ci.println("Invalid input node connector 2 string: " + ncStr2);
return;
}
- String dport = ci.nextArgument();
- if (dport == null) {
- ci.println("Null destination port number");
- return;
- }
- TopologyUserLinkConfig config = new TopologyUserLinkConfig(name,
- srcNodeIDType, dpid, srcNodeConnectorIDType, port,
- dstNodeIDType, ddpid, dstNodeConnectorIDType, dport);
+ TopologyUserLinkConfig config = new TopologyUserLinkConfig(name, ncStr1, ncStr2);
ci.println(this.addUserLink(config));
}
- public void _delTopo(CommandInterpreter ci) {
+ public void _deleteUserLink(CommandInterpreter ci) {
String name = ci.nextArgument();
if ((name == null)) {
ci.println("Please enter a valid Name");
}
public void _printNodeEdges(CommandInterpreter ci) {
- Map<Node, Set<Edge>> nodeEdges = getNodeEdges();
- if (nodeEdges == null) {
- return;
- }
- Set<Node> nodeSet = nodeEdges.keySet();
- if (nodeSet == null) {
- return;
- }
+ Map<Node, Set<Edge>> nodeEdges = getNodeEdges();
+ if (nodeEdges == null) {
+ return;
+ }
+ Set<Node> nodeSet = nodeEdges.keySet();
+ if (nodeSet == null) {
+ return;
+ }
ci.println(" Node Edge");
- for (Node node : nodeSet) {
- Set<Edge> edgeSet = nodeEdges.get(node);
- if (edgeSet == null) {
- continue;
- }
- for (Edge edge : edgeSet) {
- ci.println(node + " " + edge);
- }
+ for (Node node : nodeSet) {
+ Set<Edge> edgeSet = nodeEdges.get(node);
+ if (edgeSet == null) {
+ continue;
+ }
+ for (Edge edge : edgeSet) {
+ ci.println(node + " " + edge);
+ }
}
}
@Override
public Object readObject(ObjectInputStream ois)
throws FileNotFoundException, IOException, ClassNotFoundException {
- // TODO Auto-generated method stub
return ois.readObject();
}