79159e5ff102270c0d2e094a732acd5fb77130a5
[controller.git] / opendaylight / switchmanager / implementation / src / main / java / org / opendaylight / controller / switchmanager / internal / SwitchManagerImpl.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.controller.switchmanager.internal;
10
11 import java.io.FileNotFoundException;
12 import java.io.IOException;
13 import java.io.ObjectInputStream;
14 import java.net.InetAddress;
15 import java.net.NetworkInterface;
16 import java.net.SocketException;
17 import java.util.ArrayList;
18 import java.util.Collections;
19 import java.util.Date;
20 import java.util.Dictionary;
21 import java.util.EnumSet;
22 import java.util.Enumeration;
23 import java.util.HashMap;
24 import java.util.HashSet;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Set;
28 import java.util.concurrent.ConcurrentHashMap;
29 import java.util.concurrent.ConcurrentMap;
30 import java.util.concurrent.CopyOnWriteArrayList;
31
32 import org.apache.felix.dm.Component;
33 import org.eclipse.osgi.framework.console.CommandInterpreter;
34 import org.eclipse.osgi.framework.console.CommandProvider;
35 import org.opendaylight.controller.clustering.services.CacheConfigException;
36 import org.opendaylight.controller.clustering.services.CacheExistException;
37 import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
38 import org.opendaylight.controller.clustering.services.IClusterContainerServices;
39 import org.opendaylight.controller.clustering.services.IClusterServices;
40 import org.opendaylight.controller.configuration.IConfigurationContainerAware;
41 import org.opendaylight.controller.sal.core.Bandwidth;
42 import org.opendaylight.controller.sal.core.Config;
43 import org.opendaylight.controller.sal.core.Description;
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 global container only
101     private ConcurrentMap<NodeConnector, Map<String, Property>> nodeConnectorProps; // properties are maintained in global 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 {}",
140                             e.getMessage());
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 {}",
154                             e.getMessage());
155                 }
156             }
157         }
158     }
159
160     private void notifyModeChange(Node node, boolean proactive) {
161         synchronized (switchManagerAware) {
162             for (ISwitchManagerAware service : switchManagerAware) {
163                 try {
164                     service.modeChangeNotify(node, proactive);
165                 } catch (Exception e) {
166                     log.error("Failed to notify Subnet change {}",
167                             e.getMessage());
168                 }
169             }
170         }
171     }
172
173     public void startUp() {
174         // Initialize configuration file names
175         subnetFileName = ROOT + "subnets" + this.getContainerName() + ".conf";
176         spanFileName = ROOT + "spanPorts_" + this.getContainerName() + ".conf";
177         switchConfigFileName = ROOT + "switchConfig_" + this.getContainerName()
178                 + ".conf";
179
180         // Instantiate cluster synced variables
181         allocateCaches();
182         retrieveCaches();
183
184         /*
185          * Read startup and build database if we have not already gotten the
186          * configurations synced from another node
187          */
188         if (subnetsConfigList.isEmpty())
189             loadSubnetConfiguration();
190         if (spanConfigList.isEmpty())
191             loadSpanConfiguration();
192         if (nodeConfigList.isEmpty())
193             loadSwitchConfiguration();
194
195         MAC = getHardwareMAC();
196     }
197
198     public void shutDown() {
199         destroyCaches(this.getContainerName());
200     }
201
202     @SuppressWarnings("deprecation")
203     private void allocateCaches() {
204         if (this.clusterContainerService == null) {
205             log.warn("un-initialized clusterContainerService, can't create cache");
206             return;
207         }
208
209         try {
210             clusterContainerService.createCache(
211                     "switchmanager.subnetsConfigList",
212                     EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
213             clusterContainerService.createCache("switchmanager.spanConfigList",
214                     EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
215             clusterContainerService.createCache("switchmanager.nodeConfigList",
216                     EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
217             clusterContainerService.createCache("switchmanager.subnets",
218                     EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
219             clusterContainerService.createCache(
220                     "switchmanager.configSaveEvent",
221                     EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
222             clusterContainerService.createCache("switchmanager.nodeProps",
223                     EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
224             clusterContainerService.createCache(
225                     "switchmanager.nodeConnectorProps",
226                     EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
227             clusterContainerService.createCache(
228                     "switchmanager.nodeConnectorNames",
229                     EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
230         } catch (CacheConfigException cce) {
231             log.error("\nCache configuration invalid - check cache mode");
232         } catch (CacheExistException ce) {
233             log.error("\nCache already exits - destroy and recreate if needed");
234         }
235     }
236
237     @SuppressWarnings({ "unchecked", "deprecation" })
238     private void retrieveCaches() {
239         if (this.clusterContainerService == null) {
240             log.info("un-initialized clusterContainerService, can't create cache");
241             return;
242         }
243
244         subnetsConfigList = (ConcurrentMap<String, SubnetConfig>) clusterContainerService
245                 .getCache("switchmanager.subnetsConfigList");
246         if (subnetsConfigList == null) {
247             log.error("\nFailed to get cache for subnetsConfigList");
248         }
249
250         spanConfigList = (ConcurrentMap<Integer, SpanConfig>) clusterContainerService
251                 .getCache("switchmanager.spanConfigList");
252         if (spanConfigList == null) {
253             log.error("\nFailed to get cache for spanConfigList");
254         }
255
256         nodeConfigList = (ConcurrentMap<String, SwitchConfig>) clusterContainerService
257                 .getCache("switchmanager.nodeConfigList");
258         if (nodeConfigList == null) {
259             log.error("\nFailed to get cache for nodeConfigList");
260         }
261
262         subnets = (ConcurrentMap<InetAddress, Subnet>) clusterContainerService
263                 .getCache("switchmanager.subnets");
264         if (subnets == null) {
265             log.error("\nFailed to get cache for subnets");
266         }
267
268         configSaveEvent = (ConcurrentMap<Long, String>) clusterContainerService
269                 .getCache("switchmanager.configSaveEvent");
270         if (configSaveEvent == null) {
271             log.error("\nFailed to get cache for configSaveEvent");
272         }
273
274         nodeProps = (ConcurrentMap<Node, Map<String, Property>>) clusterContainerService
275                 .getCache("switchmanager.nodeProps");
276         if (nodeProps == null) {
277             log.error("\nFailed to get cache for nodeProps");
278         }
279
280         nodeConnectorProps = (ConcurrentMap<NodeConnector, Map<String, Property>>) clusterContainerService
281                 .getCache("switchmanager.nodeConnectorProps");
282         if (nodeConnectorProps == null) {
283             log.error("\nFailed to get cache for nodeConnectorProps");
284         }
285
286         nodeConnectorNames = (ConcurrentMap<Node, Map<String, NodeConnector>>) clusterContainerService
287                 .getCache("switchmanager.nodeConnectorNames");
288         if (nodeConnectorNames == null) {
289             log.error("\nFailed to get cache for nodeConnectorNames");
290         }
291     }
292
293     void nonClusterObjectCreate() {
294         subnetsConfigList = new ConcurrentHashMap<String, SubnetConfig>();
295         spanConfigList = new ConcurrentHashMap<Integer, SpanConfig>();
296         nodeConfigList = new ConcurrentHashMap<String, SwitchConfig>();
297         subnets = new ConcurrentHashMap<InetAddress, Subnet>();
298         configSaveEvent = new ConcurrentHashMap<Long, String>();
299         nodeProps = new ConcurrentHashMap<Node, Map<String, Property>>();
300         nodeConnectorProps = new ConcurrentHashMap<NodeConnector, Map<String, Property>>();
301         nodeConnectorNames = new ConcurrentHashMap<Node, Map<String, NodeConnector>>();
302     }
303
304     @SuppressWarnings("deprecation")
305     private void destroyCaches(String container) {
306         if (this.clusterContainerService == null) {
307             log.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     @Override
586     public void updateSwitchConfig(SwitchConfig cfgObject) {
587         boolean modeChange = false;
588
589         SwitchConfig sc = nodeConfigList.get(cfgObject.getNodeId());
590         if ((sc == null) || !cfgObject.getMode().equals(sc.getMode())) {
591             modeChange = true;
592         }
593
594         nodeConfigList.put(cfgObject.getNodeId(), cfgObject);
595         try {
596             // update default container only
597             if (isDefaultContainer) {
598                 String nodeId = cfgObject.getNodeId();
599                 Node node = Node.fromString(nodeId);
600                 Map<String, Property> propMap;
601                 if (nodeProps.get(node) != null) {
602                     propMap = nodeProps.get(node);
603                 } else {
604                     propMap = new HashMap<String, Property>();
605                 }
606                 Property desc = new Description(cfgObject.getNodeDescription());
607                 propMap.put(desc.getName(), desc);
608                 Property tier = new Tier(Integer.parseInt(cfgObject.getTier()));
609                 propMap.put(tier.getName(), tier);
610                 addNodeProps(node, propMap);
611
612                 log.info("Set Node {}'s Mode to {}", nodeId,
613                         cfgObject.getMode());
614
615                 if (modeChange) {
616                     notifyModeChange(node, cfgObject.isProactive());
617                 }
618             }
619         } catch (Exception e) {
620             log.debug("updateSwitchConfig: {}", e.getMessage());
621         }
622     }
623
624     @Override
625     public Status saveSwitchConfig() {
626         // Publish the save config event to the cluster nodes
627         configSaveEvent.put(new Date().getTime(), SAVE);
628         return saveSwitchConfigInternal();
629     }
630
631     public Status saveSwitchConfigInternal() {
632         Status retS = null, retP = null;
633         ObjectWriter objWriter = new ObjectWriter();
634
635         retS = objWriter.write(new ConcurrentHashMap<String, SubnetConfig>(
636                 subnetsConfigList), subnetFileName);
637         retP = objWriter.write(new ConcurrentHashMap<Integer, SpanConfig>(
638                 spanConfigList), spanFileName);
639         retS = objWriter.write(new ConcurrentHashMap<String, SwitchConfig>(
640                 nodeConfigList), switchConfigFileName);
641
642         if (retS.equals(retP)) {
643             if (retS.isSuccess()) {
644                 return retS;
645             } else {
646                 return new Status(StatusCode.INTERNALERROR, "Save failed");
647             }
648         } else {
649             return new Status(StatusCode.INTERNALERROR, "Partial save failure");
650         }
651     }
652
653     @Override
654     public List<SpanConfig> getSpanConfigList() {
655         return new ArrayList<SpanConfig>(spanConfigList.values());
656     }
657
658     @Override
659     public Status addSpanConfig(SpanConfig conf) {
660         // Valid config check
661         if (!conf.isValidConfig()) {
662             String msg = "Invalid Span configuration";
663             log.warn(msg);
664             return new Status(StatusCode.BADREQUEST, msg);
665         }
666
667         // Presence check
668         if (spanConfigList.containsKey(conf.hashCode())) {
669             return new Status(StatusCode.CONFLICT, "Same span config exists");
670         }
671
672         // Update database and notify clients
673         addSpanPorts(conf.getNode(), conf.getPortArrayList());
674
675         // Update configuration
676         spanConfigList.put(conf.hashCode(), conf);
677
678         return new Status(StatusCode.SUCCESS, null);
679     }
680
681     @Override
682     public Status removeSpanConfig(SpanConfig conf) {
683         removeSpanPorts(conf.getNode(), conf.getPortArrayList());
684
685         // Update configuration
686         spanConfigList.remove(conf.hashCode());
687
688         return new Status(StatusCode.SUCCESS, null);
689     }
690
691     @Override
692     public List<NodeConnector> getSpanPorts(Node node) {
693         List<NodeConnector> ncList = new ArrayList<NodeConnector>();
694
695         for (NodeConnector nodeConnector : spanNodeConnectors) {
696             if (nodeConnector.getNode().equals(node)) {
697                 ncList.add(nodeConnector);
698             }
699         }
700         return ncList;
701     }
702
703     @Override
704     public void entryCreated(Long key, String cacheName, boolean local) {
705     }
706
707     @Override
708     public void entryUpdated(Long key, String new_value, String cacheName,
709             boolean originLocal) {
710         saveSwitchConfigInternal();
711     }
712
713     @Override
714     public void entryDeleted(Long key, String cacheName, boolean originLocal) {
715     }
716
717     private void addNode(Node node, Set<Property> props) {
718         log.trace("{} added, props: {}", node, props);
719         if (nodeProps == null) {
720             return;
721         }
722
723         Map<String, Property> propMap;
724         if (nodeProps.get(node) != null) {
725             propMap = nodeProps.get(node);
726         } else {
727             propMap = new HashMap<String, Property>();
728         }
729
730         // copy node properties from plugin
731         if (props != null) {
732             for (Property prop : props) {
733                 propMap.put(prop.getName(), prop);
734             }
735         }
736
737         // copy node properties from config
738         boolean proactiveForwarding = false;
739         if (nodeConfigList != null) {
740             String nodeId = node.toString();
741             for (SwitchConfig conf : nodeConfigList.values()) {
742                 if (conf.getNodeId().equals(nodeId)) {
743                     Property description = new Description(
744                             conf.getNodeDescription());
745                     propMap.put(description.getName(), description);
746                     Property tier = new Tier(Integer.parseInt(conf.getTier()));
747                     propMap.put(tier.getName(), tier);
748                     proactiveForwarding = conf.isProactive();
749                     break;
750                 }
751             }
752         }
753         addNodeProps(node, propMap);
754
755         // check if span ports are configed
756         addSpanPorts(node);
757
758         // notify node listeners
759         notifyNode(node, UpdateType.ADDED, propMap);
760
761         // notify proactive mode forwarding
762         if (proactiveForwarding) {
763             notifyModeChange(node, true);
764         }
765     }
766
767     private void removeNode(Node node) {
768         log.trace("{} removed", node);
769         if (nodeProps == null) {
770             return;
771         }
772         nodeProps.remove(node);
773
774         // check if span ports need to be cleaned up
775         removeSpanPorts(node);
776
777         /* notify node listeners */
778         notifyNode(node, UpdateType.REMOVED, null);
779     }
780
781     private void updateNode(Node node, Set<Property> props) {
782         log.trace("{} updated, props: {}", node, props);
783         if (nodeProps == null || !nodeProps.containsKey(node) ||
784                 props == null || props.isEmpty()) {
785             return;
786         }
787
788         Map<String, Property> propMap;
789         if (nodeProps.get(node) != null) {
790             propMap = nodeProps.get(node);
791         } else {
792             propMap = new HashMap<String, Property>();
793         }
794
795         // copy node properties from plugin
796         if (props != null) {
797             for (Property prop : props) {
798                 propMap.put(prop.getName(), prop);
799             }
800         }
801         addNodeProps(node, propMap);
802
803         /* notify node listeners */
804         notifyNode(node, UpdateType.CHANGED, propMap);
805     }
806
807     @Override
808     public void updateNode(Node node, UpdateType type, Set<Property> props) {
809         switch (type) {
810         case ADDED:
811             addNode(node, props);
812             break;
813         case CHANGED:
814             updateNode(node, props);
815             break;
816         case REMOVED:
817             removeNode(node);
818             break;
819         default:
820             break;
821         }
822     }
823
824     @Override
825     public void updateNodeConnector(NodeConnector nodeConnector,
826             UpdateType type, Set<Property> props) {
827         Node node = nodeConnector.getNode();
828         Map<String, Property> propMap = new HashMap<String, Property>();
829
830         log.trace("{} {}", nodeConnector, type);
831
832         if (nodeConnectorProps == null) {
833             return;
834         }
835
836         switch (type) {
837         case ADDED:
838         case CHANGED:
839             if (props != null) {
840                 for (Property prop : props) {
841                     addNodeConnectorProp(nodeConnector, prop);
842                     propMap.put(prop.getName(), prop);
843                 }
844             } else {
845                 addNodeConnectorProp(nodeConnector, null);
846                 addNodeProps(node, null);
847             }
848
849             // check if span is configed
850             addSpanPort(nodeConnector);
851             break;
852         case REMOVED:
853             removeNodeConnectorAllProps(nodeConnector);
854             removeNodeProps(node);
855
856             // clean up span config
857             removeSpanPort(nodeConnector);
858             break;
859         default:
860             break;
861         }
862
863         notifyNodeConnector(nodeConnector, type, propMap);
864     }
865
866     @Override
867     public Set<Node> getNodes() {
868         return (nodeProps != null) ? new HashSet<Node>(nodeProps.keySet())
869                 : null;
870     }
871
872     /*
873      * test utility function which assumes all nodes are OF nodes
874      */
875     private Node getNode(Long id) {
876         Set<Node> nodes = getNodes();
877         if (nodes != null) {
878             for (Node node : nodes) {
879                 if (id.equals((Long) node.getID())) {
880                     return node;
881                 }
882             }
883         }
884         return null;
885     }
886
887     /*
888      * Returns a copy of a list of properties for a given node
889      * 
890      * (non-Javadoc)
891      * 
892      * @see
893      * org.opendaylight.controller.switchmanager.ISwitchManager#getNodeProps
894      * (org.opendaylight.controller.sal.core.Node)
895      */
896     @Override
897     public Map<String, Property> getNodeProps(Node node) {
898         if (isDefaultContainer) {
899             Map<String, Property> rv = null;
900             if (this.nodeProps != null) {
901                 rv = this.nodeProps.get(node);
902                 if (rv != null) {
903                     /* make a copy of it */
904                     rv = new HashMap<String, Property>(rv);
905                 }
906             }
907             return rv;
908         } else {
909             // get it from default container
910             ISwitchManager defaultSwitchManager = (ISwitchManager) ServiceHelper
911                     .getInstance(ISwitchManager.class,
912                             GlobalConstants.DEFAULT.toString(), this);
913             return defaultSwitchManager.getNodeProps(node);
914         }
915     }
916
917     @Override
918     public Property getNodeProp(Node node, String propName) {
919         Map<String, Property> propMap = getNodeProps(node);
920         return (propMap != null) ? propMap.get(propName) : null;
921     }
922
923     @Override
924     public void setNodeProp(Node node, Property prop) {
925         /* Get a copy of the property map */
926         Map<String, Property> propMap = getNodeProps(node);
927         if (propMap == null)
928             return;
929
930         propMap.put(prop.getName(), prop);
931         this.nodeProps.put(node, propMap);
932     }
933
934     @Override
935     public Status removeNodeProp(Node node, String propName) {
936         Map<String, Property> propMap = getNodeProps(node);
937         if (propMap != null) {
938             propMap.remove(propName);
939             this.nodeProps.put(node, propMap);
940         }
941         return new Status(StatusCode.SUCCESS, null);
942     }
943
944     @Override
945     public Status removeNodeAllProps(Node node) {
946         this.nodeProps.remove(node);
947         return new Status(StatusCode.SUCCESS, null);
948     }
949
950     @Override
951     public Set<NodeConnector> getUpNodeConnectors(Node node) {
952         if (nodeConnectorProps == null)
953             return null;
954
955         Set<NodeConnector> nodeConnectorSet = new HashSet<NodeConnector>();
956         for (NodeConnector nodeConnector : nodeConnectorProps.keySet()) {
957             if (((Long) nodeConnector.getNode().getID()).longValue() != (Long) node
958                     .getID())
959                 continue;
960             if (isNodeConnectorEnabled(nodeConnector))
961                 nodeConnectorSet.add(nodeConnector);
962         }
963
964         return nodeConnectorSet;
965     }
966
967     @Override
968     public Set<NodeConnector> getNodeConnectors(Node node) {
969         if (nodeConnectorProps == null)
970             return null;
971
972         Set<NodeConnector> nodeConnectorSet = new HashSet<NodeConnector>();
973         for (NodeConnector nodeConnector : nodeConnectorProps.keySet()) {
974             if (((Long) nodeConnector.getNode().getID()).longValue() != (Long) node
975                     .getID())
976                 continue;
977             nodeConnectorSet.add(nodeConnector);
978         }
979
980         return nodeConnectorSet;
981     }
982
983     @Override
984     public Set<NodeConnector> getPhysicalNodeConnectors(Node node) {
985         if (nodeConnectorProps == null)
986             return null;
987
988         Set<NodeConnector> nodeConnectorSet = new HashSet<NodeConnector>();
989         for (NodeConnector nodeConnector : nodeConnectorProps.keySet()) {
990             if (!nodeConnector.getNode().equals(node)
991                     || isSpecial(nodeConnector)) {
992                 continue;
993             }
994             nodeConnectorSet.add(nodeConnector);
995         }
996
997         return nodeConnectorSet;
998     }
999
1000     /*
1001      * testing utility function which assumes we are dealing with OF Node
1002      * nodeconnectors only
1003      */
1004     @SuppressWarnings("unused")
1005     private Set<Long> getEnabledNodeConnectorIds(Node node) {
1006         Set<Long> ids = new HashSet<Long>();
1007         Set<NodeConnector> nodeConnectors = getUpNodeConnectors(node);
1008
1009         if (nodeConnectors != null) {
1010             for (NodeConnector nodeConnector : nodeConnectors) {
1011                 ids.add((Long) nodeConnector.getID());
1012             }
1013         }
1014
1015         return ids;
1016     }
1017
1018     @Override
1019     public Map<String, Property> getNodeConnectorProps(
1020             NodeConnector nodeConnector) {
1021         if (isDefaultContainer) {
1022             Map<String, Property> rv = null;
1023             if (this.nodeConnectorProps != null) {
1024                 rv = this.nodeConnectorProps.get(nodeConnector);
1025                 if (rv != null) {
1026                     rv = new HashMap<String, Property>(rv);
1027                 }
1028             }
1029             return rv;
1030         } else {
1031             // get it from default container
1032             ISwitchManager defaultSwitchManager = (ISwitchManager) ServiceHelper
1033                     .getInstance(ISwitchManager.class,
1034                             GlobalConstants.DEFAULT.toString(), this);
1035             return defaultSwitchManager.getNodeConnectorProps(nodeConnector);
1036         }
1037     }
1038
1039     @Override
1040     public Property getNodeConnectorProp(NodeConnector nodeConnector,
1041             String propName) {
1042         Map<String, Property> propMap = getNodeConnectorProps(nodeConnector);
1043         return (propMap != null) ? propMap.get(propName) : null;
1044     }
1045
1046     private byte[] getHardwareMAC() {
1047         Enumeration<NetworkInterface> nis;
1048         try {
1049             nis = NetworkInterface.getNetworkInterfaces();
1050         } catch (SocketException e1) {
1051             log.error("",e1);
1052             return null;
1053         }
1054         byte[] MAC = null;
1055         for (; nis.hasMoreElements();) {
1056             NetworkInterface ni = nis.nextElement();
1057             try {
1058                 MAC = ni.getHardwareAddress();
1059             } catch (SocketException e) {
1060                 log.error("",e);
1061             }
1062             if (MAC != null) {
1063                 return MAC;
1064             }
1065         }
1066         return null;
1067     }
1068
1069     @Override
1070     public byte[] getControllerMAC() {
1071         return MAC;
1072     }
1073
1074     @Override
1075     public boolean isHostRefreshEnabled() {
1076         return hostRefresh;
1077     }
1078
1079     @Override
1080     public int getHostRetryCount() {
1081         return hostRetryCount;
1082     }
1083
1084     @Override
1085     public NodeConnector getNodeConnector(Node node, String nodeConnectorName) {
1086         if (nodeConnectorNames == null)
1087             return null;
1088
1089         Map<String, NodeConnector> map = nodeConnectorNames.get(node);
1090         if (map == null)
1091             return null;
1092
1093         return map.get(nodeConnectorName);
1094     }
1095
1096     /**
1097      * Adds a node connector and its property if any
1098      * 
1099      * @param nodeConnector
1100      *            {@link org.opendaylight.controller.sal.core.NodeConnector}
1101      * @param propName
1102      *            name of {@link org.opendaylight.controller.sal.core.Property}
1103      * @return success or failed reason
1104      */
1105     @Override
1106     public Status addNodeConnectorProp(NodeConnector nodeConnector,
1107             Property prop) {
1108         Map<String, Property> propMap = getNodeConnectorProps(nodeConnector);
1109
1110         if (propMap == null) {
1111             propMap = new HashMap<String, Property>();
1112         }
1113
1114         // Just add the nodeConnector if prop is not available (in a non-default
1115         // container)
1116         if (prop == null) {
1117             nodeConnectorProps.put(nodeConnector, propMap);
1118             return new Status(StatusCode.SUCCESS, null);
1119         }
1120
1121         propMap.put(prop.getName(), prop);
1122         nodeConnectorProps.put(nodeConnector, propMap);
1123
1124         if (prop.getName().equals(Name.NamePropName)) {
1125             if (nodeConnectorNames != null) {
1126                 Node node = nodeConnector.getNode();
1127                 Map<String, NodeConnector> map = nodeConnectorNames.get(node);
1128                 if (map == null) {
1129                     map = new HashMap<String, NodeConnector>();
1130                 }
1131
1132                 map.put(((Name) prop).getValue(), nodeConnector);
1133                 nodeConnectorNames.put(node, map);
1134             }
1135         }
1136
1137         return new Status(StatusCode.SUCCESS, null);
1138     }
1139
1140     /**
1141      * Removes one property of a node connector
1142      * 
1143      * @param nodeConnector
1144      *            {@link org.opendaylight.controller.sal.core.NodeConnector}
1145      * @param propName
1146      *            name of {@link org.opendaylight.controller.sal.core.Property}
1147      * @return success or failed reason
1148      */
1149     @Override
1150     public Status removeNodeConnectorProp(NodeConnector nodeConnector,
1151             String propName) {
1152         Map<String, Property> propMap = getNodeConnectorProps(nodeConnector);
1153
1154         if (propMap == null) {
1155             /* Nothing to remove */
1156             return new Status(StatusCode.SUCCESS, null);
1157         }
1158
1159         propMap.remove(propName);
1160         nodeConnectorProps.put(nodeConnector, propMap);
1161
1162         if (nodeConnectorNames != null) {
1163             Name name = ((Name) getNodeConnectorProp(nodeConnector,
1164                     Name.NamePropName));
1165             if (name != null) {
1166                 Node node = nodeConnector.getNode();
1167                 Map<String, NodeConnector> map = nodeConnectorNames.get(node);
1168                 if (map != null) {
1169                     map.remove(name.getValue());
1170                     nodeConnectorNames.put(node, map);
1171                 }
1172             }
1173         }
1174
1175         return new Status(StatusCode.SUCCESS, null);
1176     }
1177
1178     /**
1179      * Removes all the properties of a node connector
1180      * 
1181      * @param nodeConnector
1182      *            {@link org.opendaylight.controller.sal.core.NodeConnector}
1183      * @return success or failed reason
1184      */
1185     @Override
1186     public Status removeNodeConnectorAllProps(NodeConnector nodeConnector) {
1187         if (nodeConnectorNames != null) {
1188             Name name = ((Name) getNodeConnectorProp(nodeConnector,
1189                     Name.NamePropName));
1190             if (name != null) {
1191                 Node node = nodeConnector.getNode();
1192                 Map<String, NodeConnector> map = nodeConnectorNames.get(node);
1193                 if (map != null) {
1194                     map.remove(name.getValue());
1195                     nodeConnectorNames.put(node, map);
1196                 }
1197             }
1198         }
1199         nodeConnectorProps.remove(nodeConnector);
1200
1201         return new Status(StatusCode.SUCCESS, null);
1202     }
1203
1204     /**
1205      * Function called by the dependency manager when all the required
1206      * dependencies are satisfied
1207      * 
1208      */
1209     void init(Component c) {
1210         Dictionary<?, ?> props = c.getServiceProperties();
1211         if (props != null) {
1212             this.containerName = (String) props.get("containerName");
1213             log.trace("Running containerName: {}", this.containerName);
1214         } else {
1215             // In the Global instance case the containerName is empty
1216             this.containerName = "";
1217         }
1218         isDefaultContainer = containerName.equals(GlobalConstants.DEFAULT
1219                 .toString());
1220
1221         startUp();
1222     }
1223
1224     /**
1225      * Function called by the dependency manager when at least one dependency
1226      * become unsatisfied or when the component is shutting down because for
1227      * example bundle is being stopped.
1228      * 
1229      */
1230     void destroy() {
1231         shutDown();
1232     }
1233
1234     /**
1235      * Function called by dependency manager after "init ()" is called and after
1236      * the services provided by the class are registered in the service registry
1237      * 
1238      */
1239     void start() {
1240         // OSGI console
1241         registerWithOSGIConsole();
1242     }
1243
1244     /**
1245      * Function called after registered the service in OSGi service registry.
1246      */
1247     void started() {
1248         // solicit for existing inventories
1249         getInventories();
1250     }
1251
1252     /**
1253      * Function called by the dependency manager before the services exported by
1254      * the component are unregistered, this will be followed by a "destroy ()"
1255      * calls
1256      * 
1257      */
1258     void stop() {
1259     }
1260
1261     public void setInventoryService(IInventoryService service) {
1262         log.trace("Got inventory service set request {}", service);
1263         this.inventoryService = service;
1264
1265         // solicit for existing inventories
1266         getInventories();
1267     }
1268
1269     public void unsetInventoryService(IInventoryService service) {
1270         log.trace("Got a service UNset request");
1271         this.inventoryService = null;
1272
1273         // clear existing inventories
1274         clearInventories();
1275     }
1276
1277     public void setSwitchManagerAware(ISwitchManagerAware service) {
1278         log.trace("Got inventory service set request {}", service);
1279         if (this.switchManagerAware != null) {
1280             this.switchManagerAware.add(service);
1281         }
1282
1283         // bulk update for newly joined
1284         switchManagerAwareNotify(service);
1285     }
1286
1287     public void unsetSwitchManagerAware(ISwitchManagerAware service) {
1288         log.trace("Got a service UNset request");
1289         if (this.switchManagerAware != null) {
1290             this.switchManagerAware.remove(service);
1291         }
1292     }
1293
1294     public void setInventoryListener(IInventoryListener service) {
1295         log.trace("Got inventory listener set request {}", service);
1296         if (this.inventoryListeners != null) {
1297             this.inventoryListeners.add(service);
1298         }
1299
1300         // bulk update for newly joined
1301         bulkUpdateService(service);
1302     }
1303
1304     public void unsetInventoryListener(IInventoryListener service) {
1305         log.trace("Got a service UNset request");
1306         if (this.inventoryListeners != null) {
1307             this.inventoryListeners.remove(service);
1308         }
1309     }
1310
1311     public void setSpanAware(ISpanAware service) {
1312         log.trace("Got SpanAware set request {}", service);
1313         if (this.spanAware != null) {
1314             this.spanAware.add(service);
1315         }
1316
1317         // bulk update for newly joined
1318         spanAwareNotify(service);
1319     }
1320
1321     public void unsetSpanAware(ISpanAware service) {
1322         log.trace("Got a service UNset request");
1323         if (this.spanAware != null) {
1324             this.spanAware.remove(service);
1325         }
1326     }
1327
1328     void setClusterContainerService(IClusterContainerServices s) {
1329         log.trace("Cluster Service set");
1330         this.clusterContainerService = s;
1331     }
1332
1333     void unsetClusterContainerService(IClusterContainerServices s) {
1334         if (this.clusterContainerService == s) {
1335             log.trace("Cluster Service removed!");
1336             this.clusterContainerService = null;
1337         }
1338     }
1339
1340     private void getInventories() {
1341         if (inventoryService == null) {
1342             log.trace("inventory service not avaiable");
1343             return;
1344         }
1345
1346         nodeProps = this.inventoryService.getNodeProps();
1347         Set<Node> nodeSet = nodeProps.keySet();
1348         if (nodeSet != null) {
1349             for (Node node : nodeSet) {
1350                 addNode(node, null);
1351             }
1352         }
1353
1354         nodeConnectorProps = inventoryService.getNodeConnectorProps();
1355     }
1356
1357     private void clearInventories() {
1358         nodeProps.clear();
1359         nodeConnectorProps.clear();
1360         nodeConnectorNames.clear();
1361         spanNodeConnectors.clear();
1362     }
1363
1364     private void notifyNode(Node node, UpdateType type,
1365             Map<String, Property> propMap) {
1366         synchronized (inventoryListeners) {
1367             for (IInventoryListener service : inventoryListeners) {
1368                 service.notifyNode(node, type, propMap);
1369             }
1370         }
1371     }
1372
1373     private void notifyNodeConnector(NodeConnector nodeConnector,
1374             UpdateType type, Map<String, Property> propMap) {
1375         synchronized (inventoryListeners) {
1376             for (IInventoryListener service : inventoryListeners) {
1377                 service.notifyNodeConnector(nodeConnector, type, propMap);
1378             }
1379         }
1380     }
1381
1382     /*
1383      * For those joined late, bring them up-to-date.
1384      */
1385     private void switchManagerAwareNotify(ISwitchManagerAware service) {
1386         for (Subnet sub : subnets.values()) {
1387             service.subnetNotify(sub, true);
1388         }
1389
1390         for (Node node : getNodes()) {
1391             SwitchConfig sc = getSwitchConfig(node.toString());
1392             if ((sc != null) && isDefaultContainer) {
1393                 service.modeChangeNotify(node, sc.isProactive());
1394             }
1395         }
1396     }
1397
1398     private void bulkUpdateService(IInventoryListener service) {
1399         for (Node node : getNodes()) {
1400             service.notifyNode(node, UpdateType.ADDED, null);
1401         }
1402
1403         Map<String, Property> propMap = new HashMap<String, Property>();
1404         propMap.put(State.StatePropName, new State(State.EDGE_UP));
1405         for (NodeConnector nodeConnector : nodeConnectorProps.keySet()) {
1406             if (isNodeConnectorEnabled(nodeConnector)) {
1407                 service.notifyNodeConnector(nodeConnector, UpdateType.ADDED,
1408                         propMap);
1409             }
1410         }
1411     }
1412
1413     private void spanAwareNotify(ISpanAware service) {
1414         for (Node node : getNodes()) {
1415             for (SpanConfig conf : getSpanConfigList(node)) {
1416                 service.spanUpdate(node, conf.getPortArrayList(), true);
1417             }
1418         }
1419     }
1420
1421     private void registerWithOSGIConsole() {
1422         BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass())
1423                 .getBundleContext();
1424         bundleContext.registerService(CommandProvider.class.getName(), this,
1425                 null);
1426     }
1427
1428     @Override
1429     public Boolean isNodeConnectorEnabled(NodeConnector nodeConnector) {
1430         if (nodeConnector == null)
1431             return false;
1432
1433         Config config = (Config) getNodeConnectorProp(nodeConnector,
1434                 Config.ConfigPropName);
1435         State state = (State) getNodeConnectorProp(nodeConnector,
1436                 State.StatePropName);
1437         return ((config != null) && (config.getValue() == Config.ADMIN_UP)
1438                 && (state != null) && (state.getValue() == State.EDGE_UP));
1439     }
1440
1441     @Override
1442     public String getHelp() {
1443         StringBuffer help = new StringBuffer();
1444         help.append("---Switch Manager---\n");
1445         help.append("\t pns                    - Print connected nodes\n");
1446         help.append("\t pncs <node id>         - Print node connectors for a given node\n");
1447         help.append("\t pencs <node id>        - Print enabled node connectors for a given node\n");
1448         help.append("\t pdm <node id>          - Print switch ports in device map\n");
1449         help.append("\t snt <node id> <tier>   - Set node tier number\n");
1450         help.append("\t hostRefresh <on/off/?> - Enable/Disable/Query host refresh\n");
1451         help.append("\t hostRetry <count>      - Set host retry count\n");
1452         return help.toString();
1453     }
1454
1455     public void _pns(CommandInterpreter ci) {
1456         ci.println("           Node                       Type             Name             Tier");
1457         if (nodeProps == null) {
1458             return;
1459         }
1460         Set<Node> nodeSet = nodeProps.keySet();
1461         if (nodeSet == null) {
1462             return;
1463         }
1464         for (Node node : nodeSet) {
1465             Description desc = ((Description) getNodeProp(node,
1466                     Description.propertyName));
1467             Tier tier = ((Tier) getNodeProp(node, Tier.TierPropName));
1468             String nodeName = (desc == null) ? "" : desc.getValue();
1469             int tierNum = (tier == null) ? 0 : tier.getValue();
1470             ci.println(node + "            " + node.getType() + "            "
1471                     + nodeName + "            " + tierNum);
1472         }
1473         ci.println("Total number of Nodes: " + nodeSet.size());
1474     }
1475
1476     public void _pencs(CommandInterpreter ci) {
1477         String st = ci.nextArgument();
1478         if (st == null) {
1479             ci.println("Please enter node id");
1480             return;
1481         }
1482         Long id = Long.decode(st);
1483
1484         Node node = NodeCreator.createOFNode(id);
1485         Set<NodeConnector> nodeConnectorSet = getUpNodeConnectors(node);
1486         if (nodeConnectorSet == null) {
1487             return;
1488         }
1489         for (NodeConnector nodeConnector : nodeConnectorSet) {
1490             if (nodeConnector == null) {
1491                 continue;
1492             }
1493             ci.println(nodeConnector);
1494         }
1495         ci.println("Total number of NodeConnectors: " + nodeConnectorSet.size());
1496     }
1497
1498     public void _pncs(CommandInterpreter ci) {
1499         String st = ci.nextArgument();
1500         if (st == null) {
1501             ci.println("Please enter node id");
1502             return;
1503         }
1504         Long id = Long.decode(st);
1505
1506         ci.println("          NodeConnector               BandWidth(Gbps)     Admin     State");
1507         Node node = NodeCreator.createOFNode(id);
1508         Set<NodeConnector> nodeConnectorSet = getNodeConnectors(node);
1509         if (nodeConnectorSet == null) {
1510             return;
1511         }
1512         for (NodeConnector nodeConnector : nodeConnectorSet) {
1513             if (nodeConnector == null) {
1514                 continue;
1515             }
1516             Map<String, Property> propMap = getNodeConnectorProps(nodeConnector);
1517             Bandwidth bw = (Bandwidth) propMap.get(Bandwidth.BandwidthPropName);
1518             Config config = (Config) propMap.get(Config.ConfigPropName);
1519             State state = (State) propMap.get(State.StatePropName);
1520             String out = nodeConnector + "           ";
1521             out += (bw != null) ? bw.getValue() / Math.pow(10, 9) : "    ";
1522             out += "             ";
1523             out += (config != null) ? config.getValue() : " ";
1524             out += "          ";
1525             out += (state != null) ? state.getValue() : " ";
1526             ci.println(out);
1527         }
1528         ci.println("Total number of NodeConnectors: " + nodeConnectorSet.size());
1529     }
1530
1531     public void _pdm(CommandInterpreter ci) {
1532         String st = ci.nextArgument();
1533         if (st == null) {
1534             ci.println("Please enter node id");
1535             return;
1536         }
1537         Object id = Long.decode(st);
1538         Switch sw = getSwitchByNode(NodeCreator.createOFNode((Long) id));
1539
1540         ci.println("          NodeConnector                        Name");
1541         if (sw == null) {
1542             return;
1543         }
1544         Set<NodeConnector> nodeConnectorSet = sw.getNodeConnectors();
1545         String nodeConnectorName;
1546         if (nodeConnectorSet != null && nodeConnectorSet.size() > 0) {
1547             for (NodeConnector nodeConnector : nodeConnectorSet) {
1548                 Map<String, Property> propMap = getNodeConnectorProps(nodeConnector);
1549                 nodeConnectorName = (propMap == null) ? null : ((Name) propMap
1550                         .get(Name.NamePropName)).getValue();
1551                 if (nodeConnectorName != null) {
1552                     Node node = nodeConnector.getNode();
1553                     if (!node.equals(getNode((Long) id))) {
1554                         log.debug("node not match {} {}", node,
1555                                 getNode((Long) id));
1556                     }
1557                     Map<String, NodeConnector> map = nodeConnectorNames
1558                             .get(node);
1559                     if (map != null) {
1560                         NodeConnector nc = map.get(nodeConnectorName);
1561                         if (nc == null) {
1562                             log.debug("no nodeConnector named {}",
1563                                     nodeConnectorName);
1564                         } else if (!nc.equals(nodeConnector)) {
1565                             log.debug("nodeConnector not match {} {}", nc,
1566                                     nodeConnector);
1567                         }
1568                     }
1569                 }
1570
1571                 ci.println(nodeConnector
1572                         + "            "
1573                         + ((nodeConnectorName == null) ? "" : nodeConnectorName)
1574                         + "(" + nodeConnector.getID() + ")");
1575             }
1576             ci.println("Total number of NodeConnectors: "
1577                     + nodeConnectorSet.size());
1578         }
1579     }
1580
1581     public void _snt(CommandInterpreter ci) {
1582         String st = ci.nextArgument();
1583         if (st == null) {
1584             ci.println("Please enter node id");
1585             return;
1586         }
1587         Long id = Long.decode(st);
1588
1589         Node node = NodeCreator.createOFNode(id);
1590
1591         st = ci.nextArgument();
1592         if (st == null) {
1593             ci.println("Please enter tier number");
1594             return;
1595         }
1596         Integer tid = Integer.decode(st);
1597         Tier tier = new Tier(tid);
1598         setNodeProp(node, tier);
1599     }
1600
1601     public void _hostRefresh(CommandInterpreter ci) {
1602         String mode = ci.nextArgument();
1603         if (mode == null) {
1604             ci.println("expecting on/off/?");
1605             return;
1606         }
1607         if (mode.toLowerCase().equals("on"))
1608             hostRefresh = true;
1609         else if (mode.toLowerCase().equals("off"))
1610             hostRefresh = false;
1611         else if (mode.equals("?")) {
1612             if (hostRefresh)
1613                 ci.println("host refresh is ON");
1614             else
1615                 ci.println("host refresh is OFF");
1616         } else
1617             ci.println("expecting on/off/?");
1618         return;
1619     }
1620
1621     public void _hostRetry(CommandInterpreter ci) {
1622         String retry = ci.nextArgument();
1623         if (retry == null) {
1624             ci.println("Please enter a valid number. Current retry count is "
1625                     + hostRetryCount);
1626             return;
1627         }
1628         try {
1629             hostRetryCount = Integer.parseInt(retry);
1630         } catch (Exception e) {
1631             ci.println("Please enter a valid number");
1632         }
1633         return;
1634     }
1635
1636     @Override
1637     public byte[] getNodeMAC(Node node) {
1638         if (node.getType().equals(Node.NodeIDType.OPENFLOW)) {
1639             byte[] gmac = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
1640             long dpid = (Long) node.getID();
1641
1642             for (short i = 0; i < 6; i++) {
1643                 gmac[5 - i] = (byte) dpid;
1644                 dpid >>= 8;
1645             }
1646             return gmac;
1647         }
1648         return null;
1649     }
1650
1651     @Override
1652     public boolean isSpecial(NodeConnector p) {
1653         if (p.getType().equals(NodeConnectorIDType.CONTROLLER)
1654                 || p.getType().equals(NodeConnectorIDType.ALL)
1655                 || p.getType().equals(NodeConnectorIDType.SWSTACK)
1656                 || p.getType().equals(NodeConnectorIDType.HWPATH)) {
1657             return true;
1658         }
1659         return false;
1660     }
1661
1662     /*
1663      * Add span configuration to local cache and notify clients
1664      */
1665     private void addSpanPorts(Node node, List<NodeConnector> nodeConncetors) {
1666         List<NodeConnector> ncLists = new ArrayList<NodeConnector>();
1667
1668         for (NodeConnector nodeConnector : nodeConncetors) {
1669             if (!spanNodeConnectors.contains(nodeConnector)) {
1670                 ncLists.add(nodeConnector);
1671             }
1672         }
1673
1674         if (ncLists.size() > 0) {
1675             spanNodeConnectors.addAll(ncLists);
1676             notifySpanPortChange(node, ncLists, true);
1677         }
1678     }
1679
1680     private void addSpanPorts(Node node) {
1681         for (SpanConfig conf : getSpanConfigList(node)) {
1682             addSpanPorts(node, conf.getPortArrayList());
1683         }
1684     }
1685
1686     private void addSpanPort(NodeConnector nodeConncetor) {
1687         List<NodeConnector> ncLists = new ArrayList<NodeConnector>();
1688         ncLists.add(nodeConncetor);
1689         addSpanPorts(nodeConncetor.getNode(), ncLists);
1690     }
1691
1692     /*
1693      * Remove span configuration to local cache and notify clients
1694      */
1695     private void removeSpanPorts(Node node, List<NodeConnector> nodeConncetors) {
1696         List<NodeConnector> ncLists = new ArrayList<NodeConnector>();
1697
1698         for (NodeConnector nodeConnector : nodeConncetors) {
1699             if (!spanNodeConnectors.contains(nodeConnector)) {
1700                 ncLists.add(nodeConnector);
1701             }
1702         }
1703
1704         if (ncLists.size() > 0) {
1705             spanNodeConnectors.removeAll(ncLists);
1706             notifySpanPortChange(node, ncLists, false);
1707         }
1708     }
1709
1710     private void removeSpanPorts(Node node) {
1711         for (SpanConfig conf : getSpanConfigList(node)) {
1712             addSpanPorts(node, conf.getPortArrayList());
1713         }
1714     }
1715
1716     private void removeSpanPort(NodeConnector nodeConncetor) {
1717         List<NodeConnector> ncLists = new ArrayList<NodeConnector>();
1718         ncLists.add(nodeConncetor);
1719         removeSpanPorts(nodeConncetor.getNode(), ncLists);
1720     }
1721
1722     private void addNodeProps(Node node, Map<String, Property> propMap) {
1723         if (propMap == null) {
1724             propMap = new HashMap<String, Property>();
1725         }
1726         nodeProps.put(node, propMap);
1727     }
1728
1729     private void removeNodeProps(Node node) {
1730         if (getUpNodeConnectors(node).size() == 0) {
1731             nodeProps.remove(node);
1732         }
1733     }
1734
1735     @Override
1736     public Status saveConfiguration() {
1737         return saveSwitchConfig();
1738     }
1739
1740     /**
1741      * Creates a Name/Tier/Bandwidth Property object based on given property
1742      * name and value. Other property types are not supported yet.
1743      * 
1744      * @param propName
1745      *            Name of the Property
1746      * @param propValue
1747      *            Value of the Property
1748      * @return {@link org.opendaylight.controller.sal.core.Property}
1749      */
1750     @Override
1751     public Property createProperty(String propName, String propValue) {
1752         if (propName == null) {
1753             log.debug("propName is null");
1754             return null;
1755         }
1756         if (propValue == null) {
1757             log.debug("propValue is null");
1758             return null;
1759         }
1760
1761         try {
1762             if (propName.equalsIgnoreCase(Description.propertyName)) {
1763                 return new Description(propValue);
1764             } else if (propName.equalsIgnoreCase(Tier.TierPropName)) {
1765                 int tier = Integer.parseInt(propValue);
1766                 return new Tier(tier);
1767             } else if (propName.equalsIgnoreCase(Bandwidth.BandwidthPropName)) {
1768                 long bw = Long.parseLong(propValue);
1769                 return new Bandwidth(bw);
1770             } else {
1771                 log.debug("Not able to create {} property", propName);
1772             }
1773         } catch (Exception e) {
1774             log.debug("createProperty caught exception {}", e.getMessage());
1775         }
1776
1777         return null;
1778     }
1779
1780     @Override
1781     public String getNodeDescription(Node node) {
1782         // Check first if user configured a name
1783         SwitchConfig config = getSwitchConfig(node.toString());
1784         if (config != null) {
1785             String configuredDesc = config.getNodeDescription();
1786             if (configuredDesc != null && !configuredDesc.isEmpty()) {
1787                 return configuredDesc;
1788             }
1789         }
1790
1791         // No name configured by user, get the node advertised name
1792         Description desc = (Description) getNodeProp(node,
1793                 Description.propertyName);
1794         return (desc == null /* || desc.getValue().equalsIgnoreCase("none") */) ? ""
1795                 : desc.getValue();
1796     }
1797 }