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;
}
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());
try {
if (attribute.getValue() instanceof ObjectName) {
attribute = fixDependencyAttribute(attribute);
- } else if(attribute.getValue() instanceof ObjectName[]) {
+ } else if (attribute.getValue() instanceof ObjectName[]) {
attribute = fixDependencyListAttribute(attribute);
}
}
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;
}
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);
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);
}
import java.util.Map;
import java.util.Set;
+
import javax.management.Attribute;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
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;
}
}
+ @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<String> getAvailableModuleFactoryQNames() {
return configTransactionControllerMXBeanProxy.getAvailableModuleFactoryQNames();
+++ /dev/null
-src/main/java/org/opendaylight/controller/config/yang/test/impl/*
+++ /dev/null
-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 {
- }
- };
-
- }
-
-}
+++ /dev/null
-
-
-package org.opendaylight.controller.config.yang.test.impl;
-public class DepTestImplModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractDepTestImplModuleFactory {
-
-}
+++ /dev/null
-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 {
- }
- };
-
- }
-
-}
+++ /dev/null
-
-
-package org.opendaylight.controller.config.yang.test.impl;
-public class IdentityTestModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractIdentityTestModuleFactory {
-
-}
--- /dev/null
+ return new AutoCloseable() {
+ @Override
+ public void close() throws Exception {
+ }
+ };
+++ /dev/null
-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);
-
- }
-
-}
+++ /dev/null
-
-
-package org.opendaylight.controller.config.yang.test.impl;
-public class NetconfTestImplModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractNetconfTestImplModuleFactory {
-
-}
-return NetconfTestImplModuleUtil.registerRuntimeBeans(this);
+return org.opendaylight.controller.config.yang.test.util.NetconfTestImplModuleUtil.registerRuntimeBeans(this);
+++ /dev/null
-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 {
- }
- };
-
- }
-
-}
+++ /dev/null
-
-
-package org.opendaylight.controller.config.yang.test.impl;
-public class TestImplModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractTestImplModuleFactory {
-
-}
-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
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'";
}
}
+
+ 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;
--- /dev/null
+/*
+ * 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<ObjectName> 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();
+ }
+}
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;
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);
String serviceName = ObjectNameAttributeReadingStrategy.checkPrefixAndExtractServiceName(typeElement, prefixNamespace);
- Map<String, String> innerMap = Maps.newHashMap();
- namespaceToServices.put(serviceName, innerMap);
+ Map<String, String> innerMap = namespaceToServices.get(serviceName);
+ if (innerMap == null) {
+ innerMap = Maps.newHashMap();
+ namespaceToServices.put(serviceName, innerMap);
+ }
List<XmlElement> instances = service.getChildElements(XmlNetconfConstants.INSTANCE_KEY);
service.checkUnrecognisedElements(instances, typeElement);
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;
@Override
void handleMissingInstance(Map<String, AttributeConfigElement> 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,
NetconfDocumentedException.ErrorTag.operation_failed,
NetconfDocumentedException.ErrorSeverity.error);
}
+
@Override
void executeStrategy(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta, ObjectName on, ServiceRegistryWrapper services) throws NetconfConfigHandlingException {
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(),
}
}
}
+
+ /**
+ * 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<ObjectName> 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()]);
+ }
}
--- /dev/null
+/*
+ * 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<String, AttributeConfigElement> 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<ObjectName> testingDeps = proxy.getTestingDeps();
+ List<ObjectName> expected = asList(createReadOnlyModuleON(factoryName, D1),
+ createReadOnlyModuleON(factoryName, D2),
+ createReadOnlyModuleON(factoryName, D3));
+ assertEquals(expected, testingDeps);
+ }
+}
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;
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;
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);
@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());
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;
}
protected List<ModuleFactory> getModuleFactories() {
- return NetconfITTest.getModuleFactoriesS();
+ return asList(NetconfITTest.FACTORIES);
}
@Test
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;
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;
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;
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);
}
private NetconfServerDispatcher createDispatcher(NetconfOperationServiceFactoryListenerImpl factoriesListener) {
- return super.createDispatcher(factoriesListener, getNetconfMonitoringListenerService(), commitNot);
+ return super.createDispatcher(factoriesListener, getNetconfMonitoringListenerService(), commitNotificationProducer);
}
static NetconfMonitoringServiceImpl getNetconfMonitoringListenerService() {
@After
public void tearDown() throws Exception {
- commitNot.close();
+ commitNotificationProducer.close();
clientDispatcher.close();
}
return yangDependencies;
}
- protected List<ModuleFactory> getModuleFactories() {
- return getModuleFactoriesS();
- }
-
- static List<ModuleFactory> getModuleFactoriesS() {
- return Lists.newArrayList(new TestImplModuleFactory(), new DepTestImplModuleFactory(),
- new NetconfTestImplModuleFactory(), new IdentityTestModuleFactory());
- }
@Test
public void testNetconfClientDemonstration() throws Exception {
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<ObjectName> testingDeps = parentProxy.getTestingDeps();
+ assertEquals(2, testingDeps.size());
+ Set<String> 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<ObjectName> testingDeps = parentProxy.getTestingDeps();
+ assertEquals(3, testingDeps.size());
+ Set<String> actualRefs = getServiceReferences(testingDeps);
+ assertEquals(Sets.newHashSet("ref_d1", "ref_d2", "ref_d3"), actualRefs);
+ }
+ }
+
+ public Set<String> getServiceReferences(List<ObjectName> testingDeps) {
+ return new HashSet<>(Lists.transform(testingDeps, new Function<ObjectName, String>() {
+ @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);
+ }
}
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;
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;
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);
@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());
}
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");
</encoder>
</appender>
- <logger name="org.opendaylight.controller.netconf" level="DEBUG"/>
+ <logger name="org.opendaylight.controller.netconf" level="TRACE"/>
<root level="error">
<appender-ref ref="STDOUT" />
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<rpc message-id="6"
+ xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <edit-config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <target>
+ <candidate/>
+ </target>
+ <default-operation>merge</default-operation>
+ <test-option>set</test-option>
+ <config>
+ <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <module>
+ <name>d1</name>
+ <type xmlns:th-java="urn:opendaylight:params:xml:ns:yang:controller:test:impl">th-java:multiple-dependencies</type>
+ </module>
+ <module>
+ <name>d2</name>
+ <type xmlns:th-java="urn:opendaylight:params:xml:ns:yang:controller:test:impl">th-java:multiple-dependencies</type>
+ </module>
+ <module>
+ <name>parent</name>
+ <type xmlns:th-java="urn:opendaylight:params:xml:ns:yang:controller:test:impl">th-java:multiple-dependencies</type>
+
+ <multiple-dependencies xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+ <testing-deps>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+ <name>ref_d1</name>
+ </testing-deps>
+ <testing-deps>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+ <name>ref_d2</name>
+ </testing-deps>
+ </multiple-dependencies>
+
+ </module>
+
+ </modules>
+
+ <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <service>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+ <instance>
+ <name>ref_d1</name>
+ <provider>/modules/module[type='multiple-dependencies'][name='d1']
+ </provider>
+ </instance>
+ </service>
+ <service>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+ <instance>
+ <name>ref_d2</name>
+ <provider>/modules/module[type='multiple-dependencies'][name='d2']
+ </provider>
+ </instance>
+ </service>
+ </services>
+ </config>
+ </edit-config>
+</rpc>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<rpc message-id="6"
+ xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <edit-config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <target>
+ <candidate/>
+ </target>
+ <default-operation>merge</default-operation>
+ <test-option>set</test-option>
+ <config>
+ <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <module>
+ <name>d3</name>
+ <type xmlns:th-java="urn:opendaylight:params:xml:ns:yang:controller:test:impl">th-java:multiple-dependencies</type>
+ </module>
+ <module>
+ <name>parent</name>
+ <type xmlns:th-java="urn:opendaylight:params:xml:ns:yang:controller:test:impl">th-java:multiple-dependencies</type>
+ <multiple-dependencies xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+ <testing-deps>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+ <name>ref_d3</name>
+ </testing-deps>
+ </multiple-dependencies>
+ </module>
+ </modules>
+ <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <service>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+ <instance>
+ <name>ref_d3</name>
+ <provider>/modules/module[type='multiple-dependencies'][name='d3']
+ </provider>
+ </instance>
+ </service>
+ </services>
+ </config>
+ </edit-config>
+</rpc>