2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.controller.switchmanager.internal;
11 import java.io.FileNotFoundException;
12 import java.io.IOException;
13 import java.io.ObjectInputStream;
14 import java.net.InetAddress;
15 import java.net.NetworkInterface;
16 import java.net.SocketException;
17 import java.util.ArrayList;
18 import java.util.Collections;
19 import java.util.Date;
20 import java.util.Dictionary;
21 import java.util.EnumSet;
22 import java.util.Enumeration;
23 import java.util.HashMap;
24 import java.util.HashSet;
25 import java.util.List;
28 import java.util.concurrent.ConcurrentHashMap;
29 import java.util.concurrent.ConcurrentMap;
30 import java.util.concurrent.CopyOnWriteArrayList;
32 import org.apache.felix.dm.Component;
33 import org.eclipse.osgi.framework.console.CommandInterpreter;
34 import org.eclipse.osgi.framework.console.CommandProvider;
35 import org.opendaylight.controller.clustering.services.CacheConfigException;
36 import org.opendaylight.controller.clustering.services.CacheExistException;
37 import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
38 import org.opendaylight.controller.clustering.services.IClusterContainerServices;
39 import org.opendaylight.controller.clustering.services.IClusterServices;
40 import org.opendaylight.controller.configuration.IConfigurationContainerAware;
41 import org.opendaylight.controller.sal.core.Bandwidth;
42 import org.opendaylight.controller.sal.core.Config;
43 import org.opendaylight.controller.sal.core.ConstructionException;
44 import org.opendaylight.controller.sal.core.Description;
45 import org.opendaylight.controller.sal.core.ForwardingMode;
46 import org.opendaylight.controller.sal.core.MacAddress;
47 import org.opendaylight.controller.sal.core.Name;
48 import org.opendaylight.controller.sal.core.Node;
49 import org.opendaylight.controller.sal.core.NodeConnector;
50 import org.opendaylight.controller.sal.core.NodeConnector.NodeConnectorIDType;
51 import org.opendaylight.controller.sal.core.Property;
52 import org.opendaylight.controller.sal.core.State;
53 import org.opendaylight.controller.sal.core.Tier;
54 import org.opendaylight.controller.sal.core.UpdateType;
55 import org.opendaylight.controller.sal.inventory.IInventoryService;
56 import org.opendaylight.controller.sal.inventory.IListenInventoryUpdates;
57 import org.opendaylight.controller.sal.utils.GlobalConstants;
58 import org.opendaylight.controller.sal.utils.HexEncode;
59 import org.opendaylight.controller.sal.utils.IObjectReader;
60 import org.opendaylight.controller.sal.utils.ObjectReader;
61 import org.opendaylight.controller.sal.utils.ObjectWriter;
62 import org.opendaylight.controller.sal.utils.Status;
63 import org.opendaylight.controller.sal.utils.StatusCode;
64 import org.opendaylight.controller.switchmanager.IInventoryListener;
65 import org.opendaylight.controller.switchmanager.ISpanAware;
66 import org.opendaylight.controller.switchmanager.ISwitchManager;
67 import org.opendaylight.controller.switchmanager.ISwitchManagerAware;
68 import org.opendaylight.controller.switchmanager.SpanConfig;
69 import org.opendaylight.controller.switchmanager.Subnet;
70 import org.opendaylight.controller.switchmanager.SubnetConfig;
71 import org.opendaylight.controller.switchmanager.Switch;
72 import org.opendaylight.controller.switchmanager.SwitchConfig;
73 import org.osgi.framework.BundleContext;
74 import org.osgi.framework.FrameworkUtil;
75 import org.slf4j.Logger;
76 import org.slf4j.LoggerFactory;
79 * The class describes SwitchManager which is the central repository of all the
80 * inventory data including nodes, node connectors, properties attached, Layer3
81 * configurations, Span configurations, node configurations, network device
82 * representations viewed by Controller Web applications. One SwitchManager
83 * instance per container of the network. All the node/nodeConnector properties
84 * are maintained in the default container only.
86 public class SwitchManager implements ISwitchManager,
87 IConfigurationContainerAware, IObjectReader,
88 ICacheUpdateAware<Long, String>, IListenInventoryUpdates,
90 private static Logger log = LoggerFactory.getLogger(SwitchManager.class);
91 private static String ROOT = GlobalConstants.STARTUPHOME.toString();
92 private static final String SAVE = "Save";
93 private String subnetFileName, spanFileName, switchConfigFileName;
94 private final List<NodeConnector> spanNodeConnectors = new CopyOnWriteArrayList<NodeConnector>();
95 // set of Subnets keyed by the InetAddress
96 private ConcurrentMap<InetAddress, Subnet> subnets;
97 private ConcurrentMap<String, SubnetConfig> subnetsConfigList;
98 private ConcurrentMap<SpanConfig, SpanConfig> spanConfigList;
99 // manually configured parameters for the node such as name, tier, mode
100 private ConcurrentMap<String, SwitchConfig> nodeConfigList;
101 private ConcurrentMap<Long, String> configSaveEvent;
102 private ConcurrentMap<Node, Map<String, Property>> nodeProps;
103 private ConcurrentMap<NodeConnector, Map<String, Property>> nodeConnectorProps;
104 private ConcurrentMap<Node, Map<String, NodeConnector>> nodeConnectorNames;
105 private ConcurrentMap<String, Property> controllerProps;
106 private IInventoryService inventoryService;
107 private final Set<ISwitchManagerAware> switchManagerAware = Collections
108 .synchronizedSet(new HashSet<ISwitchManagerAware>());
109 private final Set<IInventoryListener> inventoryListeners = Collections
110 .synchronizedSet(new HashSet<IInventoryListener>());
111 private final Set<ISpanAware> spanAware = Collections.synchronizedSet(new HashSet<ISpanAware>());
112 private static boolean hostRefresh = true;
113 private int hostRetryCount = 5;
114 private IClusterContainerServices clusterContainerService = null;
115 private String containerName = null;
116 private boolean isDefaultContainer = true;
117 private static final int REPLACE_RETRY = 1;
119 public void notifySubnetChange(Subnet sub, boolean add) {
120 synchronized (switchManagerAware) {
121 for (Object subAware : switchManagerAware) {
123 ((ISwitchManagerAware) subAware).subnetNotify(sub, add);
124 } catch (Exception e) {
125 log.error("Failed to notify Subnet change {}",
132 public void notifySpanPortChange(Node node, List<NodeConnector> ports, boolean add) {
133 synchronized (spanAware) {
134 for (Object sa : spanAware) {
136 ((ISpanAware) sa).spanUpdate(node, ports, add);
137 } catch (Exception e) {
138 log.error("Failed to notify Span Interface change {}",
145 private void notifyModeChange(Node node, boolean proactive) {
146 synchronized (switchManagerAware) {
147 for (ISwitchManagerAware service : switchManagerAware) {
149 service.modeChangeNotify(node, proactive);
150 } catch (Exception e) {
151 log.error("Failed to notify Subnet change {}",
158 public void startUp() {
159 String container = this.getContainerName();
160 // Initialize configuration file names
161 subnetFileName = ROOT + "subnets_" + container + ".conf";
162 spanFileName = ROOT + "spanPorts_" + container + ".conf";
163 switchConfigFileName = ROOT + "switchConfig_" + container + ".conf";
165 // Instantiate cluster synced variables
170 * Read startup and build database if we have not already gotten the
171 * configurations synced from another node
173 if (subnetsConfigList.isEmpty()) {
174 loadSubnetConfiguration();
176 if (spanConfigList.isEmpty()) {
177 loadSpanConfiguration();
179 if (nodeConfigList.isEmpty()) {
180 loadSwitchConfiguration();
183 // Add controller MAC, if first node in the cluster
184 if (!controllerProps.containsKey(MacAddress.name)) {
185 byte controllerMac[] = getHardwareMAC();
186 if (controllerMac != null) {
187 Property existing = controllerProps.putIfAbsent(MacAddress.name, new MacAddress(controllerMac));
188 if (existing == null && log.isTraceEnabled()) {
189 log.trace("Container {}: Setting controller MAC address in the cluster: {}", container,
190 HexEncode.bytesToHexStringFormat(controllerMac));
196 public void shutDown() {
199 @SuppressWarnings("deprecation")
200 private void allocateCaches() {
201 if (this.clusterContainerService == null) {
202 this.nonClusterObjectCreate();
203 log.warn("un-initialized clusterContainerService, can't create cache");
208 clusterContainerService.createCache(
209 "switchmanager.subnetsConfigList",
210 EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
211 clusterContainerService.createCache("switchmanager.spanConfigList",
212 EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
213 clusterContainerService.createCache("switchmanager.nodeConfigList",
214 EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
215 clusterContainerService.createCache("switchmanager.subnets",
216 EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
217 clusterContainerService.createCache(
218 "switchmanager.configSaveEvent",
219 EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
220 clusterContainerService.createCache("switchmanager.nodeProps",
221 EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
222 clusterContainerService.createCache(
223 "switchmanager.nodeConnectorProps",
224 EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
225 clusterContainerService.createCache(
226 "switchmanager.nodeConnectorNames",
227 EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
228 clusterContainerService.createCache(
229 "switchmanager.controllerProps",
230 EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
231 } catch (CacheConfigException cce) {
232 log.error("\nCache configuration invalid - check cache mode");
233 } catch (CacheExistException ce) {
234 log.error("\nCache already exits - destroy and recreate if needed");
238 @SuppressWarnings({ "unchecked", "deprecation" })
239 private void retrieveCaches() {
240 if (this.clusterContainerService == null) {
241 log.info("un-initialized clusterContainerService, can't create cache");
245 subnetsConfigList = (ConcurrentMap<String, SubnetConfig>) clusterContainerService
246 .getCache("switchmanager.subnetsConfigList");
247 if (subnetsConfigList == null) {
248 log.error("\nFailed to get cache for subnetsConfigList");
251 spanConfigList = (ConcurrentMap<SpanConfig, SpanConfig>) clusterContainerService
252 .getCache("switchmanager.spanConfigList");
253 if (spanConfigList == null) {
254 log.error("\nFailed to get cache for spanConfigList");
257 nodeConfigList = (ConcurrentMap<String, SwitchConfig>) clusterContainerService
258 .getCache("switchmanager.nodeConfigList");
259 if (nodeConfigList == null) {
260 log.error("\nFailed to get cache for nodeConfigList");
263 subnets = (ConcurrentMap<InetAddress, Subnet>) clusterContainerService
264 .getCache("switchmanager.subnets");
265 if (subnets == null) {
266 log.error("\nFailed to get cache for subnets");
269 configSaveEvent = (ConcurrentMap<Long, String>) clusterContainerService
270 .getCache("switchmanager.configSaveEvent");
271 if (configSaveEvent == null) {
272 log.error("\nFailed to get cache for configSaveEvent");
275 nodeProps = (ConcurrentMap<Node, Map<String, Property>>) clusterContainerService
276 .getCache("switchmanager.nodeProps");
277 if (nodeProps == null) {
278 log.error("\nFailed to get cache for nodeProps");
281 nodeConnectorProps = (ConcurrentMap<NodeConnector, Map<String, Property>>) clusterContainerService
282 .getCache("switchmanager.nodeConnectorProps");
283 if (nodeConnectorProps == null) {
284 log.error("\nFailed to get cache for nodeConnectorProps");
287 nodeConnectorNames = (ConcurrentMap<Node, Map<String, NodeConnector>>) clusterContainerService
288 .getCache("switchmanager.nodeConnectorNames");
289 if (nodeConnectorNames == null) {
290 log.error("\nFailed to get cache for nodeConnectorNames");
293 controllerProps = (ConcurrentMap<String, Property>) clusterContainerService
294 .getCache("switchmanager.controllerProps");
295 if (controllerProps == null) {
296 log.error("\nFailed to get cache for controllerProps");
300 private void nonClusterObjectCreate() {
301 subnetsConfigList = new ConcurrentHashMap<String, SubnetConfig>();
302 spanConfigList = new ConcurrentHashMap<SpanConfig, SpanConfig>();
303 nodeConfigList = new ConcurrentHashMap<String, SwitchConfig>();
304 subnets = new ConcurrentHashMap<InetAddress, Subnet>();
305 configSaveEvent = new ConcurrentHashMap<Long, String>();
306 nodeProps = new ConcurrentHashMap<Node, Map<String, Property>>();
307 nodeConnectorProps = new ConcurrentHashMap<NodeConnector, Map<String, Property>>();
308 nodeConnectorNames = new ConcurrentHashMap<Node, Map<String, NodeConnector>>();
309 controllerProps = new ConcurrentHashMap<String, Property>();
313 public List<SubnetConfig> getSubnetsConfigList() {
314 return new ArrayList<SubnetConfig>(subnetsConfigList.values());
318 public SubnetConfig getSubnetConfig(String subnet) {
319 return subnetsConfigList.get(subnet);
322 private List<SpanConfig> getSpanConfigList(Node node) {
323 List<SpanConfig> confList = new ArrayList<SpanConfig>();
324 String nodeId = node.toString();
325 for (SpanConfig conf : spanConfigList.values()) {
326 if (conf.matchNode(nodeId)) {
333 public List<SwitchConfig> getNodeConfigList() {
334 return new ArrayList<SwitchConfig>(nodeConfigList.values());
338 public SwitchConfig getSwitchConfig(String switchId) {
339 return nodeConfigList.get(switchId);
342 public Switch getSwitchByNode(Node node) {
343 Switch sw = new Switch(node);
345 MacAddress mac = (MacAddress) this.getNodeProp(node,
348 sw.setDataLayerAddress(mac.getMacAddress());
350 Set<NodeConnector> ncSet = getPhysicalNodeConnectors(node);
351 sw.setNodeConnectors(ncSet);
353 List<NodeConnector> ncList = new ArrayList<NodeConnector>();
354 for (NodeConnector nodeConnector : ncSet) {
355 if (spanNodeConnectors.contains(nodeConnector)) {
356 ncList.add(nodeConnector);
359 sw.addSpanPorts(ncList);
365 public List<Switch> getNetworkDevices() {
366 Set<Node> nodeSet = getNodes();
367 List<Switch> swList = new ArrayList<Switch>();
368 if (nodeSet != null) {
369 for (Node node : nodeSet) {
370 swList.add(getSwitchByNode(node));
377 private Status updateConfig(SubnetConfig conf, boolean add) {
379 if(subnetsConfigList.putIfAbsent(conf.getName(), conf) != null) {
380 String msg = "Cluster conflict: Subnet with name " + conf.getName() + "already exists.";
381 return new Status(StatusCode.CONFLICT, msg);
384 subnetsConfigList.remove(conf.getName());
386 return new Status(StatusCode.SUCCESS);
389 private Status updateDatabase(SubnetConfig conf, boolean add) {
391 Subnet subnetCurr = subnets.get(conf.getIPnum());
393 if (subnetCurr == null) {
394 subnet = new Subnet(conf);
396 subnet = subnetCurr.clone();
398 // In case of API3 call we may receive the ports along with the
400 if (!conf.isGlobal()) {
401 Set<NodeConnector> sp = conf.getSubnetNodeConnectors();
402 subnet.addNodeConnectors(sp);
404 boolean result = false;
405 if(subnetCurr == null) {
406 if(subnets.putIfAbsent(conf.getIPnum(), subnet) == null) {
410 result = subnets.replace(conf.getIPnum(), subnetCurr, subnet);
413 String msg = "Cluster conflict: Conflict while adding the subnet " + conf.getIPnum();
414 return new Status(StatusCode.CONFLICT, msg);
416 } else { // This is the deletion of the whole subnet
417 subnets.remove(conf.getIPnum());
419 return new Status(StatusCode.SUCCESS);
422 private Status semanticCheck(SubnetConfig conf) {
423 Subnet newSubnet = new Subnet(conf);
424 Set<InetAddress> IPs = subnets.keySet();
426 return new Status(StatusCode.SUCCESS);
428 for (InetAddress i : IPs) {
429 Subnet existingSubnet = subnets.get(i);
430 if ((existingSubnet != null)
431 && !existingSubnet.isMutualExclusive(newSubnet)) {
432 return new Status(StatusCode.CONFLICT);
435 return new Status(StatusCode.SUCCESS);
438 private Status addRemoveSubnet(SubnetConfig conf, boolean add) {
439 // Valid config check
440 if (!conf.isValidConfig()) {
441 String msg = "Invalid Subnet configuration";
443 return new Status(StatusCode.BADREQUEST, msg);
448 if (subnetsConfigList.containsKey(conf.getName())) {
449 return new Status(StatusCode.CONFLICT,
450 "Same subnet config already exists");
453 Status rc = semanticCheck(conf);
454 if (!rc.isSuccess()) {
460 Status rc = updateDatabase(conf, add);
462 if (rc.isSuccess()) {
463 // Update Configuration
464 rc = updateConfig(conf, add);
465 if(!rc.isSuccess()) {
466 updateDatabase(conf, (!add));
474 * Adds Subnet configured in GUI or API3
477 public Status addSubnet(SubnetConfig conf) {
478 return this.addRemoveSubnet(conf, true);
482 public Status removeSubnet(SubnetConfig conf) {
483 return this.addRemoveSubnet(conf, false);
487 public Status removeSubnet(String name) {
488 SubnetConfig conf = subnetsConfigList.get(name);
490 return new Status(StatusCode.SUCCESS, "Subnet not present");
492 return this.addRemoveSubnet(conf, false);
496 public Status addPortsToSubnet(String name, String switchPorts) {
497 SubnetConfig confCurr = subnetsConfigList.get(name);
498 if (confCurr == null) {
499 return new Status(StatusCode.NOTFOUND, "Subnet does not exist");
501 if (!confCurr.isValidSwitchPort(switchPorts)) {
502 return new Status(StatusCode.BADREQUEST, "Invalid switchports");
505 Subnet subCurr = subnets.get(confCurr.getIPnum());
506 if (subCurr == null) {
507 log.debug("Cluster conflict: Subnet entry {} is not present in the subnets cache.", confCurr.getIPnum());
508 return new Status(StatusCode.NOTFOUND, "Subnet does not exist");
512 Subnet sub = subCurr.clone();
513 Set<NodeConnector> sp = confCurr.getNodeConnectors(switchPorts);
514 sub.addNodeConnectors(sp);
515 boolean subnetsReplace = subnets.replace(confCurr.getIPnum(), subCurr, sub);
516 if (!subnetsReplace) {
517 String msg = "Cluster conflict: Conflict while adding ports to the subnet " + name;
518 return new Status(StatusCode.CONFLICT, msg);
521 // Update Configuration
522 SubnetConfig conf = confCurr.clone();
523 conf.addNodeConnectors(switchPorts);
524 boolean result = subnetsConfigList.replace(name, confCurr, conf);
526 // TODO: recovery using Transactionality
527 String msg = "Cluster conflict: Conflict while adding ports to the subnet " + name;
528 return new Status(StatusCode.CONFLICT, msg);
531 return new Status(StatusCode.SUCCESS);
535 public Status removePortsFromSubnet(String name, String switchPorts) {
536 SubnetConfig confCurr = subnetsConfigList.get(name);
537 if (confCurr == null) {
538 return new Status(StatusCode.NOTFOUND, "Subnet does not exist");
541 Subnet subCurr = subnets.get(confCurr.getIPnum());
542 if (subCurr == null) {
543 log.debug("Cluster conflict: Subnet entry {} is not present in the subnets cache.", confCurr.getIPnum());
544 return new Status(StatusCode.NOTFOUND, "Subnet does not exist");
548 Subnet sub = subCurr.clone();
549 Set<NodeConnector> sp = confCurr.getNodeConnectors(switchPorts);
550 sub.deleteNodeConnectors(sp);
551 boolean subnetsReplace = subnets.replace(confCurr.getIPnum(), subCurr, sub);
552 if (!subnetsReplace) {
553 String msg = "Cluster conflict: Conflict while removing ports from the subnet " + name;
554 return new Status(StatusCode.CONFLICT, msg);
557 // Update Configuration
558 SubnetConfig conf = confCurr.clone();
559 conf.removeNodeConnectors(switchPorts);
560 boolean result = subnetsConfigList.replace(name, confCurr, conf);
562 // TODO: recovery using Transactionality
563 String msg = "Cluster conflict: Conflict while removing ports from " + conf;
564 return new Status(StatusCode.CONFLICT, msg);
567 return new Status(StatusCode.SUCCESS);
570 public String getContainerName() {
571 if (containerName == null) {
572 return GlobalConstants.DEFAULT.toString();
574 return containerName;
578 public Subnet getSubnetByNetworkAddress(InetAddress networkAddress) {
580 Set<InetAddress> indices = subnets.keySet();
581 for (InetAddress i : indices) {
582 sub = subnets.get(i);
583 if (sub.isSubnetOf(networkAddress)) {
591 public Object readObject(ObjectInputStream ois)
592 throws FileNotFoundException, IOException, ClassNotFoundException {
593 // Perform the class deserialization locally, from inside the package
594 // where the class is defined
595 return ois.readObject();
598 @SuppressWarnings("unchecked")
599 private void loadSubnetConfiguration() {
600 ObjectReader objReader = new ObjectReader();
601 ConcurrentMap<String, SubnetConfig> confList = (ConcurrentMap<String, SubnetConfig>) objReader
602 .read(this, subnetFileName);
604 if (confList == null) {
608 for (SubnetConfig conf : confList.values()) {
613 @SuppressWarnings("unchecked")
614 private void loadSpanConfiguration() {
615 ObjectReader objReader = new ObjectReader();
616 ConcurrentMap<Integer, SpanConfig> confList = (ConcurrentMap<Integer, SpanConfig>) objReader
617 .read(this, spanFileName);
619 if (confList == null) {
623 for (SpanConfig conf : confList.values()) {
628 @SuppressWarnings("unchecked")
629 private void loadSwitchConfiguration() {
630 ObjectReader objReader = new ObjectReader();
631 ConcurrentMap<String, SwitchConfig> confList = (ConcurrentMap<String, SwitchConfig>) objReader
632 .read(this, switchConfigFileName);
634 if (confList == null) {
638 for (SwitchConfig conf : confList.values()) {
639 updateSwitchConfig(conf);
644 public void updateSwitchConfig(SwitchConfig cfgObject) {
645 // update default container only
646 if (!isDefaultContainer) {
650 SwitchConfig sc = nodeConfigList.get(cfgObject.getNodeId());
652 if (nodeConfigList.putIfAbsent(cfgObject.getNodeId(), cfgObject) != null) {
656 if (!nodeConfigList.replace(cfgObject.getNodeId(), sc, cfgObject)) {
661 boolean modeChange = false;
663 if ((sc == null) || !cfgObject.getMode().equals(sc.getMode())) {
667 String nodeId = cfgObject.getNodeId();
668 Node node = Node.fromString(nodeId);
669 Map<String, Property> propMapCurr = nodeProps.get(node);
670 if (propMapCurr == null) {
673 Map<String, Property> propMap = new HashMap<String, Property>(propMapCurr);
674 Property desc = new Description(cfgObject.getNodeDescription());
675 propMap.put(desc.getName(), desc);
676 Property tier = new Tier(Integer.parseInt(cfgObject.getTier()));
677 propMap.put(tier.getName(), tier);
679 if (!nodeProps.replace(node, propMapCurr, propMap)) {
680 // TODO rollback using Transactionality
684 log.info("Set Node {}'s Mode to {}", nodeId, cfgObject.getMode());
687 notifyModeChange(node, cfgObject.isProactive());
692 public Status updateNodeConfig(SwitchConfig switchConfig) {
693 Status status = switchConfig.validate();
694 if (!status.isSuccess()) {
698 Map<String, Property> updateProperties = switchConfig.getNodeProperties();
699 String nodeId = switchConfig.getNodeId();
700 ForwardingMode mode = (ForwardingMode) updateProperties.get(ForwardingMode.name);
702 if (isDefaultContainer) {
703 if (!mode.isValid()) {
704 return new Status(StatusCode.BADREQUEST, "Invalid Forwarding Mode Value.");
707 return new Status(StatusCode.NOTACCEPTABLE,
708 "Forwarding Mode modification is allowed only in default container");
711 boolean modeChange = false;
712 SwitchConfig sc = nodeConfigList.get(nodeId);
713 Map<String, Property> prevNodeProperties = new HashMap<String, Property>();
715 if ((mode != null) && mode.isProactive()) {
718 if (!updateProperties.isEmpty()) {
719 if (nodeConfigList.putIfAbsent(nodeId, switchConfig) != null) {
720 return new Status(StatusCode.CONFLICT, "Cluster conflict: Unable to update node configuration");
724 prevNodeProperties = new HashMap<String, Property>(sc.getNodeProperties());
725 ForwardingMode prevMode = (ForwardingMode) sc.getProperty(ForwardingMode.name);
727 if ((prevMode != null) && (prevMode.isProactive())) {
731 if (((prevMode != null) && (prevMode.getValue() != mode.getValue()))
732 || (prevMode == null && mode.isProactive())) {
736 if (updateProperties.isEmpty()) {
737 nodeConfigList.remove(nodeId);
739 if (!nodeConfigList.replace(nodeId, sc, switchConfig)) {
740 return new Status(StatusCode.CONFLICT, "Cluster conflict: Unable to update node configuration");
744 Node node = Node.fromString(nodeId);
745 Map<String, Property> propMapCurr = nodeProps.get(node);
746 if (propMapCurr == null) {
747 return new Status(StatusCode.SUCCESS);
749 Map<String, Property> propMap = new HashMap<String, Property>(propMapCurr);
750 if (!prevNodeProperties.isEmpty()) {
751 for (String prop : prevNodeProperties.keySet()) {
752 if (!updateProperties.containsKey(prop)) {
753 if (prop.equals(Description.propertyName)) {
754 Map<Node, Map<String, Property>> nodeProp = this.inventoryService.getNodeProps();
755 if (nodeProp.get(node) != null) {
756 propMap.put(Description.propertyName, nodeProp.get(node).get(Description.propertyName));
760 propMap.remove(prop);
764 propMap.putAll(updateProperties);
765 if (!nodeProps.replace(node, propMapCurr, propMap)) {
766 // TODO rollback using Transactionality
767 return new Status(StatusCode.CONFLICT, "Cluster conflict: Unable to update node configuration.");
770 notifyModeChange(node, (mode == null) ? false : mode.isProactive());
772 return new Status(StatusCode.SUCCESS);
776 public Status removeNodeConfig(String nodeId) {
777 if ((nodeId == null) || (nodeId.isEmpty())) {
778 return new Status(StatusCode.BADREQUEST, "nodeId cannot be empty.");
780 Map<String, Property> nodeProperties = getSwitchConfig(nodeId).getNodeProperties();
781 Node node = Node.fromString(nodeId);
782 Map<String, Property> propMapCurr = nodeProps.get(node);
783 if ((propMapCurr != null) && (nodeProperties != null) && (!nodeProperties.isEmpty())) {
784 Map<String, Property> propMap = new HashMap<String, Property>(propMapCurr);
785 for (String prop : nodeProperties.keySet()) {
786 if (prop.equals(Description.propertyName)) {
787 Map<Node, Map<String, Property>> nodeProp = this.inventoryService.getNodeProps();
788 if (nodeProp.get(node) != null) {
789 propMap.put(Description.propertyName, nodeProp.get(node).get(Description.propertyName));
793 propMap.remove(prop);
795 if (!nodeProps.replace(node, propMapCurr, propMap)) {
796 return new Status(StatusCode.CONFLICT, "Cluster conflict: Unable to update node configuration.");
799 if (nodeConfigList != null) {
800 nodeConfigList.remove(nodeId);
802 return new Status(StatusCode.SUCCESS);
806 public Status saveSwitchConfig() {
807 // Publish the save config event to the cluster nodes
808 configSaveEvent.put(new Date().getTime(), SAVE);
809 return saveSwitchConfigInternal();
812 public Status saveSwitchConfigInternal() {
813 Status retS = null, retP = null;
814 ObjectWriter objWriter = new ObjectWriter();
816 retS = objWriter.write(new ConcurrentHashMap<String, SubnetConfig>(
817 subnetsConfigList), subnetFileName);
818 retP = objWriter.write(new ConcurrentHashMap<SpanConfig, SpanConfig>(
819 spanConfigList), spanFileName);
820 retS = objWriter.write(new ConcurrentHashMap<String, SwitchConfig>(
821 nodeConfigList), switchConfigFileName);
822 if (retS.equals(retP)) {
823 if (retS.isSuccess()) {
826 return new Status(StatusCode.INTERNALERROR, "Save failed");
829 return new Status(StatusCode.INTERNALERROR, "Partial save failure");
834 public List<SpanConfig> getSpanConfigList() {
835 return new ArrayList<SpanConfig>(spanConfigList.values());
839 public Status addSpanConfig(SpanConfig conf) {
840 // Valid config check
841 if (!conf.isValidConfig()) {
842 String msg = "Invalid Span configuration";
844 return new Status(StatusCode.BADREQUEST, msg);
848 if (spanConfigList.containsKey(conf)) {
849 return new Status(StatusCode.CONFLICT, "Same span config exists");
852 // Update configuration
853 if (spanConfigList.putIfAbsent(conf, conf) == null) {
854 // Update database and notify clients
855 addSpanPorts(conf.getNode(), conf.getPortArrayList());
858 return new Status(StatusCode.SUCCESS);
862 public Status removeSpanConfig(SpanConfig conf) {
863 removeSpanPorts(conf.getNode(), conf.getPortArrayList());
865 // Update configuration
866 spanConfigList.remove(conf);
868 return new Status(StatusCode.SUCCESS);
872 public List<NodeConnector> getSpanPorts(Node node) {
873 List<NodeConnector> ncList = new ArrayList<NodeConnector>();
875 for (NodeConnector nodeConnector : spanNodeConnectors) {
876 if (nodeConnector.getNode().equals(node)) {
877 ncList.add(nodeConnector);
884 public void entryCreated(Long key, String cacheName, boolean local) {
888 public void entryUpdated(Long key, String new_value, String cacheName,
889 boolean originLocal) {
890 saveSwitchConfigInternal();
894 public void entryDeleted(Long key, String cacheName, boolean originLocal) {
897 private void addNode(Node node, Set<Property> props) {
898 log.trace("{} added, props: {}", node, props);
899 if (nodeProps == null) {
903 Map<String, Property> propMapCurr = nodeProps.get(node);
904 Map<String, Property> propMap = (propMapCurr == null) ? new HashMap<String, Property>()
905 : new HashMap<String, Property>(propMapCurr);
907 // copy node properties from plugin
909 for (Property prop : props) {
910 propMap.put(prop.getName(), prop);
914 // copy node properties from config
915 boolean proactiveForwarding = false;
916 if (nodeConfigList != null) {
917 String nodeId = node.toString();
918 SwitchConfig conf = nodeConfigList.get(nodeId);
919 if (conf != null && (conf.getNodeProperties() != null)) {
920 Map<String, Property> nodeProperties = conf.getNodeProperties();
921 propMap.putAll(nodeProperties);
922 if (nodeProperties.get(ForwardingMode.name) != null) {
923 ForwardingMode mode = (ForwardingMode) nodeProperties.get(ForwardingMode.name);
924 proactiveForwarding = mode.isProactive();
929 boolean result = false;
930 if (propMapCurr == null) {
931 if (nodeProps.putIfAbsent(node, propMap) == null) {
935 result = nodeProps.replace(node, propMapCurr, propMap);
938 log.debug("Cluster conflict: Conflict while adding the node properties. Node: {} Properties: {}",
939 node.getID(), props);
940 addNodeProps(node, propMap);
943 // check if span ports are configed
946 // notify node listeners
947 notifyNode(node, UpdateType.ADDED, propMap);
949 // notify proactive mode forwarding
950 if (proactiveForwarding) {
951 notifyModeChange(node, true);
955 private void removeNode(Node node) {
956 log.trace("{} removed", node);
957 if (nodeProps == null) {
960 nodeProps.remove(node);
962 // check if span ports need to be cleaned up
963 removeSpanPorts(node);
965 /* notify node listeners */
966 notifyNode(node, UpdateType.REMOVED, null);
969 private void updateNode(Node node, Set<Property> props) {
970 log.trace("{} updated, props: {}", node, props);
971 if (nodeProps == null || !nodeProps.containsKey(node) ||
972 props == null || props.isEmpty()) {
976 Map<String, Property> propMapCurr = nodeProps.get(node);
977 Map<String, Property> propMap = (propMapCurr == null) ? new HashMap<String, Property>()
978 : new HashMap<String, Property>(propMapCurr);
980 // copy node properties from plugin
981 String nodeId = node.toString();
982 for (Property prop : props) {
983 if (nodeConfigList != null) {
984 SwitchConfig conf = nodeConfigList.get(nodeId);
985 if (conf != null && (conf.getNodeProperties() != null)
986 && conf.getNodeProperties().containsKey(prop.getName())) {
990 propMap.put(prop.getName(), prop);
993 if (propMapCurr == null) {
994 if (nodeProps.putIfAbsent(node, propMap) != null) {
995 log.debug("Cluster conflict: Conflict while updating the node. Node: {} Properties: {}",
996 node.getID(), props);
997 addNodeProps(node, propMap);
1000 if (!nodeProps.replace(node, propMapCurr, propMap)) {
1001 log.debug("Cluster conflict: Conflict while updating the node. Node: {} Properties: {}",
1002 node.getID(), props);
1003 addNodeProps(node, propMap);
1007 /* notify node listeners */
1008 notifyNode(node, UpdateType.CHANGED, propMap);
1012 public void updateNode(Node node, UpdateType type, Set<Property> props) {
1013 log.debug("updateNode: {} type {} props {} for container {}",
1014 new Object[] { node, type, props, containerName });
1017 addNode(node, props);
1020 updateNode(node, props);
1031 public void updateNodeConnector(NodeConnector nodeConnector,
1032 UpdateType type, Set<Property> props) {
1033 Map<String, Property> propMap = new HashMap<String, Property>();
1035 log.debug("updateNodeConnector: {} type {} props {} for container {}",
1036 new Object[] { nodeConnector, type, props, containerName });
1038 if (nodeConnectorProps == null) {
1045 if (props != null) {
1046 for (Property prop : props) {
1047 addNodeConnectorProp(nodeConnector, prop);
1048 propMap.put(prop.getName(), prop);
1051 addNodeConnectorProp(nodeConnector, null);
1054 addSpanPort(nodeConnector);
1057 removeNodeConnectorAllProps(nodeConnector);
1059 // clean up span config
1060 removeSpanPort(nodeConnector);
1066 notifyNodeConnector(nodeConnector, type, propMap);
1070 public Set<Node> getNodes() {
1071 return (nodeProps != null) ? new HashSet<Node>(nodeProps.keySet())
1076 * Returns a copy of a list of properties for a given node
1081 * org.opendaylight.controller.switchmanager.ISwitchManager#getNodeProps
1082 * (org.opendaylight.controller.sal.core.Node)
1085 public Map<String, Property> getNodeProps(Node node) {
1086 Map<String, Property> rv = new HashMap<String, Property>();
1087 if (this.nodeProps != null) {
1088 rv = this.nodeProps.get(node);
1090 /* make a copy of it */
1091 rv = new HashMap<String, Property>(rv);
1098 public Property getNodeProp(Node node, String propName) {
1099 Map<String, Property> propMap = getNodeProps(node);
1100 return (propMap != null) ? propMap.get(propName) : null;
1104 public void setNodeProp(Node node, Property prop) {
1106 for (int i = 0; i <= REPLACE_RETRY; i++) {
1107 /* Get a copy of the property map */
1108 Map<String, Property> propMapCurr = getNodeProps(node);
1109 if (propMapCurr == null) {
1113 Map<String, Property> propMap = new HashMap<String, Property>(propMapCurr);
1114 propMap.put(prop.getName(), prop);
1116 if (nodeProps.replace(node, propMapCurr, propMap)) {
1119 if (!propMapCurr.get(prop.getName()).equals(nodeProps.get(node).get(prop.getName()))) {
1120 log.debug("Cluster conflict: Unable to add property {} to node {}.", prop.getName(), node.getID());
1124 log.warn("Cluster conflict: Unable to add property {} to node {}.", prop.getName(), node.getID());
1128 public Status removeNodeProp(Node node, String propName) {
1129 for (int i = 0; i <= REPLACE_RETRY; i++) {
1130 Map<String, Property> propMapCurr = getNodeProps(node);
1131 if (propMapCurr != null) {
1132 if (!propMapCurr.containsKey(propName)) {
1133 return new Status(StatusCode.SUCCESS);
1135 Map<String, Property> propMap = new HashMap<String, Property>(propMapCurr);
1136 propMap.remove(propName);
1137 if (nodeProps.replace(node, propMapCurr, propMap)) {
1138 return new Status(StatusCode.SUCCESS);
1140 if (!propMapCurr.get(propName).equals(nodeProps.get(node).get(propName))) {
1141 String msg = "Cluster conflict: Unable to remove property " + propName + " for node "
1143 return new Status(StatusCode.CONFLICT, msg);
1147 return new Status(StatusCode.SUCCESS);
1150 String msg = "Cluster conflict: Unable to remove property " + propName + " for node " + node.getID();
1151 return new Status(StatusCode.CONFLICT, msg);
1155 public Status removeNodeAllProps(Node node) {
1156 this.nodeProps.remove(node);
1157 return new Status(StatusCode.SUCCESS);
1161 public Set<NodeConnector> getUpNodeConnectors(Node node) {
1162 if (nodeConnectorProps == null) {
1166 Set<NodeConnector> nodeConnectorSet = new HashSet<NodeConnector>();
1167 for (NodeConnector nodeConnector : nodeConnectorProps.keySet()) {
1168 if (!nodeConnector.getNode().equals(node)) {
1171 if (isNodeConnectorEnabled(nodeConnector)) {
1172 nodeConnectorSet.add(nodeConnector);
1176 return nodeConnectorSet;
1180 public Set<NodeConnector> getNodeConnectors(Node node) {
1181 if (nodeConnectorProps == null) {
1185 Set<NodeConnector> nodeConnectorSet = new HashSet<NodeConnector>();
1186 for (NodeConnector nodeConnector : nodeConnectorProps.keySet()) {
1187 if (!nodeConnector.getNode().equals(node)) {
1190 nodeConnectorSet.add(nodeConnector);
1193 return nodeConnectorSet;
1197 public Set<NodeConnector> getPhysicalNodeConnectors(Node node) {
1198 if (nodeConnectorProps == null) {
1202 Set<NodeConnector> nodeConnectorSet = new HashSet<NodeConnector>();
1203 for (NodeConnector nodeConnector : nodeConnectorProps.keySet()) {
1204 if (!nodeConnector.getNode().equals(node)
1205 || isSpecial(nodeConnector)) {
1208 nodeConnectorSet.add(nodeConnector);
1211 return nodeConnectorSet;
1215 public Map<String, Property> getNodeConnectorProps(NodeConnector nodeConnector) {
1216 Map<String, Property> rv = new HashMap<String, Property>();
1217 if (this.nodeConnectorProps != null) {
1218 rv = this.nodeConnectorProps.get(nodeConnector);
1220 rv = new HashMap<String, Property>(rv);
1227 public Property getNodeConnectorProp(NodeConnector nodeConnector,
1229 Map<String, Property> propMap = getNodeConnectorProps(nodeConnector);
1230 return (propMap != null) ? propMap.get(propName) : null;
1233 private byte[] getHardwareMAC() {
1234 Enumeration<NetworkInterface> nis;
1235 byte[] macAddress = null;
1238 nis = NetworkInterface.getNetworkInterfaces();
1239 } catch (SocketException e) {
1240 log.error("Failed to acquire controller MAC: ", e);
1244 while (nis.hasMoreElements()) {
1245 NetworkInterface ni = nis.nextElement();
1247 macAddress = ni.getHardwareAddress();
1248 } catch (SocketException e) {
1249 log.error("Failed to acquire controller MAC: ", e);
1251 if (macAddress != null) {
1255 if (macAddress == null) {
1256 log.warn("Failed to acquire controller MAC: No physical interface found");
1257 // This happens when running controller on windows VM, for example
1258 // Try parsing the OS command output
1264 public byte[] getControllerMAC() {
1265 MacAddress macProperty = (MacAddress)controllerProps.get(MacAddress.name);
1266 return (macProperty == null) ? null : macProperty.getMacAddress();
1270 public boolean isHostRefreshEnabled() {
1275 public int getHostRetryCount() {
1276 return hostRetryCount;
1280 public NodeConnector getNodeConnector(Node node, String nodeConnectorName) {
1281 if (nodeConnectorNames == null) {
1285 Map<String, NodeConnector> map = nodeConnectorNames.get(node);
1290 return map.get(nodeConnectorName);
1294 * Adds a node connector and its property if any
1296 * @param nodeConnector
1297 * {@link org.opendaylight.controller.sal.core.NodeConnector}
1299 * name of {@link org.opendaylight.controller.sal.core.Property}
1300 * @return success or failed reason
1303 public Status addNodeConnectorProp(NodeConnector nodeConnector,
1305 Map<String, Property> propMapCurr = getNodeConnectorProps(nodeConnector);
1306 Map<String, Property> propMap = (propMapCurr == null) ? new HashMap<String, Property>()
1307 : new HashMap<String, Property>(propMapCurr);
1309 String msg = "Cluster conflict: Unable to add NodeConnector Property.";
1310 // Just add the nodeConnector if prop is not available (in a non-default
1313 if (propMapCurr == null) {
1314 if (nodeConnectorProps.putIfAbsent(nodeConnector, propMap) != null) {
1315 return new Status(StatusCode.CONFLICT, msg);
1318 if (!nodeConnectorProps.replace(nodeConnector, propMapCurr, propMap)) {
1319 return new Status(StatusCode.CONFLICT, msg);
1322 return new Status(StatusCode.SUCCESS);
1325 propMap.put(prop.getName(), prop);
1326 if (propMapCurr == null) {
1327 if (nodeConnectorProps.putIfAbsent(nodeConnector, propMap) != null) {
1328 return new Status(StatusCode.CONFLICT, msg);
1331 if (!nodeConnectorProps.replace(nodeConnector, propMapCurr, propMap)) {
1332 return new Status(StatusCode.CONFLICT, msg);
1336 if (prop.getName().equals(Name.NamePropName)) {
1337 if (nodeConnectorNames != null) {
1338 Node node = nodeConnector.getNode();
1339 Map<String, NodeConnector> mapCurr = nodeConnectorNames.get(node);
1340 Map<String, NodeConnector> map = new HashMap<String, NodeConnector>();
1341 if (mapCurr != null) {
1342 for (String s : mapCurr.keySet()) {
1344 map.put(s, new NodeConnector(mapCurr.get(s)));
1345 } catch (ConstructionException e) {
1346 e.printStackTrace();
1351 map.put(((Name) prop).getValue(), nodeConnector);
1352 if (mapCurr == null) {
1353 if (nodeConnectorNames.putIfAbsent(node, map) != null) {
1354 // TODO: recovery using Transactionality
1355 return new Status(StatusCode.CONFLICT, msg);
1358 if (!nodeConnectorNames.replace(node, mapCurr, map)) {
1359 // TODO: recovery using Transactionality
1360 return new Status(StatusCode.CONFLICT, msg);
1366 return new Status(StatusCode.SUCCESS);
1370 * Removes one property of a node connector
1372 * @param nodeConnector
1373 * {@link org.opendaylight.controller.sal.core.NodeConnector}
1375 * name of {@link org.opendaylight.controller.sal.core.Property}
1376 * @return success or failed reason
1379 public Status removeNodeConnectorProp(NodeConnector nodeConnector, String propName) {
1380 Map<String, Property> propMapCurr = getNodeConnectorProps(nodeConnector);
1382 if (propMapCurr == null) {
1383 /* Nothing to remove */
1384 return new Status(StatusCode.SUCCESS);
1387 Map<String, Property> propMap = new HashMap<String, Property>(propMapCurr);
1388 propMap.remove(propName);
1389 boolean result = nodeConnectorProps.replace(nodeConnector, propMapCurr, propMap);
1390 String msg = "Cluster conflict: Unable to remove NodeConnector property.";
1392 return new Status(StatusCode.CONFLICT, msg);
1395 if (propName.equals(Name.NamePropName)) {
1396 if (nodeConnectorNames != null) {
1397 Name name = ((Name) getNodeConnectorProp(nodeConnector, Name.NamePropName));
1399 Node node = nodeConnector.getNode();
1400 Map<String, NodeConnector> mapCurr = nodeConnectorNames.get(node);
1401 if (mapCurr != null) {
1402 Map<String, NodeConnector> map = new HashMap<String, NodeConnector>();
1403 for (String s : mapCurr.keySet()) {
1405 map.put(s, new NodeConnector(mapCurr.get(s)));
1406 } catch (ConstructionException e) {
1407 e.printStackTrace();
1410 map.remove(name.getValue());
1411 if (!nodeConnectorNames.replace(node, mapCurr, map)) {
1412 // TODO: recovery using Transactionality
1413 return new Status(StatusCode.CONFLICT, msg);
1420 return new Status(StatusCode.SUCCESS);
1424 * Removes all the properties of a node connector
1426 * @param nodeConnector
1427 * {@link org.opendaylight.controller.sal.core.NodeConnector}
1428 * @return success or failed reason
1431 public Status removeNodeConnectorAllProps(NodeConnector nodeConnector) {
1432 if (nodeConnectorNames != null) {
1433 Name name = ((Name) getNodeConnectorProp(nodeConnector, Name.NamePropName));
1435 Node node = nodeConnector.getNode();
1436 Map<String, NodeConnector> mapCurr = nodeConnectorNames.get(node);
1437 if (mapCurr != null) {
1438 Map<String, NodeConnector> map = new HashMap<String, NodeConnector>();
1439 for (String s : mapCurr.keySet()) {
1441 map.put(s, new NodeConnector(mapCurr.get(s)));
1442 } catch (ConstructionException e) {
1443 e.printStackTrace();
1446 map.remove(name.getValue());
1447 if (!nodeConnectorNames.replace(node, mapCurr, map)) {
1448 log.warn("Cluster conflict: Unable remove Name property of nodeconnector {}, skip.",
1449 nodeConnector.getID());
1455 nodeConnectorProps.remove(nodeConnector);
1457 return new Status(StatusCode.SUCCESS);
1461 * Function called by the dependency manager when all the required
1462 * dependencies are satisfied
1465 void init(Component c) {
1466 Dictionary<?, ?> props = c.getServiceProperties();
1467 if (props != null) {
1468 this.containerName = (String) props.get("containerName");
1469 log.trace("Running containerName: {}", this.containerName);
1471 // In the Global instance case the containerName is empty
1472 this.containerName = "";
1474 isDefaultContainer = containerName.equals(GlobalConstants.DEFAULT
1481 * Function called by the dependency manager when at least one dependency
1482 * become unsatisfied or when the component is shutting down because for
1483 * example bundle is being stopped.
1491 * Function called by dependency manager after "init ()" is called and after
1492 * the services provided by the class are registered in the service registry
1497 registerWithOSGIConsole();
1501 * Function called after registered the service in OSGi service registry.
1504 // solicit for existing inventories
1509 * Function called by the dependency manager before the services exported by
1510 * the component are unregistered, this will be followed by a "destroy ()"
1517 public void setInventoryService(IInventoryService service) {
1518 log.trace("Got inventory service set request {}", service);
1519 this.inventoryService = service;
1521 // solicit for existing inventories
1525 public void unsetInventoryService(IInventoryService service) {
1526 log.trace("Got a service UNset request");
1527 this.inventoryService = null;
1529 // clear existing inventories
1533 public void setSwitchManagerAware(ISwitchManagerAware service) {
1534 log.trace("Got inventory service set request {}", service);
1535 if (this.switchManagerAware != null) {
1536 this.switchManagerAware.add(service);
1539 // bulk update for newly joined
1540 switchManagerAwareNotify(service);
1543 public void unsetSwitchManagerAware(ISwitchManagerAware service) {
1544 log.trace("Got a service UNset request");
1545 if (this.switchManagerAware != null) {
1546 this.switchManagerAware.remove(service);
1550 public void setInventoryListener(IInventoryListener service) {
1551 log.trace("Got inventory listener set request {}", service);
1552 if (this.inventoryListeners != null) {
1553 this.inventoryListeners.add(service);
1556 // bulk update for newly joined
1557 bulkUpdateService(service);
1560 public void unsetInventoryListener(IInventoryListener service) {
1561 log.trace("Got a service UNset request");
1562 if (this.inventoryListeners != null) {
1563 this.inventoryListeners.remove(service);
1567 public void setSpanAware(ISpanAware service) {
1568 log.trace("Got SpanAware set request {}", service);
1569 if (this.spanAware != null) {
1570 this.spanAware.add(service);
1573 // bulk update for newly joined
1574 spanAwareNotify(service);
1577 public void unsetSpanAware(ISpanAware service) {
1578 log.trace("Got a service UNset request");
1579 if (this.spanAware != null) {
1580 this.spanAware.remove(service);
1584 void setClusterContainerService(IClusterContainerServices s) {
1585 log.trace("Cluster Service set");
1586 this.clusterContainerService = s;
1589 void unsetClusterContainerService(IClusterContainerServices s) {
1590 if (this.clusterContainerService == s) {
1591 log.trace("Cluster Service removed!");
1592 this.clusterContainerService = null;
1596 private void getInventories() {
1597 if (inventoryService == null) {
1598 log.trace("inventory service not avaiable");
1602 Map<Node, Map<String, Property>> nodeProp = this.inventoryService.getNodeProps();
1603 for (Map.Entry<Node, Map<String, Property>> entry : nodeProp.entrySet()) {
1604 Node node = entry.getKey();
1605 log.debug("getInventories: {} added for container {}", new Object[] { node, containerName });
1606 Map<String, Property> propMap = entry.getValue();
1607 Set<Property> props = new HashSet<Property>();
1608 for (Property property : propMap.values()) {
1609 props.add(property);
1611 addNode(node, props);
1614 Map<NodeConnector, Map<String, Property>> nodeConnectorProp = this.inventoryService.getNodeConnectorProps();
1615 for (Map.Entry<NodeConnector, Map<String, Property>> entry : nodeConnectorProp.entrySet()) {
1616 Map<String, Property> propMap = entry.getValue();
1617 for (Property property : propMap.values()) {
1618 addNodeConnectorProp(entry.getKey(), property);
1623 private void clearInventories() {
1625 nodeConnectorProps.clear();
1626 nodeConnectorNames.clear();
1627 spanNodeConnectors.clear();
1630 private void notifyNode(Node node, UpdateType type,
1631 Map<String, Property> propMap) {
1632 synchronized (inventoryListeners) {
1633 for (IInventoryListener service : inventoryListeners) {
1634 service.notifyNode(node, type, propMap);
1639 private void notifyNodeConnector(NodeConnector nodeConnector,
1640 UpdateType type, Map<String, Property> propMap) {
1641 synchronized (inventoryListeners) {
1642 for (IInventoryListener service : inventoryListeners) {
1643 service.notifyNodeConnector(nodeConnector, type, propMap);
1649 * For those joined late, bring them up-to-date.
1651 private void switchManagerAwareNotify(ISwitchManagerAware service) {
1652 for (Subnet sub : subnets.values()) {
1653 service.subnetNotify(sub, true);
1656 for (Node node : getNodes()) {
1657 SwitchConfig sc = getSwitchConfig(node.toString());
1658 if ((sc != null) && isDefaultContainer) {
1659 ForwardingMode mode = (ForwardingMode) sc.getProperty(ForwardingMode.name);
1660 service.modeChangeNotify(node, (mode == null) ? false : mode.isProactive());
1665 private void bulkUpdateService(IInventoryListener service) {
1666 Map<String, Property> propMap;
1667 UpdateType type = UpdateType.ADDED;
1669 for (Node node : getNodes()) {
1670 propMap = nodeProps.get(node);
1671 service.notifyNode(node, type, propMap);
1674 for (NodeConnector nodeConnector : nodeConnectorProps.keySet()) {
1675 propMap = nodeConnectorProps.get(nodeConnector);
1676 service.notifyNodeConnector(nodeConnector, type, propMap);
1680 private void spanAwareNotify(ISpanAware service) {
1681 for (Node node : getNodes()) {
1682 for (SpanConfig conf : getSpanConfigList(node)) {
1683 service.spanUpdate(node, conf.getPortArrayList(), true);
1688 private void registerWithOSGIConsole() {
1689 BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass())
1690 .getBundleContext();
1691 bundleContext.registerService(CommandProvider.class.getName(), this,
1696 public Boolean isNodeConnectorEnabled(NodeConnector nodeConnector) {
1697 if (nodeConnector == null) {
1701 Config config = (Config) getNodeConnectorProp(nodeConnector,
1702 Config.ConfigPropName);
1703 State state = (State) getNodeConnectorProp(nodeConnector,
1704 State.StatePropName);
1705 return ((config != null) && (config.getValue() == Config.ADMIN_UP)
1706 && (state != null) && (state.getValue() == State.EDGE_UP));
1710 public String getHelp() {
1711 StringBuffer help = new StringBuffer();
1712 help.append("---Switch Manager---\n");
1713 help.append("\t pns - Print connected nodes\n");
1714 help.append("\t pncs <node id> - Print node connectors for a given node\n");
1715 help.append("\t pencs <node id> - Print enabled node connectors for a given node\n");
1716 help.append("\t pdm <node id> - Print switch ports in device map\n");
1717 help.append("\t snt <node id> <tier> - Set node tier number\n");
1718 help.append("\t hostRefresh <on/off/?> - Enable/Disable/Query host refresh\n");
1719 help.append("\t hostRetry <count> - Set host retry count\n");
1720 return help.toString();
1723 public void _pns(CommandInterpreter ci) {
1724 ci.println(" Node Type MAC Name Tier");
1725 if (nodeProps == null) {
1728 Set<Node> nodeSet = nodeProps.keySet();
1729 if (nodeSet == null) {
1732 List<String> nodeArray = new ArrayList<String>();
1733 for (Node node : nodeSet) {
1734 nodeArray.add(node.toString());
1736 Collections.sort(nodeArray);
1737 for (String str: nodeArray) {
1738 Node node = Node.fromString(str);
1739 Description desc = ((Description) getNodeProp(node,
1740 Description.propertyName));
1741 Tier tier = ((Tier) getNodeProp(node, Tier.TierPropName));
1742 String nodeName = (desc == null) ? "" : desc.getValue();
1743 MacAddress mac = (MacAddress) getNodeProp(node,
1745 String macAddr = (mac == null) ? "" : HexEncode
1746 .bytesToHexStringFormat(mac.getMacAddress());
1747 int tierNum = (tier == null) ? 0 : tier.getValue();
1748 ci.println(node + " " + node.getType() + " " + macAddr
1749 + " " + nodeName + " " + tierNum);
1751 ci.println("Total number of Nodes: " + nodeSet.size());
1754 public void _pencs(CommandInterpreter ci) {
1755 String st = ci.nextArgument();
1757 ci.println("Please enter node id");
1761 Node node = Node.fromString(st);
1763 ci.println("Please enter node id");
1767 Set<NodeConnector> nodeConnectorSet = getUpNodeConnectors(node);
1768 if (nodeConnectorSet == null) {
1771 for (NodeConnector nodeConnector : nodeConnectorSet) {
1772 if (nodeConnector == null) {
1775 ci.println(nodeConnector);
1777 ci.println("Total number of NodeConnectors: " + nodeConnectorSet.size());
1780 public void _pncs(CommandInterpreter ci) {
1781 String st = ci.nextArgument();
1783 ci.println("Please enter node id");
1787 Node node = Node.fromString(st);
1789 ci.println("Please enter node id");
1793 ci.println(" NodeConnector BandWidth(Gbps) Admin State");
1794 Set<NodeConnector> nodeConnectorSet = getNodeConnectors(node);
1795 if (nodeConnectorSet == null) {
1798 for (NodeConnector nodeConnector : nodeConnectorSet) {
1799 if (nodeConnector == null) {
1802 Map<String, Property> propMap = getNodeConnectorProps(nodeConnector);
1803 Bandwidth bw = (Bandwidth) propMap.get(Bandwidth.BandwidthPropName);
1804 Config config = (Config) propMap.get(Config.ConfigPropName);
1805 State state = (State) propMap.get(State.StatePropName);
1806 String out = nodeConnector + " ";
1807 out += (bw != null) ? bw.getValue() / Math.pow(10, 9) : " ";
1809 out += (config != null) ? config.getValue() : " ";
1811 out += (state != null) ? state.getValue() : " ";
1814 ci.println("Total number of NodeConnectors: " + nodeConnectorSet.size());
1817 public void _pdm(CommandInterpreter ci) {
1818 String st = ci.nextArgument();
1820 ci.println("Please enter node id");
1824 Node node = Node.fromString(st);
1826 ci.println("Please enter node id");
1830 Switch sw = getSwitchByNode(node);
1832 ci.println(" NodeConnector Name");
1836 Set<NodeConnector> nodeConnectorSet = sw.getNodeConnectors();
1837 String nodeConnectorName;
1838 if (nodeConnectorSet != null && nodeConnectorSet.size() > 0) {
1839 for (NodeConnector nodeConnector : nodeConnectorSet) {
1840 Map<String, Property> propMap = getNodeConnectorProps(nodeConnector);
1841 nodeConnectorName = (propMap == null) ? null : ((Name) propMap
1842 .get(Name.NamePropName)).getValue();
1843 if (nodeConnectorName != null) {
1844 Node nd = nodeConnector.getNode();
1845 if (!nd.equals(node)) {
1846 log.debug("node not match {} {}", nd, node);
1848 Map<String, NodeConnector> map = nodeConnectorNames
1851 NodeConnector nc = map.get(nodeConnectorName);
1853 log.debug("no nodeConnector named {}",
1855 } else if (!nc.equals(nodeConnector)) {
1856 log.debug("nodeConnector not match {} {}", nc,
1862 ci.println(nodeConnector
1864 + ((nodeConnectorName == null) ? "" : nodeConnectorName)
1865 + "(" + nodeConnector.getID() + ")");
1867 ci.println("Total number of NodeConnectors: "
1868 + nodeConnectorSet.size());
1872 public void _snt(CommandInterpreter ci) {
1873 String st = ci.nextArgument();
1875 ci.println("Please enter node id");
1879 Node node = Node.fromString(st);
1881 ci.println("Please enter node id");
1885 st = ci.nextArgument();
1887 ci.println("Please enter tier number");
1890 Integer tid = Integer.decode(st);
1891 Tier tier = new Tier(tid);
1892 setNodeProp(node, tier);
1895 public void _hostRefresh(CommandInterpreter ci) {
1896 String mode = ci.nextArgument();
1898 ci.println("expecting on/off/?");
1901 if (mode.toLowerCase().equals("on")) {
1903 } else if (mode.toLowerCase().equals("off")) {
1904 hostRefresh = false;
1905 } else if (mode.equals("?")) {
1907 ci.println("host refresh is ON");
1909 ci.println("host refresh is OFF");
1912 ci.println("expecting on/off/?");
1917 public void _hostRetry(CommandInterpreter ci) {
1918 String retry = ci.nextArgument();
1919 if (retry == null) {
1920 ci.println("Please enter a valid number. Current retry count is "
1925 hostRetryCount = Integer.parseInt(retry);
1926 } catch (Exception e) {
1927 ci.println("Please enter a valid number");
1933 public byte[] getNodeMAC(Node node) {
1934 MacAddress mac = (MacAddress) this.getNodeProp(node,
1936 return (mac != null) ? mac.getMacAddress() : null;
1940 public boolean isSpecial(NodeConnector p) {
1941 if (p.getType().equals(NodeConnectorIDType.CONTROLLER)
1942 || p.getType().equals(NodeConnectorIDType.ALL)
1943 || p.getType().equals(NodeConnectorIDType.SWSTACK)
1944 || p.getType().equals(NodeConnectorIDType.HWPATH)) {
1951 * Add span configuration to local cache and notify clients
1953 private void addSpanPorts(Node node, List<NodeConnector> nodeConnectors) {
1954 List<NodeConnector> ncLists = new ArrayList<NodeConnector>();
1956 for (NodeConnector nodeConnector : nodeConnectors) {
1957 if (!spanNodeConnectors.contains(nodeConnector)) {
1958 ncLists.add(nodeConnector);
1962 if (ncLists.size() > 0) {
1963 spanNodeConnectors.addAll(ncLists);
1964 notifySpanPortChange(node, ncLists, true);
1968 private void addSpanPorts(Node node) {
1969 for (SpanConfig conf : getSpanConfigList(node)) {
1970 addSpanPorts(node, conf.getPortArrayList());
1974 private void addSpanPort(NodeConnector nodeConnector) {
1975 // only add if span is configured on this nodeConnector
1976 for (SpanConfig conf : getSpanConfigList(nodeConnector.getNode())) {
1977 if (conf.getPortArrayList().contains(nodeConnector)) {
1978 List<NodeConnector> ncLists = new ArrayList<NodeConnector>();
1979 ncLists.add(nodeConnector);
1980 addSpanPorts(nodeConnector.getNode(), ncLists);
1987 * Remove span configuration to local cache and notify clients
1989 private void removeSpanPorts(Node node, List<NodeConnector> nodeConnectors) {
1990 List<NodeConnector> ncLists = new ArrayList<NodeConnector>();
1992 for (NodeConnector nodeConnector : nodeConnectors) {
1993 if (spanNodeConnectors.contains(nodeConnector)) {
1994 ncLists.add(nodeConnector);
1998 if (ncLists.size() > 0) {
1999 spanNodeConnectors.removeAll(ncLists);
2000 notifySpanPortChange(node, ncLists, false);
2004 private void removeSpanPorts(Node node) {
2005 for (SpanConfig conf : getSpanConfigList(node)) {
2006 addSpanPorts(node, conf.getPortArrayList());
2010 private void removeSpanPort(NodeConnector nodeConnector) {
2011 if (spanNodeConnectors.contains(nodeConnector)) {
2012 List<NodeConnector> ncLists = new ArrayList<NodeConnector>();
2013 ncLists.add(nodeConnector);
2014 removeSpanPorts(nodeConnector.getNode(), ncLists);
2018 private void addNodeProps(Node node, Map<String, Property> propMap) {
2019 if (propMap == null) {
2020 propMap = new HashMap<String, Property>();
2022 nodeProps.put(node, propMap);
2025 private void removeNodeProps(Node node) {
2026 if (getUpNodeConnectors(node).size() == 0) {
2027 nodeProps.remove(node);
2032 public Status saveConfiguration() {
2033 return saveSwitchConfig();
2037 * Creates a Name/Tier/Bandwidth Property object based on given property
2038 * name and value. Other property types are not supported yet.
2041 * Name of the Property
2043 * Value of the Property
2044 * @return {@link org.opendaylight.controller.sal.core.Property}
2047 public Property createProperty(String propName, String propValue) {
2048 if (propName == null) {
2049 log.debug("propName is null");
2052 if (propValue == null) {
2053 log.debug("propValue is null");
2058 if (propName.equalsIgnoreCase(Description.propertyName)) {
2059 return new Description(propValue);
2060 } else if (propName.equalsIgnoreCase(Tier.TierPropName)) {
2061 int tier = Integer.parseInt(propValue);
2062 return new Tier(tier);
2063 } else if (propName.equalsIgnoreCase(Bandwidth.BandwidthPropName)) {
2064 long bw = Long.parseLong(propValue);
2065 return new Bandwidth(bw);
2066 } else if (propName.equalsIgnoreCase(ForwardingMode.name)) {
2067 int mode = Integer.parseInt(propValue);
2068 return new ForwardingMode(mode);
2070 log.debug("Not able to create {} property", propName);
2072 } catch (Exception e) {
2073 log.debug("createProperty caught exception {}", e.getMessage());
2080 public String getNodeDescription(Node node) {
2081 // Check first if user configured a name
2082 SwitchConfig config = getSwitchConfig(node.toString());
2083 if (config != null) {
2084 String configuredDesc = config.getNodeDescription();
2085 if (configuredDesc != null && !configuredDesc.isEmpty()) {
2086 return configuredDesc;
2090 // No name configured by user, get the node advertised name
2091 Description desc = (Description) getNodeProp(node,
2092 Description.propertyName);
2093 return (desc == null /* || desc.getValue().equalsIgnoreCase("none") */) ? ""