Merge "Revert "BUG-1425: Integrated new Binding to Normalized Node codec for write...
authorEd Warnicke <eaw@cisco.com>
Fri, 15 Aug 2014 15:24:43 +0000 (15:24 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Fri, 15 Aug 2014 15:24:43 +0000 (15:24 +0000)
40 files changed:
opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/jmx/ObjectNameUtil.java
opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/JmxAttributeValidationExceptionTest.java [new file with mode: 0644]
opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/ValidationExceptionTest.java [new file with mode: 0644]
opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/jmx/ObjectNameUtilTest.java [new file with mode: 0644]
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/BlankTransactionServiceTracker.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/ModuleFactoryBundleTracker.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/util/InterfacesHelper.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/util/ModuleQNameUtil.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/util/OsgiRegistrationUtil.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/BlankTransactionServiceTrackerTest.java [new file with mode: 0644]
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/BundleContextBackedModuleFactoriesResolverTest.java [new file with mode: 0644]
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/ExtensibleBundleTrackerTest.java [new file with mode: 0644]
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/ModuleFactoryBundleTrackerTest.java [new file with mode: 0644]
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/util/InterfacesHelperTest.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/util/ObjectNameUtilTest.java [deleted file]
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/util/OsgiRegistrationUtilTest.java [new file with mode: 0644]
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/threadpool/AbstractTestingFixedThreadPoolModuleFactory.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/threadpool/test/SimpleConfigurationTest.java
opendaylight/config/config-manager/src/test/resources/module-factories/module-factory-fail [new file with mode: 0644]
opendaylight/config/config-manager/src/test/resources/module-factories/module-factory-ok [new file with mode: 0644]
opendaylight/config/netconf-config-dispatcher/pom.xml
opendaylight/config/netconf-config-dispatcher/src/test/java/org/opendaylight/controller/config/yang/config/netconf/client/dispatcher/NetconfClientDispatcherModuleTest.java [new file with mode: 0644]
opendaylight/config/netty-event-executor-config/src/test/java/org/opendaylight/controller/config/yang/netty/eventexecutor/ImmediateEventExecutorModuleTest.java [new file with mode: 0644]
opendaylight/config/netty-timer-config/src/test/java/org/opendaylight/controller/config/yang/netty/timer/HashedWheelTimerModuleTest.java [moved from opendaylight/config/netty-timer-config/src/test/org/opendaylight/controller/config/yang/netty/timer/HashedWheelTimerModuleTest.java with 99% similarity]
opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/FlowCapableInventoryProvider.java
opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/InventoryActivator.java
opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/InventoryOperation.java
opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/NodeChangeCommiter.java
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/protobuff/messages/shard/CompositeModificationPayload.java [moved from opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/mdsal/CompositeModificationPayload.java with 91% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/resources/CompositeModificationPayload.proto
opendaylight/md-sal/sal-clustering-config/pom.xml
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/CompositeModificationPayload.java
opendaylight/md-sal/sal-remoterpc-connector/src/test/resources/application.conf
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowStatsTracker.java
opendaylight/md-sal/topology-manager/src/main/java/org/opendaylight/md/controller/topology/manager/FlowCapableTopologyExporter.java
opendaylight/md-sal/topology-manager/src/main/java/org/opendaylight/md/controller/topology/manager/FlowCapableTopologyProvider.java
opendaylight/md-sal/topology-manager/src/main/java/org/opendaylight/md/controller/topology/manager/OperationProcessor.java
opendaylight/md-sal/topology-manager/src/main/java/org/opendaylight/md/controller/topology/manager/TopologyOperation.java
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronRouter.java
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFloatingIPsNorthbound.java

index d60e6086176daebd69f58a795ccadd4f24eca4de..abb9f1ae9bf4d448c78bc795a74f0076b68de745 100644 (file)
@@ -35,7 +35,6 @@ public class ObjectNameUtil {
     public static final String SERVICE_QNAME_KEY = "serviceQName";
     public static final String INSTANCE_NAME_KEY = "instanceName";
     public static final String TYPE_KEY = ConfigRegistryConstants.TYPE_KEY;
-    public static final String TYPE_CONFIG_REGISTRY = ConfigRegistryConstants.TYPE_CONFIG_REGISTRY;
     public static final String TYPE_CONFIG_TRANSACTION = "ConfigTransaction";
     public static final String TYPE_MODULE = "Module";
     public static final String TYPE_SERVICE_REFERENCE = "ServiceReference";
@@ -43,6 +42,7 @@ public class ObjectNameUtil {
     public static final String TRANSACTION_NAME_KEY = "TransactionName";
     public static final String REF_NAME_KEY = "RefName";
     private static final String REPLACED_QUOTATION_MARK = "\\?";
+    public static final String ON_WILDCARD = "*";
 
     public static ObjectName createON(String on) {
         try {
@@ -304,12 +304,9 @@ public class ObjectNameUtil {
 
     public static ObjectName createModulePattern(String moduleName,
                                                  String instanceName) {
-        if (moduleName == null) {
-            moduleName = "*";
-        }
-        if (instanceName == null) {
-            instanceName = "*";
-        }
+        moduleName = moduleName == null ? ON_WILDCARD : moduleName;
+        instanceName = instanceName == null ? ON_WILDCARD : instanceName;
+
         // do not return object names containing transaction name
         ObjectName namePattern = ObjectNameUtil
                 .createON(ObjectNameUtil.ON_DOMAIN + ":"
@@ -323,6 +320,10 @@ public class ObjectNameUtil {
 
     public static ObjectName createModulePattern(String ifcName,
                                                  String instanceName, String transactionName) {
+        ifcName = ifcName == null ? ON_WILDCARD : ifcName;
+        instanceName = instanceName == null ? ON_WILDCARD : instanceName;
+        transactionName = transactionName == null ? ON_WILDCARD : transactionName;
+
         return ObjectNameUtil.createON(ObjectNameUtil.ON_DOMAIN
                 + ":type=Module," + ObjectNameUtil.MODULE_FACTORY_NAME_KEY
                 + "=" + ifcName + "," + ObjectNameUtil.INSTANCE_NAME_KEY + "="
@@ -332,6 +333,9 @@ public class ObjectNameUtil {
 
     public static ObjectName createRuntimeBeanPattern(String moduleName,
                                                       String instanceName) {
+        moduleName = moduleName == null ? ON_WILDCARD : moduleName;
+        instanceName = instanceName == null ? ON_WILDCARD : instanceName;
+
         return ObjectNameUtil.createON(ObjectNameUtil.ON_DOMAIN + ":"
                 + ObjectNameUtil.TYPE_KEY + "="
                 + ObjectNameUtil.TYPE_RUNTIME_BEAN + ","
diff --git a/opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/JmxAttributeValidationExceptionTest.java b/opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/JmxAttributeValidationExceptionTest.java
new file mode 100644 (file)
index 0000000..7a057bb
--- /dev/null
@@ -0,0 +1,51 @@
+package org.opendaylight.controller.config.api;
+
+import static org.junit.Assert.assertEquals;
+
+import com.google.common.collect.Lists;
+import org.junit.Before;
+import org.junit.Test;
+
+public class JmxAttributeValidationExceptionTest {
+
+    private JmxAttribute jmxAttribute = new JmxAttribute("attr1");
+    private JmxAttribute jmxAttribute2 = new JmxAttribute("attr2");
+
+    @Before
+    public void setUp() throws Exception {
+
+    }
+
+    @Test
+    public void testGetAttributeNames() throws Exception {
+
+    }
+
+    @Test
+    public void testCheckNotNull() throws Exception {
+        try {
+            JmxAttributeValidationException.checkNotNull(false, "message", jmxAttribute);
+        } catch (JmxAttributeValidationException e) {
+            assertJmxEx(e, jmxAttribute.getAttributeName() + " " + "message", jmxAttribute);
+        }
+    }
+
+    @Test
+    public void testWrap() throws Exception {
+
+    }
+
+    @Test
+    public void testCheckCondition() throws Exception {
+        try {
+            JmxAttributeValidationException.checkCondition(false, "message", jmxAttribute);
+        } catch (JmxAttributeValidationException e) {
+            assertJmxEx(e, jmxAttribute.getAttributeName() + " " + "message", jmxAttribute);
+        }
+    }
+
+    private void assertJmxEx(JmxAttributeValidationException e, String message, JmxAttribute... attrNames) {
+        assertEquals(message, e.getMessage());
+        assertEquals(Lists.newArrayList(attrNames), e.getAttributeNames());
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/ValidationExceptionTest.java b/opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/ValidationExceptionTest.java
new file mode 100644 (file)
index 0000000..1809e45
--- /dev/null
@@ -0,0 +1,54 @@
+package org.opendaylight.controller.config.api;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.fail;
+import static org.junit.Assert.assertThat;
+import static org.junit.matchers.JUnitMatchers.containsString;
+
+import com.google.common.collect.Lists;
+import java.util.Map;
+import org.junit.Test;
+
+public class ValidationExceptionTest {
+
+    private String instance = "instance";
+    private final ModuleIdentifier mi = new ModuleIdentifier("module", instance);
+    private String instance2 = "instance2";
+    private final ModuleIdentifier mi2 = new ModuleIdentifier("module", instance2);
+    private final String message = "ex message";
+    private final Exception e = new IllegalStateException(message);
+
+    @Test
+    public void testCreateFromCollectedValidationExceptions() throws Exception {
+        ValidationException single = ValidationException.createForSingleException(mi, e);
+        ValidationException single2 = ValidationException.createForSingleException(mi2, e);
+
+        ValidationException collected = ValidationException.createFromCollectedValidationExceptions(Lists.newArrayList(single, single2));
+
+        Map<String, Map<String, ValidationException.ExceptionMessageWithStackTrace>> failedMap = collected.getFailedValidations();
+        assertEquals(1, failedMap.size());
+        assertTrue(failedMap.containsKey("module"));
+
+        Map<String, ValidationException.ExceptionMessageWithStackTrace> failedModule = failedMap.get("module");
+        assertEquals(2, failedModule.size());
+        assertTrue(failedModule.containsKey(instance));
+        assertEquals(message, failedModule.get(instance).getMessage());
+        assertEquals(message, failedModule.get(instance2).getMessage());
+        assertEquals(failedModule.get(instance), failedModule.get(instance2));
+    }
+
+    @Test
+    public void testCreateFromCollectedValidationExceptionsWithDuplicate() throws Exception {
+        ValidationException single = ValidationException.createForSingleException(mi, e);
+        ValidationException single2 = ValidationException.createForSingleException(mi, e);
+        try {
+            ValidationException.createFromCollectedValidationExceptions(Lists.newArrayList(single, single2));
+        } catch (IllegalArgumentException ex) {
+            // Duplicate exception
+            assertThat(ex.getMessage(), containsString("Cannot merge"));
+            return;
+        }
+        fail("Duplicate exception should have failed");
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/jmx/ObjectNameUtilTest.java b/opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/jmx/ObjectNameUtilTest.java
new file mode 100644 (file)
index 0000000..d3d8469
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * 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.config.api.jmx;
+
+import static junit.framework.Assert.fail;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.google.common.base.Throwables;
+import com.google.common.collect.Maps;
+import java.util.Map;
+import javax.management.ObjectName;
+import junit.framework.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.config.api.ModuleIdentifier;
+
+public class ObjectNameUtilTest {
+
+    private String moduleName;
+    private String instanceName;
+
+    @Before
+    public void setUp() throws Exception {
+        moduleName = "module";
+        instanceName = "instance";
+    }
+
+    @Test
+    public void testServiceReferenceName() throws Exception {
+        String serviceQName = "(namespace?revision=r)qname";
+        String refName = "refName";
+        String transaction = "transaction";
+
+        ObjectName serviceReferenceON = ObjectNameUtil.createTransactionServiceON(transaction, serviceQName, refName);
+        ObjectNameUtil.checkType(serviceReferenceON, ObjectNameUtil.TYPE_SERVICE_REFERENCE);
+
+        assertFalse(serviceReferenceON.isPattern());
+        assertEquals(serviceQName, ObjectNameUtil.getServiceQName(serviceReferenceON));
+        assertEquals(refName, ObjectNameUtil.getReferenceName(serviceReferenceON));
+        assertEquals(transaction, ObjectNameUtil.getTransactionName(serviceReferenceON));
+        assertEquals(ObjectNameUtil.createReadOnlyServiceON(serviceQName, refName), ObjectNameUtil.withoutTransactionName(serviceReferenceON));
+
+        serviceReferenceON = ObjectNameUtil.createReadOnlyServiceON(serviceQName, refName);
+        assertFalse(serviceReferenceON.isPattern());
+        assertEquals(serviceQName, ObjectNameUtil.getServiceQName(serviceReferenceON));
+        assertEquals(refName, ObjectNameUtil.getReferenceName(serviceReferenceON));
+        assertEquals(null, ObjectNameUtil.getTransactionName(serviceReferenceON));
+    }
+
+    @Test
+    public void testModuleName() throws Exception {
+        String txName = "transaction";
+
+        ObjectName on = ObjectNameUtil.createTransactionModuleON(txName, moduleName, instanceName);
+
+        ObjectNameUtil.checkDomain(on);
+        ObjectNameUtil.checkType(on, ObjectNameUtil.TYPE_MODULE);
+
+        assertFalse(on.isPattern());
+        assertEquals(moduleName, ObjectNameUtil.getFactoryName(on));
+        assertEquals(instanceName, ObjectNameUtil.getInstanceName(on));
+        assertEquals(txName, ObjectNameUtil.getTransactionName(on));
+        assertEquals(4, ObjectNameUtil.getAdditionalProperties(on).size());
+
+        ObjectName withoutTx = ObjectNameUtil.withoutTransactionName(on);
+        assertEquals(ObjectNameUtil.createReadOnlyModuleON(moduleName, instanceName), withoutTx);
+        assertEquals(moduleName, ObjectNameUtil.getFactoryName(withoutTx));
+        assertEquals(instanceName, ObjectNameUtil.getInstanceName(withoutTx));
+        assertEquals(null, ObjectNameUtil.getTransactionName(withoutTx));
+        assertEquals(on, ObjectNameUtil.withTransactionName(withoutTx, txName));
+
+        ObjectName pattern = ObjectNameUtil.createModulePattern(moduleName, null);
+        assertPattern(withoutTx, pattern);
+        pattern = ObjectNameUtil.createModulePattern(moduleName, null, txName);
+        assertPattern(on, pattern);
+    }
+
+    private void assertPattern(ObjectName test, ObjectName pattern) {
+        assertTrue(pattern.isPattern());
+        assertTrue(pattern.apply(test));
+    }
+
+    @Test
+    public void testRuntimeBeanName() throws Exception {
+
+        Map<String, String> properties = Maps.newHashMap();
+        properties.put("p1", "value");
+        properties.put("p2", "value2");
+
+        ObjectName on = ObjectNameUtil.createRuntimeBeanName(moduleName, instanceName, properties);
+
+        ObjectNameUtil.checkDomain(on);
+        ObjectNameUtil.checkTypeOneOf(on, ObjectNameUtil.TYPE_RUNTIME_BEAN);
+
+        assertFalse(on.isPattern());
+        assertEquals(moduleName, ObjectNameUtil.getFactoryName(on));
+        assertEquals(instanceName, ObjectNameUtil.getInstanceName(on));
+        assertEquals(2, ObjectNameUtil.getAdditionalPropertiesOfRuntimeBeanName(on).size());
+        assertTrue(ObjectNameUtil.getAdditionalPropertiesOfRuntimeBeanName(on).containsKey("p1"));
+        assertEquals("value", ObjectNameUtil.getAdditionalPropertiesOfRuntimeBeanName(on).get("p1"));
+        assertTrue(ObjectNameUtil.getAdditionalProperties(on).containsKey("p2"));
+        assertEquals("value2", ObjectNameUtil.getAdditionalPropertiesOfRuntimeBeanName(on).get("p2"));
+
+        ObjectName pattern = ObjectNameUtil.createRuntimeBeanPattern(null, instanceName);
+        assertPattern(on, pattern);
+    }
+
+    @Test
+    public void testModuleIdentifier() throws Exception {
+        ModuleIdentifier mi = new ModuleIdentifier(moduleName, instanceName);
+        ObjectName on = ObjectNameUtil.createReadOnlyModuleON(mi);
+        assertEquals(moduleName, ObjectNameUtil.getFactoryName(on));
+        assertEquals(instanceName, ObjectNameUtil.getInstanceName(on));
+
+        assertEquals(mi, ObjectNameUtil.fromON(on, ObjectNameUtil.TYPE_MODULE));
+    }
+
+    @Test
+    public void testChecks() throws Exception {
+        final ObjectName on = ObjectNameUtil.createON("customDomain", ObjectNameUtil.TYPE_KEY, ObjectNameUtil.TYPE_MODULE);
+
+        assertFailure(new Runnable() {
+            @Override
+            public void run() {
+                ObjectNameUtil.checkTypeOneOf(on, ObjectNameUtil.TYPE_RUNTIME_BEAN, ObjectNameUtil.TYPE_CONFIG_TRANSACTION);
+            }
+        }, IllegalArgumentException.class);
+
+        assertFailure(new Runnable() {
+            @Override
+            public void run() {
+                ObjectNameUtil.checkType(on, ObjectNameUtil.TYPE_RUNTIME_BEAN);
+            }
+        }, IllegalArgumentException.class);
+
+        assertFailure(new Runnable() {
+            @Override
+            public void run() {
+                ObjectNameUtil.checkDomain(on);
+            }
+        }, IllegalArgumentException.class);
+    }
+
+    private void assertFailure(Runnable test, Class<? extends Exception> ex) {
+        try {
+            test.run();
+        } catch(Exception e) {
+            Assert.assertTrue("Failed with wrong exception: " + Throwables.getStackTraceAsString(e),
+                    e.getClass().isAssignableFrom(ex));
+            return;
+        }
+
+        fail(test + " should have failed on " + ex);
+    }
+}
index 720b7197ea6100b0890ee0fd4a89d5f5de9157bd..375ef5948712f3bcc5dc803802645b1d6fa56103 100644 (file)
@@ -7,6 +7,8 @@
  */
 package org.opendaylight.controller.config.manager.impl.osgi;
 
+import com.google.common.annotations.VisibleForTesting;
+import javax.management.ObjectName;
 import org.opendaylight.controller.config.api.ConflictingVersionException;
 import org.opendaylight.controller.config.api.ValidationException;
 import org.opendaylight.controller.config.api.jmx.CommitStatus;
@@ -17,8 +19,6 @@ import org.osgi.util.tracker.ServiceTrackerCustomizer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.management.ObjectName;
-
 /**
  * Every time factory is added or removed, blank transaction is triggered to handle
  * {@link org.opendaylight.controller.config.spi.ModuleFactory#getDefaultModules(org.opendaylight.controller.config.api.DependencyResolverFactory, org.osgi.framework.BundleContext)}
@@ -27,10 +27,29 @@ import javax.management.ObjectName;
 public class BlankTransactionServiceTracker implements ServiceTrackerCustomizer<ModuleFactory, Object> {
     private static final Logger logger = LoggerFactory.getLogger(BlankTransactionServiceTracker.class);
 
-    private final ConfigRegistryImpl configRegistry;
+    public static final int DEFAULT_MAX_ATTEMPTS = 10;
 
-    public BlankTransactionServiceTracker(ConfigRegistryImpl configRegistry) {
-        this.configRegistry = configRegistry;
+    private final BlankTransaction blankTransaction;
+    private int maxAttempts;
+
+    public BlankTransactionServiceTracker(final ConfigRegistryImpl configRegistry) {
+        this(new BlankTransaction() {
+            @Override
+            public CommitStatus hit() throws ValidationException, ConflictingVersionException {
+                ObjectName tx = configRegistry.beginConfig(true);
+                return configRegistry.commitConfig(tx);
+            }
+        });
+    }
+
+    public BlankTransactionServiceTracker(final BlankTransaction blankTransaction) {
+        this(blankTransaction, DEFAULT_MAX_ATTEMPTS);
+    }
+
+    @VisibleForTesting
+    BlankTransactionServiceTracker(final BlankTransaction blankTx, final int maxAttempts) {
+        this.blankTransaction = blankTx;
+        this.maxAttempts = maxAttempts;
     }
 
     @Override
@@ -42,13 +61,10 @@ public class BlankTransactionServiceTracker implements ServiceTrackerCustomizer<
     synchronized void blankTransaction() {
         // race condition check: config-persister might push new configuration while server is starting up.
         ConflictingVersionException lastException = null;
-        int maxAttempts = 10;
         for (int i = 0; i < maxAttempts; i++) {
             try {
                 // create transaction
-                boolean blankTransaction = true;
-                ObjectName tx = configRegistry.beginConfig(blankTransaction);
-                CommitStatus commitStatus = configRegistry.commitConfig(tx);
+                CommitStatus commitStatus = blankTransaction.hit();
                 logger.debug("Committed blank transaction with status {}", commitStatus);
                 return;
             } catch (ConflictingVersionException e) {
@@ -77,4 +93,9 @@ public class BlankTransactionServiceTracker implements ServiceTrackerCustomizer<
     public void removedService(ServiceReference<ModuleFactory> moduleFactoryServiceReference, Object o) {
         blankTransaction();
     }
+
+    @VisibleForTesting
+    static interface BlankTransaction {
+        CommitStatus hit() throws ValidationException, ConflictingVersionException;
+    }
 }
index 05ca43c3e2d88e01ea9458fc15bc621a0cd9daa4..3015ed229e28f1c04015d9d488d641c9ebceb161 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.controller.config.manager.impl.osgi;
 
 import static java.lang.String.format;
 
+import com.google.common.annotations.VisibleForTesting;
 import java.io.InputStream;
 import java.net.URL;
 import java.util.List;
@@ -70,9 +71,10 @@ public class ModuleFactoryBundleTracker implements BundleTrackerCustomizer<Objec
         blankTransactionServiceTracker.blankTransaction();
     }
 
-    // TODO:test
-    private static ServiceRegistration<?> registerFactory(String factoryClassName, Bundle bundle) {
+    @VisibleForTesting
+    protected static ServiceRegistration<?> registerFactory(String factoryClassName, Bundle bundle) {
         String errorMessage;
+        Exception ex = null;
         try {
             Class<?> clazz = bundle.loadClass(factoryClassName);
             if (ModuleFactory.class.isAssignableFrom(clazz)) {
@@ -86,10 +88,12 @@ public class ModuleFactoryBundleTracker implements BundleTrackerCustomizer<Objec
                     errorMessage = logMessage(
                             "Could not instantiate {} in bundle {}, reason {}",
                             factoryClassName, bundle, e);
+                    ex = e;
                 } catch (IllegalAccessException e) {
                     errorMessage = logMessage(
-                            "Illegal access during instatiation of class {} in bundle {}, reason {}",
+                            "Illegal access during instantiation of class {} in bundle {}, reason {}",
                             factoryClassName, bundle, e);
+                    ex = e;
                 }
             } else {
                 errorMessage = logMessage(
@@ -98,10 +102,12 @@ public class ModuleFactoryBundleTracker implements BundleTrackerCustomizer<Objec
             }
         } catch (ClassNotFoundException e) {
             errorMessage = logMessage(
-                    "Could not find class {} in bunde {}, reason {}",
+                    "Could not find class {} in bundle {}, reason {}",
                     factoryClassName, bundle, e);
+            ex = e;
         }
-        throw new IllegalStateException(errorMessage);
+
+        throw ex == null ? new IllegalStateException(errorMessage) : new IllegalStateException(errorMessage, ex);
     }
 
     public static String logMessage(String slfMessage, Object... params) {
index a6e9b1ba965b8532eb2e688742ca6ec66c5d5e10..510fdf9373f46a7dc0c5f1aa61aabd15d31fbb25 100644 (file)
@@ -109,7 +109,6 @@ public class InterfacesHelper {
      */
     public static Set<Class<?>> getOsgiRegistrationTypes(
             Class<? extends Module> configBeanClass) {
-        // TODO test with service interface hierarchy
         Set<Class<?>> serviceInterfaces = getServiceInterfaces(configBeanClass);
         Set<Class<?>> result = new HashSet<>();
         for (Class<?> clazz : serviceInterfaces) {
index e84337756e4ad6a74200ce1cd60293848b59d3ab..f1072a76ae907d934d13984478c119092c9f0dbd 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.controller.config.manager.impl.util;
 
 import org.opendaylight.controller.config.spi.ModuleFactory;
 import org.opendaylight.yangtools.yang.binding.annotations.ModuleQName;
+import org.opendaylight.yangtools.yang.common.QName;
 import org.osgi.framework.BundleContext;
 
 import java.util.HashSet;
@@ -31,9 +32,7 @@ public class ModuleQNameUtil {
                 inspected = inspected.getSuperclass();
             }
             if (annotation != null) {
-                // FIXME
-                String qName = "(" + annotation.namespace() + "?revision=" + annotation.revision() + ")" + annotation.name();
-                result.add(qName);
+                result.add(QName.create(annotation.namespace(), annotation.revision(), annotation.name()).toString());
             }
         }
         return result;
index 8873596642e43a8c460a8ee18fb7ef5fef8e9733..2df28f0a154b8b7a6e37f1930b5e06d46efda675 100644 (file)
@@ -8,6 +8,11 @@
 
 package org.opendaylight.controller.config.manager.impl.util;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ListIterator;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.util.tracker.BundleTracker;
@@ -15,12 +20,6 @@ import org.osgi.util.tracker.ServiceTracker;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.ListIterator;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
 public class OsgiRegistrationUtil {
     private static final Logger logger = LoggerFactory.getLogger(OsgiRegistrationUtil.class);
 
diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/BlankTransactionServiceTrackerTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/BlankTransactionServiceTrackerTest.java
new file mode 100644 (file)
index 0000000..471c98a
--- /dev/null
@@ -0,0 +1,83 @@
+package org.opendaylight.controller.config.manager.impl.osgi;
+
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertSame;
+import static junit.framework.Assert.fail;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import java.util.Collections;
+import javax.management.ObjectName;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.config.api.ConflictingVersionException;
+import org.opendaylight.controller.config.api.ModuleIdentifier;
+import org.opendaylight.controller.config.api.ValidationException;
+import org.opendaylight.controller.config.api.jmx.CommitStatus;
+import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.osgi.framework.ServiceReference;
+
+public class BlankTransactionServiceTrackerTest {
+
+    @Mock
+    private BlankTransactionServiceTracker.BlankTransaction blankTx;
+    private BlankTransactionServiceTracker tracker;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        doReturn(new CommitStatus(Collections.<ObjectName>emptyList(), Collections.<ObjectName>emptyList(), Collections.<ObjectName>emptyList())).when(blankTx).hit();
+        tracker = new BlankTransactionServiceTracker(blankTx);
+    }
+
+    @Test
+    public void testBlankTransaction() throws Exception {
+        tracker.addingService(getMockServiceReference());
+        tracker.modifiedService(getMockServiceReference(), null);
+        tracker.removedService(getMockServiceReference(), null);
+        verify(blankTx, times(3)).hit();
+    }
+
+    @Test
+    public void testValidationException() throws Exception {
+        IllegalArgumentException argumentException = new IllegalArgumentException();
+        ValidationException validationException = ValidationException.createForSingleException(new ModuleIdentifier("m", "i"), argumentException);
+        doThrow(validationException).when(blankTx).hit();
+        try {
+            tracker.addingService(getMockServiceReference());
+        } catch (Exception e) {
+            verify(blankTx, times(1)).hit();
+            assertNotNull(e.getCause());
+            assertSame(validationException, e.getCause());
+            return;
+        }
+
+        fail("Exception should have occurred for validation exception");
+    }
+
+    @Test
+    public void testConflictingException() throws Exception {
+        int maxAttempts = 2;
+        tracker = new BlankTransactionServiceTracker(blankTx, maxAttempts);
+
+        final ConflictingVersionException ex = new ConflictingVersionException();
+        doThrow(ex).when(blankTx).hit();
+        try {
+            tracker.addingService(getMockServiceReference());
+        } catch (Exception e) {
+            verify(blankTx, times(maxAttempts)).hit();
+            return;
+        }
+
+        fail("Exception should have occurred for conflicting exception");
+    }
+
+    private ServiceReference<ModuleFactory> getMockServiceReference() {
+        return mock(ServiceReference.class);
+    }
+}
diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/BundleContextBackedModuleFactoriesResolverTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/BundleContextBackedModuleFactoriesResolverTest.java
new file mode 100644 (file)
index 0000000..dc3dedd
--- /dev/null
@@ -0,0 +1,104 @@
+package org.opendaylight.controller.config.manager.impl.osgi;
+
+import static junit.framework.Assert.fail;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.matchers.JUnitMatchers.containsString;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+import com.google.common.collect.Lists;
+import java.util.Map;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+
+public class BundleContextBackedModuleFactoriesResolverTest {
+
+    @Mock
+    private BundleContext bundleContext;
+    private BundleContextBackedModuleFactoriesResolver resolver;
+    private ServiceReference s1;
+    private ServiceReference s2;
+    private ModuleFactory f1;
+    private ModuleFactory f2;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        s1 = getServiceRef();
+        s2 = getServiceRef();
+        doReturn(Lists.newArrayList(s1, s2)).when(bundleContext).getServiceReferences(ModuleFactory.class, null);
+        f1 = getMockFactory("f1");
+        doReturn(f1).when(bundleContext).getService(s1);
+        f2 = getMockFactory("f2");
+        doReturn(f2).when(bundleContext).getService(s2);
+        resolver = new BundleContextBackedModuleFactoriesResolver(bundleContext);
+    }
+
+    private ModuleFactory getMockFactory(String name) {
+        ModuleFactory mock = mock(ModuleFactory.class);
+        doReturn(name).when(mock).toString();
+        doReturn(name).when(mock).getImplementationName();
+        return mock;
+    }
+
+    private ServiceReference getServiceRef() {
+        ServiceReference mock = mock(ServiceReference.class);
+        doReturn("serviceRef").when(mock).toString();
+        final Bundle bundle = mock(Bundle.class);
+        doReturn(bundleContext).when(bundle).getBundleContext();
+        doReturn(bundle).when(mock).getBundle();
+        return mock;
+    }
+
+    @Test
+    public void testGetAllFactories() throws Exception {
+        Map<String, Map.Entry<ModuleFactory, BundleContext>> allFactories = resolver.getAllFactories();
+        assertEquals(2, allFactories.size());
+        assertTrue(allFactories.containsKey(f1.getImplementationName()));
+        assertEquals(f1, allFactories.get(f1.getImplementationName()).getKey());
+        assertEquals(bundleContext, allFactories.get(f1.getImplementationName()).getValue());
+        assertTrue(allFactories.containsKey(f2.getImplementationName()));
+        assertEquals(f2, allFactories.get(f2.getImplementationName()).getKey());
+        assertEquals(bundleContext, allFactories.get(f2.getImplementationName()).getValue());
+    }
+
+    @Test
+    public void testDuplicateFactories() throws Exception {
+        doReturn(f1).when(bundleContext).getService(s2);
+        try {
+            resolver.getAllFactories();
+        } catch (Exception e) {
+            assertThat(e.getMessage(), containsString(f1.getImplementationName()));
+            assertThat(e.getMessage(), containsString("unique"));
+            return;
+        }
+
+        fail("Should fail with duplicate factory name");
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testNullFactory() throws Exception {
+        doReturn(null).when(bundleContext).getService(s2);
+        resolver.getAllFactories();
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void testNullFactoryName() throws Exception {
+        doReturn(null).when(f1).getImplementationName();
+        resolver.getAllFactories();
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testNullBundleName() throws Exception {
+        doReturn(null).when(s1).getBundle();
+        resolver.getAllFactories();
+    }
+}
diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/ExtensibleBundleTrackerTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/ExtensibleBundleTrackerTest.java
new file mode 100644 (file)
index 0000000..9a3ba64
--- /dev/null
@@ -0,0 +1,76 @@
+package org.opendaylight.controller.config.manager.impl.osgi;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import com.google.common.util.concurrent.Futures;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.util.tracker.BundleTrackerCustomizer;
+
+public class ExtensibleBundleTrackerTest {
+
+    @Mock
+    private BundleContext bundleContext;
+    @Mock
+    private Bundle bundle;
+    @Mock
+    private BundleEvent bundleEvent;
+
+    @Mock
+    private BundleTrackerCustomizer<Object> primaryTracker;
+    @Mock
+    private BundleTrackerCustomizer<?> additionalTracker;
+
+    private ExtensibleBundleTracker<Object> extensibleBundleTracker;
+    private Object primaryValue = new Object();
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        doReturn("bundle").when(bundle).toString();
+        doReturn("bundleEvent").when(bundleEvent).toString();
+
+        doReturn(primaryValue).when(primaryTracker).addingBundle(bundle, bundleEvent);
+        doNothing().when(primaryTracker).modifiedBundle(bundle, bundleEvent, primaryValue);
+        doNothing().when(primaryTracker).removedBundle(bundle, bundleEvent, primaryValue);
+
+        doReturn(new Object()).when(additionalTracker).addingBundle(bundle, bundleEvent);
+        doNothing().when(additionalTracker).modifiedBundle(bundle, bundleEvent, null);
+        doNothing().when(additionalTracker).removedBundle(bundle, bundleEvent, null);
+        extensibleBundleTracker = new ExtensibleBundleTracker<>(bundleContext, primaryTracker, additionalTracker);
+    }
+
+    @Test
+    public void testAddingBundle() throws Exception {
+        assertEquals(primaryValue, extensibleBundleTracker.addingBundle(bundle, bundleEvent).get());
+        InOrder inOrder = Mockito.inOrder(primaryTracker, additionalTracker);
+        inOrder.verify(primaryTracker).addingBundle(bundle, bundleEvent);
+        inOrder.verify(additionalTracker).addingBundle(bundle, bundleEvent);
+    }
+
+    @Test
+    public void testRemovedBundle() throws Exception {
+        extensibleBundleTracker.removedBundle(bundle, bundleEvent, Futures.immediateFuture(primaryValue));
+        InOrder inOrder = Mockito.inOrder(primaryTracker, additionalTracker);
+        inOrder.verify(primaryTracker).removedBundle(bundle, bundleEvent, primaryValue);
+        inOrder.verify(additionalTracker).removedBundle(bundle, bundleEvent, null);
+    }
+
+    @Test
+    public void testRemovedBundleWithEx() throws Exception {
+        IllegalStateException throwable = new IllegalStateException();
+        extensibleBundleTracker.removedBundle(bundle, bundleEvent, Futures.immediateFailedFuture(throwable));
+        verifyZeroInteractions(primaryTracker);
+        verifyZeroInteractions(additionalTracker);
+    }
+}
diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/ModuleFactoryBundleTrackerTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/ModuleFactoryBundleTrackerTest.java
new file mode 100644 (file)
index 0000000..5b83412
--- /dev/null
@@ -0,0 +1,193 @@
+package org.opendaylight.controller.config.manager.impl.osgi;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import java.util.Dictionary;
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.opendaylight.controller.config.api.DependencyResolver;
+import org.opendaylight.controller.config.api.DependencyResolverFactory;
+import org.opendaylight.controller.config.api.DynamicMBeanWithInstance;
+import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface;
+import org.opendaylight.controller.config.spi.Module;
+import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.ServiceRegistration;
+
+public class ModuleFactoryBundleTrackerTest {
+
+    @Mock
+    private Bundle bundle;
+    @Mock
+    private BundleContext context;
+    @Mock
+    private ServiceRegistration<?> reg;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        doAnswer(new Answer() {
+            @Override
+            public Object answer(final InvocationOnMock invocation) throws Throwable {
+                return getClass().getClassLoader().loadClass((String) invocation.getArguments()[0]);
+            }
+        }).when(bundle).loadClass(anyString());
+        doReturn("mockBundle").when(bundle).toString();
+        doReturn(context).when(bundle).getBundleContext();
+        doReturn(reg).when(context).registerService(anyString(), anyObject(), any(Dictionary.class));
+    }
+
+    @Test
+    public void testRegisterFactory() throws Exception {
+        ModuleFactoryBundleTracker.registerFactory(TestingFactory.class.getName(), bundle);
+        verify(context).registerService(ModuleFactory.class.getName(), TestingFactory.currentInstance, null);
+    }
+
+    @Test
+    public void testRegisterFactoryInstantiateEx() throws Exception {
+        try {
+            ModuleFactoryBundleTracker.registerFactory(WrongConstructorTestingFactory.class.getName(), bundle);
+        } catch (Exception e) {
+            verifyZeroInteractions(context);
+            assertNotNull(e.getCause());
+            assertEquals(InstantiationException.class, e.getCause().getClass());
+            return;
+        }
+
+        fail("Cannot register without proper constructor");
+    }
+
+    @Test
+    public void testRegisterFactoryInstantiateExAccess() throws Exception {
+        try {
+            ModuleFactoryBundleTracker.registerFactory(NoAccessConstructorTestingFactory.class.getName(), bundle);
+        } catch (Exception e) {
+            verifyZeroInteractions(context);
+            assertNotNull(e.getCause());
+            assertEquals(IllegalAccessException.class, e.getCause().getClass());
+            return;
+        }
+
+        fail("Cannot register without proper constructor");
+    }
+
+    @Test
+    public void testRegisterFactoryNotExtending() throws Exception {
+        try {
+            ModuleFactoryBundleTracker.registerFactory(NotExtendingTestingFactory.class.getName(), bundle);
+        } catch (Exception e) {
+            verifyZeroInteractions(context);
+            return;
+        }
+
+        fail("Cannot register without extend");
+    }
+
+    @Test
+    public void testRegisterFactoryNotExisting() throws Exception {
+        try {
+            ModuleFactoryBundleTracker.registerFactory("Unknown class", bundle);
+        } catch (Exception e) {
+            verifyZeroInteractions(context);
+            assertNotNull(e.getCause());
+            assertEquals(ClassNotFoundException.class, e.getCause().getClass());
+            return;
+        }
+
+        fail("Cannot register without extend");
+    }
+
+    @Mock
+    private BlankTransactionServiceTracker blankTxTracker;
+
+    @Test
+    public void testAddingBundle() throws Exception {
+        final ModuleFactoryBundleTracker tracker = new ModuleFactoryBundleTracker(blankTxTracker);
+        doReturn(getClass().getResource("/module-factories/module-factory-ok")).when(bundle).getEntry(anyString());
+        tracker.addingBundle(bundle, mock(BundleEvent.class));
+        verify(context).registerService(ModuleFactory.class.getName(), TestingFactory.currentInstance, null);
+    }
+
+    @Test
+    public void testAddingBundleError() throws Exception {
+        final ModuleFactoryBundleTracker tracker = new ModuleFactoryBundleTracker(blankTxTracker);
+        doReturn(getClass().getResource("/module-factories/module-factory-fail")).when(bundle).getEntry(anyString());
+        try {
+            tracker.addingBundle(bundle, mock(BundleEvent.class));
+        } catch (Exception e) {
+            verifyZeroInteractions(context);
+            return;
+        }
+
+        fail("Cannot register");
+    }
+
+    static class WrongConstructorTestingFactory extends TestingFactory {
+        WrongConstructorTestingFactory(String randomParam) {
+        }
+    }
+
+    static class NotExtendingTestingFactory {}
+
+    static class NoAccessConstructorTestingFactory extends TestingFactory {
+        private NoAccessConstructorTestingFactory() {
+        }
+    }
+
+    static class TestingFactory implements ModuleFactory {
+
+        static TestingFactory currentInstance;
+
+        TestingFactory() {
+            currentInstance = this;
+        }
+
+        @Override
+        public String getImplementationName() {
+            return "Testing";
+        }
+
+        @Override
+        public Module createModule(final String instanceName, final DependencyResolver dependencyResolver, final BundleContext bundleContext) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Module createModule(final String instanceName, final DependencyResolver dependencyResolver, final DynamicMBeanWithInstance old, final BundleContext bundleContext) throws Exception {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean isModuleImplementingServiceInterface(final Class<? extends AbstractServiceInterface> serviceInterface) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Set<Class<? extends AbstractServiceInterface>> getImplementedServiceIntefaces() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Set<? extends Module> getDefaultModules(final DependencyResolverFactory dependencyResolverFactory, final BundleContext bundleContext) {
+            throw new UnsupportedOperationException();
+        }
+    }
+}
index 22ea528030931b5350cd79c0facc30d1c4ed73a5..220bef03bc95eab1efbbe54122e7b42cb657927e 100644 (file)
@@ -9,20 +9,19 @@ package org.opendaylight.controller.config.manager.impl.util;
 
 import static org.junit.Assert.assertEquals;
 
+import com.google.common.collect.Sets;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
-
 import javax.management.MXBean;
-
 import org.junit.Test;
 import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface;
+import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
 import org.opendaylight.controller.config.manager.testingservices.seviceinterface.TestingScheduledThreadPoolServiceInterface;
 import org.opendaylight.controller.config.manager.testingservices.seviceinterface.TestingThreadPoolServiceInterface;
 import org.opendaylight.controller.config.spi.Module;
 import org.opendaylight.yangtools.concepts.Identifiable;
 
-import com.google.common.collect.Sets;
-
 public class InterfacesHelperTest {
 
     interface SuperA {
@@ -46,10 +45,19 @@ public class InterfacesHelperTest {
 
     }
 
+    @ServiceInterfaceAnnotation(value = "a", osgiRegistrationType = SuperA.class, namespace = "n", revision = "r", localName = "l")
+    interface Service extends AbstractServiceInterface{}
+    @ServiceInterfaceAnnotation(value = "b", osgiRegistrationType = SuperC.class, namespace = "n", revision = "r", localName = "l")
+    interface SubService extends Service{}
+
     abstract class SubClass extends SuperClass implements SubA, Module {
 
     }
 
+    abstract class SubClassWithService implements SubService, Module {
+
+    }
+
     @Test
     public void testGetAllInterfaces() {
         Set<Class<?>> expected = Sets.<Class<?>> newHashSet(SuperA.class, SuperBMXBean.class, SuperC.class,
@@ -58,6 +66,19 @@ public class InterfacesHelperTest {
                 InterfacesHelper.getAllInterfaces(SubClass.class));
     }
 
+    @Test
+    public void testGetServiceInterfaces() throws Exception {
+        assertEquals(Collections.<Class<?>>emptySet(), InterfacesHelper.getServiceInterfaces(SubClass.class));
+        assertEquals(Sets.<Class<?>>newHashSet(Service.class, SubService.class), InterfacesHelper.getServiceInterfaces(SubClassWithService.class));
+    }
+
+    @Test
+    public void testGetOsgiRegistrationTypes() throws Exception {
+        assertEquals(Collections.<Class<?>>emptySet(), InterfacesHelper.getOsgiRegistrationTypes(SubClass.class));
+        assertEquals(Sets.<Class<?>>newHashSet(SuperA.class, SuperC.class),
+                InterfacesHelper.getOsgiRegistrationTypes(SubClassWithService.class));
+    }
+
     @Test
     public void testGetMXInterfaces() {
         Set<Class<?>> expected = Sets.<Class<?>> newHashSet(SuperBMXBean.class, SubA.class);
diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/util/ObjectNameUtilTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/util/ObjectNameUtilTest.java
deleted file mode 100644 (file)
index fe32289..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.config.manager.impl.util;
-
-import com.google.common.base.Throwables;
-import com.google.common.collect.Sets;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
-import org.opendaylight.controller.config.manager.impl.AbstractLockedPlatformMBeanServerTest;
-
-import javax.management.ObjectName;
-import java.util.Set;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-
-public class ObjectNameUtilTest extends AbstractLockedPlatformMBeanServerTest {
-    private Set<ObjectName> unregisterONs;
-
-    @Before
-    public void initUnregisterList() {
-        unregisterONs = Sets.newHashSet();
-    }
-
-    @After
-    public void unregisterONs() {
-        Exception lastException = null;
-        for (ObjectName on : unregisterONs) {
-            try {
-                platformMBeanServer.unregisterMBean(on);
-            } catch (Exception e) {
-                lastException = e;
-            }
-        }
-        if (lastException != null) {
-            throw Throwables.propagate(lastException);
-        }
-    }
-
-    @Test
-    public void testQuotation() throws Exception {
-        String serviceQName = "(namespace?revision=r)qname";
-        String refName = "refName";
-        String transaction = "transaction";
-        ObjectName serviceReferenceON = ObjectNameUtil.createTransactionServiceON(transaction, serviceQName, refName);
-        assertFalse(serviceReferenceON.isPattern());
-        assertEquals(serviceQName, ObjectNameUtil.getServiceQName(serviceReferenceON));
-        assertEquals(refName, ObjectNameUtil.getReferenceName(serviceReferenceON));
-        assertEquals(transaction, ObjectNameUtil.getTransactionName(serviceReferenceON));
-
-        serviceReferenceON = ObjectNameUtil.createReadOnlyServiceON(serviceQName, refName);
-        assertFalse(serviceReferenceON.isPattern());
-        assertEquals(serviceQName, ObjectNameUtil.getServiceQName(serviceReferenceON));
-        assertEquals(refName, ObjectNameUtil.getReferenceName(serviceReferenceON));
-        assertEquals(null, ObjectNameUtil.getTransactionName(serviceReferenceON));
-
-    }
-}
diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/util/OsgiRegistrationUtilTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/util/OsgiRegistrationUtilTest.java
new file mode 100644 (file)
index 0000000..fb59e3d
--- /dev/null
@@ -0,0 +1,61 @@
+package org.opendaylight.controller.config.manager.impl.util;
+
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.Mockito;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.util.tracker.BundleTracker;
+import org.osgi.util.tracker.ServiceTracker;
+
+public class OsgiRegistrationUtilTest {
+
+    @Test
+    public void testRegisterService() throws Exception {
+        final BundleContext bundleContext = mock(BundleContext.class);
+        ServiceRegistration<?> registration = mockServiceRegistration();
+        doReturn(registration).when(bundleContext).registerService(String.class, "string", null);
+        ServiceRegistration<?> registration2 = mockServiceRegistration();
+        doReturn(registration2).when(bundleContext).registerService(Object.class, "string", null);
+
+        AutoCloseable aggregatedRegister = OsgiRegistrationUtil.registerService(bundleContext, "string", String.class, Object.class);
+        aggregatedRegister.close();
+
+        InOrder inOrder = Mockito.inOrder(registration, registration2);
+        inOrder.verify(registration2).unregister();
+        inOrder.verify(registration).unregister();
+    }
+
+    @Test
+    public void testWrap() throws Exception {
+        final ServiceRegistration<?> serviceReg = mockServiceRegistration();
+        OsgiRegistrationUtil.wrap(serviceReg).close();
+        verify(serviceReg).unregister();
+
+        final BundleTracker tracker = mock(BundleTracker.class);
+        doNothing().when(tracker).close();
+        OsgiRegistrationUtil.wrap(tracker).close();
+        verify(tracker).close();
+
+        final ServiceTracker<?, ?> sTracker = mock(ServiceTracker.class);
+        doNothing().when(sTracker).close();
+        OsgiRegistrationUtil.wrap(sTracker).close();
+        verify(sTracker).close();
+    }
+
+    private ServiceRegistration<?> mockServiceRegistration() {
+        ServiceRegistration mock = mock(ServiceRegistration.class);
+        doNothing().when(mock).unregister();
+        return mock;
+    }
+
+    @Test
+    public void testAggregate() throws Exception {
+
+    }
+}
\ No newline at end of file
index 0286400d7b844524ba72dd8cadc7f2de44f7d317..a7024ca39e258011ae11afb15537ddd99764c294 100644 (file)
@@ -9,6 +9,6 @@ package org.opendaylight.controller.config.manager.testingservices.threadpool;
 
 import org.opendaylight.yangtools.yang.binding.annotations.ModuleQName;
 
-@ModuleQName(namespace = "namespace", revision = "revision", name = "name")
+@ModuleQName(namespace = "namespace", revision = "2012-12-12", name = "name")
 public abstract class AbstractTestingFixedThreadPoolModuleFactory {
 }
index 97d1c63ed2770da0ceb4fb504a4795a775b12c89..4ba3dc89399d11f157fdc833b5a72277e8e33ea1 100644 (file)
@@ -380,7 +380,8 @@ public class SimpleConfigurationTest extends AbstractConfigTest {
     @Test
     public void testQNames() {
         Set<String> availableModuleFactoryQNames = configRegistryClient.getAvailableModuleFactoryQNames();
-        String expected = "(namespace?revision=revision)name";
+        String expected = "(namespace?revision=2012-12-12)name";
+
         assertEquals(Sets.newHashSet(expected), availableModuleFactoryQNames);
     }
 
diff --git a/opendaylight/config/config-manager/src/test/resources/module-factories/module-factory-fail b/opendaylight/config/config-manager/src/test/resources/module-factories/module-factory-fail
new file mode 100644 (file)
index 0000000..fbd8108
--- /dev/null
@@ -0,0 +1 @@
+org.opendaylight.controller.config.manager.impl.osgi.ModuleFactoryBundleTrackerTest$NotExtendingTestingFactory
\ No newline at end of file
diff --git a/opendaylight/config/config-manager/src/test/resources/module-factories/module-factory-ok b/opendaylight/config/config-manager/src/test/resources/module-factories/module-factory-ok
new file mode 100644 (file)
index 0000000..031b622
--- /dev/null
@@ -0,0 +1 @@
+org.opendaylight.controller.config.manager.impl.osgi.ModuleFactoryBundleTrackerTest$TestingFactory
\ No newline at end of file
index b9d218ead1ea0fe39efd15c051037ebc2807e8be..1e5fcce6093bec286d4fce3e5e40ea3efc4b8834 100644 (file)
       <groupId>${project.groupId}</groupId>
       <artifactId>netconf-client</artifactId>
     </dependency>
+
+      <dependency>
+          <groupId>${project.groupId}</groupId>
+          <artifactId>config-manager</artifactId>
+          <type>test-jar</type>
+          <scope>test</scope>
+      </dependency>
+      <dependency>
+          <groupId>${project.groupId}</groupId>
+          <artifactId>config-manager</artifactId>
+          <scope>test</scope>
+      </dependency>
+      <dependency>
+          <groupId>${project.groupId}</groupId>
+          <artifactId>config-util</artifactId>
+          <scope>test</scope>
+      </dependency>
+      <dependency>
+          <groupId>${project.groupId}</groupId>
+          <artifactId>netty-threadgroup-config</artifactId>
+          <scope>test</scope>
+      </dependency>
+      <dependency>
+          <groupId>${project.groupId}</groupId>
+          <artifactId>netty-timer-config</artifactId>
+          <scope>test</scope>
+      </dependency>
+      <dependency>
+          <groupId>org.opendaylight.yangtools</groupId>
+          <artifactId>mockito-configuration</artifactId>
+          <scope>test</scope>
+      </dependency>
   </dependencies>
 
   <build>
diff --git a/opendaylight/config/netconf-config-dispatcher/src/test/java/org/opendaylight/controller/config/yang/config/netconf/client/dispatcher/NetconfClientDispatcherModuleTest.java b/opendaylight/config/netconf-config-dispatcher/src/test/java/org/opendaylight/controller/config/yang/config/netconf/client/dispatcher/NetconfClientDispatcherModuleTest.java
new file mode 100644 (file)
index 0000000..85477a0
--- /dev/null
@@ -0,0 +1,102 @@
+package org.opendaylight.controller.config.yang.config.netconf.client.dispatcher;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectName;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.config.api.ConflictingVersionException;
+import org.opendaylight.controller.config.api.ValidationException;
+import org.opendaylight.controller.config.api.jmx.CommitStatus;
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
+import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
+import org.opendaylight.controller.config.yang.netty.threadgroup.NettyThreadgroupModuleFactory;
+import org.opendaylight.controller.config.yang.netty.threadgroup.NettyThreadgroupModuleMXBean;
+import org.opendaylight.controller.config.yang.netty.timer.HashedWheelTimerModuleFactory;
+
+public class NetconfClientDispatcherModuleTest extends AbstractConfigTest{
+
+    private NetconfClientDispatcherModuleFactory factory;
+    private final String instanceName = "dispatch";
+
+    @Before
+    public void setUp() {
+        factory = new NetconfClientDispatcherModuleFactory();
+        super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory,
+                new NettyThreadgroupModuleFactory(),
+                new HashedWheelTimerModuleFactory()));
+    }
+
+    @Test
+    public void testCreateBean() throws InstanceAlreadyExistsException, ValidationException, ConflictingVersionException {
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+
+        createInstance(transaction, instanceName, "timer", "thGroup");
+        createInstance(transaction, instanceName + 2, "timer2", "thGroup2");
+        transaction.validateConfig();
+        CommitStatus status = transaction.commit();
+
+        assertBeanCount(2, factory.getImplementationName());
+        assertStatus(status, 2 + 4, 0, 0);
+    }
+
+    @Test
+    public void testReusingOldInstance() throws InstanceAlreadyExistsException, ConflictingVersionException, ValidationException {
+
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+        createInstance(transaction, instanceName, "timer", "thGroup");
+
+        transaction.commit();
+
+        transaction = configRegistryClient.createTransaction();
+        assertBeanCount(1, factory.getImplementationName());
+        CommitStatus status = transaction.commit();
+
+        assertBeanCount(1, factory.getImplementationName());
+        assertStatus(status, 0, 0, 3);
+    }
+
+    @Test
+    public void testReconfigure() throws InstanceAlreadyExistsException, ConflictingVersionException,
+            ValidationException, InstanceNotFoundException {
+
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+        createInstance(transaction, instanceName, "timer", "thGroup");
+
+        transaction.commit();
+
+        transaction = configRegistryClient.createTransaction();
+        assertBeanCount(1, factory.getImplementationName());
+        NetconfClientDispatcherModuleMXBean mxBean = transaction.newMBeanProxy(
+                transaction.lookupConfigBean(NetconfClientDispatcherModuleFactory.NAME, instanceName),
+                NetconfClientDispatcherModuleMXBean.class);
+        mxBean.setBossThreadGroup(getThreadGroup(transaction, "group2"));
+        CommitStatus status = transaction.commit();
+
+        assertBeanCount(1, factory.getImplementationName());
+        assertStatus(status, 1, 1, 2);
+    }
+
+    private ObjectName createInstance(ConfigTransactionJMXClient transaction, String instanceName, String timerName, String threadGroupName)
+            throws InstanceAlreadyExistsException {
+        ObjectName nameCreated = transaction.createModule(factory.getImplementationName(), instanceName);
+        NetconfClientDispatcherModuleMXBean mxBean = transaction.newMBeanProxy(nameCreated, NetconfClientDispatcherModuleMXBean.class);
+        ObjectName thGroup = getThreadGroup(transaction, threadGroupName);
+        mxBean.setBossThreadGroup(thGroup);
+        mxBean.setWorkerThreadGroup(thGroup);
+        mxBean.setTimer(getTimer(transaction, timerName));
+        return nameCreated;
+    }
+
+    private ObjectName getTimer(ConfigTransactionJMXClient transaction, String name) throws InstanceAlreadyExistsException {
+        return transaction.createModule(HashedWheelTimerModuleFactory.NAME, name);
+    }
+
+    private ObjectName getThreadGroup(ConfigTransactionJMXClient transaction, String name) throws InstanceAlreadyExistsException {
+        ObjectName nameCreated = transaction.createModule(NettyThreadgroupModuleFactory.NAME, name);
+        NettyThreadgroupModuleMXBean mxBean = transaction.newMXBeanProxy(nameCreated, NettyThreadgroupModuleMXBean.class);
+        mxBean.setThreadCount(1);
+        return nameCreated;
+    }
+}
diff --git a/opendaylight/config/netty-event-executor-config/src/test/java/org/opendaylight/controller/config/yang/netty/eventexecutor/ImmediateEventExecutorModuleTest.java b/opendaylight/config/netty-event-executor-config/src/test/java/org/opendaylight/controller/config/yang/netty/eventexecutor/ImmediateEventExecutorModuleTest.java
new file mode 100644 (file)
index 0000000..4cc9cc3
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * 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.config.yang.netty.eventexecutor;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.ObjectName;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.config.api.ConflictingVersionException;
+import org.opendaylight.controller.config.api.ValidationException;
+import org.opendaylight.controller.config.api.jmx.CommitStatus;
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
+import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
+
+public class ImmediateEventExecutorModuleTest extends AbstractConfigTest {
+
+    private GlobalEventExecutorModuleFactory factory;
+    private final String instanceName = ImmediateEventExecutorModuleFactory.SINGLETON_NAME;
+
+    @Before
+    public void setUp() {
+        factory = new GlobalEventExecutorModuleFactory();
+        super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory));
+    }
+
+    @Test
+    public void testCreateBean() throws InstanceAlreadyExistsException, ValidationException,
+            ConflictingVersionException {
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+
+        createInstance(transaction, instanceName);
+
+        transaction.validateConfig();
+        CommitStatus status = transaction.commit();
+
+        assertBeanCount(1, factory.getImplementationName());
+        assertStatus(status, 1, 0, 0);
+    }
+
+    @Test
+    public void testReusingOldInstance() throws InstanceAlreadyExistsException, ConflictingVersionException,
+            ValidationException {
+
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+        createInstance(transaction, instanceName);
+
+        transaction.commit();
+
+        transaction = configRegistryClient.createTransaction();
+        assertBeanCount(1, factory.getImplementationName());
+        CommitStatus status = transaction.commit();
+
+        assertBeanCount(1, factory.getImplementationName());
+        assertStatus(status, 0, 0, 1);
+    }
+
+    private ObjectName createInstance(ConfigTransactionJMXClient transaction, String instanceName)
+            throws InstanceAlreadyExistsException {
+        ObjectName nameCreated = transaction.createModule(factory.getImplementationName(), instanceName);
+        transaction.newMBeanProxy(nameCreated, ImmediateEventExecutorModuleMXBean.class);
+        return nameCreated;
+    }
+
+}
@@ -34,7 +34,7 @@ public class HashedWheelTimerModuleTest extends AbstractConfigTest {
     public void setUp() {
         factory = new HashedWheelTimerModuleFactory();
         threadFactory = new NamingThreadFactoryModuleFactory();
-        super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory, threadFactory));
+        super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, factory, threadFactory));
     }
 
     public void testValidationExceptionTickDuration() throws InstanceAlreadyExistsException {
index 9724d31f9ae6cd3ab8eaef0c23212bf626cfca84..29ac12393ac54aa33d2de6b01af01c1213db1c4c 100644 (file)
@@ -7,21 +7,20 @@
  */
 package org.opendaylight.controller.md.inventory.manager;
 
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
 import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.ExecutionException;
 import java.util.concurrent.LinkedBlockingDeque;
-
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
-import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Preconditions;
-
 class FlowCapableInventoryProvider implements AutoCloseable, Runnable {
     private static final Logger LOG = LoggerFactory.getLogger(FlowCapableInventoryProvider.class);
     private static final int QUEUE_DEPTH = 500;
@@ -29,12 +28,13 @@ class FlowCapableInventoryProvider implements AutoCloseable, Runnable {
 
     private final BlockingQueue<InventoryOperation> queue = new LinkedBlockingDeque<>(QUEUE_DEPTH);
     private final NotificationProviderService notificationService;
-    private final DataProviderService dataService;
+
+    private final DataBroker dataBroker;
     private ListenerRegistration<?> listenerRegistration;
     private Thread thread;
 
-    FlowCapableInventoryProvider(final DataProviderService dataService, final NotificationProviderService notificationService) {
-        this.dataService = Preconditions.checkNotNull(dataService);
+    FlowCapableInventoryProvider(final DataBroker dataBroker, final NotificationProviderService notificationService) {
+        this.dataBroker = Preconditions.checkNotNull(dataBroker);
         this.notificationService = Preconditions.checkNotNull(notificationService);
     }
 
@@ -82,10 +82,10 @@ class FlowCapableInventoryProvider implements AutoCloseable, Runnable {
     @Override
     public void run() {
         try {
-            for (;;) {
+            for (; ; ) {
                 InventoryOperation op = queue.take();
 
-                final DataModificationTransaction tx = dataService.beginTransaction();
+                final ReadWriteTransaction tx = dataBroker.newReadWriteTransaction();
                 LOG.debug("New operations available, starting transaction {}", tx.getIdentifier());
 
                 int ops = 0;
@@ -102,14 +102,18 @@ class FlowCapableInventoryProvider implements AutoCloseable, Runnable {
 
                 LOG.debug("Processed {} operations, submitting transaction {}", ops, tx.getIdentifier());
 
-                try {
-                    final RpcResult<TransactionStatus> result = tx.commit().get();
-                    if(!result.isSuccessful()) {
-                        LOG.error("Transaction {} failed", tx.getIdentifier());
+                final CheckedFuture<Void, TransactionCommitFailedException> result = tx.submit();
+                Futures.addCallback(result, new FutureCallback<Void>() {
+                    @Override
+                    public void onSuccess(Void aVoid) {
+                        //NOOP
+                    }
+
+                    @Override
+                    public void onFailure(Throwable throwable) {
+                        LOG.error("Transaction {} failed.", tx.getIdentifier(), throwable);
                     }
-                } catch (ExecutionException e) {
-                    LOG.warn("Failed to commit inventory change", e.getCause());
-                }
+                });
             }
         } catch (InterruptedException e) {
             LOG.info("Processing interrupted, terminating", e);
index 5bcae367e3e98a6270e01e270adbd2f231256fa9..991611aebc4492c63bd8ece7f7eb1f10289b89da 100644 (file)
@@ -7,10 +7,10 @@
  */
 package org.opendaylight.controller.md.inventory.manager;
 
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
 import org.osgi.framework.BundleContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -21,11 +21,11 @@ public class InventoryActivator extends AbstractBindingAwareProvider {
 
     @Override
     public void onSessionInitiated(final ProviderContext session) {
-        DataProviderService salDataService = session.getSALService(DataProviderService.class);
+        DataBroker dataBroker = session.getSALService(DataBroker.class);
         NotificationProviderService salNotifiService =
                 session.getSALService(NotificationProviderService.class);
 
-        provider = new FlowCapableInventoryProvider(salDataService, salNotifiService);
+        provider = new FlowCapableInventoryProvider(dataBroker, salNotifiService);
         provider.start();
     }
 
index 3be5fcf643fec84694a5ba0ae4eacc1e557a5c01..cfc95799839a40cac8ef195e79d8320c1e42e91e 100644 (file)
@@ -7,10 +7,10 @@
  */
 package org.opendaylight.controller.md.inventory.manager;
 
-import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 
 interface InventoryOperation {
 
-    void applyOperation(DataModificationTransaction tx);
+    void applyOperation(ReadWriteTransaction tx);
 
 }
index 3db3c93fcce11ccf46569514b901ef3c9c99e60d..57ec89307678ae5e28641671182650e8de9254b6 100644 (file)
@@ -7,11 +7,20 @@
  */
 package org.opendaylight.controller.md.inventory.manager;
 
-import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorUpdated;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRemoved;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdated;
@@ -25,13 +34,12 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.No
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Preconditions;
-
 class NodeChangeCommiter implements OpendaylightInventoryListener {
     private static final Logger LOG = LoggerFactory.getLogger(NodeChangeCommiter.class);
 
@@ -43,21 +51,23 @@ class NodeChangeCommiter implements OpendaylightInventoryListener {
 
     @Override
     public synchronized void onNodeConnectorRemoved(final NodeConnectorRemoved connector) {
+        LOG.debug("Node connector removed notification received.");
         manager.enqueue(new InventoryOperation() {
             @Override
-            public void applyOperation(final DataModificationTransaction tx) {
+            public void applyOperation(final ReadWriteTransaction tx) {
                 final NodeConnectorRef ref = connector.getNodeConnectorRef();
                 LOG.debug("removing node connector {} ", ref.getValue());
-                tx.removeOperationalData(ref.getValue());
+                tx.delete(LogicalDatastoreType.OPERATIONAL, ref.getValue());
             }
         });
     }
 
     @Override
     public synchronized void onNodeConnectorUpdated(final NodeConnectorUpdated connector) {
+        LOG.debug("Node connector updated notification received.");
         manager.enqueue(new InventoryOperation() {
             @Override
-            public void applyOperation(final DataModificationTransaction tx) {
+            public void applyOperation(final ReadWriteTransaction tx) {
                 final NodeConnectorRef ref = connector.getNodeConnectorRef();
                 final NodeConnectorBuilder data = new NodeConnectorBuilder(connector);
                 data.setKey(new NodeConnectorKey(connector.getId()));
@@ -68,22 +78,23 @@ class NodeChangeCommiter implements OpendaylightInventoryListener {
                     final FlowCapableNodeConnector augment = InventoryMapping.toInventoryAugment(flowConnector);
                     data.addAugmentation(FlowCapableNodeConnector.class, augment);
                 }
-                InstanceIdentifier<? extends Object> value = ref.getValue();
+                InstanceIdentifier<NodeConnector> value = (InstanceIdentifier<NodeConnector>) ref.getValue();
                 LOG.debug("updating node connector : {}.", value);
                 NodeConnector build = data.build();
-                tx.putOperationalData(value, build);
+                tx.put(LogicalDatastoreType.OPERATIONAL, value, build);
             }
         });
     }
 
     @Override
     public synchronized void onNodeRemoved(final NodeRemoved node) {
+        LOG.debug("Node removed notification received.");
         manager.enqueue(new InventoryOperation() {
             @Override
-            public void applyOperation(final DataModificationTransaction tx) {
+            public void applyOperation(final ReadWriteTransaction tx) {
                 final NodeRef ref = node.getNodeRef();
                 LOG.debug("removing node : {}", ref.getValue());
-                tx.removeOperationalData((ref.getValue()));
+                tx.delete(LogicalDatastoreType.OPERATIONAL, ref.getValue());
             }
         });
     }
@@ -94,23 +105,62 @@ class NodeChangeCommiter implements OpendaylightInventoryListener {
         if (flowNode == null) {
             return;
         }
-
+        LOG.debug("Node updated notification received.");
         manager.enqueue(new InventoryOperation() {
             @Override
-            public void applyOperation(final DataModificationTransaction tx) {
+            public void applyOperation(ReadWriteTransaction tx) {
                 final NodeRef ref = node.getNodeRef();
+                @SuppressWarnings("unchecked")
+                InstanceIdentifierBuilder<Node> builder = ((InstanceIdentifier<Node>) ref.getValue()).builder();
+                InstanceIdentifierBuilder<FlowCapableNode> augmentation = builder.augmentation(FlowCapableNode.class);
+                final InstanceIdentifier<FlowCapableNode> path = augmentation.build();
+                CheckedFuture readFuture = tx.read(LogicalDatastoreType.OPERATIONAL, path);
+                Futures.addCallback(readFuture, new FutureCallback<Optional<? extends DataObject>>() {
+                    @Override
+                    public void onSuccess(Optional<? extends DataObject> optional) {
+                        enqueueWriteNodeDataTx(node, flowNode, path);
+                        if (!optional.isPresent()) {
+                            enqueuePutTable0Tx(ref);
+                        }
+                    }
+
+                    @Override
+                    public void onFailure(Throwable throwable) {
+                        LOG.debug(String.format("Can't retrieve node data for node %s. Writing node data with table0.", node));
+                        enqueueWriteNodeDataTx(node, flowNode, path);
+                        enqueuePutTable0Tx(ref);
+                    }
+                });
+            }
+        });
+    }
+
+    private void enqueueWriteNodeDataTx(final NodeUpdated node, final FlowCapableNodeUpdated flowNode, final InstanceIdentifier<FlowCapableNode> path) {
+        manager.enqueue(new InventoryOperation() {
+            @Override
+            public void applyOperation(final ReadWriteTransaction tx) {
                 final NodeBuilder nodeBuilder = new NodeBuilder(node);
                 nodeBuilder.setKey(new NodeKey(node.getId()));
 
                 final FlowCapableNode augment = InventoryMapping.toInventoryAugment(flowNode);
                 nodeBuilder.addAugmentation(FlowCapableNode.class, augment);
-
-                @SuppressWarnings("unchecked")
-                InstanceIdentifierBuilder<Node> builder = ((InstanceIdentifier<Node>) ref.getValue()).builder();
-                InstanceIdentifierBuilder<FlowCapableNode> augmentation = builder.augmentation(FlowCapableNode.class);
-                final InstanceIdentifier<FlowCapableNode> path = augmentation.build();
                 LOG.debug("updating node :{} ", path);
-                tx.putOperationalData(path, augment);
+                tx.put(LogicalDatastoreType.OPERATIONAL, path, augment);
+            }
+        });
+    }
+
+    private void enqueuePutTable0Tx(final NodeRef ref) {
+        manager.enqueue(new InventoryOperation() {
+            @Override
+            public void applyOperation(ReadWriteTransaction tx) {
+                final TableKey tKey = new TableKey((short) 0);
+                final InstanceIdentifier<Table> tableIdentifier =
+                        ((InstanceIdentifier<Node>) ref.getValue()).augmentation(FlowCapableNode.class).child(Table.class, new TableKey(tKey));
+                TableBuilder tableBuilder = new TableBuilder();
+                Table table0 = tableBuilder.setId((short) 0).build();
+                LOG.debug("writing table :{} ", tableIdentifier);
+                tx.put(LogicalDatastoreType.OPERATIONAL, tableIdentifier, table0, true);
             }
         });
     }
@@ -1,13 +1,13 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: CompositeModificationPayload.proto
 
-package org.opendaylight.controller.mdsal;
+package org.opendaylight.controller.protobuff.messages.shard;
 
 public final class CompositeModificationPayload {
   private CompositeModificationPayload() {}
   public static void registerAllExtensions(
       com.google.protobuf.ExtensionRegistry registry) {
-    registry.add(org.opendaylight.controller.mdsal.CompositeModificationPayload.modification);
+    registry.add(org.opendaylight.controller.protobuff.messages.shard.CompositeModificationPayload.modification);
   }
   public static final int MODIFICATION_FIELD_NUMBER = 2;
   /**
@@ -36,7 +36,8 @@ public final class CompositeModificationPayload {
       "daylight.controller.cluster.raft.AppendE" +
       "ntries.ReplicatedLogEntry.Payload\030\002 \001(\0132" +
       "8.org.opendaylight.controller.mdsal.Comp" +
-      "ositeModification"
+      "ositeModificationB6\n4org.opendaylight.co" +
+      "ntroller.protobuff.messages.shard"
     };
     com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
       new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
index b571cd25c57cc09063f442491b82b6c0647e7531..e824e9e3ae3abb56c88e140ae73baf1d6e72fd71 100644 (file)
@@ -4,6 +4,8 @@ import "AppendEntriesMessages.proto";
 import "Common.proto";
 import "Persistent.proto";
 
+option java_package = "org.opendaylight.controller.protobuff.messages.shard";
+
 extend org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry.Payload {
     optional CompositeModification modification=2;
 }
index d726823b98b2c736fb75309024f84de1cdb6e64b..a42a66aed14d48423101e0667dc10ad3760258b4 100644 (file)
   <description>Configuration files for md-sal clustering</description>
   <packaging>jar</packaging>
   <build>
-    <plugins>
-        <plugin>
-        <groupId>org.codehaus.mojo</groupId>
-        <artifactId>build-helper-maven-plugin</artifactId>
-        <executions>
-          <execution>
-            <id>attach-artifacts</id>
-            <goals>
-              <goal>attach-artifact</goal>
-            </goals>
-            <phase>package</phase>
-            <configuration>
-              <artifacts>
-                <artifact>
-                  <file>${project.build.directory}/classes/initial/*.conf</file>
-                  <type>xml</type>
-                  <classifier>config</classifier>
-                </artifact>
-              </artifacts>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
-    </plugins>
   </build>
 </project>
index d0abb20718bd87dfc13f862bbe6f4672878abc35..36c0447b6e90d35c8f54f8844cf762c3fc0e1897 100644 (file)
@@ -35,7 +35,8 @@ public class CompositeModificationPayload extends Payload implements
     @Override public Map<GeneratedMessage.GeneratedExtension, PersistentMessages.CompositeModification> encode() {
         Preconditions.checkState(modification!=null);
         Map<GeneratedMessage.GeneratedExtension, PersistentMessages.CompositeModification> map = new HashMap<>();
-        map.put(org.opendaylight.controller.mdsal.CompositeModificationPayload.modification, this.modification);
+        map.put(
+            org.opendaylight.controller.protobuff.messages.shard.CompositeModificationPayload.modification, this.modification);
         return map;
     }
 
@@ -43,7 +44,7 @@ public class CompositeModificationPayload extends Payload implements
         AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload payload) {
         PersistentMessages.CompositeModification modification = payload
             .getExtension(
-                org.opendaylight.controller.mdsal.CompositeModificationPayload.modification);
+                org.opendaylight.controller.protobuff.messages.shard.CompositeModificationPayload.modification);
 
 
 
index 874d3fcb90a412169c9ddd7c00c4d9dfbd25354e..459eb78903b6dc09b0739b49198a71d71f05c2f2 100644 (file)
@@ -17,13 +17,13 @@ odl-cluster{
 
       log-remote-lifecycle-events = off
       netty.tcp {
-        hostname = "localhost"
+        hostname = "127.0.0.1"
         port = 2551
       }
     }
 
     cluster {
-      seed-nodes = ["akka.tcp://opendaylight-rpc@localhost:2551"]
+      seed-nodes = ["akka.tcp://opendaylight-rpc@127.0.0.1:2551"]
 
       auto-down-unreachable-after = 10s
     }
@@ -52,13 +52,13 @@ memberA{
 
       log-remote-lifecycle-events = off
       netty.tcp {
-        hostname = "localhost"
+        hostname = "127.0.0.1"
         port = 2551
       }
     }
 
     cluster {
-      seed-nodes = ["akka.tcp://opendaylight-rpc@localhost:2551"]
+      seed-nodes = ["akka.tcp://opendaylight-rpc@127.0.0.1:2551"]
 
       auto-down-unreachable-after = 10s
     }
@@ -77,13 +77,13 @@ memberB{
 
       log-remote-lifecycle-events = off
       netty.tcp {
-        hostname = "localhost"
+        hostname = "127.0.0.1"
         port = 2552
       }
     }
 
     cluster {
-      seed-nodes = ["akka.tcp://opendaylight-rpc@localhost:2551"]
+      seed-nodes = ["akka.tcp://opendaylight-rpc@127.0.0.1:2551"]
 
       auto-down-unreachable-after = 10s
     }
@@ -102,13 +102,13 @@ memberC{
 
       log-remote-lifecycle-events = off
       netty.tcp {
-        hostname = "localhost"
+        hostname = "127.0.0.1"
         port = 2553
       }
     }
 
     cluster {
-      seed-nodes = ["akka.tcp://opendaylight-rpc@localhost:2551"]
+      seed-nodes = ["akka.tcp://opendaylight-rpc@127.0.0.1:2551"]
 
       auto-down-unreachable-after = 10s
     }
index edf7388a769a662a0ea7848694501c08a864ac0a..1a14de6f5d5b9049e4199ce743fc7ba95ad913e3 100644 (file)
@@ -32,6 +32,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.f
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.GenericStatistics;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -52,11 +53,10 @@ final class FlowStatsTracker extends AbstractListeningStatsTracker<FlowAndStatis
 
     @Override
     protected void cleanupSingleStat(final DataModificationTransaction trans, final FlowStatsEntry item) {
-        InstanceIdentifier<?> flowRef = getNodeIdentifierBuilder()
-                            .augmentation(FlowCapableNode.class)
-                            .child(Table.class, new TableKey(item.getTableId()))
-                            .child(Flow.class,item.getFlow().getKey())
-                            .augmentation(FlowStatisticsData.class).toInstance();
+        KeyedInstanceIdentifier<Flow, FlowKey> flowRef = getNodeIdentifier()
+                .augmentation(FlowCapableNode.class)
+                .child(Table.class, new TableKey(item.getTableId()))
+                .child(Flow.class, item.getFlow().getKey());
         trans.removeOperationalData(flowRef);
     }
 
index 6dbfd7225b81fe7651881e21f954dee73c729a7f..d7ce9485c63ec92b9fdb48a576246faa0f5ad7e2 100644 (file)
@@ -15,8 +15,14 @@ import static org.opendaylight.md.controller.topology.manager.FlowCapableNodeMap
 import static org.opendaylight.md.controller.topology.manager.FlowCapableNodeMapping.toTopologyNode;
 import static org.opendaylight.md.controller.topology.manager.FlowCapableNodeMapping.toTopologyNodeId;
 
-import org.opendaylight.controller.md.sal.binding.util.TypeSafeDataReader;
-import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorUpdated;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdated;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.FlowTopologyDiscoveryListener;
@@ -41,10 +47,12 @@ import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-import com.google.common.base.Preconditions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 class FlowCapableTopologyExporter implements FlowTopologyDiscoveryListener, OpendaylightInventoryListener {
+
+    private final Logger LOG = LoggerFactory.getLogger(FlowCapableTopologyExporter.class);
     private final InstanceIdentifier<Topology> topology;
     private final OperationProcessor processor;
 
@@ -55,13 +63,21 @@ class FlowCapableTopologyExporter implements FlowTopologyDiscoveryListener, Open
 
     @Override
     public void onNodeRemoved(final NodeRemoved notification) {
+
+        final NodeId nodeId = toTopologyNodeId(getNodeKey(notification.getNodeRef()).getId());
+        final InstanceIdentifier<Node> nodeInstance = toNodeIdentifier(notification.getNodeRef());
+
         processor.enqueueOperation(new TopologyOperation() {
             @Override
-            public void applyOperation(final DataModificationTransaction transaction) {
-                NodeId nodeId = toTopologyNodeId(getNodeKey(notification.getNodeRef()).getId());
-                InstanceIdentifier<Node> nodeInstance = toNodeIdentifier(notification.getNodeRef());
-                transaction.removeOperationalData(nodeInstance);
-                removeAffectedLinks(transaction, nodeId);
+            public void applyOperation(final ReadWriteTransaction transaction) {
+                removeAffectedLinks(nodeId);
+            }
+        });
+
+        processor.enqueueOperation(new TopologyOperation() {
+            @Override
+            public void applyOperation(ReadWriteTransaction transaction) {
+                transaction.delete(LogicalDatastoreType.OPERATIONAL, nodeInstance);
             }
         });
     }
@@ -72,10 +88,10 @@ class FlowCapableTopologyExporter implements FlowTopologyDiscoveryListener, Open
         if (fcnu != null) {
             processor.enqueueOperation(new TopologyOperation() {
                 @Override
-                public void applyOperation(final DataModificationTransaction transaction) {
-                    Node node = toTopologyNode(toTopologyNodeId(notification.getId()), notification.getNodeRef());
-                    InstanceIdentifier<Node> path = getNodePath(toTopologyNodeId(notification.getId()));
-                    transaction.putOperationalData(path, node);
+                public void applyOperation(final ReadWriteTransaction transaction) {
+                    final Node node = toTopologyNode(toTopologyNodeId(notification.getId()), notification.getNodeRef());
+                    final InstanceIdentifier<Node> path = getNodePath(toTopologyNodeId(notification.getId()));
+                    transaction.put(LogicalDatastoreType.OPERATIONAL, path, node);
                 }
             });
         }
@@ -83,15 +99,22 @@ class FlowCapableTopologyExporter implements FlowTopologyDiscoveryListener, Open
 
     @Override
     public void onNodeConnectorRemoved(final NodeConnectorRemoved notification) {
+
+        final InstanceIdentifier<TerminationPoint> tpInstance = toTerminationPointIdentifier(notification
+                .getNodeConnectorRef());
+
         processor.enqueueOperation(new TopologyOperation() {
             @Override
-            public void applyOperation(final DataModificationTransaction transaction) {
-                InstanceIdentifier<TerminationPoint> tpInstance = toTerminationPointIdentifier(notification
-                        .getNodeConnectorRef());
-                TpId tpId = toTerminationPointId(getNodeConnectorKey(notification.getNodeConnectorRef()).getId());
+            public void applyOperation(final ReadWriteTransaction transaction) {
+                final TpId tpId = toTerminationPointId(getNodeConnectorKey(notification.getNodeConnectorRef()).getId());
+                removeAffectedLinks(tpId);
+            }
+        });
 
-                transaction.removeOperationalData(tpInstance);
-                removeAffectedLinks(transaction, tpId);
+        processor.enqueueOperation(new TopologyOperation() {
+            @Override
+            public void applyOperation(ReadWriteTransaction transaction) {
+                transaction.delete(LogicalDatastoreType.OPERATIONAL, tpInstance);
             }
         });
     }
@@ -102,16 +125,15 @@ class FlowCapableTopologyExporter implements FlowTopologyDiscoveryListener, Open
         if (fcncu != null) {
             processor.enqueueOperation(new TopologyOperation() {
                 @Override
-                public void applyOperation(final DataModificationTransaction transaction) {
-                    NodeId nodeId = toTopologyNodeId(getNodeKey(notification.getNodeConnectorRef()).getId());
+                public void applyOperation(final ReadWriteTransaction transaction) {
+                    final NodeId nodeId = toTopologyNodeId(getNodeKey(notification.getNodeConnectorRef()).getId());
                     TerminationPoint point = toTerminationPoint(toTerminationPointId(notification.getId()),
                             notification.getNodeConnectorRef());
-                    InstanceIdentifier<TerminationPoint> path = tpPath(nodeId, point.getKey().getTpId());
-
-                    transaction.putOperationalData(path, point);
+                    final InstanceIdentifier<TerminationPoint> path = tpPath(nodeId, point.getKey().getTpId());
+                    transaction.put(LogicalDatastoreType.OPERATIONAL, path, point);
                     if ((fcncu.getState() != null && fcncu.getState().isLinkDown())
                             || (fcncu.getConfiguration() != null && fcncu.getConfiguration().isPORTDOWN())) {
-                        removeAffectedLinks(transaction, point.getTpId());
+                        removeAffectedLinks(point.getTpId());
                     }
                 }
             });
@@ -122,10 +144,10 @@ class FlowCapableTopologyExporter implements FlowTopologyDiscoveryListener, Open
     public void onLinkDiscovered(final LinkDiscovered notification) {
         processor.enqueueOperation(new TopologyOperation() {
             @Override
-            public void applyOperation(final DataModificationTransaction transaction) {
-                Link link = toTopologyLink(notification);
-                InstanceIdentifier<Link> path = linkPath(link);
-                transaction.putOperationalData(path, link);
+            public void applyOperation(final ReadWriteTransaction transaction) {
+                final Link link = toTopologyLink(notification);
+                final InstanceIdentifier<Link> path = linkPath(link);
+                transaction.put(LogicalDatastoreType.OPERATIONAL, path, link);
             }
         });
     }
@@ -139,8 +161,8 @@ class FlowCapableTopologyExporter implements FlowTopologyDiscoveryListener, Open
     public void onLinkRemoved(final LinkRemoved notification) {
         processor.enqueueOperation(new TopologyOperation() {
             @Override
-            public void applyOperation(final DataModificationTransaction transaction) {
-                transaction.removeOperationalData(linkPath(toTopologyLink(notification)));
+            public void applyOperation(final ReadWriteTransaction transaction) {
+                transaction.delete(LogicalDatastoreType.OPERATIONAL, linkPath(toTopologyLink(notification)));
             }
         });
     }
@@ -162,28 +184,58 @@ class FlowCapableTopologyExporter implements FlowTopologyDiscoveryListener, Open
         return tpPath(toTopologyNodeId(invNodeKey.getId()), toTerminationPointId(invNodeConnectorKey.getId()));
     }
 
-    private void removeAffectedLinks(final DataModificationTransaction transaction, final NodeId id) {
-        TypeSafeDataReader reader = TypeSafeDataReader.forReader(transaction);
-        Topology topologyData = reader.readOperationalData(topology);
-        if (topologyData != null) {
-            for (Link link : topologyData.getLink()) {
-                if (id.equals(link.getSource().getSourceNode()) || id.equals(link.getDestination().getDestNode())) {
-                    transaction.removeOperationalData(linkPath(link));
-                }
+    private void removeAffectedLinks(final NodeId id) {
+        processor.enqueueOperation(new TopologyOperation() {
+            @Override
+            public void applyOperation(final ReadWriteTransaction transaction) {
+                CheckedFuture<Optional<Topology>, ReadFailedException> topologyDataFuture = transaction.read(LogicalDatastoreType.OPERATIONAL, topology);
+                Futures.addCallback(topologyDataFuture, new FutureCallback<Optional<Topology>>() {
+                    @Override
+                    public void onSuccess(Optional<Topology> topologyOptional) {
+                        if (topologyOptional.isPresent()) {
+                            Topology topologyData = topologyOptional.get();
+                            for (Link link : topologyData.getLink()) {
+                                if (id.equals(link.getSource().getSourceNode()) || id.equals(link.getDestination().getDestNode())) {
+                                    transaction.delete(LogicalDatastoreType.OPERATIONAL, linkPath(link));
+                                }
+                            }
+                        }
+                    }
+
+                    @Override
+                    public void onFailure(Throwable throwable) {
+                        LOG.error("Error reading topology data for topology {}", topology, throwable);
+                    }
+                });
             }
-        }
+        });
     }
 
-    private void removeAffectedLinks(final DataModificationTransaction transaction, final TpId id) {
-        TypeSafeDataReader reader = TypeSafeDataReader.forReader(transaction);
-        Topology topologyData = reader.readOperationalData(topology);
-        if (topologyData != null) {
-            for (Link link : topologyData.getLink()) {
-                if (id.equals(link.getSource().getSourceTp()) || id.equals(link.getDestination().getDestTp())) {
-                    transaction.removeOperationalData(linkPath(link));
-                }
+    private void removeAffectedLinks(final TpId id) {
+        processor.enqueueOperation(new TopologyOperation() {
+            @Override
+            public void applyOperation(final ReadWriteTransaction transaction) {
+                CheckedFuture<Optional<Topology>, ReadFailedException> topologyDataFuture = transaction.read(LogicalDatastoreType.OPERATIONAL, topology);
+                Futures.addCallback(topologyDataFuture, new FutureCallback<Optional<Topology>>() {
+                    @Override
+                    public void onSuccess(Optional<Topology> topologyOptional) {
+                        if (topologyOptional.isPresent()) {
+                            Topology topologyData = topologyOptional.get();
+                            for (Link link : topologyData.getLink()) {
+                                if (id.equals(link.getSource().getSourceTp()) || id.equals(link.getDestination().getDestTp())) {
+                                    transaction.delete(LogicalDatastoreType.OPERATIONAL, linkPath(link));
+                                }
+                            }
+                        }
+                    }
+
+                    @Override
+                    public void onFailure(Throwable throwable) {
+                        LOG.error("Error reading topology data for topology {}", topology, throwable);
+                    }
+                });
             }
-        }
+        });
     }
 
     private InstanceIdentifier<Node> getNodePath(final NodeId nodeId) {
index a87971bc6bc0e1d6a294c30a08dfb73cf81484be..0a3b9f6a6b7c53c193cd3fd523504d4e729df180 100644 (file)
@@ -8,12 +8,12 @@
 package org.opendaylight.md.controller.topology.manager;
 
 import java.util.concurrent.ExecutionException;
-
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
-import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
@@ -38,7 +38,7 @@ public class FlowCapableTopologyProvider extends AbstractBindingAwareProvider im
      */
     @Override
     public synchronized void onSessionInitiated(final ProviderContext session) {
-        final DataProviderService dataService = session.getSALService(DataProviderService.class);
+        final DataBroker dataBroker = session.getSALService(DataBroker.class);
         final NotificationProviderService notificationService = session.getSALService(NotificationProviderService.class);
 
         final String name = "flow:1";
@@ -48,14 +48,14 @@ public class FlowCapableTopologyProvider extends AbstractBindingAwareProvider im
                 .child(Topology.class, key)
                 .build();
 
-        final OperationProcessor processor = new OperationProcessor(dataService);
+        final OperationProcessor processor = new OperationProcessor(dataBroker);
         final FlowCapableTopologyExporter listener = new FlowCapableTopologyExporter(processor, path);
         this.listenerRegistration = notificationService.registerNotificationListener(listener);
 
-        final DataModificationTransaction tx = dataService.beginTransaction();
-        tx.putOperationalData(path, new TopologyBuilder().setKey(key).build());
+        final ReadWriteTransaction tx = dataBroker.newReadWriteTransaction();
+        tx.put(LogicalDatastoreType.OPERATIONAL, path, new TopologyBuilder().setKey(key).build());
         try {
-            tx.commit().get();
+            tx.submit().get();
         } catch (InterruptedException | ExecutionException e) {
             LOG.warn("Initial topology export failed, continuing anyway", e);
         }
@@ -87,8 +87,7 @@ public class FlowCapableTopologyProvider extends AbstractBindingAwareProvider im
     /**
      * Gets called during stop bundle
      *
-     * @param context
-     *            The execution context of the bundle being stopped.
+     * @param context The execution context of the bundle being stopped.
      */
     @Override
     public void stopImpl(final BundleContext context) {
index d60c88032dbcc7015fc064a791ca9a16921d7332..3800413eb1b9964d00207f526177862eb69c5885 100644 (file)
@@ -7,30 +7,27 @@
  */
 package org.opendaylight.md.controller.topology.manager;
 
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
 import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.ExecutionException;
 import java.util.concurrent.LinkedBlockingQueue;
-
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
-import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Preconditions;
-
 final class OperationProcessor implements Runnable {
     private static final Logger LOG = LoggerFactory.getLogger(OperationProcessor.class);
     private static final int MAX_TRANSACTION_OPERATIONS = 100;
     private static final int OPERATION_QUEUE_DEPTH = 500;
 
     private final BlockingQueue<TopologyOperation> queue = new LinkedBlockingQueue<>(OPERATION_QUEUE_DEPTH);
-    // FIXME: Flow capable topology exporter should use transaction chaining API
-    private final DataProviderService dataService;
+    private final DataBroker dataBroker;
 
-    OperationProcessor(final DataProviderService dataService) {
-        this.dataService = Preconditions.checkNotNull(dataService);
+    OperationProcessor(final DataBroker dataBroker) {
+        this.dataBroker = Preconditions.checkNotNull(dataBroker);
     }
 
     void enqueueOperation(final TopologyOperation task) {
@@ -44,11 +41,11 @@ final class OperationProcessor implements Runnable {
     @Override
     public void run() {
         try {
-            for (;;) {
+            for (; ; ) {
                 TopologyOperation op = queue.take();
 
                 LOG.debug("New operations available, starting transaction");
-                final DataModificationTransaction tx = dataService.beginTransaction();
+                final ReadWriteTransaction tx = dataBroker.newReadWriteTransaction();
 
                 int ops = 0;
                 do {
@@ -64,14 +61,18 @@ final class OperationProcessor implements Runnable {
 
                 LOG.debug("Processed {} operations, submitting transaction", ops);
 
-                try {
-                    final RpcResult<TransactionStatus> s = tx.commit().get();
-                    if (!s.isSuccessful()) {
-                        LOG.error("Topology export failed for Tx:{}", tx.getIdentifier());
+                final CheckedFuture txResultFuture = tx.submit();
+                Futures.addCallback(txResultFuture, new FutureCallback() {
+                    @Override
+                    public void onSuccess(Object o) {
+                        LOG.debug("Topology export successful for tx :{}", tx.getIdentifier());
+                    }
+
+                    @Override
+                    public void onFailure(Throwable throwable) {
+                        LOG.error("Topology export transaction {} failed", tx.getIdentifier(), throwable.getCause());
                     }
-                } catch (ExecutionException e) {
-                    LOG.error("Topology export transaction {} failed", tx.getIdentifier(), e.getCause());
-                }
+                });
             }
         } catch (InterruptedException e) {
             LOG.info("Interrupted processing, terminating", e);
index 29d06beade946a1a0bf341917a3741097b5ce980..bbb8a74b03ce4a8701c301bd74fafcd14437465e 100644 (file)
@@ -7,7 +7,7 @@
  */
 package org.opendaylight.md.controller.topology.manager;
 
-import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 
 /**
  * Internal interface for submitted operations. Implementations of this
@@ -19,5 +19,5 @@ interface TopologyOperation {
      *
      * @param transaction Datastore transaction
      */
-    void applyOperation(DataModificationTransaction transaction);
+    void applyOperation(ReadWriteTransaction transaction);
 }
\ No newline at end of file
index 2c10cca0c0e4d0819f91d2f7d5543897d216cd65..ae5aa0f7fbb0c4ccb55d8d389ae4709afe1df4a5 100644 (file)
@@ -43,9 +43,18 @@ public class NeutronRouter extends ConfigurationObject implements Serializable,
     @XmlElement (name="tenant_id")
     String tenantID;
 
-    @XmlElement (name="external_gateway_info")
+    @XmlElement (name="external_gateway_info", nillable=true)
     NeutronRouter_NetworkReference externalGatewayInfo;
 
+    @XmlElement (name="distributed")
+    Boolean distributed;
+
+    @XmlElement (name="gw_port_id", nillable=true)
+    String gatewayPortId;
+
+    @XmlElement (name="routes")
+    List<String> routes;
+
     /* Holds a map of OpenStackRouterInterfaces by subnet UUID
      * used for internal mapping to DOVE
      */
@@ -112,6 +121,30 @@ public class NeutronRouter extends ConfigurationObject implements Serializable,
         this.externalGatewayInfo = externalGatewayInfo;
     }
 
+    public Boolean getDistributed() {
+        return distributed;
+    }
+
+    public void setDistributed(Boolean distributed) {
+        this.distributed = distributed;
+    }
+
+    public String getGatewayPortId() {
+        return gatewayPortId;
+    }
+
+    public void setGatewayPortId(String gatewayPortId) {
+        this.gatewayPortId = gatewayPortId;
+    }
+
+    public List<String> getRoutes() {
+        return routes;
+    }
+
+    public void setRoutes(List<String> routes) {
+        this.routes = routes;
+    }
+
     /**
      * This method copies selected fields from the object and returns them
      * as a new object, suitable for marshaling.
@@ -121,7 +154,6 @@ public class NeutronRouter extends ConfigurationObject implements Serializable,
      * @return an OpenStackRouters object with only the selected fields
      * populated
      */
-
     public NeutronRouter extractFields(List<String> fields) {
         NeutronRouter ans = new NeutronRouter();
         Iterator<String> i = fields.iterator();
@@ -145,6 +177,15 @@ public class NeutronRouter extends ConfigurationObject implements Serializable,
             if (s.equals("external_gateway_info")) {
                 ans.setExternalGatewayInfo(this.getExternalGatewayInfo());
             }
+            if (s.equals("distributed")) {
+                ans.setDistributed(this.getDistributed());
+            }
+            if (s.equals("gw_port_id")) {
+                ans.setGatewayPortId(this.getGatewayPortId());
+            }
+            if (s.equals("routes")){
+                ans.setRoutes(this.getRoutes());
+            }
         }
         return ans;
     }
index f93191220b407b43080595edfff2f771d7160aa4..af7cfd18b98376cd712b8a747f37c62d1a1e476d 100644 (file)
@@ -203,7 +203,7 @@ public class NeutronFloatingIPsNorthbound {
             // if floating IP is specified, make sure it can come from the network
             String floatingIP = singleton.getFloatingIPAddress();
             if (floatingIP != null) {
-                if (externNetwork.getSubnets().size() > 1)
+                if (externNetwork.getSubnets().size() != 1)
                     throw new BadRequestException("external network doesn't have a subnet");
                 NeutronSubnet externSubnet = subnetInterface.getSubnet(externNetwork.getSubnets().get(0));
                 if (!externSubnet.isValidIP(floatingIP))
@@ -312,7 +312,7 @@ public class NeutronFloatingIPsNorthbound {
         if (!input.isSingleton())
             throw new BadRequestException("only singleton requests allowed.");
         NeutronFloatingIP singleton = input.getSingleton();
-        if (singleton.getID() != null)
+        if (singleton.getID() == null)
             throw new BadRequestException("singleton UUID doesn't exist.");
 
         NeutronNetwork externNetwork = networkInterface.getNetwork(
@@ -321,7 +321,7 @@ public class NeutronFloatingIPsNorthbound {
         // if floating IP is specified, make sure it can come from the network
         String floatingIP = singleton.getFloatingIPAddress();
         if (floatingIP != null) {
-            if (externNetwork.getSubnets().size() > 1)
+            if (externNetwork.getSubnets().size() != 1)
                 throw new BadRequestException("external network doesn't have a subnet.");
             NeutronSubnet externSubnet = subnetInterface.getSubnet(externNetwork.getSubnets().get(0));
             if (!externSubnet.isValidIP(floatingIP))