import java.net.SocketException;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Date;
import java.util.Dictionary;
import java.util.EnumSet;
import java.util.Enumeration;
import org.eclipse.osgi.framework.console.CommandProvider;
import org.opendaylight.controller.clustering.services.CacheConfigException;
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.IConfigurationContainerAware;
import org.opendaylight.controller.sal.core.UpdateType;
import org.opendaylight.controller.sal.inventory.IInventoryService;
import org.opendaylight.controller.sal.inventory.IListenInventoryUpdates;
+import org.opendaylight.controller.sal.reader.NodeDescription;
import org.opendaylight.controller.sal.utils.GlobalConstants;
import org.opendaylight.controller.sal.utils.HexEncode;
import org.opendaylight.controller.sal.utils.IObjectReader;
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.statisticsmanager.IStatisticsManager;
import org.opendaylight.controller.switchmanager.IInventoryListener;
import org.opendaylight.controller.switchmanager.ISpanAware;
import org.opendaylight.controller.switchmanager.ISwitchManager;
* instance per container of the network. All the node/nodeConnector properties
* are maintained in the default container only.
*/
-public class SwitchManager implements ISwitchManager,
-IConfigurationContainerAware, IObjectReader,
-ICacheUpdateAware<Long, String>, IListenInventoryUpdates,
-CommandProvider {
+public class SwitchManager implements ISwitchManager, IConfigurationContainerAware,
+ IObjectReader, IListenInventoryUpdates, CommandProvider {
private static Logger log = LoggerFactory.getLogger(SwitchManager.class);
private static String ROOT = GlobalConstants.STARTUPHOME.toString();
- private static final String SAVE = "Save";
private String subnetFileName, spanFileName, switchConfigFileName;
private final List<NodeConnector> spanNodeConnectors = new CopyOnWriteArrayList<NodeConnector>();
- // set of Subnets keyed by the InetAddress
+ // Collection of Subnets keyed by the InetAddress
private ConcurrentMap<InetAddress, Subnet> subnets;
private ConcurrentMap<String, SubnetConfig> subnetsConfigList;
private ConcurrentMap<SpanConfig, SpanConfig> spanConfigList;
// 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;
private ConcurrentMap<NodeConnector, Map<String, Property>> nodeConnectorProps;
private ConcurrentMap<Node, Map<String, NodeConnector>> nodeConnectorNames;
private ConcurrentMap<String, Property> controllerProps;
private IInventoryService inventoryService;
+ private IStatisticsManager statisticsManager;
private final Set<ISwitchManagerAware> switchManagerAware = Collections
.synchronizedSet(new HashSet<ISwitchManagerAware>());
private final Set<IInventoryListener> inventoryListeners = Collections
.synchronizedSet(new HashSet<IInventoryListener>());
private final Set<ISpanAware> spanAware = Collections.synchronizedSet(new HashSet<ISpanAware>());
- private static boolean hostRefresh = true;
- private int hostRetryCount = 5;
private IClusterContainerServices clusterContainerService = null;
private String containerName = null;
private boolean isDefaultContainer = true;
private static final int REPLACE_RETRY = 1;
+ /* Information about the default subnet. If there have been no configured subnets, i.e.,
+ * subnets.size() == 0 or subnetsConfigList.size() == 0, then this subnet will be the
+ * only subnet returned. As soon as a user-configured subnet is created this one will
+ * vanish.
+ */
+ protected static SubnetConfig DEFAULT_SUBNETCONFIG;
+ protected static Subnet DEFAULT_SUBNET;
+ protected static String DEFAULT_SUBNET_NAME = "default (cannot be modifed)";
+ static{
+ DEFAULT_SUBNETCONFIG = new SubnetConfig(DEFAULT_SUBNET_NAME, "0.0.0.0/0", new ArrayList<String>());
+ DEFAULT_SUBNET = new Subnet(DEFAULT_SUBNETCONFIG);
+ }
+
public void notifySubnetChange(Subnet sub, boolean add) {
synchronized (switchManagerAware) {
for (Object subAware : switchManagerAware) {
public void shutDown() {
}
- @SuppressWarnings("deprecation")
private void allocateCaches() {
if (this.clusterContainerService == null) {
this.nonClusterObjectCreate();
try {
clusterContainerService.createCache(
"switchmanager.subnetsConfigList",
- EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+ EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
clusterContainerService.createCache("switchmanager.spanConfigList",
- EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+ EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
clusterContainerService.createCache("switchmanager.nodeConfigList",
- EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+ EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
clusterContainerService.createCache("switchmanager.subnets",
- EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
- clusterContainerService.createCache(
- "switchmanager.configSaveEvent",
- EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+ EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
clusterContainerService.createCache("switchmanager.nodeProps",
- EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+ EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
clusterContainerService.createCache(
"switchmanager.nodeConnectorProps",
- EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+ EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
clusterContainerService.createCache(
"switchmanager.nodeConnectorNames",
- EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+ EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
clusterContainerService.createCache(
"switchmanager.controllerProps",
- EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+ EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
} catch (CacheConfigException cce) {
log.error("\nCache configuration invalid - check cache mode");
} catch (CacheExistException ce) {
}
}
- @SuppressWarnings({ "unchecked", "deprecation" })
+ @SuppressWarnings({ "unchecked" })
private void retrieveCaches() {
if (this.clusterContainerService == null) {
log.info("un-initialized clusterContainerService, can't create cache");
log.error("\nFailed to get cache for subnets");
}
- configSaveEvent = (ConcurrentMap<Long, String>) clusterContainerService
- .getCache("switchmanager.configSaveEvent");
- if (configSaveEvent == null) {
- log.error("\nFailed to get cache for configSaveEvent");
- }
-
nodeProps = (ConcurrentMap<Node, Map<String, Property>>) clusterContainerService
.getCache("switchmanager.nodeProps");
if (nodeProps == null) {
spanConfigList = new ConcurrentHashMap<SpanConfig, SpanConfig>();
nodeConfigList = new ConcurrentHashMap<String, SwitchConfig>();
subnets = new ConcurrentHashMap<InetAddress, Subnet>();
- configSaveEvent = new ConcurrentHashMap<Long, String>();
nodeProps = new ConcurrentHashMap<Node, Map<String, Property>>();
nodeConnectorProps = new ConcurrentHashMap<NodeConnector, Map<String, Property>>();
nodeConnectorNames = new ConcurrentHashMap<Node, Map<String, NodeConnector>>();
@Override
public List<SubnetConfig> getSubnetsConfigList() {
- return new ArrayList<SubnetConfig>(subnetsConfigList.values());
+ // if there are no subnets, return the default subnet
+ if(subnetsConfigList.size() == 0){
+ return Collections.singletonList(DEFAULT_SUBNETCONFIG);
+ }else{
+ return new ArrayList<SubnetConfig>(subnetsConfigList.values());
+ }
}
@Override
public SubnetConfig getSubnetConfig(String subnet) {
- return subnetsConfigList.get(subnet);
+ // if there are no subnets, return the default subnet
+ if(subnetsConfigList.size() == 0 && subnet == DEFAULT_SUBNET_NAME){
+ return DEFAULT_SUBNETCONFIG;
+ }else{
+ return subnetsConfigList.get(subnet);
+ }
}
private List<SpanConfig> getSpanConfigList(Node node) {
private Status updateDatabase(SubnetConfig conf, boolean add) {
if (add) {
- Subnet subnetCurr = subnets.get(conf.getIPnum());
+ Subnet subnetCurr = subnets.get(conf.getIPAddress());
Subnet subnet;
if (subnetCurr == null) {
subnet = new Subnet(conf);
// In case of API3 call we may receive the ports along with the
// subnet creation
if (!conf.isGlobal()) {
- Set<NodeConnector> sp = conf.getSubnetNodeConnectors();
- subnet.addNodeConnectors(sp);
+ subnet.addNodeConnectors(conf.getNodeConnectors());
}
- boolean result = false;
+ boolean putNewSubnet = false;
if(subnetCurr == null) {
- if(subnets.putIfAbsent(conf.getIPnum(), subnet) == null) {
- result = true;
+ if(subnets.putIfAbsent(conf.getIPAddress(), subnet) == null) {
+ putNewSubnet = true;
}
} else {
- result = subnets.replace(conf.getIPnum(), subnetCurr, subnet);
+ putNewSubnet = subnets.replace(conf.getIPAddress(), subnetCurr, subnet);
}
- if(!result) {
- String msg = "Cluster conflict: Conflict while adding the subnet " + conf.getIPnum();
+ if(!putNewSubnet) {
+ String msg = "Cluster conflict: Conflict while adding the subnet " + conf.getIPAddress();
return new Status(StatusCode.CONFLICT, msg);
}
- } else { // This is the deletion of the whole subnet
- subnets.remove(conf.getIPnum());
+
+ // Subnet removal case
+ } else {
+ subnets.remove(conf.getIPAddress());
}
return new Status(StatusCode.SUCCESS);
}
}
for (InetAddress i : IPs) {
Subnet existingSubnet = subnets.get(i);
- if ((existingSubnet != null)
- && !existingSubnet.isMutualExclusive(newSubnet)) {
- return new Status(StatusCode.CONFLICT);
+ if ((existingSubnet != null) && !existingSubnet.isMutualExclusive(newSubnet)) {
+ return new Status(StatusCode.CONFLICT, "This subnet conflicts with an existing one.");
}
}
return new Status(StatusCode.SUCCESS);
}
- private Status addRemoveSubnet(SubnetConfig conf, boolean add) {
- // Valid config check
- if (!conf.isValidConfig()) {
- String msg = "Invalid Subnet configuration";
- log.warn(msg);
- return new Status(StatusCode.BADREQUEST, msg);
+ private Status addRemoveSubnet(SubnetConfig conf, boolean isAdding) {
+ // Valid configuration check
+ Status status = conf.validate();
+ if (!status.isSuccess()) {
+ log.warn(status.getDescription());
+ return status;
}
- if (add) {
+ if (isAdding) {
// Presence check
if (subnetsConfigList.containsKey(conf.getName())) {
return new Status(StatusCode.CONFLICT,
- "Same subnet config already exists");
+ "Subnet with the specified name already exists.");
}
- // Semantyc check
- Status rc = semanticCheck(conf);
- if (!rc.isSuccess()) {
- return rc;
+ // Semantic check
+ status = semanticCheck(conf);
+ if (!status.isSuccess()) {
+ return status;
}
}
// Update Database
- Status rc = updateDatabase(conf, add);
+ status = updateDatabase(conf, isAdding);
- if (rc.isSuccess()) {
+ if (status.isSuccess()) {
// Update Configuration
- rc = updateConfig(conf, add);
- if(!rc.isSuccess()) {
- updateDatabase(conf, (!add));
+ status = updateConfig(conf, isAdding);
+ if(!status.isSuccess()) {
+ updateDatabase(conf, (!isAdding));
}
}
- return rc;
+ return status;
}
/**
}
@Override
- public Status addPortsToSubnet(String name, String switchPorts) {
+ public Status modifySubnet(SubnetConfig conf) {
+ // Sanity check
+ if (conf == null) {
+ return new Status(StatusCode.BADREQUEST, "Invalid Subnet configuration: null");
+ }
+
+ // Valid configuration check
+ Status status = conf.validate();
+ if (!status.isSuccess()) {
+ log.warn(status.getDescription());
+ return status;
+ }
+
+ // If a subnet configuration with this name does not exist, consider this is a creation
+ SubnetConfig target = subnetsConfigList.get(conf.getName());
+ if (target == null) {
+ return this.addSubnet(conf);
+ }
+
+ // No change
+ if (target.equals(conf)) {
+ return new Status(StatusCode.SUCCESS);
+ }
+
+ // Check not allowed modifications
+ if (!target.getSubnet().equals(conf.getSubnet())) {
+ return new Status(StatusCode.BADREQUEST, "IP address change is not allowed");
+ }
+
+ // Derive the set of node connectors that are being removed
+ Set<NodeConnector> toRemove = target.getNodeConnectors();
+ toRemove.removeAll(conf.getNodeConnectors());
+ List<String> nodeConnectorStrings = null;
+ if (!toRemove.isEmpty()) {
+ nodeConnectorStrings = new ArrayList<String>();
+ for (NodeConnector nc : toRemove) {
+ nodeConnectorStrings.add(nc.toString());
+ }
+ status = this.removePortsFromSubnet(conf.getName(), nodeConnectorStrings);
+ if (!status.isSuccess()) {
+ return status;
+ }
+ }
+
+ // Derive the set of node connectors that are being added
+ Set<NodeConnector> toAdd = conf.getNodeConnectors();
+ toAdd.removeAll(target.getNodeConnectors());
+ if (!toAdd.isEmpty()) {
+ List<String> nodeConnectorStringRemoved = nodeConnectorStrings;
+ nodeConnectorStrings = new ArrayList<String>();
+ for (NodeConnector nc : toAdd) {
+ nodeConnectorStrings.add(nc.toString());
+ }
+ status = this.addPortsToSubnet(conf.getName(), nodeConnectorStrings);
+ if (!status.isSuccess()) {
+ // If any port was removed, add it back as a best recovery effort
+ if (!toRemove.isEmpty()) {
+ this.addPortsToSubnet(conf.getName(), nodeConnectorStringRemoved);
+ }
+ return status;
+ }
+ }
+
+ // Update Configuration
+ subnetsConfigList.put(conf.getName(), conf);
+
+ return new Status(StatusCode.SUCCESS);
+ }
+
+ @Override
+ public Status addPortsToSubnet(String name, List<String> switchPorts) {
+ if (name == null) {
+ return new Status(StatusCode.BADREQUEST, "Null subnet name");
+ }
SubnetConfig confCurr = subnetsConfigList.get(name);
if (confCurr == null) {
return new Status(StatusCode.NOTFOUND, "Subnet does not exist");
}
- if (!confCurr.isValidSwitchPort(switchPorts)) {
- return new Status(StatusCode.BADREQUEST, "Invalid switchports");
+
+ if (switchPorts == null || switchPorts.isEmpty()) {
+ return new Status(StatusCode.BADREQUEST, "Null or empty port set");
}
- Subnet subCurr = subnets.get(confCurr.getIPnum());
+ Subnet subCurr = subnets.get(confCurr.getIPAddress());
if (subCurr == null) {
- log.debug("Cluster conflict: Subnet entry {} is not present in the subnets cache.", confCurr.getIPnum());
+ log.debug("Cluster conflict: Subnet entry {} is not present in the subnets cache.", confCurr.getIPAddress());
return new Status(StatusCode.NOTFOUND, "Subnet does not exist");
}
// Update Database
Subnet sub = subCurr.clone();
- Set<NodeConnector> sp = confCurr.getNodeConnectors(switchPorts);
+ Set<NodeConnector> sp = NodeConnector.fromString(switchPorts);
sub.addNodeConnectors(sp);
- boolean subnetsReplace = subnets.replace(confCurr.getIPnum(), subCurr, sub);
- if (!subnetsReplace) {
+ boolean subnetsReplaced = subnets.replace(confCurr.getIPAddress(), subCurr, sub);
+ if (!subnetsReplaced) {
String msg = "Cluster conflict: Conflict while adding ports to the subnet " + name;
return new Status(StatusCode.CONFLICT, msg);
}
// Update Configuration
SubnetConfig conf = confCurr.clone();
conf.addNodeConnectors(switchPorts);
- boolean result = subnetsConfigList.replace(name, confCurr, conf);
- if (!result) {
+ boolean configReplaced = subnetsConfigList.replace(name, confCurr, conf);
+ if (!configReplaced) {
// TODO: recovery using Transactionality
String msg = "Cluster conflict: Conflict while adding ports to the subnet " + name;
return new Status(StatusCode.CONFLICT, msg);
}
@Override
- public Status removePortsFromSubnet(String name, String switchPorts) {
+ public Status removePortsFromSubnet(String name, List<String> switchPorts) {
+ if (name == null) {
+ return new Status(StatusCode.BADREQUEST, "Null subnet name");
+ }
SubnetConfig confCurr = subnetsConfigList.get(name);
if (confCurr == null) {
return new Status(StatusCode.NOTFOUND, "Subnet does not exist");
}
- Subnet subCurr = subnets.get(confCurr.getIPnum());
+ if (switchPorts == null || switchPorts.isEmpty()) {
+ return new Status(StatusCode.BADREQUEST, "Null or empty port set");
+ }
+
+ Subnet subCurr = subnets.get(confCurr.getIPAddress());
if (subCurr == null) {
- log.debug("Cluster conflict: Subnet entry {} is not present in the subnets cache.", confCurr.getIPnum());
+ log.debug("Cluster conflict: Subnet entry {} is not present in the subnets cache.", confCurr.getIPAddress());
return new Status(StatusCode.NOTFOUND, "Subnet does not exist");
}
+ // Validation check
+ Status status = SubnetConfig.validatePorts(switchPorts);
+ if (!status.isSuccess()) {
+ return status;
+ }
// Update Database
Subnet sub = subCurr.clone();
- Set<NodeConnector> sp = confCurr.getNodeConnectors(switchPorts);
+ Set<NodeConnector> sp = NodeConnector.fromString(switchPorts);
sub.deleteNodeConnectors(sp);
- boolean subnetsReplace = subnets.replace(confCurr.getIPnum(), subCurr, sub);
+ boolean subnetsReplace = subnets.replace(confCurr.getIPAddress(), subCurr, sub);
if (!subnetsReplace) {
String msg = "Cluster conflict: Conflict while removing ports from the subnet " + name;
return new Status(StatusCode.CONFLICT, msg);
@Override
public Subnet getSubnetByNetworkAddress(InetAddress networkAddress) {
+ // if there are no subnets, return the default subnet
+ if (subnets.size() == 0) {
+ return DEFAULT_SUBNET;
+ }
+
Subnet sub;
Set<InetAddress> indices = subnets.keySet();
for (InetAddress i : indices) {
}
for (SwitchConfig conf : confList.values()) {
- updateSwitchConfig(conf);
+ updateNodeConfig(conf);
}
}
+ @SuppressWarnings("deprecation")
@Override
public void updateSwitchConfig(SwitchConfig cfgObject) {
// update default container only
}
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.BADREQUEST, "Invalid Forwarding Mode Value.");
+ return new Status(StatusCode.BADREQUEST, "Invalid Forwarding Mode Value");
}
} else {
return new Status(StatusCode.NOTACCEPTABLE,
"Forwarding Mode modification is allowed only in default container");
}
}
+
+ Description description = (Description) switchConfig.getProperty(Description.propertyName);
+ String nodeId = switchConfig.getNodeId();
+ Node node = Node.fromString(nodeId);
+ NodeDescription nodeDesc = (this.statisticsManager == null) ? null : this.statisticsManager
+ .getNodeDescription(node);
+ String advertisedDesc = (nodeDesc == null) ? "" : nodeDesc.getDescription();
+ if (description != null && description.getValue() != null) {
+ if (description.getValue().isEmpty() || description.getValue().equals(advertisedDesc)) {
+ updateProperties.remove(Description.propertyName);
+ switchConfig = new SwitchConfig(nodeId, updateProperties);
+ } else {
+ // check if description is configured or was published by any other node
+ for (Map.Entry<Node, Map<String, Property>> entry : nodeProps.entrySet()) {
+ Node n = entry.getKey();
+ Description desc = (Description) getNodeProp(n, Description.propertyName);
+ NodeDescription nDesc = (this.statisticsManager == null) ? null : this.statisticsManager
+ .getNodeDescription(n);
+ String advDesc = (nDesc == null) ? "" : nDesc.getDescription();
+ if ((description.equals(desc) || description.getValue().equals(advDesc)) && !node.equals(n)) {
+ return new Status(StatusCode.CONFLICT, "Node name already in use");
+ }
+ }
+ }
+ }
+
boolean modeChange = false;
SwitchConfig sc = nodeConfigList.get(nodeId);
Map<String, Property> prevNodeProperties = new HashMap<String, Property>();
}
}
}
- Node node = Node.fromString(nodeId);
Map<String, Property> propMapCurr = nodeProps.get(node);
if (propMapCurr == null) {
return new Status(StatusCode.SUCCESS);
}
Map<String, Property> propMap = new HashMap<String, Property>(propMapCurr);
- 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;
- }
+ for (Map.Entry<String, Property> entry : prevNodeProperties.entrySet()) {
+ String prop = entry.getKey();
+ if (!updateProperties.containsKey(prop)) {
+ if (prop.equals(Description.propertyName)) {
+ if (!advertisedDesc.isEmpty()) {
+ Property desc = new Description(advertisedDesc);
+ propMap.put(Description.propertyName, desc);
}
- propMap.remove(prop);
+ continue;
+ } else if (prop.equals(ForwardingMode.name)) {
+ Property defaultMode = new ForwardingMode(ForwardingMode.REACTIVE_FORWARDING);
+ propMap.put(ForwardingMode.name, defaultMode);
+ 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.");
+ return new Status(StatusCode.CONFLICT, "Cluster conflict: Unable to update node configuration");
}
if (modeChange) {
notifyModeChange(node, (mode == null) ? false : mode.isProactive());
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()) {
+ for (Map.Entry<String, Property> entry : nodeProperties.entrySet()) {
+ String prop = entry.getKey();
if (prop.equals(Description.propertyName)) {
Map<Node, Map<String, Property>> nodeProp = this.inventoryService.getNodeProps();
if (nodeProp.get(node) != null) {
@Override
public Status saveSwitchConfig() {
- // Publish the save config event to the cluster nodes
- configSaveEvent.put(new Date().getTime(), SAVE);
return saveSwitchConfigInternal();
}
return ncList;
}
- @Override
- public void entryCreated(Long key, String cacheName, boolean local) {
- }
-
- @Override
- public void entryUpdated(Long key, String new_value, String cacheName,
- boolean originLocal) {
- saveSwitchConfigInternal();
- }
-
- @Override
- public void entryDeleted(Long key, String cacheName, boolean originLocal) {
- }
-
private void addNode(Node node, Set<Property> props) {
log.trace("{} added, props: {}", node, props);
if (nodeProps == null) {
}
}
- // copy node properties from config
boolean proactiveForwarding = false;
+ // copy node properties from config
if (nodeConfigList != null) {
String nodeId = node.toString();
SwitchConfig conf = nodeConfigList.get(nodeId);
}
}
+ if (!propMap.containsKey(ForwardingMode.name)) {
+ Property defaultMode = new ForwardingMode(ForwardingMode.REACTIVE_FORWARDING);
+ propMap.put(ForwardingMode.name, defaultMode);
+ }
boolean result = false;
if (propMapCurr == null) {
if (nodeProps.putIfAbsent(node, propMap) == null) {
return;
}
nodeProps.remove(node);
+ nodeConnectorNames.remove(node);
+ Set<NodeConnector> removeNodeConnectorSet = new HashSet<NodeConnector>();
+ for (Map.Entry<NodeConnector, Map<String, Property>> entry : nodeConnectorProps.entrySet()) {
+ NodeConnector nodeConnector = entry.getKey();
+ if (nodeConnector.getNode().equals(node)) {
+ removeNodeConnectorSet.add(nodeConnector);
+ }
+ }
+ for (NodeConnector nc : removeNodeConnectorSet) {
+ nodeConnectorProps.remove(nc);
+ }
// check if span ports need to be cleaned up
removeSpanPorts(node);
public void updateNodeConnector(NodeConnector nodeConnector,
UpdateType type, Set<Property> props) {
Map<String, Property> propMap = new HashMap<String, Property>();
+ boolean update = true;
log.debug("updateNodeConnector: {} type {} props {} for container {}",
new Object[] { nodeConnector, type, props, containerName });
switch (type) {
case ADDED:
- case CHANGED:
if (props != null) {
for (Property prop : props) {
addNodeConnectorProp(nodeConnector, prop);
addSpanPort(nodeConnector);
break;
+ case CHANGED:
+ if (!nodeConnectorProps.containsKey(nodeConnector) || (props == null)) {
+ update = false;
+ } else {
+ for (Property prop : props) {
+ addNodeConnectorProp(nodeConnector, prop);
+ propMap.put(prop.getName(), prop);
+ }
+ }
+ break;
case REMOVED:
+ if (!nodeConnectorProps.containsKey(nodeConnector)) {
+ update = false;
+ }
removeNodeConnectorAllProps(nodeConnector);
// clean up span config
removeSpanPort(nodeConnector);
break;
default:
+ update = false;
break;
}
- notifyNodeConnector(nodeConnector, type, propMap);
+ if (update) {
+ notifyNodeConnector(nodeConnector, type, propMap);
+ }
}
@Override
public Set<Node> getNodes() {
- return (nodeProps != null) ? new HashSet<Node>(nodeProps.keySet())
- : null;
+ return (nodeProps != null) ? new HashSet<Node>(nodeProps.keySet()) : new HashSet<Node>();
+ }
+
+ @Override
+ public Map<String, Property> getControllerProperties() {
+ return new HashMap<String, Property>(this.controllerProps);
+ }
+
+ @Override
+ public Property getControllerProperty(String propertyName) {
+ if (propertyName != null) {
+ HashMap<String, Property> propertyMap = new HashMap<String, Property>(this.controllerProps);
+ return propertyMap.get(propertyName);
+ }
+ return null;
+ }
+
+ @Override
+ public Status setControllerProperty(Property property) {
+ if (property != null) {
+ this.controllerProps.put(property.getName(), property);
+ return new Status(StatusCode.SUCCESS);
+ }
+ return new Status(StatusCode.BADREQUEST, "Invalid property provided when setting property");
+ }
+
+ @Override
+ public Status removeControllerProperty(String propertyName) {
+ if (propertyName != null) {
+ if (this.controllerProps.containsKey(propertyName)) {
+ this.controllerProps.remove(propertyName);
+ if (!this.controllerProps.containsKey(propertyName)) {
+ return new Status(StatusCode.SUCCESS);
+ }
+ }
+ String msg = "Unable to remove property " + propertyName + " from Controller";
+ return new Status(StatusCode.BADREQUEST, msg);
+ }
+ String msg = "Invalid property provided when removing property from Controller";
+ return new Status(StatusCode.BADREQUEST, msg);
}
/*
}
Set<NodeConnector> nodeConnectorSet = new HashSet<NodeConnector>();
- for (NodeConnector nodeConnector : nodeConnectorProps.keySet()) {
+ for (Map.Entry<NodeConnector, Map<String, Property>> entry : nodeConnectorProps.entrySet()) {
+ NodeConnector nodeConnector = entry.getKey();
if (!nodeConnector.getNode().equals(node)) {
continue;
}
}
Set<NodeConnector> nodeConnectorSet = new HashSet<NodeConnector>();
- for (NodeConnector nodeConnector : nodeConnectorProps.keySet()) {
+ for (Map.Entry<NodeConnector, Map<String, Property>> entry : nodeConnectorProps.entrySet()) {
+ NodeConnector nodeConnector = entry.getKey();
if (!nodeConnector.getNode().equals(node)) {
continue;
}
}
Set<NodeConnector> nodeConnectorSet = new HashSet<NodeConnector>();
- for (NodeConnector nodeConnector : nodeConnectorProps.keySet()) {
+ for (Map.Entry<NodeConnector, Map<String, Property>> entry : nodeConnectorProps.entrySet()) {
+ NodeConnector nodeConnector = entry.getKey();
if (!nodeConnector.getNode().equals(node)
|| isSpecial(nodeConnector)) {
continue;
return (macProperty == null) ? null : macProperty.getMacAddress();
}
- @Override
- public boolean isHostRefreshEnabled() {
- return hostRefresh;
- }
-
- @Override
- public int getHostRetryCount() {
- return hostRetryCount;
- }
-
@Override
public NodeConnector getNodeConnector(Node node, String nodeConnectorName) {
if (nodeConnectorNames == null) {
Map<String, NodeConnector> mapCurr = nodeConnectorNames.get(node);
Map<String, NodeConnector> map = new HashMap<String, NodeConnector>();
if (mapCurr != null) {
- for (String s : mapCurr.keySet()) {
+ for (Map.Entry<String, NodeConnector> entry : mapCurr.entrySet()) {
+ String s = entry.getKey();
try {
- map.put(s, new NodeConnector(mapCurr.get(s)));
+ map.put(s, new NodeConnector(entry.getValue()));
} catch (ConstructionException e) {
- e.printStackTrace();
+ log.error("An error occured",e);
}
}
}
Map<String, NodeConnector> mapCurr = nodeConnectorNames.get(node);
if (mapCurr != null) {
Map<String, NodeConnector> map = new HashMap<String, NodeConnector>();
- for (String s : mapCurr.keySet()) {
+ for (Map.Entry<String, NodeConnector> entry : mapCurr.entrySet()) {
+ String s = entry.getKey();
try {
- map.put(s, new NodeConnector(mapCurr.get(s)));
+ map.put(s, new NodeConnector(entry.getValue()));
} catch (ConstructionException e) {
- e.printStackTrace();
+ log.error("An error occured",e);
}
}
map.remove(name.getValue());
Map<String, NodeConnector> mapCurr = nodeConnectorNames.get(node);
if (mapCurr != null) {
Map<String, NodeConnector> map = new HashMap<String, NodeConnector>();
- for (String s : mapCurr.keySet()) {
+ for (Map.Entry<String, NodeConnector> entry : mapCurr.entrySet()) {
+ String s = entry.getKey();
try {
- map.put(s, new NodeConnector(mapCurr.get(s)));
+ map.put(s, new NodeConnector(entry.getValue()));
} catch (ConstructionException e) {
- e.printStackTrace();
+ log.error("An error occured",e);
}
}
map.remove(name.getValue());
- if (!nodeConnectorNames.replace(node, mapCurr, map)) {
- log.warn("Cluster conflict: Unable remove Name property of nodeconnector {}, skip.",
- nodeConnector.getID());
+ if (map.isEmpty()) {
+ nodeConnectorNames.remove(node);
+ } else {
+ if (!nodeConnectorNames.replace(node, mapCurr, map)) {
+ log.warn("Cluster conflict: Unable remove Name property of nodeconnector {}, skip.",
+ nodeConnector.getID());
+ }
}
}
clearInventories();
}
+ public void setStatisticsManager(IStatisticsManager statisticsManager) {
+ log.trace("Got statistics manager set request {}", statisticsManager);
+ this.statisticsManager = statisticsManager;
+ }
+
+ public void unsetStatisticsManager(IStatisticsManager statisticsManager) {
+ log.trace("Got statistics manager UNset request");
+ this.statisticsManager = null;
+ }
+
public void setSwitchManagerAware(ISwitchManagerAware service) {
log.trace("Got inventory service set request {}", service);
if (this.switchManagerAware != null) {
service.notifyNode(node, type, propMap);
}
- for (NodeConnector nodeConnector : nodeConnectorProps.keySet()) {
+ for (Map.Entry<NodeConnector, Map<String, Property>> entry : nodeConnectorProps.entrySet()) {
+ NodeConnector nodeConnector = entry.getKey();
propMap = nodeConnectorProps.get(nodeConnector);
service.notifyNodeConnector(nodeConnector, type, propMap);
}
&& (state != null) && (state.getValue() == State.EDGE_UP));
}
+ @Override
+ public boolean doesNodeConnectorExist(NodeConnector nc) {
+ return (nc != null && nodeConnectorProps != null
+ && nodeConnectorProps.containsKey(nc));
+ }
+
@Override
public String getHelp() {
StringBuffer help = new StringBuffer();
help.append("---Switch Manager---\n");
- help.append("\t pns - Print connected nodes\n");
- help.append("\t pncs <node id> - Print node connectors for a given node\n");
help.append("\t pencs <node id> - Print enabled node connectors for a given node\n");
help.append("\t pdm <node id> - Print switch ports in device map\n");
- help.append("\t snt <node id> <tier> - Set node tier number\n");
- help.append("\t hostRefresh <on/off/?> - Enable/Disable/Query host refresh\n");
- help.append("\t hostRetry <count> - Set host retry count\n");
return help.toString();
}
- public void _pns(CommandInterpreter ci) {
- ci.println(" Node Type MAC Name Tier");
- if (nodeProps == null) {
- return;
- }
- Set<Node> nodeSet = nodeProps.keySet();
- if (nodeSet == null) {
- return;
- }
- List<String> nodeArray = new ArrayList<String>();
- for (Node node : nodeSet) {
- nodeArray.add(node.toString());
- }
- Collections.sort(nodeArray);
- for (String str: nodeArray) {
- Node node = Node.fromString(str);
- Description desc = ((Description) getNodeProp(node,
- Description.propertyName));
- Tier tier = ((Tier) getNodeProp(node, Tier.TierPropName));
- String nodeName = (desc == null) ? "" : desc.getValue();
- MacAddress mac = (MacAddress) getNodeProp(node,
- MacAddress.name);
- String macAddr = (mac == null) ? "" : HexEncode
- .bytesToHexStringFormat(mac.getMacAddress());
- int tierNum = (tier == null) ? 0 : tier.getValue();
- ci.println(node + " " + node.getType() + " " + macAddr
- + " " + nodeName + " " + tierNum);
- }
- ci.println("Total number of Nodes: " + nodeSet.size());
- }
-
public void _pencs(CommandInterpreter ci) {
String st = ci.nextArgument();
if (st == null) {
ci.println("Total number of NodeConnectors: " + nodeConnectorSet.size());
}
- public void _pncs(CommandInterpreter ci) {
- String st = ci.nextArgument();
- if (st == null) {
- ci.println("Please enter node id");
- return;
- }
-
- Node node = Node.fromString(st);
- if (node == null) {
- ci.println("Please enter node id");
- return;
- }
-
- ci.println(" NodeConnector BandWidth(Gbps) Admin State");
- Set<NodeConnector> nodeConnectorSet = getNodeConnectors(node);
- if (nodeConnectorSet == null) {
- return;
- }
- for (NodeConnector nodeConnector : nodeConnectorSet) {
- if (nodeConnector == null) {
- continue;
- }
- Map<String, Property> propMap = getNodeConnectorProps(nodeConnector);
- Bandwidth bw = (Bandwidth) propMap.get(Bandwidth.BandwidthPropName);
- Config config = (Config) propMap.get(Config.ConfigPropName);
- State state = (State) propMap.get(State.StatePropName);
- String out = nodeConnector + " ";
- out += (bw != null) ? bw.getValue() / Math.pow(10, 9) : " ";
- out += " ";
- out += (config != null) ? config.getValue() : " ";
- out += " ";
- out += (state != null) ? state.getValue() : " ";
- ci.println(out);
- }
- ci.println("Total number of NodeConnectors: " + nodeConnectorSet.size());
- }
-
public void _pdm(CommandInterpreter ci) {
String st = ci.nextArgument();
if (st == null) {
Switch sw = getSwitchByNode(node);
ci.println(" NodeConnector Name");
- if (sw == null) {
- return;
- }
+
Set<NodeConnector> nodeConnectorSet = sw.getNodeConnectors();
String nodeConnectorName;
if (nodeConnectorSet != null && nodeConnectorSet.size() > 0) {
}
}
- public void _snt(CommandInterpreter ci) {
- String st = ci.nextArgument();
- if (st == null) {
- ci.println("Please enter node id");
- return;
- }
-
- Node node = Node.fromString(st);
- if (node == null) {
- ci.println("Please enter node id");
- return;
- }
-
- st = ci.nextArgument();
- if (st == null) {
- ci.println("Please enter tier number");
- return;
- }
- Integer tid = Integer.decode(st);
- Tier tier = new Tier(tid);
- setNodeProp(node, tier);
- }
-
- public void _hostRefresh(CommandInterpreter ci) {
- String mode = ci.nextArgument();
- if (mode == null) {
- ci.println("expecting on/off/?");
- return;
- }
- if (mode.toLowerCase().equals("on")) {
- hostRefresh = true;
- } else if (mode.toLowerCase().equals("off")) {
- hostRefresh = false;
- } else if (mode.equals("?")) {
- if (hostRefresh) {
- ci.println("host refresh is ON");
- } else {
- ci.println("host refresh is OFF");
- }
- } else {
- ci.println("expecting on/off/?");
- }
- return;
- }
-
- public void _hostRetry(CommandInterpreter ci) {
- String retry = ci.nextArgument();
- if (retry == null) {
- ci.println("Please enter a valid number. Current retry count is "
- + hostRetryCount);
- return;
- }
- try {
- hostRetryCount = Integer.parseInt(retry);
- } catch (Exception e) {
- ci.println("Please enter a valid number");
- }
- return;
- }
-
@Override
public byte[] getNodeMAC(Node node) {
MacAddress mac = (MacAddress) this.getNodeProp(node,
nodeProps.put(node, propMap);
}
- private void removeNodeProps(Node node) {
- if (getUpNodeConnectors(node).size() == 0) {
- nodeProps.remove(node);
- }
- }
-
@Override
public Status saveConfiguration() {
return saveSwitchConfig();
}
/**
- * Creates a Name/Tier/Bandwidth Property object based on given property
- * name and value. Other property types are not supported yet.
+ * Creates a Name/Tier/Bandwidth/MacAddress(controller property) Property
+ * object based on given property name and value. Other property types are
+ * not supported yet.
*
* @param propName
* Name of the Property
} else if (propName.equalsIgnoreCase(ForwardingMode.name)) {
int mode = Integer.parseInt(propValue);
return new ForwardingMode(mode);
- } else {
+ } else if (propName.equalsIgnoreCase(MacAddress.name)){
+ return new MacAddress(propValue);
+ }
+ else {
log.debug("Not able to create {} property", propName);
}
} catch (Exception e) {
return null;
}
+
+ @SuppressWarnings("deprecation")
@Override
public String getNodeDescription(Node node) {
// Check first if user configured a name