From: Ed Warnicke Date: Sun, 8 Dec 2013 14:23:01 +0000 (+0000) Subject: Merge "Fixed add/delete/modify RPC for group/flow/remove reach the test provider" X-Git-Tag: jenkins-controller-bulk-release-prepare-only-2-1~234 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=eff404d4edd10fcde6d85c5821c80263339d9a4a;hp=d904bd30445bd0f6d670afd5f5b6f8225410256a Merge "Fixed add/delete/modify RPC for group/flow/remove reach the test provider" --- diff --git a/opendaylight/config/config-persister-api/src/main/java/org/opendaylight/controller/config/persist/api/ConfigSnapshotHolder.java b/opendaylight/config/config-persister-api/src/main/java/org/opendaylight/controller/config/persist/api/ConfigSnapshotHolder.java index 654326a898..37d29d746e 100644 --- a/opendaylight/config/config-persister-api/src/main/java/org/opendaylight/controller/config/persist/api/ConfigSnapshotHolder.java +++ b/opendaylight/config/config-persister-api/src/main/java/org/opendaylight/controller/config/persist/api/ConfigSnapshotHolder.java @@ -4,14 +4,15 @@ import java.util.SortedSet; public interface ConfigSnapshotHolder { - /** - * Get part of get-config document that contains just - */ - String getConfigSnapshot(); + /** + * Get part of get-config document that contains just + */ + String getConfigSnapshot(); - /** - * Get only required capabilities referenced by the snapshot. - */ - SortedSet getCapabilities(); - } + /** + * Get only required capabilities referenced by the snapshot. + */ + SortedSet getCapabilities(); + +} diff --git a/opendaylight/config/config-persister-api/src/main/java/org/opendaylight/controller/config/persist/api/ConfigSnapshotHolderImpl.java b/opendaylight/config/config-persister-api/src/main/java/org/opendaylight/controller/config/persist/api/ConfigSnapshotHolderImpl.java new file mode 100644 index 0000000000..a0586df840 --- /dev/null +++ b/opendaylight/config/config-persister-api/src/main/java/org/opendaylight/controller/config/persist/api/ConfigSnapshotHolderImpl.java @@ -0,0 +1,39 @@ +package org.opendaylight.controller.config.persist.api; + +import java.util.SortedSet; + +public class ConfigSnapshotHolderImpl implements ConfigSnapshotHolder { + + private final String snapshot; + private final SortedSet caps; + private final String fileName; + + public ConfigSnapshotHolderImpl(String configSnapshot, SortedSet capabilities, String fileName) { + this.snapshot = configSnapshot; + this.caps = capabilities; + this.fileName = fileName; + } + + @Override + public String getConfigSnapshot() { + return snapshot; + } + + @Override + public SortedSet getCapabilities() { + return caps; + } + + public String getFileName() { + return fileName; + } + + @Override + public String toString() { + return "ConfigSnapshotHolderImpl{" + + "snapshot='" + snapshot + '\'' + + ", caps=" + caps + + ", fileName='" + fileName + '\'' + + '}'; + } +} 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 1448e553e3..5509c99437 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 @@ -8,9 +8,8 @@ package org.opendaylight.controller.config.persist.api; -import com.google.common.base.Optional; - import java.io.IOException; +import java.util.List; /** * Base interface for persister implementation. @@ -19,7 +18,7 @@ public interface Persister extends AutoCloseable { void persistConfig(ConfigSnapshotHolder configSnapshotHolder) throws IOException; - Optional loadLastConfig() throws IOException; + List loadLastConfigs() throws IOException; @Override void close(); diff --git a/opendaylight/config/config-persister-directory-adapter/src/main/java/org/opendaylight/controller/config/persist/storage/directory/DirectoryPersister.java b/opendaylight/config/config-persister-directory-adapter/src/main/java/org/opendaylight/controller/config/persist/storage/directory/DirectoryPersister.java index 25628b6041..39595edb0b 100644 --- a/opendaylight/config/config-persister-directory-adapter/src/main/java/org/opendaylight/controller/config/persist/storage/directory/DirectoryPersister.java +++ b/opendaylight/config/config-persister-directory-adapter/src/main/java/org/opendaylight/controller/config/persist/storage/directory/DirectoryPersister.java @@ -8,10 +8,10 @@ package org.opendaylight.controller.config.persist.storage.directory; import com.google.common.base.Charsets; -import com.google.common.base.Optional; import com.google.common.io.Files; import org.apache.commons.io.IOUtils; import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder; +import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolderImpl; import org.opendaylight.controller.config.persist.api.Persister; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -64,30 +64,25 @@ public class DirectoryPersister implements Persister { } @Override - public Optional loadLastConfig() throws IOException { + public List loadLastConfigs() throws IOException { File[] filesArray = storage.listFiles(); - if (filesArray.length == 0) { - return Optional.absent(); + if (filesArray == null || filesArray.length == 0) { + return Collections.emptyList(); } List sortedFiles = new ArrayList<>(Arrays.asList(filesArray)); Collections.sort(sortedFiles); // combine all found files + logger.debug("Reading files in following order: {}", sortedFiles); - SortedSet combinedCapabilities = new TreeSet<>(); - StringBuilder modulesBuilder = new StringBuilder(), servicesBuilder = new StringBuilder(); + List result = new ArrayList<>(); for (File file : sortedFiles) { logger.trace("Adding file '{}' to combined result", file); final MyLineProcessor lineProcessor = new MyLineProcessor(file.getAbsolutePath()); Files.readLines(file, ENCODING, lineProcessor); - - modulesBuilder.append(lineProcessor.getModules()); - servicesBuilder.append(lineProcessor.getServices()); - combinedCapabilities.addAll(lineProcessor.getCapabilities()); + result.add(lineProcessor.getConfigSnapshotHolder(header, middle, footer)); } - String combinedSnapshot = header + modulesBuilder.toString() + middle + servicesBuilder.toString() + footer; - ConfigSnapshotHolder result = new ConfigSnapshotHolderImpl(combinedSnapshot, combinedCapabilities); - return Optional.of(result); + return result; } @@ -165,25 +160,11 @@ class MyLineProcessor implements com.google.common.io.LineProcessor { return caps; } -} - -class ConfigSnapshotHolderImpl implements ConfigSnapshotHolder { - - private final String snapshot; - private final SortedSet caps; - - public ConfigSnapshotHolderImpl(String configSnapshot, SortedSet capabilities) { - this.snapshot = configSnapshot; - this.caps = capabilities; - } - - @Override - public String getConfigSnapshot() { - return snapshot; + ConfigSnapshotHolder getConfigSnapshotHolder(String header, String middle, String footer) { + String combinedSnapshot = header + getModules() + middle + getServices() + footer; + ConfigSnapshotHolder result = new ConfigSnapshotHolderImpl(combinedSnapshot, getCapabilities(), fileNameForReporting); + return result; } - @Override - public SortedSet getCapabilities() { - return caps; - } } + diff --git a/opendaylight/config/config-persister-directory-adapter/src/test/java/org/opendaylight/controller/config/persist/storage/directory/DirectoryStorageAdapterTest.java b/opendaylight/config/config-persister-directory-adapter/src/test/java/org/opendaylight/controller/config/persist/storage/directory/DirectoryStorageAdapterTest.java index 53ab4c210e..f17e414c49 100644 --- a/opendaylight/config/config-persister-directory-adapter/src/test/java/org/opendaylight/controller/config/persist/storage/directory/DirectoryStorageAdapterTest.java +++ b/opendaylight/config/config-persister-directory-adapter/src/test/java/org/opendaylight/controller/config/persist/storage/directory/DirectoryStorageAdapterTest.java @@ -8,14 +8,13 @@ package org.opendaylight.controller.config.persist.storage.directory; -import com.google.common.base.Optional; import org.apache.commons.io.IOUtils; -import org.junit.Before; import org.junit.Test; import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder; import java.io.File; -import java.io.IOException; +import java.util.Collections; +import java.util.List; import java.util.SortedSet; import java.util.TreeSet; @@ -25,21 +24,13 @@ import static org.junit.Assert.fail; public class DirectoryStorageAdapterTest { DirectoryPersister tested; - SortedSet expectedCapabilities; - String expectedSnapshot; - - @Before - public void setUp() throws Exception { - expectedCapabilities = new TreeSet<>(IOUtils.readLines(getClass().getResourceAsStream("/expectedCapabilities.txt"))); - expectedSnapshot = IOUtils.toString(getClass().getResourceAsStream("/expectedSnapshot.xml")); - } @Test public void testEmptyDirectory() throws Exception { File folder = new File("target/emptyFolder"); folder.mkdir(); tested = new DirectoryPersister((folder)); - assertEquals(Optional.absent(), tested.loadLastConfig()); + assertEquals(Collections.emptyList(), tested.loadLastConfigs()); try { tested.persistConfig(new ConfigSnapshotHolder() { @@ -70,22 +61,28 @@ public class DirectoryStorageAdapterTest { public void testOneFile() throws Exception { File folder = getFolder("oneFile"); tested = new DirectoryPersister((folder)); - assertExpected(); + List results = tested.loadLastConfigs(); + assertEquals(1, results.size()); + ConfigSnapshotHolder result = results.get(0); + assertSnapshot(result, "oneFileExpected"); } - private void assertExpected() throws IOException { - Optional maybeResult = tested.loadLastConfig(); - assertTrue(maybeResult.isPresent()); - ConfigSnapshotHolder result = maybeResult.get(); - assertEquals(expectedCapabilities, result.getCapabilities()); - assertEquals(expectedSnapshot, result.getConfigSnapshot()); - } @Test public void testTwoFiles() throws Exception { File folder = getFolder("twoFiles"); tested = new DirectoryPersister((folder)); - assertExpected(); + List results = tested.loadLastConfigs(); + assertEquals(2, results.size()); + assertSnapshot(results.get(0), "twoFilesExpected1"); + assertSnapshot(results.get(1), "twoFilesExpected2"); + } + + private void assertSnapshot(ConfigSnapshotHolder result, String directory) throws Exception { + SortedSet expectedCapabilities = new TreeSet<>(IOUtils.readLines(getClass().getResourceAsStream("/" + directory + "/expectedCapabilities.txt"))); + String expectedSnapshot = IOUtils.toString(getClass().getResourceAsStream("/" + directory + "/expectedSnapshot.xml")); + assertEquals(expectedCapabilities, result.getCapabilities()); + assertEquals(expectedSnapshot, result.getConfigSnapshot()); } } diff --git a/opendaylight/config/config-persister-directory-adapter/src/test/resources/expectedCapabilities.txt b/opendaylight/config/config-persister-directory-adapter/src/test/resources/oneFileExpected/expectedCapabilities.txt similarity index 100% rename from opendaylight/config/config-persister-directory-adapter/src/test/resources/expectedCapabilities.txt rename to opendaylight/config/config-persister-directory-adapter/src/test/resources/oneFileExpected/expectedCapabilities.txt diff --git a/opendaylight/config/config-persister-directory-adapter/src/test/resources/expectedSnapshot.xml b/opendaylight/config/config-persister-directory-adapter/src/test/resources/oneFileExpected/expectedSnapshot.xml similarity index 100% rename from opendaylight/config/config-persister-directory-adapter/src/test/resources/expectedSnapshot.xml rename to opendaylight/config/config-persister-directory-adapter/src/test/resources/oneFileExpected/expectedSnapshot.xml diff --git a/opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFilesExpected1/expectedCapabilities.txt b/opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFilesExpected1/expectedCapabilities.txt new file mode 100644 index 0000000000..ef35fddbce --- /dev/null +++ b/opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFilesExpected1/expectedCapabilities.txt @@ -0,0 +1 @@ +urn:opendaylight:l2:types?module=opendaylight-l2-types&revision=2013-08-27 diff --git a/opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFilesExpected1/expectedSnapshot.xml b/opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFilesExpected1/expectedSnapshot.xml new file mode 100644 index 0000000000..2b1d06ecc0 --- /dev/null +++ b/opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFilesExpected1/expectedSnapshot.xml @@ -0,0 +1,84 @@ + + + + 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 + + + + + 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'] + + + + diff --git a/opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFilesExpected2/expectedCapabilities.txt b/opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFilesExpected2/expectedCapabilities.txt new file mode 100644 index 0000000000..9924111627 --- /dev/null +++ b/opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFilesExpected2/expectedCapabilities.txt @@ -0,0 +1,19 @@ +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/config/config-persister-directory-adapter/src/test/resources/twoFilesExpected2/expectedSnapshot.xml b/opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFilesExpected2/expectedSnapshot.xml new file mode 100644 index 0000000000..887cb2c1d4 --- /dev/null +++ b/opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFilesExpected2/expectedSnapshot.xml @@ -0,0 +1,25 @@ + + + + prefix:binding-data-broker + binding-data-broker + + dom:dom-broker-osgi-registry + ref_dom-broker + + + binding:binding-dom-mapping-service + ref_runtime-mapping-singleton + + + + + + binding:binding-data-broker + + ref_binding-data-broker + /config/modules/module[name='binding-data-broker']/instance[name='binding-data-broker'] + + + + 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 66d0414d9a..3ec8713b47 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 @@ -15,17 +15,19 @@ import com.google.common.base.Preconditions; import com.google.common.io.Files; import org.apache.commons.lang3.StringUtils; import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder; +import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolderImpl; import org.opendaylight.controller.config.persist.api.Persister; import org.opendaylight.controller.config.persist.api.PropertiesProvider; import org.opendaylight.controller.config.persist.api.StorageAdapter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.xml.sax.SAXException; -import javax.xml.parsers.ParserConfigurationException; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; @@ -105,7 +107,7 @@ public class FileStorageAdapter implements StorageAdapter, Persister { } else { numberOfStoredBackups = Integer.MAX_VALUE; } - + logger.trace("Property {} set to {}", NUMBER_OF_BACKUPS, numberOfStoredBackups); return result; } @@ -164,27 +166,23 @@ public class FileStorageAdapter implements StorageAdapter, Persister { } @Override - public Optional loadLastConfig() throws IOException { + public List loadLastConfigs() throws IOException { Preconditions.checkNotNull(storage, "Storage file is null"); if (!storage.exists()) { - return Optional.absent(); + return Collections.emptyList(); } final LineProcessor lineProcessor = new LineProcessor(); - String result = Files.readLines(storage, ENCODING, lineProcessor); - - try { - if (lineProcessor.getConfigSnapshot().isPresent() == false) { - return Optional.absent(); - } else { - return Optional. of(new PersistedConfigImpl(lineProcessor.getConfigSnapshot(), - lineProcessor.getCapabilities())); - } + Files.readLines(storage, ENCODING, lineProcessor); - } catch (ParserConfigurationException | SAXException e) { - throw new IOException("Unable to load last config ", e); + if (lineProcessor.getConfigSnapshot().isPresent() == false) { + return Collections.emptyList(); + } else { + return Arrays.asList(new ConfigSnapshotHolderImpl(lineProcessor.getConfigSnapshot().get(), + lineProcessor.getCapabilities(), storage.getAbsolutePath())); } + } private static final class LineProcessor implements com.google.common.io.LineProcessor { @@ -227,15 +225,16 @@ public class FileStorageAdapter implements StorageAdapter, Persister { return true; } - Optional getConfigSnapshot() throws IOException, SAXException, ParserConfigurationException { + Optional getConfigSnapshot() { final String xmlContent = snapshotBuffer.toString(); - if (xmlContent == null || xmlContent.equals("")) { + if (xmlContent.equals("")) { return Optional.absent(); - } else + } else { return Optional.of(xmlContent); + } } - SortedSet getCapabilities() throws IOException, SAXException, ParserConfigurationException { + SortedSet getCapabilities() { return caps; } @@ -251,25 +250,4 @@ public class FileStorageAdapter implements StorageAdapter, Persister { return "FileStorageAdapter [storage=" + storage + "]"; } - private class PersistedConfigImpl implements ConfigSnapshotHolder { - - private final String snapshot; - private final SortedSet caps; - - public PersistedConfigImpl(Optional configSnapshot, SortedSet capabilities) { - this.snapshot = configSnapshot.get(); - this.caps = capabilities; - } - - @Override - public String getConfigSnapshot() { - return snapshot; - } - - @Override - 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 ed50184aa7..0236598f2b 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 @@ -9,7 +9,6 @@ package org.opendaylight.controller.config.persist.storage.file; 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 org.junit.Before; @@ -20,11 +19,11 @@ import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder; import java.io.File; import java.nio.file.Files; import java.util.Collection; +import java.util.List; import java.util.SortedSet; import java.util.TreeSet; import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertTrue; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; @@ -75,11 +74,12 @@ public class FileStorageAdapterTest { }); assertEquals(14, readLines.size()); - Optional lastConf = storage.loadLastConfig(); - assertTrue(lastConf.isPresent()); + List lastConf = storage.loadLastConfigs(); + assertEquals(1, lastConf.size()); + ConfigSnapshotHolder configSnapshotHolder = lastConf.get(0); assertEquals("2", - lastConf.get().getConfigSnapshot().replaceAll("\\s", "")); - assertEquals(createCaps(), lastConf.get().getCapabilities()); + configSnapshotHolder.getConfigSnapshot().replaceAll("\\s", "")); + assertEquals(createCaps(), configSnapshotHolder.getCapabilities()); } private SortedSet createCaps() { @@ -123,10 +123,11 @@ public class FileStorageAdapterTest { }); assertEquals(7, readLines.size()); - Optional lastConf = storage.loadLastConfig(); - assertTrue(lastConf.isPresent()); + List lastConf = storage.loadLastConfigs(); + assertEquals(1, lastConf.size()); + ConfigSnapshotHolder configSnapshotHolder = lastConf.get(0); assertEquals("2", - lastConf.get().getConfigSnapshot().replaceAll("\\s", "")); + configSnapshotHolder.getConfigSnapshot().replaceAll("\\s", "")); } @Test @@ -163,10 +164,11 @@ public class FileStorageAdapterTest { assertEquals(14, readLines.size()); - Optional lastConf = storage.loadLastConfig(); - assertTrue(lastConf.isPresent()); + List lastConf = storage.loadLastConfigs(); + assertEquals(1, lastConf.size()); + ConfigSnapshotHolder configSnapshotHolder = lastConf.get(0); assertEquals("3", - lastConf.get().getConfigSnapshot().replaceAll("\\s", "")); + configSnapshotHolder.getConfigSnapshot().replaceAll("\\s", "")); assertFalse(readLines.contains(holder.getConfigSnapshot())); } @@ -178,14 +180,14 @@ public class FileStorageAdapterTest { FileStorageAdapter storage = new FileStorageAdapter(); storage.setFileStorage(file); - Optional elementOptional = storage.loadLastConfig(); - assertThat(elementOptional.isPresent(), is(false)); + List elementOptional = storage.loadLastConfigs(); + assertThat(elementOptional.size(), is(0)); } @Test(expected = NullPointerException.class) public void testNoProperties() throws Exception { FileStorageAdapter storage = new FileStorageAdapter(); - storage.loadLastConfig(); + storage.loadLastConfigs(); } @Test(expected = NullPointerException.class) diff --git a/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/FtlFilePersister.java b/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/FtlFilePersister.java index b0b6f3d74c..f721895921 100644 --- a/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/FtlFilePersister.java +++ b/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/FtlFilePersister.java @@ -7,19 +7,9 @@ */ package org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.StringWriter; -import java.io.Writer; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.regex.Pattern; - +import com.google.common.annotations.VisibleForTesting; +import freemarker.template.Configuration; +import freemarker.template.Template; import org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator; import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.directives.AnnotationsDirective; import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.directives.ConstructorsDirective; @@ -33,11 +23,18 @@ import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.directives import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.annotations.VisibleForTesting; - -import freemarker.template.Configuration; -import freemarker.template.Template; -import freemarker.template.TemplateException; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.regex.Pattern; public class FtlFilePersister { private static final Logger logger = LoggerFactory @@ -56,7 +53,7 @@ public class FtlFilePersister { ftlFile.getFtlTempleteLocation()); try { template.process(ftlFile, writer); - } catch (TemplateException e) { + } catch (Throwable e) { throw new IllegalStateException( "Template error while generating " + ftlFile, e); } diff --git a/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/TemplateFactory.java b/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/TemplateFactory.java index 3a6ff18081..6da68018f2 100644 --- a/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/TemplateFactory.java +++ b/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/TemplateFactory.java @@ -21,13 +21,13 @@ import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry; import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry; import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry.Rpc; import org.opendaylight.controller.config.yangjmxgenerator.ServiceInterfaceEntry; -import org.opendaylight.controller.config.yangjmxgenerator.attribute.DependencyAttribute.Dependency; -import org.opendaylight.controller.config.yangjmxgenerator.attribute.DependencyAttribute; +import org.opendaylight.controller.config.yangjmxgenerator.attribute.AbstractDependencyAttribute; import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc; +import org.opendaylight.controller.config.yangjmxgenerator.attribute.Dependency; import org.opendaylight.controller.config.yangjmxgenerator.attribute.JavaAttribute; -import org.opendaylight.controller.config.yangjmxgenerator.attribute.TypedAttribute; -import org.opendaylight.controller.config.yangjmxgenerator.attribute.TOAttribute; import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListAttribute; +import org.opendaylight.controller.config.yangjmxgenerator.attribute.TOAttribute; +import org.opendaylight.controller.config.yangjmxgenerator.attribute.TypedAttribute; import org.opendaylight.controller.config.yangjmxgenerator.attribute.VoidAttribute; import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Annotation; import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Annotation.Parameter; @@ -39,6 +39,7 @@ import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Meth import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.ModuleField; import org.opendaylight.controller.config.yangjmxgenerator.plugin.util.FullyQualifiedNameHelper; import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil; +import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType; import org.opendaylight.yangtools.sal.binding.model.api.Type; import javax.management.openmbean.SimpleType; @@ -112,8 +113,8 @@ public class TemplateFactory { // convert attributes to getters for (AttributeIfc attributeIfc : entry.getAttributes()) { - String returnType = null; - returnType = getReturnType(entry, attributeIfc); + String returnType; + returnType = getReturnType(attributeIfc); String getterName = "get" + attributeIfc.getUpperCaseCammelCase(); MethodDeclaration getter = new MethodDeclaration(returnType, @@ -132,7 +133,7 @@ public class TemplateFactory { fields.add(field); } MethodDeclaration operation = new MethodDeclaration( - getReturnType(entry, rpc.getReturnType()), rpc.getName(), fields); + getReturnType(rpc.getReturnType()), rpc.getName(), fields); methods.add(operation); } @@ -150,28 +151,35 @@ public class TemplateFactory { return result; } - private static String getReturnType(RuntimeBeanEntry entry, AttributeIfc attributeIfc) { + // FIXME: put into Type.toString + static String serializeType(Type type) { + if (type instanceof ParameterizedType){ + ParameterizedType parameterizedType = (ParameterizedType) type; + StringBuffer sb = new StringBuffer(); + sb.append(parameterizedType.getRawType().getFullyQualifiedName()); + sb.append("<"); + boolean first = true; + for(Type parameter: parameterizedType.getActualTypeArguments()) { + if (first) { + first = false; + } else { + sb.append(","); + } + sb.append(serializeType(parameter)); + } + sb.append(">"); + return sb.toString(); + } else { + return type.getFullyQualifiedName(); + } + } + + + private static String getReturnType(AttributeIfc attributeIfc) { String returnType; if (attributeIfc instanceof TypedAttribute) { - returnType = ((TypedAttribute) attributeIfc).getType() - .getFullyQualifiedName(); - } else if (attributeIfc instanceof TOAttribute) { - String fullyQualifiedName = FullyQualifiedNameHelper - .getFullyQualifiedName(entry.getPackageName(), - attributeIfc.getUpperCaseCammelCase()); - - returnType = fullyQualifiedName; - } else if (attributeIfc instanceof ListAttribute) { - AttributeIfc innerAttr = ((ListAttribute) attributeIfc) - .getInnerAttribute(); - - String innerTpe = innerAttr instanceof TypedAttribute ? ((TypedAttribute) innerAttr) - .getType().getFullyQualifiedName() - : FullyQualifiedNameHelper.getFullyQualifiedName( - entry.getPackageName(), - attributeIfc.getUpperCaseCammelCase()); - - returnType = "java.util.List<" + innerTpe + ">"; + Type type = ((TypedAttribute) attributeIfc).getType(); + returnType = serializeType(type); } else if (attributeIfc == VoidAttribute.getInstance()) { return "void"; } else { @@ -292,8 +300,7 @@ public class TemplateFactory { public static GeneralInterfaceTemplate mXBeanInterfaceTemplateFromMbe( ModuleMXBeanEntry mbe) { MXBeanInterfaceAttributesProcessor attrProcessor = new MXBeanInterfaceAttributesProcessor(); - attrProcessor.processAttributes(mbe.getAttributes(), - mbe.getPackageName()); + attrProcessor.processAttributes(mbe.getAttributes()); GeneralInterfaceTemplate ifcTemplate = new GeneralInterfaceTemplate( getHeaderFromEntry(mbe), mbe.getPackageName(), mbe.getMXBeanInterfaceName(), Lists. newArrayList(), @@ -306,7 +313,7 @@ public class TemplateFactory { ModuleMXBeanEntry mbe) { Map retVal = Maps.newHashMap(); TOAttributesProcessor processor = new TOAttributesProcessor(); - processor.processAttributes(mbe.getAttributes(), mbe.getPackageName()); + processor.processAttributes(mbe.getAttributes()); for (org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.TemplateFactory.TOAttributesProcessor.TOInternal to : processor .getTOs()) { List constructors = Lists.newArrayList(); @@ -345,7 +352,7 @@ public class TemplateFactory { yangPropertiesToTypesMap.put(returnType.getAttributeYangName(), returnType); } - processor.processAttributes(yangPropertiesToTypesMap, rbe.getPackageName()); + processor.processAttributes(yangPropertiesToTypesMap); for (org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.TemplateFactory.TOAttributesProcessor.TOInternal to : processor .getTOs()) { List constructors = Lists.newArrayList(); @@ -372,36 +379,29 @@ public class TemplateFactory { private final List tos = Lists.newArrayList(); - void processAttributes(Map attributes, - String packageName) { + void processAttributes(Map attributes) { for (Entry attrEntry : attributes.entrySet()) { AttributeIfc attributeIfc = attrEntry.getValue(); if (attributeIfc instanceof TOAttribute) { - createTOInternal(packageName, attributeIfc); + createTOInternal((TOAttribute) attributeIfc); } if (attributeIfc instanceof ListAttribute) { AttributeIfc innerAttr = ((ListAttribute) attributeIfc) .getInnerAttribute(); if (innerAttr instanceof TOAttribute) { - createTOInternal(packageName, innerAttr); + createTOInternal((TOAttribute) innerAttr); } } } } - private void createTOInternal(String packageName, - AttributeIfc attributeIfc) { - String fullyQualifiedName = FullyQualifiedNameHelper - .getFullyQualifiedName(packageName, attributeIfc.getUpperCaseCammelCase()); + private void createTOInternal(TOAttribute toAttribute) { - String type = fullyQualifiedName; - String name = attributeIfc.getUpperCaseCammelCase(); - Map attrs = ((TOAttribute) attributeIfc) - .getCapitalizedPropertiesToTypesMap(); - // recursive processing - processAttributes(attrs, packageName); + Map attrs = toAttribute.getCapitalizedPropertiesToTypesMap(); + // recursive processing of TO's attributes + processAttributes(attrs); - tos.add(new TOInternal(type, name, attrs, packageName)); + tos.add(new TOInternal(toAttribute.getType(), attrs)); } List getTOs() { @@ -409,20 +409,22 @@ public class TemplateFactory { } private static class TOInternal { - private final String type, name; + private final String fullyQualifiedName, name; private List fields; private List methods; - public TOInternal(String type, String name, + public TOInternal(Type type, Map attrs) { + this(type.getFullyQualifiedName(), type.getName(), attrs, type.getPackageName()); + } + + public TOInternal(String fullyQualifiedName, String name, Map attrs, String packageName) { - super(); - this.type = type; + this.fullyQualifiedName = fullyQualifiedName; this.name = name; processAttrs(attrs, packageName); } - private void processAttrs(Map attrs, - String packageName) { + private void processAttrs(Map attrs, String packageName) { fields = Lists.newArrayList(); methods = Lists.newArrayList(); @@ -431,25 +433,14 @@ public class TemplateFactory { String varName = BindingGeneratorUtil .parseToValidParamName(attrEntry.getKey()); - String fullyQualifiedName = null; + String fullyQualifiedName; if (attrEntry.getValue() instanceof TypedAttribute) { - Type innerType = ((TypedAttribute) attrEntry.getValue()) - .getType(); - fullyQualifiedName = innerType.getFullyQualifiedName(); - } else if (attrEntry.getValue() instanceof ListAttribute) { - AttributeIfc innerAttr = ((ListAttribute) attrEntry - .getValue()).getInnerAttribute(); - - String innerTpe = innerAttr instanceof TypedAttribute ? ((TypedAttribute) innerAttr) - .getType().getFullyQualifiedName() - : FullyQualifiedNameHelper - .getFullyQualifiedName(packageName, attrEntry.getValue().getUpperCaseCammelCase()); - - fullyQualifiedName = "java.util.List<" + innerTpe + ">"; - } else + Type type = ((TypedAttribute) attrEntry.getValue()).getType(); + fullyQualifiedName = serializeType(type); + } else { fullyQualifiedName = FullyQualifiedNameHelper .getFullyQualifiedName(packageName, attrEntry.getValue().getUpperCaseCammelCase()); - + } fields.add(new Field(fullyQualifiedName, varName)); String getterName = "get" + innerName; @@ -470,7 +461,7 @@ public class TemplateFactory { } String getType() { - return type; + return fullyQualifiedName; } String getName() { @@ -488,38 +479,16 @@ public class TemplateFactory { } private static class MXBeanInterfaceAttributesProcessor { - private static final String STRING_FULLY_QUALIFIED_NAME = "java.util.List"; private final List methods = Lists.newArrayList(); - void processAttributes(Map attributes, - String packageName) { + void processAttributes(Map attributes) { for (Entry attrEntry : attributes.entrySet()) { String returnType; AttributeIfc attributeIfc = attrEntry.getValue(); if (attributeIfc instanceof TypedAttribute) { - returnType = ((TypedAttribute) attributeIfc).getType() - .getFullyQualifiedName(); - } else if (attributeIfc instanceof TOAttribute) { - String fullyQualifiedName = FullyQualifiedNameHelper - .getFullyQualifiedName(packageName, attributeIfc.getUpperCaseCammelCase()); - - returnType = fullyQualifiedName; - } else if (attributeIfc instanceof ListAttribute) { - String fullyQualifiedName = null; - - AttributeIfc innerAttr = ((ListAttribute) attributeIfc) - .getInnerAttribute(); - if (innerAttr instanceof JavaAttribute) { - fullyQualifiedName = ((JavaAttribute) innerAttr) - .getType().getFullyQualifiedName(); - } else if (innerAttr instanceof TOAttribute) { - fullyQualifiedName = FullyQualifiedNameHelper - .getFullyQualifiedName(packageName, innerAttr.getUpperCaseCammelCase()); - } - - returnType = STRING_FULLY_QUALIFIED_NAME.concat("<") - .concat(fullyQualifiedName).concat(">"); + TypedAttribute typedAttribute = (TypedAttribute) attributeIfc; + returnType = serializeType(typedAttribute.getType()); } else { throw new UnsupportedOperationException( "Attribute not supported: " @@ -565,14 +534,14 @@ public class TemplateFactory { AttributeIfc attributeIfc = attrEntry.getValue(); if (attributeIfc instanceof TypedAttribute) { - type = ((TypedAttribute) attributeIfc).getType() - .getFullyQualifiedName(); + TypedAttribute typedAttribute = (TypedAttribute) attributeIfc; + type = serializeType(typedAttribute.getType()); } else if (attributeIfc instanceof TOAttribute) { String fullyQualifiedName = FullyQualifiedNameHelper .getFullyQualifiedName(packageName, attributeIfc.getUpperCaseCammelCase()); type = fullyQualifiedName; - } else if (attributeIfc instanceof ListAttribute) { + } else if (attributeIfc instanceof ListAttribute) { //FIXME: listAttribute might extend TypedAttribute String fullyQualifiedName = null; AttributeIfc innerAttr = ((ListAttribute) attributeIfc) .getInnerAttribute(); @@ -617,8 +586,8 @@ public class TemplateFactory { AttributeIfc attributeIfc = attrEntry.getValue(); if (attributeIfc instanceof TypedAttribute) { - type = ((TypedAttribute) attributeIfc).getType() - .getFullyQualifiedName(); + TypedAttribute typedAttribute = (TypedAttribute) attributeIfc; + type = serializeType(typedAttribute.getType()); } else if (attributeIfc instanceof TOAttribute) { String fullyQualifiedName = FullyQualifiedNameHelper .getFullyQualifiedName(packageName, attributeIfc.getUpperCaseCammelCase()); @@ -651,9 +620,9 @@ public class TemplateFactory { List annotations = Lists .newArrayList(overrideAnnotation); - if (attributeIfc instanceof DependencyAttribute) { + if (attributeIfc instanceof AbstractDependencyAttribute) { isDependency = true; - dependency = ((DependencyAttribute) attributeIfc) + dependency = ((AbstractDependencyAttribute) attributeIfc) .getDependency(); annotations.add(Annotation .createRequireIfcAnnotation(dependency.getSie())); diff --git a/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/model/ModuleField.java b/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/model/ModuleField.java index 293696d10e..5624e169da 100644 --- a/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/model/ModuleField.java +++ b/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/model/ModuleField.java @@ -7,11 +7,13 @@ */ package org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model; + +import org.opendaylight.controller.config.yangjmxgenerator.attribute.Dependency; + +import java.util.ArrayList; import java.util.Collections; import java.util.List; -import org.opendaylight.controller.config.yangjmxgenerator.attribute.DependencyAttribute.Dependency; - public class ModuleField extends Field { private final String nullableDefault, attributeName; @@ -22,10 +24,14 @@ public class ModuleField extends Field { String attributeName, String nullableDefault, boolean isDependency, Dependency dependency) { super(modifiers, type, name); - this.nullableDefault = nullableDefault; this.dependent = isDependency; this.dependency = dependency; this.attributeName = attributeName; + if (type.startsWith(List.class.getName()) && nullableDefault == null) { + String generics = type.substring(List.class.getName().length()); + nullableDefault = "new " + ArrayList.class.getName() + generics + "()"; + } + this.nullableDefault = nullableDefault; } public ModuleField(String type, String name, String attributeName, @@ -49,4 +55,5 @@ public class ModuleField extends Field { public String getAttributeName() { return attributeName; } + } diff --git a/opendaylight/config/yang-jmx-generator-plugin/src/main/resources/freeMarker/module_abs_template_new.ftl b/opendaylight/config/yang-jmx-generator-plugin/src/main/resources/freeMarker/module_abs_template_new.ftl index d0646f467a..f7197d1582 100644 --- a/opendaylight/config/yang-jmx-generator-plugin/src/main/resources/freeMarker/module_abs_template_new.ftl +++ b/opendaylight/config/yang-jmx-generator-plugin/src/main/resources/freeMarker/module_abs_template_new.ftl @@ -52,8 +52,14 @@ package ${packageName}; public void validate(){ <#list moduleFields as field> <#if field.dependent==true && field.dependency.mandatory==true> + <#if field.type?starts_with("java.util.List")> + for(javax.management.ObjectName dep : ${field.name}) { + dependencyResolver.validateDependency(${field.dependency.sie.fullyQualifiedName}.class, dep, ${field.name}JmxAttribute); + } + <#else> dependencyResolver.validateDependency(${field.dependency.sie.fullyQualifiedName}.class, ${field.name}, ${field.name}JmxAttribute); + customValidation(); } @@ -65,10 +71,17 @@ package ${packageName}; // caches of resolved dependencies <#list moduleFields as field> <#if field.dependent==true> + <#if field.type?starts_with("java.util.List")> + private java.util.List<${field.dependency.sie.exportedOsgiClassName}> ${field.name}Dependency = new java.util.ArrayList<${field.dependency.sie.exportedOsgiClassName}>(); + protected final java.util.List<${field.dependency.sie.exportedOsgiClassName}> get${field.attributeName}Dependency(){ + return ${field.name}Dependency; + } + <#else> private ${field.dependency.sie.exportedOsgiClassName} ${field.name}Dependency; protected final ${field.dependency.sie.exportedOsgiClassName} get${field.attributeName}Dependency(){ return ${field.name}Dependency; } + @@ -79,12 +92,18 @@ package ${packageName}; <#list moduleFields as field> <#if field.dependent==true> - <#if field.dependency.mandatory==false> if(${field.name}!=null) { - ${field.name}Dependency = dependencyResolver.resolveInstance(${field.dependency.sie.exportedOsgiClassName}.class, ${field.name}, ${field.name}JmxAttribute); + <#if field.type?starts_with("java.util.List")> + ${field.name}Dependency = new java.util.ArrayList<${field.dependency.sie.exportedOsgiClassName}>(); + for(javax.management.ObjectName dep : ${field.name}) { + ${field.name}Dependency.add(dependencyResolver.resolveInstance(${field.dependency.sie.exportedOsgiClassName}.class, dep, ${field.name}JmxAttribute)); + } + <#else> + ${field.name}Dependency = dependencyResolver.resolveInstance(${field.dependency.sie.exportedOsgiClassName}.class, ${field.name}, ${field.name}JmxAttribute); + <#if field.dependency.mandatory==false> } diff --git a/opendaylight/config/yang-jmx-generator-plugin/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/JMXGeneratorTest.java b/opendaylight/config/yang-jmx-generator-plugin/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/JMXGeneratorTest.java index 0d6ec3cccb..2f1437404a 100644 --- a/opendaylight/config/yang-jmx-generator-plugin/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/JMXGeneratorTest.java +++ b/opendaylight/config/yang-jmx-generator-plugin/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/JMXGeneratorTest.java @@ -75,6 +75,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; +//TODO: refactor public class JMXGeneratorTest extends AbstractGeneratorTest { JMXGenerator jmxGenerator; @@ -84,19 +85,7 @@ public class JMXGeneratorTest extends AbstractGeneratorTest { File generatedResourcesDir; private static final List expectedModuleFileNames = ServiceInterfaceEntryTest - .toFileNames("[AbstractAsyncEventBusModule.java, AbstractAsyncEventBusModuleFactory.java, " + - "AbstractDynamicThreadPoolModule.java, AbstractDynamicThreadPoolModuleFactory.java, " + - "AbstractEventBusModule.java, AbstractEventBusModuleFactory.java, " + - "AbstractNamingThreadFactoryModule.java, AbstractNamingThreadFactoryModuleFactory.java, " + - "AsyncEventBusModule.java, AsyncEventBusModuleFactory.java, AsyncEventBusModuleMXBean.java, " + - "AsyncEventBusRuntimeMXBean.java, AsyncEventBusRuntimeRegistration.java, " + - "AsyncEventBusRuntimeRegistrator.java, DynamicThreadPoolModule.java, " + - "DynamicThreadPoolModuleFactory.java, DynamicThreadPoolModuleMXBean.java, " + - "DynamicThreadPoolRuntimeMXBean.java, DynamicThreadPoolRuntimeRegistration.java, " + - "DynamicThreadPoolRuntimeRegistrator.java, EventBusModule.java, EventBusModuleFactory.java, " + - "EventBusModuleMXBean.java, EventRuntimeMXBean.java, EventRuntimeRegistration.java, " + - "InnerStreamList.java, NamingThreadFactoryModule.java, NamingThreadFactoryModuleFactory.java, " + - "NamingThreadFactoryModuleMXBean.java, NamingThreadFactoryRuntimeMXBean.java, NamingThreadFactoryRuntimeRegistration.java, NamingThreadFactoryRuntimeRegistrator.java, Peer.java, StreamRuntimeMXBean.java, StreamRuntimeRegistration.java, ThreadRuntimeMXBean.java, ThreadRuntimeRegistration.java, ThreadStreamRuntimeMXBean.java, ThreadStreamRuntimeRegistration.java]"); + .toFileNames("[AbstractAsyncEventBusModule.java, AbstractAsyncEventBusModuleFactory.java, AbstractDynamicThreadPoolModule.java, AbstractDynamicThreadPoolModuleFactory.java, AbstractEventBusModule.java, AbstractEventBusModuleFactory.java, AbstractNamingThreadFactoryModule.java, AbstractNamingThreadFactoryModuleFactory.java, AbstractThreadPoolRegistryImplModule.java, AbstractThreadPoolRegistryImplModuleFactory.java, AsyncEventBusModule.java, AsyncEventBusModuleFactory.java, AsyncEventBusModuleMXBean.java, AsyncEventBusRuntimeMXBean.java, AsyncEventBusRuntimeRegistration.java, AsyncEventBusRuntimeRegistrator.java, DynamicThreadPoolModule.java, DynamicThreadPoolModuleFactory.java, DynamicThreadPoolModuleMXBean.java, DynamicThreadPoolRuntimeMXBean.java, DynamicThreadPoolRuntimeRegistration.java, DynamicThreadPoolRuntimeRegistrator.java, EventBusModule.java, EventBusModuleFactory.java, EventBusModuleMXBean.java, EventRuntimeMXBean.java, EventRuntimeRegistration.java, InnerStreamList.java, NamingThreadFactoryModule.java, NamingThreadFactoryModuleFactory.java, NamingThreadFactoryModuleMXBean.java, NamingThreadFactoryRuntimeMXBean.java, NamingThreadFactoryRuntimeRegistration.java, NamingThreadFactoryRuntimeRegistrator.java, Peer.java, StreamRuntimeMXBean.java, StreamRuntimeRegistration.java, ThreadPoolRegistryImplModule.java, ThreadPoolRegistryImplModuleFactory.java, ThreadPoolRegistryImplModuleMXBean.java, ThreadRuntimeMXBean.java, ThreadRuntimeRegistration.java, ThreadStreamRuntimeMXBean.java, ThreadStreamRuntimeRegistration.java]"); private static final List expectedBGPNames = ServiceInterfaceEntryTest .toFileNames("[AbstractBgpListenerImplModule.java, " + "AbstractBgpListenerImplModuleFactory.java, " + @@ -119,38 +108,7 @@ public class JMXGeneratorTest extends AbstractGeneratorTest { "NetconfTestFiles1ImplModuleMXBean.java, NetconfTestFiles1ImplRuntimeMXBean.java, " + "NetconfTestFiles1ImplRuntimeRegistration.java, NetconfTestFiles1ImplRuntimeRegistrator.java, TestFileImplModule.java, TestFileImplModuleFactory.java, TestFileImplModuleMXBean.java, TestFileImplRuntimeMXBean.java, TestFileImplRuntimeRegistration.java, TestFileImplRuntimeRegistrator.java, TestFiles1ImplModule.java, TestFiles1ImplModuleFactory.java, TestFiles1ImplModuleMXBean.java, TestFiles1ImplRuntimeMXBean.java, TestFiles1ImplRuntimeRegistration.java, TestFiles1ImplRuntimeRegistrator.java]"); private static final List expectedAllFileNames = ServiceInterfaceEntryTest - .toFileNames("[AbstractAsyncEventBusModule.java, AbstractAsyncEventBusModuleFactory.java, " + - "AbstractBgpListenerImplModule.java, AbstractBgpListenerImplModuleFactory.java, " + - "AbstractDynamicThreadPoolModule.java, AbstractDynamicThreadPoolModuleFactory.java, " + - "AbstractEventBusModule.java, AbstractEventBusModuleFactory.java, " + - "AbstractNamingThreadFactoryModule.java, AbstractNamingThreadFactoryModuleFactory.java, " + - "AbstractNetconfTestFileImplModule.java, AbstractNetconfTestFileImplModuleFactory.java, " + - "AbstractNetconfTestFiles1ImplModule.java, AbstractNetconfTestFiles1ImplModuleFactory.java, " + - "AbstractNetconfTestImplModule.java, AbstractNetconfTestImplModuleFactory.java, " + - "AbstractTestFileImplModule.java, AbstractTestFileImplModuleFactory.java, " + - "AbstractTestFiles1ImplModule.java, AbstractTestFiles1ImplModuleFactory.java, " + - "AbstractTestImplModule.java, AbstractTestImplModuleFactory.java, AsyncEventBusModule.java, " + - "AsyncEventBusModuleFactory.java, AsyncEventBusModuleMXBean.java, " + - "AsyncEventBusRuntimeMXBean.java, AsyncEventBusRuntimeRegistration.java, " + - "AsyncEventBusRuntimeRegistrator.java, AutoCloseableServiceInterface.java, " + - "BgpListenerImplModule.java, BgpListenerImplModuleFactory.java, BgpListenerImplModuleMXBean.java," + - " BgpListenerImplRuntimeMXBean.java, BgpListenerImplRuntimeRegistration.java, " + - "BgpListenerImplRuntimeRegistrator.java, ComplexDtoBInner.java, ComplexList.java, Deep.java, " + - "DtoA.java, DtoA.java, DtoA.java, DtoA1.java, DtoAInner.java, DtoAInnerInner.java, DtoB.java, " + - "DtoC.java, DynamicThreadPoolModule.java, DynamicThreadPoolModuleFactory.java, " + - "DynamicThreadPoolModuleMXBean.java, DynamicThreadPoolRuntimeMXBean.java, " + - "DynamicThreadPoolRuntimeRegistration.java, DynamicThreadPoolRuntimeRegistrator.java, " + - "EventBusModule.java, EventBusModuleFactory.java, EventBusModuleMXBean.java, " + - "EventBusServiceInterface.java, EventRuntimeMXBean.java, EventRuntimeRegistration.java, " + - "InnerStreamList.java, NamingThreadFactoryModule.java, NamingThreadFactoryModuleFactory.java, " + - "NamingThreadFactoryModuleMXBean.java, NamingThreadFactoryRuntimeMXBean.java, " + - "NamingThreadFactoryRuntimeRegistration.java, NamingThreadFactoryRuntimeRegistrator.java, " + - "NetconfTestFileImplModule.java, NetconfTestFileImplModuleFactory.java, " + - "NetconfTestFileImplModuleMXBean.java, NetconfTestFileImplRuntimeMXBean.java, " + - "NetconfTestFileImplRuntimeRegistration.java, NetconfTestFileImplRuntimeRegistrator.java, " + - "NetconfTestFiles1ImplModule.java, NetconfTestFiles1ImplModuleFactory.java, " + - "NetconfTestFiles1ImplModuleMXBean.java, NetconfTestFiles1ImplRuntimeMXBean.java, " + - "NetconfTestFiles1ImplRuntimeRegistration.java, NetconfTestFiles1ImplRuntimeRegistrator.java, NetconfTestImplModule.java, NetconfTestImplModuleFactory.java, NetconfTestImplModuleMXBean.java, NetconfTestImplRuntimeMXBean.java, NetconfTestImplRuntimeRegistration.java, NetconfTestImplRuntimeRegistrator.java, Peer.java, Peer.java, PeersRuntimeMXBean.java, PeersRuntimeRegistration.java, ScheduledThreadPoolServiceInterface.java, SimpleList.java, StreamRuntimeMXBean.java, StreamRuntimeRegistration.java, TestFileImplModule.java, TestFileImplModuleFactory.java, TestFileImplModuleMXBean.java, TestFileImplRuntimeMXBean.java, TestFileImplRuntimeRegistration.java, TestFileImplRuntimeRegistrator.java, TestFiles1ImplModule.java, TestFiles1ImplModuleFactory.java, TestFiles1ImplModuleMXBean.java, TestFiles1ImplRuntimeMXBean.java, TestFiles1ImplRuntimeRegistration.java, TestFiles1ImplRuntimeRegistrator.java, TestImplModule.java, TestImplModuleFactory.java, TestImplModuleMXBean.java, TestImplRuntimeMXBean.java, TestImplRuntimeRegistration.java, TestImplRuntimeRegistrator.java, ThreadFactoryServiceInterface.java, ThreadPoolServiceInterface.java, ThreadRuntimeMXBean.java, ThreadRuntimeRegistration.java, ThreadStreamRuntimeMXBean.java, ThreadStreamRuntimeRegistration.java]"); + .toFileNames("[AbstractAsyncEventBusModule.java, AbstractAsyncEventBusModuleFactory.java, AbstractBgpListenerImplModule.java, AbstractBgpListenerImplModuleFactory.java, AbstractDynamicThreadPoolModule.java, AbstractDynamicThreadPoolModuleFactory.java, AbstractEventBusModule.java, AbstractEventBusModuleFactory.java, AbstractNamingThreadFactoryModule.java, AbstractNamingThreadFactoryModuleFactory.java, AbstractNetconfTestFileImplModule.java, AbstractNetconfTestFileImplModuleFactory.java, AbstractNetconfTestFiles1ImplModule.java, AbstractNetconfTestFiles1ImplModuleFactory.java, AbstractNetconfTestImplModule.java, AbstractNetconfTestImplModuleFactory.java, AbstractTestFileImplModule.java, AbstractTestFileImplModuleFactory.java, AbstractTestFiles1ImplModule.java, AbstractTestFiles1ImplModuleFactory.java, AbstractTestImplModule.java, AbstractTestImplModuleFactory.java, AbstractThreadPoolRegistryImplModule.java, AbstractThreadPoolRegistryImplModuleFactory.java, AsyncEventBusModule.java, AsyncEventBusModuleFactory.java, AsyncEventBusModuleMXBean.java, AsyncEventBusRuntimeMXBean.java, AsyncEventBusRuntimeRegistration.java, AsyncEventBusRuntimeRegistrator.java, AutoCloseableServiceInterface.java, BgpListenerImplModule.java, BgpListenerImplModuleFactory.java, BgpListenerImplModuleMXBean.java, BgpListenerImplRuntimeMXBean.java, BgpListenerImplRuntimeRegistration.java, BgpListenerImplRuntimeRegistrator.java, ComplexDtoBInner.java, ComplexList.java, Deep.java, DtoA.java, DtoA.java, DtoA.java, DtoA1.java, DtoAInner.java, DtoAInnerInner.java, DtoB.java, DtoC.java, DynamicThreadPoolModule.java, DynamicThreadPoolModuleFactory.java, DynamicThreadPoolModuleMXBean.java, DynamicThreadPoolRuntimeMXBean.java, DynamicThreadPoolRuntimeRegistration.java, DynamicThreadPoolRuntimeRegistrator.java, EventBusModule.java, EventBusModuleFactory.java, EventBusModuleMXBean.java, EventBusServiceInterface.java, EventRuntimeMXBean.java, EventRuntimeRegistration.java, InnerStreamList.java, NamingThreadFactoryModule.java, NamingThreadFactoryModuleFactory.java, NamingThreadFactoryModuleMXBean.java, NamingThreadFactoryRuntimeMXBean.java, NamingThreadFactoryRuntimeRegistration.java, NamingThreadFactoryRuntimeRegistrator.java, NetconfTestFileImplModule.java, NetconfTestFileImplModuleFactory.java, NetconfTestFileImplModuleMXBean.java, NetconfTestFileImplRuntimeMXBean.java, NetconfTestFileImplRuntimeRegistration.java, NetconfTestFileImplRuntimeRegistrator.java, NetconfTestFiles1ImplModule.java, NetconfTestFiles1ImplModuleFactory.java, NetconfTestFiles1ImplModuleMXBean.java, NetconfTestFiles1ImplRuntimeMXBean.java, NetconfTestFiles1ImplRuntimeRegistration.java, NetconfTestFiles1ImplRuntimeRegistrator.java, NetconfTestImplModule.java, NetconfTestImplModuleFactory.java, NetconfTestImplModuleMXBean.java, NetconfTestImplRuntimeMXBean.java, NetconfTestImplRuntimeRegistration.java, NetconfTestImplRuntimeRegistrator.java, Peer.java, Peer.java, PeersRuntimeMXBean.java, PeersRuntimeRegistration.java, ScheduledThreadPoolServiceInterface.java, SimpleList.java, StreamRuntimeMXBean.java, StreamRuntimeRegistration.java, TestFileImplModule.java, TestFileImplModuleFactory.java, TestFileImplModuleMXBean.java, TestFileImplRuntimeMXBean.java, TestFileImplRuntimeRegistration.java, TestFileImplRuntimeRegistrator.java, TestFiles1ImplModule.java, TestFiles1ImplModuleFactory.java, TestFiles1ImplModuleMXBean.java, TestFiles1ImplRuntimeMXBean.java, TestFiles1ImplRuntimeRegistration.java, TestFiles1ImplRuntimeRegistrator.java, TestImplModule.java, TestImplModuleFactory.java, TestImplModuleMXBean.java, TestImplRuntimeMXBean.java, TestImplRuntimeRegistration.java, TestImplRuntimeRegistrator.java, ThreadFactoryServiceInterface.java, ThreadPoolRegistryImplModule.java, ThreadPoolRegistryImplModuleFactory.java, ThreadPoolRegistryImplModuleMXBean.java, ThreadPoolServiceInterface.java, ThreadRuntimeMXBean.java, ThreadRuntimeRegistration.java, ThreadStreamRuntimeMXBean.java, ThreadStreamRuntimeRegistration.java]"); private static final List expectedGenerateMBEsListNames = ServiceInterfaceEntryTest .toFileNames("[AbstractBgpListenerImplModule.java, AbstractBgpListenerImplModuleFactory.java, BgpListenerImplModule.java, BgpListenerImplModuleFactory.java, BgpListenerImplModuleMXBean.java, BgpListenerImplRuntimeMXBean.java, BgpListenerImplRuntimeRegistration.java, BgpListenerImplRuntimeRegistrator.java, PeersRuntimeMXBean.java, PeersRuntimeRegistration.java]"); @@ -381,7 +339,11 @@ public class JMXGeneratorTest extends AbstractGeneratorTest { PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX + ".threads.java.DynamicThreadPoolModuleFactory",// PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX - + ".threads.java.NamingThreadFactoryModuleFactory"); + + ".threads.java.NamingThreadFactoryModuleFactory", // + PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX + + ".threads.java.ThreadPoolRegistryImplModuleFactory"); + + assertThat(lines, equalTo(expectedLines)); } diff --git a/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntry.java b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntry.java index 70a4edde41..a7110b874c 100644 --- a/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntry.java +++ b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntry.java @@ -8,11 +8,14 @@ package org.opendaylight.controller.config.yangjmxgenerator; import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Optional; import com.google.common.collect.Sets; +import org.opendaylight.controller.config.yangjmxgenerator.attribute.AbstractDependencyAttribute; import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc; import org.opendaylight.controller.config.yangjmxgenerator.attribute.DependencyAttribute; import org.opendaylight.controller.config.yangjmxgenerator.attribute.JavaAttribute; import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListAttribute; +import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListDependenciesAttribute; import org.opendaylight.controller.config.yangjmxgenerator.attribute.TOAttribute; import org.opendaylight.controller.config.yangjmxgenerator.plugin.util.FullyQualifiedNameHelper; import org.opendaylight.controller.config.yangjmxgenerator.plugin.util.NameConflictException; @@ -21,6 +24,7 @@ import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode; import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; +import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode; import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode; @@ -338,7 +342,7 @@ public class ModuleMXBeanEntry extends AbstractEntry { moduleLocalNameFromXPath); yangToAttributes = fillConfiguration(choiceCaseNode, currentModule, typeProviderWrapper, - qNamesToSIEs, schemaContext); + qNamesToSIEs, schemaContext, packageName); checkUniqueAttributesWithGeneratedClass( uniqueGeneratedClassesNames, when.getQName(), yangToAttributes); @@ -484,12 +488,12 @@ public class ModuleMXBeanEntry extends AbstractEntry { ChoiceCaseNode choiceCaseNode, Module currentModule, TypeProviderWrapper typeProviderWrapper, Map qNamesToSIEs, - SchemaContext schemaContext) { + SchemaContext schemaContext, String packageName) { Map yangToAttributes = new HashMap<>(); for (DataSchemaNode attrNode : choiceCaseNode.getChildNodes()) { AttributeIfc attributeValue = getAttributeValue(attrNode, currentModule, qNamesToSIEs, typeProviderWrapper, - schemaContext); + schemaContext, packageName); yangToAttributes.put(attributeValue.getAttributeYangName(), attributeValue); } @@ -549,11 +553,12 @@ public class ModuleMXBeanEntry extends AbstractEntry { } } - private static int getChildNodeSizeWithoutUses(ContainerSchemaNode csn) { + private static int getChildNodeSizeWithoutUses(DataNodeContainer csn) { int result = 0; for (DataSchemaNode dsn : csn.getChildNodes()) { - if (dsn.isAddedByUses() == false) + if (dsn.isAddedByUses() == false) { result++; + } } return result; } @@ -561,7 +566,7 @@ public class ModuleMXBeanEntry extends AbstractEntry { private static AttributeIfc getAttributeValue(DataSchemaNode attrNode, Module currentModule, Map qNamesToSIEs, - TypeProviderWrapper typeProviderWrapper, SchemaContext schemaContext) { + TypeProviderWrapper typeProviderWrapper, SchemaContext schemaContext, String packageName) { if (attrNode instanceof LeafSchemaNode) { // simple type @@ -570,49 +575,75 @@ public class ModuleMXBeanEntry extends AbstractEntry { } else if (attrNode instanceof ContainerSchemaNode) { // reference or TO ContainerSchemaNode containerSchemaNode = (ContainerSchemaNode) attrNode; - if (containerSchemaNode.getUses().size() == 1 - && getChildNodeSizeWithoutUses(containerSchemaNode) == 0) { - // reference - UsesNode usesNode = containerSchemaNode.getUses().iterator() - .next(); - checkState(usesNode.getRefines().size() == 1, - "Unexpected 'refine' child node size of " - + containerSchemaNode); - LeafSchemaNode refine = (LeafSchemaNode) usesNode.getRefines() - .values().iterator().next(); - checkState(refine.getUnknownSchemaNodes().size() == 1, - "Unexpected unknown schema node size of " + refine); - UnknownSchemaNode requiredIdentity = refine - .getUnknownSchemaNodes().iterator().next(); - checkState( - ConfigConstants.REQUIRED_IDENTITY_EXTENSION_QNAME.equals(requiredIdentity - .getNodeType()), - "Unexpected language extension " + requiredIdentity); - String prefixAndIdentityLocalName = requiredIdentity - .getNodeParameter(); - // import should point to a module - ServiceInterfaceEntry serviceInterfaceEntry = findSIE( - prefixAndIdentityLocalName, currentModule, - qNamesToSIEs, schemaContext); - boolean mandatory = refine.getConstraints().isMandatory(); - return new DependencyAttribute(attrNode, serviceInterfaceEntry, - mandatory, attrNode.getDescription()); + Optional dependencyAttributeOptional = extractDependency(containerSchemaNode, + attrNode, currentModule, qNamesToSIEs, schemaContext); + if (dependencyAttributeOptional.isPresent()) { + return dependencyAttributeOptional.get(); } else { - return TOAttribute.create(containerSchemaNode, - typeProviderWrapper); + return TOAttribute.create(containerSchemaNode, typeProviderWrapper, packageName); } + } else if (attrNode instanceof LeafListSchemaNode) { return ListAttribute.create((LeafListSchemaNode) attrNode, typeProviderWrapper); } else if (attrNode instanceof ListSchemaNode) { - return ListAttribute.create((ListSchemaNode) attrNode, - typeProviderWrapper); + ListSchemaNode listSchemaNode = (ListSchemaNode) attrNode; + Optional dependencyAttributeOptional = extractDependency(listSchemaNode, + attrNode, currentModule, qNamesToSIEs, schemaContext); + if (dependencyAttributeOptional.isPresent()) { + return dependencyAttributeOptional.get(); + } else { + return ListAttribute.create(listSchemaNode, typeProviderWrapper, packageName); + } } else { throw new UnsupportedOperationException( "Unknown configuration node " + attrNode.toString()); } } + private static Optional extractDependency(DataNodeContainer dataNodeContainer, + DataSchemaNode attrNode, + Module currentModule, + Map qNamesToSIEs, + SchemaContext schemaContext) { + if (dataNodeContainer.getUses().size() == 1 + && getChildNodeSizeWithoutUses(dataNodeContainer) == 0) { + // reference + UsesNode usesNode = dataNodeContainer.getUses().iterator() + .next(); + checkState(usesNode.getRefines().size() == 1, + "Unexpected 'refine' child node size of " + + dataNodeContainer); + LeafSchemaNode refine = (LeafSchemaNode) usesNode.getRefines() + .values().iterator().next(); + checkState(refine.getUnknownSchemaNodes().size() == 1, + "Unexpected unknown schema node size of " + refine); + UnknownSchemaNode requiredIdentity = refine + .getUnknownSchemaNodes().iterator().next(); + checkState( + ConfigConstants.REQUIRED_IDENTITY_EXTENSION_QNAME.equals(requiredIdentity + .getNodeType()), + "Unexpected language extension " + requiredIdentity); + String prefixAndIdentityLocalName = requiredIdentity + .getNodeParameter(); + // import should point to a module + ServiceInterfaceEntry serviceInterfaceEntry = findSIE( + prefixAndIdentityLocalName, currentModule, + qNamesToSIEs, schemaContext); + boolean mandatory = refine.getConstraints().isMandatory(); + AbstractDependencyAttribute reference; + if (dataNodeContainer instanceof ContainerSchemaNode ){ + reference = new DependencyAttribute(attrNode, serviceInterfaceEntry, + mandatory, attrNode.getDescription()); + } else { + reference = new ListDependenciesAttribute(attrNode, serviceInterfaceEntry, + mandatory, attrNode.getDescription()); + } + return Optional.of(reference); + } + return Optional.absent(); + } + private static ServiceInterfaceEntry findSIE( String prefixAndIdentityLocalName, Module currentModule, Map qNamesToSIEs, diff --git a/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/RuntimeBeanEntry.java b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/RuntimeBeanEntry.java index 9b82f123ca..f19a46d0f4 100644 --- a/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/RuntimeBeanEntry.java +++ b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/RuntimeBeanEntry.java @@ -67,7 +67,7 @@ public class RuntimeBeanEntry { private final Set rpcs; @VisibleForTesting - public RuntimeBeanEntry(String packageName, + RuntimeBeanEntry(String packageName, DataSchemaNode nodeForReporting, String yangName, String javaNamePrefix, boolean isRoot, Optional keyYangName, List attributes, @@ -228,7 +228,7 @@ public class RuntimeBeanEntry { ContainerSchemaNode container = (ContainerSchemaNode) child; // this can be either TO or hierarchical RB TOAttribute toAttribute = TOAttribute.create(container, - typeProviderWrapper); + typeProviderWrapper, packageName); attributes.add(toAttribute); } else if (child instanceof ListSchemaNode) { if (isInnerStateBean(child)) { @@ -239,7 +239,7 @@ public class RuntimeBeanEntry { runtimeBeanEntries.add(hierarchicalChild); } else /* ordinary list attribute */{ ListAttribute listAttribute = ListAttribute.create( - (ListSchemaNode) child, typeProviderWrapper); + (ListSchemaNode) child, typeProviderWrapper, packageName); attributes.add(listAttribute); } @@ -280,7 +280,7 @@ public class RuntimeBeanEntry { } else if (rpcDefinition.getOutput().getChildNodes().size() == 1) { DataSchemaNode returnDSN = rpcDefinition.getOutput() .getChildNodes().iterator().next(); - returnType = getReturnTypeAttribute(returnDSN, typeProviderWrapper); + returnType = getReturnTypeAttribute(returnDSN, typeProviderWrapper, packageName); } else { throw new IllegalArgumentException( @@ -311,16 +311,17 @@ public class RuntimeBeanEntry { attributes, rpcs); } - private static AttributeIfc getReturnTypeAttribute(DataSchemaNode child, TypeProviderWrapper typeProviderWrapper) { + private static AttributeIfc getReturnTypeAttribute(DataSchemaNode child, TypeProviderWrapper typeProviderWrapper, + String packageName) { if (child instanceof LeafSchemaNode) { LeafSchemaNode leaf = (LeafSchemaNode) child; return new JavaAttribute(leaf, typeProviderWrapper); } else if (child instanceof ContainerSchemaNode) { ContainerSchemaNode container = (ContainerSchemaNode) child; - TOAttribute toAttribute = TOAttribute.create(container, typeProviderWrapper); + TOAttribute toAttribute = TOAttribute.create(container, typeProviderWrapper, packageName); return toAttribute; } else if (child instanceof ListSchemaNode) { - return ListAttribute.create((ListSchemaNode) child, typeProviderWrapper); + return ListAttribute.create((ListSchemaNode) child, typeProviderWrapper, packageName); } else if (child instanceof LeafListSchemaNode) { return ListAttribute.create((LeafListSchemaNode) child, typeProviderWrapper); } else { diff --git a/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/AbstractDependencyAttribute.java b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/AbstractDependencyAttribute.java new file mode 100644 index 0000000000..eb1c9e41a6 --- /dev/null +++ b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/AbstractDependencyAttribute.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.config.yangjmxgenerator.attribute; + +import org.opendaylight.controller.config.yangjmxgenerator.ServiceInterfaceEntry; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; + +public abstract class AbstractDependencyAttribute extends AbstractAttribute implements TypedAttribute { + + protected final Dependency dependency; + protected final String nullableDescription, nullableDefault; + + public AbstractDependencyAttribute(DataSchemaNode attrNode, + ServiceInterfaceEntry sie, boolean mandatory, + String nullableDescription) { + super(attrNode); + dependency = new Dependency(sie, mandatory); + this.nullableDescription = nullableDescription; + nullableDefault = null; + } + + public Dependency getDependency() { + return dependency; + } + + @Override + public String getNullableDescription() { + return nullableDescription; + } + + @Override + public String getNullableDefault() { + return nullableDefault; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + if (!super.equals(o)) + return false; + + AbstractDependencyAttribute that = (AbstractDependencyAttribute) o; + + if (dependency != null ? !dependency.equals(that.dependency) + : that.dependency != null) + return false; + if (nullableDefault != null ? !nullableDefault + .equals(that.nullableDefault) : that.nullableDefault != null) + return false; + if (nullableDescription != null ? !nullableDescription + .equals(that.nullableDescription) + : that.nullableDescription != null) + return false; + + return true; + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (dependency != null ? dependency.hashCode() : 0); + result = 31 + * result + + (nullableDescription != null ? nullableDescription.hashCode() + : 0); + result = 31 * result + + (nullableDefault != null ? nullableDefault.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return getClass().getName() + "{" + getAttributeYangName() + "," + + "dependency=" + dependency + '}'; + } + + +} diff --git a/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/Dependency.java b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/Dependency.java new file mode 100644 index 0000000000..38de6e1528 --- /dev/null +++ b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/Dependency.java @@ -0,0 +1,45 @@ +package org.opendaylight.controller.config.yangjmxgenerator.attribute; + +import org.opendaylight.controller.config.yangjmxgenerator.ServiceInterfaceEntry; + +public class Dependency { + private final ServiceInterfaceEntry sie; + private final boolean mandatory; + + public Dependency(ServiceInterfaceEntry sie, boolean mandatory) { + this.sie = sie; + this.mandatory = mandatory; + } + + public ServiceInterfaceEntry getSie() { + return sie; + } + + public boolean isMandatory() { + return mandatory; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + Dependency that = (Dependency) o; + + if (mandatory != that.mandatory) + return false; + if (!sie.equals(that.sie)) + return false; + + return true; + } + + @Override + public int hashCode() { + int result = sie.hashCode(); + result = 31 * result + (mandatory ? 1 : 0); + return result; + } + } diff --git a/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/DependencyAttribute.java b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/DependencyAttribute.java index 1912b75e0e..d8df78af0a 100644 --- a/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/DependencyAttribute.java +++ b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/DependencyAttribute.java @@ -15,19 +15,13 @@ import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; import javax.management.ObjectName; import javax.management.openmbean.SimpleType; -public class DependencyAttribute extends AbstractAttribute implements - TypedAttribute { +public class DependencyAttribute extends AbstractDependencyAttribute { - private final Dependency dependency; - private final String nullableDescription, nullableDefault; public DependencyAttribute(DataSchemaNode attrNode, ServiceInterfaceEntry sie, boolean mandatory, String nullableDescription) { - super(attrNode); - dependency = new Dependency(sie, mandatory); - this.nullableDescription = nullableDescription; - nullableDefault = null; + super(attrNode, sie, mandatory, nullableDescription); } @Override @@ -35,109 +29,9 @@ public class DependencyAttribute extends AbstractAttribute implements return Types.typeForClass(ObjectName.class); } - public Dependency getDependency() { - return dependency; - } - - @Override - public String getNullableDescription() { - return nullableDescription; - } - - @Override - public String getNullableDefault() { - return nullableDefault; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (o == null || getClass() != o.getClass()) - return false; - if (!super.equals(o)) - return false; - - DependencyAttribute that = (DependencyAttribute) o; - - if (dependency != null ? !dependency.equals(that.dependency) - : that.dependency != null) - return false; - if (nullableDefault != null ? !nullableDefault - .equals(that.nullableDefault) : that.nullableDefault != null) - return false; - if (nullableDescription != null ? !nullableDescription - .equals(that.nullableDescription) - : that.nullableDescription != null) - return false; - - return true; - } - - @Override - public int hashCode() { - int result = super.hashCode(); - result = 31 * result + (dependency != null ? dependency.hashCode() : 0); - result = 31 - * result - + (nullableDescription != null ? nullableDescription.hashCode() - : 0); - result = 31 * result - + (nullableDefault != null ? nullableDefault.hashCode() : 0); - return result; - } - - @Override - public String toString() { - return "DependencyAttribute{" + getAttributeYangName() + "," - + "dependency=" + dependency + '}'; - } - @Override public SimpleType getOpenType() { return SimpleType.OBJECTNAME; } - public static class Dependency { - private final ServiceInterfaceEntry sie; - private final boolean mandatory; - - public Dependency(ServiceInterfaceEntry sie, boolean mandatory) { - this.sie = sie; - this.mandatory = mandatory; - } - - public ServiceInterfaceEntry getSie() { - return sie; - } - - public boolean isMandatory() { - return mandatory; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (o == null || getClass() != o.getClass()) - return false; - - Dependency that = (Dependency) o; - - if (mandatory != that.mandatory) - return false; - if (!sie.equals(that.sie)) - return false; - - return true; - } - - @Override - public int hashCode() { - int result = sie.hashCode(); - result = 31 * result + (mandatory ? 1 : 0); - return result; - } - } - } diff --git a/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/ListAttribute.java b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/ListAttribute.java index 083b0b53e9..73b557e291 100644 --- a/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/ListAttribute.java +++ b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/ListAttribute.java @@ -7,24 +7,27 @@ */ package org.opendaylight.controller.config.yangjmxgenerator.attribute; -import javax.management.openmbean.ArrayType; -import javax.management.openmbean.OpenDataException; -import javax.management.openmbean.OpenType; - import org.opendaylight.controller.config.yangjmxgenerator.TypeProviderWrapper; +import org.opendaylight.yangtools.binding.generator.util.Types; +import org.opendaylight.yangtools.sal.binding.model.api.Type; import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode; import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; -public class ListAttribute extends AbstractAttribute { +import javax.management.openmbean.ArrayType; +import javax.management.openmbean.OpenDataException; +import javax.management.openmbean.OpenType; +import java.util.List; + +public class ListAttribute extends AbstractAttribute implements TypedAttribute { private final String nullableDescription, nullableDefault; - private final AttributeIfc innerAttribute; + private final TypedAttribute innerAttribute; public static ListAttribute create(ListSchemaNode node, - TypeProviderWrapper typeProvider) { + TypeProviderWrapper typeProvider, String packageName) { - AttributeIfc innerAttribute = TOAttribute.create(node, typeProvider); + TOAttribute innerAttribute = TOAttribute.create(node, typeProvider, packageName); return new ListAttribute(node, innerAttribute, node.getDescription()); } @@ -32,12 +35,12 @@ public class ListAttribute extends AbstractAttribute { public static ListAttribute create(LeafListSchemaNode node, TypeProviderWrapper typeProvider) { - AttributeIfc innerAttribute = new JavaAttribute(node, typeProvider); + JavaAttribute innerAttribute = new JavaAttribute(node, typeProvider); return new ListAttribute(node, innerAttribute, node.getDescription()); } - ListAttribute(DataSchemaNode attrNode, AttributeIfc innerAttribute, + ListAttribute(DataSchemaNode attrNode, TypedAttribute innerAttribute, String description) { super(attrNode); this.nullableDescription = description; @@ -99,14 +102,24 @@ public class ListAttribute extends AbstractAttribute { return true; } + + @Override + public Type getType() { + return Types.parameterizedTypeFor(Types.typeForClass(List.class), innerAttribute.getType()); + } + @Override public ArrayType getOpenType() { - OpenType inerOpenType = innerAttribute.getOpenType(); + OpenType innerOpenType = innerAttribute.getOpenType(); + return constructArrayType(innerOpenType); + } + + static ArrayType constructArrayType(OpenType innerOpenType){ try { - return new ArrayType<>(1, inerOpenType); + return new ArrayType<>(1, innerOpenType); } catch (OpenDataException e) { throw new RuntimeException("Unable to create " + ArrayType.class - + " with inner element of type " + inerOpenType, e); + + " with inner element of type " + innerOpenType, e); } } diff --git a/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/ListDependenciesAttribute.java b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/ListDependenciesAttribute.java new file mode 100644 index 0000000000..641099aef3 --- /dev/null +++ b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/ListDependenciesAttribute.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.config.yangjmxgenerator.attribute; + +import org.opendaylight.controller.config.yangjmxgenerator.ServiceInterfaceEntry; +import org.opendaylight.yangtools.binding.generator.util.Types; +import org.opendaylight.yangtools.sal.binding.model.api.Type; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; + +import javax.management.ObjectName; +import javax.management.openmbean.ArrayType; +import javax.management.openmbean.OpenType; +import javax.management.openmbean.SimpleType; +import java.util.List; + +public class ListDependenciesAttribute extends AbstractDependencyAttribute { + + public ListDependenciesAttribute(DataSchemaNode attrNode, ServiceInterfaceEntry sie, boolean mandatory, String nullableDescription) { + super(attrNode, sie, mandatory, nullableDescription); + } + + @Override + public Type getType() { + return Types.parameterizedTypeFor(Types.typeForClass(List.class), Types.typeForClass(ObjectName.class)); + } + + @Override + public ArrayType getOpenType() { + OpenType innerOpenType = SimpleType.OBJECTNAME; + return ListAttribute.constructArrayType(innerOpenType); + } + +} diff --git a/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/TOAttribute.java b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/TOAttribute.java index 96656338df..6a540b50b2 100644 --- a/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/TOAttribute.java +++ b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/TOAttribute.java @@ -13,6 +13,8 @@ import com.google.common.collect.Maps; import com.google.common.collect.Sets; import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry; import org.opendaylight.controller.config.yangjmxgenerator.TypeProviderWrapper; +import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl; +import org.opendaylight.yangtools.sal.binding.model.api.Type; import org.opendaylight.yangtools.yang.model.api.AugmentationTarget; import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; @@ -29,11 +31,12 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; -public class TOAttribute extends AbstractAttribute { +public class TOAttribute extends AbstractAttribute implements TypedAttribute { private final String nullableDescription, nullableDefault; private final Map yangNameToAttributeMap; private final Map attributeNameMap; + private final String packageName; private static final Set> ALLOWED_CHILDREN = Sets .newHashSet(); @@ -45,7 +48,7 @@ public class TOAttribute extends AbstractAttribute { } public static TOAttribute create( - T containerSchemaNode, TypeProviderWrapper typeProviderWrapper) { + T containerSchemaNode, TypeProviderWrapper typeProviderWrapper, String packageName) { // Transfer Object: get the leaves Map map = new HashMap<>(); Map attributeNameMap = new HashMap<>(); @@ -55,18 +58,18 @@ public class TOAttribute extends AbstractAttribute { String yangName = dataSchemaNode.getQName().getLocalName(); map.put(yangName, createInnerAttribute(dataSchemaNode, - typeProviderWrapper)); + typeProviderWrapper, packageName)); } catch (IllegalArgumentException e) { throw new IllegalStateException("Unable to create TO", e); } } return new TOAttribute(containerSchemaNode, map, attributeNameMap, - containerSchemaNode.getDescription()); + containerSchemaNode.getDescription(), packageName); } private static AttributeIfc createInnerAttribute( DataSchemaNode dataSchemaNode, - TypeProviderWrapper typeProviderWrapper) { + TypeProviderWrapper typeProviderWrapper, String packageName) { Class type = isAllowedType(dataSchemaNode); if (type.equals(LeafSchemaNode.class)) @@ -74,13 +77,13 @@ public class TOAttribute extends AbstractAttribute { typeProviderWrapper); else if (type.equals(ListSchemaNode.class)) return ListAttribute.create((ListSchemaNode) dataSchemaNode, - typeProviderWrapper); + typeProviderWrapper, packageName); else if (type.equals(LeafListSchemaNode.class)) return ListAttribute.create((LeafListSchemaNode) dataSchemaNode, typeProviderWrapper); else if (type.equals(ContainerSchemaNode.class)) return TOAttribute.create((ContainerSchemaNode) dataSchemaNode, - typeProviderWrapper); + typeProviderWrapper, packageName); throw new IllegalStateException("This should never happen"); } @@ -98,12 +101,13 @@ public class TOAttribute extends AbstractAttribute { private TOAttribute(DataSchemaNode attrNode, Map transferObject, - Map attributeNameMap, String nullableDescription) { + Map attributeNameMap, String nullableDescription, String packageName) { super(attrNode); yangNameToAttributeMap = transferObject; this.attributeNameMap = attributeNameMap; this.nullableDescription = nullableDescription; nullableDefault = null; + this.packageName = packageName; } public Map getAttributeNameMap() { @@ -197,6 +201,12 @@ public class TOAttribute extends AbstractAttribute { + yangNameToAttributeMap + '}'; } + @Override + public Type getType() { + // TODO: ReferencedTypeImpl from Types + return new ReferencedTypeImpl(packageName, getUpperCaseCammelCase()); + } + @Override public CompositeType getOpenType() { String description = getNullableDescription() == null ? getAttributeYangName() @@ -222,6 +232,10 @@ public class TOAttribute extends AbstractAttribute { } } + public String getPackageName() { + return packageName; + } + private static final class FunctionImpl implements Function, OpenType> { private final String[] itemNames; diff --git a/opendaylight/config/yang-jmx-generator/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntryTest.java b/opendaylight/config/yang-jmx-generator/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntryTest.java index 661dbd7da3..e86c876169 100644 --- a/opendaylight/config/yang-jmx-generator/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntryTest.java +++ b/opendaylight/config/yang-jmx-generator/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntryTest.java @@ -7,38 +7,14 @@ */ package org.opendaylight.controller.config.yangjmxgenerator; -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; - -import java.net.URI; -import java.net.URISyntaxException; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.regex.Matcher; - -import javax.management.openmbean.ArrayType; -import javax.management.openmbean.CompositeType; -import javax.management.openmbean.SimpleType; - +import com.google.common.collect.Sets; import org.junit.Before; import org.junit.Test; import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc; import org.opendaylight.controller.config.yangjmxgenerator.attribute.DependencyAttribute; import org.opendaylight.controller.config.yangjmxgenerator.attribute.JavaAttribute; import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListAttribute; +import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListDependenciesAttribute; import org.opendaylight.controller.config.yangjmxgenerator.attribute.TOAttribute; import org.opendaylight.controller.config.yangjmxgenerator.attribute.TypedAttribute; import org.opendaylight.yangtools.binding.generator.util.Types; @@ -48,13 +24,37 @@ import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath; -import com.google.common.collect.Sets; +import javax.management.openmbean.ArrayType; +import javax.management.openmbean.CompositeType; +import javax.management.openmbean.SimpleType; +import java.net.URI; +import java.net.URISyntaxException; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; public class ModuleMXBeanEntryTest extends AbstractYangTest { public static final String EVENTBUS_MXB_NAME = "eventbus"; public static final String ASYNC_EVENTBUS_MXB_NAME = "async-eventbus"; public static final String THREADFACTORY_NAMING_MXB_NAME = "threadfactory-naming"; public static final String THREADPOOL_DYNAMIC_MXB_NAME = "threadpool-dynamic"; + public static final String THREADPOOL_REGISTRY_IMPL_NAME = "threadpool-registry-impl"; public static final String BGP_LISTENER_IMPL_MXB_NAME = "bgp-listener-impl"; @@ -87,7 +87,7 @@ public class ModuleMXBeanEntryTest extends AbstractYangTest { assertNotNull(namesToMBEs); Set expectedMXBeanNames = Sets.newHashSet(EVENTBUS_MXB_NAME, ASYNC_EVENTBUS_MXB_NAME, THREADFACTORY_NAMING_MXB_NAME, - THREADPOOL_DYNAMIC_MXB_NAME); + THREADPOOL_DYNAMIC_MXB_NAME, THREADPOOL_REGISTRY_IMPL_NAME); assertThat(namesToMBEs.keySet(), is(expectedMXBeanNames)); return namesToMBEs; } @@ -299,6 +299,15 @@ public class ModuleMXBeanEntryTest extends AbstractYangTest { } } + { // test multiple dependencies + ModuleMXBeanEntry threadPoolRegistry = namesToMBEs.get(THREADPOOL_REGISTRY_IMPL_NAME); + Map attributes = threadPoolRegistry.getAttributes(); + assertEquals(1, attributes.size()); + AttributeIfc threadpoolsAttr = attributes.get("threadpools"); + assertNotNull(threadpoolsAttr); + assertTrue(threadpoolsAttr instanceof ListDependenciesAttribute); + ListDependenciesAttribute threadpools = (ListDependenciesAttribute) threadpoolsAttr; + } } } diff --git a/opendaylight/config/yang-jmx-generator/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/SchemaContextTest.java b/opendaylight/config/yang-jmx-generator/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/SchemaContextTest.java index 24c025755b..14ec7e0fdc 100644 --- a/opendaylight/config/yang-jmx-generator/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/SchemaContextTest.java +++ b/opendaylight/config/yang-jmx-generator/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/SchemaContextTest.java @@ -100,10 +100,15 @@ public class SchemaContextTest extends AbstractYangTest { @Test public void testReadingIdentities_threadsJavaModule() { - Map> expectedIdentitiesToBases = ImmutableMap - .of("eventbus", Optional.of(MODULE_TYPE_Q_NAME), "async-eventbus", Optional.of(MODULE_TYPE_Q_NAME), - "threadfactory-naming", Optional.of(MODULE_TYPE_Q_NAME), "threadpool-dynamic", - Optional.of(MODULE_TYPE_Q_NAME), "thread-rpc-context", Optional.absent()); + Map> expectedIdentitiesToBases = new HashMap(){{ + put(ModuleMXBeanEntryTest.EVENTBUS_MXB_NAME, Optional.of(MODULE_TYPE_Q_NAME)); + put(ModuleMXBeanEntryTest.ASYNC_EVENTBUS_MXB_NAME, Optional.of(MODULE_TYPE_Q_NAME)); + put(ModuleMXBeanEntryTest.THREADFACTORY_NAMING_MXB_NAME, Optional.of(MODULE_TYPE_Q_NAME)); + put(ModuleMXBeanEntryTest.THREADPOOL_DYNAMIC_MXB_NAME, Optional.of(MODULE_TYPE_Q_NAME)); + put("thread-rpc-context", Optional.absent()); + put(ModuleMXBeanEntryTest.THREADPOOL_REGISTRY_IMPL_NAME, Optional.of(MODULE_TYPE_Q_NAME)); + }}; + assertAllIdentitiesAreExpected(threadsJavaModule, expectedIdentitiesToBases); } diff --git a/opendaylight/config/yang-jmx-generator/src/test/resources/test-config-threads-java.yang b/opendaylight/config/yang-jmx-generator/src/test/resources/test-config-threads-java.yang index 2972cec04f..4af5b9569a 100644 --- a/opendaylight/config/yang-jmx-generator/src/test/resources/test-config-threads-java.yang +++ b/opendaylight/config/yang-jmx-generator/src/test/resources/test-config-threads-java.yang @@ -241,4 +241,25 @@ module config-threads-java { } } } + + identity threadpool-registry-impl { + base config:module-type; + config:java-name-prefix ThreadPoolRegistryImpl; + } + + augment "/config:modules/config:module/config:configuration" { + case threadpool-registry-impl { + when "/config:modules/config:module/config:type = 'threadpool-registry-impl'"; + + // list of dependencies: + list threadpools { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity th2:threadpool; + } + } + } + } + } } 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 ba5021ea09..bd83a4cc70 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 @@ -242,6 +242,15 @@ module config-test-impl { } } } + + list testing-deps { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity test:testing; + } + } + } } } diff --git a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowConfig.java b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowConfig.java index de7597730f..3ec9f8443a 100644 --- a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowConfig.java +++ b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowConfig.java @@ -836,21 +836,14 @@ public class FlowConfig implements Serializable { sstr = Pattern.compile("OUTPUT=(.*)").matcher(actiongrp); if (sstr.matches()) { for (String t : sstr.group(1).split(",")) { - Matcher n = Pattern.compile("(?:(\\d+))").matcher(t); - if (n.matches()) { - String port = n.group(1); - if (port != null) { - if (!isPortValid(sw, port)) { - String msg = String.format("Output port %s is not valid for this switch", port); - if (!containerName.equals(GlobalConstants.DEFAULT.toString())) { - msg += " in Container " + containerName; - } - return new Status(StatusCode.BADREQUEST, msg); + if (t != null) { + if (!isPortValid(sw, t)) { + String msg = String.format("Output port %s is not valid for this switch", t); + if (!containerName.equals(GlobalConstants.DEFAULT.toString())) { + msg += " in Container " + containerName; } + return new Status(StatusCode.BADREQUEST, msg); } - } else { - String msg = String.format("Output port %s is not valid", t); - return new Status(StatusCode.BADREQUEST, msg); } } continue; @@ -859,21 +852,15 @@ public class FlowConfig implements Serializable { sstr = Pattern.compile("ENQUEUE=(.*)").matcher(actiongrp); if (sstr.matches()) { for (String t : sstr.group(1).split(",")) { - Matcher n = Pattern.compile("(?:(\\d+:\\d+))").matcher(t); - if (n.matches()) { - if (n.group(1) != null) { - String port = n.group(1).split(":")[0]; - if (!isPortValid(sw, port)) { - String msg = String.format("Output port %d is not valid for this switch", port); - if (!containerName.equals(GlobalConstants.DEFAULT.toString())) { - msg += " in Container " + containerName; - } - return new Status(StatusCode.BADREQUEST, msg); + if (t != null) { + String port = t.split(":")[0]; + if (!isPortValid(sw, port)) { + String msg = String.format("Output port %d is not valid for this switch", port); + if (!containerName.equals(GlobalConstants.DEFAULT.toString())) { + msg += " in Container " + containerName; } + return new Status(StatusCode.BADREQUEST, msg); } - } else { - String msg = String.format("Enqueue port %s is not valid", t); - return new Status(StatusCode.BADREQUEST, msg); } } continue; @@ -1102,12 +1089,9 @@ public class FlowConfig implements Serializable { sstr = Pattern.compile(ActionType.OUTPUT + "=(.*)").matcher(actiongrp); if (sstr.matches()) { for (String t : sstr.group(1).split(",")) { - Matcher n = Pattern.compile("(?:(\\d+))").matcher(t); - if (n.matches()) { - if (n.group(1) != null) { - String nc = String.format("%s|%s@%s", node.getType(), n.group(1), node.toString()); - actionList.add(new Output(NodeConnector.fromString(nc))); - } + if (t != null) { + String nc = String.format("%s|%s@%s", node.getType(), t, node.toString()); + actionList.add(new Output(NodeConnector.fromString(nc))); } } continue; @@ -1116,17 +1100,14 @@ public class FlowConfig implements Serializable { sstr = Pattern.compile(ActionType.ENQUEUE + "=(.*)").matcher(actiongrp); if (sstr.matches()) { for (String t : sstr.group(1).split(",")) { - Matcher n = Pattern.compile("(?:(\\d+:\\d+))").matcher(t); - if (n.matches()) { - if (n.group(1) != null) { - String parts[] = n.group(1).split(":"); - String nc = String.format("%s|%s@%s", node.getType(), parts[0], node.toString()); - if (parts.length == 1) { - actionList.add(new Enqueue(NodeConnector.fromString(nc))); - } else { - actionList - .add(new Enqueue(NodeConnector.fromString(nc), Integer.parseInt(parts[1]))); - } + if (t != null) { + String parts[] = t.split(":"); + String nc = String.format("%s|%s@%s", node.getType(), parts[0], node.toString()); + if (parts.length == 1) { + actionList.add(new Enqueue(NodeConnector.fromString(nc))); + } else { + actionList + .add(new Enqueue(NodeConnector.fromString(nc), Integer.parseInt(parts[1]))); } } } diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/statistics/DataBrokerRuntimeMXBeanImpl.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/statistics/DataBrokerRuntimeMXBeanImpl.java index a1a24ebc8a..5da084e9bd 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/statistics/DataBrokerRuntimeMXBeanImpl.java +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/statistics/DataBrokerRuntimeMXBeanImpl.java @@ -1,14 +1,15 @@ package org.opendaylight.controller.config.yang.md.sal.binding.statistics; +import org.opendaylight.controller.config.yang.md.sal.binding.impl.Data; import org.opendaylight.controller.config.yang.md.sal.binding.impl.DataBrokerImplRuntimeMXBean; import org.opendaylight.controller.config.yang.md.sal.binding.impl.Transactions; import org.opendaylight.controller.sal.binding.impl.DataBrokerImpl; public class DataBrokerRuntimeMXBeanImpl extends DataBrokerImpl implements DataBrokerImplRuntimeMXBean { - private Transactions transactions = new Transactions(); + private final Transactions transactions = new Transactions(); + private final Data data = new Data(); - @Override public Transactions getTransactions() { transactions.setCreated(getCreatedTransactionsCount().get()); transactions.setSubmitted(getSubmittedTransactionsCount().get()); @@ -16,4 +17,14 @@ public class DataBrokerRuntimeMXBeanImpl extends DataBrokerImpl implements DataB transactions.setFailed(getFailedTransactionsCount().get()); return transactions; } + + @Override + public Data getData() { + transactions.setCreated(getCreatedTransactionsCount().get()); + transactions.setSubmitted(getSubmittedTransactionsCount().get()); + transactions.setSuccessful(getFinishedTransactionsCount().get()); + transactions.setFailed(getFailedTransactionsCount().get()); + data.setTransactions(transactions); + return data; + } } diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/yang/opendaylight-binding-broker-impl.yang b/opendaylight/md-sal/sal-binding-broker/src/main/yang/opendaylight-binding-broker-impl.yang index 9da073f71b..b040aa025e 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/yang/opendaylight-binding-broker-impl.yang +++ b/opendaylight/md-sal/sal-binding-broker/src/main/yang/opendaylight-binding-broker-impl.yang @@ -121,7 +121,9 @@ module opendaylight-sal-binding-broker-impl { augment "/config:modules/config:module/config:state" { case binding-data-broker { when "/config:modules/config:module/config:type = 'binding-data-broker'"; - uses common:data-state; + container data { + uses common:data-state; + } } } augment "/config:modules/config:module/config:state" { diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomBrokerImplModule.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomBrokerImplModule.java index 050966faa0..9a2a90445e 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomBrokerImplModule.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomBrokerImplModule.java @@ -9,10 +9,12 @@ */ package org.opendaylight.controller.config.yang.md.sal.dom.impl; +import org.opendaylight.controller.config.yang.md.sal.dom.statistics.DomBrokerRuntimeMXBeanImpl; import org.opendaylight.controller.sal.core.api.data.DataStore; import org.opendaylight.controller.sal.dom.broker.BrokerConfigActivator; import org.opendaylight.controller.sal.dom.broker.BrokerImpl; import org.osgi.framework.BundleContext; + import static com.google.common.base.Preconditions.*; /** @@ -37,14 +39,15 @@ public final class DomBrokerImplModule extends org.opendaylight.controller.confi checkArgument(getDataStore() != null, "Data Store needs to be provided for DomBroker"); } - - @Override public java.lang.AutoCloseable createInstance() { - BrokerImpl broker = new BrokerImpl(); - BrokerConfigActivator activator = new BrokerConfigActivator(); - DataStore store = getDataStoreDependency(); - activator.start(broker, store,getBundleContext()); + final BrokerImpl broker = new BrokerImpl(); + final BrokerConfigActivator activator = new BrokerConfigActivator(); + final DataStore store = getDataStoreDependency(); + activator.start(broker, store, getBundleContext()); + + final DomBrokerImplRuntimeMXBean domBrokerRuntimeMXBean = new DomBrokerRuntimeMXBeanImpl(activator.getDataService()); + getRootRuntimeBeanRegistratorWrapper().register(domBrokerRuntimeMXBean); return broker; } diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/statistics/DomBrokerRuntimeMXBeanImpl.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/statistics/DomBrokerRuntimeMXBeanImpl.java new file mode 100644 index 0000000000..bc13979d67 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/statistics/DomBrokerRuntimeMXBeanImpl.java @@ -0,0 +1,36 @@ +package org.opendaylight.controller.config.yang.md.sal.dom.statistics; + +import org.opendaylight.controller.config.yang.md.sal.dom.impl.Data; +import org.opendaylight.controller.config.yang.md.sal.dom.impl.DomBrokerImplRuntimeMXBean; +import org.opendaylight.controller.config.yang.md.sal.dom.impl.Transactions; +import org.opendaylight.controller.sal.dom.broker.DataBrokerImpl; + +public class DomBrokerRuntimeMXBeanImpl implements + DomBrokerImplRuntimeMXBean { + + private final DataBrokerImpl dataService; + private final Transactions transactions = new Transactions(); + private final Data data = new Data(); + + public DomBrokerRuntimeMXBeanImpl(DataBrokerImpl dataService) { + this.dataService = dataService; + } + + public Transactions getTransactions() { + transactions.setCreated(dataService.getCreatedTransactionsCount().get()); + transactions.setSubmitted(dataService.getSubmittedTransactionsCount().get()); + transactions.setSuccessful(dataService.getFinishedTransactionsCount().get()); + transactions.setFailed(dataService.getFailedTransactionsCount().get()); + return transactions; + } + + @Override + public Data getData() { + transactions.setCreated(dataService.getCreatedTransactionsCount().get()); + transactions.setSubmitted(dataService.getSubmittedTransactionsCount().get()); + transactions.setSuccessful(dataService.getFinishedTransactionsCount().get()); + transactions.setFailed(dataService.getFailedTransactionsCount().get()); + data.setTransactions(transactions); + return data; + } +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerConfigActivator.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerConfigActivator.xtend index da7cccb156..482cfa959f 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerConfigActivator.xtend +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerConfigActivator.xtend @@ -19,15 +19,16 @@ class BrokerConfigActivator implements AutoCloseable { private static val ROOT = InstanceIdentifier.builder().toInstance(); + + @Property + private var DataBrokerImpl dataService; private var ServiceRegistration schemaReg; private var ServiceRegistration dataReg; private var ServiceRegistration dataProviderReg; private var ServiceRegistration mountReg; private var ServiceRegistration mountProviderReg; - private var SchemaServiceImpl schemaService; - private var DataBrokerImpl dataService; private var MountPointManagerImpl mountService; SchemaAwareDataStoreAdapter wrappedStore diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataBrokerImpl.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataBrokerImpl.java index ac5313a9ca..56eae97848 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataBrokerImpl.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataBrokerImpl.java @@ -2,7 +2,6 @@ package org.opendaylight.controller.sal.dom.broker; import java.util.concurrent.atomic.AtomicLong; -import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent; import org.opendaylight.controller.md.sal.common.api.data.DataReader; import org.opendaylight.controller.md.sal.common.impl.service.AbstractDataBroker; import org.opendaylight.controller.sal.common.DataStoreIdentifier; @@ -15,17 +14,23 @@ import org.opendaylight.yangtools.yang.data.api.CompositeNode; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; public class DataBrokerImpl extends AbstractDataBroker implements - DataProviderService { + DataProviderService, AutoCloseable { + private AtomicLong nextTransaction = new AtomicLong(); + private final AtomicLong createdTransactionsCount = new AtomicLong(); + public DataBrokerImpl() { setDataReadRouter(new DataReaderRouter()); } - - private AtomicLong nextTransaction = new AtomicLong(); + + public AtomicLong getCreatedTransactionsCount() { + return createdTransactionsCount; + } @Override public DataTransactionImpl beginTransaction() { String transactionId = "DOM-" + nextTransaction.getAndIncrement(); + createdTransactionsCount.getAndIncrement(); return new DataTransactionImpl(transactionId,this); } @@ -66,4 +71,9 @@ public class DataBrokerImpl extends AbstractDataBroker { } else if (attributeIfc instanceof DependencyAttribute) { return caseDependencyAttribute(((DependencyAttribute) attributeIfc).getOpenType()); } else if (attributeIfc instanceof ListAttribute) { - return caseListAttribute(((ListAttribute) attributeIfc).getOpenType()); + return caseListAttribute((ArrayType) attributeIfc.getOpenType()); + } else if (attributeIfc instanceof ListDependenciesAttribute) { + return caseListDependeciesAttribute((ArrayType) attributeIfc.getOpenType()); } else if (attributeIfc instanceof TOAttribute) { return caseTOAttribute(((TOAttribute) attributeIfc).getOpenType()); } @@ -45,6 +48,7 @@ public abstract class AttributeIfcSwitchStatement { throw getIllegalArgumentException(attributeIfc); } + private IllegalArgumentException getIllegalArgumentException(AttributeIfc attributeIfc) { return new IllegalArgumentException("Unknown attribute type " + attributeIfc.getClass() + ", " + attributeIfc + " with open type:" + attributeIfc.getOpenType()); @@ -74,6 +78,7 @@ public abstract class AttributeIfcSwitchStatement { protected abstract T caseListAttribute(ArrayType openType); + protected abstract T caseListDependeciesAttribute(ArrayType openType); private static class UnknownOpenTypeException extends RuntimeException { public UnknownOpenTypeException(String message) { diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/ObjectXmlReader.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/ObjectXmlReader.java index bc3c74a88f..e2ea404e21 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/ObjectXmlReader.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/ObjectXmlReader.java @@ -12,6 +12,7 @@ import com.google.common.base.Preconditions; import com.google.common.collect.Maps; import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc; import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListAttribute; +import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListDependenciesAttribute; import org.opendaylight.controller.config.yangjmxgenerator.attribute.TOAttribute; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.AttributeIfcSwitchStatement; @@ -86,4 +87,11 @@ public class ObjectXmlReader extends AttributeIfcSwitchStatement openType) { + Preconditions.checkState(lastAttribute instanceof ListDependenciesAttribute); + AttributeReadingStrategy innerStrategy = caseDependencyAttribute(SimpleType.OBJECTNAME); + return new ArrayAttributeReadingStrategy(lastAttribute.getNullableDefault(), innerStrategy); + } + } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/ObjectMapper.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/ObjectMapper.java index 853197c0b0..6e5bd0d3fe 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/ObjectMapper.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/ObjectMapper.java @@ -13,6 +13,7 @@ import com.google.common.collect.Maps; import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc; import org.opendaylight.controller.config.yangjmxgenerator.attribute.DependencyAttribute; import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListAttribute; +import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListDependenciesAttribute; import org.opendaylight.controller.config.yangjmxgenerator.attribute.TOAttribute; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.AttributeIfcSwitchStatement; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services; @@ -121,4 +122,10 @@ public class ObjectMapper extends AttributeIfcSwitchStatement> caseListDependeciesAttribute(ArrayType openType) { + Preconditions.checkState(lastAttribute instanceof ListDependenciesAttribute); + return new ArrayAttributeMappingStrategy(openType, caseDependencyAttribute(SimpleType.OBJECTNAME)); + } + } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/ObjectResolver.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/ObjectResolver.java index c321164cf6..f5a2511260 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/ObjectResolver.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/ObjectResolver.java @@ -12,6 +12,7 @@ import com.google.common.base.Preconditions; import com.google.common.collect.Maps; import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc; import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListAttribute; +import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListDependenciesAttribute; import org.opendaylight.controller.config.yangjmxgenerator.attribute.TOAttribute; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.AttributeIfcSwitchStatement; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services; @@ -109,4 +110,10 @@ public class ObjectResolver extends AttributeIfcSwitchStatement> caseListDependeciesAttribute(ArrayType openType) { + Preconditions.checkState(lastAttribute instanceof ListDependenciesAttribute); + return new ArrayAttributeResolvingStrategy(caseDependencyAttribute(SimpleType.OBJECTNAME), openType); + } + } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/ObjectXmlWriter.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/ObjectXmlWriter.java index 99e969970c..ad587ea987 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/ObjectXmlWriter.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/ObjectXmlWriter.java @@ -12,6 +12,7 @@ import com.google.common.base.Preconditions; import com.google.common.collect.Maps; import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc; import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListAttribute; +import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListDependenciesAttribute; import org.opendaylight.controller.config.yangjmxgenerator.attribute.TOAttribute; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.AttributeIfcSwitchStatement; import org.w3c.dom.Document; @@ -96,4 +97,11 @@ public class ObjectXmlWriter extends AttributeIfcSwitchStatement openType) { + Preconditions.checkState(lastAttribute instanceof ListDependenciesAttribute); + AttributeWritingStrategy innerStrategy = caseDependencyAttribute(SimpleType.OBJECTNAME); + return new ArrayAttributeWritingStrategy(innerStrategy); + } + } 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 e4fa6f504b..f522668733 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 @@ -284,8 +284,13 @@ public final class Services { public static ServiceInstance fromString(String instanceId) { instanceId = instanceId.trim(); Matcher matcher = p.matcher(instanceId); + if(matcher.matches() == false) { + matcher = pDeprecated.matcher(instanceId); + } + Preconditions.checkArgument(matcher.matches(), "Unexpected format for provider, expected " + p.toString() - + " but was " + instanceId); + + " or " + pDeprecated.toString() + " but was " + instanceId); + String factoryName = matcher.group(1); String instanceName = matcher.group(2); return new ServiceInstance(factoryName, instanceName); @@ -310,16 +315,25 @@ public final class Services { return instanceName; } - private static final String blueprint = "/" + XmlNetconfConstants.CONFIG_KEY + "/" + private static final String blueprint = "/" + XmlNetconfConstants.MODULES_KEY + "/" + XmlNetconfConstants.MODULE_KEY + "[" - + XmlNetconfConstants.NAME_KEY + "='%s']/" + XmlNetconfConstants.INSTANCE_KEY + "[" + + XmlNetconfConstants.TYPE_KEY + "='%s'][" + XmlNetconfConstants.NAME_KEY + "='%s']"; - private static final String blueprintR = "/" + XmlNetconfConstants.CONFIG_KEY + "/" + // TODO unify with xpath in RuntimeRpc + + // Previous version of xpath, needs to be supported for backwards compatibility (persisted configs by config-persister) + private static final String blueprintRDeprecated = "/" + XmlNetconfConstants.CONFIG_KEY + "/" + XmlNetconfConstants.MODULES_KEY + "/" + XmlNetconfConstants.MODULE_KEY + "\\[" + XmlNetconfConstants.NAME_KEY + "='%s'\\]/" + XmlNetconfConstants.INSTANCE_KEY + "\\[" + XmlNetconfConstants.NAME_KEY + "='%s'\\]"; + private static final String blueprintR = "/" + + XmlNetconfConstants.MODULES_KEY + "/" + XmlNetconfConstants.MODULE_KEY + "\\[" + + XmlNetconfConstants.TYPE_KEY + "='%s'\\]\\[" + + XmlNetconfConstants.NAME_KEY + "='%s'\\]"; + + private static final Pattern pDeprecated = Pattern.compile(String.format(blueprintRDeprecated, "(.+)", "(.+)")); private static final Pattern p = Pattern.compile(String.format(blueprintR, "(.+)", "(.+)")); @Override diff --git a/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java b/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java index d91e38db33..35fa0428ec 100644 --- a/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java +++ b/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java @@ -132,10 +132,12 @@ public class NetconfMappingTest extends AbstractConfigTest { // check after edit commit(); Element response = getConfigRunning(); + System.err.println(XmlUtil.toString(response)); checkBinaryLeafEdited(response); checkTypeConfigAttribute(response); checkTypedefs(response); + checkTestingDeps(response); checkEnum(response); checkBigDecimal(response); @@ -163,11 +165,6 @@ public class NetconfMappingTest extends AbstractConfigTest { verifyNoMoreInteractions(netconfOperationRouter); } - private void checkBigDecimal(Element response) { - int size = response.getElementsByTagName("sleep-factor").getLength(); - assertEquals(1, size); - } - private void closeSession() throws NetconfDocumentedException, ParserConfigurationException, SAXException, IOException { DefaultCloseSession closeOp = new DefaultCloseSession(NETCONF_SESSION_ID); @@ -394,6 +391,17 @@ public class NetconfMappingTest extends AbstractConfigTest { fail("Enum attribute " + enumName + ":" + enumContent + " not present in " + XmlUtil.toString(response)); } + private void checkTestingDeps(Element response) { + int testingDepsSize = response.getElementsByTagName("testing-deps").getLength(); + assertEquals(2, testingDepsSize); + } + + private void checkBigDecimal(Element response) { + int size = response.getElementsByTagName("sleep-factor").getLength(); + assertEquals(1, size); + } + + private void checkTypeConfigAttribute(Element response) { XmlElement modulesElement = XmlElement.fromDomElement(response).getOnlyChildElement("data") 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 99b7ee60a2..1c3ac7a455 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 @@ -8,45 +8,22 @@ package org.opendaylight.controller.netconf.persist.impl; -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; -import com.google.common.collect.Sets; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import java.io.Closeable; -import java.io.IOException; -import java.io.InputStream; -import java.net.InetSocketAddress; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; -import java.util.regex.Pattern; -import javax.annotation.concurrent.ThreadSafe; -import javax.management.InstanceNotFoundException; -import javax.management.MBeanServerConnection; -import javax.management.Notification; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.xml.xpath.XPathConstants; -import javax.xml.xpath.XPathExpression; -import org.opendaylight.controller.config.api.ConflictingVersionException; -import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder; -import org.opendaylight.controller.config.persist.api.Persister; -import org.opendaylight.controller.netconf.api.NetconfMessage; import org.opendaylight.controller.netconf.api.jmx.CommitJMXNotification; import org.opendaylight.controller.netconf.api.jmx.DefaultCommitOperationMXBean; import org.opendaylight.controller.netconf.api.jmx.NetconfJMXNotification; import org.opendaylight.controller.netconf.client.NetconfClient; -import org.opendaylight.controller.netconf.client.NetconfClientDispatcher; -import org.opendaylight.controller.netconf.util.xml.XMLNetconfUtil; -import org.opendaylight.controller.netconf.util.xml.XmlElement; -import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants; -import org.opendaylight.controller.netconf.util.xml.XmlUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.xml.sax.SAXException; + +import javax.annotation.concurrent.ThreadSafe; +import javax.management.InstanceNotFoundException; +import javax.management.MBeanServerConnection; +import javax.management.Notification; +import javax.management.NotificationListener; +import javax.management.ObjectName; +import java.io.Closeable; +import java.io.IOException; +import java.util.regex.Pattern; /** * Responsible for listening for notifications from netconf containing latest @@ -57,163 +34,27 @@ import org.xml.sax.SAXException; 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; - - private NetconfClientDispatcher netconfClientDispatcher; - private NetconfClient netconfClient; - - private final Persister persister; - private final MBeanServerConnection mbeanServer; - - - private final ObjectName on = DefaultCommitOperationMXBean.objectName; - - public static final long DEFAULT_TIMEOUT = 120000L;// 120 seconds until netconf must be stable - private final long timeout; + private final MBeanServerConnection mBeanServerConnection; + private final NetconfClient netconfClient; + private final PersisterAggregator persisterAggregator; private final Pattern ignoredMissingCapabilityRegex; - public ConfigPersisterNotificationHandler(Persister persister, InetSocketAddress address, - MBeanServerConnection mbeanServer, Pattern ignoredMissingCapabilityRegex) { - this(persister, address, mbeanServer, DEFAULT_TIMEOUT, ignoredMissingCapabilityRegex); - - } - - public ConfigPersisterNotificationHandler(Persister persister, InetSocketAddress address, - MBeanServerConnection mbeanServer, long timeout, Pattern ignoredMissingCapabilityRegex) { - this.persister = persister; - this.address = address; - this.mbeanServer = mbeanServer; - this.timeout = timeout; - - this.nettyThreadgroup = new NioEventLoopGroup(); + public ConfigPersisterNotificationHandler(MBeanServerConnection mBeanServerConnection, NetconfClient netconfClient, + PersisterAggregator persisterAggregator, Pattern ignoredMissingCapabilityRegex) { + this.mBeanServerConnection = mBeanServerConnection; + this.netconfClient = netconfClient; + this.persisterAggregator = persisterAggregator; this.ignoredMissingCapabilityRegex = ignoredMissingCapabilityRegex; } - public void init() throws InterruptedException { - Optional maybeConfig = loadLastConfig(); - - if (maybeConfig.isPresent()) { - logger.debug("Last config found {}", persister); - ConflictingVersionException lastException = null; - pushLastConfigWithRetries(maybeConfig, lastException); - - } else { - // this ensures that netconf is initialized, this is first - // connection - // this means we can register as listener for commit - registerToNetconf(Collections.emptySet()); - - logger.info("No last config provided by backend storage {}", persister); - } + public void init() { registerAsJMXListener(); } - private void pushLastConfigWithRetries(Optional maybeConfig, ConflictingVersionException lastException) throws InterruptedException { - int maxAttempts = 30; - for(int i = 0 ; i < maxAttempts; i++) { - registerToNetconf(maybeConfig.get().getCapabilities()); - - final String configSnapshot = maybeConfig.get().getConfigSnapshot(); - logger.trace("Pushing following xml to netconf {}", configSnapshot); - try { - pushLastConfig(XmlUtil.readXmlToElement(configSnapshot)); - return; - } catch(ConflictingVersionException e) { - closeClientAndDispatcher(netconfClient, netconfClientDispatcher); - lastException = e; - Thread.sleep(1000); - } catch (SAXException | IOException e) { - throw new IllegalStateException("Unable to load last config", e); - } - } - throw new IllegalStateException("Failed to push configuration, maximum attempt count has been reached: " - + maxAttempts, lastException); - } - - private synchronized long registerToNetconf(Set expectedCaps) throws InterruptedException { - - Set currentCapabilities = Sets.newHashSet(); - - // TODO think about moving capability subset check to netconf client - // could be utilized by integration tests - - long pollingStart = System.currentTimeMillis(); - int delay = 5000; - - int attempt = 0; - - long deadline = pollingStart + timeout; - while (System.currentTimeMillis() < deadline) { - attempt++; - netconfClientDispatcher = new NetconfClientDispatcher(nettyThreadgroup, nettyThreadgroup); - try { - netconfClient = new NetconfClient(this.toString(), address, delay, netconfClientDispatcher); - } catch (IllegalStateException e) { - logger.debug("Netconf {} was not initialized or is not stable, attempt {}", address, attempt, e); - netconfClientDispatcher.close(); - Thread.sleep(delay); - continue; - } - currentCapabilities = netconfClient.getCapabilities(); - - if (isSubset(currentCapabilities, expectedCaps)) { - logger.debug("Hello from netconf stable with {} capabilities", currentCapabilities); - long currentSessionId = netconfClient.getSessionId(); - logger.info("Session id received from netconf server: {}", currentSessionId); - return currentSessionId; - } - - - - logger.debug("Polling hello from netconf, attempt {}, capabilities {}", attempt, currentCapabilities); - - closeClientAndDispatcher(netconfClient, netconfClientDispatcher); - - Thread.sleep(delay); - } - Set allNotFound = new HashSet<>(expectedCaps); - allNotFound.removeAll(currentCapabilities); - logger.error("Netconf server did not provide required capabilities. Expected but not found: {}, all expected {}, current {}", - allNotFound, expectedCaps ,currentCapabilities); - throw new RuntimeException("Netconf server did not provide required capabilities. Expected but not found:" + allNotFound); - - } - - private static void closeClientAndDispatcher(Closeable client, Closeable dispatcher) { - Exception fromClient = null; - try { - client.close(); - } catch (Exception e) { - fromClient = e; - } finally { - try { - dispatcher.close(); - } catch (Exception e) { - if (fromClient != null) { - e.addSuppressed(fromClient); - } - - throw new RuntimeException("Error closing temporary client ", e); - } - } - } - - private boolean isSubset(Set currentCapabilities, Set expectedCaps) { - for (String exCap : expectedCaps) { - if (currentCapabilities.contains(exCap) == false) - return false; - } - return true; - } - private void registerAsJMXListener() { logger.trace("Called registerAsJMXListener"); try { - mbeanServer.addNotificationListener(on, this, null, null); + mBeanServerConnection.addNotificationListener(DefaultCommitOperationMXBean.objectName, this, null, null); } catch (InstanceNotFoundException | IOException e) { throw new RuntimeException("Cannot register as JMX listener to netconf", e); } @@ -242,7 +83,7 @@ public class ConfigPersisterNotificationHandler implements NotificationListener, private void handleAfterCommitNotification(final CommitJMXNotification notification) { try { - persister.persistConfig(new CapabilityStrippingConfigSnapshotHolder(notification.getConfigSnapshot(), + persisterAggregator.persistConfig(new CapabilityStrippingConfigSnapshotHolder(notification.getConfigSnapshot(), notification.getCapabilities(), ignoredMissingCapabilityRegex)); logger.info("Configuration persisted successfully"); } catch (IOException e) { @@ -250,137 +91,21 @@ public class ConfigPersisterNotificationHandler implements NotificationListener, } } - private Optional loadLastConfig() { - Optional maybeConfigElement; - try { - maybeConfigElement = persister.loadLastConfig(); - } catch (IOException e) { - throw new RuntimeException("Unable to load configuration", e); - } - return maybeConfigElement; - } - - private synchronized void pushLastConfig(Element xmlToBePersisted) throws ConflictingVersionException { - logger.info("Pushing last configuration to netconf"); - StringBuilder response = new StringBuilder("editConfig response = {"); - - - NetconfMessage message = createEditConfigMessage(xmlToBePersisted, "/netconfOp/editConfig.xml"); - - // sending message to netconf - 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)); - element = element.getOnlyChildElement(); - - checkIsOk(element, responseMessage); - response.append(XmlUtil.toString(responseMessage.getDocument())); - response.append("}"); - 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)); - element = element.getOnlyChildElement(); - - checkIsOk(element, responseMessage); - response.append("commit response = {"); - response.append(XmlUtil.toString(responseMessage.getDocument())); - response.append("}"); - logger.info("Last configuration loaded successfully"); - logger.trace("Detailed message {}", response); - } - - static void checkIsOk(XmlElement element, NetconfMessage responseMessage) throws ConflictingVersionException { - if (element.getName().equals(XmlNetconfConstants.OK)) { - return; - } - - if (element.getName().equals(XmlNetconfConstants.RPC_ERROR)) { - logger.warn("Can not load last configuration, operation failed"); - // is it ConflictingVersionException ? - XPathExpression xPathExpression = XMLNetconfUtil.compileXPath("/netconf:rpc-reply/netconf:rpc-error/netconf:error-info/netconf:error"); - String error = (String) XmlUtil.evaluateXPath(xPathExpression, element.getDomElement(), XPathConstants.STRING); - if (error!=null && error.contains(ConflictingVersionException.class.getCanonicalName())) { - throw new ConflictingVersionException(error); - } - throw new IllegalStateException("Can not load last configuration, operation failed: " - + XmlUtil.toString(responseMessage.getDocument())); - } - - logger.warn("Can not load last configuration. Operation failed."); - throw new IllegalStateException("Can not load last configuration. Operation failed: " - + XmlUtil.toString(responseMessage.getDocument())); - } - - private static NetconfMessage createEditConfigMessage(Element dataElement, String editConfigResourcename) { - try (InputStream stream = ConfigPersisterNotificationHandler.class.getResourceAsStream(editConfigResourcename)) { - Preconditions.checkNotNull(stream, "Unable to load resource " + editConfigResourcename); - - Document doc = XmlUtil.readXmlToDocument(stream); - - doc.getDocumentElement(); - XmlElement editConfigElement = XmlElement.fromDomDocument(doc).getOnlyChildElement(); - XmlElement configWrapper = editConfigElement.getOnlyChildElement(XmlNetconfConstants.CONFIG_KEY); - editConfigElement.getDomElement().removeChild(configWrapper.getDomElement()); - for (XmlElement el : XmlElement.fromDomElement(dataElement).getChildElements()) { - configWrapper.appendChild((Element) doc.importNode(el.getDomElement(), true)); - } - editConfigElement.appendChild(configWrapper.getDomElement()); - return new NetconfMessage(doc); - } catch (IOException | SAXException e) { - throw new RuntimeException("Unable to parse message from resources " + editConfigResourcename, e); - } - } - - private NetconfMessage getNetconfMessageFromResource(String resource) { - try (InputStream stream = getClass().getResourceAsStream(resource)) { - Preconditions.checkNotNull(stream, "Unable to load resource " + resource); - return new NetconfMessage(XmlUtil.readXmlToDocument(stream)); - } catch (SAXException | IOException e) { - throw new RuntimeException("Unable to parse message from resources " + resource, e); - } - } - @Override public synchronized void close() { - // TODO persister is received from constructor, should not be closed - // here - try { - persister.close(); - } catch (Exception e) { - logger.warn("Unable to close config persister {}", persister, e); - } - - if (netconfClient != null) { - try { - netconfClient.close(); - } catch (Exception e) { - logger.warn("Unable to close connection to netconf {}", netconfClient, e); - } - } - - if (netconfClientDispatcher != null) { - try { - netconfClientDispatcher.close(); - } catch (Exception e) { - logger.warn("Unable to close connection to netconf {}", netconfClientDispatcher, e); - } - } - - try { - nettyThreadgroup.shutdownGracefully(); - } catch (Exception e) { - logger.warn("Unable to close netconf client thread group {}", netconfClientDispatcher, e); - } - // unregister from JMX + ObjectName on = DefaultCommitOperationMXBean.objectName; try { - if (mbeanServer.isRegistered(on)) { - mbeanServer.removeNotificationListener(on, this); + if (mBeanServerConnection.isRegistered(on)) { + mBeanServerConnection.removeNotificationListener(on, this); } } catch (Exception e) { logger.warn("Unable to unregister {} as listener for {}", this, on, e); } } + + public NetconfClient getNetconfClient() { + return netconfClient; + } + } diff --git a/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPusher.java b/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPusher.java new file mode 100644 index 0000000000..044346e2c5 --- /dev/null +++ b/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPusher.java @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.netconf.persist.impl; + +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import io.netty.channel.EventLoopGroup; +import org.opendaylight.controller.config.api.ConflictingVersionException; +import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder; +import org.opendaylight.controller.netconf.api.NetconfMessage; +import org.opendaylight.controller.netconf.client.NetconfClient; +import org.opendaylight.controller.netconf.client.NetconfClientDispatcher; +import org.opendaylight.controller.netconf.util.xml.XmlElement; +import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants; +import org.opendaylight.controller.netconf.util.xml.XmlUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +import javax.annotation.concurrent.Immutable; +import java.io.IOException; +import java.io.InputStream; +import java.net.InetSocketAddress; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +@Immutable +public class ConfigPusher { + 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; + + + public static final long DEFAULT_TIMEOUT = 120000L;// 120 seconds until netconf must be stable + private final long timeout; + + public ConfigPusher(InetSocketAddress address, EventLoopGroup nettyThreadgroup) { + this(address, DEFAULT_TIMEOUT, nettyThreadgroup); + + } + + public ConfigPusher(InetSocketAddress address, long timeout, EventLoopGroup nettyThreadgroup) { + this.address = address; + this.timeout = timeout; + + this.nettyThreadgroup = nettyThreadgroup; + } + + public synchronized NetconfClient init(List configs) throws InterruptedException { + logger.debug("Last config snapshots to be pushed to netconf: {}", configs); + return pushAllConfigs(configs); + } + + private synchronized NetconfClient pushAllConfigs(List configs) throws InterruptedException { + NetconfClient netconfClient = makeNetconfConnection(Collections.emptySet(), Optional.absent()); + for (ConfigSnapshotHolder configSnapshotHolder: configs){ + netconfClient = pushSnapshotWithRetries(configSnapshotHolder, Optional.of(netconfClient)); + } + return netconfClient; + } + + private synchronized NetconfClient pushSnapshotWithRetries(ConfigSnapshotHolder configSnapshotHolder, + Optional oldClientForPossibleReuse) + throws InterruptedException { + + ConflictingVersionException lastException = null; + int maxAttempts = 30; + for(int i = 0 ; i < maxAttempts; i++) { + NetconfClient netconfClient = makeNetconfConnection(configSnapshotHolder.getCapabilities(), oldClientForPossibleReuse); + final String configSnapshot = configSnapshotHolder.getConfigSnapshot(); + logger.trace("Pushing following xml to netconf {}", configSnapshot); + try { + pushLastConfig(configSnapshotHolder, netconfClient); + return netconfClient; + } catch(ConflictingVersionException e) { + Util.closeClientAndDispatcher(netconfClient); + lastException = e; + Thread.sleep(1000); + } catch (SAXException | IOException e) { + throw new IllegalStateException("Unable to load last config", e); + } + } + throw new IllegalStateException("Failed to push configuration, maximum attempt count has been reached: " + + maxAttempts, lastException); + } + + /** + * @param expectedCaps capabilities that server hello must contain. Will retry until all are found or throws RuntimeException. + * If empty set is provided, will only make sure netconf client successfuly connected to the server. + * @param oldClientForPossibleReuse if present, try to get expected capabilities from it before closing it and retrying with + * new client connection. + * @return NetconfClient that has all required capabilities from server. + */ + private synchronized NetconfClient makeNetconfConnection(Set expectedCaps, + Optional oldClientForPossibleReuse) + throws InterruptedException { + + if (oldClientForPossibleReuse.isPresent()) { + NetconfClient oldClient = oldClientForPossibleReuse.get(); + if (Util.isSubset(oldClient, expectedCaps)) { + return oldClient; + } else { + Util.closeClientAndDispatcher(oldClient); + } + } + + // TODO think about moving capability subset check to netconf client + // could be utilized by integration tests + + long pollingStart = System.currentTimeMillis(); + int delay = 5000; + + int attempt = 0; + + long deadline = pollingStart + timeout; + + Set latestCapabilities = new HashSet<>(); + while (System.currentTimeMillis() < deadline) { + attempt++; + NetconfClientDispatcher netconfClientDispatcher = new NetconfClientDispatcher(nettyThreadgroup, nettyThreadgroup); + NetconfClient netconfClient; + try { + netconfClient = new NetconfClient(this.toString(), address, delay, netconfClientDispatcher); + } catch (IllegalStateException e) { + logger.debug("Netconf {} was not initialized or is not stable, attempt {}", address, attempt, e); + netconfClientDispatcher.close(); + Thread.sleep(delay); + continue; + } + latestCapabilities = netconfClient.getCapabilities(); + if (Util.isSubset(netconfClient, expectedCaps)) { + logger.debug("Hello from netconf stable with {} capabilities", latestCapabilities); + logger.info("Session id received from netconf server: {}", netconfClient.getClientSession()); + return netconfClient; + } + logger.debug("Polling hello from netconf, attempt {}, capabilities {}", attempt, latestCapabilities); + Util.closeClientAndDispatcher(netconfClient); + Thread.sleep(delay); + } + Set allNotFound = new HashSet<>(expectedCaps); + allNotFound.removeAll(latestCapabilities); + logger.error("Netconf server did not provide required capabilities. Expected but not found: {}, all expected {}, current {}", + allNotFound, expectedCaps, latestCapabilities); + throw new RuntimeException("Netconf server did not provide required capabilities. Expected but not found:" + allNotFound); + } + + + private synchronized void pushLastConfig(ConfigSnapshotHolder configSnapshotHolder, NetconfClient netconfClient) + throws ConflictingVersionException, IOException, SAXException { + + Element xmlToBePersisted = XmlUtil.readXmlToElement(configSnapshotHolder.getConfigSnapshot()); + logger.info("Pushing last configuration to netconf: {}", configSnapshotHolder); + StringBuilder response = new StringBuilder("editConfig response = {"); + + + NetconfMessage message = createEditConfigMessage(xmlToBePersisted, "/netconfOp/editConfig.xml"); + + // sending message to netconf + 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)); + element = element.getOnlyChildElement(); + + Util.checkIsOk(element, responseMessage); + response.append(XmlUtil.toString(responseMessage.getDocument())); + response.append("}"); + 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)); + element = element.getOnlyChildElement(); + + Util.checkIsOk(element, responseMessage); + response.append("commit response = {"); + response.append(XmlUtil.toString(responseMessage.getDocument())); + response.append("}"); + logger.info("Last configuration loaded successfully"); + logger.trace("Detailed message {}", response); + } + + private static NetconfMessage createEditConfigMessage(Element dataElement, String editConfigResourcename) { + try (InputStream stream = ConfigPersisterNotificationHandler.class.getResourceAsStream(editConfigResourcename)) { + Preconditions.checkNotNull(stream, "Unable to load resource " + editConfigResourcename); + + Document doc = XmlUtil.readXmlToDocument(stream); + + doc.getDocumentElement(); + XmlElement editConfigElement = XmlElement.fromDomDocument(doc).getOnlyChildElement(); + XmlElement configWrapper = editConfigElement.getOnlyChildElement(XmlNetconfConstants.CONFIG_KEY); + editConfigElement.getDomElement().removeChild(configWrapper.getDomElement()); + for (XmlElement el : XmlElement.fromDomElement(dataElement).getChildElements()) { + configWrapper.appendChild((Element) doc.importNode(el.getDomElement(), true)); + } + editConfigElement.appendChild(configWrapper.getDomElement()); + return new NetconfMessage(doc); + } catch (IOException | SAXException e) { + throw new RuntimeException("Unable to parse message from resources " + editConfigResourcename, e); + } + } + + private static NetconfMessage getNetconfMessageFromResource(String resource) { + try (InputStream stream = ConfigPusher.class.getResourceAsStream(resource)) { + Preconditions.checkNotNull(stream, "Unable to load resource " + resource); + return new NetconfMessage(XmlUtil.readXmlToDocument(stream)); + } catch (SAXException | IOException e) { + throw new RuntimeException("Unable to parse message from resources " + resource, e); + } + } +} diff --git a/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/NoOpStorageAdapter.java b/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/NoOpStorageAdapter.java index b37c1457c3..27f930990d 100644 --- a/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/NoOpStorageAdapter.java +++ b/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/NoOpStorageAdapter.java @@ -8,7 +8,6 @@ package org.opendaylight.controller.netconf.persist.impl; -import com.google.common.base.Optional; import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder; import org.opendaylight.controller.config.persist.api.Persister; import org.opendaylight.controller.config.persist.api.PropertiesProvider; @@ -17,6 +16,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; +import java.util.Collections; +import java.util.List; public class NoOpStorageAdapter implements StorageAdapter, Persister { private static final Logger logger = LoggerFactory.getLogger(NoOpStorageAdapter.class); @@ -33,9 +34,9 @@ public class NoOpStorageAdapter implements StorageAdapter, Persister { } @Override - public Optional loadLastConfig() throws IOException { + public List loadLastConfigs() throws IOException { logger.debug("loadLastConfig called"); - return Optional.absent(); + return Collections.emptyList(); } @Override diff --git a/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/PersisterAggregator.java b/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/PersisterAggregator.java index e109ebec88..7e9dce67bd 100644 --- a/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/PersisterAggregator.java +++ b/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/PersisterAggregator.java @@ -9,7 +9,6 @@ package org.opendaylight.controller.netconf.persist.impl; import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Optional; import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder; import org.opendaylight.controller.config.persist.api.Persister; import org.opendaylight.controller.config.persist.api.StorageAdapter; @@ -20,6 +19,7 @@ import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.ListIterator; @@ -48,7 +48,7 @@ import java.util.ListIterator; * During server startup {@link ConfigPersisterNotificationHandler} requests last snapshot from underlying storages. * Each storage can respond by giving snapshot or absent response. - * The {@link #loadLastConfig()} will search for first non-absent response from storages ordered backwards as user + * The {@link #loadLastConfigs()} will search for first non-absent response from storages ordered backwards as user * specified (first '3', then '2'). * * When a commit notification is received, '2' will be omitted because readonly flag is set to true, so @@ -154,19 +154,29 @@ public final class PersisterAggregator implements Persister { } } + /** + * @return last non-empty result from input persisters + */ @Override - public Optional loadLastConfig() throws IOException { + public List loadLastConfigs() { // iterate in reverse order ListIterator li = persisterWithConfigurations.listIterator(persisterWithConfigurations.size()); while(li.hasPrevious()) { PersisterWithConfiguration persisterWithConfiguration = li.previous(); - Optional configSnapshotHolderOptional = persisterWithConfiguration.storage.loadLastConfig(); - if (configSnapshotHolderOptional.isPresent()) { - return configSnapshotHolderOptional; + List configs = null; + try { + configs = persisterWithConfiguration.storage.loadLastConfigs(); + } catch (IOException e) { + throw new RuntimeException("Error while calling loadLastConfig on " + persisterWithConfiguration, e); + } + if (configs.isEmpty() == false) { + logger.debug("Found non empty configs using {}:{}", persisterWithConfiguration, configs); + return configs; } } // no storage had an answer - return Optional.absent(); + logger.debug("No non-empty list of configuration snapshots found"); + return Collections.emptyList(); } @VisibleForTesting diff --git a/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/Util.java b/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/Util.java index b17309123c..811ba38c10 100644 --- a/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/Util.java +++ b/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/Util.java @@ -8,24 +8,79 @@ package org.opendaylight.controller.netconf.persist.impl; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ThreadFactory; +import org.opendaylight.controller.config.api.ConflictingVersionException; +import org.opendaylight.controller.netconf.api.NetconfMessage; +import org.opendaylight.controller.netconf.client.NetconfClient; +import org.opendaylight.controller.netconf.client.NetconfClientDispatcher; +import org.opendaylight.controller.netconf.util.xml.XMLNetconfUtil; +import org.opendaylight.controller.netconf.util.xml.XmlElement; +import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants; +import org.opendaylight.controller.netconf.util.xml.XmlUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpression; +import java.util.Set; public final class Util { + private static final Logger logger = LoggerFactory.getLogger(Util.class); + + + public static boolean isSubset(NetconfClient netconfClient, Set expectedCaps) { + return isSubset(netconfClient.getCapabilities(), expectedCaps); + + } + + private static boolean isSubset(Set currentCapabilities, Set expectedCaps) { + for (String exCap : expectedCaps) { + if (currentCapabilities.contains(exCap) == false) + return false; + } + return true; + } + + + // TODO: check if closing in correct order + public static void closeClientAndDispatcher(NetconfClient client) { + NetconfClientDispatcher dispatcher = client.getNetconfClientDispatcher(); + Exception fromClient = null; + try { + client.close(); + } catch (Exception e) { + fromClient = e; + } finally { + try { + dispatcher.close(); + } catch (Exception e) { + if (fromClient != null) { + e.addSuppressed(fromClient); + } + throw new RuntimeException("Error closing temporary client ", e); + } + } + } - public static ScheduledExecutorService getExecutorServiceWithThreadName(final String threadNamePrefix, - int threadCount) { - return Executors.newScheduledThreadPool(threadCount, new ThreadFactory() { - private int i = 1; + public static void checkIsOk(XmlElement element, NetconfMessage responseMessage) throws ConflictingVersionException { + if (element.getName().equals(XmlNetconfConstants.OK)) { + return; + } - @Override - public Thread newThread(Runnable r) { - Thread thread = new Thread(r); - thread.setName(threadNamePrefix + ":" + i++); - return thread; + if (element.getName().equals(XmlNetconfConstants.RPC_ERROR)) { + logger.warn("Can not load last configuration, operation failed"); + // is it ConflictingVersionException ? + XPathExpression xPathExpression = XMLNetconfUtil.compileXPath("/netconf:rpc-reply/netconf:rpc-error/netconf:error-info/netconf:error"); + String error = (String) XmlUtil.evaluateXPath(xPathExpression, element.getDomElement(), XPathConstants.STRING); + if (error!=null && error.contains(ConflictingVersionException.class.getCanonicalName())) { + throw new ConflictingVersionException(error); } - }); + throw new IllegalStateException("Can not load last configuration, operation failed: " + + XmlUtil.toString(responseMessage.getDocument())); + } + + logger.warn("Can not load last configuration. Operation failed."); + throw new IllegalStateException("Can not load last configuration. Operation failed: " + + XmlUtil.toString(responseMessage.getDocument())); } } 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 e7916c2d5f..656091115c 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 @@ -8,8 +8,13 @@ package org.opendaylight.controller.netconf.persist.impl.osgi; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import org.opendaylight.controller.netconf.client.NetconfClient; import org.opendaylight.controller.netconf.persist.impl.ConfigPersisterNotificationHandler; +import org.opendaylight.controller.netconf.persist.impl.ConfigPusher; import org.opendaylight.controller.netconf.persist.impl.PersisterAggregator; +import org.opendaylight.controller.netconf.persist.impl.Util; import org.opendaylight.controller.netconf.util.osgi.NetconfConfigUtil; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; @@ -28,14 +33,19 @@ public class ConfigPersisterActivator implements BundleActivator { private final static MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer(); private static final String IGNORED_MISSING_CAPABILITY_REGEX_SUFFIX = "ignoredMissingCapabilityRegex"; - private ConfigPersisterNotificationHandler configPersisterNotificationHandler; + public static final String NETCONF_CONFIG_PERSISTER = "netconf.config.persister"; - private Thread initializationThread; + public static final String STORAGE_ADAPTER_CLASS_PROP_SUFFIX = "storageAdapterClass"; - public static final String NETCONF_CONFIG_PERSISTER = "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"; + + private volatile ConfigPersisterNotificationHandler jmxNotificationHandler; + private volatile NetconfClient netconfClient; + private Thread initializationThread; + private EventLoopGroup nettyThreadgroup; + private PersisterAggregator persisterAggregator; + @Override public void start(final BundleContext context) throws Exception { logger.debug("ConfigPersister starting"); @@ -49,20 +59,24 @@ public class ConfigPersisterActivator implements BundleActivator { } else { regex = DEFAULT_IGNORED_REGEX; } - Pattern ignoredMissingCapabilityRegex = Pattern.compile(regex); - PersisterAggregator persister = PersisterAggregator.createFromProperties(propertiesProvider); + final Pattern ignoredMissingCapabilityRegex = Pattern.compile(regex); + nettyThreadgroup = new NioEventLoopGroup(); + + persisterAggregator = PersisterAggregator.createFromProperties(propertiesProvider); + final InetSocketAddress address = NetconfConfigUtil.extractTCPNetconfAddress(context, "Netconf is not configured, persister is not operational", true); + final ConfigPusher configPusher = new ConfigPusher(address, nettyThreadgroup); - InetSocketAddress address = NetconfConfigUtil.extractTCPNetconfAddress(context, - "Netconf is not configured, persister is not operational",true); - configPersisterNotificationHandler = new ConfigPersisterNotificationHandler(persister, address, - platformMBeanServer, ignoredMissingCapabilityRegex); // offload initialization to another thread in order to stop blocking activator Runnable initializationRunnable = new Runnable() { @Override public void run() { try { - configPersisterNotificationHandler.init(); + netconfClient = configPusher.init(persisterAggregator.loadLastConfigs()); + jmxNotificationHandler = new ConfigPersisterNotificationHandler( + platformMBeanServer, netconfClient, persisterAggregator, + ignoredMissingCapabilityRegex); + jmxNotificationHandler.init(); } catch (InterruptedException e) { logger.info("Interrupted while waiting for netconf connection"); } @@ -75,6 +89,18 @@ public class ConfigPersisterActivator implements BundleActivator { @Override public void stop(BundleContext context) throws Exception { initializationThread.interrupt(); - configPersisterNotificationHandler.close(); + if (jmxNotificationHandler != null) { + jmxNotificationHandler.close(); + } + if (netconfClient != null) { + netconfClient = jmxNotificationHandler.getNetconfClient(); + try { + Util.closeClientAndDispatcher(netconfClient); + } catch (Exception e) { + logger.warn("Unable to close connection to netconf {}", netconfClient, e); + } + } + nettyThreadgroup.shutdownGracefully(); + persisterAggregator.close(); } } diff --git a/opendaylight/netconf/config-persister-impl/src/test/java/org/opendaylight/controller/netconf/persist/impl/ConfigPersisterNotificationHandlerTest.java b/opendaylight/netconf/config-persister-impl/src/test/java/org/opendaylight/controller/netconf/persist/impl/ConfigPersisterNotificationHandlerTest.java index 6c45c9c011..a124d85b91 100644 --- a/opendaylight/netconf/config-persister-impl/src/test/java/org/opendaylight/controller/netconf/persist/impl/ConfigPersisterNotificationHandlerTest.java +++ b/opendaylight/netconf/config-persister-impl/src/test/java/org/opendaylight/controller/netconf/persist/impl/ConfigPersisterNotificationHandlerTest.java @@ -24,7 +24,7 @@ public class ConfigPersisterNotificationHandlerTest { public void testConflictingVersionDetection() throws Exception { Document document = XmlUtil.readXmlToDocument(getClass().getResourceAsStream("/conflictingVersionResponse.xml")); try{ - ConfigPersisterNotificationHandler.checkIsOk(XmlElement.fromDomDocument(document).getOnlyChildElement(), new NetconfMessage(document)); + Util.checkIsOk(XmlElement.fromDomDocument(document).getOnlyChildElement(), new NetconfMessage(document)); fail(); }catch(ConflictingVersionException e){ assertThat(e.getMessage(), containsString("Optimistic lock failed. Expected parent version 21, was 18")); diff --git a/opendaylight/netconf/config-persister-impl/src/test/java/org/opendaylight/controller/netconf/persist/impl/DummyAdapter.java b/opendaylight/netconf/config-persister-impl/src/test/java/org/opendaylight/controller/netconf/persist/impl/DummyAdapter.java index 7a11b9cd6f..e824b58832 100644 --- a/opendaylight/netconf/config-persister-impl/src/test/java/org/opendaylight/controller/netconf/persist/impl/DummyAdapter.java +++ b/opendaylight/netconf/config-persister-impl/src/test/java/org/opendaylight/controller/netconf/persist/impl/DummyAdapter.java @@ -7,13 +7,14 @@ */ package org.opendaylight.controller.netconf.persist.impl; -import com.google.common.base.Optional; import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder; import org.opendaylight.controller.config.persist.api.Persister; import org.opendaylight.controller.config.persist.api.PropertiesProvider; import org.opendaylight.controller.config.persist.api.StorageAdapter; import java.io.IOException; +import java.util.Collections; +import java.util.List; public class DummyAdapter implements StorageAdapter, Persister { @@ -27,9 +28,9 @@ public class DummyAdapter implements StorageAdapter, Persister { static int load = 0; @Override - public Optional loadLastConfig() throws IOException { + public List loadLastConfigs() throws IOException { load++; - return Optional.absent(); + return Collections.emptyList(); } static int props = 0; diff --git a/opendaylight/netconf/config-persister-impl/src/test/java/org/opendaylight/controller/netconf/persist/impl/PersisterAggregatorTest.java b/opendaylight/netconf/config-persister-impl/src/test/java/org/opendaylight/controller/netconf/persist/impl/PersisterAggregatorTest.java index d9fa7ba4d8..227018bf5b 100644 --- a/opendaylight/netconf/config-persister-impl/src/test/java/org/opendaylight/controller/netconf/persist/impl/PersisterAggregatorTest.java +++ b/opendaylight/netconf/config-persister-impl/src/test/java/org/opendaylight/controller/netconf/persist/impl/PersisterAggregatorTest.java @@ -8,7 +8,6 @@ package org.opendaylight.controller.netconf.persist.impl; -import com.google.common.base.Optional; import org.junit.Test; import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder; import org.opendaylight.controller.config.persist.api.Persister; @@ -18,14 +17,14 @@ import org.opendaylight.controller.netconf.persist.impl.osgi.PropertiesProviderB import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Properties; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.fail; -import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; import static org.junit.matchers.JUnitMatchers.containsString; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; @@ -79,9 +78,9 @@ public class PersisterAggregatorTest { assertFalse(persister.isReadOnly()); persisterAggregator.persistConfig(null); - persisterAggregator.loadLastConfig(); + persisterAggregator.loadLastConfigs(); persisterAggregator.persistConfig(null); - persisterAggregator.loadLastConfig(); + persisterAggregator.loadLastConfigs(); assertEquals(2, DummyAdapter.persist); assertEquals(2, DummyAdapter.load); @@ -110,29 +109,41 @@ public class PersisterAggregatorTest { } } + private ConfigSnapshotHolder mockHolder(String name){ + ConfigSnapshotHolder result = mock(ConfigSnapshotHolder.class); + doReturn("mock:" + name).when(result).toString(); + return result; + } + + private Persister mockPersister(String name){ + Persister result = mock(Persister.class); + doReturn("mock:" + name).when(result).toString(); + return result; + } + @Test public void loadLastConfig() throws Exception { List persisterWithConfigurations = new ArrayList<>(); PersisterWithConfiguration first = new PersisterWithConfiguration(mock(Persister.class), false); - ConfigSnapshotHolder ignored = mock(ConfigSnapshotHolder.class); - doReturn(Optional.of(ignored)).when(first.getStorage()).loadLastConfig(); // should be ignored + ConfigSnapshotHolder ignored = mockHolder("ignored"); + doReturn(Arrays.asList(ignored)).when(first.getStorage()).loadLastConfigs(); // should be ignored - ConfigSnapshotHolder used = mock(ConfigSnapshotHolder.class); - PersisterWithConfiguration second = new PersisterWithConfiguration(mock(Persister.class), false); - doReturn(Optional.of(used)).when(second.getStorage()).loadLastConfig(); // should be used - PersisterWithConfiguration third = new PersisterWithConfiguration(mock(Persister.class), false); - doReturn(Optional.absent()).when(third.getStorage()).loadLastConfig(); + ConfigSnapshotHolder used = mockHolder("used"); + PersisterWithConfiguration second = new PersisterWithConfiguration(mockPersister("p1"), false); + doReturn(Arrays.asList(used)).when(second.getStorage()).loadLastConfigs(); // should be used + + PersisterWithConfiguration third = new PersisterWithConfiguration(mockPersister("p2"), false); + doReturn(Arrays.asList()).when(third.getStorage()).loadLastConfigs(); persisterWithConfigurations.add(first); persisterWithConfigurations.add(second); persisterWithConfigurations.add(third); PersisterAggregator persisterAggregator = new PersisterAggregator(persisterWithConfigurations); - Optional configSnapshotHolderOptional = persisterAggregator.loadLastConfig(); - assertTrue(configSnapshotHolderOptional.isPresent()); - assertEquals(used, configSnapshotHolderOptional.get()); + List configSnapshotHolderOptional = persisterAggregator.loadLastConfigs(); + assertEquals(1, configSnapshotHolderOptional.size()); + assertEquals(used, configSnapshotHolderOptional.get(0)); } - } diff --git a/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClient.java b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClient.java index d95977492a..d644cddff4 100644 --- a/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClient.java +++ b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClient.java @@ -100,6 +100,10 @@ public class NetconfClient implements Closeable { clientSession.close(); } + public NetconfClientDispatcher getNetconfClientDispatcher() { + return dispatch; + } + private static ReconnectStrategy getReconnectStrategy(int connectionAttempts, int attemptMsTimeout) { return new TimedReconnectStrategy(GlobalEventExecutor.INSTANCE, attemptMsTimeout, 1000, 1.0, null, Long.valueOf(connectionAttempts), null); 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 ccc7c85eb3..c61dab7f64 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 @@ -8,23 +8,41 @@ package org.opendaylight.controller.netconf.it; -import ch.ethz.ssh2.Connection; -import ch.ethz.ssh2.Session; -import com.google.common.base.Optional; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; +import static java.util.Collections.emptyList; +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertTrue; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; import io.netty.channel.ChannelFuture; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.util.HashedWheelTimer; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.management.ManagementFactory; +import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import javax.management.ObjectName; +import javax.xml.parsers.ParserConfigurationException; + import junit.framework.Assert; + import org.junit.After; import org.junit.Before; import org.junit.Ignore; 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.persist.api.Persister; import org.opendaylight.controller.config.spi.ModuleFactory; import org.opendaylight.controller.config.util.ConfigTransactionJMXClient; import org.opendaylight.controller.config.yang.store.api.YangStoreException; @@ -49,8 +67,6 @@ import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFact import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl; import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceSnapshot; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService; -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; @@ -64,28 +80,11 @@ import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.xml.sax.SAXException; -import javax.management.ObjectName; -import javax.xml.parsers.ParserConfigurationException; -import java.io.IOException; -import java.io.InputStream; -import java.lang.management.ManagementFactory; -import java.net.InetSocketAddress; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.regex.Pattern; +import ch.ethz.ssh2.Connection; +import ch.ethz.ssh2.Session; -import static java.util.Collections.emptyList; -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertNotNull; -import static junit.framework.Assert.assertTrue; -import static org.mockito.Matchers.anyLong; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; public class NetconfITTest extends AbstractConfigTest { @@ -220,14 +219,18 @@ public class NetconfITTest extends AbstractConfigTest { } } + + //TODO: test persister actually + @Ignore @Test(timeout = 10000) public void testPersister() throws Exception { - Persister persister = mock(Persister.class); - doReturn("mockPersister").when(persister).toString(); - doReturn(Optional.absent()).when(persister).loadLastConfig(); - ConfigPersisterNotificationHandler h = - new ConfigPersisterNotificationHandler(persister, tcpAddress, ManagementFactory.getPlatformMBeanServer(), Pattern.compile(ConfigPersisterActivator.DEFAULT_IGNORED_REGEX)); - h.init(); +// Persister persister = mock(Persister.class); +// doReturn("mockPersister").when(persister).toString(); +// doReturn(Collections.emptyList()).when(persister).loadLastConfigs(); +// ConfigPersisterNotificationHandler h = +// new ConfigPersisterNotificationHandler(persister, tcpAddress, ManagementFactory.getPlatformMBeanServer(), +// Pattern.compile(ConfigPersisterActivator.DEFAULT_IGNORED_REGEX)); +// h.init(); } @Ignore diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig.xml index caa0094c4b..dc522d2e64 100644 --- a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig.xml +++ b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig.xml @@ -94,6 +94,15 @@ prefix:testing ref_dep + + + prefix:testing + ref_dep + + + prefix:testing + ref_dep_2 + @@ -105,7 +114,7 @@ prefix:testing - ref_dep + ref_dep_2 @@ -115,7 +124,7 @@ prefix:testing ref_dep - /config/modules/module[name='impl-dep']/instance[name='dep'] + /modules/module[type='impl-dep'][name='dep'] @@ -125,7 +134,8 @@ ref_test1 - /config/modules/module[name='impl-netconf']/instance[name='test1'] + + /modules/module[type='impl-netconf'][name='test1'] diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_none.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_none.xml index c825536b7b..388aa4f2ab 100644 --- a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_none.xml +++ b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_none.xml @@ -89,17 +89,18 @@ prefix:testing ref_dep - /config/modules/module[name='impl-dep']/instance[name='dep'] + /modules/module[type='impl-dep'][name='dep'] ref_dep_2 - /config/modules/module[name='impl-dep']/instance[name='dep2'] + /modules/module[type='impl-dep'][name='dep2'] ref_test1 - /config/modules/module[name='impl-netconf']/instance[name='test1'] + + /modules/module[type='impl-netconf'][name='test1'] diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_differentNamespaceTO.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_differentNamespaceTO.xml index 82c218dd73..4d94d9e949 100644 --- a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_differentNamespaceTO.xml +++ b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_differentNamespaceTO.xml @@ -97,17 +97,18 @@ prefix:testing ref_dep - /config/modules/module[name='impl-dep']/instance[name='dep'] + /modules/module[type='impl-dep'][name='dep'] ref_dep_2 - /config/modules/module[name='impl-dep']/instance[name='dep2'] + /modules/module[type='impl-dep'][name='dep2'] ref_test1 - /config/modules/module[name='impl-netconf']/instance[name='test1'] + + /modules/module[type='impl-netconf'][name='test1'] diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_sameAttrDifferentNamespaces.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_sameAttrDifferentNamespaces.xml index 7c19b9f7b3..c399c196d3 100644 --- a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_sameAttrDifferentNamespaces.xml +++ b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_sameAttrDifferentNamespaces.xml @@ -98,17 +98,18 @@ prefix:testing ref_dep - /config/modules/module[name='impl-dep']/instance[name='dep'] + /modules/module[type='impl-dep'][name='dep'] ref_dep_2 - /config/modules/module[name='impl-dep']/instance[name='dep2'] + /modules/module[type='impl-dep'][name='dep2'] ref_test1 - /config/modules/module[name='impl-netconf']/instance[name='test1'] + + /modules/module[type='impl-netconf'][name='test1'] diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_sameAttrDifferentNamespacesList.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_sameAttrDifferentNamespacesList.xml index 84ae575559..47b82c6114 100644 --- a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_sameAttrDifferentNamespacesList.xml +++ b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_sameAttrDifferentNamespacesList.xml @@ -97,17 +97,18 @@ prefix:testing ref_dep - /config/modules/module[name='impl-dep']/instance[name='dep'] + /modules/module[type='impl-dep'][name='dep'] ref_dep_2 - /config/modules/module[name='impl-dep']/instance[name='dep2'] + /modules/module[type='impl-dep'][name='dep2'] ref_test1 - /config/modules/module[name='impl-netconf']/instance[name='test1'] + + /modules/module[type='impl-netconf'][name='test1'] diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_typeNameConfigAttributeMatching.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_typeNameConfigAttributeMatching.xml index 2d9e9edb2c..0e70e13a34 100644 --- a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_typeNameConfigAttributeMatching.xml +++ b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_typeNameConfigAttributeMatching.xml @@ -96,17 +96,18 @@ prefix:testing ref_dep - /config/modules/module[name='impl-dep']/instance[name='dep'] + /modules/module[type='impl-dep'][name='dep'] ref_dep_2 - /config/modules/module[name='impl-dep']/instance[name='dep2'] + /modules/module[type='impl-dep'][name='dep2'] ref_test1 - /config/modules/module[name='impl-netconf']/instance[name='test1'] + + /modules/module[type='impl-netconf'][name='test1'] diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised2.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised2.xml index 9407dd0c75..bc05d63931 100644 --- a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised2.xml +++ b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised2.xml @@ -27,7 +27,7 @@ prefix:testing ref_dep - /config/modules/module[name='impl-dep']/instance[name='dep'] + /modules/module[type='impl-dep'][name='dep'] diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised3.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised3.xml index 233ad23286..f20d9ff9fa 100644 --- a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised3.xml +++ b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised3.xml @@ -28,7 +28,7 @@ prefix:testing ref_dep - /config/modules/module[name='impl-dep']/instance[name='dep'] + /modules/module[type='impl-dep'][name='dep'] diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised4.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised4.xml index 4593887f49..ff0bd9feb5 100644 --- a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised4.xml +++ b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised4.xml @@ -29,7 +29,7 @@ ref_dep - /config/modules/module[name='impl-dep']/instance[name='dep'] + /modules/module[type='impl-dep'][name='dep'] diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised5.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised5.xml index 81c4137d4e..906367b7a6 100644 --- a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised5.xml +++ b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised5.xml @@ -29,7 +29,7 @@ ref_dep error - /config/modules/module[name='impl-dep']/instance[name='dep'] + /modules/module[type='impl-dep'][name='dep'] diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised6.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised6.xml index 528d5b06fc..b05046db4b 100644 --- a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised6.xml +++ b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised6.xml @@ -26,7 +26,7 @@ prefix:testing ref_dep - /config/modules/module[name='impl-dep']/instance[name='dep'] + /modules/module[type='impl-dep'][name='dep'] diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised7.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised7.xml index a1e304b374..d03bb084b8 100644 --- a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised7.xml +++ b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised7.xml @@ -97,17 +97,18 @@ prefix:testing ref_dep - /config/modules/module[name='impl-dep']/instance[name='dep'] + /modules/module[type='impl-dep'][name='dep'] ref_dep_2 - /config/modules/module[name='impl-dep']/instance[name='dep2'] + /modules/module[type='impl-dep'][name='dep2'] ref_test1 - /config/modules/module[name='impl-netconf']/instance[name='test1'] + + /modules/module[type='impl-netconf'][name='test1'] diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised8.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised8.xml index 812882a2a9..3722973912 100644 --- a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised8.xml +++ b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised8.xml @@ -97,17 +97,18 @@ prefix:testing ref_dep - /config/modules/module[name='impl-dep']/instance[name='dep'] + /modules/module[type='impl-dep'][name='dep'] ref_dep_2 - /config/modules/module[name='impl-dep']/instance[name='dep2'] + /modules/module[type='impl-dep'][name='dep2'] ref_test1 - /config/modules/module[name='impl-netconf']/instance[name='test1'] + + /modules/module[type='impl-netconf'][name='test1']