From 03ac144dcc9a63b7c45e59b8fe849a9762d2de1a Mon Sep 17 00:00:00 2001 From: Tomas Olvecky Date: Wed, 27 Nov 2013 18:04:40 +0100 Subject: [PATCH] Refactor persister: require only capabilities referenced by the xml snapshot. Also repair logback bug preventing it from taking snapshot configuration. Change-Id: I48c0383441bfaee3c192159f5158f833e7e1d938 Signed-off-by: Tomas Olvecky --- .../config/persist/api/Persister.java | 11 +- .../storage/file/FileStorageAdapter.java | 13 +- .../storage/file/FileStorageAdapterTest.java | 19 ++- .../logback/config/ContextSetterImpl.java | 16 +-- .../yang/logback/config/LogbackModule.java | 11 +- .../netconf/config-persister-impl/pom.xml | 5 + ...pabilityStrippingConfigSnapshotHolder.java | 119 ++++++++++++++++++ .../ConfigPersisterNotificationHandler.java | 32 +++-- .../impl/osgi/ConfigPersisterActivator.java | 13 +- ...lityStrippingConfigSnapshotHolderTest.java | 62 +++++++++ .../src/test/resources/capabilities-all.txt | 20 +++ .../test/resources/capabilities-stripped.txt | 5 + .../src/test/resources/logback-test.xml | 13 ++ .../src/test/resources/snapshot.xml | 103 +++++++++++++++ .../controller/netconf/it/NetconfITTest.java | 5 +- 15 files changed, 397 insertions(+), 50 deletions(-) create mode 100644 opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/CapabilityStrippingConfigSnapshotHolder.java create mode 100644 opendaylight/netconf/config-persister-impl/src/test/java/org/opendaylight/controller/netconf/persist/impl/CapabilityStrippingConfigSnapshotHolderTest.java create mode 100644 opendaylight/netconf/config-persister-impl/src/test/resources/capabilities-all.txt create mode 100644 opendaylight/netconf/config-persister-impl/src/test/resources/capabilities-stripped.txt create mode 100644 opendaylight/netconf/config-persister-impl/src/test/resources/logback-test.xml create mode 100644 opendaylight/netconf/config-persister-impl/src/test/resources/snapshot.xml diff --git a/opendaylight/config/config-persister-api/src/main/java/org/opendaylight/controller/config/persist/api/Persister.java b/opendaylight/config/config-persister-api/src/main/java/org/opendaylight/controller/config/persist/api/Persister.java index f9c9301b88..78ce2b9718 100644 --- a/opendaylight/config/config-persister-api/src/main/java/org/opendaylight/controller/config/persist/api/Persister.java +++ b/opendaylight/config/config-persister-api/src/main/java/org/opendaylight/controller/config/persist/api/Persister.java @@ -12,7 +12,7 @@ import com.google.common.base.Optional; import java.io.Closeable; import java.io.IOException; -import java.util.Set; +import java.util.SortedSet; /** * Base interface for persister implementation. @@ -25,8 +25,15 @@ public interface Persister extends Closeable { public static interface ConfigSnapshotHolder { + /** + * Get part of get-config document that contains just + */ String getConfigSnapshot(); - Set getCapabilities(); + + /** + * Get only required capabilities referenced by the snapshot. + */ + SortedSet getCapabilities(); } } diff --git a/opendaylight/config/config-persister-file-adapter/src/main/java/org/opendaylight/controller/config/persist/storage/file/FileStorageAdapter.java b/opendaylight/config/config-persister-file-adapter/src/main/java/org/opendaylight/controller/config/persist/storage/file/FileStorageAdapter.java index 5098c6f352..d3508939d7 100644 --- a/opendaylight/config/config-persister-file-adapter/src/main/java/org/opendaylight/controller/config/persist/storage/file/FileStorageAdapter.java +++ b/opendaylight/config/config-persister-file-adapter/src/main/java/org/opendaylight/controller/config/persist/storage/file/FileStorageAdapter.java @@ -12,7 +12,6 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Charsets; import com.google.common.base.Optional; import com.google.common.base.Preconditions; -import com.google.common.collect.Sets; import com.google.common.io.Files; import org.apache.commons.lang3.StringUtils; import org.opendaylight.controller.config.persist.api.storage.StorageAdapter; @@ -25,6 +24,8 @@ import java.io.File; import java.io.IOException; import java.nio.charset.Charset; import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; /** * StorageAdapter that stores configuration in a plan file. @@ -187,7 +188,7 @@ public class FileStorageAdapter implements StorageAdapter { private boolean inLastConfig, inLastSnapshot; private final StringBuffer snapshotBuffer = new StringBuffer(); - private final Set caps = Sets.newHashSet(); + private final SortedSet caps = new TreeSet<>(); @Override public String getResult() { @@ -231,7 +232,7 @@ public class FileStorageAdapter implements StorageAdapter { return Optional.of(xmlContent); } - Set getCapabilities() throws IOException, SAXException, ParserConfigurationException { + SortedSet getCapabilities() throws IOException, SAXException, ParserConfigurationException { return caps; } @@ -250,9 +251,9 @@ public class FileStorageAdapter implements StorageAdapter { private class PersistedConfigImpl implements ConfigSnapshotHolder { private final String snapshot; - private final Set caps; + private final SortedSet caps; - public PersistedConfigImpl(Optional configSnapshot, Set capabilities) { + public PersistedConfigImpl(Optional configSnapshot, SortedSet capabilities) { this.snapshot = configSnapshot.get(); this.caps = capabilities; } @@ -263,7 +264,7 @@ public class FileStorageAdapter implements StorageAdapter { } @Override - public Set getCapabilities() { + public SortedSet getCapabilities() { return caps; } } diff --git a/opendaylight/config/config-persister-file-adapter/src/test/java/org/opendaylight/controller/config/persist/storage/file/FileStorageAdapterTest.java b/opendaylight/config/config-persister-file-adapter/src/test/java/org/opendaylight/controller/config/persist/storage/file/FileStorageAdapterTest.java index c7d37dcbd8..886298a881 100644 --- a/opendaylight/config/config-persister-file-adapter/src/test/java/org/opendaylight/controller/config/persist/storage/file/FileStorageAdapterTest.java +++ b/opendaylight/config/config-persister-file-adapter/src/test/java/org/opendaylight/controller/config/persist/storage/file/FileStorageAdapterTest.java @@ -12,7 +12,6 @@ import com.google.common.base.Charsets; import com.google.common.base.Optional; import com.google.common.base.Predicate; import com.google.common.collect.Collections2; -import com.google.common.collect.Sets; import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; @@ -21,8 +20,8 @@ import org.opendaylight.controller.config.persist.api.Persister; import java.io.File; import java.nio.file.Files; import java.util.Collection; -import java.util.Collections; -import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; @@ -56,7 +55,7 @@ public class FileStorageAdapterTest { } @Override - public Set getCapabilities() { + public SortedSet getCapabilities() { return createCaps(); } }; @@ -83,8 +82,8 @@ public class FileStorageAdapterTest { assertEquals(createCaps(), lastConf.get().getCapabilities()); } - private Set createCaps() { - Set caps = Sets.newHashSet(); + private SortedSet createCaps() { + SortedSet caps = new TreeSet<>(); caps.add("cap1"); caps.add("cap2"); @@ -104,7 +103,7 @@ public class FileStorageAdapterTest { } @Override - public Set getCapabilities() { + public SortedSet getCapabilities() { return createCaps(); } }; @@ -142,7 +141,7 @@ public class FileStorageAdapterTest { } @Override - public Set getCapabilities() { + public SortedSet getCapabilities() { return createCaps(); } }; @@ -199,8 +198,8 @@ public class FileStorageAdapterTest { } @Override - public Set getCapabilities() { - return Collections. emptySet(); + public SortedSet getCapabilities() { + return new TreeSet<>(); } } ); } diff --git a/opendaylight/config/logback-config/src/main/java/org/opendaylight/controller/config/yang/logback/config/ContextSetterImpl.java b/opendaylight/config/logback-config/src/main/java/org/opendaylight/controller/config/yang/logback/config/ContextSetterImpl.java index 205f123b1d..02fba141b3 100644 --- a/opendaylight/config/logback-config/src/main/java/org/opendaylight/controller/config/yang/logback/config/ContextSetterImpl.java +++ b/opendaylight/config/logback-config/src/main/java/org/opendaylight/controller/config/yang/logback/config/ContextSetterImpl.java @@ -101,13 +101,15 @@ public class ContextSetterImpl implements ContextSetter, Closeable { private void addNewAppenders(Map> appendersMap, LoggerTO logger, ch.qos.logback.classic.Logger logbackLogger, Optional>> appendersBefore) { - for (String appenderName : logger.getAppenders()) { - if (appendersMap.containsKey(appenderName)) { - logbackLogger.addAppender(appendersMap.get(appenderName)); - classLogger.trace("Logger {}: Adding new appender: {}", logger.getLoggerName(), appenderName); - } else { - throw new IllegalStateException("No appender " + appenderName - + " found. This error should have been discovered by validation"); + if (logger.getAppenders() != null) { + for (String appenderName : logger.getAppenders()) { + if (appendersMap.containsKey(appenderName)) { + logbackLogger.addAppender(appendersMap.get(appenderName)); + classLogger.trace("Logger {}: Adding new appender: {}", logger.getLoggerName(), appenderName); + } else { + throw new IllegalStateException("No appender " + appenderName + + " found. This error should have been discovered by validation"); + } } } } diff --git a/opendaylight/config/logback-config/src/main/java/org/opendaylight/controller/config/yang/logback/config/LogbackModule.java b/opendaylight/config/logback-config/src/main/java/org/opendaylight/controller/config/yang/logback/config/LogbackModule.java index 9cbcd47b20..d75bf6367a 100644 --- a/opendaylight/config/logback-config/src/main/java/org/opendaylight/controller/config/yang/logback/config/LogbackModule.java +++ b/opendaylight/config/logback-config/src/main/java/org/opendaylight/controller/config/yang/logback/config/LogbackModule.java @@ -54,11 +54,12 @@ public final class LogbackModule extends org.opendaylight.controller.config.yang "LoggerName needs to be set", loggersJmxAttribute); JmxAttributeValidationException.checkCondition(!loggerToValidate.getLevel().isEmpty(), "Level needs to be set", loggersJmxAttribute); - - for (String appenderName : loggerToValidate.getAppenders()) { - JmxAttributeValidationException.checkCondition(appenderNames.contains(appenderName), "Appender " - + appenderName + " referenced by logger " + loggerToValidate.getLoggerName() - + " not present in configuration, present appenders: " + appenderNames, loggersJmxAttribute); + if (loggerToValidate.getAppenders() != null) { + for (String appenderName : loggerToValidate.getAppenders()) { + JmxAttributeValidationException.checkCondition(appenderNames.contains(appenderName), "Appender " + + appenderName + " referenced by logger " + loggerToValidate.getLoggerName() + + " not present in configuration, present appenders: " + appenderNames, loggersJmxAttribute); + } } } diff --git a/opendaylight/netconf/config-persister-impl/pom.xml b/opendaylight/netconf/config-persister-impl/pom.xml index 21ecd31339..e9cf2b70bd 100644 --- a/opendaylight/netconf/config-persister-impl/pom.xml +++ b/opendaylight/netconf/config-persister-impl/pom.xml @@ -53,6 +53,11 @@ ${bgpcep.version} test + + commons-io + commons-io + test + diff --git a/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/CapabilityStrippingConfigSnapshotHolder.java b/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/CapabilityStrippingConfigSnapshotHolder.java new file mode 100644 index 0000000000..0440cbd257 --- /dev/null +++ b/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/CapabilityStrippingConfigSnapshotHolder.java @@ -0,0 +1,119 @@ +/** + * @author Tomas Olvecky + * + * 11 2013 + * + * Copyright (c) 2013 by Cisco Systems, Inc. + * All rights reserved. + */ +package org.opendaylight.controller.netconf.persist.impl; + +import com.google.common.annotations.VisibleForTesting; +import org.opendaylight.controller.config.persist.api.Persister.ConfigSnapshotHolder; +import org.opendaylight.controller.netconf.util.xml.XmlElement; +import org.opendaylight.controller.netconf.util.xml.XmlUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Attr; +import org.w3c.dom.Element; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map.Entry; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.regex.Pattern; + +import static com.google.common.base.Preconditions.checkState; + +public class CapabilityStrippingConfigSnapshotHolder implements ConfigSnapshotHolder { + private static final Logger logger = LoggerFactory.getLogger(CapabilityStrippingConfigSnapshotHolder.class); + + private final String configSnapshot; + private final StripCapabilitiesResult stripCapabilitiesResult; + + public CapabilityStrippingConfigSnapshotHolder(Element snapshot, Set capabilities, Pattern ignoredMissingCapabilityRegex) { + final XmlElement configElement = XmlElement.fromDomElement(snapshot); + configSnapshot = XmlUtil.toString(configElement.getDomElement()); + stripCapabilitiesResult = stripCapabilities(configElement, capabilities, ignoredMissingCapabilityRegex); + } + + private static class StripCapabilitiesResult { + private final SortedSet requiredCapabilities, missingNamespaces; + + private StripCapabilitiesResult(SortedSet requiredCapabilities, SortedSet missingNamespaces) { + this.requiredCapabilities = Collections.unmodifiableSortedSet(requiredCapabilities); + this.missingNamespaces = Collections.unmodifiableSortedSet(missingNamespaces); + } + } + + + @VisibleForTesting + static StripCapabilitiesResult stripCapabilities(XmlElement configElement, Set allCapabilitiesFromHello, + Pattern ignoredMissingCapabilityRegex) { + // collect all namespaces + Set foundNamespacesInXML = getNamespaces(configElement); + logger.trace("All capabilities {}\nFound namespaces in XML {}", allCapabilitiesFromHello, foundNamespacesInXML); + // required are referenced both in xml and hello + SortedSet requiredCapabilities = new TreeSet<>(); + // can be removed + Set obsoleteCapabilities = new HashSet<>(); + // are in xml but not in hello + SortedSet missingNamespaces = new TreeSet<>(foundNamespacesInXML); + for (String capability : allCapabilitiesFromHello) { + String namespace = capability.replaceAll("\\?.*",""); + if (foundNamespacesInXML.contains(namespace)) { + requiredCapabilities.add(capability); + checkState(missingNamespaces.remove(namespace)); + } else { + obsoleteCapabilities.add(capability); + } + } + + logger.trace("Required capabilities {}, \nObsolete capabilities {}", + requiredCapabilities, obsoleteCapabilities); + + for(Iterator iterator = missingNamespaces.iterator();iterator.hasNext(); ){ + String capability = iterator.next(); + if (ignoredMissingCapabilityRegex.matcher(capability).matches()){ + logger.trace("Ignoring missing capability {}", capability); + iterator.remove(); + } + } + if (missingNamespaces.size() > 0) { + logger.warn("Some capabilities are missing: {}", missingNamespaces); + } + return new StripCapabilitiesResult(requiredCapabilities, missingNamespaces); + } + + static Set getNamespaces(XmlElement element){ + Set result = new HashSet<>(); + for (Entry attribute : element.getAttributes().entrySet()) { + if (attribute.getKey().startsWith("xmlns")){ + result.add(attribute.getValue().getValue()); + } + } + //element.getAttributes() + for(XmlElement child: element.getChildElements()) { + result.addAll(getNamespaces(child)); + } + return result; + } + + @Override + public SortedSet getCapabilities() { + return stripCapabilitiesResult.requiredCapabilities; + } + + @VisibleForTesting + Set getMissingNamespaces(){ + return stripCapabilitiesResult.missingNamespaces; + } + + @Override + public String getConfigSnapshot() { + return configSnapshot; + } +} diff --git a/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPersisterNotificationHandler.java b/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPersisterNotificationHandler.java index 747965c064..748303160d 100644 --- a/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPersisterNotificationHandler.java +++ b/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPersisterNotificationHandler.java @@ -43,6 +43,7 @@ import java.net.InetSocketAddress; import java.util.Collections; import java.util.HashSet; import java.util.Set; +import java.util.regex.Pattern; /** * Responsible for listening for notifications from netconf containing latest @@ -53,6 +54,8 @@ import java.util.Set; public class ConfigPersisterNotificationHandler implements NotificationListener, Closeable { private static final Logger logger = LoggerFactory.getLogger(ConfigPersisterNotificationHandler.class); + private static final int NETCONF_SEND_ATTEMPT_MS_DELAY = 1000; + private static final int NETCONF_SEND_ATTEMPTS = 20; private final InetSocketAddress address; private final EventLoopGroup nettyThreadgroup; @@ -66,22 +69,25 @@ public class ConfigPersisterNotificationHandler implements NotificationListener, private final ObjectName on = DefaultCommitOperationMXBean.objectName; - public static final long DEFAULT_TIMEOUT = 40000L; + public static final long DEFAULT_TIMEOUT = 120000L;// 120 seconds until netconf must be stable private final long timeout; + private final Pattern ignoredMissingCapabilityRegex; public ConfigPersisterNotificationHandler(Persister persister, InetSocketAddress address, - MBeanServerConnection mbeanServer) { - this(persister, address, mbeanServer, DEFAULT_TIMEOUT); + MBeanServerConnection mbeanServer, Pattern ignoredMissingCapabilityRegex) { + this(persister, address, mbeanServer, DEFAULT_TIMEOUT, ignoredMissingCapabilityRegex); + } public ConfigPersisterNotificationHandler(Persister persister, InetSocketAddress address, - MBeanServerConnection mbeanServer, long timeout) { + MBeanServerConnection mbeanServer, long timeout, Pattern ignoredMissingCapabilityRegex) { this.persister = persister; this.address = address; this.mbeanServer = mbeanServer; this.timeout = timeout; this.nettyThreadgroup = new NioEventLoopGroup(); + this.ignoredMissingCapabilityRegex = ignoredMissingCapabilityRegex; } public void init() throws InterruptedException { @@ -220,18 +226,8 @@ public class ConfigPersisterNotificationHandler implements NotificationListener, private void handleAfterCommitNotification(final CommitJMXNotification notification) { try { - final XmlElement configElement = XmlElement.fromDomElement(notification.getConfigSnapshot()); - persister.persistConfig(new Persister.ConfigSnapshotHolder() { - @Override - public String getConfigSnapshot() { - return XmlUtil.toString(configElement.getDomElement()); - } - - @Override - public Set getCapabilities() { - return notification.getCapabilities(); - } - }); + persister.persistConfig(new CapabilityStrippingConfigSnapshotHolder(notification.getConfigSnapshot(), + notification.getCapabilities(), ignoredMissingCapabilityRegex)); logger.debug("Configuration persisted successfully"); } catch (IOException e) { throw new RuntimeException("Unable to persist configuration snapshot", e); @@ -256,7 +252,7 @@ public class ConfigPersisterNotificationHandler implements NotificationListener, NetconfMessage message = createEditConfigMessage(xmlToBePersisted, "/netconfOp/editConfig.xml"); // sending message to netconf - NetconfMessage responseMessage = netconfClient.sendMessage(message); + NetconfMessage responseMessage = netconfClient.sendMessage(message, NETCONF_SEND_ATTEMPTS, NETCONF_SEND_ATTEMPT_MS_DELAY); XmlElement element = XmlElement.fromDomDocument(responseMessage.getDocument()); Preconditions.checkState(element.getName().equals(XmlNetconfConstants.RPC_REPLY_KEY)); @@ -265,7 +261,7 @@ public class ConfigPersisterNotificationHandler implements NotificationListener, checkIsOk(element, responseMessage); response.append(XmlUtil.toString(responseMessage.getDocument())); response.append("}"); - responseMessage = netconfClient.sendMessage(getNetconfMessageFromResource("/netconfOp/commit.xml")); + responseMessage = netconfClient.sendMessage(getNetconfMessageFromResource("/netconfOp/commit.xml"), NETCONF_SEND_ATTEMPTS, NETCONF_SEND_ATTEMPT_MS_DELAY); element = XmlElement.fromDomDocument(responseMessage.getDocument()); Preconditions.checkState(element.getName().equals(XmlNetconfConstants.RPC_REPLY_KEY)); diff --git a/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/osgi/ConfigPersisterActivator.java b/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/osgi/ConfigPersisterActivator.java index 241830ddc3..036cb757ae 100644 --- a/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/osgi/ConfigPersisterActivator.java +++ b/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/osgi/ConfigPersisterActivator.java @@ -20,12 +20,14 @@ import org.slf4j.LoggerFactory; import javax.management.MBeanServer; import java.lang.management.ManagementFactory; import java.net.InetSocketAddress; +import java.util.regex.Pattern; public class ConfigPersisterActivator implements BundleActivator { private static final Logger logger = LoggerFactory.getLogger(ConfigPersisterActivator.class); private final static MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer(); + private static final String IGNORED_MISSING_CAPABILITY_REGEX_SUFFIX = "ignoredMissingCapabilityRegex"; private ConfigPersisterNotificationHandler configPersisterNotificationHandler; @@ -33,6 +35,7 @@ public class ConfigPersisterActivator implements BundleActivator { private static final String NETCONF_CONFIG_PERSISTER_PREFIX = "netconf.config.persister."; public static final String STORAGE_ADAPTER_CLASS_PROP_SUFFIX = "storageAdapterClass"; + public static final String DEFAULT_IGNORED_REGEX = "^urn:ietf:params:xml:ns:netconf:base:1.0"; @Override public void start(final BundleContext context) throws Exception { @@ -50,12 +53,20 @@ public class ConfigPersisterActivator implements BundleActivator { } }; + String regexProperty = propertiesProvider.getProperty(IGNORED_MISSING_CAPABILITY_REGEX_SUFFIX); + String regex; + if (regexProperty != null) { + regex = regexProperty; + } else { + regex = DEFAULT_IGNORED_REGEX; + } + Pattern ignoredMissingCapabilityRegex = Pattern.compile(regex); PersisterImpl persister = PersisterImpl.createFromProperties(propertiesProvider); InetSocketAddress address = NetconfConfigUtil.extractTCPNetconfAddress(context, "Netconf is not configured, persister is not operational"); configPersisterNotificationHandler = new ConfigPersisterNotificationHandler(persister, address, - platformMBeanServer); + platformMBeanServer, ignoredMissingCapabilityRegex); // offload initialization to another thread in order to stop blocking activator Runnable initializationRunnable = new Runnable() { diff --git a/opendaylight/netconf/config-persister-impl/src/test/java/org/opendaylight/controller/netconf/persist/impl/CapabilityStrippingConfigSnapshotHolderTest.java b/opendaylight/netconf/config-persister-impl/src/test/java/org/opendaylight/controller/netconf/persist/impl/CapabilityStrippingConfigSnapshotHolderTest.java new file mode 100644 index 0000000000..7e4e048988 --- /dev/null +++ b/opendaylight/netconf/config-persister-impl/src/test/java/org/opendaylight/controller/netconf/persist/impl/CapabilityStrippingConfigSnapshotHolderTest.java @@ -0,0 +1,62 @@ +/** + * @author Tomas Olvecky + * + * 11 2013 + * + * Copyright (c) 2013 by Cisco Systems, Inc. + * All rights reserved. + */ +package org.opendaylight.controller.netconf.persist.impl; + +import com.google.common.collect.Sets; +import org.apache.commons.io.IOUtils; +import org.junit.Test; +import org.opendaylight.controller.netconf.persist.impl.osgi.ConfigPersisterActivator; +import org.opendaylight.controller.netconf.util.xml.XmlUtil; +import org.w3c.dom.Element; + +import java.io.IOException; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import java.util.regex.Pattern; + +import static org.junit.Assert.assertEquals; + +public class CapabilityStrippingConfigSnapshotHolderTest { + + @Test + public void testCapabilityStripping() throws Exception { + Set allCapabilities = readLines("/capabilities-all.txt"); + Set expectedCapabilities = readLines("/capabilities-stripped.txt"); + String snapshotAsString = readToString("/snapshot.xml"); + Element element = XmlUtil.readXmlToElement(snapshotAsString); + { + CapabilityStrippingConfigSnapshotHolder tested = new CapabilityStrippingConfigSnapshotHolder( + element, allCapabilities, Pattern.compile( + ConfigPersisterActivator.DEFAULT_IGNORED_REGEX + )); + assertEquals(expectedCapabilities, tested.getCapabilities()); + assertEquals(Collections.emptySet(), tested.getMissingNamespaces()); + } + { + // test regex + CapabilityStrippingConfigSnapshotHolder tested = new CapabilityStrippingConfigSnapshotHolder( + element, allCapabilities, Pattern.compile( + "^bar" + )); + assertEquals(expectedCapabilities, tested.getCapabilities()); + assertEquals(Sets.newHashSet(ConfigPersisterActivator.DEFAULT_IGNORED_REGEX.substring(1)), + tested.getMissingNamespaces()); + } + } + + private Set readLines(String fileName) throws IOException { + return new HashSet<>(IOUtils.readLines(getClass().getResourceAsStream(fileName))); + } + + private String readToString(String fileName) throws IOException { + return IOUtils.toString(getClass().getResourceAsStream(fileName)); + } + +} diff --git a/opendaylight/netconf/config-persister-impl/src/test/resources/capabilities-all.txt b/opendaylight/netconf/config-persister-impl/src/test/resources/capabilities-all.txt new file mode 100644 index 0000000000..84c85b740c --- /dev/null +++ b/opendaylight/netconf/config-persister-impl/src/test/resources/capabilities-all.txt @@ -0,0 +1,20 @@ +urn:opendaylight:l2:types?module=opendaylight-l2-types&revision=2013-08-27 +urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28 +urn:opendaylight:params:xml:ns:yang:controller:threadpool?module=threadpool&revision=2013-04-09 +urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom?module=opendaylight-md-sal-dom&revision=2013-10-28 +urn:opendaylight:params:xml:ns:yang:controller:config?module=config&revision=2013-04-05 +urn:ietf:params:netconf:capability:candidate:1.0 +urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring?module=ietf-netconf-monitoring&revision=2010-10-04 +urn:opendaylight:params:xml:ns:yang:controller:netty:eventexecutor?module=netty-event-executor&revision=2013-11-12 +urn:ietf:params:xml:ns:yang:rpc-context?module=rpc-context&revision=2013-06-17 +urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl?module=opendaylight-sal-binding-broker-impl&revision=2013-10-28 +urn:ietf:params:xml:ns:yang:ietf-inet-types?module=ietf-inet-types&revision=2010-09-24 +urn:ietf:params:netconf:capability:rollback-on-error:1.0 +urn:ietf:params:xml:ns:yang:ietf-yang-types?module=ietf-yang-types&revision=2010-09-24 +urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl?module=threadpool-impl&revision=2013-04-05 +urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&revision=2013-10-28 +urn:opendaylight:params:xml:ns:yang:controller:logback:config?module=config-logging&revision=2013-07-16 +urn:opendaylight:yang:extension:yang-ext?module=yang-ext&revision=2013-07-09 +urn:opendaylight:params:xml:ns:yang:iana?module=iana&revision=2013-08-16 +urn:opendaylight:params:xml:ns:yang:controller:md:sal:common?module=opendaylight-md-sal-common&revision=2013-10-28 +urn:opendaylight:params:xml:ns:yang:ieee754?module=ieee754&revision=2013-08-19 diff --git a/opendaylight/netconf/config-persister-impl/src/test/resources/capabilities-stripped.txt b/opendaylight/netconf/config-persister-impl/src/test/resources/capabilities-stripped.txt new file mode 100644 index 0000000000..4a0b7ffffd --- /dev/null +++ b/opendaylight/netconf/config-persister-impl/src/test/resources/capabilities-stripped.txt @@ -0,0 +1,5 @@ +urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28 +urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom?module=opendaylight-md-sal-dom&revision=2013-10-28 +urn:opendaylight:params:xml:ns:yang:controller:config?module=config&revision=2013-04-05 +urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl?module=opendaylight-sal-binding-broker-impl&revision=2013-10-28 +urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&revision=2013-10-28 diff --git a/opendaylight/netconf/config-persister-impl/src/test/resources/logback-test.xml b/opendaylight/netconf/config-persister-impl/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..a4ff3abe49 --- /dev/null +++ b/opendaylight/netconf/config-persister-impl/src/test/resources/logback-test.xml @@ -0,0 +1,13 @@ + + + + + %date{"yyyy-MM-dd HH:mm:ss.SSS z"} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + diff --git a/opendaylight/netconf/config-persister-impl/src/test/resources/snapshot.xml b/opendaylight/netconf/config-persister-impl/src/test/resources/snapshot.xml new file mode 100644 index 0000000000..a6a57d704a --- /dev/null +++ b/opendaylight/netconf/config-persister-impl/src/test/resources/snapshot.xml @@ -0,0 +1,103 @@ + + + + prefix:schema-service-singleton + yang-schema-service + + + prefix:hash-map-data-store + hash-map-data-store + + + prefix:dom-broker-impl + dom-broker + + dom:dom-data-store + ref_hash-map-data-store + + + + prefix:binding-broker-impl + binding-broker-impl + + binding:binding-notification-service + ref_binding-notification-broker + + + binding:binding-data-broker + ref_binding-data-broker + + + + prefix:runtime-generated-mapping + runtime-mapping-singleton + + + prefix:binding-notification-broker + binding-notification-broker + + + prefix:binding-data-broker + binding-data-broker + + dom:dom-broker-osgi-registry + ref_dom-broker + + + binding:binding-dom-mapping-service + ref_runtime-mapping-singleton + + + + + + dom:schema-service + + ref_yang-schema-service + /config/modules/module[name='schema-service-singleton']/instance[name='yang-schema-service'] + + + + binding:binding-notification-service + + ref_binding-notification-broker + /config/modules/module[name='binding-notification-broker']/instance[name='binding-notification-broker'] + + + + dom:dom-data-store + + ref_hash-map-data-store + /config/modules/module[name='hash-map-data-store']/instance[name='hash-map-data-store'] + + + + binding:binding-broker-osgi-registry + + ref_binding-broker-impl + /config/modules/module[name='binding-broker-impl']/instance[name='binding-broker-impl'] + + + + binding-impl:binding-dom-mapping-service + + ref_runtime-mapping-singleton + /config/modules/module[name='runtime-generated-mapping']/instance[name='runtime-mapping-singleton'] + + + + dom:dom-broker-osgi-registry + + ref_dom-broker + /config/modules/module[name='dom-broker-impl']/instance[name='dom-broker'] + + + + binding:binding-data-broker + + ref_binding-data-broker + /config/modules/module[name='binding-data-broker']/instance[name='binding-data-broker'] + + + + 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 d08bb957e1..d35ac28d8a 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 @@ -27,6 +27,7 @@ import java.util.Collection; import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; +import java.util.regex.Pattern; import javax.management.ObjectName; import javax.net.ssl.SSLContext; import javax.xml.parsers.ParserConfigurationException; @@ -65,6 +66,7 @@ import org.opendaylight.controller.netconf.impl.mapping.ExiDecoderHandler; import org.opendaylight.controller.netconf.impl.mapping.ExiEncoderHandler; import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl; import org.opendaylight.controller.netconf.persist.impl.ConfigPersisterNotificationHandler; +import org.opendaylight.controller.netconf.persist.impl.osgi.ConfigPersisterActivator; import org.opendaylight.controller.netconf.ssh.NetconfSSHServer; import org.opendaylight.controller.netconf.util.test.XmlFileLoader; import org.opendaylight.controller.netconf.util.xml.ExiParameters; @@ -215,7 +217,8 @@ public class NetconfITTest extends AbstractConfigTest { Persister persister = mock(Persister.class); doReturn("mockPersister").when(persister).toString(); doReturn(Optional.absent()).when(persister).loadLastConfig(); - ConfigPersisterNotificationHandler h = new ConfigPersisterNotificationHandler(persister, tcpAddress, ManagementFactory.getPlatformMBeanServer()); + ConfigPersisterNotificationHandler h = + new ConfigPersisterNotificationHandler(persister, tcpAddress, ManagementFactory.getPlatformMBeanServer(), Pattern.compile(ConfigPersisterActivator.DEFAULT_IGNORED_REGEX)); h.init(); } -- 2.36.6