Controller MAC to be synced in cluster 79/779/3
authorAlessandro Boch <aboch@cisco.com>
Sat, 3 Aug 2013 16:34:23 +0000 (09:34 -0700)
committerAlessandro Boch <aboch@cisco.com>
Sat, 3 Aug 2013 16:34:23 +0000 (09:34 -0700)
CHANGE:
- Add a new property database for controller properties in switch manager.
  Switch manager maintains the container inventory and we could have
   different controller properties in different container instances.
- Have switch mgr acquire the hardware mac and set the MacAddress
  controller property only if no other controller has already done so
- Removed ReasonCode enum that was old and unused
- Rename SwitchManagerImpl class to SwitchManager as it is already part
  of the implementaiton package

Change-Id: Id3859d0ca7873ea2e3c2f597e0003bd220e90d9a
Signed-off-by: Alessandro Boch <aboch@cisco.com>
opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/Activator.java
opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManager.java [moved from opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManagerImpl.java with 96% similarity]
opendaylight/switchmanager/implementation/src/test/java/org/opendaylight/controller/switchmanager/internal/SwitchManagerTest.java [moved from opendaylight/switchmanager/implementation/src/test/java/org/opendaylight/controller/switchmanager/internal/SwitchManagerImplTest.java with 96% similarity]

index d4511ff..2420d60 100644 (file)
@@ -66,7 +66,7 @@ public class Activator extends ComponentActivatorAbstractBase {
      * Object
      */
     public Object[] getImplementations() {
-        Object[] res = { SwitchManagerImpl.class };
+        Object[] res = { SwitchManager.class };
         return res;
     }
 
@@ -84,7 +84,7 @@ public class Activator extends ComponentActivatorAbstractBase {
      * should not be the case though.
      */
     public void configureInstance(Component c, Object imp, String containerName) {
-        if (imp.equals(SwitchManagerImpl.class)) {
+        if (imp.equals(SwitchManager.class)) {
             Dictionary<String, Set<String>> props = new Hashtable<String, Set<String>>();
             Set<String> propSet = new HashSet<String>();
             propSet.add("switchmanager.configSaveEvent");
@@ -83,16 +83,14 @@ import org.slf4j.LoggerFactory;
  * instance per container of the network. All the node/nodeConnector properties
  * are maintained in the default container only.
  */
-public class SwitchManagerImpl implements ISwitchManager,
+public class SwitchManager implements ISwitchManager,
 IConfigurationContainerAware, IObjectReader,
 ICacheUpdateAware<Long, String>, IListenInventoryUpdates,
 CommandProvider {
-    private static Logger log = LoggerFactory
-            .getLogger(SwitchManagerImpl.class);
+    private static Logger log = LoggerFactory.getLogger(SwitchManager.class);
     private static String ROOT = GlobalConstants.STARTUPHOME.toString();
     private static final String SAVE = "Save";
-    private String subnetFileName = null, spanFileName = null,
-            switchConfigFileName = null;
+    private String subnetFileName, spanFileName, switchConfigFileName;
     private final List<NodeConnector> spanNodeConnectors = new CopyOnWriteArrayList<NodeConnector>();
     // set of Subnets keyed by the InetAddress
     private ConcurrentMap<InetAddress, Subnet> subnets;
@@ -104,14 +102,13 @@ CommandProvider {
     private ConcurrentMap<Node, Map<String, Property>> nodeProps;
     private ConcurrentMap<NodeConnector, Map<String, Property>> nodeConnectorProps;
     private ConcurrentMap<Node, Map<String, NodeConnector>> nodeConnectorNames;
+    private ConcurrentMap<String, Property> controllerProps;
     private IInventoryService inventoryService;
     private final Set<ISwitchManagerAware> switchManagerAware = Collections
             .synchronizedSet(new HashSet<ISwitchManagerAware>());
     private final Set<IInventoryListener> inventoryListeners = Collections
             .synchronizedSet(new HashSet<IInventoryListener>());
-    private final Set<ISpanAware> spanAware = Collections
-            .synchronizedSet(new HashSet<ISpanAware>());
-    private byte[] MAC;
+    private final Set<ISpanAware> spanAware = Collections.synchronizedSet(new HashSet<ISpanAware>());
     private static boolean hostRefresh = true;
     private int hostRetryCount = 5;
     private IClusterContainerServices clusterContainerService = null;
@@ -119,23 +116,6 @@ CommandProvider {
     private boolean isDefaultContainer = true;
     private static final int REPLACE_RETRY = 1;
 
-    public enum ReasonCode {
-        SUCCESS("Success"), FAILURE("Failure"), INVALID_CONF(
-                "Invalid Configuration"), EXIST("Entry Already Exist"), CONFLICT(
-                        "Configuration Conflict with Existing Entry");
-
-        private final String name;
-
-        private ReasonCode(String name) {
-            this.name = name;
-        }
-
-        @Override
-        public String toString() {
-            return name;
-        }
-    }
-
     public void notifySubnetChange(Subnet sub, boolean add) {
         synchronized (switchManagerAware) {
             for (Object subAware : switchManagerAware) {
@@ -149,8 +129,7 @@ CommandProvider {
         }
     }
 
-    public void notifySpanPortChange(Node node, List<NodeConnector> ports,
-            boolean add) {
+    public void notifySpanPortChange(Node node, List<NodeConnector> ports, boolean add) {
         synchronized (spanAware) {
             for (Object sa : spanAware) {
                 try {
@@ -177,11 +156,11 @@ CommandProvider {
     }
 
     public void startUp() {
+        String container = this.getContainerName();
         // Initialize configuration file names
-        subnetFileName = ROOT + "subnets_" + this.getContainerName() + ".conf";
-        spanFileName = ROOT + "spanPorts_" + this.getContainerName() + ".conf";
-        switchConfigFileName = ROOT + "switchConfig_" + this.getContainerName()
-                + ".conf";
+        subnetFileName = ROOT + "subnets_" + container + ".conf";
+        spanFileName = ROOT + "spanPorts_" + container + ".conf";
+        switchConfigFileName = ROOT + "switchConfig_" + container + ".conf";
 
         // Instantiate cluster synced variables
         allocateCaches();
@@ -201,7 +180,17 @@ CommandProvider {
             loadSwitchConfiguration();
         }
 
-        MAC = getHardwareMAC();
+        // Add controller MAC, if first node in the cluster
+        if (!controllerProps.containsKey(MacAddress.name)) {
+            byte controllerMac[] = getHardwareMAC();
+            if (controllerMac != null) {
+                Property existing = controllerProps.putIfAbsent(MacAddress.name, new MacAddress(controllerMac));
+                if (existing == null && log.isTraceEnabled()) {
+                    log.trace("Container {}: Setting controller MAC address in the cluster: {}", container,
+                            HexEncode.bytesToHexStringFormat(controllerMac));
+                }
+            }
+        }
     }
 
     public void shutDown() {
@@ -236,6 +225,9 @@ CommandProvider {
             clusterContainerService.createCache(
                     "switchmanager.nodeConnectorNames",
                     EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+            clusterContainerService.createCache(
+                    "switchmanager.controllerProps",
+                    EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
         } catch (CacheConfigException cce) {
             log.error("\nCache configuration invalid - check cache mode");
         } catch (CacheExistException ce) {
@@ -297,6 +289,12 @@ CommandProvider {
         if (nodeConnectorNames == null) {
             log.error("\nFailed to get cache for nodeConnectorNames");
         }
+
+        controllerProps = (ConcurrentMap<String, Property>) clusterContainerService
+                .getCache("switchmanager.controllerProps");
+        if (controllerProps == null) {
+            log.error("\nFailed to get cache for controllerProps");
+        }
     }
 
     private void nonClusterObjectCreate() {
@@ -308,6 +306,7 @@ CommandProvider {
         nodeProps = new ConcurrentHashMap<Node, Map<String, Property>>();
         nodeConnectorProps = new ConcurrentHashMap<NodeConnector, Map<String, Property>>();
         nodeConnectorNames = new ConcurrentHashMap<Node, Map<String, NodeConnector>>();
+        controllerProps = new ConcurrentHashMap<String, Property>();
     }
 
     @Override
@@ -1233,30 +1232,38 @@ CommandProvider {
 
     private byte[] getHardwareMAC() {
         Enumeration<NetworkInterface> nis;
+        byte[] macAddress = null;
+
         try {
             nis = NetworkInterface.getNetworkInterfaces();
-        } catch (SocketException e1) {
-            log.error("",e1);
-            return null;
+        } catch (SocketException e) {
+            log.error("Failed to acquire controller MAC: ", e);
+            return macAddress;
         }
-        byte[] MAC = null;
-        for (; nis.hasMoreElements();) {
+
+        while (nis.hasMoreElements()) {
             NetworkInterface ni = nis.nextElement();
             try {
-                MAC = ni.getHardwareAddress();
+                macAddress = ni.getHardwareAddress();
             } catch (SocketException e) {
-                log.error("",e);
+                log.error("Failed to acquire controller MAC: ", e);
             }
-            if (MAC != null) {
-                return MAC;
+            if (macAddress != null) {
+                break;
             }
         }
-        return null;
+        if (macAddress == null) {
+            log.warn("Failed to acquire controller MAC: No physical interface found");
+            // This happens when running controller on windows VM, for example
+            // Try parsing the OS command output
+        }
+        return macAddress;
     }
 
     @Override
     public byte[] getControllerMAC() {
-        return MAC;
+        MacAddress macProperty = (MacAddress)controllerProps.get(MacAddress.name);
+        return (macProperty == null) ? null : macProperty.getMacAddress();
     }
 
     @Override
@@ -26,11 +26,11 @@ import org.opendaylight.controller.sal.utils.NodeCreator;
 import org.opendaylight.controller.sal.utils.Status;
 import org.opendaylight.controller.switchmanager.SubnetConfig;
 
-public class SwitchManagerImplTest {
+public class SwitchManagerTest {
 
     @Test
     public void testSwitchManagerAddRemoveSubnet() {
-        SwitchManagerImpl switchmgr = new SwitchManagerImpl();
+        SwitchManager switchmgr = new SwitchManager();
         switchmgr.startUp();
 
         ArrayList<String> portList = new ArrayList<String>();
@@ -55,7 +55,7 @@ public class SwitchManagerImplTest {
 
     @Test
     public void testSwitchManagerNodeConnectors() {
-        SwitchManagerImpl switchmgr = new SwitchManagerImpl();
+        SwitchManager switchmgr = new SwitchManager();
         switchmgr.startUp();
 
         State state;