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