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();
EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
clusterContainerService.createCache("switchmanager.subnets",
EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
- clusterContainerService.createCache(
- "switchmanager.configSaveEvent",
- EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
clusterContainerService.createCache("switchmanager.nodeProps",
EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
clusterContainerService.createCache(
}
}
- @SuppressWarnings({ "unchecked", "deprecation" })
+ @SuppressWarnings({ "unchecked" })
private void retrieveCaches() {
if (this.clusterContainerService == null) {
log.info("un-initialized clusterContainerService, can't create cache");
@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 putNewSubnet = false;
if(subnetCurr == null) {
- if(subnets.putIfAbsent(conf.getIPnum(), subnet) == null) {
+ if(subnets.putIfAbsent(conf.getIPAddress(), subnet) == null) {
putNewSubnet = true;
}
} else {
- putNewSubnet = subnets.replace(conf.getIPnum(), subnetCurr, subnet);
+ putNewSubnet = subnets.replace(conf.getIPAddress(), subnetCurr, subnet);
}
if(!putNewSubnet) {
- String msg = "Cluster conflict: Conflict while adding the subnet " + conf.getIPnum();
+ String msg = "Cluster conflict: Conflict while adding the subnet " + conf.getIPAddress();
return new Status(StatusCode.CONFLICT, msg);
}
// Subnet removal case
} else {
- subnets.remove(conf.getIPnum());
+ 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 isAdding) {
- // Valid config check
- if (!conf.isValidConfig()) {
- String msg = "Invalid Subnet configuration";
- log.warn(msg);
- return new Status(StatusCode.BADREQUEST, msg);
+ // Valid configuration check
+ Status status = conf.validate();
+ if (!status.isSuccess()) {
+ log.warn(status.getDescription());
+ return status;
}
if (isAdding) {
// Presence check
if (subnetsConfigList.containsKey(conf.getName())) {
return new Status(StatusCode.CONFLICT,
- "Subnet with the specified name already configured.");
+ "Subnet with the specified name already exists.");
}
// Semantic check
- Status rc = semanticCheck(conf);
- if (!rc.isSuccess()) {
- return rc;
+ status = semanticCheck(conf);
+ if (!status.isSuccess()) {
+ return status;
}
}
// Update Database
- Status rc = updateDatabase(conf, isAdding);
+ status = updateDatabase(conf, isAdding);
- if (rc.isSuccess()) {
+ if (status.isSuccess()) {
// Update Configuration
- rc = updateConfig(conf, isAdding);
- if(!rc.isSuccess()) {
+ 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 subnetsReplaced = subnets.replace(confCurr.getIPnum(), subCurr, sub);
+ 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);
}
@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) {
}
}
+ @SuppressWarnings("deprecation")
@Override
public void updateSwitchConfig(SwitchConfig cfgObject) {
// update default container only
@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);
}
/*
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) {
try {
map.put(s, new NodeConnector(entry.getValue()));
} catch (ConstructionException e) {
- e.printStackTrace();
+ log.error("An error occured",e);
}
}
}
try {
map.put(s, new NodeConnector(entry.getValue()));
} catch (ConstructionException e) {
- e.printStackTrace();
+ log.error("An error occured",e);
}
}
map.remove(name.getValue());
try {
map.put(s, new NodeConnector(entry.getValue()));
} catch (ConstructionException e) {
- e.printStackTrace();
+ log.error("An error occured",e);
}
}
map.remove(name.getValue());
&& (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 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();
}
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,
}
/**
- * 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