Configuration Save event sync mechanism using Clustering services. 68/568/1
authorMadhu Venugopal <vmadhu@cisco.com>
Fri, 5 Jul 2013 06:17:37 +0000 (23:17 -0700)
committerMadhu Venugopal <vmadhu@cisco.com>
Fri, 5 Jul 2013 06:17:37 +0000 (23:17 -0700)
Every Controller in the cluster will receive a Config save event and the save is performed locally on each of the Controllers.
This is the first step towards the centralized configuration service.

Change-Id: Icbff65117ccb237a4c31091d392b27de43d8ae1d
Signed-off-by: Madhu Venugopal <vmadhu@cisco.com>
opendaylight/configuration/api/src/main/java/org/opendaylight/controller/configuration/ConfigurationEvent.java [new file with mode: 0644]
opendaylight/configuration/implementation/src/main/java/org/opendaylight/controller/configuration/internal/Activator.java
opendaylight/configuration/implementation/src/main/java/org/opendaylight/controller/configuration/internal/ConfigurationImpl.java

diff --git a/opendaylight/configuration/api/src/main/java/org/opendaylight/controller/configuration/ConfigurationEvent.java b/opendaylight/configuration/api/src/main/java/org/opendaylight/controller/configuration/ConfigurationEvent.java
new file mode 100644 (file)
index 0000000..77333e2
--- /dev/null
@@ -0,0 +1,27 @@
+package org.opendaylight.controller.configuration;
+
+public enum ConfigurationEvent {
+    SAVE("Save"),
+    BACKUP("Backup"),
+    RESTORE("Restore"),
+    DELETE("Delete");
+
+    private ConfigurationEvent(String name) {
+        this.name = name;
+    }
+
+    private String name;
+
+    public String toString() {
+        return name;
+    }
+
+    public static ConfigurationEvent fromString(String pName) {
+        for(ConfigurationEvent p:ConfigurationEvent.values()) {
+            if (p.toString().equals(pName)) {
+                return p;
+            }
+        }
+        return null;
+    }
+}
index 9fb5b159f64e395249140f3eae4143502665162d..78b64400c8fcc44acba896397d621243848f9ea4 100644 (file)
@@ -9,7 +9,13 @@
 
 package org.opendaylight.controller.configuration.internal;
 
 
 package org.opendaylight.controller.configuration.internal;
 
+import java.util.Dictionary;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Set;
+
 import org.apache.felix.dm.Component;
 import org.apache.felix.dm.Component;
+import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
 import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
 import org.opendaylight.controller.configuration.IConfigurationAware;
 import org.opendaylight.controller.configuration.IConfigurationContainerAware;
 import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
 import org.opendaylight.controller.configuration.IConfigurationAware;
 import org.opendaylight.controller.configuration.IConfigurationContainerAware;
@@ -84,8 +90,8 @@ public class Activator extends ComponentActivatorAbstractBase {
 
             c.add(createContainerServiceDependency(containerName).setService(
                     IConfigurationContainerAware.class).setCallbacks(
 
             c.add(createContainerServiceDependency(containerName).setService(
                     IConfigurationContainerAware.class).setCallbacks(
-                    "addConfigurationContainerAware",
-                    "removeConfigurationContainerAware").setRequired(false));
+                            "addConfigurationContainerAware",
+                            "removeConfigurationContainerAware").setRequired(false));
         }
     }
 
         }
     }
 
@@ -117,21 +123,26 @@ public class Activator extends ComponentActivatorAbstractBase {
      */
     protected void configureGlobalInstance(Component c, Object imp) {
         if (imp.equals(ConfigurationImpl.class)) {
      */
     protected void configureGlobalInstance(Component c, Object imp) {
         if (imp.equals(ConfigurationImpl.class)) {
+            Dictionary<String, Set<String>> props = new Hashtable<String, Set<String>>();
+            Set<String> propSet = new HashSet<String>();
+            propSet.add("config.event.save");
+            props.put("cachenames", propSet);
 
             // export the service
             c.setInterface(
 
             // export the service
             c.setInterface(
-                    new String[] { IConfigurationService.class.getName() },
-                    null);
+                    new String[] { IConfigurationService.class.getName(),
+                            ICacheUpdateAware.class.getName()},
+                            props);
 
             c.add(createServiceDependency().setService(
                     IClusterGlobalServices.class).setCallbacks(
 
             c.add(createServiceDependency().setService(
                     IClusterGlobalServices.class).setCallbacks(
-                    "setClusterServices", "unsetClusterServices").setRequired(
-                    true));
+                            "setClusterServices", "unsetClusterServices").setRequired(
+                                    true));
 
             c.add(createServiceDependency().setService(
                     IConfigurationAware.class).setCallbacks(
 
             c.add(createServiceDependency().setService(
                     IConfigurationAware.class).setCallbacks(
-                    "addConfigurationAware", "removeConfigurationAware")
-                    .setRequired(false));
+                            "addConfigurationAware", "removeConfigurationAware")
+                            .setRequired(false));
         }
     }
 }
         }
     }
 }
index 20821f10282b038c19202a0f2c9d82839072b08b..8e2741e7d1b1231b5d16ab63af07712ea4a8cad9 100644 (file)
 package org.opendaylight.controller.configuration.internal;
 
 import java.util.Collections;
 package org.opendaylight.controller.configuration.internal;
 
 import java.util.Collections;
+import java.util.EnumSet;
 import java.util.HashSet;
 import java.util.Set;
 import java.util.HashSet;
 import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
 
 
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
 import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
 import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
+import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.configuration.ConfigurationEvent;
 import org.opendaylight.controller.configuration.IConfigurationAware;
 import org.opendaylight.controller.configuration.IConfigurationService;
 import org.opendaylight.controller.sal.utils.StatusCode;
 import org.opendaylight.controller.configuration.IConfigurationAware;
 import org.opendaylight.controller.configuration.IConfigurationService;
 import org.opendaylight.controller.sal.utils.StatusCode;
@@ -29,10 +36,11 @@ import org.slf4j.LoggerFactory;
  *
  */
 
  *
  */
 
-public class ConfigurationImpl implements IConfigurationService {
+public class ConfigurationImpl implements IConfigurationService, ICacheUpdateAware<ConfigurationEvent, String> {
     private static final Logger logger = LoggerFactory
             .getLogger(ConfigurationImpl.class);
     private IClusterGlobalServices clusterServices;
     private static final Logger logger = LoggerFactory
             .getLogger(ConfigurationImpl.class);
     private IClusterGlobalServices clusterServices;
+    private ConcurrentMap <ConfigurationEvent, String> configEvent;
     /*
      * Collection containing the configuration objects.
      * This is configuration world: container names (also the map key)
     /*
      * Collection containing the configuration objects.
      * This is configuration world: container names (also the map key)
@@ -72,6 +80,11 @@ public class ConfigurationImpl implements IConfigurationService {
         logger.info("ContainerManager startup....");
     }
 
         logger.info("ContainerManager startup....");
     }
 
+    public void start() {
+        allocateCache();
+        retrieveCache();
+    }
+
     public void destroy() {
         // Clear local states
         this.configurationAwareList.clear();
     public void destroy() {
         // Clear local states
         this.configurationAwareList.clear();
@@ -79,21 +92,76 @@ public class ConfigurationImpl implements IConfigurationService {
 
     @Override
     public Status saveConfigurations() {
 
     @Override
     public Status saveConfigurations() {
+        if (configEvent != null) {
+            configEvent.put(ConfigurationEvent.SAVE, "");
+        }
+        return saveConfigurationsInternal();
+    }
+
+    private Status saveConfigurationsInternal() {
         boolean success = true;
         for (IConfigurationAware configurationAware : configurationAwareList) {
         boolean success = true;
         for (IConfigurationAware configurationAware : configurationAwareList) {
-                Status status = configurationAware.saveConfiguration();
+            Status status = configurationAware.saveConfiguration();
             if (!status.isSuccess()) {
                 success = false;
                 logger.info("Failed to save config for {}",
             if (!status.isSuccess()) {
                 success = false;
                 logger.info("Failed to save config for {}",
-                                configurationAware.getClass().getName());
+                        configurationAware.getClass().getName());
             }
         }
         if (success) {
             }
         }
         if (success) {
-            return new Status(StatusCode.SUCCESS, null);
+            return new Status(StatusCode.SUCCESS);
         } else {
             return new Status(StatusCode.INTERNALERROR,
         } else {
             return new Status(StatusCode.INTERNALERROR,
-                        "Failed to Save All Configurations");
+                    "Failed to Save All Configurations");
+        }
+    }
+
+    @Override
+    public void entryCreated(ConfigurationEvent key, String cacheName,
+            boolean originLocal) {
+        if (originLocal) return;
+    }
+
+    @Override
+    public void entryUpdated(ConfigurationEvent key, String new_value,
+            String cacheName, boolean originLocal) {
+        if (originLocal) return;
+        if (key == ConfigurationEvent.SAVE) {
+            saveConfigurationsInternal();
         }
     }
 
         }
     }
 
+    @Override
+    public void entryDeleted(ConfigurationEvent key, String cacheName,
+            boolean originLocal) {
+        if (originLocal) return;
+    }
+
+    @SuppressWarnings("deprecation")
+    private void allocateCache() {
+        if (this.clusterServices == null) {
+            logger.error("uninitialized clusterServices, can't create cache");
+            return;
+        }
+        try {
+            this.clusterServices.createCache("config.event.save",
+                    EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+        } catch (CacheConfigException cce) {
+            logger.error("Error creating Configuration cache ", cce);
+        } catch (CacheExistException cce) {
+            logger.error("Configuration Cache already exists, destroy and recreate ", cce);
+        }
+    }
+
+    @SuppressWarnings({ "unchecked", "deprecation" })
+    private void retrieveCache() {
+        if (this.clusterServices == null) {
+            logger.error("uninitialized clusterServices, can't retrieve cache");
+            return;
+        }
+        configEvent = (ConcurrentMap<ConfigurationEvent, String>) this.clusterServices.getCache("config.event.save");
+        if (configEvent == null) {
+            logger.error("Failed to retrieve configuration Cache");
+        }
+    }
 }
 }