Merge "Fixed the problem in which different containers could have different mac addre...
authorAlessandro Boch <aboch@cisco.com>
Thu, 20 Mar 2014 01:14:43 +0000 (01:14 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Thu, 20 Mar 2014 01:14:43 +0000 (01:14 +0000)
opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/Activator.java
opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/ControllerProperties.java [new file with mode: 0644]
opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/IControllerProperties.java [new file with mode: 0644]
opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManager.java

index 002e06c0bf4fb3b84d3de4e2f6982552ed86a8b3..0f11284e53a4bce1db970d66ccc1a86cf024dc67 100644 (file)
@@ -11,6 +11,7 @@ package org.opendaylight.controller.switchmanager.internal;
 
 import org.apache.felix.dm.Component;
 import org.opendaylight.controller.clustering.services.IClusterContainerServices;
+import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
 import org.opendaylight.controller.configuration.IConfigurationContainerAware;
 import org.opendaylight.controller.configuration.IConfigurationContainerService;
 import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
@@ -100,12 +101,34 @@ public class Activator extends ComponentActivatorAbstractBase {
                     IConfigurationContainerService.class).setCallbacks(
                     "setConfigurationContainerService",
                     "unsetConfigurationContainerService").setRequired(true));
+            c.add(createServiceDependency()
+                    .setService(IControllerProperties.class)
+                    .setCallbacks("setControllerProperties", "unsetControllerProperties")
+                    .setRequired(true));
         }
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     protected Object[] getGlobalImplementations() {
-        final Object[] res = { SwitchManagerCLI.class };
+        final Object[] res = { ControllerProperties.class, SwitchManagerCLI.class };
         return res;
     }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void configureGlobalInstance(Component c, Object imp) {
+        if (imp.equals(ControllerProperties.class)) {
+            c.setInterface(new String[] { IControllerProperties.class.getName() }, null);
+
+            c.add(createServiceDependency()
+                    .setService(IClusterGlobalServices.class)
+                    .setCallbacks("setClusterService", "unsetClusterService")
+                    .setRequired(true));
+        }
+    }
 }
diff --git a/opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/ControllerProperties.java b/opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/ControllerProperties.java
new file mode 100644 (file)
index 0000000..4b319b8
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.switchmanager.internal;
+
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.EnumSet;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
+import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.sal.core.MacAddress;
+import org.opendaylight.controller.sal.core.Property;
+import org.opendaylight.controller.sal.utils.HexEncode;
+import org.opendaylight.controller.sal.utils.Status;
+import org.opendaylight.controller.sal.utils.StatusCode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The class ControllerProperties
+ * provides implementation for the ControllerProperties API
+ */
+public class ControllerProperties implements IControllerProperties {
+
+    private IClusterGlobalServices clusterService = null;
+    private final Logger log = LoggerFactory
+            .getLogger(ControllerProperties.class);
+    private static final String controllerGlobalPropertiesCacheName = "switchmanager.controllerGlobalProperties";
+
+    private ConcurrentMap<String, Property> controllerGlobalProperties;
+
+    private void allocateCaches() {
+        if (this.clusterService == null) {
+            this.nonClusterObjectCreate();
+            log.warn("un-initialized clusterService, can't create cache");
+            return;
+        }
+        try {
+            this.clusterService.createCache(controllerGlobalPropertiesCacheName,
+                    EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+        } catch (CacheConfigException cce) {
+            log.error("\nCache configuration invalid - check cache mode");
+        } catch (CacheExistException ce) {
+            log.error("\nCache already exits - destroy and recreate if needed");
+        }
+    }
+
+    private void nonClusterObjectCreate() {
+        controllerGlobalProperties = new ConcurrentHashMap<String, Property>();
+    }
+
+    @SuppressWarnings({ "unchecked" })
+    private void retrieveCaches() {
+        if (this.clusterService == null) {
+            log.warn("un-initialized clusterService, can't create cache");
+            return;
+        }
+        controllerGlobalProperties = (ConcurrentMap<String, Property>) this.clusterService
+                .getCache(controllerGlobalPropertiesCacheName);
+        if (controllerGlobalProperties == null) {
+            log.error("\nFailed to get cache for controllerGlobalProperties");
+        }
+    }
+
+    /**
+     * Function called by the dependency manager when all the required
+     * dependencies are satisfied
+     *
+     * @param c Component
+     */
+    void init(Component c) {
+        // Instantiate cluster synced variables
+        allocateCaches();
+        retrieveCaches();
+    }
+
+    private void initializeProperties() {
+        byte controllerMac[] = getHardwareMAC();
+        if (controllerMac != null) {
+            Property existing = controllerGlobalProperties.putIfAbsent(MacAddress.name, new MacAddress(controllerMac));
+            if (existing == null && log.isTraceEnabled()) {
+                log.trace("Setting controller MAC address in the cluster: {}", HexEncode.bytesToHexStringFormat(controllerMac));
+            }
+        }
+    }
+
+    private byte[] getHardwareMAC() {
+        Enumeration<NetworkInterface> nis;
+        byte[] macAddress = null;
+
+        try {
+            nis = NetworkInterface.getNetworkInterfaces();
+        } catch (SocketException e) {
+            log.error("Failed to acquire controller MAC: ", e);
+            return macAddress;
+        }
+
+        while (nis.hasMoreElements()) {
+            NetworkInterface ni = nis.nextElement();
+            try {
+                macAddress = ni.getHardwareAddress();
+            } catch (SocketException e) {
+                log.error("Failed to acquire controller MAC: ", e);
+            }
+            if (macAddress != null && macAddress.length != 0) {
+                break;
+            }
+        }
+        if (macAddress == null) {
+            log.warn("Failed to acquire controller MAC: No physical interface found");
+            // This happens when running controller on windows VM, for example
+            // TODO: Try parsing the OS command output
+            // For now provide a quick fix for the release
+            macAddress = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x0c, (byte) 0x60, (byte) 0x0D, (byte) 0x10 };
+            log.debug("Assigning custom MAC address to controller");
+        }
+        return macAddress;
+    }
+
+    /**
+     * Function called by dependency manager after "init ()" is called and after
+     * the services provided by the class are registered in the service registry
+     *
+     */
+    void start() {
+        // initialize required properties if first node in the cluster
+        if(this.clusterService.amICoordinator()) {
+            initializeProperties();
+        }
+    }
+
+    /**
+     * Function called after registered the service in OSGi service registry.
+     */
+    void started() {
+        // nothing to do
+    }
+
+    /**
+     * Function called before services of the component are removed
+     * from OSGi service registry.
+     */
+    void stopping() {
+        // nothing to do
+    }
+
+    /**
+     * Function called by the dependency manager before the services exported by
+     * the component are unregistered, this will be followed by a "destroy ()"
+     * calls
+     *
+     */
+    void stop() {
+        // nothing to do
+    }
+
+    /**
+     * Function called by the dependency manager when at least one dependency
+     * become unsatisfied or when the component is shutting down because for
+     * example bundle is being stopped.
+     *
+     */
+    void destroy() {
+        // nothing to do
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Map<String, Property> getControllerProperties() {
+        return new HashMap<String, Property>(this.controllerGlobalProperties);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Property getControllerProperty(String propertyName) {
+        if (propertyName != null) {
+            return this.controllerGlobalProperties.get(propertyName);
+        }
+        return null;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Status setControllerProperty(Property property) {
+        if (property != null) {
+            this.controllerGlobalProperties.put(property.getName(), property);
+            return new Status(StatusCode.SUCCESS);
+        }
+        return new Status(StatusCode.BADREQUEST, "Invalid property provided when setting property");
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Status removeControllerProperty(String propertyName) {
+        if (propertyName != null) {
+            this.controllerGlobalProperties.remove(propertyName);
+            return new Status(StatusCode.SUCCESS);
+        }
+        return new Status(StatusCode.BADREQUEST, "Invalid property provided when removing property");
+    }
+
+    /**
+     * setClusterService
+     * @param s
+     */
+    public void setClusterService(IClusterGlobalServices s) {
+        this.clusterService = s;
+    }
+
+    /**
+     * unsetClusterServices
+     * @param s
+     */
+    public void unsetClusterServices(IClusterGlobalServices s) {
+        if (this.clusterService == s) {
+            this.clusterService = null;
+        }
+    }
+
+}
diff --git a/opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/IControllerProperties.java b/opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/IControllerProperties.java
new file mode 100644 (file)
index 0000000..f9301e2
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.switchmanager.internal;
+
+import java.util.Map;
+
+import org.opendaylight.controller.sal.core.Property;
+import org.opendaylight.controller.sal.utils.Status;
+
+/**
+ * The class ControllerProperties is a global store
+ * for controller properties. Use this api to store/retrieve properties
+ * that are container independent.
+ *
+ * This is visible only to switch manager. Hence its a part of
+ * switch manager internal bundle.
+ */
+public interface IControllerProperties {
+
+    /**
+     * Return all the global properties of the controller
+     *
+     * @return map of {@link org.opendaylight.controller.sal.core.Property} such
+     *         as {@link org.opendaylight.controller.sal.core.Description}
+     *         and/or {@link org.opendaylight.controller.sal.core.Tier} etc.
+     */
+    public Map<String, Property> getControllerProperties();
+
+    /**
+     * Return a specific property of the controller given the property name
+     *
+     * @param propertyName
+     *            the property name specified by
+     *            {@link org.opendaylight.controller.sal.core.Property} and its
+     *            extended classes
+     * @return {@link org.opendaylight.controller.sal.core.Property}
+     */
+    public Property getControllerProperty(String propertyName);
+
+    /**
+     * Set a specific property of the controller
+     *
+     * @param property
+     *            {@link org.opendaylight.controller.sal.core.Property}
+     * @return Status
+     */
+    public Status setControllerProperty(Property property);
+
+    /**
+     * Remove a property of a node
+     *
+     * @param propertyName
+     *            the property name specified by
+     *            {@link org.opendaylight.controller.sal.core.Property} and its
+     *            extended classes
+     * @return success or failed reason
+     */
+    public Status removeControllerProperty(String propertyName);
+
+}
index e457fecfedf9b75d5ec1f59f006d64775472e144..07252b06f78dfb2a80a4c88d112f6b3f41fd5422 100644 (file)
@@ -12,13 +12,10 @@ import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.net.InetAddress;
-import java.net.NetworkInterface;
-import java.net.SocketException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Dictionary;
 import java.util.EnumSet;
-import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -56,7 +53,6 @@ import org.opendaylight.controller.sal.inventory.IInventoryService;
 import org.opendaylight.controller.sal.inventory.IListenInventoryUpdates;
 import org.opendaylight.controller.sal.reader.NodeDescription;
 import org.opendaylight.controller.sal.utils.GlobalConstants;
-import org.opendaylight.controller.sal.utils.HexEncode;
 import org.opendaylight.controller.sal.utils.IObjectReader;
 import org.opendaylight.controller.sal.utils.Status;
 import org.opendaylight.controller.sal.utils.StatusCode;
@@ -102,6 +98,7 @@ public class SwitchManager implements ISwitchManager, IConfigurationContainerAwa
     private ConcurrentMap<String, Property> controllerProps;
     private IInventoryService inventoryService;
     private IStatisticsManager statisticsManager;
+    private IControllerProperties controllerProperties;
     private IConfigurationContainerService configurationService;
     private final Set<ISwitchManagerAware> switchManagerAware = Collections
             .synchronizedSet(new HashSet<ISwitchManagerAware>());
@@ -171,13 +168,13 @@ public class SwitchManager implements ISwitchManager, IConfigurationContainerAwa
         retrieveCaches();
 
         // Add controller MAC, if first node in the cluster
-        if (!controllerProps.containsKey(MacAddress.name)) {
-            byte controllerMac[] = getHardwareMAC();
+        if ((!controllerProps.containsKey(MacAddress.name)) && (controllerProperties != null)) {
+            Property controllerMac = controllerProperties.getControllerProperty(MacAddress.name);
             if (controllerMac != null) {
-                Property existing = controllerProps.putIfAbsent(MacAddress.name, new MacAddress(controllerMac));
+                Property existing = controllerProps.putIfAbsent(MacAddress.name, controllerMac);
                 if (existing == null && log.isTraceEnabled()) {
                     log.trace("Container {}: Setting controller MAC address in the cluster: {}", getContainerName(),
-                            HexEncode.bytesToHexStringFormat(controllerMac));
+                            controllerMac);
                 }
             }
         }
@@ -1405,36 +1402,6 @@ public class SwitchManager implements ISwitchManager, IConfigurationContainerAwa
         return (propMap != null) ? propMap.get(propName) : null;
     }
 
-    private byte[] getHardwareMAC() {
-        Enumeration<NetworkInterface> nis;
-        byte[] macAddress = null;
-
-        try {
-            nis = NetworkInterface.getNetworkInterfaces();
-        } catch (SocketException e) {
-            log.error("Failed to acquire controller MAC: ", e);
-            return macAddress;
-        }
-
-        while (nis.hasMoreElements()) {
-            NetworkInterface ni = nis.nextElement();
-            try {
-                macAddress = ni.getHardwareAddress();
-            } catch (SocketException e) {
-                log.error("Failed to acquire controller MAC: ", e);
-            }
-            if (macAddress != null && macAddress.length != 0) {
-                break;
-            }
-        }
-        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() {
         MacAddress macProperty = (MacAddress)controllerProps.get(MacAddress.name);
@@ -1793,6 +1760,16 @@ public class SwitchManager implements ISwitchManager, IConfigurationContainerAwa
         }
     }
 
+    public void setControllerProperties(IControllerProperties controllerProperties) {
+        log.trace("Got controller properties set request {}", controllerProperties);
+        this.controllerProperties = controllerProperties;
+    }
+
+    public void unsetControllerProperties(IControllerProperties controllerProperties) {
+        log.trace("Got controller properties UNset request");
+        this.controllerProperties = null;
+    }
+
     private void getInventories() {
         if (inventoryService == null) {
             log.trace("inventory service not avaiable");