X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fswitchmanager%2Fimplementation%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fswitchmanager%2Finternal%2FSwitchManager.java;h=4d2aea203601dafe6e19fcacc208ae4760819b0f;hp=f50f303a3f6b07dd325bc4d488d86092499b61a8;hb=55c40fd972a68ae81a1c6b8a3e4977e2aa838464;hpb=c3e3c2ceaecea472a899d65f40826a65a9079003 diff --git a/opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManager.java b/opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManager.java index f50f303a3f..4d2aea2036 100644 --- a/opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManager.java +++ b/opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManager.java @@ -16,7 +16,6 @@ import java.net.NetworkInterface; 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; @@ -34,7 +33,6 @@ import org.eclipse.osgi.framework.console.CommandInterpreter; 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; @@ -54,6 +52,7 @@ import org.opendaylight.controller.sal.core.Tier; 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; @@ -61,6 +60,7 @@ 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.statisticsmanager.IStatisticsManager; import org.opendaylight.controller.switchmanager.IInventoryListener; import org.opendaylight.controller.switchmanager.ISpanAware; import org.opendaylight.controller.switchmanager.ISwitchManager; @@ -83,39 +83,47 @@ import org.slf4j.LoggerFactory; * 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, 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 spanNodeConnectors = new CopyOnWriteArrayList(); - // set of Subnets keyed by the InetAddress + // Collection of Subnets keyed by the InetAddress private ConcurrentMap subnets; private ConcurrentMap subnetsConfigList; private ConcurrentMap spanConfigList; // manually configured parameters for the node such as name, tier, mode private ConcurrentMap nodeConfigList; - private ConcurrentMap configSaveEvent; private ConcurrentMap> nodeProps; private ConcurrentMap> nodeConnectorProps; private ConcurrentMap> nodeConnectorNames; private ConcurrentMap controllerProps; private IInventoryService inventoryService; + private IStatisticsManager statisticsManager; private final Set switchManagerAware = Collections .synchronizedSet(new HashSet()); private final Set inventoryListeners = Collections .synchronizedSet(new HashSet()); private final Set spanAware = Collections.synchronizedSet(new HashSet()); - 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()); + DEFAULT_SUBNET = new Subnet(DEFAULT_SUBNETCONFIG); + } + public void notifySubnetChange(Subnet sub, boolean add) { synchronized (switchManagerAware) { for (Object subAware : switchManagerAware) { @@ -196,7 +204,6 @@ CommandProvider { public void shutDown() { } - @SuppressWarnings("deprecation") private void allocateCaches() { if (this.clusterContainerService == null) { this.nonClusterObjectCreate(); @@ -207,27 +214,24 @@ CommandProvider { 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) { @@ -235,7 +239,7 @@ CommandProvider { } } - @SuppressWarnings({ "unchecked", "deprecation" }) + @SuppressWarnings({ "unchecked" }) private void retrieveCaches() { if (this.clusterContainerService == null) { log.info("un-initialized clusterContainerService, can't create cache"); @@ -266,12 +270,6 @@ CommandProvider { log.error("\nFailed to get cache for subnets"); } - configSaveEvent = (ConcurrentMap) clusterContainerService - .getCache("switchmanager.configSaveEvent"); - if (configSaveEvent == null) { - log.error("\nFailed to get cache for configSaveEvent"); - } - nodeProps = (ConcurrentMap>) clusterContainerService .getCache("switchmanager.nodeProps"); if (nodeProps == null) { @@ -302,7 +300,6 @@ CommandProvider { spanConfigList = new ConcurrentHashMap(); nodeConfigList = new ConcurrentHashMap(); subnets = new ConcurrentHashMap(); - configSaveEvent = new ConcurrentHashMap(); nodeProps = new ConcurrentHashMap>(); nodeConnectorProps = new ConcurrentHashMap>(); nodeConnectorNames = new ConcurrentHashMap>(); @@ -311,12 +308,22 @@ CommandProvider { @Override public List getSubnetsConfigList() { - return new ArrayList(subnetsConfigList.values()); + // if there are no subnets, return the default subnet + if(subnetsConfigList.size() == 0){ + return Collections.singletonList(DEFAULT_SUBNETCONFIG); + }else{ + return new ArrayList(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 getSpanConfigList(Node node) { @@ -388,7 +395,7 @@ CommandProvider { 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); @@ -398,23 +405,24 @@ CommandProvider { // In case of API3 call we may receive the ports along with the // subnet creation if (!conf.isGlobal()) { - Set 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); } @@ -427,47 +435,46 @@ CommandProvider { } 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; } /** @@ -493,27 +500,101 @@ CommandProvider { } @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 toRemove = target.getNodeConnectors(); + toRemove.removeAll(conf.getNodeConnectors()); + List nodeConnectorStrings = null; + if (!toRemove.isEmpty()) { + nodeConnectorStrings = new ArrayList(); + 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 toAdd = conf.getNodeConnectors(); + toAdd.removeAll(target.getNodeConnectors()); + if (!toAdd.isEmpty()) { + List nodeConnectorStringRemoved = nodeConnectorStrings; + nodeConnectorStrings = new ArrayList(); + 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 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 sp = confCurr.getNodeConnectors(switchPorts); + Set 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); } @@ -521,8 +602,8 @@ CommandProvider { // 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); @@ -532,23 +613,35 @@ CommandProvider { } @Override - public Status removePortsFromSubnet(String name, String switchPorts) { + public Status removePortsFromSubnet(String name, List 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 sp = confCurr.getNodeConnectors(switchPorts); + Set 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); @@ -576,6 +669,11 @@ CommandProvider { @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 indices = subnets.keySet(); for (InetAddress i : indices) { @@ -640,6 +738,7 @@ CommandProvider { } } + @SuppressWarnings("deprecation") @Override public void updateSwitchConfig(SwitchConfig cfgObject) { // update default container only @@ -696,18 +795,43 @@ CommandProvider { } Map 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> 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 prevNodeProperties = new HashMap(); @@ -741,30 +865,32 @@ CommandProvider { } } } - Node node = Node.fromString(nodeId); Map propMapCurr = nodeProps.get(node); if (propMapCurr == null) { return new Status(StatusCode.SUCCESS); } Map propMap = new HashMap(propMapCurr); - if (!prevNodeProperties.isEmpty()) { - for (String prop : prevNodeProperties.keySet()) { - if (!updateProperties.containsKey(prop)) { - if (prop.equals(Description.propertyName)) { - Map> nodeProp = this.inventoryService.getNodeProps(); - if (nodeProp.get(node) != null) { - propMap.put(Description.propertyName, nodeProp.get(node).get(Description.propertyName)); - continue; - } + for (Map.Entry 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()); @@ -782,7 +908,8 @@ CommandProvider { Map propMapCurr = nodeProps.get(node); if ((propMapCurr != null) && (nodeProperties != null) && (!nodeProperties.isEmpty())) { Map propMap = new HashMap(propMapCurr); - for (String prop : nodeProperties.keySet()) { + for (Map.Entry entry : nodeProperties.entrySet()) { + String prop = entry.getKey(); if (prop.equals(Description.propertyName)) { Map> nodeProp = this.inventoryService.getNodeProps(); if (nodeProp.get(node) != null) { @@ -804,8 +931,6 @@ CommandProvider { @Override public Status saveSwitchConfig() { - // Publish the save config event to the cluster nodes - configSaveEvent.put(new Date().getTime(), SAVE); return saveSwitchConfigInternal(); } @@ -880,20 +1005,6 @@ CommandProvider { 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 props) { log.trace("{} added, props: {}", node, props); if (nodeProps == null) { @@ -911,8 +1022,8 @@ CommandProvider { } } - // 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); @@ -926,6 +1037,10 @@ CommandProvider { } } + 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) { @@ -958,6 +1073,17 @@ CommandProvider { return; } nodeProps.remove(node); + nodeConnectorNames.remove(node); + Set removeNodeConnectorSet = new HashSet(); + for (Map.Entry> 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); @@ -1031,6 +1157,7 @@ CommandProvider { public void updateNodeConnector(NodeConnector nodeConnector, UpdateType type, Set props) { Map propMap = new HashMap(); + boolean update = true; log.debug("updateNodeConnector: {} type {} props {} for container {}", new Object[] { nodeConnector, type, props, containerName }); @@ -1041,7 +1168,6 @@ CommandProvider { switch (type) { case ADDED: - case CHANGED: if (props != null) { for (Property prop : props) { addNodeConnectorProp(nodeConnector, prop); @@ -1053,23 +1179,77 @@ CommandProvider { 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 getNodes() { - return (nodeProps != null) ? new HashSet(nodeProps.keySet()) - : null; + return (nodeProps != null) ? new HashSet(nodeProps.keySet()) : new HashSet(); + } + + @Override + public Map getControllerProperties() { + return new HashMap(this.controllerProps); + } + + @Override + public Property getControllerProperty(String propertyName) { + if (propertyName != null) { + HashMap propertyMap = new HashMap(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); } /* @@ -1164,7 +1344,8 @@ CommandProvider { } Set nodeConnectorSet = new HashSet(); - for (NodeConnector nodeConnector : nodeConnectorProps.keySet()) { + for (Map.Entry> entry : nodeConnectorProps.entrySet()) { + NodeConnector nodeConnector = entry.getKey(); if (!nodeConnector.getNode().equals(node)) { continue; } @@ -1183,7 +1364,8 @@ CommandProvider { } Set nodeConnectorSet = new HashSet(); - for (NodeConnector nodeConnector : nodeConnectorProps.keySet()) { + for (Map.Entry> entry : nodeConnectorProps.entrySet()) { + NodeConnector nodeConnector = entry.getKey(); if (!nodeConnector.getNode().equals(node)) { continue; } @@ -1200,7 +1382,8 @@ CommandProvider { } Set nodeConnectorSet = new HashSet(); - for (NodeConnector nodeConnector : nodeConnectorProps.keySet()) { + for (Map.Entry> entry : nodeConnectorProps.entrySet()) { + NodeConnector nodeConnector = entry.getKey(); if (!nodeConnector.getNode().equals(node) || isSpecial(nodeConnector)) { continue; @@ -1266,16 +1449,6 @@ CommandProvider { 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) { @@ -1339,11 +1512,12 @@ CommandProvider { Map mapCurr = nodeConnectorNames.get(node); Map map = new HashMap(); if (mapCurr != null) { - for (String s : mapCurr.keySet()) { + for (Map.Entry 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); } } } @@ -1400,11 +1574,12 @@ CommandProvider { Map mapCurr = nodeConnectorNames.get(node); if (mapCurr != null) { Map map = new HashMap(); - for (String s : mapCurr.keySet()) { + for (Map.Entry 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()); @@ -1436,17 +1611,22 @@ CommandProvider { Map mapCurr = nodeConnectorNames.get(node); if (mapCurr != null) { Map map = new HashMap(); - for (String s : mapCurr.keySet()) { + for (Map.Entry 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()); + } } } @@ -1530,6 +1710,16 @@ CommandProvider { 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) { @@ -1671,7 +1861,8 @@ CommandProvider { service.notifyNode(node, type, propMap); } - for (NodeConnector nodeConnector : nodeConnectorProps.keySet()) { + for (Map.Entry> entry : nodeConnectorProps.entrySet()) { + NodeConnector nodeConnector = entry.getKey(); propMap = nodeConnectorProps.get(nodeConnector); service.notifyNodeConnector(nodeConnector, type, propMap); } @@ -1706,51 +1897,21 @@ CommandProvider { && (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 - Print node connectors for a given node\n"); help.append("\t pencs - Print enabled node connectors for a given node\n"); help.append("\t pdm - Print switch ports in device map\n"); - help.append("\t snt - Set node tier number\n"); - help.append("\t hostRefresh - Enable/Disable/Query host refresh\n"); - help.append("\t hostRetry - 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 nodeSet = nodeProps.keySet(); - if (nodeSet == null) { - return; - } - List nodeArray = new ArrayList(); - 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) { @@ -1777,43 +1938,6 @@ CommandProvider { 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 nodeConnectorSet = getNodeConnectors(node); - if (nodeConnectorSet == null) { - return; - } - for (NodeConnector nodeConnector : nodeConnectorSet) { - if (nodeConnector == null) { - continue; - } - Map 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) { @@ -1830,9 +1954,7 @@ CommandProvider { Switch sw = getSwitchByNode(node); ci.println(" NodeConnector Name"); - if (sw == null) { - return; - } + Set nodeConnectorSet = sw.getNodeConnectors(); String nodeConnectorName; if (nodeConnectorSet != null && nodeConnectorSet.size() > 0) { @@ -1869,66 +1991,6 @@ CommandProvider { } } - 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, @@ -2022,20 +2084,15 @@ CommandProvider { 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 @@ -2066,7 +2123,10 @@ CommandProvider { } 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) { @@ -2076,6 +2136,8 @@ CommandProvider { return null; } + + @SuppressWarnings("deprecation") @Override public String getNodeDescription(Node node) { // Check first if user configured a name