From: Tomas Olvecky Date: Wed, 9 Jul 2014 13:27:09 +0000 (+0200) Subject: Introducing simple merge strategy for config subsystem X-Git-Tag: release/helium~491^2 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=1ed653e2399fccfd914215f6cbbbff4328b42e9e Introducing simple merge strategy for config subsystem MergeEditStrategy wasn't really merging. Now it is, but only for ObjectName[]. However, since ObjectName[] is 90% of the interesting cases, this should get us a long way. This is needed to be able to handle reasonably extension, with the ability to wire in multiple extension modules independently, as we need to do for things like OF extension. Change-Id: Ieca579cbc6781d77f489f5f754490c8da8f65188 Signed-off-by: Ed Warnicke Signed-off-by: Tomas Olvecky --- diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dynamicmbean/DynamicWritableWrapper.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dynamicmbean/DynamicWritableWrapper.java index 335acc81fe..07bd63b7c7 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dynamicmbean/DynamicWritableWrapper.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dynamicmbean/DynamicWritableWrapper.java @@ -53,12 +53,12 @@ public class DynamicWritableWrapper extends AbstractDynamicWrapper { private final ReadOnlyAtomicBoolean configBeanModificationDisabled; public DynamicWritableWrapper(Module module, - ModuleIdentifier moduleIdentifier, - TransactionIdentifier transactionIdentifier, - ReadOnlyAtomicBoolean configBeanModificationDisabled, - MBeanServer internalServer, MBeanServer configMBeanServer) { + ModuleIdentifier moduleIdentifier, + TransactionIdentifier transactionIdentifier, + ReadOnlyAtomicBoolean configBeanModificationDisabled, + MBeanServer internalServer, MBeanServer configMBeanServer) { super(module, true, moduleIdentifier, ObjectNameUtil - .createTransactionModuleON(transactionIdentifier.getName(), moduleIdentifier), getOperations(moduleIdentifier), + .createTransactionModuleON(transactionIdentifier.getName(), moduleIdentifier), getOperations(moduleIdentifier), internalServer, configMBeanServer); this.configBeanModificationDisabled = configBeanModificationDisabled; } @@ -67,22 +67,19 @@ public class DynamicWritableWrapper extends AbstractDynamicWrapper { ModuleIdentifier moduleIdentifier) { Method validationMethod; try { - validationMethod = DynamicWritableWrapper.class.getMethod( - "validate", new Class[0]); + validationMethod = DynamicWritableWrapper.class.getMethod("validate"); } catch (NoSuchMethodException e) { - throw new IllegalStateException("No such method exception on " - + moduleIdentifier, e); + throw new IllegalStateException("No such method exception on " + moduleIdentifier, e); } - return new MBeanOperationInfo[] { new MBeanOperationInfo("Validation", - validationMethod) }; + return new MBeanOperationInfo[]{new MBeanOperationInfo("Validation", validationMethod)}; } @Override public synchronized void setAttribute(Attribute attribute) - throws AttributeNotFoundException, InvalidAttributeValueException, - MBeanException, ReflectionException { - if (configBeanModificationDisabled.get() == true) + throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException { + if (configBeanModificationDisabled.get() == true) { throw new IllegalStateException("Operation is not allowed now"); + } if (attribute.getName().equals("Attribute")) { setAttribute((Attribute) attribute.getValue()); @@ -92,7 +89,7 @@ public class DynamicWritableWrapper extends AbstractDynamicWrapper { try { if (attribute.getValue() instanceof ObjectName) { attribute = fixDependencyAttribute(attribute); - } else if(attribute.getValue() instanceof ObjectName[]) { + } else if (attribute.getValue() instanceof ObjectName[]) { attribute = fixDependencyListAttribute(attribute); } @@ -104,24 +101,19 @@ public class DynamicWritableWrapper extends AbstractDynamicWrapper { } private Attribute fixDependencyListAttribute(Attribute attribute) { - AttributeHolder attributeHolder = attributeHolderMap - .get(attribute.getName()); + AttributeHolder attributeHolder = attributeHolderMap.get(attribute.getName()); if (attributeHolder.getRequireInterfaceOrNull() != null) { - attribute = new Attribute(attribute.getName(), - fixObjectNames((ObjectName[]) attribute.getValue())); + attribute = new Attribute(attribute.getName(), fixObjectNames((ObjectName[]) attribute.getValue())); } return attribute; } private Attribute fixDependencyAttribute(Attribute attribute) { - AttributeHolder attributeHolder = attributeHolderMap - .get(attribute.getName()); + AttributeHolder attributeHolder = attributeHolderMap.get(attribute.getName()); if (attributeHolder.getRequireInterfaceOrNull() != null) { - attribute = new Attribute(attribute.getName(), - fixObjectName((ObjectName) attribute.getValue())); + attribute = new Attribute(attribute.getName(), fixObjectName((ObjectName) attribute.getValue())); } else { - attribute = new Attribute(attribute.getName(), - attribute.getValue()); + attribute = new Attribute(attribute.getName(), attribute.getValue()); } return attribute; } @@ -145,8 +137,7 @@ public class DynamicWritableWrapper extends AbstractDynamicWrapper { setAttribute(attribute); result.add(attribute); } catch (Exception e) { - logger.warn("Setting attribute {} failed on {}", - attribute.getName(), moduleIdentifier, e); + logger.warn("Setting attribute {} failed on {}", attribute.getName(), moduleIdentifier, e); throw new IllegalArgumentException( "Setting attribute failed - " + attribute.getName() + " on " + moduleIdentifier, e); diff --git a/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionClient.java b/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionClient.java index 4f02db5a38..f5381424de 100644 --- a/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionClient.java +++ b/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionClient.java @@ -41,4 +41,14 @@ public interface ConfigTransactionClient extends void destroyModule(String moduleName, String instanceName) throws InstanceNotFoundException; void setAttribute(ObjectName on, String jmxName, Attribute attribute); + + /* + * Get the attribute named jmxName from the Object with ObjectName on + * + * @param on - ObjectName of the Object from which the attribute should be read + * @param jmxName - name of the attribute to be read + * + * @return Attribute of Object on with attribute name jmxName + */ + Attribute getAttribute(ObjectName on, String jmxName); } diff --git a/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionJMXClient.java b/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionJMXClient.java index 4cf766a812..bc18851553 100644 --- a/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionJMXClient.java +++ b/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionJMXClient.java @@ -9,6 +9,7 @@ package org.opendaylight.controller.config.util; import java.util.Map; import java.util.Set; + import javax.management.Attribute; import javax.management.InstanceAlreadyExistsException; import javax.management.InstanceNotFoundException; @@ -17,6 +18,7 @@ import javax.management.JMX; import javax.management.MBeanException; import javax.management.MBeanServer; 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; @@ -270,6 +272,20 @@ public class ConfigTransactionJMXClient implements ConfigTransactionClient { } } + @Override + public Attribute getAttribute(ObjectName on, String attrName) { + if (ObjectNameUtil.getTransactionName(on) == null) + throw new IllegalArgumentException("Not in transaction instance " + + on + ", no transaction name present"); + + try { + return new Attribute(attrName, configMBeanServer.getAttribute(on,attrName)); + } catch (JMException e) { + throw new IllegalStateException("Unable to get attribute " + + attrName + " for " + on, e); + } + } + @Override public Set getAvailableModuleFactoryQNames() { return configTransactionControllerMXBeanProxy.getAvailableModuleFactoryQNames(); diff --git a/opendaylight/config/yang-test/.gitignore b/opendaylight/config/yang-test/.gitignore deleted file mode 100644 index 14393541b4..0000000000 --- a/opendaylight/config/yang-test/.gitignore +++ /dev/null @@ -1 +0,0 @@ -src/main/java/org/opendaylight/controller/config/yang/test/impl/* diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/.gitignore b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/.gitignore new file mode 100644 index 0000000000..27d1535693 --- /dev/null +++ b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/.gitignore @@ -0,0 +1 @@ +*.java diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/DepTestImplModule.java b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/DepTestImplModule.java deleted file mode 100644 index 6046665f45..0000000000 --- a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/DepTestImplModule.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.opendaylight.controller.config.yang.test.impl; -public class DepTestImplModule extends org.opendaylight.controller.config.yang.test.impl.AbstractDepTestImplModule { - public DepTestImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { - super(identifier, dependencyResolver); - } - - public DepTestImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.controller.config.yang.test.impl.DepTestImplModule oldModule, java.lang.AutoCloseable oldInstance) { - super(identifier, dependencyResolver, oldModule, oldInstance); - } - - @Override - public void customValidation() { - // add custom validation form module attributes here. - } - - @Override - public java.lang.AutoCloseable createInstance() { - return new AutoCloseable() { - @Override - public void close() throws Exception { - } - }; - - } - -} diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/DepTestImplModuleFactory.java b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/DepTestImplModuleFactory.java deleted file mode 100644 index 026dd9aca2..0000000000 --- a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/DepTestImplModuleFactory.java +++ /dev/null @@ -1,6 +0,0 @@ - - -package org.opendaylight.controller.config.yang.test.impl; -public class DepTestImplModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractDepTestImplModuleFactory { - -} diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/IdentityTestModule.java b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/IdentityTestModule.java deleted file mode 100644 index bda3548892..0000000000 --- a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/IdentityTestModule.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.opendaylight.controller.config.yang.test.impl; -public class IdentityTestModule extends org.opendaylight.controller.config.yang.test.impl.AbstractIdentityTestModule { - public IdentityTestModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { - super(identifier, dependencyResolver); - } - - public IdentityTestModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.controller.config.yang.test.impl.IdentityTestModule oldModule, java.lang.AutoCloseable oldInstance) { - super(identifier, dependencyResolver, oldModule, oldInstance); - } - - @Override - public void customValidation() { - // add custom validation form module attributes here. - } - - @Override - public java.lang.AutoCloseable createInstance() { - org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(getClass()); - logger.info("Afi: {}", getAfi()); - logger.info("Afi class: {}", getAfiIdentity()); - - for (Identities identities : getIdentities()) { - logger.info("Identities Afi class: {}", identities.resolveAfi()); - logger.info("Identities Safi class: {}", identities.resolveSafi()); - - } - logger.info("IdentityContainer Afi class: {}", getIdentitiesContainer().resolveAfi()); - - return new AutoCloseable() { - @Override - public void close() throws Exception { - } - }; - - } - -} diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/IdentityTestModuleFactory.java b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/IdentityTestModuleFactory.java deleted file mode 100644 index 3a4348d376..0000000000 --- a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/IdentityTestModuleFactory.java +++ /dev/null @@ -1,6 +0,0 @@ - - -package org.opendaylight.controller.config.yang.test.impl; -public class IdentityTestModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractIdentityTestModuleFactory { - -} diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/MultipleDependenciesModuleStub.txt b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/MultipleDependenciesModuleStub.txt new file mode 100644 index 0000000000..80c1e54a15 --- /dev/null +++ b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/MultipleDependenciesModuleStub.txt @@ -0,0 +1,5 @@ + return new AutoCloseable() { + @Override + public void close() throws Exception { + } + }; diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModule.java b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModule.java deleted file mode 100644 index ab43dea5e4..0000000000 --- a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModule.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.opendaylight.controller.config.yang.test.impl; -public class NetconfTestImplModule extends org.opendaylight.controller.config.yang.test.impl.AbstractNetconfTestImplModule { - public NetconfTestImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { - super(identifier, dependencyResolver); - } - - public NetconfTestImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModule oldModule, java.lang.AutoCloseable oldInstance) { - super(identifier, dependencyResolver, oldModule, oldInstance); - } - - @Override - public void customValidation() { - // add custom validation form module attributes here. - } - - @Override - public java.lang.AutoCloseable createInstance() { -return NetconfTestImplModuleUtil.registerRuntimeBeans(this); - - } - -} diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleFactory.java b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleFactory.java deleted file mode 100644 index 587089b10f..0000000000 --- a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleFactory.java +++ /dev/null @@ -1,6 +0,0 @@ - - -package org.opendaylight.controller.config.yang.test.impl; -public class NetconfTestImplModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractNetconfTestImplModuleFactory { - -} diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleStub.txt b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleStub.txt index 6515412f24..dbb6fe6d67 100644 --- a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleStub.txt +++ b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleStub.txt @@ -1 +1 @@ -return NetconfTestImplModuleUtil.registerRuntimeBeans(this); +return org.opendaylight.controller.config.yang.test.util.NetconfTestImplModuleUtil.registerRuntimeBeans(this); diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/TestImplModule.java b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/TestImplModule.java deleted file mode 100644 index 2880b46d1f..0000000000 --- a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/TestImplModule.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.opendaylight.controller.config.yang.test.impl; -public class TestImplModule extends org.opendaylight.controller.config.yang.test.impl.AbstractTestImplModule { - public TestImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { - super(identifier, dependencyResolver); - } - - public TestImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.controller.config.yang.test.impl.TestImplModule oldModule, java.lang.AutoCloseable oldInstance) { - super(identifier, dependencyResolver, oldModule, oldInstance); - } - - @Override - public void customValidation() { - // add custom validation form module attributes here. - } - - @Override - public java.lang.AutoCloseable createInstance() { - return new AutoCloseable() { - @Override - public void close() throws Exception { - } - }; - - } - -} diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/TestImplModuleFactory.java b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/TestImplModuleFactory.java deleted file mode 100644 index de9ac2fef3..0000000000 --- a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/TestImplModuleFactory.java +++ /dev/null @@ -1,6 +0,0 @@ - - -package org.opendaylight.controller.config.yang.test.impl; -public class TestImplModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractTestImplModuleFactory { - -} diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleUtil.java b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/util/NetconfTestImplModuleUtil.java similarity index 69% rename from opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleUtil.java rename to opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/util/NetconfTestImplModuleUtil.java index 1d5cda036f..5e37f5afcf 100644 --- a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleUtil.java +++ b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/util/NetconfTestImplModuleUtil.java @@ -1,13 +1,34 @@ -package org.opendaylight.controller.config.yang.test.impl; +/* + * Copyright (c) 2014 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 + */ -import com.google.common.collect.Lists; +package org.opendaylight.controller.config.yang.test.util; +import com.google.common.collect.Lists; import java.util.List; +import org.opendaylight.controller.config.yang.test.impl.Asdf; +import org.opendaylight.controller.config.yang.test.impl.Deep2; +import org.opendaylight.controller.config.yang.test.impl.Deep3; +import org.opendaylight.controller.config.yang.test.impl.Deep4; +import org.opendaylight.controller.config.yang.test.impl.InnerInnerRunningDataRuntimeMXBean; +import org.opendaylight.controller.config.yang.test.impl.InnerRunningDataAdditionalRuntimeMXBean; +import org.opendaylight.controller.config.yang.test.impl.InnerRunningDataRuntimeMXBean; +import org.opendaylight.controller.config.yang.test.impl.InnerRunningDataRuntimeRegistration; +import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModule; +import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplRuntimeMXBean; +import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplRuntimeRegistration; +import org.opendaylight.controller.config.yang.test.impl.NotStateBean; +import org.opendaylight.controller.config.yang.test.impl.RetValContainer; +import org.opendaylight.controller.config.yang.test.impl.RetValList; public class NetconfTestImplModuleUtil { - static NetconfTestImplRuntimeRegistration registerRuntimeBeans(final NetconfTestImplModule module) { + public static NetconfTestImplRuntimeRegistration registerRuntimeBeans(final NetconfTestImplModule module) { NetconfTestImplRuntimeRegistration reg = module.getRootRuntimeBeanRegistratorWrapper().register(new NetconfTestImplRuntimeMXBean() { @Override diff --git a/opendaylight/config/yang-test/src/main/yang/config-test-impl.yang b/opendaylight/config/yang-test/src/main/yang/config-test-impl.yang index 4b006bc72e..e7aa64d7a6 100644 --- a/opendaylight/config/yang-test/src/main/yang/config-test-impl.yang +++ b/opendaylight/config/yang-test/src/main/yang/config-test-impl.yang @@ -41,6 +41,12 @@ module config-test-impl { config:java-name-prefix IdentityTest; } + identity multiple-dependencies { + base config:module-type; + config:provided-service test:testing; + config:java-name-prefix MultipleDependencies; + } + augment "/config:modules/config:module/config:configuration" { case impl-identity-test { when "/config:modules/config:module/config:type = 'impl-identity-test'"; @@ -444,6 +450,24 @@ module config-test-impl { } } + + augment "/config:modules/config:module/config:configuration" { + case multiple-dependencies { + when "/config:modules/config:module/config:type = 'multiple-dependencies'"; + container multiple-dependencies { + list testing-deps { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity test:testing; + } + } + } + } + } + } + + identity test-rpc; identity inner-test-rpc; identity inner-inner-test-rpc; diff --git a/opendaylight/config/yang-test/src/test/java/org/opendaylight/controller/config/yang/test/impl/MultipleDependenciesModuleTest.java b/opendaylight/config/yang-test/src/test/java/org/opendaylight/controller/config/yang/test/impl/MultipleDependenciesModuleTest.java new file mode 100644 index 0000000000..2df15d0dc1 --- /dev/null +++ b/opendaylight/config/yang-test/src/test/java/org/opendaylight/controller/config/yang/test/impl/MultipleDependenciesModuleTest.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2014 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.test.impl; + +import static java.util.Arrays.asList; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.opendaylight.controller.config.api.jmx.ObjectNameUtil.getInstanceName; +import static org.opendaylight.controller.config.api.jmx.ObjectNameUtil.getTransactionName; + +import java.util.List; +import javax.management.ObjectName; +import org.junit.Before; +import org.junit.Test; +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 MultipleDependenciesModuleTest extends AbstractConfigTest { + private static final MultipleDependenciesModuleFactory factory = new MultipleDependenciesModuleFactory(); + + @Before + public void setUp() throws Exception { + super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, factory)); + } + + @Test + public void testMultipleDependencies() throws Exception { + ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction(); + ObjectName d1 = transaction.createModule(factory.getImplementationName(), "d1"); + ObjectName d2 = transaction.createModule(factory.getImplementationName(), "d2"); + + assertEquals(transaction.getTransactionName(), getTransactionName(d1)); + + ObjectName parent = transaction.createModule(factory.getImplementationName(), "parent"); + MultipleDependenciesModuleMXBean multipleDependenciesModuleMXBean = transaction.newMXBeanProxy(parent, MultipleDependenciesModuleMXBean.class); + multipleDependenciesModuleMXBean.setTestingDeps(asList(d1, d2)); + List found = multipleDependenciesModuleMXBean.getTestingDeps(); + ObjectName d1WithoutTxName = found.get(0); + assertEquals(getInstanceName(d1), getInstanceName(d1WithoutTxName)); + // check that transaction name gets stripped automatically from attribute. + // d1,2 contained tx name, found doesn't + assertNull(getTransactionName(d1WithoutTxName)); + transaction.commit(); + } +} diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/ServiceRegistryWrapper.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/ServiceRegistryWrapper.java index f86d641112..2b363ea153 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/ServiceRegistryWrapper.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/ServiceRegistryWrapper.java @@ -13,11 +13,12 @@ import java.util.Map; import javax.management.InstanceNotFoundException; import javax.management.ObjectName; import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry; +import org.opendaylight.controller.config.api.jmx.ObjectNameUtil; import org.opendaylight.yangtools.yang.common.QName; public class ServiceRegistryWrapper { - private ServiceReferenceReadableRegistry configServiceRefRegistry; + private final ServiceReferenceReadableRegistry configServiceRefRegistry; public ServiceRegistryWrapper(ServiceReferenceReadableRegistry configServiceRefRegistry) { this.configServiceRefRegistry = configServiceRefRegistry; @@ -43,7 +44,12 @@ public class ServiceRegistryWrapper { String qNameOfService = configServiceRefRegistry.getServiceInterfaceName(namespace, serviceName); try { - return configServiceRefRegistry.getServiceReference(qNameOfService, refName); + /* + Remove transaction name as this is redundant - will be stripped in DynamicWritableWrapper, + and makes it hard to compare with service references got from MXBean attributes + */ + return ObjectNameUtil.withoutTransactionName( + configServiceRefRegistry.getServiceReference(qNameOfService, refName)); } catch (InstanceNotFoundException e) { throw new IllegalArgumentException("No serviceInstance mapped to " + refName + " under service name " + serviceName + " , " + refNameToInstance.keySet(), e); diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Services.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Services.java index 37ad2bb222..59a1d4fe71 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Services.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Services.java @@ -104,8 +104,11 @@ public final class Services { String serviceName = ObjectNameAttributeReadingStrategy.checkPrefixAndExtractServiceName(typeElement, prefixNamespace); - Map innerMap = Maps.newHashMap(); - namespaceToServices.put(serviceName, innerMap); + Map innerMap = namespaceToServices.get(serviceName); + if (innerMap == null) { + innerMap = Maps.newHashMap(); + namespaceToServices.put(serviceName, innerMap); + } List instances = service.getChildElements(XmlNetconfConstants.INSTANCE_KEY); service.checkUnrecognisedElements(instances, typeElement); diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/MergeEditConfigStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/MergeEditConfigStrategy.java index 6ebeeaa07b..d8ceb31103 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/MergeEditConfigStrategy.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/MergeEditConfigStrategy.java @@ -8,6 +8,10 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig; +import static java.util.Arrays.asList; + +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.Map.Entry; import javax.management.Attribute; @@ -30,7 +34,7 @@ public class MergeEditConfigStrategy extends AbstractEditConfigStrategy { @Override void handleMissingInstance(Map configuration, ConfigTransactionClient ta, - String module, String instance, ServiceRegistryWrapper services) throws NetconfConfigHandlingException { + String module, String instance, ServiceRegistryWrapper services) throws NetconfConfigHandlingException { throw new NetconfConfigHandlingException( String.format("Unable to handle missing instance, no missing instances should appear at this point, missing: %s : %s ", module, @@ -39,6 +43,7 @@ public class MergeEditConfigStrategy extends AbstractEditConfigStrategy { NetconfDocumentedException.ErrorTag.operation_failed, NetconfDocumentedException.ErrorSeverity.error); } + @Override void executeStrategy(Map configuration, ConfigTransactionClient ta, ObjectName on, ServiceRegistryWrapper services) throws NetconfConfigHandlingException { @@ -51,10 +56,16 @@ public class MergeEditConfigStrategy extends AbstractEditConfigStrategy { continue; } - Object value = ace.getResolvedValue().get(); - ta.setAttribute(on, ace.getJmxName(), new Attribute(ace.getJmxName(), value)); - logger.debug("Attribute {} set to {} for {}", configAttributeEntry.getKey(), value, on); + Object toBeMergedIn = ace.getResolvedValue().get(); + // Get the existing values so we can merge the new values with them. + Attribute currentAttribute = ta.getAttribute(on, ace.getJmxName()); + Object oldValue = (currentAttribute != null ? currentAttribute.getValue() : null); + // Merge value with currentValue + toBeMergedIn = merge(oldValue, toBeMergedIn); + ta.setAttribute(on, ace.getJmxName(), new Attribute(ace.getJmxName(), toBeMergedIn)); + logger.debug("Attribute {} set to {} for {}", configAttributeEntry.getKey(), toBeMergedIn, on); } catch (Exception e) { + logger.error("Error while merging objectnames of {}", on, e); throw new NetconfConfigHandlingException(String.format("Unable to set attributes for %s, Error with attribute %s : %s ", on, configAttributeEntry.getKey(), @@ -65,4 +76,44 @@ public class MergeEditConfigStrategy extends AbstractEditConfigStrategy { } } } + + /** + * Merge value into current value + * Currently, this is only implemented for arrays of ObjectNames, but that is the + * most common case for which it is needed. + */ + protected Object merge(Object oldValue, Object toBeMergedIn) { + if (oldValue instanceof ObjectName[] && toBeMergedIn instanceof ObjectName[]) { + toBeMergedIn = mergeObjectNameArrays((ObjectName[]) oldValue, (ObjectName[]) toBeMergedIn); + } + return toBeMergedIn; + } + + /** + * Merge value into current values + * This implements for arrays of ObjectNames, but that is the + * most common case for which it is needed. + * + * @param oldValue - the new values to be merged into existing values + * @param toBeMergedIn - the existing values + * + * @return an ObjectName[] consisting the elements of currentValue with an elements from values not already present in currentValue added + * + */ + protected ObjectName[] mergeObjectNameArrays(ObjectName[] oldValue, ObjectName[] toBeMergedIn) { + List newValueList = new ArrayList<>(); + newValueList.addAll(asList(oldValue)); + /* + It is guaranteed that old values do not contain transaction name. + Since toBeMergedIn is filled using service references translated by ServiceRegistryWrapper, it + is also guaranteed that this list will not contain transaction names. + Run through the list of values to be merged. If we don't have them already, add them to the list. + */ + for (ObjectName objName : toBeMergedIn) { + if (!newValueList.contains(objName)) { + newValueList.add(objName); + } + } + return newValueList.toArray(new ObjectName[newValueList.size()]); + } } diff --git a/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/MergeEditConfigStrategyTest.java b/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/MergeEditConfigStrategyTest.java new file mode 100644 index 0000000000..b1877498a9 --- /dev/null +++ b/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/MergeEditConfigStrategyTest.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2014 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.netconf.confignetconfconnector.operations.editconfig; + +import static java.util.Arrays.asList; +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.opendaylight.controller.config.api.jmx.ObjectNameUtil.createReadOnlyModuleON; + +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableMap; +import java.util.List; +import java.util.Map; +import javax.management.ObjectName; +import org.junit.Before; +import org.junit.Test; +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.test.impl.MultipleDependenciesModule; +import org.opendaylight.controller.config.yang.test.impl.MultipleDependenciesModuleFactory; +import org.opendaylight.controller.config.yang.test.impl.MultipleDependenciesModuleMXBean; +import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement; +import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ServiceRegistryWrapper; + +public class MergeEditConfigStrategyTest extends AbstractConfigTest { + private static final MultipleDependenciesModuleFactory factory = new MultipleDependenciesModuleFactory(); + public static final String PARENT = "parent"; + public static final String D1 = "d1"; + public static final String D2 = "d2"; + public static final String D3 = "d3"; + + private static final String factoryName = factory.getImplementationName(); + + @Before + public void setUp() throws Exception { + super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, factory)); + + ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction(); + ObjectName d1 = transaction.createModule(factoryName, D1); + ObjectName d2 = transaction.createModule(factoryName, D2); + ObjectName parent = transaction.createModule(factoryName, PARENT); + MultipleDependenciesModuleMXBean multipleDependenciesModuleMXBean = transaction.newMXBeanProxy(parent, + MultipleDependenciesModuleMXBean.class); + multipleDependenciesModuleMXBean.setTestingDeps(asList(d1, d2)); + transaction.createModule(factoryName, D3); + transaction.commit(); + } + + @Test + public void testMergingOfObjectNames() throws Exception { + MergeEditConfigStrategy strategy = new MergeEditConfigStrategy(); + ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction(); + + // add D3 + + AttributeConfigElement attributeConfigElement = mock(AttributeConfigElement.class); + doReturn(Optional.of(new ObjectName[] {createReadOnlyModuleON(factoryName, D3)})).when(attributeConfigElement).getResolvedValue(); + doReturn("mocked").when(attributeConfigElement).toString(); + String attributeName = MultipleDependenciesModule.testingDepsJmxAttribute.getAttributeName(); + doReturn(attributeName).when(attributeConfigElement).getJmxName(); + Map configuration = ImmutableMap.of( + attributeName, + attributeConfigElement); + + strategy.executeConfiguration(factoryName, PARENT, configuration, transaction, + mock(ServiceRegistryWrapper.class)); + transaction.commit(); + + // parent's attribute should contain d1,d2,d3 + MultipleDependenciesModuleMXBean proxy = configRegistryClient.newMXBeanProxy( + createReadOnlyModuleON(factoryName, PARENT), + MultipleDependenciesModuleMXBean.class); + List testingDeps = proxy.getTestingDeps(); + List expected = asList(createReadOnlyModuleON(factoryName, D1), + createReadOnlyModuleON(factoryName, D2), + createReadOnlyModuleON(factoryName, D3)); + assertEquals(expected, testingDeps); + } +} diff --git a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfConfigPersisterITTest.java b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfConfigPersisterITTest.java index f7091beba5..eb99be0dc0 100644 --- a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfConfigPersisterITTest.java +++ b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfConfigPersisterITTest.java @@ -18,17 +18,18 @@ import static org.opendaylight.controller.netconf.util.test.XmlUnitUtil.assertCo import static org.opendaylight.controller.netconf.util.test.XmlUnitUtil.assertElementsCount; import static org.opendaylight.controller.netconf.util.xml.XmlUtil.readXmlToDocument; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import io.netty.channel.ChannelFuture; import java.io.IOException; import java.io.InputStream; import java.net.InetSocketAddress; import java.util.Collection; import java.util.List; import java.util.Set; - import javax.management.InstanceNotFoundException; import javax.management.Notification; import javax.management.NotificationListener; - import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -37,7 +38,6 @@ import org.mockito.stubbing.Answer; import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver; import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder; import org.opendaylight.controller.config.persist.api.Persister; -import org.opendaylight.controller.config.spi.ModuleFactory; import org.opendaylight.controller.netconf.api.NetconfMessage; import org.opendaylight.controller.netconf.api.jmx.CommitJMXNotification; import org.opendaylight.controller.netconf.api.monitoring.NetconfManagementSession; @@ -63,10 +63,6 @@ import org.w3c.dom.Document; import org.w3c.dom.Element; import org.xml.sax.SAXException; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; -import io.netty.channel.ChannelFuture; - public class NetconfConfigPersisterITTest extends AbstractNetconfConfigTest { private static final InetSocketAddress tcpAddress = new InetSocketAddress("127.0.0.1", 12023); @@ -76,8 +72,7 @@ public class NetconfConfigPersisterITTest extends AbstractNetconfConfigTest { @Before public void setUp() throws Exception { - super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,NetconfITTest.getModuleFactoriesS().toArray( - new ModuleFactory[0]))); + super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,NetconfITTest.FACTORIES)); NetconfMonitoringServiceImpl monitoringService = new NetconfMonitoringServiceImpl(getNetconfOperationProvider()); diff --git a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITSecureTest.java b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITSecureTest.java index 0969bd92a5..2f7bd20d61 100644 --- a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITSecureTest.java +++ b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITSecureTest.java @@ -8,6 +8,7 @@ package org.opendaylight.controller.netconf.it; +import static java.util.Arrays.asList; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.doAnswer; @@ -99,7 +100,7 @@ public class NetconfITSecureTest extends AbstractNetconfConfigTest { } protected List getModuleFactories() { - return NetconfITTest.getModuleFactoriesS(); + return asList(NetconfITTest.FACTORIES); } @Test diff --git a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java index 60a5207daa..8e69e6a345 100644 --- a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java +++ b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java @@ -16,6 +16,7 @@ import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +import com.google.common.base.Function; import com.google.common.base.Throwables; import com.google.common.collect.Lists; import com.google.common.collect.Sets; @@ -28,6 +29,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.ExecutionException; @@ -39,11 +41,14 @@ import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.matchers.JUnitMatchers; +import org.opendaylight.controller.config.api.jmx.ObjectNameUtil; import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver; import org.opendaylight.controller.config.spi.ModuleFactory; import org.opendaylight.controller.config.util.ConfigTransactionJMXClient; import org.opendaylight.controller.config.yang.test.impl.DepTestImplModuleFactory; import org.opendaylight.controller.config.yang.test.impl.IdentityTestModuleFactory; +import org.opendaylight.controller.config.yang.test.impl.MultipleDependenciesModuleFactory; +import org.opendaylight.controller.config.yang.test.impl.MultipleDependenciesModuleMXBean; import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleFactory; import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleMXBean; import org.opendaylight.controller.config.yang.test.impl.TestImplModuleFactory; @@ -81,23 +86,27 @@ public class NetconfITTest extends AbstractNetconfConfigTest { private NetconfMessage getConfig, getConfigCandidate, editConfig, closeSession; - private DefaultCommitNotificationProducer commitNot; + private DefaultCommitNotificationProducer commitNotificationProducer; private NetconfServerDispatcher dispatch; private NetconfClientDispatcherImpl clientDispatcher; + static ModuleFactory[] FACTORIES = {new TestImplModuleFactory(), new DepTestImplModuleFactory(), + new NetconfTestImplModuleFactory(), new IdentityTestModuleFactory(), + new MultipleDependenciesModuleFactory()}; + @Before public void setUp() throws Exception { - super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,getModuleFactories().toArray( - new ModuleFactory[0]))); + initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, + FACTORIES + )); loadMessages(); NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl(); factoriesListener.onAddNetconfOperationServiceFactory(new NetconfOperationServiceFactoryImpl(getYangStore())); - - commitNot = new DefaultCommitNotificationProducer(ManagementFactory.getPlatformMBeanServer()); + commitNotificationProducer = new DefaultCommitNotificationProducer(ManagementFactory.getPlatformMBeanServer()); dispatch = createDispatcher(factoriesListener); ChannelFuture s = dispatch.createServer(tcpAddress); @@ -107,7 +116,7 @@ public class NetconfITTest extends AbstractNetconfConfigTest { } private NetconfServerDispatcher createDispatcher(NetconfOperationServiceFactoryListenerImpl factoriesListener) { - return super.createDispatcher(factoriesListener, getNetconfMonitoringListenerService(), commitNot); + return super.createDispatcher(factoriesListener, getNetconfMonitoringListenerService(), commitNotificationProducer); } static NetconfMonitoringServiceImpl getNetconfMonitoringListenerService() { @@ -120,7 +129,7 @@ public class NetconfITTest extends AbstractNetconfConfigTest { @After public void tearDown() throws Exception { - commitNot.close(); + commitNotificationProducer.close(); clientDispatcher.close(); } @@ -155,14 +164,6 @@ public class NetconfITTest extends AbstractNetconfConfigTest { return yangDependencies; } - protected List getModuleFactories() { - return getModuleFactoriesS(); - } - - static List getModuleFactoriesS() { - return Lists.newArrayList(new TestImplModuleFactory(), new DepTestImplModuleFactory(), - new NetconfTestImplModuleFactory(), new IdentityTestModuleFactory()); - } @Test public void testNetconfClientDemonstration() throws Exception { @@ -392,4 +393,66 @@ public class NetconfITTest extends AbstractNetconfConfigTest { doReturn(codec).when(ret).getIdentityCodec(); return ret; } + + + @Test + public void testMultipleDependencies() throws Exception { + // push first xml, should add parent and d1,d2 dependencies + try (TestingNetconfClient netconfClient = createSession(tcpAddress, "1")) { + Document rpcReply = netconfClient.sendMessage( + XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/editConfig_merge_multiple-deps1.xml")) + .getDocument(); + assertIsOK(rpcReply); + commit(netconfClient); + } + // verify that parent.getTestingDeps == d1,d2 + MultipleDependenciesModuleMXBean parentProxy = configRegistryClient.newMXBeanProxy( + configRegistryClient.lookupConfigBean(MultipleDependenciesModuleFactory.NAME, "parent"), + MultipleDependenciesModuleMXBean.class); + { + List testingDeps = parentProxy.getTestingDeps(); + assertEquals(2, testingDeps.size()); + Set actualRefs = getServiceReferences(testingDeps); + assertEquals(Sets.newHashSet("ref_d1", "ref_d2"), actualRefs); + } + + // push second xml, should add d3 to parent's dependencies + mergeD3(parentProxy); + // push second xml again, to test that d3 is not added again + mergeD3(parentProxy); + } + + public void mergeD3(MultipleDependenciesModuleMXBean parentProxy) throws Exception { + try (TestingNetconfClient netconfClient = new TestingNetconfClient( + "test " + tcpAddress.toString(), clientDispatcher, getClientConfiguration(tcpAddress, 5000))) { + + Document rpcReply = netconfClient.sendMessage( + XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/editConfig_merge_multiple-deps2.xml")) + .getDocument(); + assertIsOK(rpcReply); + commit(netconfClient); + } + { + List testingDeps = parentProxy.getTestingDeps(); + assertEquals(3, testingDeps.size()); + Set actualRefs = getServiceReferences(testingDeps); + assertEquals(Sets.newHashSet("ref_d1", "ref_d2", "ref_d3"), actualRefs); + } + } + + public Set getServiceReferences(List testingDeps) { + return new HashSet<>(Lists.transform(testingDeps, new Function() { + @Override + public String apply(ObjectName input) { + return ObjectNameUtil.getReferenceName(input); + } + })); + } + + public void commit(TestingNetconfClient netconfClient) throws Exception { + Document rpcReply; + rpcReply = netconfClient.sendMessage(XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/commit.xml")) + .getDocument(); + assertIsOK(rpcReply); + } } diff --git a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfMonitoringITTest.java b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfMonitoringITTest.java index 3b263f7e75..05e32577fe 100644 --- a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfMonitoringITTest.java +++ b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfMonitoringITTest.java @@ -13,6 +13,10 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.opendaylight.controller.netconf.util.test.XmlUnitUtil.assertContainsElementWithText; +import com.google.common.base.Charsets; +import com.google.common.base.Optional; +import com.google.common.collect.Sets; +import io.netty.channel.ChannelFuture; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; @@ -22,14 +26,11 @@ import java.net.Socket; import java.util.Collection; import java.util.List; import java.util.Set; - import junit.framework.Assert; - import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver; -import org.opendaylight.controller.config.spi.ModuleFactory; import org.opendaylight.controller.netconf.api.NetconfMessage; import org.opendaylight.controller.netconf.api.monitoring.NetconfManagementSession; import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl; @@ -53,11 +54,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; -import com.google.common.base.Charsets; -import com.google.common.base.Optional; -import com.google.common.collect.Sets; -import io.netty.channel.ChannelFuture; - public class NetconfMonitoringITTest extends AbstractNetconfConfigTest { private static final Logger logger = LoggerFactory.getLogger(NetconfITTest.class); @@ -74,8 +70,7 @@ public class NetconfMonitoringITTest extends AbstractNetconfConfigTest { @Before public void setUp() throws Exception { - super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, NetconfITTest.getModuleFactoriesS().toArray( - new ModuleFactory[0]))); + super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, NetconfITTest.FACTORIES)); monitoringService = new NetconfMonitoringServiceImpl(getNetconfOperationProvider()); diff --git a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/SSLUtil.java b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/SSLUtil.java index 07ca2f134d..4d232a619a 100644 --- a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/SSLUtil.java +++ b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/SSLUtil.java @@ -28,7 +28,7 @@ public final class SSLUtil { } public static SSLContext initializeSecureContext(final String pass, final InputStream ksKeysFile, final InputStream ksTrustFile, - final String algorithm) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, + final String algorithm) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, UnrecoverableKeyException, KeyManagementException { Preconditions.checkNotNull(ksTrustFile, "ksTrustFile cannot be null"); diff --git a/opendaylight/netconf/netconf-it/src/test/resources/logback.xml b/opendaylight/netconf/netconf-it/src/test/resources/logback-test.xml similarity index 83% rename from opendaylight/netconf/netconf-it/src/test/resources/logback.xml rename to opendaylight/netconf/netconf-it/src/test/resources/logback-test.xml index fa467a1080..c5037d34ed 100644 --- a/opendaylight/netconf/netconf-it/src/test/resources/logback.xml +++ b/opendaylight/netconf/netconf-it/src/test/resources/logback-test.xml @@ -6,7 +6,7 @@ - + diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_merge_multiple-deps1.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_merge_multiple-deps1.xml new file mode 100644 index 0000000000..0a021143d6 --- /dev/null +++ b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_merge_multiple-deps1.xml @@ -0,0 +1,59 @@ + + + + + + + merge + set + + + + d1 + th-java:multiple-dependencies + + + d2 + th-java:multiple-dependencies + + + parent + th-java:multiple-dependencies + + + + prefix:testing + ref_d1 + + + prefix:testing + ref_d2 + + + + + + + + + + prefix:testing + + ref_d1 + /modules/module[type='multiple-dependencies'][name='d1'] + + + + + prefix:testing + + ref_d2 + /modules/module[type='multiple-dependencies'][name='d2'] + + + + + + + diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_merge_multiple-deps2.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_merge_multiple-deps2.xml new file mode 100644 index 0000000000..d331976c0a --- /dev/null +++ b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_merge_multiple-deps2.xml @@ -0,0 +1,39 @@ + + + + + + + merge + set + + + + d3 + th-java:multiple-dependencies + + + parent + th-java:multiple-dependencies + + + prefix:testing + ref_d3 + + + + + + + prefix:testing + + ref_d3 + /modules/module[type='multiple-dependencies'][name='d3'] + + + + + + +