Merge "ISSUE Opendaylight controller to get node description from OF description...
[controller.git] / opendaylight / switchmanager / src / main / java / org / opendaylight / controller / switchmanager / internal / SwitchManagerImpl.java
1
2 /*
3  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
4  *
5  * This program and the accompanying materials are made available under the
6  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
7  * and is available at http://www.eclipse.org/legal/epl-v10.html
8  */
9
10 package org.opendaylight.controller.switchmanager.internal;
11
12 import java.io.FileNotFoundException;
13 import java.io.IOException;
14 import java.io.ObjectInputStream;
15 import java.net.InetAddress;
16 import java.net.NetworkInterface;
17 import java.net.SocketException;
18 import java.util.ArrayList;
19 import java.util.Collections;
20 import java.util.Date;
21 import java.util.Dictionary;
22 import java.util.EnumSet;
23 import java.util.Enumeration;
24 import java.util.HashMap;
25 import java.util.HashSet;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Set;
29 import java.util.concurrent.ConcurrentHashMap;
30 import java.util.concurrent.ConcurrentMap;
31 import java.util.concurrent.CopyOnWriteArrayList;
32
33 import org.apache.felix.dm.Component;
34 import org.eclipse.osgi.framework.console.CommandInterpreter;
35 import org.eclipse.osgi.framework.console.CommandProvider;
36 import org.opendaylight.controller.clustering.services.CacheConfigException;
37 import org.opendaylight.controller.clustering.services.CacheExistException;
38 import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
39 import org.opendaylight.controller.clustering.services.IClusterContainerServices;
40 import org.opendaylight.controller.clustering.services.IClusterServices;
41 import org.opendaylight.controller.configuration.IConfigurationContainerAware;
42 import org.opendaylight.controller.sal.core.Bandwidth;
43 import org.opendaylight.controller.sal.core.Config;
44 import org.opendaylight.controller.sal.core.Description;
45 import org.opendaylight.controller.sal.core.Name;
46 import org.opendaylight.controller.sal.core.Node;
47 import org.opendaylight.controller.sal.core.NodeConnector;
48 import org.opendaylight.controller.sal.core.NodeConnector.NodeConnectorIDType;
49 import org.opendaylight.controller.sal.core.Property;
50 import org.opendaylight.controller.sal.core.State;
51 import org.opendaylight.controller.sal.core.Tier;
52 import org.opendaylight.controller.sal.core.UpdateType;
53 import org.opendaylight.controller.sal.inventory.IInventoryService;
54 import org.opendaylight.controller.sal.inventory.IListenInventoryUpdates;
55 import org.opendaylight.controller.sal.utils.StatusCode;
56 import org.opendaylight.controller.sal.utils.GlobalConstants;
57 import org.opendaylight.controller.sal.utils.IObjectReader;
58 import org.opendaylight.controller.sal.utils.NodeCreator;
59 import org.opendaylight.controller.sal.utils.ObjectReader;
60 import org.opendaylight.controller.sal.utils.ObjectWriter;
61 import org.opendaylight.controller.sal.utils.ServiceHelper;
62 import org.opendaylight.controller.sal.utils.Status;
63 import org.opendaylight.controller.switchmanager.IInventoryListener;
64 import org.opendaylight.controller.switchmanager.ISpanAware;
65 import org.opendaylight.controller.switchmanager.ISwitchManager;
66 import org.opendaylight.controller.switchmanager.ISwitchManagerAware;
67 import org.opendaylight.controller.switchmanager.SpanConfig;
68 import org.opendaylight.controller.switchmanager.Subnet;
69 import org.opendaylight.controller.switchmanager.SubnetConfig;
70 import org.opendaylight.controller.switchmanager.Switch;
71 import org.opendaylight.controller.switchmanager.SwitchConfig;
72 import org.osgi.framework.BundleContext;
73 import org.osgi.framework.FrameworkUtil;
74 import org.slf4j.Logger;
75 import org.slf4j.LoggerFactory;
76
77 /**
78  * The class describes SwitchManager which is the central repository of all the
79  * inventory data including nodes, node connectors, properties attached, Layer3
80  * configurations, Span configurations, node configurations, network device
81  * representations viewed by Controller Web applications. One SwitchManager
82  * instance per container of the network. All the node/nodeConnector properties
83  * are maintained in the default container only.
84  */
85 public class SwitchManagerImpl implements ISwitchManager,
86         IConfigurationContainerAware, IObjectReader,
87         ICacheUpdateAware<Long, String>, IListenInventoryUpdates,
88         CommandProvider {
89     private static Logger log = LoggerFactory
90             .getLogger(SwitchManagerImpl.class);
91     private static String ROOT = GlobalConstants.STARTUPHOME.toString();
92     private static final String SAVE = "Save";
93     private String subnetFileName = null, spanFileName = null,
94             switchConfigFileName = null;
95     private List<NodeConnector> spanNodeConnectors = new CopyOnWriteArrayList<NodeConnector>();
96     private ConcurrentMap<InetAddress, Subnet> subnets; // set of Subnets keyed by the InetAddress
97     private ConcurrentMap<String, SubnetConfig> subnetsConfigList;
98     private ConcurrentMap<Integer, SpanConfig> spanConfigList;
99     private ConcurrentMap<String, SwitchConfig> nodeConfigList; // manually configured parameters for the node, like name and tier
100     private ConcurrentMap<Long, String> configSaveEvent;
101     private ConcurrentMap<Node, Map<String, Property>> nodeProps; // properties are maintained in default container only
102     private ConcurrentMap<NodeConnector, Map<String, Property>> nodeConnectorProps; // properties are maintained in default container only
103     private ConcurrentMap<Node, Map<String, NodeConnector>> nodeConnectorNames;
104     private IInventoryService inventoryService;
105     private Set<ISwitchManagerAware> switchManagerAware = Collections
106             .synchronizedSet(new HashSet<ISwitchManagerAware>());
107     private Set<IInventoryListener> inventoryListeners = Collections
108             .synchronizedSet(new HashSet<IInventoryListener>());
109     private Set<ISpanAware> spanAware = Collections
110             .synchronizedSet(new HashSet<ISpanAware>());
111     private byte[] MAC;
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     
118     public enum ReasonCode {
119         SUCCESS("Success"), FAILURE("Failure"), INVALID_CONF(
120                 "Invalid Configuration"), EXIST("Entry Already Exist"), CONFLICT(
121                 "Configuration Conflict with Existing Entry");
122
123         private String name;
124
125         private ReasonCode(String name) {
126             this.name = name;
127         }
128
129         public String toString() {
130             return name;
131         }
132     }
133
134     public void notifySubnetChange(Subnet sub, boolean add) {
135         synchronized (switchManagerAware) {
136             for (Object subAware : switchManagerAware) {
137                 try {
138                     ((ISwitchManagerAware) subAware).subnetNotify(sub, add);
139                 } catch (Exception e) {
140                     log.error("Failed to notify Subnet change", e);
141                 }
142             }
143         }
144     }
145
146     public void notifySpanPortChange(Node node, List<NodeConnector> ports,
147             boolean add) {
148         synchronized (spanAware) {
149             for (Object sa : spanAware) {
150                 try {
151                     ((ISpanAware) sa).spanUpdate(node, ports, add);
152                 } catch (Exception e) {
153                     log.error("Failed to notify Span Interface change", e);
154                 }
155             }
156         }
157     }
158
159     private void notifyModeChange(Node node, boolean proactive) {
160         synchronized (switchManagerAware) {
161             for (ISwitchManagerAware service : switchManagerAware) {
162                 try {
163                     service.modeChangeNotify(node, proactive);
164                 } catch (Exception e) {
165                     log.error("Failed to notify Subnet change", e);
166                 }
167             }
168         }
169     }
170
171     public void startUp() {
172         // Initialize configuration file names
173         subnetFileName = ROOT + "subnets" + this.getContainerName() + ".conf";
174         spanFileName = ROOT + "spanPorts_" + this.getContainerName() + ".conf";
175         switchConfigFileName = ROOT + "switchConfig_" + this.getContainerName()
176                 + ".conf";
177
178         // Instantiate cluster synced variables
179         allocateCaches();
180         retrieveCaches();
181
182         /*
183          * Read startup and build database if we have not already gotten the
184          * configurations synced from another node
185          */
186         if (subnetsConfigList.isEmpty())
187             loadSubnetConfiguration();
188         if (spanConfigList.isEmpty())
189             loadSpanConfiguration();
190         if (nodeConfigList.isEmpty())
191             loadSwitchConfiguration();
192
193         MAC = getHardwareMAC();
194     }
195
196     public void shutDown() {
197         destroyCaches(this.getContainerName());
198     }
199
200     @SuppressWarnings("deprecation")
201         private void allocateCaches() {
202         if (this.clusterContainerService == null) {
203             log.info("un-initialized clusterContainerService, can't create cache");
204             return;
205         }
206
207         try {
208             clusterContainerService.createCache(
209                     "switchmanager.subnetsConfigList", EnumSet
210                             .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", EnumSet
219                             .of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
220             clusterContainerService.createCache("switchmanager.nodeProps",
221                     EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
222             clusterContainerService.createCache(
223                     "switchmanager.nodeConnectorProps", EnumSet
224                             .of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
225             clusterContainerService.createCache(
226                     "switchmanager.nodeConnectorNames", EnumSet
227                             .of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
228         } catch (CacheConfigException cce) {
229             log.error("\nCache configuration invalid - check cache mode");
230         } catch (CacheExistException ce) {
231             log.error("\nCache already exits - destroy and recreate if needed");
232         }
233     }
234
235     @SuppressWarnings({ "unchecked", "deprecation" })
236     private void retrieveCaches() {
237         if (this.clusterContainerService == null) {
238             log
239                     .info("un-initialized clusterContainerService, can't create cache");
240             return;
241         }
242
243         subnetsConfigList = (ConcurrentMap<String, SubnetConfig>) clusterContainerService
244                 .getCache("switchmanager.subnetsConfigList");
245         if (subnetsConfigList == null) {
246             log.error("\nFailed to get cache for subnetsConfigList");
247         }
248
249         spanConfigList = (ConcurrentMap<Integer, SpanConfig>) clusterContainerService
250                 .getCache("switchmanager.spanConfigList");
251         if (spanConfigList == null) {
252             log.error("\nFailed to get cache for spanConfigList");
253         }
254
255         nodeConfigList = (ConcurrentMap<String, SwitchConfig>) clusterContainerService
256                 .getCache("switchmanager.nodeConfigList");
257         if (nodeConfigList == null) {
258             log.error("\nFailed to get cache for nodeConfigList");
259         }
260
261         subnets = (ConcurrentMap<InetAddress, Subnet>) clusterContainerService
262                 .getCache("switchmanager.subnets");
263         if (subnets == null) {
264             log.error("\nFailed to get cache for subnets");
265         }
266
267         configSaveEvent = (ConcurrentMap<Long, String>) clusterContainerService
268                 .getCache("switchmanager.configSaveEvent");
269         if (configSaveEvent == null) {
270             log.error("\nFailed to get cache for configSaveEvent");
271         }
272
273         nodeProps = (ConcurrentMap<Node, Map<String, Property>>) clusterContainerService
274                 .getCache("switchmanager.nodeProps");
275         if (nodeProps == null) {
276             log.error("\nFailed to get cache for nodeProps");
277         }
278
279         nodeConnectorProps = (ConcurrentMap<NodeConnector, Map<String, Property>>) clusterContainerService
280                 .getCache("switchmanager.nodeConnectorProps");
281         if (nodeConnectorProps == null) {
282             log.error("\nFailed to get cache for nodeConnectorProps");
283         }
284
285         nodeConnectorNames = (ConcurrentMap<Node, Map<String, NodeConnector>>) clusterContainerService
286                 .getCache("switchmanager.nodeConnectorNames");
287         if (nodeConnectorNames == null) {
288             log.error("\nFailed to get cache for nodeConnectorNames");
289         }
290     }
291
292     void nonClusterObjectCreate() {
293         subnetsConfigList = new ConcurrentHashMap<String, SubnetConfig>();
294         spanConfigList = new ConcurrentHashMap<Integer, SpanConfig>();
295         nodeConfigList = new ConcurrentHashMap<String, SwitchConfig>();
296         subnets = new ConcurrentHashMap<InetAddress, Subnet>();
297         configSaveEvent = new ConcurrentHashMap<Long, String>();
298         nodeProps = new ConcurrentHashMap<Node, Map<String, Property>>();
299         nodeConnectorProps = new ConcurrentHashMap<NodeConnector, Map<String, Property>>();
300         nodeConnectorNames = new ConcurrentHashMap<Node, Map<String, NodeConnector>>();
301     }
302
303     @SuppressWarnings("deprecation")
304         private void destroyCaches(String container) {
305         if (this.clusterContainerService == null) {
306             log
307                     .info("un-initialized clusterContainerService, can't create cache");
308             return;
309         }
310
311         clusterContainerService.destroyCache("switchmanager.subnetsConfigList");
312         clusterContainerService.destroyCache("switchmanager.spanConfigList");
313         clusterContainerService.destroyCache("switchmanager.nodeConfigList");
314         clusterContainerService.destroyCache("switchmanager.subnets");
315         clusterContainerService.destroyCache("switchmanager.configSaveEvent");
316         clusterContainerService.destroyCache("switchmanager.nodeProps");
317         clusterContainerService
318                 .destroyCache("switchmanager.nodeConnectorProps");
319         clusterContainerService
320                 .destroyCache("switchmanager.nodeConnectorNames");
321         nonClusterObjectCreate();
322     }
323
324     public List<SubnetConfig> getSubnetsConfigList() {
325         return new ArrayList<SubnetConfig>(subnetsConfigList.values());
326     }
327
328     @Override
329     public SubnetConfig getSubnetConfig(String subnet) {
330         return subnetsConfigList.get(subnet);
331     }
332
333     private List<SpanConfig> getSpanConfigList(Node node) {
334         List<SpanConfig> confList = new ArrayList<SpanConfig>();
335         String nodeId = node.toString();
336         for (SpanConfig conf : spanConfigList.values()) {
337             if (conf.matchNode(nodeId)) {
338                 confList.add(conf);
339             }
340         }
341         return confList;
342     }
343
344     public List<SwitchConfig> getNodeConfigList() {
345         return new ArrayList<SwitchConfig>(nodeConfigList.values());
346     }
347
348     public SwitchConfig getSwitchConfig(String switchId) {
349         return nodeConfigList.get(switchId);
350     }
351
352     public Switch getSwitchByNode(Node node) {
353         Switch sw = new Switch(node);
354         sw.setNode(node);
355
356         Set<NodeConnector> ncSet = getPhysicalNodeConnectors(node);
357         sw.setNodeConnectors(ncSet);
358
359         List<NodeConnector> ncList = new ArrayList<NodeConnector>();
360         for (NodeConnector nodeConnector : ncSet) {
361             if (spanNodeConnectors.contains(nodeConnector)) {
362                 ncList.add(nodeConnector);
363             }
364         }
365         sw.addSpanPorts(ncList);
366
367         return sw;
368     }
369
370     public List<Switch> getNetworkDevices() {
371         Set<Node> nodeSet = getNodes();
372         List<Switch> swList = new ArrayList<Switch>();
373         if (nodeSet != null) {
374             for (Node node : nodeSet) {
375                 swList.add(getSwitchByNode(node));
376             }
377         }
378
379         return swList;
380     }
381
382     private void updateConfig(SubnetConfig conf, boolean add) {
383         if (add) {
384             subnetsConfigList.put(conf.getName(), conf);
385         } else {
386             subnetsConfigList.remove(conf.getName());
387         }
388     }
389
390     private void updateDatabase(SubnetConfig conf, boolean add) {
391         Subnet subnet = subnets.get(conf.getIPnum());
392         if (add) {
393             if (subnet == null) {
394                 subnet = new Subnet(conf);
395             }
396             // In case of API3 call we may receive the ports along with the
397             // subnet creation
398             if (!conf.isGlobal()) {
399                 Set<NodeConnector> sp = conf.getSubnetNodeConnectors();
400                 subnet.addNodeConnectors(sp);
401             }
402             subnets.put(conf.getIPnum(), subnet);
403         } else { // This is the deletion of the whole subnet
404             if (subnet == null)
405                 return;
406             subnets.remove(conf.getIPnum());
407         }
408     }
409
410     private Status semanticCheck(SubnetConfig conf) {
411         Subnet newSubnet = new Subnet(conf);
412         Set<InetAddress> IPs = subnets.keySet();
413         if (IPs == null) {
414                 return new Status(StatusCode.SUCCESS, null);
415         }
416         for (InetAddress i : IPs) {
417             Subnet existingSubnet = subnets.get(i);
418             if ((existingSubnet != null)
419                     && !existingSubnet.isMutualExclusive(newSubnet)) {
420                 return new Status(StatusCode.CONFLICT, null);
421             }
422         }
423         return new Status(StatusCode.SUCCESS, null);
424     }
425
426     private Status addRemoveSubnet(SubnetConfig conf, boolean add) {
427         // Valid config check
428         if (!conf.isValidConfig()) {
429                 String msg = "Invalid Subnet configuration";
430             log.warn(msg);
431             return new Status(StatusCode.BADREQUEST, msg);
432         }
433
434         if (add) {
435             // Presence check
436             if (subnetsConfigList.containsKey(conf.getName())) {
437                 return new Status(StatusCode.CONFLICT, 
438                                 "Same subnet config already exists");
439             }
440             // Semantyc check
441             Status rc = semanticCheck(conf);
442             if (!rc.isSuccess()) {
443                 return rc;
444             }
445         }
446         // Update Configuration
447         updateConfig(conf, add);
448
449         // Update Database
450         updateDatabase(conf, add);
451
452         return new Status(StatusCode.SUCCESS, null);
453     }
454
455     /**
456      * Adds Subnet configured in GUI or API3
457      */
458     public Status addSubnet(SubnetConfig conf) {
459         return this.addRemoveSubnet(conf, true);
460     }
461
462     @Override
463     public Status removeSubnet(SubnetConfig conf) {
464         return this.addRemoveSubnet(conf, false);
465     }
466
467     @Override
468     public Status removeSubnet(String name) {
469         SubnetConfig conf = subnetsConfigList.get(name);
470         if (conf == null) {
471             return new Status(StatusCode.SUCCESS, "Subnet not present");
472         }
473         return this.addRemoveSubnet(conf, false);
474     }
475
476     @Override
477     public Status addPortsToSubnet(String name, String switchPorts) {
478         // Update Configuration
479         SubnetConfig conf = subnetsConfigList.get(name);
480         if (conf == null) {
481             return new Status(StatusCode.NOTFOUND, "Subnet does not exist");
482         }
483         if (!conf.isValidSwitchPort(switchPorts)) {
484                 return new Status(StatusCode.BADREQUEST, "Invalid switchports");
485         }
486
487         conf.addNodeConnectors(switchPorts);
488
489         // Update Database
490         Subnet sub = subnets.get(conf.getIPnum());
491         Set<NodeConnector> sp = conf.getNodeConnectors(switchPorts);
492         sub.addNodeConnectors(sp);
493         return new Status(StatusCode.SUCCESS, null);
494     }
495
496     @Override
497     public Status removePortsFromSubnet(String name, String switchPorts) {
498         // Update Configuration
499         SubnetConfig conf = subnetsConfigList.get(name);
500         if (conf == null) {
501                 return new Status(StatusCode.NOTFOUND, "Subnet does not exist");
502         }
503         conf.removeNodeConnectors(switchPorts);
504
505         // Update Database
506         Subnet sub = subnets.get(conf.getIPnum());
507         Set<NodeConnector> sp = conf.getNodeConnectors(switchPorts);
508         sub.deleteNodeConnectors(sp);
509         return new Status(StatusCode.SUCCESS, null);
510     }
511
512     public String getContainerName() {
513         if (containerName == null) {
514             return GlobalConstants.DEFAULT.toString();
515         }
516         return containerName;
517     }
518
519     @Override
520     public Subnet getSubnetByNetworkAddress(InetAddress networkAddress) {
521         Subnet sub;
522         Set<InetAddress> indices = subnets.keySet();
523         for (InetAddress i : indices) {
524             sub = subnets.get(i);
525             if (sub.isSubnetOf(networkAddress)) {
526                 return sub;
527             }
528         }
529         return null;
530     }
531
532     @Override
533     public Object readObject(ObjectInputStream ois)
534             throws FileNotFoundException, IOException, ClassNotFoundException {
535         // Perform the class deserialization locally, from inside the package
536         // where the class is defined
537         return ois.readObject();
538     }
539
540     @SuppressWarnings("unchecked")
541     private void loadSubnetConfiguration() {
542         ObjectReader objReader = new ObjectReader();
543         ConcurrentMap<Integer, SubnetConfig> confList = (ConcurrentMap<Integer, SubnetConfig>) objReader
544                 .read(this, subnetFileName);
545
546         if (confList == null) {
547             return;
548         }
549
550         for (SubnetConfig conf : confList.values()) {
551             addSubnet(conf);
552         }
553     }
554
555     @SuppressWarnings("unchecked")
556     private void loadSpanConfiguration() {
557         ObjectReader objReader = new ObjectReader();
558         ConcurrentMap<Integer, SpanConfig> confList = (ConcurrentMap<Integer, SpanConfig>) objReader
559                 .read(this, spanFileName);
560
561         if (confList == null) {
562             return;
563         }
564
565         for (SpanConfig conf : confList.values()) {
566             addSpanConfig(conf);
567         }
568     }
569
570     @SuppressWarnings("unchecked")
571     private void loadSwitchConfiguration() {
572         ObjectReader objReader = new ObjectReader();
573         ConcurrentMap<String, SwitchConfig> confList = (ConcurrentMap<String, SwitchConfig>) objReader
574                 .read(this, switchConfigFileName);
575
576         if (confList == null) {
577             return;
578         }
579
580         for (SwitchConfig conf : confList.values()) {
581             updateSwitchConfig(conf);
582         }
583     }
584
585     public void updateSwitchConfig(SwitchConfig cfgObject) {
586         boolean modeChange = false;
587
588         SwitchConfig sc = nodeConfigList.get(cfgObject.getNodeId());
589         if ((sc == null) || !cfgObject.getMode().equals(sc.getMode())) {
590             modeChange = true;
591         }
592
593         nodeConfigList.put(cfgObject.getNodeId(), cfgObject);
594         try {
595             // update default container only
596             if (isDefaultContainer) {
597                 String nodeId = cfgObject.getNodeId();
598                 Node node = Node.fromString(nodeId);
599                 Map<String, Property> propMap;
600                 if (nodeProps.get(node) != null) {
601                     propMap = nodeProps.get(node);
602                 } else {
603                     propMap = new HashMap<String, Property>();
604                 }
605                 Property desc = new Description(cfgObject.getNodeDescription());
606                 propMap.put(desc.getName(), desc);
607                 Property tier = new Tier(Integer.parseInt(cfgObject.getTier()));
608                 propMap.put(tier.getName(), tier);
609                 addNodeProps(node, propMap);
610
611                 log.info("Set Node {}'s Mode to {}", nodeId, cfgObject
612                         .getMode());
613
614                 if (modeChange) {
615                     notifyModeChange(node, cfgObject.isProactive());
616                 }
617             }
618         } catch (Exception e) {
619             log.debug("updateSwitchConfig: {}", e);
620         }
621     }
622
623     @Override
624     public Status saveSwitchConfig() {
625         // Publish the save config event to the cluster nodes
626         configSaveEvent.put(new Date().getTime(), SAVE);
627         return saveSwitchConfigInternal();
628     }
629
630     public Status saveSwitchConfigInternal() {
631         Status retS = null, retP = null;
632         ObjectWriter objWriter = new ObjectWriter();
633
634         retS = objWriter.write(new ConcurrentHashMap<String, SubnetConfig>(
635                 subnetsConfigList), subnetFileName);
636         retP = objWriter.write(new ConcurrentHashMap<Integer, SpanConfig>(
637                 spanConfigList), spanFileName);
638         retS = objWriter.write(new ConcurrentHashMap<String, SwitchConfig>(
639                 nodeConfigList), switchConfigFileName);
640
641         if (retS.equals(retP)) {
642             if (retS.isSuccess()) {
643                 return retS;
644             } else {
645                 return new Status(StatusCode.INTERNALERROR, "Save failed");
646             }
647         } else {
648             return new Status(StatusCode.INTERNALERROR, "Partial save failure");
649         }
650     }
651
652     @Override
653     public List<SpanConfig> getSpanConfigList() {
654         return new ArrayList<SpanConfig>(spanConfigList.values());
655     }
656
657     @Override
658     public Status addSpanConfig(SpanConfig conf) {
659         // Valid config check
660         if (!conf.isValidConfig()) {
661                 String msg = "Invalid Span configuration";
662             log.warn(msg);
663             return new Status(StatusCode.BADREQUEST, msg);
664         }
665
666         // Presence check
667         if (spanConfigList.containsKey(conf.hashCode())) {
668                 return new Status(StatusCode.CONFLICT, "Same span config exists");
669         }
670
671         // Update database and notify clients
672         addSpanPorts(conf.getNode(), conf.getPortArrayList());
673
674         // Update configuration
675         spanConfigList.put(conf.hashCode(), conf);
676
677         return new Status(StatusCode.SUCCESS, null);
678     }
679
680     @Override
681     public Status removeSpanConfig(SpanConfig conf) {
682         removeSpanPorts(conf.getNode(), conf.getPortArrayList());
683
684         // Update configuration
685         spanConfigList.remove(conf.hashCode());
686
687         return new Status(StatusCode.SUCCESS, null);
688     }
689
690     @Override
691     public List<NodeConnector> getSpanPorts(Node node) {
692         List<NodeConnector> ncList = new ArrayList<NodeConnector>();
693
694         for (NodeConnector nodeConnector : spanNodeConnectors) {
695             if (nodeConnector.getNode().equals(node)) {
696                 ncList.add(nodeConnector);
697             }
698         }
699         return ncList;
700     }
701
702     @Override
703     public void entryCreated(Long key, String cacheName, boolean local) {
704     }
705
706     @Override
707     public void entryUpdated(Long key, String new_value, String cacheName,
708             boolean originLocal) {
709         saveSwitchConfigInternal();
710     }
711
712     @Override
713     public void entryDeleted(Long key, String cacheName, boolean originLocal) {
714     }
715
716     private void addNode(Node node, Set<Property> props) {
717         log.trace("{} added", node);
718         if (nodeProps == null) {
719             return;
720         }
721
722         Map<String, Property> propMap;
723         if (nodeProps.get(node) != null) {
724             propMap = nodeProps.get(node);
725         } else {
726             propMap = new HashMap<String, Property>();
727         }
728
729         // copy node properties from plugin
730         if (props != null) {
731             for (Property prop : props) {
732                 propMap.put(prop.getName(), prop);
733             }
734         }
735
736         // copy node properties from config
737         boolean proactiveForwarding = false;
738         if (nodeConfigList != null) {
739             String nodeId = node.getNodeIDString();
740             for (SwitchConfig conf : nodeConfigList.values()) {
741                 if (conf.getNodeId().equals(nodeId)) {
742                     Property description = new Description(conf.getNodeDescription());
743                     propMap.put(description.getName(), description);
744                     Property tier = new Tier(Integer.parseInt(conf.getTier()));
745                     propMap.put(tier.getName(), tier);
746                     proactiveForwarding = conf.isProactive();
747                     break;
748                 }
749             }
750         }
751         addNodeProps(node, propMap);
752
753         // check if span ports are configed
754         addSpanPorts(node);
755
756         // notify node listeners
757         notifyNode(node, UpdateType.ADDED, propMap);
758         
759         // notify proactive mode forwarding
760         if (proactiveForwarding) {
761                 notifyModeChange(node, true);
762         }
763     }
764
765     private void removeNode(Node node) {
766         log.trace("{} removed", node);
767         if (nodeProps == null)
768             return;
769         nodeProps.remove(node);
770
771         // check if span ports need to be cleaned up
772         removeSpanPorts(node);
773
774         /* notify node listeners */
775         notifyNode(node, UpdateType.REMOVED, null);
776     }
777
778     private void updateNode(Node node, Set<Property> props) {
779         log.trace("{} updated", node);
780         if (nodeProps == null) {
781             return;
782         }
783
784         Map<String, Property> propMap;
785         if (nodeProps.get(node) != null) {
786             propMap = nodeProps.get(node);
787         } else {
788             propMap = new HashMap<String, Property>();
789         }
790
791         // copy node properties from plugin
792         if (props != null) {
793             for (Property prop : props) {
794                 propMap.put(prop.getName(), prop);
795             }
796         }
797         addNodeProps(node, propMap);
798
799         /* notify node listeners */
800         notifyNode(node, UpdateType.CHANGED, propMap);
801     }
802
803     @Override
804     public void updateNode(Node node, UpdateType type, Set<Property> props) {
805         switch (type) {
806         case ADDED:
807             addNode(node, props);
808             break;
809         case CHANGED:
810             updateNode(node, props);
811             break;
812         case REMOVED:
813             removeNode(node);
814             break;
815         default:
816             break;
817         }
818     }
819
820     @Override
821     public void updateNodeConnector(NodeConnector nodeConnector,
822             UpdateType type, Set<Property> props) {
823         Node node = nodeConnector.getNode();
824         Map<String, Property> propMap = new HashMap<String, Property>();
825
826         log.trace("{} {}", nodeConnector, type);
827
828         if (nodeConnectorProps == null) {
829             return;
830         }
831
832         switch (type) {
833         case ADDED:
834         case CHANGED:
835             if (props != null) {
836                 for (Property prop : props) {
837                     addNodeConnectorProp(nodeConnector, prop);
838                     propMap.put(prop.getName(), prop);
839                 }
840             } else {
841                 addNodeConnectorProp(nodeConnector, null);
842                 addNodeProps(node, null);
843             }
844
845             // check if span is configed
846             addSpanPort(nodeConnector);
847             break;
848         case REMOVED:
849             removeNodeConnectorAllProps(nodeConnector);
850             removeNodeProps(node);
851
852             // clean up span config
853             removeSpanPort(nodeConnector);
854             break;
855         default:
856             break;
857         }
858
859         notifyNodeConnector(nodeConnector, type, propMap);
860     }
861
862     @Override
863     public Set<Node> getNodes() {
864         return (nodeProps != null) ? new HashSet<Node>(nodeProps.keySet())
865                 : null;
866     }
867
868     /*
869      * test utility function which assumes all nodes are OF nodes
870      */
871     private Node getNode(Long id) {
872         Set<Node> nodes = getNodes();
873         if (nodes != null) {
874             for (Node node : nodes) {
875                 if (id.equals((Long)node.getID())) {
876                     return node;
877                 }
878             }
879         }
880         return null;
881     }
882
883     /*
884      * Returns a copy of a list of properties for a given node
885      *
886      * (non-Javadoc)
887      * @see org.opendaylight.controller.switchmanager.ISwitchManager#getNodeProps(org.opendaylight.controller.sal.core.Node)
888      */
889     @Override
890     public Map<String, Property> getNodeProps(Node node) {
891         if (isDefaultContainer) {
892             Map<String, Property> rv = null;
893             if (this.nodeProps != null) {
894                 rv = this.nodeProps.get(node);
895                 if (rv != null) {
896                     /* make a copy of it */
897                     rv = new HashMap<String, Property>(rv);
898                 }
899             }
900             return rv;
901         } else {
902             // get it from default container
903             ISwitchManager defaultSwitchManager = (ISwitchManager) ServiceHelper
904                     .getInstance(ISwitchManager.class, GlobalConstants.DEFAULT
905                             .toString(), this);
906             return defaultSwitchManager.getNodeProps(node);
907         }
908     }
909
910     @Override
911     public Property getNodeProp(Node node, String propName) {
912         Map<String, Property> propMap = getNodeProps(node);
913         return (propMap != null) ? propMap.get(propName) : null;
914     }
915
916     @Override
917     public void setNodeProp(Node node, Property prop) {
918         /* Get a copy of the property map */
919         Map<String, Property> propMap = getNodeProps(node);
920         if (propMap == null)
921             return;
922
923         propMap.put(prop.getName(), prop);
924         this.nodeProps.put(node, propMap);
925     }
926
927     @Override
928     public Status removeNodeProp(Node node, String propName) {
929         Map<String, Property> propMap = getNodeProps(node);
930         if (propMap != null) {
931                 propMap.remove(propName);
932                 this.nodeProps.put(node, propMap);
933         }
934         return new Status(StatusCode.SUCCESS, null);
935     }
936
937     @Override
938     public Status removeNodeAllProps(Node node) {
939         this.nodeProps.remove(node);
940         return new Status(StatusCode.SUCCESS, null);
941     }
942
943     @Override
944     public Set<NodeConnector> getUpNodeConnectors(Node node) {
945         if (nodeConnectorProps == null)
946             return null;
947
948         Set<NodeConnector> nodeConnectorSet = new HashSet<NodeConnector>();
949         for (NodeConnector nodeConnector : nodeConnectorProps.keySet()) {
950             if (((Long) nodeConnector.getNode().getID())
951                     .longValue() != (Long) node.getID())
952                 continue;
953             if (isNodeConnectorEnabled(nodeConnector))
954                 nodeConnectorSet.add(nodeConnector);
955         }
956
957         return nodeConnectorSet;
958     }
959
960     @Override
961     public Set<NodeConnector> getNodeConnectors(Node node) {
962         if (nodeConnectorProps == null)
963             return null;
964
965         Set<NodeConnector> nodeConnectorSet = new HashSet<NodeConnector>();
966         for (NodeConnector nodeConnector : nodeConnectorProps.keySet()) {
967             if (((Long) nodeConnector.getNode().getID())
968                     .longValue() != (Long) node.getID())
969                 continue;
970             nodeConnectorSet.add(nodeConnector);
971         }
972
973         return nodeConnectorSet;
974     }
975
976     @Override
977     public Set<NodeConnector> getPhysicalNodeConnectors(Node node) {
978         if (nodeConnectorProps == null)
979             return null;
980
981         Set<NodeConnector> nodeConnectorSet = new HashSet<NodeConnector>();
982         for (NodeConnector nodeConnector : nodeConnectorProps.keySet()) {
983             if (!nodeConnector.getNode().equals(node)
984                     || isSpecial(nodeConnector)) {
985                 continue;
986             }
987             nodeConnectorSet.add(nodeConnector);
988         }
989
990         return nodeConnectorSet;
991     }
992
993     /*
994      * testing utility function which assumes we are dealing with OF Node nodeconnectors only
995      */
996     @SuppressWarnings("unused")
997     private Set<Long> getEnabledNodeConnectorIds(Node node) {
998         Set<Long> ids = new HashSet<Long>();
999         Set<NodeConnector> nodeConnectors = getUpNodeConnectors(node);
1000
1001         if (nodeConnectors != null) {
1002             for (NodeConnector nodeConnector : nodeConnectors) {
1003                 ids.add((Long) nodeConnector.getID());
1004             }
1005         }
1006
1007         return ids;
1008     }
1009
1010     @Override
1011     public Map<String, Property> getNodeConnectorProps(
1012             NodeConnector nodeConnector) {
1013         if (isDefaultContainer) {
1014             Map<String, Property> rv = null;
1015             if (this.nodeConnectorProps != null) {
1016                 rv = this.nodeConnectorProps.get(nodeConnector);
1017                 if (rv != null) {
1018                     rv = new HashMap<String, Property>(rv);
1019                 }
1020             }
1021             return rv;
1022         } else {
1023             // get it from default container
1024             ISwitchManager defaultSwitchManager = (ISwitchManager) ServiceHelper
1025                     .getInstance(ISwitchManager.class, GlobalConstants.DEFAULT
1026                             .toString(), this);
1027             return defaultSwitchManager.getNodeConnectorProps(nodeConnector);
1028         }
1029     }
1030
1031     @Override
1032     public Property getNodeConnectorProp(NodeConnector nodeConnector,
1033             String propName) {
1034         Map<String, Property> propMap = getNodeConnectorProps(nodeConnector);
1035         return (propMap != null) ? propMap.get(propName) : null;
1036     }
1037
1038     private byte[] getHardwareMAC() {
1039         Enumeration<NetworkInterface> nis;
1040         try {
1041             nis = NetworkInterface.getNetworkInterfaces();
1042         } catch (SocketException e1) {
1043             e1.printStackTrace();
1044             return null;
1045         }
1046         byte[] MAC = null;
1047         for (; nis.hasMoreElements();) {
1048             NetworkInterface ni = nis.nextElement();
1049             try {
1050                 MAC = ni.getHardwareAddress();
1051             } catch (SocketException e) {
1052                 e.printStackTrace();
1053             }
1054             if (MAC != null) {
1055                 return MAC;
1056             }
1057         }
1058         return null;
1059     }
1060
1061     @Override
1062     public byte[] getControllerMAC() {
1063         return MAC;
1064     }
1065
1066     @Override
1067     public boolean isHostRefreshEnabled() {
1068         return hostRefresh;
1069     }
1070
1071     @Override
1072     public int getHostRetryCount() {
1073         return hostRetryCount;
1074     }
1075
1076     @Override
1077     public NodeConnector getNodeConnector(Node node, String nodeConnectorName) {
1078         if (nodeConnectorNames == null)
1079             return null;
1080
1081         Map<String, NodeConnector> map = nodeConnectorNames.get(node);
1082         if (map == null)
1083             return null;
1084
1085         return map.get(nodeConnectorName);
1086     }
1087
1088     /**
1089      * Adds a node connector and its property if any
1090      * 
1091      * @param nodeConnector {@link org.opendaylight.controller.sal.core.NodeConnector}
1092      * @param propName          name of {@link org.opendaylight.controller.sal.core.Property}
1093      * @return success or failed reason
1094      */
1095     @Override
1096     public Status addNodeConnectorProp(NodeConnector nodeConnector, Property prop) {
1097         Map<String, Property> propMap = getNodeConnectorProps(nodeConnector);
1098
1099         if (propMap == null) {
1100             propMap = new HashMap<String, Property>();
1101         }
1102
1103         // Just add the nodeConnector if prop is not available (in a non-default container)
1104         if (prop == null) {
1105             nodeConnectorProps.put(nodeConnector, propMap);
1106             return new Status(StatusCode.SUCCESS, null);
1107         }
1108
1109         propMap.put(prop.getName(), prop);
1110         nodeConnectorProps.put(nodeConnector, propMap);
1111
1112         if (prop.getName().equals(Name.NamePropName)) {
1113             if (nodeConnectorNames != null) {
1114                 Node node = nodeConnector.getNode();
1115                 Map<String, NodeConnector> map = nodeConnectorNames.get(node);
1116                 if (map == null) {
1117                     map = new HashMap<String, NodeConnector>();
1118                 }
1119
1120                 map.put(((Name) prop).getValue(), nodeConnector);
1121                 nodeConnectorNames.put(node, map);
1122             }
1123         }
1124
1125         return new Status(StatusCode.SUCCESS, null);
1126     }
1127
1128     /**
1129      * Removes one property of a node connector
1130      * 
1131      * @param nodeConnector {@link org.opendaylight.controller.sal.core.NodeConnector}
1132      * @param propName          name of {@link org.opendaylight.controller.sal.core.Property}
1133      * @return success or failed reason
1134      */
1135     @Override
1136     public Status removeNodeConnectorProp(NodeConnector nodeConnector, String propName) {
1137         Map<String, Property> propMap = getNodeConnectorProps(nodeConnector);
1138
1139         if (propMap == null) {
1140                 /* Nothing to remove */
1141             return new Status(StatusCode.SUCCESS, null);
1142         }
1143
1144         propMap.remove(propName);
1145         nodeConnectorProps.put(nodeConnector, propMap);
1146
1147         if (nodeConnectorNames != null) {
1148             Name name = ((Name) getNodeConnectorProp(nodeConnector,
1149                     Name.NamePropName));
1150             if (name != null) {
1151                 Node node = nodeConnector.getNode();
1152                 Map<String, NodeConnector> map = nodeConnectorNames.get(node);
1153                 if (map != null) {
1154                     map.remove(name.getValue());
1155                     nodeConnectorNames.put(node, map);
1156                 }
1157             }
1158         }
1159
1160         return new Status(StatusCode.SUCCESS, null);
1161     }
1162
1163     /**
1164      * Removes all the properties of a node connector
1165      * 
1166      * @param nodeConnector {@link org.opendaylight.controller.sal.core.NodeConnector}
1167      * @return success or failed reason
1168      */
1169     @Override
1170     public Status removeNodeConnectorAllProps(NodeConnector nodeConnector) {
1171         if (nodeConnectorNames != null) {
1172             Name name = ((Name) getNodeConnectorProp(nodeConnector,
1173                     Name.NamePropName));
1174             if (name != null) {
1175                 Node node = nodeConnector.getNode();
1176                 Map<String, NodeConnector> map = nodeConnectorNames.get(node);
1177                 if (map != null) {
1178                     map.remove(name.getValue());
1179                     nodeConnectorNames.put(node, map);
1180                 }
1181             }
1182         }
1183         nodeConnectorProps.remove(nodeConnector);
1184
1185         return new Status(StatusCode.SUCCESS, null);
1186     }
1187
1188     /**
1189      * Function called by the dependency manager when all the required
1190      * dependencies are satisfied
1191      *
1192      */
1193     void init(Component c) {
1194         Dictionary<?, ?> props = c.getServiceProperties();
1195         if (props != null) {
1196             this.containerName = (String) props.get("containerName");
1197             log.trace("Running containerName:" + this.containerName);
1198         } else {
1199             // In the Global instance case the containerName is empty
1200             this.containerName = "";
1201         }
1202         isDefaultContainer = containerName.equals(GlobalConstants.DEFAULT
1203                 .toString());
1204
1205         startUp();
1206     }
1207
1208     /**
1209      * Function called by the dependency manager when at least one
1210      * dependency become unsatisfied or when the component is shutting
1211      * down because for example bundle is being stopped.
1212      *
1213      */
1214     void destroy() {
1215         shutDown();
1216     }
1217
1218     /**
1219      * Function called by dependency manager after "init ()" is called
1220      * and after the services provided by the class are registered in
1221      * the service registry
1222      *
1223      */
1224     void start() {
1225         // OSGI console
1226         registerWithOSGIConsole();
1227     }
1228
1229     /**
1230      * Function called after registered the
1231      * service in OSGi service registry.
1232      */
1233     void started() {
1234         // solicit for existing inventories
1235         getInventories();
1236     }
1237
1238     /**
1239      * Function called by the dependency manager before the services
1240      * exported by the component are unregistered, this will be
1241      * followed by a "destroy ()" calls
1242      *
1243      */
1244     void stop() {
1245     }
1246
1247     public void setInventoryService(IInventoryService service) {
1248         log.trace("Got inventory service set request {}", service);
1249         this.inventoryService = service;
1250
1251         // solicit for existing inventories
1252         getInventories();
1253     }
1254
1255     public void unsetInventoryService(IInventoryService service) {
1256         log.trace("Got a service UNset request");
1257         this.inventoryService = null;
1258
1259         // clear existing inventories
1260         clearInventories();
1261     }
1262
1263     public void setSwitchManagerAware(ISwitchManagerAware service) {
1264         log.trace("Got inventory service set request {}", service);
1265         if (this.switchManagerAware != null) {
1266             this.switchManagerAware.add(service);
1267         }
1268
1269         // bulk update for newly joined
1270         switchManagerAwareNotify(service);
1271     }
1272
1273     public void unsetSwitchManagerAware(ISwitchManagerAware service) {
1274         log.trace("Got a service UNset request");
1275         if (this.switchManagerAware != null) {
1276             this.switchManagerAware.remove(service);
1277         }
1278     }
1279
1280     public void setInventoryListener(IInventoryListener service) {
1281         log.trace("Got inventory listener set request {}", service);
1282         if (this.inventoryListeners != null) {
1283             this.inventoryListeners.add(service);
1284         }
1285
1286         // bulk update for newly joined
1287         bulkUpdateService(service);
1288     }
1289
1290     public void unsetInventoryListener(IInventoryListener service) {
1291         log.trace("Got a service UNset request");
1292         if (this.inventoryListeners != null) {
1293             this.inventoryListeners.remove(service);
1294         }
1295     }
1296
1297     public void setSpanAware(ISpanAware service) {
1298         log.trace("Got SpanAware set request {}", service);
1299         if (this.spanAware != null) {
1300             this.spanAware.add(service);
1301         }
1302
1303         // bulk update for newly joined
1304         spanAwareNotify(service);
1305     }
1306
1307     public void unsetSpanAware(ISpanAware service) {
1308         log.trace("Got a service UNset request");
1309         if (this.spanAware != null) {
1310             this.spanAware.remove(service);
1311         }
1312     }
1313
1314     void setClusterContainerService(IClusterContainerServices s) {
1315         log.trace("Cluster Service set");
1316         this.clusterContainerService = s;
1317     }
1318
1319     void unsetClusterContainerService(IClusterContainerServices s) {
1320         if (this.clusterContainerService == s) {
1321             log.trace("Cluster Service removed!");
1322             this.clusterContainerService = null;
1323         }
1324     }
1325
1326     private void getInventories() {
1327         if (inventoryService == null) {
1328             log.trace("inventory service not avaiable");
1329             return;
1330         }
1331
1332         nodeProps = this.inventoryService.getNodeProps();
1333         Set<Node> nodeSet = nodeProps.keySet();
1334         if (nodeSet != null) {
1335             for (Node node : nodeSet) {
1336                 addNode(node, null);
1337             }
1338         }
1339
1340         nodeConnectorProps = inventoryService.getNodeConnectorProps();
1341     }
1342
1343     private void clearInventories() {
1344         nodeProps.clear();
1345         nodeConnectorProps.clear();
1346         nodeConnectorNames.clear();
1347         spanNodeConnectors.clear();
1348     }
1349
1350     private void notifyNode(Node node, UpdateType type,
1351             Map<String, Property> propMap) {
1352         synchronized (inventoryListeners) {
1353             for (IInventoryListener service : inventoryListeners) {
1354                 service.notifyNode(node, type, propMap);
1355             }
1356         }
1357     }
1358
1359     private void notifyNodeConnector(NodeConnector nodeConnector,
1360             UpdateType type, Map<String, Property> propMap) {
1361         synchronized (inventoryListeners) {
1362             for (IInventoryListener service : inventoryListeners) {
1363                 service.notifyNodeConnector(nodeConnector, type, propMap);
1364             }
1365         }
1366     }
1367
1368     /*
1369      * For those joined late, bring them up-to-date.
1370      */
1371     private void switchManagerAwareNotify(ISwitchManagerAware service) {
1372         for (Subnet sub : subnets.values()) {
1373             service.subnetNotify(sub, true);
1374         }
1375
1376         for (Node node : getNodes()) {
1377             SwitchConfig sc = getSwitchConfig(node.toString());
1378             if ((sc != null) && isDefaultContainer) {
1379                 service.modeChangeNotify(node, sc.isProactive());
1380             }
1381         }
1382     }
1383
1384     private void bulkUpdateService(IInventoryListener service) {
1385         for (Node node : getNodes()) {
1386             service.notifyNode(node, UpdateType.ADDED, null);
1387         }
1388
1389         Map<String, Property> propMap = new HashMap<String, Property>();
1390         propMap.put(State.StatePropName, new State(State.EDGE_UP));
1391         for (NodeConnector nodeConnector : nodeConnectorProps.keySet()) {
1392             if (isNodeConnectorEnabled(nodeConnector)) {
1393                 service.notifyNodeConnector(nodeConnector, UpdateType.ADDED,
1394                         propMap);
1395             }
1396         }
1397     }
1398
1399     private void spanAwareNotify(ISpanAware service) {
1400         for (Node node : getNodes()) {
1401             for (SpanConfig conf : getSpanConfigList(node)) {
1402                 service.spanUpdate(node, conf.getPortArrayList(), true);
1403             }
1404         }
1405     }
1406
1407     private void registerWithOSGIConsole() {
1408         BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass())
1409                 .getBundleContext();
1410         bundleContext.registerService(CommandProvider.class.getName(), this,
1411                 null);
1412     }
1413
1414     @Override
1415     public Boolean isNodeConnectorEnabled(NodeConnector nodeConnector) {
1416         if (nodeConnector == null)
1417             return false;
1418
1419         Config config = (Config) getNodeConnectorProp(nodeConnector,
1420                 Config.ConfigPropName);
1421         State state = (State) getNodeConnectorProp(nodeConnector,
1422                 State.StatePropName);
1423         return ((config != null) && (config.getValue() == Config.ADMIN_UP)
1424                 && (state != null) && (state.getValue() == State.EDGE_UP));
1425     }
1426
1427     @Override
1428     public String getHelp() {
1429         StringBuffer help = new StringBuffer();
1430         help.append("---Switch Manager---\n");
1431         help.append("\t pns                    - Print connected nodes\n");
1432         help
1433                 .append("\t pncs <node id>         - Print node connectors for a given node\n");
1434         help
1435                 .append("\t pencs <node id>        - Print enabled node connectors for a given node\n");
1436         help
1437                 .append("\t pdm <node id>          - Print switch ports in device map\n");
1438         help.append("\t snt <node id> <tier>   - Set node tier number\n");
1439         help
1440                 .append("\t hostRefresh <on/off/?> - Enable/Disable/Query host refresh\n");
1441         help.append("\t hostRetry <count>      - Set host retry count\n");
1442         return help.toString();
1443     }
1444
1445     public void _pns(CommandInterpreter ci) {
1446         ci
1447                 .println("           Node                       Type             Name             Tier");
1448         if (nodeProps == null) {
1449             return;
1450         }
1451         Set<Node> nodeSet = nodeProps.keySet();
1452         if (nodeSet == null) {
1453             return;
1454         }
1455         for (Node node : nodeSet) {
1456                 Description desc = ((Description) getNodeProp(node, Description.propertyName));
1457             Tier tier = ((Tier) getNodeProp(node, Tier.TierPropName));
1458             String nodeName = (desc == null) ? "" : desc.getValue();
1459             int tierNum = (tier == null) ? 0 : tier.getValue();
1460             ci.println(node + "            " + node.getType()
1461                     + "            " + nodeName + "            " + tierNum);
1462         }
1463     }
1464
1465     public void _pencs(CommandInterpreter ci) {
1466         String st = ci.nextArgument();
1467         if (st == null) {
1468             ci.println("Please enter node id");
1469             return;
1470         }
1471         Long id = Long.decode(st);
1472
1473         Node node = NodeCreator.createOFNode(id);
1474         Set<NodeConnector> nodeConnectorSet = getUpNodeConnectors(node);
1475         if (nodeConnectorSet == null) {
1476             return;
1477         }
1478         for (NodeConnector nodeConnector : nodeConnectorSet) {
1479             if (nodeConnector == null) {
1480                 continue;
1481             }
1482             ci.println(nodeConnector);
1483         }
1484     }
1485
1486     public void _pncs(CommandInterpreter ci) {
1487         String st = ci.nextArgument();
1488         if (st == null) {
1489             ci.println("Please enter node id");
1490             return;
1491         }
1492         Long id = Long.decode(st);
1493
1494         ci.println("          NodeConnector               BandWidth(Gbps)     Admin     State");
1495         Node node = NodeCreator.createOFNode(id);
1496         Set<NodeConnector> nodeConnectorSet = getNodeConnectors(node);
1497         if (nodeConnectorSet == null) {
1498             return;
1499         }
1500         for (NodeConnector nodeConnector : nodeConnectorSet) {
1501             if (nodeConnector == null) {
1502                 continue;
1503             }
1504             Map<String, Property> propMap = getNodeConnectorProps(nodeConnector);
1505             Bandwidth bw = (Bandwidth) propMap.get(Bandwidth.BandwidthPropName);
1506             Config config = (Config) propMap.get(Config.ConfigPropName);
1507             State state = (State) propMap.get(State.StatePropName);
1508             String out = nodeConnector + "           ";
1509             out += (bw != null) ? bw.getValue() / Math.pow(10, 9) : "    ";
1510             out += "             ";
1511             out += (config != null) ? config.getValue() : " ";
1512             out += "          ";
1513             out += (state != null) ? state.getValue() : " ";
1514             ci.println(out);
1515         }
1516     }
1517
1518     public void _pdm(CommandInterpreter ci) {
1519         String st = ci.nextArgument();
1520         if (st == null) {
1521             ci.println("Please enter node id");
1522             return;
1523         }
1524         Object id = Long.decode(st);
1525         Switch sw = getSwitchByNode(NodeCreator.createOFNode((Long) id));
1526
1527         ci
1528                 .println("          NodeConnector                        Name");
1529         if (sw == null) {
1530             return;
1531         }
1532         Set<NodeConnector> nodeConnectorSet = sw.getNodeConnectors();
1533         String nodeConnectorName;
1534         if (nodeConnectorSet != null && nodeConnectorSet.size() > 0) {
1535             for (NodeConnector nodeConnector : nodeConnectorSet) {
1536                 Map<String, Property> propMap = getNodeConnectorProps(nodeConnector);
1537                 nodeConnectorName = (propMap == null) ? null : ((Name) propMap
1538                         .get(Name.NamePropName)).getValue();
1539                 if (nodeConnectorName != null) {
1540                     Node node = nodeConnector.getNode();
1541                     if (!node.equals(getNode((Long) id))) {
1542                         log.debug("node not match {} {}", node,
1543                                 getNode((Long) id));
1544                     }
1545                     Map<String, NodeConnector> map = nodeConnectorNames
1546                             .get(node);
1547                     if (map != null) {
1548                         NodeConnector nc = map.get(nodeConnectorName);
1549                         if (nc == null) {
1550                             log.debug("no nodeConnector named {}",
1551                                     nodeConnectorName);
1552                         } else if (!nc.equals(nodeConnector)) {
1553                             log.debug("nodeConnector not match {} {}", nc,
1554                                     nodeConnector);
1555                         }
1556                     }
1557                 }
1558
1559                 ci
1560                         .println(nodeConnector
1561                                 + "            "
1562                                 + ((nodeConnectorName == null) ? ""
1563                                         : nodeConnectorName) + "("
1564                                 + nodeConnector.getID() + ")");
1565             }
1566         }
1567     }
1568
1569     public void _snt(CommandInterpreter ci) {
1570         String st = ci.nextArgument();
1571         if (st == null) {
1572             ci.println("Please enter node id");
1573             return;
1574         }
1575         Long id = Long.decode(st);
1576
1577         Node node = NodeCreator.createOFNode(id);
1578
1579         st = ci.nextArgument();
1580         if (st == null) {
1581             ci.println("Please enter tier number");
1582             return;
1583         }
1584         Integer tid = Integer.decode(st);
1585         Tier tier = new Tier(tid);
1586         setNodeProp(node, tier);
1587     }
1588
1589     public void _hostRefresh(CommandInterpreter ci) {
1590         String mode = ci.nextArgument();
1591         if (mode == null) {
1592             ci.println("expecting on/off/?");
1593             return;
1594         }
1595         if (mode.toLowerCase().equals("on"))
1596             hostRefresh = true;
1597         else if (mode.toLowerCase().equals("off"))
1598             hostRefresh = false;
1599         else if (mode.equals("?")) {
1600             if (hostRefresh)
1601                 ci.println("host refresh is ON");
1602             else
1603                 ci.println("host refresh is OFF");
1604         } else
1605             ci.println("expecting on/off/?");
1606         return;
1607     }
1608
1609     public void _hostRetry(CommandInterpreter ci) {
1610         String retry = ci.nextArgument();
1611         if (retry == null) {
1612             ci.println("Please enter a valid number. Current retry count is "
1613                     + hostRetryCount);
1614             return;
1615         }
1616         try {
1617             hostRetryCount = Integer.parseInt(retry);
1618         } catch (Exception e) {
1619             ci.println("Please enter a valid number");
1620         }
1621         return;
1622     }
1623
1624     @Override
1625     public byte[] getNodeMAC(Node node) {
1626         if (node.getType().equals(Node.NodeIDType.OPENFLOW)) {
1627             byte[] gmac = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
1628             long dpid = (Long) node.getID();
1629
1630             for (short i = 0; i < 6; i++) {
1631                 gmac[5 - i] = (byte) dpid;
1632                 dpid >>= 8;
1633             }
1634             return gmac;
1635         }
1636         return null;
1637     }
1638
1639     @Override
1640     public boolean isSpecial(NodeConnector p) {
1641         if (p.getType().equals(NodeConnectorIDType.CONTROLLER) ||
1642             p.getType().equals(NodeConnectorIDType.ALL) ||
1643             p.getType().equals(NodeConnectorIDType.SWSTACK) ||
1644             p.getType().equals(NodeConnectorIDType.HWPATH)) {
1645             return true;
1646         }
1647         return false;
1648     }
1649
1650     /*
1651      * Add span configuration to local cache and notify clients
1652      */
1653     private void addSpanPorts(Node node, List<NodeConnector> nodeConncetors) {
1654         List<NodeConnector> ncLists = new ArrayList<NodeConnector>();
1655
1656         for (NodeConnector nodeConnector : nodeConncetors) {
1657             if (!spanNodeConnectors.contains(nodeConnector)) {
1658                 ncLists.add(nodeConnector);
1659             }
1660         }
1661
1662         if (ncLists.size() > 0) {
1663             spanNodeConnectors.addAll(ncLists);
1664             notifySpanPortChange(node, ncLists, true);
1665         }
1666     }
1667
1668     private void addSpanPorts(Node node) {
1669         for (SpanConfig conf : getSpanConfigList(node)) {
1670             addSpanPorts(node, conf.getPortArrayList());
1671         }
1672     }
1673
1674     private void addSpanPort(NodeConnector nodeConncetor) {
1675         List<NodeConnector> ncLists = new ArrayList<NodeConnector>();
1676         ncLists.add(nodeConncetor);
1677         addSpanPorts(nodeConncetor.getNode(), ncLists);
1678     }
1679
1680     /*
1681      * Remove span configuration to local cache and notify clients
1682      */
1683     private void removeSpanPorts(Node node, List<NodeConnector> nodeConncetors) {
1684         List<NodeConnector> ncLists = new ArrayList<NodeConnector>();
1685
1686         for (NodeConnector nodeConnector : nodeConncetors) {
1687             if (!spanNodeConnectors.contains(nodeConnector)) {
1688                 ncLists.add(nodeConnector);
1689             }
1690         }
1691
1692         if (ncLists.size() > 0) {
1693             spanNodeConnectors.removeAll(ncLists);
1694             notifySpanPortChange(node, ncLists, false);
1695         }
1696     }
1697
1698     private void removeSpanPorts(Node node) {
1699         for (SpanConfig conf : getSpanConfigList(node)) {
1700             addSpanPorts(node, conf.getPortArrayList());
1701         }
1702     }
1703
1704     private void removeSpanPort(NodeConnector nodeConncetor) {
1705         List<NodeConnector> ncLists = new ArrayList<NodeConnector>();
1706         ncLists.add(nodeConncetor);
1707         removeSpanPorts(nodeConncetor.getNode(), ncLists);
1708     }
1709
1710     private void addNodeProps(Node node, Map<String, Property> propMap) {
1711         if (propMap == null) {
1712             propMap = new HashMap<String, Property>();
1713         }
1714         nodeProps.put(node, propMap);
1715     }
1716
1717     private void removeNodeProps(Node node) {
1718         if (getUpNodeConnectors(node).size() == 0) {
1719             nodeProps.remove(node);
1720         }
1721     }
1722
1723     @Override
1724     public Status saveConfiguration() {
1725         return saveSwitchConfig();
1726     }
1727
1728         /**
1729          * Creates a Name/Tier/Bandwidth Property object based on given property
1730          * name and value. Other property types are not supported yet.
1731          * 
1732          * @param propName  Name of the Property
1733          * @param propValue Value of the Property
1734          * @return {@link org.opendaylight.controller.sal.core.Property}
1735          */
1736         @Override
1737         public Property createProperty(String propName, String propValue) {
1738                 if (propName == null) {
1739                         log.debug("propName is null");
1740                         return null;
1741                 }
1742                 if (propValue == null) {
1743                         log.debug("propValue is null");
1744                         return null;
1745                 }
1746                 
1747                 try {
1748                         if (propName.equalsIgnoreCase(Description.propertyName)) {
1749                                 return new Description(propValue);
1750                         } else if (propName.equalsIgnoreCase(Tier.TierPropName)) {
1751                                 int tier = Integer.parseInt(propValue);
1752                                 return new Tier(tier);
1753                         } else if (propName.equalsIgnoreCase(Bandwidth.BandwidthPropName)) {
1754                                 long bw = Long.parseLong(propValue);
1755                                 return new Bandwidth(bw);
1756                         } else {
1757                                 log.debug("Not able to create {} property", propName);
1758                         }
1759                 } catch (Exception e) {
1760                         log.debug(e.getMessage());
1761                 }
1762
1763                 return null;
1764     }
1765         
1766         @Override
1767         public String getNodeDescription(Node node) {
1768         // Check first if user configured a name
1769         SwitchConfig config = getSwitchConfig(node.getNodeIDString());
1770         if (config != null) {
1771                 String configuredDesc = config.getNodeDescription();
1772                 if (configuredDesc != null && !configuredDesc.isEmpty()) {
1773                         return configuredDesc;
1774                 }
1775         }
1776         
1777         // No name configured by user, get the node advertised name
1778         Description desc = (Description) getNodeProp(node, Description.propertyName);
1779         return (desc == null /*|| desc.getValue().equalsIgnoreCase("none")*/) ? 
1780                                         "" : desc.getValue();
1781     }
1782 }