Add a mechanism to read the entity owner selection strategies from a config file 05/29405/8
authorMoiz Raja <moraja@cisco.com>
Sun, 11 Oct 2015 07:48:34 +0000 (00:48 -0700)
committerTom Pantelis <tpanteli@brocade.com>
Fri, 13 Nov 2015 00:38:16 +0000 (19:38 -0500)
Change-Id: Ie951e4f83aaf38f00e959f4243820a88cb988788
Signed-off-by: Moiz Raja <moraja@cisco.com>
Signed-off-by: Tom Pantelis <tpanteli@brocade.com>
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/entityownership/selectionstrategy/EntityOwnerSelectionStrategyConfig.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/entityownership/selectionstrategy/EntityOwnerSelectionStrategyConfigReader.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/config/yang/config/distributed_entity_ownership_service/DistributedEntityOwnershipServiceProviderModule.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/config/yang/config/distributed_entity_ownership_service/DistributedEntityOwnershipServiceProviderModuleFactory.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/entityownership/selectionstrategy/EntityOwnerSelectionStrategyConfigReaderTest.java [new file with mode: 0644]

index db2377d4d536fb2c55168ba898633df745e70b51..298589ae0570f585461e0c50ed39d36571c17edb 100644 (file)
@@ -23,6 +23,10 @@ public class EntityOwnerSelectionStrategyConfig {
 
     }
 
+    public boolean isStrategyConfigured(String entityType){
+        return entityTypeToStrategyInfo.get(entityType) != null;
+    }
+
     public EntityOwnerSelectionStrategy createStrategy(String entityType){
         final EntityOwnerSelectionStrategy strategy;
         final EntityOwnerSelectionStrategy existingStrategy = entityTypeToOwnerSelectionStrategy.get(entityType);
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/entityownership/selectionstrategy/EntityOwnerSelectionStrategyConfigReader.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/entityownership/selectionstrategy/EntityOwnerSelectionStrategyConfigReader.java
new file mode 100644 (file)
index 0000000..b6092b2
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2015 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.cluster.datastore.entityownership.selectionstrategy;
+
+import com.google.common.base.Preconditions;
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import javax.annotation.Nullable;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class EntityOwnerSelectionStrategyConfigReader {
+    public static final String CONFIG_ID = "org.opendaylight.controller.cluster.entity-owner-selection-strategies";
+
+    private static final Logger LOG = LoggerFactory.getLogger(EntityOwnerSelectionStrategyConfigReader.class);
+    private final BundleContext bundleContext;
+    private final EntityOwnerSelectionStrategyConfig config;
+
+    public EntityOwnerSelectionStrategyConfigReader(BundleContext bundleContext) {
+        this.bundleContext = Preconditions.checkNotNull(bundleContext);
+        ServiceReference<ConfigurationAdmin> configAdminServiceReference =
+                bundleContext.getServiceReference(ConfigurationAdmin.class);
+        if(configAdminServiceReference == null) {
+            LOG.warn("No ConfigurationAdmin service found");
+            this.config = EntityOwnerSelectionStrategyConfig.newBuilder().build();
+        } else {
+            this.config = readConfiguration(configAdminServiceReference);
+        }
+    }
+
+    private EntityOwnerSelectionStrategyConfig readConfiguration(ServiceReference<ConfigurationAdmin> configAdminServiceReference) {
+        EntityOwnerSelectionStrategyConfig.Builder builder = EntityOwnerSelectionStrategyConfig.newBuilder();
+        ConfigurationAdmin configAdmin = null;
+        try {
+            configAdmin = bundleContext.getService(configAdminServiceReference);
+            Dictionary<String, Object> properties = getProperties(configAdmin);
+            if(properties != null) {
+                Enumeration<String> keys = properties.keys();
+                while (keys.hasMoreElements()) {
+                    String key = keys.nextElement();
+                    String strategyProps = (String) properties.get(key);
+                    String[] strategyClassAndDelay = strategyProps.split(",");
+                    if(strategyClassAndDelay.length >= 1) {
+                        @SuppressWarnings("unchecked")
+                        Class<? extends EntityOwnerSelectionStrategy> aClass
+                        = (Class<? extends EntityOwnerSelectionStrategy>) getClass().getClassLoader().loadClass(strategyClassAndDelay[0]);
+                        long delay = 0;
+                        if(strategyClassAndDelay.length > 1){
+                            delay = Long.parseLong(strategyClassAndDelay[1]);
+                        }
+                        builder.addStrategy(key, aClass, delay);
+                    }
+                }
+            }
+        } catch(Exception e){
+            LOG.warn("Failed to read selection strategy configuration file. All configuration will be ignored.", e);
+        } finally {
+            if(configAdmin != null) {
+                try {
+                    bundleContext.ungetService(configAdminServiceReference);
+                } catch (Exception e) {
+                    LOG.debug("Error from ungetService", e);
+                }
+            }
+        }
+
+        return builder.build();
+    }
+
+    @Nullable
+    private static Dictionary<String, Object> getProperties(ConfigurationAdmin configAdmin) throws IOException {
+        Configuration config = configAdmin.getConfiguration(CONFIG_ID);
+        return config != null ? config.getProperties() : null;
+    }
+
+    public EntityOwnerSelectionStrategyConfig getConfig() {
+        return config;
+    }
+}
index 679f067afc00bd34b112191f9d372722db185ed0..7a43bfd83e29af00cdb57a01e558de72db88aa75 100644 (file)
@@ -4,10 +4,14 @@ import com.google.common.base.Preconditions;
 import org.opendaylight.controller.cluster.datastore.DistributedDataStore;
 import org.opendaylight.controller.cluster.datastore.entityownership.DistributedEntityOwnershipService;
 import org.opendaylight.controller.cluster.datastore.entityownership.selectionstrategy.EntityOwnerSelectionStrategyConfig;
+import org.opendaylight.controller.cluster.datastore.entityownership.selectionstrategy.EntityOwnerSelectionStrategyConfigReader;
 import org.opendaylight.controller.sal.core.spi.data.DOMStore;
+import org.osgi.framework.BundleContext;
 
 
 public class DistributedEntityOwnershipServiceProviderModule extends org.opendaylight.controller.config.yang.config.distributed_entity_ownership_service.AbstractDistributedEntityOwnershipServiceProviderModule {
+    private BundleContext bundleContext;
+
     public DistributedEntityOwnershipServiceProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
         super(identifier, dependencyResolver);
     }
@@ -31,8 +35,13 @@ public class DistributedEntityOwnershipServiceProviderModule extends org.openday
         DOMStore dataStore = getDataStoreDependency();
         Preconditions.checkArgument(dataStore instanceof DistributedDataStore,
                 "Injected DOMStore must be an instance of DistributedDataStore");
-        DistributedEntityOwnershipService service = new DistributedEntityOwnershipService((DistributedDataStore)dataStore, EntityOwnerSelectionStrategyConfig.newBuilder().build());
+        EntityOwnerSelectionStrategyConfig strategyConfig = new EntityOwnerSelectionStrategyConfigReader(bundleContext).getConfig();
+        DistributedEntityOwnershipService service = new DistributedEntityOwnershipService((DistributedDataStore)dataStore, strategyConfig);
         service.start();
         return service;
     }
+
+    public void setBundleContext(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+    }
 }
index 7d7447d4b093ec29ca966a5cd8f6f0016ec976e3..3eb6d9fc7d23e3b30ed31d36fd2e22b7f7d9d832 100644 (file)
@@ -8,6 +8,25 @@
 * Do not modify this file unless it is present under src/main directory
 */
 package org.opendaylight.controller.config.yang.config.distributed_entity_ownership_service;
+
+import org.opendaylight.controller.config.api.DependencyResolver;
+import org.opendaylight.controller.config.api.DynamicMBeanWithInstance;
+import org.opendaylight.controller.config.spi.Module;
+import org.osgi.framework.BundleContext;
+
 public class DistributedEntityOwnershipServiceProviderModuleFactory extends org.opendaylight.controller.config.yang.config.distributed_entity_ownership_service.AbstractDistributedEntityOwnershipServiceProviderModuleFactory {
 
+    @Override
+    public Module createModule(String instanceName, DependencyResolver dependencyResolver, BundleContext bundleContext) {
+        DistributedEntityOwnershipServiceProviderModule module = (DistributedEntityOwnershipServiceProviderModule) super.createModule(instanceName, dependencyResolver, bundleContext);
+        module.setBundleContext(bundleContext);
+        return module;
+    }
+
+    @Override
+    public Module createModule(String instanceName, DependencyResolver dependencyResolver, DynamicMBeanWithInstance old, BundleContext bundleContext) throws Exception {
+        DistributedEntityOwnershipServiceProviderModule module = (DistributedEntityOwnershipServiceProviderModule) super.createModule(instanceName, dependencyResolver, old, bundleContext);
+        module.setBundleContext(bundleContext);
+        return module;
+    }
 }
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/entityownership/selectionstrategy/EntityOwnerSelectionStrategyConfigReaderTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/entityownership/selectionstrategy/EntityOwnerSelectionStrategyConfigReaderTest.java
new file mode 100644 (file)
index 0000000..252e7b7
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2015 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.cluster.datastore.entityownership.selectionstrategy;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import java.io.IOException;
+import java.util.Hashtable;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+public class EntityOwnerSelectionStrategyConfigReaderTest {
+    @Mock
+    private BundleContext mockBundleContext;
+
+    @Mock
+    private ServiceReference<ConfigurationAdmin> mockConfigAdminServiceRef;
+
+    @Mock
+    private ConfigurationAdmin mockConfigAdmin;
+
+    @Mock
+    private Configuration mockConfig;
+
+    @Before
+    public void setup() throws IOException {
+        MockitoAnnotations.initMocks(this);
+
+        doReturn(mockConfigAdminServiceRef).when(mockBundleContext).getServiceReference(ConfigurationAdmin.class);
+        doReturn(mockConfigAdmin).when(mockBundleContext).getService(mockConfigAdminServiceRef);
+
+        doReturn(mockConfig).when(mockConfigAdmin).getConfiguration(EntityOwnerSelectionStrategyConfigReader.CONFIG_ID);
+    }
+
+    @Test
+    public void testReadStrategies(){
+        Hashtable<String, Object> props = new Hashtable<>();
+        props.put("test", "org.opendaylight.controller.cluster.datastore.entityownership.selectionstrategy.LastCandidateSelectionStrategy,100");
+
+        doReturn(props).when(mockConfig).getProperties();
+
+        EntityOwnerSelectionStrategyConfig config = new EntityOwnerSelectionStrategyConfigReader(mockBundleContext).getConfig();
+
+        assertTrue(config.isStrategyConfigured("test"));
+
+        EntityOwnerSelectionStrategy strategy = config.createStrategy("test");
+        assertTrue(strategy instanceof LastCandidateSelectionStrategy);
+        assertEquals(100L, strategy.getSelectionDelayInMillis());
+    }
+
+    @Test
+    public void testReadStrategiesWithIOException() throws IOException {
+        doThrow(IOException.class).when(mockConfigAdmin).getConfiguration(EntityOwnerSelectionStrategyConfigReader.CONFIG_ID);
+
+        EntityOwnerSelectionStrategyConfig config = new EntityOwnerSelectionStrategyConfigReader(mockBundleContext).getConfig();
+
+        assertFalse(config.isStrategyConfigured("test"));
+    }
+
+    @Test
+    public void testReadStrategiesWithNullConfiguration() throws IOException {
+        doReturn(null).when(mockConfigAdmin).getConfiguration(EntityOwnerSelectionStrategyConfigReader.CONFIG_ID);
+
+        EntityOwnerSelectionStrategyConfig config = new EntityOwnerSelectionStrategyConfigReader(mockBundleContext).getConfig();
+
+        assertFalse(config.isStrategyConfigured("test"));
+    }
+
+    @Test
+    public void testReadStrategiesWithNullConfigurationProperties() throws IOException {
+        doReturn(null).when(mockConfig).getProperties();
+
+        EntityOwnerSelectionStrategyConfig config = new EntityOwnerSelectionStrategyConfigReader(mockBundleContext).getConfig();
+
+        assertFalse(config.isStrategyConfigured("test"));
+    }
+
+    @Test
+    public void testReadStrategiesInvalidDelay(){
+        Hashtable<String, Object> props = new Hashtable<>();
+        props.put("test", "org.opendaylight.controller.cluster.datastore.entityownership.selectionstrategy.LastCandidateSelectionStrategy,foo");
+
+        doReturn(props).when(mockConfig).getProperties();
+
+        EntityOwnerSelectionStrategyConfig config = new EntityOwnerSelectionStrategyConfigReader(mockBundleContext).getConfig();
+
+        assertFalse(config.isStrategyConfigured("test"));
+    }
+
+    @Test
+    public void testReadStrategiesInvalidClassType(){
+        Hashtable<String, Object> props = new Hashtable<>();
+        props.put("test", "String,100");
+
+        doReturn(props).when(mockConfig).getProperties();
+
+        EntityOwnerSelectionStrategyConfig config = new EntityOwnerSelectionStrategyConfigReader(mockBundleContext).getConfig();
+
+        assertFalse(config.isStrategyConfigured("test"));
+    }
+
+    @Test
+    public void testReadStrategiesMissingDelay(){
+        Hashtable<String, Object> props = new Hashtable<>();
+        props.put("test", "org.opendaylight.controller.cluster.datastore.entityownership.selectionstrategy.LastCandidateSelectionStrategy,100");
+        props.put("test1", "org.opendaylight.controller.cluster.datastore.entityownership.selectionstrategy.LastCandidateSelectionStrategy");
+
+        doReturn(props).when(mockConfig).getProperties();
+
+        EntityOwnerSelectionStrategyConfig config = new EntityOwnerSelectionStrategyConfigReader(mockBundleContext).getConfig();
+
+        assertEquals(100, config.createStrategy("test").getSelectionDelayInMillis());
+        assertEquals(0, config.createStrategy("test2").getSelectionDelayInMillis());
+    }
+
+}
\ No newline at end of file