From: Chi-Vien Ly Date: Mon, 13 Jan 2014 17:09:57 +0000 (+0000) Subject: Merge "ArpHandler to ignore ip packet sent to default GW" X-Git-Tag: jenkins-controller-bulk-release-prepare-only-2-1~101 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=54bed4dd6dfbada9a8e2ddf70ca84952aec3f55a;hp=ad32425a1ee129ddfb9d78574fd0ea5045f4f9dd;p=controller.git Merge "ArpHandler to ignore ip packet sent to default GW" --- diff --git a/.gitignore b/.gitignore index 18817e7c35..b079cba0a1 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,4 @@ opendaylight/northbound/integrationtest/logs/* .idea xtend-gen classes +out/ diff --git a/opendaylight/commons/opendaylight/pom.xml b/opendaylight/commons/opendaylight/pom.xml index 8933b1442f..24b1ed9cbc 100644 --- a/opendaylight/commons/opendaylight/pom.xml +++ b/opendaylight/commons/opendaylight/pom.xml @@ -61,6 +61,7 @@ 5.0.0 2010.09.24.2-SNAPSHOT 2010.09.24.2-SNAPSHOT + 2013.10.21.0-SNAPSHOT 2013.08.27.1 2013.09.07.1 3.17.1-GA @@ -666,6 +667,11 @@ ietf-yang-types ${ietf-yang-types.version} + + org.opendaylight.yangtools.model + ietf-topology + ${ietf-topology.version} + org.opendaylight.yangtools.model opendaylight-l2-types diff --git a/opendaylight/config/config-persister-api/pom.xml b/opendaylight/config/config-persister-api/pom.xml index 80016a804b..f622992bb5 100644 --- a/opendaylight/config/config-persister-api/pom.xml +++ b/opendaylight/config/config-persister-api/pom.xml @@ -24,6 +24,10 @@ + + org.apache.maven.plugins + maven-jar-plugin + org.apache.felix maven-bundle-plugin diff --git a/opendaylight/config/config-persister-api/src/test/java/org/opendaylight/controller/config/persist/test/PropertiesProviderTest.java b/opendaylight/config/config-persister-api/src/test/java/org/opendaylight/controller/config/persist/test/PropertiesProviderTest.java new file mode 100644 index 0000000000..2df07b114c --- /dev/null +++ b/opendaylight/config/config-persister-api/src/test/java/org/opendaylight/controller/config/persist/test/PropertiesProviderTest.java @@ -0,0 +1,29 @@ +/* + * 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.persist.test; + +import java.util.HashMap; +import java.util.Map; +import org.opendaylight.controller.config.persist.api.PropertiesProvider; + +public class PropertiesProviderTest implements PropertiesProvider { + private final Map properties = new HashMap(); + + public void addProperty(String key,String value){ + properties.put(key,value); + } + @Override + public String getProperty(String key) { + return properties.get(key); + } + + @Override + public String getFullKeyForReporting(String key) { + return null; + } +} diff --git a/opendaylight/config/config-persister-directory-adapter/pom.xml b/opendaylight/config/config-persister-directory-adapter/pom.xml index b2da71eea2..c67a08c7af 100644 --- a/opendaylight/config/config-persister-directory-adapter/pom.xml +++ b/opendaylight/config/config-persister-directory-adapter/pom.xml @@ -42,6 +42,12 @@ mockito-configuration test + + ${project.groupId} + config-persister-api + test-jar + test + 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 f17e414c49..72bd208ff3 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,28 +8,32 @@ package org.opendaylight.controller.config.persist.storage.directory; -import org.apache.commons.io.IOUtils; -import org.junit.Test; -import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder; - import java.io.File; import java.util.Collections; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; - +import org.apache.commons.io.IOUtils; +import org.junit.Test; +import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder; +import org.opendaylight.controller.config.persist.api.Persister; +import org.opendaylight.controller.config.persist.test.PropertiesProviderTest; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; public class DirectoryStorageAdapterTest { - DirectoryPersister tested; + Persister tested; @Test public void testEmptyDirectory() throws Exception { File folder = new File("target/emptyFolder"); folder.mkdir(); - tested = new DirectoryPersister((folder)); + + PropertiesProviderTest pp = new PropertiesProviderTest(); + pp.addProperty("directoryStorage",folder.getPath()); + DirectoryStorageAdapter dsa = new DirectoryStorageAdapter(); + tested = dsa.instantiate(pp); assertEquals(Collections.emptyList(), tested.loadLastConfigs()); try { @@ -60,7 +64,11 @@ public class DirectoryStorageAdapterTest { @Test public void testOneFile() throws Exception { File folder = getFolder("oneFile"); - tested = new DirectoryPersister((folder)); + PropertiesProviderTest pp = new PropertiesProviderTest(); + pp.addProperty("directoryStorage",folder.getPath()); + DirectoryStorageAdapter dsa = new DirectoryStorageAdapter(); + tested = dsa.instantiate(pp); + List results = tested.loadLastConfigs(); assertEquals(1, results.size()); ConfigSnapshotHolder result = results.get(0); @@ -71,7 +79,11 @@ public class DirectoryStorageAdapterTest { @Test public void testTwoFiles() throws Exception { File folder = getFolder("twoFiles"); - tested = new DirectoryPersister((folder)); + PropertiesProviderTest pp = new PropertiesProviderTest(); + pp.addProperty("directoryStorage",folder.getPath()); + DirectoryStorageAdapter dsa = new DirectoryStorageAdapter(); + tested = dsa.instantiate(pp); + List results = tested.loadLastConfigs(); assertEquals(2, results.size()); assertSnapshot(results.get(0), "twoFilesExpected1"); diff --git a/opendaylight/config/config-persister-directory-xml-adapter/pom.xml b/opendaylight/config/config-persister-directory-xml-adapter/pom.xml index b2ea632834..96d3a71c30 100644 --- a/opendaylight/config/config-persister-directory-xml-adapter/pom.xml +++ b/opendaylight/config/config-persister-directory-xml-adapter/pom.xml @@ -57,6 +57,12 @@ mockito-configuration test + + ${project.groupId} + config-persister-api + test-jar + test + diff --git a/opendaylight/config/config-persister-directory-xml-adapter/src/test/java/org/opendaylight/controller/config/persist/storage/directory/xml/DirectoryStorageAdapterTest.java b/opendaylight/config/config-persister-directory-xml-adapter/src/test/java/org/opendaylight/controller/config/persist/storage/directory/xml/DirectoryStorageAdapterTest.java index 73061f81de..0a36db9e2e 100644 --- a/opendaylight/config/config-persister-directory-xml-adapter/src/test/java/org/opendaylight/controller/config/persist/storage/directory/xml/DirectoryStorageAdapterTest.java +++ b/opendaylight/config/config-persister-directory-xml-adapter/src/test/java/org/opendaylight/controller/config/persist/storage/directory/xml/DirectoryStorageAdapterTest.java @@ -8,20 +8,21 @@ package org.opendaylight.controller.config.persist.storage.directory.xml; -import org.junit.Test; -import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder; - import java.io.File; import java.util.Collections; import java.util.List; import java.util.SortedSet; - +import org.junit.Test; +import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder; +import org.opendaylight.controller.config.persist.api.Persister; +import org.opendaylight.controller.config.persist.test.PropertiesProviderTest; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; public class DirectoryStorageAdapterTest { - XmlDirectoryPersister tested; + + Persister tested; @Test public void testEmptyDirectory() throws Exception { @@ -58,7 +59,12 @@ public class DirectoryStorageAdapterTest { @Test public void testOneFile() throws Exception { File folder = getFolder("oneFile"); - tested = new XmlDirectoryPersister((folder)); + + PropertiesProviderTest pp = new PropertiesProviderTest(); + pp.addProperty("directoryStorage",folder.getPath()); + XmlDirectoryStorageAdapter xmlDsa = new XmlDirectoryStorageAdapter(); + tested = xmlDsa.instantiate(pp); + List results = tested.loadLastConfigs(); assertEquals(1, results.size()); ConfigSnapshotHolder result = results.get(0); @@ -76,7 +82,12 @@ public class DirectoryStorageAdapterTest { @Test public void testTwoFiles() throws Exception { File folder = getFolder("twoFiles"); - tested = new XmlDirectoryPersister((folder)); + + PropertiesProviderTest pp = new PropertiesProviderTest(); + pp.addProperty("directoryStorage",folder.getPath()); + XmlDirectoryStorageAdapter xmlDsa = new XmlDirectoryStorageAdapter(); + tested = xmlDsa.instantiate(pp); + List results = tested.loadLastConfigs(); assertEquals(2, results.size()); diff --git a/opendaylight/config/config-persister-file-adapter/pom.xml b/opendaylight/config/config-persister-file-adapter/pom.xml index b16cb2b6f3..3cd3e907b3 100644 --- a/opendaylight/config/config-persister-file-adapter/pom.xml +++ b/opendaylight/config/config-persister-file-adapter/pom.xml @@ -38,6 +38,12 @@ mockito-configuration test + + ${project.groupId} + config-persister-api + test-jar + test + 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 3ec8713b47..1b9948bf39 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 @@ -13,15 +13,6 @@ import com.google.common.base.Charsets; import com.google.common.base.Optional; 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 java.io.File; import java.io.IOException; import java.nio.charset.Charset; @@ -31,9 +22,17 @@ import java.util.List; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; +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; /** - * StorageAdapter that stores configuration in a plan file. + * StorageAdapter that stores configuration in a plain file. */ public class FileStorageAdapter implements StorageAdapter, Persister { private static final Logger logger = LoggerFactory.getLogger(FileStorageAdapter.class); 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 0236598f2b..0366dbcaed 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 @@ -11,18 +11,18 @@ package org.opendaylight.controller.config.persist.storage.file; import com.google.common.base.Charsets; import com.google.common.base.Predicate; import com.google.common.collect.Collections2; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; -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 org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder; +import org.opendaylight.controller.config.persist.api.Persister; +import org.opendaylight.controller.config.persist.test.PropertiesProviderTest; import static junit.framework.Assert.assertFalse; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertEquals; @@ -42,6 +42,49 @@ public class FileStorageAdapterTest { i = 1; } + + @Test + public void testFileAdapterAsPersister() throws Exception { + FileStorageAdapter storage = new FileStorageAdapter(); + PropertiesProviderTest pp = new PropertiesProviderTest(); + pp.addProperty("fileStorage",file.getPath()); + pp.addProperty("numberOfBackups",Integer.toString(Integer.MAX_VALUE)); + + Persister configPersister = storage.instantiate(pp); + final ConfigSnapshotHolder holder = new ConfigSnapshotHolder() { + @Override + public String getConfigSnapshot() { + return createConfig(); + } + + @Override + public SortedSet getCapabilities() { + return createCaps(); + } + }; + configPersister.persistConfig(holder); + + configPersister.persistConfig(holder); + + Collection readLines = Collections2.filter(com.google.common.io.Files.readLines(file, Charsets.UTF_8), + new Predicate() { + + @Override + public boolean apply(String input) { + if (input.equals("")) + return false; + return true; + } + }); + assertEquals(14, readLines.size()); + + List lastConf = storage.loadLastConfigs(); + assertEquals(1, lastConf.size()); + ConfigSnapshotHolder configSnapshotHolder = lastConf.get(0); + assertEquals("2", + configSnapshotHolder.getConfigSnapshot().replaceAll("\\s", "")); + assertEquals(createCaps(), configSnapshotHolder.getCapabilities()); + } @Test public void testFileAdapter() throws Exception { FileStorageAdapter storage = new FileStorageAdapter(); diff --git a/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionClient.java b/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionClient.java index 75b180921a..4f02db5a38 100644 --- a/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionClient.java +++ b/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionClient.java @@ -32,8 +32,13 @@ public interface ConfigTransactionClient extends void validateBean(ObjectName configBeanON) throws ValidationException; - void destroyConfigBean(String moduleName, String instanceName) - throws InstanceNotFoundException; + @Deprecated + /** + * Use {@link #destroyModule(String, String)} + */ + void destroyConfigBean(String moduleName, String instanceName) throws InstanceNotFoundException; + + void destroyModule(String moduleName, String instanceName) throws InstanceNotFoundException; void setAttribute(ObjectName on, String jmxName, Attribute attribute); } diff --git a/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionJMXClient.java b/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionJMXClient.java index e683d915ba..3583dafd0d 100644 --- a/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionJMXClient.java +++ b/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionJMXClient.java @@ -84,12 +84,23 @@ public class ConfigTransactionJMXClient implements ConfigTransactionClient { } @Override + @Deprecated + /** + * {@inheritDoc} + */ public void destroyConfigBean(String moduleName, String instanceName) throws InstanceNotFoundException { destroyModule(ObjectNameUtil.createTransactionModuleON( getTransactionName(), moduleName, instanceName)); } + @Override + public void destroyModule(String moduleName, String instanceName) + throws InstanceNotFoundException { + destroyModule(ObjectNameUtil.createTransactionModuleON( + getTransactionName(), moduleName, instanceName)); + } + @Override public void abortConfig() { configTransactionControllerMXBeanProxy.abortConfig(); diff --git a/opendaylight/config/pom.xml b/opendaylight/config/pom.xml index 9f9bca9d98..36b109fcd1 100644 --- a/opendaylight/config/pom.xml +++ b/opendaylight/config/pom.xml @@ -155,6 +155,12 @@ config-persister-api ${config.version} + + ${project.groupId} + config-persister-api + ${config.version} + test-jar + org.opendaylight.bgpcep mockito-configuration diff --git a/opendaylight/config/yang-test/src/test/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleTest.java b/opendaylight/config/yang-test/src/test/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleTest.java similarity index 64% rename from opendaylight/config/yang-test/src/test/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleTest.java rename to opendaylight/config/yang-test/src/test/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleTest.java index 50e1d4bb6a..41ceab0e55 100644 --- a/opendaylight/config/yang-test/src/test/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleTest.java +++ b/opendaylight/config/yang-test/src/test/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleTest.java @@ -4,8 +4,6 @@ import com.google.common.collect.Lists; import junit.framework.Assert; import org.junit.Before; import org.junit.Test; -import org.opendaylight.controller.config.api.ConflictingVersionException; -import org.opendaylight.controller.config.api.ValidationException; import org.opendaylight.controller.config.api.jmx.CommitStatus; import org.opendaylight.controller.config.api.jmx.ObjectNameUtil; import org.opendaylight.controller.config.manager.impl.AbstractConfigTest; @@ -15,8 +13,14 @@ import org.opendaylight.controller.config.util.ConfigTransactionJMXClient; import javax.management.InstanceAlreadyExistsException; import javax.management.ObjectName; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + public class NetconfTestImplModuleTest extends AbstractConfigTest { public static final String TESTING_DEP_PREFIX = "testing-dep"; @@ -32,17 +36,16 @@ public class NetconfTestImplModuleTest extends AbstractConfigTest { } @Test - public void testDependencyList() throws InstanceAlreadyExistsException, ValidationException, - ConflictingVersionException { + public void testDependencyList() throws Exception { ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction(); ObjectName on = createInstance(transaction, instanceName, 4); transaction.validateConfig(); - CommitStatus status = transaction.commit(); + CommitStatus status1 = transaction.commit(); assertBeanCount(1, factory.getImplementationName()); assertBeanCount(4 + 1, DepTestImplModuleFactory.NAME); - assertStatus(status, 1 + 4 + 1, 0, 0); + assertStatus(status1, 1 + 4 + 1, 0, 0); transaction = configRegistryClient.createTransaction(); @@ -56,6 +59,38 @@ public class NetconfTestImplModuleTest extends AbstractConfigTest { assertTestingDeps(testingDeps, 4); transaction.abortConfig(); + + // check that reuse logic works - equals on list of dependencies. + transaction = configRegistryClient.createTransaction(); + CommitStatus status2 = transaction.commit(); + assertStatus(status2, 0, 0, 6); + + // replace single dependency + transaction = configRegistryClient.createTransaction(); + String instanceName1 = TESTING_DEP_PREFIX + 1; + transaction.destroyModule(DepTestImplModuleFactory.NAME, instanceName1); + transaction.createModule(DepTestImplModuleFactory.NAME, instanceName1); + CommitStatus status3 = transaction.commit(); + assertStatus(status3, 1, 1, 4); + + } + + @Test + public void testNullCheckInListOfDependencies() throws Exception { + ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction(); + + ObjectName on = createInstance(transaction, instanceName, 4); + NetconfTestImplModuleMXBean proxy = transaction.newMXBeanProxy(on, NetconfTestImplModuleMXBean.class); + try{ + proxy.setTestingDeps(null); + fail(); + }catch(RuntimeException e) { + Throwable cause = e.getCause(); + assertNotNull(cause); + assertTrue("Invalid type " + cause, cause instanceof IllegalArgumentException); + assertEquals("Null not supported", cause.getMessage()); + } + proxy.setTestingDeps(Collections.emptyList()); } private void assertTestingDeps(List testingDeps, int i) { diff --git a/opendaylight/distribution/opendaylight/pom.xml b/opendaylight/distribution/opendaylight/pom.xml index 6fca9db636..f1eca41dee 100644 --- a/opendaylight/distribution/opendaylight/pom.xml +++ b/opendaylight/distribution/opendaylight/pom.xml @@ -152,7 +152,6 @@ org.opendaylight.yangtools.model ietf-topology - 2013.07.12.2-SNAPSHOT org.opendaylight.controller 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 3ec9f8443a..de6b8182b0 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 @@ -8,19 +8,6 @@ package org.opendaylight.controller.forwardingrulesmanager; -import java.io.Serializable; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; - import org.opendaylight.controller.sal.action.Action; import org.opendaylight.controller.sal.action.ActionType; import org.opendaylight.controller.sal.action.Controller; @@ -62,6 +49,18 @@ import org.opendaylight.controller.switchmanager.Switch; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + /** * Configuration Java Object which represents a flow configuration information * for Forwarding Rules Manager. @@ -1044,6 +1043,7 @@ public class FlowConfig implements Serializable { } Flow flow = new Flow(match, getActionList()); + if (this.cookie != null) { flow.setId(Long.parseLong(cookie)); } @@ -1056,6 +1056,8 @@ public class FlowConfig implements Serializable { if (this.priority != null) { flow.setPriority(Integer.decode(this.priority).shortValue()); } + + return flow; } diff --git a/opendaylight/md-sal/compatibility/pom.xml b/opendaylight/md-sal/compatibility/pom.xml index 151fdbfaaa..37d866dca5 100644 --- a/opendaylight/md-sal/compatibility/pom.xml +++ b/opendaylight/md-sal/compatibility/pom.xml @@ -25,7 +25,7 @@ org.opendaylight.controller sal - 0.5.1-SNAPSHOT + 0.7.0-SNAPSHOT org.opendaylight.controller.model diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/pom.xml b/opendaylight/md-sal/compatibility/sal-compatibility/pom.xml index f72e5b9bfa..5e52e3bb89 100644 --- a/opendaylight/md-sal/compatibility/sal-compatibility/pom.xml +++ b/opendaylight/md-sal/compatibility/sal-compatibility/pom.xml @@ -30,6 +30,11 @@ sal-binding-util 1.0-SNAPSHOT + + org.opendaylight.controller + clustering.services + 0.4.1-SNAPSHOT + bundle diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ComponentActivator.xtend b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ComponentActivator.xtend index d7a345cfc8..2156a81787 100644 --- a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ComponentActivator.xtend +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ComponentActivator.xtend @@ -27,6 +27,8 @@ import org.opendaylight.controller.sal.topology.IPluginOutTopologyService import org.opendaylight.controller.sal.utils.GlobalConstants import org.opendaylight.controller.sal.utils.INodeConnectorFactory import org.opendaylight.controller.sal.utils.INodeFactory +import org.opendaylight.controller.clustering.services.IClusterGlobalServices + import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsService import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsService @@ -143,6 +145,13 @@ class ComponentActivator extends ComponentActivatorAbstractBase implements Bindi .setService(IPluginOutFlowProgrammerService) // .setCallbacks("setFlowProgrammerPublisher", "setFlowProgrammerPublisher") // .setRequired(false)) + + add( + createServiceDependency() // + .setService(IClusterGlobalServices) // + .setCallbacks("setClusterGlobalServices", "unsetClusterGlobalServices") // + .setRequired(false)) + } private def dispatch configure(InventoryAndReadAdapter imp, Component it) { @@ -162,6 +171,7 @@ class ComponentActivator extends ComponentActivatorAbstractBase implements Bindi .setService(IDiscoveryService) // .setCallbacks("setDiscoveryPublisher", "setDiscoveryPublisher") // .setRequired(false)) + } diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/FlowProgrammerAdapter.xtend b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/FlowProgrammerAdapter.xtend index 450c7f1f23..35c641c45a 100644 --- a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/FlowProgrammerAdapter.xtend +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/FlowProgrammerAdapter.xtend @@ -1,12 +1,21 @@ package org.opendaylight.controller.sal.compatibility +import java.util.Map +import java.util.UUID import java.util.concurrent.ExecutionException +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.Future +import java.util.EnumSet import org.opendaylight.controller.sal.core.Node import org.opendaylight.controller.sal.flowprogrammer.Flow import org.opendaylight.controller.sal.flowprogrammer.IPluginInFlowProgrammerService import org.opendaylight.controller.sal.flowprogrammer.IPluginOutFlowProgrammerService import org.opendaylight.controller.sal.utils.Status import org.opendaylight.controller.sal.utils.StatusCode +import org.opendaylight.controller.clustering.services.CacheExistException +import org.opendaylight.controller.clustering.services.IClusterGlobalServices +import org.opendaylight.controller.clustering.services.IClusterServices + import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAdded import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SwitchFlowRemoved @@ -20,19 +29,14 @@ import org.slf4j.LoggerFactory import org.opendaylight.controller.sal.binding.api.data.DataBrokerService import org.opendaylight.controller.md.sal.common.api.TransactionStatus -import org.opendaylight.controller.md.sal.common.api.data.DataModification import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey -import org.opendaylight.yangtools.yang.binding.DataObject import org.opendaylight.yangtools.yang.binding.InstanceIdentifier -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId import static extension org.opendaylight.controller.sal.compatibility.MDFlowMapping.* @@ -43,6 +47,7 @@ import static extension org.opendaylight.controller.sal.compatibility.ToSalConve class FlowProgrammerAdapter implements IPluginInFlowProgrammerService, SalFlowListener { private static val LOG = LoggerFactory.getLogger(FlowProgrammerAdapter); + private static val CACHE_NAME = "flowprogrammeradapter.flowtoid"; @Property private SalFlowService delegate; @@ -53,39 +58,38 @@ class FlowProgrammerAdapter implements IPluginInFlowProgrammerService, SalFlowLi @Property private IPluginOutFlowProgrammerService flowProgrammerPublisher; + @Property + private IClusterGlobalServices clusterGlobalServices; + + + @Property + private Map flowToFlowId = new ConcurrentHashMap(); + + override addFlow(Node node, Flow flow) { - return addFlowAsync(node,flow,0) + return toFutureStatus(internalAddFlowAsync(node,flow,0)); } override modifyFlow(Node node, Flow oldFlow, Flow newFlow) { - return modifyFlowAsync(node, oldFlow,newFlow,0) + return toFutureStatus(internalModifyFlowAsync(node, oldFlow,newFlow,0)); } override removeFlow(Node node, Flow flow) { - return removeFlowAsync(node, flow,0); + return toFutureStatus(internalRemoveFlowAsync(node, flow,0)); } override addFlowAsync(Node node, Flow flow, long rid) { - writeFlow(flow.toMDFlow, new NodeKey(new NodeId(node.getNodeIDString()))); + internalAddFlowAsync(node, flow, rid); return toStatus(true); } override modifyFlowAsync(Node node, Flow oldFlow, Flow newFlow, long rid) { - writeFlow(newFlow.toMDFlow, new NodeKey(new NodeId(node.getNodeIDString()))); + internalModifyFlowAsync(node, oldFlow, newFlow, rid); return toStatus(true); } - override removeFlowAsync(Node node, Flow adflow, long rid) { - val flow = adflow.toMDFlow; - val modification = this._dataBrokerService.beginTransaction(); - val flowPath = InstanceIdentifier.builder(Nodes) - .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, new NodeKey(new NodeId(node.getNodeIDString()))) - .augmentation(FlowCapableNode) - .child(Table, new TableKey(flow.getTableId())) - .child(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow, new FlowKey(flow.id)) - .build; - modification.removeConfigurationData(flowPath); - val commitFuture = modification.commit(); + override removeFlowAsync(Node node, Flow flow, long rid) { + internalRemoveFlowAsync(node, flow, rid); return toStatus(true); } @@ -114,27 +118,6 @@ class FlowProgrammerAdapter implements IPluginInFlowProgrammerService, SalFlowLi } } - - private def writeFlow(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow flow, NodeKey nodeKey) { - val modification = this._dataBrokerService.beginTransaction(); - val flowPath = InstanceIdentifier.builder(Nodes) - .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, nodeKey) - .augmentation(FlowCapableNode) - .child(Table, new TableKey(flow.getTableId())) - .child(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow, new FlowKey(flow.id)) - .build; - modification.putConfigurationData(flowPath, flow); - val commitFuture = modification.commit(); - try { - val result = commitFuture.get(); - val status = result.getResult(); - } catch (InterruptedException e) { - LOG.error(e.getMessage(), e); - } catch (ExecutionException e) { - LOG.error(e.getMessage(), e); - } - } - public static def toStatus(RpcResult result) { return toStatus(result.isSuccessful()); } @@ -177,4 +160,90 @@ class FlowProgrammerAdapter implements IPluginInFlowProgrammerService, SalFlowLi NodeExperimenterErrorNotification notification) { // NOOP : Not supported by AD SAL } + + private def Future> writeFlowAsync(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow flow, NodeKey nodeKey){ + val modification = this._dataBrokerService.beginTransaction(); + val flowPath = InstanceIdentifier.builder(Nodes) + .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, nodeKey) + .augmentation(FlowCapableNode) + .child(Table, new TableKey(flow.getTableId())) + .child(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow, new FlowKey(flow.id)) + .build; + modification.putConfigurationData(flowPath, flow); + return modification.commit(); + } + + private def Future> internalAddFlowAsync(Node node, Flow flow, long rid){ + var flowId = getCache().get(flow); + if(flowId != null) { + removeFlow(node, flow); + return internalAddFlowAsync(node, flow, rid); + } + + flowId = UUID.randomUUID(); + getCache().put(flow, flowId); + + return writeFlowAsync(flow.toMDFlow(flowId.toString()), new NodeKey(new NodeId(node.getNodeIDString()))); + } + + private def Future> internalModifyFlowAsync(Node node, Flow oldFlow, Flow newFlow, long rid) { + val flowId = getCache().remove(oldFlow); + if(flowId == null){ + throw new IllegalArgumentException("oldFlow is unknown"); + } + + getCache().put(newFlow, flowId); + return writeFlowAsync(newFlow.toMDFlow(flowId.toString()), new NodeKey(new NodeId(node.getNodeIDString()))); + } + + + private def Future> internalRemoveFlowAsync(Node node, Flow adflow, long rid){ + val flowId = getCache().remove(adflow); + if(flowId == null){ + throw new IllegalArgumentException("adflow is unknown"); + } + val flow = adflow.toMDFlow(flowId.toString()); + val modification = this._dataBrokerService.beginTransaction(); + val flowPath = InstanceIdentifier.builder(Nodes) + .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, new NodeKey(new NodeId(node.getNodeIDString()))) + .augmentation(FlowCapableNode) + .child(Table, new TableKey(flow.getTableId())) + .child(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow, new FlowKey(flow.id)) + .build; + modification.removeConfigurationData(flowPath); + return modification.commit(); + } + + private def toFutureStatus(Future> future){ + try { + val result = future.get(); + return toStatus(result); + } catch (InterruptedException e) { + return processException(e); + } catch (ExecutionException e) { + return processException(e); + } catch (Exception e){ + processException(e); + } + return toStatus(false); + } + + private def Map getCache(){ + if(clusterGlobalServices == null){ + return new ConcurrentHashMap(); + } + + var cache = clusterGlobalServices.getCache(CACHE_NAME); + + if(cache == null) { + try { + cache = clusterGlobalServices.createCache(CACHE_NAME, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL)); + } catch (CacheExistException e) { + cache = clusterGlobalServices.getCache(CACHE_NAME); + } + } + return cache as Map; + + } + } diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryAndReadAdapter.xtend b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryAndReadAdapter.xtend index 56ca1b609c..47a3d11325 100644 --- a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryAndReadAdapter.xtend +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryAndReadAdapter.xtend @@ -137,7 +137,7 @@ class InventoryAndReadAdapter implements IPluginInReadService, for(flow : table.flow){ val adsalFlow = ToSalConversionsUtils.toFlow(flow); - val statsFromDataStore = flow.getAugmentation(FlowStatisticsData) as FlowStatisticsData; + val statsFromDataStore = flow.getAugmentation(FlowStatisticsData); if(statsFromDataStore != null){ val it = new FlowOnNode(adsalFlow); @@ -207,7 +207,7 @@ class InventoryAndReadAdapter implements IPluginInReadService, for (table : dsFlowCapableNode.table){ - val tableStats = table.getAugmentation(FlowTableStatisticsData) as FlowTableStatisticsData; + val tableStats = table.getAugmentation(FlowTableStatisticsData); if(tableStats != null){ ret.add(toNodeTableStatistics(tableStats.flowTableStatistics,table.id,node)); @@ -242,7 +242,7 @@ class InventoryAndReadAdapter implements IPluginInReadService, for(mdsalFlow : table.flow){ if(FromSalConversionsUtils.flowEquals(mdsalFlow, MDFlowMapping.toMDSalflow(targetFlow))){ - val statsFromDataStore = mdsalFlow.getAugmentation(FlowStatisticsData) as FlowStatisticsData; + val statsFromDataStore = mdsalFlow.getAugmentation(FlowStatisticsData); if(statsFromDataStore != null){ LOG.debug("Found matching flow in the data store flow table "); @@ -308,7 +308,7 @@ class InventoryAndReadAdapter implements IPluginInReadService, val table= it.readConfigurationData(tableRef) as Table; if(table != null){ - val tableStats = table.getAugmentation(FlowTableStatisticsData) as FlowTableStatisticsData; + val tableStats = table.getAugmentation(FlowTableStatisticsData); if(tableStats != null){ nodeStats = toNodeTableStatistics(tableStats.flowTableStatistics,table.id,nodeTable.node); @@ -345,7 +345,6 @@ class InventoryAndReadAdapter implements IPluginInReadService, } override onNodeUpdated(NodeUpdated notification) { - val properties = Collections.emptySet(); val InstanceIdentifier identifier = notification.nodeRef.value as InstanceIdentifier; var updateType = UpdateType.CHANGED; @@ -502,7 +501,7 @@ class InventoryAndReadAdapter implements IPluginInReadService, * OpendaylightFlowStatisticsListener interface implementation */ override onAggregateFlowStatisticsUpdate(AggregateFlowStatisticsUpdate notification) { - throw new UnsupportedOperationException("TODO: auto-generated method stub") + //Ignoring this notification as there does not seem to be a way to bubble this up to AD-SAL } override onFlowsStatisticsUpdate(FlowsStatisticsUpdate notification) { @@ -571,4 +570,8 @@ class InventoryAndReadAdapter implements IPluginInReadService, return it; } + + override getConfiguredNotConnectedNodes() { + return Collections.emptySet(); + } } diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/MDFlowMapping.xtend b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/MDFlowMapping.xtend index b0f6065bac..5a91e919dd 100644 --- a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/MDFlowMapping.xtend +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/MDFlowMapping.xtend @@ -135,7 +135,7 @@ public class MDFlowMapping { } - public static def toMDFlow(Flow sourceFlow) { + public static def toMDFlow(Flow sourceFlow, String flowId) { if (sourceFlow == null) throw new IllegalArgumentException(); val it = new FlowBuilder(); @@ -143,7 +143,7 @@ public class MDFlowMapping { idleTimeout = sourceFlow.idleTimeout as int cookie = BigInteger.valueOf(sourceFlow.id) priority = sourceFlow.priority as int - id = new FlowId(sourceFlow.id) + id = new FlowId(flowId) val sourceActions = sourceFlow.actions; val targetActions = new ArrayList(); diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowTransaction.xtend b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowTransaction.xtend index 6fcadea8bf..dc2a7ee6f9 100644 --- a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowTransaction.xtend +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowTransaction.xtend @@ -16,14 +16,16 @@ import org.opendaylight.yangtools.yang.binding.DataObject import org.opendaylight.yangtools.yang.binding.InstanceIdentifier import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowRef +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri class FlowTransaction extends AbstractTransaction { @Property - val SalFlowService salFlowService; + val SalFlowService salFlowService; + new(DataModification, DataObject> modification,SalFlowService salFlowService) { - super(modification) + super(modification) _salFlowService = salFlowService; } @@ -33,9 +35,10 @@ class FlowTransaction extends AbstractTransaction { val tableInstanceId = instanceId.firstIdentifierOf(Table); val nodeInstanceId = instanceId.firstIdentifierOf(Node); val builder = new RemoveFlowInputBuilder(flow); - builder.setFlowRef(new FlowRef(instanceId)); + builder.setFlowRef(new FlowRef(instanceId)); builder.setNode(new NodeRef(nodeInstanceId)); builder.setFlowTable(new FlowTableRef(tableInstanceId)); + builder.setTransactionUri(new Uri(modification.getIdentifier() as String)); _salFlowService.removeFlow(builder.build()); } } @@ -50,6 +53,7 @@ class FlowTransaction extends AbstractTransaction { builder.setFlowRef(new FlowRef(instanceId)); val ufb = new UpdatedFlowBuilder(updatedFlow); builder.setUpdatedFlow((ufb.build())); + builder.setTransactionUri(new Uri(modification.getIdentifier() as String)); val ofb = new OriginalFlowBuilder(originalFlow); builder.setOriginalFlow(ofb.build()); _salFlowService.updateFlow(builder.build()); @@ -64,6 +68,7 @@ class FlowTransaction extends AbstractTransaction { val nodeInstanceId = instanceId.firstIdentifierOf(Node); val builder = new AddFlowInputBuilder(flow); builder.setNode(new NodeRef(nodeInstanceId)); + builder.setTransactionUri(new Uri(modification.getIdentifier() as String)); builder.setFlowRef(new FlowRef(instanceId)); builder.setFlowTable(new FlowTableRef(tableInstanceId)); _salFlowService.addFlow(builder.build()); diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupTransaction.xtend b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupTransaction.xtend index d68ffa09fa..f79c9b61a6 100644 --- a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupTransaction.xtend +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupTransaction.xtend @@ -14,14 +14,15 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node import org.opendaylight.yangtools.yang.binding.DataObject import org.opendaylight.yangtools.yang.binding.InstanceIdentifier +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri class GroupTransaction extends AbstractTransaction { @Property val SalGroupService groupService; - + new(DataModification, DataObject> modification,SalGroupService groupService) { - super(modification) + super(modification) _groupService = groupService; } @@ -31,6 +32,7 @@ class GroupTransaction extends AbstractTransaction { val nodeInstanceId = instanceId.firstIdentifierOf(Node); val builder = new RemoveGroupInputBuilder(group); builder.setNode(new NodeRef(nodeInstanceId)); + builder.setTransactionUri(new Uri(modification.getIdentifier() as String)); builder.setGroupRef(new GroupRef(instanceId)); _groupService.removeGroup(builder.build()); } @@ -46,6 +48,7 @@ class GroupTransaction extends AbstractTransaction { builder.setGroupRef(new GroupRef(instanceId)); val ufb = new UpdatedGroupBuilder(updatedGroup); builder.setUpdatedGroup((ufb.build())); + builder.setTransactionUri(new Uri(modification.getIdentifier() as String)); val ofb = new OriginalGroupBuilder(originalGroup); builder.setOriginalGroup(ofb.build()); _groupService.updateGroup(builder.build()); @@ -60,6 +63,7 @@ class GroupTransaction extends AbstractTransaction { val builder = new AddGroupInputBuilder(group); builder.setNode(new NodeRef(nodeInstanceId)); builder.setGroupRef(new GroupRef(instanceId)); + builder.setTransactionUri(new Uri(modification.getIdentifier() as String)); _groupService.addGroup(builder.build()); } } diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterTransaction.xtend b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterTransaction.xtend index d64f2518a8..594a16c34e 100644 --- a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterTransaction.xtend +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterTransaction.xtend @@ -14,14 +14,15 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.Meter import org.opendaylight.yangtools.yang.binding.DataObject import org.opendaylight.yangtools.yang.binding.InstanceIdentifier import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterRef +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri class MeterTransaction extends AbstractTransaction { @Property val SalMeterService salMeterService; - + new(DataModification, DataObject> modification,SalMeterService salMeterService) { - super(modification) + super(modification) _salMeterService = salMeterService; } @@ -32,6 +33,7 @@ class MeterTransaction extends AbstractTransaction { val builder = new RemoveMeterInputBuilder(meter); builder.setNode(new NodeRef(nodeInstanceId)); builder.setMeterRef(new MeterRef(instanceId)); + builder.setTransactionUri(new Uri(modification.getIdentifier() as String)); _salMeterService.removeMeter(builder.build()); } } @@ -46,6 +48,7 @@ class MeterTransaction extends AbstractTransaction { builder.setMeterRef(new MeterRef(instanceId)); val ufb = new UpdatedMeterBuilder(updatedMeter); builder.setUpdatedMeter((ufb.build())); + builder.setTransactionUri(new Uri(modification.getIdentifier() as String)); val ofb = new OriginalMeterBuilder(originalMeter); builder.setOriginalMeter(ofb.build()); _salMeterService.updateMeter(builder.build()); @@ -60,6 +63,7 @@ class MeterTransaction extends AbstractTransaction { val builder = new AddMeterInputBuilder(meter); builder.setNode(new NodeRef(nodeInstanceId)); builder.setMeterRef(new MeterRef(instanceId)); + builder.setTransactionUri(new Uri(modification.getIdentifier() as String)); _salMeterService.addMeter(builder.build()); } } diff --git a/opendaylight/md-sal/model/model-flow-base/src/main/yang/opendaylight-action-types.yang b/opendaylight/md-sal/model/model-flow-base/src/main/yang/opendaylight-action-types.yang index 43754a1dfd..3cc490f017 100644 --- a/opendaylight/md-sal/model/model-flow-base/src/main/yang/opendaylight-action-types.yang +++ b/opendaylight/md-sal/model/model-flow-base/src/main/yang/opendaylight-action-types.yang @@ -49,9 +49,7 @@ module opendaylight-action-types { } leaf max-length { - type uint16 { - range "0..65294"; - } + type uint16; } } } @@ -59,9 +57,7 @@ module opendaylight-action-types { case controller-action-case { container controller-action { leaf max-length { - type uint16 { - range "0..65294"; - } + type uint16; } } } diff --git a/opendaylight/md-sal/model/model-flow-service/src/main/yang/flow-node-inventory.yang b/opendaylight/md-sal/model/model-flow-service/src/main/yang/flow-node-inventory.yang index e55c50fb29..0f5cc71e8b 100644 --- a/opendaylight/md-sal/model/model-flow-service/src/main/yang/flow-node-inventory.yang +++ b/opendaylight/md-sal/model/model-flow-service/src/main/yang/flow-node-inventory.yang @@ -92,7 +92,7 @@ module flow-node-inventory { } typedef flow-id { - type uint32; // Note: This doesn't really belong here, and not sure if unint32 is right + type inet:uri; } grouping tables { diff --git a/opendaylight/md-sal/model/model-flow-service/src/main/yang/packet-processing.yang b/opendaylight/md-sal/model/model-flow-service/src/main/yang/packet-processing.yang index bfdf5049c3..00ecdbacf0 100644 --- a/opendaylight/md-sal/model/model-flow-service/src/main/yang/packet-processing.yang +++ b/opendaylight/md-sal/model/model-flow-service/src/main/yang/packet-processing.yang @@ -6,6 +6,8 @@ module packet-processing { import opendaylight-inventory {prefix inv;revision-date "2013-08-19";} import ietf-yang-types {prefix yang;revision-date "2010-09-24";} import opendaylight-l2-types {prefix types;revision-date "2013-08-27";} + import opendaylight-match-types {prefix match-type;revision-date "2013-10-26";} + import opendaylight-table-types {prefix table-type;revision-date "2013-10-26";} revision "2013-07-09" { description ""; @@ -34,11 +36,44 @@ module packet-processing { } } + identity packet-in-reason { + description "Base identity for all the available packet in reason"; + } + + identity no-match { + base packet-in-reason; + description "No matching flow in the classifier"; + } + + identity send-to-controller { + base packet-in-reason; + description "Explicit instruction to send packet to controller"; + } + + identity invalid-ttl { + base packet-in-reason; + description "Packet with invalid TTL"; + } notification packet-received { leaf cookie { type cookie; } + + leaf table-id { + type table-type:table-id; + } + + leaf packet-in-reason { + type identityref { + base packet-in-reason; + } + } + + container match { + uses match-type:match; + } + uses raw-packet; } @@ -56,4 +91,4 @@ module packet-processing { uses raw-packet; } } -} \ No newline at end of file +} diff --git a/opendaylight/md-sal/model/model-flow-statistics/src/main/yang/flow-statistics.yang b/opendaylight/md-sal/model/model-flow-statistics/src/main/yang/flow-statistics.yang index 7bbcca3a12..2b1d993026 100644 --- a/opendaylight/md-sal/model/model-flow-statistics/src/main/yang/flow-statistics.yang +++ b/opendaylight/md-sal/model/model-flow-statistics/src/main/yang/flow-statistics.yang @@ -11,6 +11,7 @@ module opendaylight-flow-statistics { import flow-node-inventory {prefix flow-node;revision-date "2013-08-19";} import flow-capable-transaction {prefix tr;} import sal-flow {prefix flow;} + import ietf-inet-types {prefix inet; revision-date "2010-09-24";} revision "2013-08-19" { @@ -33,7 +34,7 @@ module opendaylight-flow-statistics { typedef flow-id { description "flow id"; - type yang:counter32; + type inet:uri; } grouping flow-and-statistics-map-list { diff --git a/opendaylight/md-sal/model/model-inventory/src/main/yang/netconf-node-inventory.yang b/opendaylight/md-sal/model/model-inventory/src/main/yang/netconf-node-inventory.yang new file mode 100644 index 0000000000..b5cde6ee5b --- /dev/null +++ b/opendaylight/md-sal/model/model-inventory/src/main/yang/netconf-node-inventory.yang @@ -0,0 +1,27 @@ +module netconf-node-inventory { + namespace "urn:opendaylight:netconf-node-inventory"; + prefix "netinv"; + + import opendaylight-inventory { prefix inv; revision-date "2013-08-19";} + import yang-ext {prefix ext; revision-date "2013-07-09";} + + revision "2014-01-08" { + description "Initial revision of Inventory model"; + } + + grouping netconf-node-fields { + leaf-list initial-capability { + type string; + } + + leaf-list current-capability { + type string; + } + } + + augment /inv:nodes/inv:node { + ext:augment-identifier "netconf-node"; + + uses netconf-node-fields; + } +} \ No newline at end of file diff --git a/opendaylight/md-sal/model/model-topology/pom.xml b/opendaylight/md-sal/model/model-topology/pom.xml index c91b9dd53a..e2ce7a9735 100644 --- a/opendaylight/md-sal/model/model-topology/pom.xml +++ b/opendaylight/md-sal/model/model-topology/pom.xml @@ -17,15 +17,15 @@ bundle - - org.opendaylight.controller.model - model-inventory - 1.0-SNAPSHOT - - - org.opendaylight.yangtools.model - ietf-topology - 2013.07.12.2-SNAPSHOT - + + org.opendaylight.controller.model + model-inventory + 1.0-SNAPSHOT + + + org.opendaylight.yangtools.model + ietf-topology + 2013.10.21.0-SNAPSHOT + diff --git a/opendaylight/md-sal/model/model-topology/src/main/yang/opendaylight-topology-inventory.yang b/opendaylight/md-sal/model/model-topology/src/main/yang/opendaylight-topology-inventory.yang index ceeef45f23..87de0f5ae1 100644 --- a/opendaylight/md-sal/model/model-topology/src/main/yang/opendaylight-topology-inventory.yang +++ b/opendaylight/md-sal/model/model-topology/src/main/yang/opendaylight-topology-inventory.yang @@ -8,7 +8,7 @@ module opendaylight-topology-inventory { import ietf-inet-types { prefix "inet"; } import opendaylight-inventory {prefix "inv";} import opendaylight-topology {prefix "odt";} - import network-topology {prefix "topo";} + import network-topology {prefix "topo"; revision-date "2013-07-12"; } organization "TBD"; @@ -33,4 +33,4 @@ module opendaylight-topology-inventory { type inv:node-connector-ref; } } -} \ No newline at end of file +} diff --git a/opendaylight/md-sal/model/model-topology/src/main/yang/opendaylight-topology.yang b/opendaylight/md-sal/model/model-topology/src/main/yang/opendaylight-topology.yang index 038a1b7c67..6bbfd4b479 100644 --- a/opendaylight/md-sal/model/model-topology/src/main/yang/opendaylight-topology.yang +++ b/opendaylight/md-sal/model/model-topology/src/main/yang/opendaylight-topology.yang @@ -7,7 +7,7 @@ module opendaylight-topology { import yang-ext { prefix "ext"; } import ietf-inet-types { prefix "inet"; } import opendaylight-inventory {prefix "inv";} - import network-topology {prefix "topo";} + import network-topology {prefix "topo"; revision-date "2013-07-12"; } organization "TBD"; diff --git a/opendaylight/md-sal/model/model-topology/src/main/yang/topology-view.yang b/opendaylight/md-sal/model/model-topology/src/main/yang/topology-view.yang index 2fecb327ca..1a10bf6fdd 100644 --- a/opendaylight/md-sal/model/model-topology/src/main/yang/topology-view.yang +++ b/opendaylight/md-sal/model/model-topology/src/main/yang/topology-view.yang @@ -6,7 +6,7 @@ module opendaylight-topology-view { import yang-ext { prefix "ext"; } import ietf-inet-types { prefix "inet"; } - import network-topology {prefix "topo";} + import network-topology {prefix "topo"; revision-date "2013-07-12"; } import opendaylight-topology {prefix "odl";} organization "TBD"; @@ -45,4 +45,4 @@ module opendaylight-topology-view { ext:augment-identifier "aggregated-node"; uses aggregate-node; } -} \ No newline at end of file +} diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/AugmentationCodec.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/AugmentationCodec.java index cdddec76d4..970e077c03 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/AugmentationCodec.java +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/AugmentationCodec.java @@ -1,6 +1,7 @@ package org.opendaylight.controller.sal.binding.dom.serializer.api; import org.opendaylight.yangtools.yang.binding.Augmentation; +import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.CompositeNode; import org.opendaylight.yangtools.yang.data.api.Node; @@ -12,4 +13,6 @@ public interface AugmentationCodec> extends DomCodec deserialize(Node input); + + public QName getAugmentationQName(); } diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/CodecRegistry.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/CodecRegistry.java index b9a4fe87ac..4565b545ba 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/CodecRegistry.java +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/CodecRegistry.java @@ -10,6 +10,7 @@ import java.util.List; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.controller.sal.binding.dom.serializer.api.IdentifierCodec; +import org.opendaylight.yangtools.yang.binding.DataObject; public interface CodecRegistry { @@ -36,4 +37,6 @@ public interface CodecRegistry { void bindingClassEncountered(Class cls); void putPathToClass(List names, Class cls); + + public abstract QName getQNameForAugmentation(Class cls); } diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/InstanceIdentifierCodecImpl.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/InstanceIdentifierCodecImpl.xtend index 150d0f199f..f84503bea4 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/InstanceIdentifierCodecImpl.xtend +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/InstanceIdentifierCodecImpl.xtend @@ -26,13 +26,13 @@ import org.opendaylight.yangtools.yang.binding.Augmentable import com.google.common.collect.ImmutableList import org.opendaylight.yangtools.yang.binding.Augmentation import java.util.concurrent.ConcurrentHashMap +import org.opendaylight.yangtools.yang.binding.util.BindingReflections class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec { private static val LOG = LoggerFactory.getLogger(InstanceIdentifierCodecImpl); val CodecRegistry codecRegistry; - val Map,QName> classToQName = new WeakHashMap; val Map, Map, Class>> classToPreviousAugment = new WeakHashMap; public new(CodecRegistry registry) { @@ -106,7 +106,7 @@ class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec { previousAugmentation = null; } else { - previousQName = resolveQname(baArg.type); + previousQName = codecRegistry.getQNameForAugmentation(baArg.type as Class); previousAugmentation = baArg.type; } } @@ -122,7 +122,7 @@ class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec { private def dispatch PathArgument serializePathArgument(Item argument, QName previousQname) { val type = argument.type; - val qname = resolveQname(type); + val qname = BindingReflections.findQName(type); if(previousQname == null) { return new NodeIdentifier(qname); } @@ -134,7 +134,7 @@ class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec { val Map predicates = new HashMap(); val type = argument.type; val keyCodec = codecRegistry.getIdentifierCodecForIdentifiable(type); - val qname = resolveQname(type); + val qname = BindingReflections.findQName(type); val combinedInput = new ValueWithQName(previousQname,argument.key) val compositeOutput = keyCodec.serialize(combinedInput as ValueWithQName); for(outputValue :compositeOutput.value) { @@ -145,15 +145,4 @@ class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec { } return new NodeIdentifierWithPredicates(QName.create(previousQname,qname.localName),predicates); } - - def resolveQname(Class class1) { - val qname = classToQName.get(class1); - if(qname !== null) { - return qname; - } - val qnameField = class1.getField("QNAME"); - val qnameValue = qnameField.get(null) as QName; - classToQName.put(class1,qnameValue); - return qnameValue; - } } \ No newline at end of file diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/LazyGeneratedCodecRegistry.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/LazyGeneratedCodecRegistry.java index cabb1bc4e2..89d9b49081 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/LazyGeneratedCodecRegistry.java +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/LazyGeneratedCodecRegistry.java @@ -44,6 +44,7 @@ import org.opendaylight.yangtools.yang.binding.BindingCodec; import org.opendaylight.yangtools.yang.binding.DataContainer; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.Identifier; +import org.opendaylight.yangtools.yang.binding.util.BindingReflections; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.CompositeNode; import org.opendaylight.yangtools.yang.data.api.Node; @@ -153,6 +154,12 @@ public class LazyGeneratedCodecRegistry implements // } return codec; } + + @Override + public QName getQNameForAugmentation(Class cls) { + checkArgument(Augmentation.class.isAssignableFrom(cls)); + return getCodecForAugmentation((Class)cls).getAugmentationQName(); + } private static Class> getAugmentableArgumentFrom( final Class> augmentation) { @@ -909,9 +916,11 @@ public class LazyGeneratedCodecRegistry implements // Delegator { private BindingCodec delegate; + private QName augmentationQName; public AugmentationCodecWrapper(BindingCodec, Object> rawCodec) { this.delegate = rawCodec; + this.augmentationQName = BindingReflections.findQName(rawCodec.getClass()); } @Override @@ -936,6 +945,11 @@ public class LazyGeneratedCodecRegistry implements // Object rawCodecValue = getDelegate().deserialize((Map) input); return new ValueWithQName(input.getNodeType(), (T) rawCodecValue); } + + @Override + public QName getAugmentationQName() { + return augmentationQName; + } } private class IdentityCompositeCodec implements IdentitityCodec { diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/NotificationBrokerImpl.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/NotificationBrokerImpl.xtend index b10c06f0c5..b0939a043f 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/NotificationBrokerImpl.xtend +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/NotificationBrokerImpl.xtend @@ -20,8 +20,9 @@ import org.opendaylight.yangtools.concepts.AbstractObjectRegistration import org.opendaylight.yangtools.concepts.ListenerRegistration import org.opendaylight.yangtools.concepts.Registration import org.opendaylight.yangtools.yang.binding.Notification -import org.slf4j.LoggerFactory import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder - +import org.slf4j.LoggerFactory +import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder + class NotificationBrokerImpl implements NotificationProviderService, AutoCloseable { val Multimap, NotificationListener> listeners; @@ -178,10 +179,19 @@ class NotifyTask implements Callable { val Notification notification; override call() { + //Only logging the complete notification in debug mode try { - log.info("Delivering notification {} to {}",notification,listener); + if(log.isDebugEnabled){ + log.debug("Delivering notification {} to {}",notification,listener); + } else { + log.info("Delivering notification {} to {}",notification.class.name,listener); + } listener.onNotification(notification); - log.info("Notification delivered {} to {}",notification,listener); + if(log.isDebugEnabled){ + log.debug("Notification delivered {} to {}",notification,listener); + } else { + log.info("Notification delivered {} to {}",notification.class.name,listener); + } } catch (Exception e) { log.error("Unhandled exception thrown by listener: {}", listener, e); } diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/FlagsSerializationTest.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/FlagsSerializationTest.java index 1304f0d52a..e31ae6b8c7 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/FlagsSerializationTest.java +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/FlagsSerializationTest.java @@ -1,35 +1,10 @@ package org.opendaylight.controller.sal.binding.test.bugfix; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - - - - - - - - - - - - - - - - - - - +import com.google.common.collect.ImmutableSet; import org.junit.Test; import org.opendaylight.controller.md.sal.common.api.TransactionStatus; -import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest; import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; +import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopMplsActionCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.mpls.action._case.PopMplsActionBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action; @@ -48,16 +23,13 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instru import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; @@ -65,21 +37,21 @@ import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.data.api.CompositeNode; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.ListeningExecutorService; -import com.google.common.util.concurrent.MoreExecutors; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; public class FlagsSerializationTest extends AbstractDataServiceTest { private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id"); private static final QName FLOW_ID_QNAME = QName.create(Flow.QNAME, "id"); private static final QName FLOW_NODE_QNAME = QName.create(Flow.QNAME, "node"); - private static final long FLOW_ID = 1234; + private static final String FLOW_ID = "1234"; private static final short TABLE_ID = (short)0; private static final String NODE_ID = "node:1"; diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java index ea36f81b0b..55bff1a5c7 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java @@ -1,15 +1,6 @@ package org.opendaylight.controller.sal.binding.test.connect.dom; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.concurrent.Future; - +import com.google.common.collect.ImmutableMap; import org.junit.Test; import org.opendaylight.controller.md.sal.common.api.TransactionStatus; import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler; @@ -17,13 +8,11 @@ import org.opendaylight.controller.md.sal.common.api.data.DataModification; import org.opendaylight.controller.sal.binding.impl.connect.dom.CommitHandlersTransactions; import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest; import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpVersion; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DecNwTtlCaseBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopMplsActionCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.dec.nw.ttl._case.DecNwTtl; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.dec.nw.ttl._case.DecNwTtlBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.mpls.action._case.PopMplsActionBuilder; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpVersion; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey; @@ -44,14 +33,10 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatchBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder; import org.opendaylight.yangtools.concepts.Registration; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; @@ -59,7 +44,14 @@ import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.data.api.CompositeNode; -import com.google.common.collect.ImmutableMap; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; public class ChangeOriginatedInDomBrokerTest extends AbstractDataServiceTest { @@ -69,7 +61,7 @@ public class ChangeOriginatedInDomBrokerTest extends AbstractDataServiceTest { private static final QName TABLE_ID_QNAME = QName.create(Table.QNAME, "id"); private static final String NODE_ID = "node:1"; - private static final FlowId FLOW_ID = new FlowId(1234L); + private static final FlowId FLOW_ID = new FlowId("1234"); private static final Short TABLE_ID = Short.valueOf((short) 0); private static final NodeKey NODE_KEY = new NodeKey(new NodeId(NODE_ID)); diff --git a/opendaylight/md-sal/sal-dom-broker/pom.xml b/opendaylight/md-sal/sal-dom-broker/pom.xml index 4740b0d569..10e7946a7b 100644 --- a/opendaylight/md-sal/sal-dom-broker/pom.xml +++ b/opendaylight/md-sal/sal-dom-broker/pom.xml @@ -30,11 +30,6 @@ sal-common-impl 1.0-SNAPSHOT - - org.opendaylight.controller - sal-common-impl - 1.0-SNAPSHOT - org.opendaylight.controller sal-core-spi diff --git a/opendaylight/md-sal/sal-netconf-connector/pom.xml b/opendaylight/md-sal/sal-netconf-connector/pom.xml index 2323b09f99..67e2934a0e 100644 --- a/opendaylight/md-sal/sal-netconf-connector/pom.xml +++ b/opendaylight/md-sal/sal-netconf-connector/pom.xml @@ -98,12 +98,6 @@ test ${netconf.version} - - ${project.groupId} - yang-test - test - ${netconf.version} - ${project.groupId} config-manager diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/pom.xml b/opendaylight/md-sal/sal-remoterpc-connector/implementation/pom.xml index 6c72a610a7..d5648a0625 100644 --- a/opendaylight/md-sal/sal-remoterpc-connector/implementation/pom.xml +++ b/opendaylight/md-sal/sal-remoterpc-connector/implementation/pom.xml @@ -61,10 +61,6 @@ org.opendaylight.yangtools yang-data-impl - - org.opendaylight.yangtools - yang-common - diff --git a/opendaylight/md-sal/sal-rest-connector/pom.xml b/opendaylight/md-sal/sal-rest-connector/pom.xml index 5e798b6720..0bd86a3ead 100644 --- a/opendaylight/md-sal/sal-rest-connector/pom.xml +++ b/opendaylight/md-sal/sal-rest-connector/pom.xml @@ -42,7 +42,7 @@ yang-data-impl ${yang.version} - + org.opendaylight.yangtools yang-model-util ${yang.version} @@ -82,11 +82,6 @@ 2.4 test - - org.opendaylight.yangtools - yang-model-util - 0.5.9-SNAPSHOT - diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfService.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfService.java index 012b51fb5e..60a8f285a2 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfService.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfService.java @@ -7,6 +7,8 @@ */ package org.opendaylight.controller.sal.rest.api; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; @@ -66,30 +68,50 @@ public interface RestconfService extends RestconfServiceLegacy { @Produces({Draft01.MediaTypes.DATA+JSON,Draft01.MediaTypes.DATA+XML, Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML, MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML}) + @Consumes({Draft01.MediaTypes.DATA+JSON,Draft01.MediaTypes.DATA+XML, + Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML, + MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML}) public StructuredData invokeRpc(@PathParam("identifier") String identifier, CompositeNode payload); + @POST + @Path("/operations/{identifier}") + @Produces({Draft01.MediaTypes.DATA+JSON,Draft01.MediaTypes.DATA+XML, + Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML, + MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML}) + public StructuredData invokeRpc(@PathParam("identifier") String identifier); + @GET @Path("/config/{identifier:.+}") @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML, MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML}) public StructuredData readConfigurationData(@PathParam("identifier") String identifier); - - @POST - @Path("/config/{identifier:.+}") + + @GET + @Path("/operational/{identifier:.+}") @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML, MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML}) - public Response createConfigurationData(@PathParam("identifier") String identifier, CompositeNode payload); + public StructuredData readOperationalData(@PathParam("identifier") String identifier); @PUT @Path("/config/{identifier:.+}") - @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML, + @Consumes({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML, MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML}) public Response updateConfigurationData(@PathParam("identifier") String identifier, CompositeNode payload); - @GET - @Path("/operational/{identifier:.+}") - @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML, + @POST + @Path("/config/{identifier:.+}") + @Consumes({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML, MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML}) - public StructuredData readOperationalData(@PathParam("identifier") String identifier); + public Response createConfigurationData(@PathParam("identifier") String identifier, CompositeNode payload); + + @POST + @Path("/config") + @Consumes({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML, + MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML}) + public Response createConfigurationData(CompositeNode payload); + + @DELETE + @Path("/config/{identifier:.+}") + public Response deleteConfigurationData(@PathParam("identifier") String identifier); } diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfServiceLegacy.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfServiceLegacy.java index 35da98b1a0..9b69c1f09a 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfServiceLegacy.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfServiceLegacy.java @@ -1,5 +1,6 @@ package org.opendaylight.controller.sal.rest.api; +import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; @@ -33,14 +34,14 @@ public interface RestconfServiceLegacy { @Deprecated @POST @Path("/datastore/{identifier:.+}") - @Produces({Draft01.MediaTypes.DATA+JSON,Draft01.MediaTypes.DATA+XML, + @Consumes({Draft01.MediaTypes.DATA+JSON,Draft01.MediaTypes.DATA+XML, MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML}) public Response createConfigurationDataLegacy(@PathParam("identifier") String identifier, CompositeNode payload); @Deprecated @PUT @Path("/datastore/{identifier:.+}") - @Produces({Draft01.MediaTypes.DATA+JSON,Draft01.MediaTypes.DATA+XML, + @Consumes({Draft01.MediaTypes.DATA+JSON,Draft01.MediaTypes.DATA+XML, MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML}) public Response updateConfigurationDataLegacy(@PathParam("identifier") String identifier, CompositeNode payload); diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonMapper.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonMapper.java index 8b1bdef8ba..7f7e8606c3 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonMapper.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonMapper.java @@ -194,7 +194,7 @@ class JsonMapper { if (node.getValue() instanceof QName) { IdentityValuesDTO valueDTO = (IdentityValuesDTO) RestCodec.from(baseType).serialize(node.getValue()); IdentityValue valueFromDTO = valueDTO.getValuesWithNamespaces().get(0); - String moduleName = ControllerContext.getInstance().findModuleByNamespace( + String moduleName = ControllerContext.getInstance().findModuleNameByNamespace( URI.create(valueFromDTO.getNamespace())); writer.value(moduleName + ":" + valueFromDTO.getValue()); } else { diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/BrokerFacade.xtend b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/BrokerFacade.xtend index df6b58c897..343601865d 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/BrokerFacade.xtend +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/BrokerFacade.xtend @@ -41,13 +41,13 @@ class BrokerFacade implements DataReader { override readConfigurationData(InstanceIdentifier path) { checkPreconditions - LOG.info("Read Configuration via Restconf: {}",path) + LOG.info("Read Configuration via Restconf: {}", path) return dataService.readConfigurationData(path); } override readOperationalData(InstanceIdentifier path) { checkPreconditions - LOG.info("Read Operational via Restconf: {}",path) + LOG.info("Read Operational via Restconf: {}", path) return dataService.readOperationalData(path); } @@ -60,15 +60,28 @@ class BrokerFacade implements DataReader { def commitConfigurationDataPut(InstanceIdentifier path, CompositeNode payload) { checkPreconditions val transaction = dataService.beginTransaction; + LOG.info("Put Configuration via Restconf: {}", path) transaction.putConfigurationData(path, payload); - return transaction.commit() + return transaction.commit } - def commitOperationalDataPut(InstanceIdentifier path, CompositeNode payload) { + def commitConfigurationDataPost(InstanceIdentifier path, CompositeNode payload) { checkPreconditions val transaction = dataService.beginTransaction; - transaction.putOperationalData(path, payload); - return transaction.commit() + transaction.putConfigurationData(path, payload); + if (payload == transaction.createdConfigurationData.get(path)) { + LOG.info("Post Configuration via Restconf: {}", path) + return transaction.commit + } + LOG.info("Post Configuration via Restconf was not executed because data already exists: {}", path) + return null; } - + + def commitConfigurationDataDelete(InstanceIdentifier path) { + checkPreconditions + val transaction = dataService.beginTransaction; + transaction.removeConfigurationData(path) + return transaction.commit + } + } diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/CompositeNodeWrapper.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/CompositeNodeWrapper.java index 0ded60dae4..74a32d452e 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/CompositeNodeWrapper.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/CompositeNodeWrapper.java @@ -78,6 +78,11 @@ public final class CompositeNodeWrapper implements NodeWrapper, C Preconditions.checkState(compositeNode == null, "Data can be inconsistent."); return Collections.unmodifiableList(values); } + + @Override + public boolean isChangeAllowed() { + return compositeNode == null ? true : false; + } @Override public CompositeNode unwrap() { @@ -230,4 +235,5 @@ public final class CompositeNodeWrapper implements NodeWrapper, C public Set>>> entrySet() { return unwrap().entrySet(); } + } diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.xtend b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.xtend index 1a60e14589..308975c8c5 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.xtend +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.xtend @@ -12,6 +12,7 @@ import java.util.Map import java.util.concurrent.ConcurrentHashMap import javax.ws.rs.core.Response import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener +import org.opendaylight.controller.sal.core.api.mount.MountService import org.opendaylight.controller.sal.rest.impl.RestUtil import org.opendaylight.controller.sal.rest.impl.RestconfProvider import org.opendaylight.yangtools.yang.common.QName @@ -26,16 +27,17 @@ import org.opendaylight.yangtools.yang.model.api.ChoiceNode 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.LeafListSchemaNode import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode import org.opendaylight.yangtools.yang.model.api.ListSchemaNode +import org.opendaylight.yangtools.yang.model.api.Module import org.opendaylight.yangtools.yang.model.api.RpcDefinition import org.opendaylight.yangtools.yang.model.api.SchemaContext import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition import org.slf4j.LoggerFactory import static com.google.common.base.Preconditions.* -import org.opendaylight.controller.sal.core.api.mount.MountService -import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode +import java.util.ArrayList class ControllerContext implements SchemaServiceListener { val static LOG = LoggerFactory.getLogger(ControllerContext) @@ -73,6 +75,7 @@ class ControllerContext implements SchemaServiceListener { } public def InstanceIdWithSchemaNode toInstanceIdentifier(String restconfInstance) { + checkPreconditions val ret = InstanceIdentifier.builder(); val pathArgs = restconfInstance.split("/"); if (pathArgs.empty) { @@ -81,24 +84,28 @@ class ControllerContext implements SchemaServiceListener { if (pathArgs.head.empty) { pathArgs.remove(0) } - val schemaNode = ret.collectPathArguments(pathArgs, globalSchema.findModule(pathArgs.head)); + val mountPoints = new ArrayList + val schemaNode = ret.collectPathArguments(pathArgs, globalSchema.findModule(pathArgs.head), mountPoints); if (schemaNode === null) { return null } - return new InstanceIdWithSchemaNode(ret.toInstance, schemaNode) + return new InstanceIdWithSchemaNode(ret.toInstance, schemaNode, mountPoints.last) } - private static def findModule(SchemaContext context,String argument) { - //checkPreconditions + private def findModule(SchemaContext context,String argument) { checkNotNull(argument); val startModule = argument.toModuleName(); return context.getLatestModule(startModule) } - - static def getLatestModule(SchemaContext schema,String moduleName) { - checkArgument(schema != null); + + private def getLatestModule(SchemaContext schema,String moduleName) { + checkArgument(schema !== null); checkArgument(moduleName !== null && !moduleName.empty) val modules = schema.modules.filter[m|m.name == moduleName] + return modules.filterLatestModule + } + + private def filterLatestModule(Iterable modules) { var latestModule = modules.head for (module : modules) { if (module.revision.after(latestModule.revision)) { @@ -107,6 +114,31 @@ class ControllerContext implements SchemaServiceListener { } return latestModule } + + def findModuleByName(String moduleName) { + checkPreconditions + checkArgument(moduleName !== null && !moduleName.empty) + return globalSchema.getLatestModule(moduleName) + } + + def findModuleByName(String moduleName, InstanceIdentifier partialPath) { + checkArgument(moduleName !== null && !moduleName.empty && partialPath !== null && !partialPath.path.empty) + val mountPointSchema = mountService?.getMountPoint(partialPath)?.schemaContext; + return mountPointSchema?.getLatestModule(moduleName); + } + + def findModuleByNamespace(URI namespace) { + checkPreconditions + val moduleSchemas = globalSchema.findModuleByNamespace(namespace) + return moduleSchemas?.filterLatestModule + } + + def findModuleByNamespace(URI namespace, InstanceIdentifier partialPath) { + checkArgument(namespace !== null && !namespace.toString.empty && partialPath !== null && !partialPath.path.empty) + val mountPointSchema = mountService?.getMountPoint(partialPath)?.schemaContext; + val moduleSchemas = mountPointSchema?.findModuleByNamespace(namespace) + return moduleSchemas?.filterLatestModule + } def String toFullRestconfIdentifier(InstanceIdentifier path) { checkPreconditions @@ -136,18 +168,13 @@ class ControllerContext implements SchemaServiceListener { throw new IllegalArgumentException("Conversion of generic path argument is not supported"); } - def findModuleByNamespace(URI namespace) { + def findModuleNameByNamespace(URI namespace) { checkPreconditions var module = uriToModuleName.get(namespace) if (module === null) { val moduleSchemas = globalSchema.findModuleByNamespace(namespace); if(moduleSchemas === null) return null - var latestModule = moduleSchemas.head - for (m : moduleSchemas) { - if (m.revision.after(latestModule.revision)) { - latestModule = m - } - } + var latestModule = moduleSchemas.filterLatestModule if(latestModule === null) return null uriToModuleName.put(namespace, latestModule.name) module = latestModule.name; @@ -155,16 +182,10 @@ class ControllerContext implements SchemaServiceListener { return module } - def findNamespaceByModule(String module) { + def findNamespaceByModuleName(String module) { var namespace = moduleNameToUri.get(module) if (namespace === null) { - val moduleSchemas = globalSchema.modules.filter[it|it.name.equals(module)] - var latestModule = moduleSchemas.head - for (m : moduleSchemas) { - if (m.revision.after(latestModule.revision)) { - latestModule = m - } - } + var latestModule = globalSchema.getLatestModule(module) if(latestModule === null) return null namespace = latestModule.namespace uriToModuleName.put(namespace, latestModule.name) @@ -235,7 +256,7 @@ class ControllerContext implements SchemaServiceListener { } private def DataSchemaNode collectPathArguments(InstanceIdentifierBuilder builder, List strings, - DataNodeContainer parentNode) { + DataNodeContainer parentNode, List mountPoints) { checkNotNull(strings) if (parentNode === null) { return null; @@ -255,8 +276,12 @@ class ControllerContext implements SchemaServiceListener { // Node is possibly in other mount point val partialPath = builder.toInstance; val mountPointSchema = mountService?.getMountPoint(partialPath)?.schemaContext; - if(mountPointSchema != null) { - return builder.collectPathArguments(strings, mountPointSchema.findModule(strings.head)); + if(mountPointSchema !== null) { + val module = mountPointSchema.findModule(strings.head) + if (module !== null) { + mountPoints.add(partialPath) + } + return builder.collectPathArguments(strings, module, mountPoints); } return null } @@ -294,7 +319,7 @@ class ControllerContext implements SchemaServiceListener { } if (targetNode instanceof DataNodeContainer) { val remaining = strings.subList(consumed, strings.length); - val result = builder.collectPathArguments(remaining, targetNode as DataNodeContainer); + val result = builder.collectPathArguments(remaining, targetNode as DataNodeContainer, mountPoints); return result } @@ -310,7 +335,7 @@ class ControllerContext implements SchemaServiceListener { val allCases = container.childNodes.filter(ChoiceNode).map[cases].flatten for (caze : allCases) { potentialNode = caze.findInstanceDataChild(name); - if(potentialNode != null) { + if(potentialNode !== null) { return potentialNode; } } diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/EmptyNodeWrapper.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/EmptyNodeWrapper.java index c146954dce..cdb9599a46 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/EmptyNodeWrapper.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/EmptyNodeWrapper.java @@ -64,6 +64,11 @@ public final class EmptyNodeWrapper implements NodeWrapper>, Node this.namespace = namespace; } + @Override + public boolean isChangeAllowed() { + return unwrapped == null ? true : false; + } + @Override public Node unwrap() { if (unwrapped == null) { diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/InstanceIdWithSchemaNode.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/InstanceIdWithSchemaNode.java index ad0654af78..ba0e47ff92 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/InstanceIdWithSchemaNode.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/InstanceIdWithSchemaNode.java @@ -7,10 +7,12 @@ public class InstanceIdWithSchemaNode { private final InstanceIdentifier instanceIdentifier; private final DataSchemaNode schemaNode; + private final InstanceIdentifier mountPoint; - public InstanceIdWithSchemaNode(InstanceIdentifier instanceIdentifier, DataSchemaNode schemaNode) { + public InstanceIdWithSchemaNode(InstanceIdentifier instanceIdentifier, DataSchemaNode schemaNode, InstanceIdentifier mountPoint) { this.instanceIdentifier = instanceIdentifier; this.schemaNode = schemaNode; + this.mountPoint = mountPoint; } public InstanceIdentifier getInstanceIdentifier() { @@ -21,4 +23,8 @@ public class InstanceIdWithSchemaNode { return schemaNode; } + public InstanceIdentifier getMountPoint() { + return mountPoint; + } + } diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/NodeWrapper.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/NodeWrapper.java index 675e119439..6b8665f765 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/NodeWrapper.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/NodeWrapper.java @@ -11,6 +11,8 @@ public interface NodeWrapper> { T unwrap(); + boolean isChangeAllowed(); + URI getNamespace(); void setNamespace(URI namespace); diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestCodec.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestCodec.java index 40fba88356..45f3f7f30b 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestCodec.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestCodec.java @@ -107,7 +107,7 @@ public class RestCodec { public QName deserialize(IdentityValuesDTO data) { IdentityValue valueWithNamespace = data.getValuesWithNamespaces().get(0); String namespace = valueWithNamespace.getNamespace(); - URI validNamespace = ControllerContext.getInstance().findNamespaceByModule(namespace); + URI validNamespace = ControllerContext.getInstance().findNamespaceByModuleName(namespace); if (validNamespace == null) { validNamespace = URI.create(namespace); } diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend index 4645a411c1..a65c0ff97a 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend @@ -1,6 +1,7 @@ package org.opendaylight.controller.sal.restconf.impl import java.util.ArrayList +import java.util.HashMap import java.util.List import java.util.Set import javax.ws.rs.core.Response @@ -8,6 +9,8 @@ import org.opendaylight.controller.md.sal.common.api.TransactionStatus import org.opendaylight.controller.sal.rest.api.RestconfService import org.opendaylight.yangtools.yang.common.QName import org.opendaylight.yangtools.yang.data.api.CompositeNode +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.InstanceIdentifierBuilder import org.opendaylight.yangtools.yang.data.api.Node import org.opendaylight.yangtools.yang.data.impl.NodeFactory import org.opendaylight.yangtools.yang.model.api.ChoiceNode @@ -17,10 +20,12 @@ import org.opendaylight.yangtools.yang.model.api.DataSchemaNode import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode import org.opendaylight.yangtools.yang.model.api.ListSchemaNode +import org.opendaylight.yangtools.yang.model.api.Module import org.opendaylight.yangtools.yang.model.api.TypeDefinition import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition import static javax.ws.rs.core.Response.Status.* +import org.opendaylight.yangtools.yang.model.api.RpcDefinition class RestconfImpl implements RestconfService { @@ -55,41 +60,27 @@ class RestconfImpl implements RestconfService { return null; } - override readData(String identifier) { - val instanceIdentifierWithSchemaNode = identifier.resolveInstanceIdentifier - val data = broker.readOperationalData(instanceIdentifierWithSchemaNode.getInstanceIdentifier); - return new StructuredData(data, instanceIdentifierWithSchemaNode.schemaNode) - } - - override createConfigurationData(String identifier, CompositeNode payload) { - val identifierWithSchemaNode = identifier.resolveInstanceIdentifier - val value = normalizeNode(payload, identifierWithSchemaNode.schemaNode) - val status = broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier, value).get(); - switch status.result { - case TransactionStatus.COMMITED: Response.status(NO_CONTENT).build - default: Response.status(INTERNAL_SERVER_ERROR).build - } + override invokeRpc(String identifier, CompositeNode payload) { + return callRpc(identifier.rpcDefinition, payload) } - - override updateConfigurationData(String identifier, CompositeNode payload) { - val identifierWithSchemaNode = identifier.resolveInstanceIdentifier - val value = normalizeNode(payload, identifierWithSchemaNode.schemaNode) - val status = broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier, value).get(); - switch status.result { - case TransactionStatus.COMMITED: Response.status(OK).build - default: Response.status(INTERNAL_SERVER_ERROR).build - } + + override invokeRpc(String identifier) { + return callRpc(identifier.rpcDefinition, null) } - - override invokeRpc(String identifier, CompositeNode payload) { - val rpc = identifier.rpcDefinition + + private def StructuredData callRpc(RpcDefinition rpc, CompositeNode payload) { if (rpc === null) { throw new ResponseException(NOT_FOUND, "RPC does not exist."); } - val value = normalizeNode(payload, rpc.input) - val List> input = new ArrayList - input.add(value) - val rpcRequest = NodeFactory.createMutableCompositeNode(rpc.QName, null, input, null, null) + var CompositeNode rpcRequest; + if (payload === null) { + rpcRequest = NodeFactory.createMutableCompositeNode(rpc.QName, null, null, null, null) + } else { + val value = normalizeNode(payload, rpc.input, null) + val List> input = new ArrayList + input.add(value) + rpcRequest = NodeFactory.createMutableCompositeNode(rpc.QName, null, input, null, null) + } val rpcResult = broker.invokeRpc(rpc.QName, rpcRequest); if (!rpcResult.successful) { throw new ResponseException(INTERNAL_SERVER_ERROR, "Operation failed") @@ -100,6 +91,12 @@ class RestconfImpl implements RestconfService { return new StructuredData(rpcResult.result, rpc.output) } + override readData(String identifier) { + val instanceIdentifierWithSchemaNode = identifier.resolveInstanceIdentifier + val data = broker.readOperationalData(instanceIdentifierWithSchemaNode.getInstanceIdentifier); + return new StructuredData(data, instanceIdentifierWithSchemaNode.schemaNode) + } + override readConfigurationData(String identifier) { val instanceIdentifierWithSchemaNode = identifier.resolveInstanceIdentifier val data = broker.readConfigurationData(instanceIdentifierWithSchemaNode.getInstanceIdentifier); @@ -116,10 +113,61 @@ class RestconfImpl implements RestconfService { updateConfigurationData(identifier, payload); } + override updateConfigurationData(String identifier, CompositeNode payload) { + val identifierWithSchemaNode = identifier.resolveInstanceIdentifier + val value = normalizeNode(payload, identifierWithSchemaNode.schemaNode, identifierWithSchemaNode.mountPoint) + val status = broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier, value).get(); + switch status.result { + case TransactionStatus.COMMITED: Response.status(OK).build + default: Response.status(INTERNAL_SERVER_ERROR).build + } + } + override createConfigurationDataLegacy(String identifier, CompositeNode payload) { createConfigurationData(identifier, payload); } + override createConfigurationData(String identifier, CompositeNode payload) { + val uncompleteIdentifierWithSchemaNode = identifier.resolveInstanceIdentifier + var schemaNode = (uncompleteIdentifierWithSchemaNode.schemaNode as DataNodeContainer).getSchemaChildNode(payload) + if (schemaNode === null) { + schemaNode = payload.findModule(uncompleteIdentifierWithSchemaNode.instanceIdentifier)?.getSchemaChildNode(payload) + } + val value = normalizeNode(payload, schemaNode, uncompleteIdentifierWithSchemaNode.instanceIdentifier) + val completeIdentifierWithSchemaNode = uncompleteIdentifierWithSchemaNode.addLastIdentifierFromData(value, schemaNode) + val status = broker.commitConfigurationDataPost(completeIdentifierWithSchemaNode.instanceIdentifier, value)?.get(); + if (status === null) { + return Response.status(ACCEPTED).build + } + switch status.result { + case TransactionStatus.COMMITED: Response.status(NO_CONTENT).build + default: Response.status(INTERNAL_SERVER_ERROR).build + } + } + + override createConfigurationData(CompositeNode payload) { + val schemaNode = payload.findModule(null)?.getSchemaChildNode(payload) + val value = normalizeNode(payload, schemaNode, null) + val identifierWithSchemaNode = addLastIdentifierFromData(null, value, schemaNode) + val status = broker.commitConfigurationDataPost(identifierWithSchemaNode.instanceIdentifier, value)?.get(); + if (status === null) { + return Response.status(ACCEPTED).build + } + switch status.result { + case TransactionStatus.COMMITED: Response.status(NO_CONTENT).build + default: Response.status(INTERNAL_SERVER_ERROR).build + } + } + + override deleteConfigurationData(String identifier) { + val instanceIdentifierWithSchemaNode = identifier.resolveInstanceIdentifier + val status = broker.commitConfigurationDataDelete(instanceIdentifierWithSchemaNode.getInstanceIdentifier).get; + switch status.result { + case TransactionStatus.COMMITED: Response.status(OK).build + default: Response.status(INTERNAL_SERVER_ERROR).build + } + } + private def InstanceIdWithSchemaNode resolveInstanceIdentifier(String identifier) { val identifierWithSchemaNode = identifier.toInstanceIdentifier if (identifierWithSchemaNode === null) { @@ -128,18 +176,89 @@ class RestconfImpl implements RestconfService { return identifierWithSchemaNode } - private def CompositeNode normalizeNode(CompositeNode node, DataSchemaNode schema) { + private def dispatch Module findModule(CompositeNode data, InstanceIdentifier partialPath) { + if (partialPath !== null && !partialPath.path.empty) { + return data.nodeType.namespace.findModuleByNamespace(partialPath) + } else { + return data.nodeType.namespace.findModuleByNamespace + } + } + + private def dispatch Module findModule(CompositeNodeWrapper data, InstanceIdentifier partialPath) { + var Module module = null; + if (partialPath !== null && !partialPath.path.empty) { + module = data.namespace.findModuleByNamespace(partialPath) // namespace from XML + if (module === null) { + module = data.namespace.toString.findModuleByName(partialPath) // namespace (module name) from JSON + } + } else { + module = data.namespace.findModuleByNamespace // namespace from XML + if (module === null) { + module = data.namespace.toString.findModuleByName // namespace (module name) from JSON + } + } + return module + } + + private def dispatch DataSchemaNode getSchemaChildNode(DataNodeContainer parentSchemaNode, CompositeNode data) { + return parentSchemaNode?.getDataChildByName(data.nodeType.localName) + } + + private def dispatch DataSchemaNode getSchemaChildNode(DataNodeContainer parentSchemaNode, CompositeNodeWrapper data) { + return parentSchemaNode?.getDataChildByName(data.localName) + } + + private def InstanceIdWithSchemaNode addLastIdentifierFromData(InstanceIdWithSchemaNode identifierWithSchemaNode, CompositeNode data, DataSchemaNode schemaOfData) { + val iiOriginal = identifierWithSchemaNode?.instanceIdentifier + var InstanceIdentifierBuilder iiBuilder = null + if (iiOriginal === null) { + iiBuilder = InstanceIdentifier.builder + } else { + iiBuilder = InstanceIdentifier.builder(iiOriginal) + } + + if (schemaOfData instanceof ListSchemaNode) { + iiBuilder.nodeWithKey(schemaOfData.QName, (schemaOfData as ListSchemaNode).resolveKeysFromData(data)) + } else { + iiBuilder.node(schemaOfData.QName) + } + return new InstanceIdWithSchemaNode(iiBuilder.toInstance, schemaOfData, identifierWithSchemaNode?.mountPoint) + } + + private def resolveKeysFromData(ListSchemaNode listNode, CompositeNode dataNode) { + val keyValues = new HashMap(); + for (key : listNode.keyDefinition) { + val dataNodeKeyValueObject = dataNode.getSimpleNodesByName(key.localName)?.head?.value + if (dataNodeKeyValueObject === null) { + throw new ResponseException(BAD_REQUEST, "Data contains list \"" + dataNode.nodeType.localName + "\" which does not contain key: \"" + key.localName + "\"") + } + keyValues.put(key, dataNodeKeyValueObject); + } + return keyValues + } + + private def CompositeNode normalizeNode(CompositeNode node, DataSchemaNode schema, InstanceIdentifier mountPoint) { + if (schema !== null && !schema.containerOrList) { + throw new ResponseException(BAD_REQUEST, "Root element has to be container or list yang datatype."); + } if (node instanceof CompositeNodeWrapper) { - normalizeNode(node as CompositeNodeWrapper, schema, null) + if ((node as CompositeNodeWrapper).changeAllowed) { + normalizeNode(node as CompositeNodeWrapper, schema, null, mountPoint) + } return (node as CompositeNodeWrapper).unwrap() } return node } - private def void normalizeNode(NodeWrapper nodeBuilder, DataSchemaNode schema, QName previousAugment) { + private def isContainerOrList(DataSchemaNode schemaNode) { + return (schemaNode instanceof ContainerSchemaNode) || (schemaNode instanceof ListSchemaNode) + } + + private def void normalizeNode(NodeWrapper nodeBuilder, DataSchemaNode schema, QName previousAugment, + InstanceIdentifier mountPoint) { if (schema === null) { throw new ResponseException(BAD_REQUEST, - "Data has bad format\n" + nodeBuilder.localName + " does not exist in yang schema."); + "Data has bad format.\n\"" + nodeBuilder.localName + "\" does not exist in yang schema."); } var validQName = schema.QName var currentAugment = previousAugment; @@ -148,15 +267,18 @@ class RestconfImpl implements RestconfService { } else if (previousAugment !== null && schema.QName.namespace !== previousAugment.namespace) { validQName = QName.create(currentAugment, schema.QName.localName); } - val moduleName = controllerContext.findModuleByNamespace(validQName.namespace); + var moduleName = controllerContext.findModuleNameByNamespace(validQName.namespace); + if (moduleName === null && mountPoint !== null && !mountPoint.path.empty) { + moduleName = controllerContext.findModuleByNamespace(validQName.namespace, mountPoint)?.name + } if (nodeBuilder.namespace === null || nodeBuilder.namespace == validQName.namespace || nodeBuilder.namespace.toString == moduleName) { nodeBuilder.qname = validQName } else { throw new ResponseException(BAD_REQUEST, - "Data has bad format\nIf data is in XML format then namespace for " + nodeBuilder.localName + - " should be " + schema.QName.namespace + ".\n If data is in Json format then module name for " + - nodeBuilder.localName + " should be " + moduleName + "."); + "Data has bad format.\nIf data is in XML format then namespace for \"" + nodeBuilder.localName + + "\" should be \"" + schema.QName.namespace + "\".\nIf data is in Json format then module name for \"" + + nodeBuilder.localName + "\" should be \"" + moduleName + "\"."); } if (nodeBuilder instanceof CompositeNodeWrapper) { @@ -164,7 +286,7 @@ class RestconfImpl implements RestconfService { for (child : children) { normalizeNode(child, findFirstSchemaByLocalName(child.localName, (schema as DataNodeContainer).childNodes), - currentAugment) + currentAugment, mountPoint) } if(schema instanceof ListSchemaNode) { val listKeys = (schema as ListSchemaNode).keyDefinition @@ -177,7 +299,7 @@ class RestconfImpl implements RestconfService { } if (!foundKey) { throw new ResponseException(BAD_REQUEST, - "Missing key \"" + listKey.localName + "\" of list \"" + schema.QName.localName + "\"") + "Missing key in URI \"" + listKey.localName + "\" of list \"" + schema.QName.localName + "\"") } } } diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/SimpleNodeWrapper.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/SimpleNodeWrapper.java index 97f8102127..6aa8ada5ee 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/SimpleNodeWrapper.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/SimpleNodeWrapper.java @@ -58,6 +58,11 @@ public final class SimpleNodeWrapper implements NodeWrapper>, Simp this.namespace = namespace; } + @Override + public boolean isChangeAllowed() { + return simpleNode == null ? true : false; + } + @Override public SimpleNode unwrap() { if (simpleNode == null) { diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/cnsn/test/JsonToCnSnTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/cnsn/test/JsonToCnSnTest.java index f2c0c29bc4..afe458d6e0 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/cnsn/test/JsonToCnSnTest.java +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/cnsn/test/JsonToCnSnTest.java @@ -13,7 +13,6 @@ import javax.ws.rs.WebApplicationException; import org.junit.Test; import org.opendaylight.controller.sal.rest.impl.JsonToCompositeNodeProvider; import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper; -import org.opendaylight.controller.sal.restconf.impl.ResponseException; import org.opendaylight.controller.sal.restconf.impl.test.TestUtils; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.CompositeNode; @@ -207,15 +206,8 @@ public class JsonToCnSnTest { assertEquals("lst", compNode.getNodeType().getLocalName()); verifyCompositeNode(compNode, "simple:list:yang1"); - String exceptionMessage = ""; - try { - TestUtils.normalizeCompositeNode(compositeNode, modules2, "simple-list-yang2:lst"); - } catch (ResponseException e) { - exceptionMessage = String.valueOf(e.getResponse().getEntity()); - } - assertTrue(exceptionMessage - .contains("Data has bad format\nIf data is in XML format then namespace for lst should be simple:list:yang2.\n If data is in Json format then module name for lst should be simple-list-yang2.")); - + TestUtils.normalizeCompositeNode(compositeNode, modules2, "simple-list-yang2:lst"); + verifyCompositeNode(compNode, "simple:list:yang1"); } @Test diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/DeleteRestCallTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/DeleteRestCallTest.java new file mode 100644 index 0000000000..7b164d4615 --- /dev/null +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/DeleteRestCallTest.java @@ -0,0 +1,101 @@ +package org.opendaylight.controller.sal.restconf.impl.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URLEncoder; +import java.util.Set; +import java.util.concurrent.Future; +import java.util.logging.Level; + +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.Application; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.test.JerseyTest; +import org.glassfish.jersey.test.TestProperties; +import org.junit.BeforeClass; +import org.junit.Test; +import org.opendaylight.controller.md.sal.common.api.TransactionStatus; +import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider; +import org.opendaylight.controller.sal.rest.impl.XmlMapper; +import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider; +import org.opendaylight.controller.sal.restconf.impl.BrokerFacade; +import org.opendaylight.controller.sal.restconf.impl.ControllerContext; +import org.opendaylight.controller.sal.restconf.impl.RestconfImpl; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; +import org.opendaylight.yangtools.yang.model.api.Module; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; + +import com.google.common.base.Charsets; + +public class DeleteRestCallTest extends JerseyTest { + + private static ControllerContext controllerContext; + private static BrokerFacade brokerFacade; + private static RestconfImpl restconfImpl; + private static final MediaType MEDIA_TYPE_DRAFT02 = new MediaType("application", "yang.data+xml"); + + @BeforeClass + public static void init() throws FileNotFoundException { + Set allModules = TestUtils.loadModulesFrom("/test-config-data/yang1"); + assertNotNull(allModules); + SchemaContext schemaContext = TestUtils.loadSchemaContext(allModules); + controllerContext = ControllerContext.getInstance(); + controllerContext.setSchemas(schemaContext); + brokerFacade = mock(BrokerFacade.class); + restconfImpl = RestconfImpl.getInstance(); + restconfImpl.setBroker(brokerFacade); + restconfImpl.setControllerContext(controllerContext); + } + + @Test + public void testDeleteConfigurationData() throws UnsupportedEncodingException, FileNotFoundException { + String uri2 = createUri("/config/", "test-interface:interfaces"); + + RpcResult rpcResult = new DummyRpcResult.Builder().result( + TransactionStatus.COMMITED).build(); + Future> dummyFuture = DummyFuture.builder().rpcResult(rpcResult).build(); + when(brokerFacade.commitConfigurationDataDelete(any(InstanceIdentifier.class))).thenReturn(dummyFuture); + + Response response = target(uri2).request(MEDIA_TYPE_DRAFT02).delete(); + assertEquals(200, response.getStatus()); + + rpcResult = new DummyRpcResult.Builder().result(TransactionStatus.FAILED).build(); + dummyFuture = DummyFuture.builder().rpcResult(rpcResult).build(); + + when(brokerFacade.commitConfigurationDataDelete(any(InstanceIdentifier.class))).thenReturn(dummyFuture); + + response = target(uri2).request(MEDIA_TYPE_DRAFT02).delete(); + assertEquals(500, response.getStatus()); + } + + private String createUri(String prefix, String encodedPart) throws UnsupportedEncodingException { + return URI.create(prefix + URLEncoder.encode(encodedPart, Charsets.US_ASCII.name()).toString()).toASCIIString(); + } + + @Override + protected Application configure() { + enable(TestProperties.LOG_TRAFFIC); + enable(TestProperties.DUMP_ENTITY); + enable(TestProperties.RECORD_LOG_LEVEL); + set(TestProperties.RECORD_LOG_LEVEL, Level.ALL.intValue()); + + ResourceConfig resourceConfig = new ResourceConfig(); + resourceConfig = resourceConfig.registerInstances(restconfImpl, StructuredDataToXmlProvider.INSTANCE, + XmlToCompositeNodeProvider.INSTANCE); + return resourceConfig; + } +} diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/InvokeRpcMethodTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/InvokeRpcMethodTest.java index 2370035861..c5f5a1eddc 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/InvokeRpcMethodTest.java +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/InvokeRpcMethodTest.java @@ -60,7 +60,7 @@ public class InvokeRpcMethodTest { ControllerContext contContext = ControllerContext.getInstance(); contContext.onGlobalContextUpdated(TestUtils.loadSchemaContext(modules)); try { - contContext.findModuleByNamespace(new URI("invoke:rpc:module")); + contContext.findModuleNameByNamespace(new URI("invoke:rpc:module")); } catch (URISyntaxException e) { assertTrue("Uri wasn't created sucessfuly", false); } diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/NormalizeNodeTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/NormalizeNodeTest.java new file mode 100644 index 0000000000..83e6ae51d0 --- /dev/null +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/NormalizeNodeTest.java @@ -0,0 +1,83 @@ +package org.opendaylight.controller.sal.restconf.impl.test; + +import static org.junit.Assert.*; + +import java.net.URI; +import java.net.URISyntaxException; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper; +import org.opendaylight.controller.sal.restconf.impl.ResponseException; +import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; + +public class NormalizeNodeTest extends YangAndXmlAndDataSchemaLoader { + + @BeforeClass + public static void initialization() { + dataLoad("/normalize-node/yang/"); + } + + @Test + public void namespaceNotNullAndInvalidNamespaceAndNoModuleNameTest() { + boolean exceptionReised = false; + try { + TestUtils.normalizeCompositeNode(prepareCnSn("wrongnamespace"), modules, schemaNodePath); + } catch (ResponseException e) { + exceptionReised = true; + } + assertTrue(exceptionReised); + } + + @Test + public void namespaceNullTest() { + String exceptionMessage = null; + try { + TestUtils.normalizeCompositeNode(prepareCnSn(null), modules, schemaNodePath); + } catch (ResponseException e) { + exceptionMessage = String.valueOf(e.getResponse().getEntity()); + } + assertNull(exceptionMessage); + } + + @Test + public void namespaceValidNamespaceTest() { + String exceptionMessage = null; + try { + TestUtils.normalizeCompositeNode(prepareCnSn("normalize:node:module"), modules, schemaNodePath); + } catch (ResponseException e) { + exceptionMessage = String.valueOf(e.getResponse().getEntity()); + } + assertNull(exceptionMessage); + } + + @Test + public void namespaceValidModuleNameTest() { + String exceptionMessage = null; + try { + TestUtils.normalizeCompositeNode(prepareCnSn("normalize-node-module"), modules, schemaNodePath); + } catch (ResponseException e) { + exceptionMessage = String.valueOf(e.getResponse().getEntity()); + } + assertNull(exceptionMessage); + } + + private CompositeNode prepareCnSn(String namespace) { + URI uri = null; + if (namespace != null) { + try { + uri = new URI(namespace); + } catch (URISyntaxException e) { + } + assertNotNull(uri); + } + + SimpleNodeWrapper lf1 = new SimpleNodeWrapper(uri, "lf1", 43); + CompositeNodeWrapper cont = new CompositeNodeWrapper(uri, "cont"); + cont.addValue(lf1); + + return cont; + } + +} diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestConfigDataTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestConfigDataTest.java new file mode 100644 index 0000000000..dccf0d3bae --- /dev/null +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestConfigDataTest.java @@ -0,0 +1,210 @@ +package org.opendaylight.controller.sal.restconf.impl.test; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.times; +import static org.junit.Assert.assertEquals; + +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URLEncoder; +import java.text.ParseException; +import java.util.Set; +import java.util.concurrent.Future; +import java.util.logging.Level; + +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.Application; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.test.JerseyTest; +import org.glassfish.jersey.test.TestProperties; +import org.junit.BeforeClass; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.opendaylight.controller.md.sal.common.api.TransactionStatus; +import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider; +import org.opendaylight.controller.sal.rest.impl.XmlMapper; +import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider; +import org.opendaylight.controller.sal.restconf.impl.BrokerFacade; +import org.opendaylight.controller.sal.restconf.impl.ControllerContext; +import org.opendaylight.controller.sal.restconf.impl.RestconfImpl; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; +import org.opendaylight.yangtools.yang.model.api.Module; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.controller.sal.core.api.mount.MountInstance; +import org.opendaylight.controller.sal.core.api.mount.MountService; + +import com.google.common.base.Charsets; + +public class RestConfigDataTest extends JerseyTest { + + private static ControllerContext controllerContext; + private static BrokerFacade brokerFacade; + private static RestconfImpl restconfImpl; + private static MountService mountService; + private static SchemaContext schemaContext; + + private static final MediaType MEDIA_TYPE_XML_DRAFT02 = new MediaType("application", "yang.data+xml"); + + @BeforeClass + public static void init() throws FileNotFoundException { + Set modules = TestUtils.loadModulesFrom("/test-config-data/yang1"); + schemaContext = TestUtils.loadSchemaContext(modules); + initMocking(); + } + + private static void initMocking() { + controllerContext = ControllerContext.getInstance(); + controllerContext.setSchemas(schemaContext); + mountService = mock(MountService.class); + controllerContext.setMountService(mountService); + brokerFacade = mock(BrokerFacade.class); + restconfImpl = RestconfImpl.getInstance(); + restconfImpl.setBroker(brokerFacade); + restconfImpl.setControllerContext(controllerContext); + } + + @Test + public void createConfigurationDataTest() throws UnsupportedEncodingException, ParseException { + initMocking(); + String URI_1 = createUri("/config", ""); + String URI_2 = createUri("/config/", ""); + String URI_3 = createUri("/config/", "test-interface:interfaces/"); + String URI_4 = createUri("/config/", "test-interface:interfaces/"); + String URI_5 = createUri("/config/", "test-interface:interfaces/test-interface2:class"); + + RpcResult rpcResult = new DummyRpcResult.Builder().result( + TransactionStatus.COMMITED).build(); + Future> dummyFuture = DummyFuture.builder().rpcResult(rpcResult).build(); + + when(brokerFacade.commitConfigurationDataPost(any(InstanceIdentifier.class), any(CompositeNode.class))) + .thenReturn(dummyFuture); + + ArgumentCaptor instanceIdCaptor = ArgumentCaptor.forClass(InstanceIdentifier.class); + ArgumentCaptor compNodeCaptor = ArgumentCaptor.forClass(CompositeNode.class); + + // Test URI_1 + Entity entity = createEntity("/test-config-data/xml/test-interface.xml"); + Response response = target(URI_1).request(MEDIA_TYPE_XML_DRAFT02).post(entity); + assertEquals(204, response.getStatus()); + verify(brokerFacade).commitConfigurationDataPost(instanceIdCaptor.capture(), compNodeCaptor.capture()); + String identifier = "[(urn:ietf:params:xml:ns:yang:test-interface?revision=2014-07-01)interfaces]"; + assertEquals("Bad format URI", identifier, instanceIdCaptor.getValue().getPath().toString()); + + // Test URI_2 + response = target(URI_2).request(MEDIA_TYPE_XML_DRAFT02).post(entity); + assertEquals(204, response.getStatus()); + verify(brokerFacade, times(2)) + .commitConfigurationDataPost(instanceIdCaptor.capture(), compNodeCaptor.capture()); + assertEquals("Bad format URI", identifier, instanceIdCaptor.getValue().getPath().toString()); + + // Test URI_3 + entity = createEntity("/test-config-data/xml/test-interface2.xml"); + response = target(URI_3).request(MEDIA_TYPE_XML_DRAFT02).post(entity); + assertEquals(204, response.getStatus()); + verify(brokerFacade, times(3)) + .commitConfigurationDataPost(instanceIdCaptor.capture(), compNodeCaptor.capture()); + + identifier = "[(urn:ietf:params:xml:ns:yang:test-interface?revision=2014-07-01)interfaces, (urn:ietf:params:xml:ns:yang:test-interface?revision=2014-07-01)interface[{(urn:ietf:params:xml:ns:yang:test-interface?revision=2014-07-01)name=eth0}]]"; + assertEquals("Bad format URI", identifier, instanceIdCaptor.getValue().getPath().toString()); + + // Test URI_4 + Set modules2 = TestUtils.loadModulesFrom("/test-config-data/yang2"); + SchemaContext schemaContext2 = TestUtils.loadSchemaContext(modules2); + MountInstance mountInstance = mock(MountInstance.class); + when(mountInstance.getSchemaContext()).thenReturn(schemaContext2); + when(mountService.getMountPoint(any(InstanceIdentifier.class))).thenReturn(mountInstance); + + entity = createEntity("/test-config-data/xml/test-interface3.xml"); + response = target(URI_4).request(MEDIA_TYPE_XML_DRAFT02).post(entity); + assertEquals(204, response.getStatus()); + verify(brokerFacade, times(4)) + .commitConfigurationDataPost(instanceIdCaptor.capture(), compNodeCaptor.capture()); + identifier = "[(urn:ietf:params:xml:ns:yang:test-interface?revision=2014-07-01)interfaces, (urn:ietf:params:xml:ns:yang:test-interface2?revision=2014-08-01)class]"; + assertEquals("Bad format URI", identifier, instanceIdCaptor.getValue().getPath().toString()); + + // Test URI_5 + response = target(URI_5).request(MEDIA_TYPE_XML_DRAFT02).post(entity); + assertEquals(204, response.getStatus()); + verify(brokerFacade, times(5)) + .commitConfigurationDataPost(instanceIdCaptor.capture(), compNodeCaptor.capture()); + identifier = "[(urn:ietf:params:xml:ns:yang:test-interface?revision=2014-07-01)interfaces, (urn:ietf:params:xml:ns:yang:test-interface2?revision=2014-08-01)class, (urn:ietf:params:xml:ns:yang:test-interface2?revision=2014-08-01)class]"; + assertEquals("Bad format URI", identifier, instanceIdCaptor.getValue().getPath().toString()); + } + + @Test + public void testExistingData() throws UnsupportedEncodingException { + initMocking(); + String URI_1 = createUri("/config", ""); + String URI_2 = createUri("/config/", ""); + String URI_3 = createUri("/config/", "test-interface:interfaces/"); + String URI_4 = createUri("/config/", "test-interface:interfaces/"); + String URI_5 = createUri("/config/", "test-interface:interfaces/test-interface2:class"); + + when(brokerFacade.commitConfigurationDataPost(any(InstanceIdentifier.class), any(CompositeNode.class))) + .thenReturn(null); + + // Test URI_1 + Entity entity = createEntity("/test-config-data/xml/test-interface.xml"); + Response response = target(URI_1).request(MEDIA_TYPE_XML_DRAFT02).post(entity); + assertEquals(202, response.getStatus()); + + // Test URI_2 + response = target(URI_2).request(MEDIA_TYPE_XML_DRAFT02).post(entity); + assertEquals(202, response.getStatus()); + + // Test URI_3 + entity = createEntity("/test-config-data/xml/test-interface2.xml"); + response = target(URI_3).request(MEDIA_TYPE_XML_DRAFT02).post(entity); + assertEquals(202, response.getStatus()); + + // Test URI_4 + Set modules2 = TestUtils.loadModulesFrom("/test-config-data/yang2"); + SchemaContext schemaContext2 = TestUtils.loadSchemaContext(modules2); + MountInstance mountInstance = mock(MountInstance.class); + when(mountInstance.getSchemaContext()).thenReturn(schemaContext2); + when(mountService.getMountPoint(any(InstanceIdentifier.class))).thenReturn(mountInstance); + + entity = createEntity("/test-config-data/xml/test-interface3.xml"); + response = target(URI_4).request(MEDIA_TYPE_XML_DRAFT02).post(entity); + assertEquals(202, response.getStatus()); + + // Test URI_5 + response = target(URI_5).request(MEDIA_TYPE_XML_DRAFT02).post(entity); + assertEquals(202, response.getStatus()); + } + + private String createUri(String prefix, String encodedPart) throws UnsupportedEncodingException { + return URI.create(prefix + URLEncoder.encode(encodedPart, Charsets.US_ASCII.name()).toString()).toASCIIString(); + } + + private Entity createEntity(final String relativePathToXml) { + InputStream inputStream = XmlMapper.class.getResourceAsStream(relativePathToXml); + String xml = TestUtils.getDocumentInPrintableForm(TestUtils.loadDocumentFrom(inputStream)); + Entity entity = Entity.entity(xml, MEDIA_TYPE_XML_DRAFT02); + + return entity; + } + + @Override + protected Application configure() { + enable(TestProperties.LOG_TRAFFIC); + enable(TestProperties.DUMP_ENTITY); + enable(TestProperties.RECORD_LOG_LEVEL); + set(TestProperties.RECORD_LOG_LEVEL, Level.ALL.intValue()); + + ResourceConfig resourceConfig = new ResourceConfig(); + resourceConfig = resourceConfig.registerInstances(restconfImpl, StructuredDataToXmlProvider.INSTANCE, + XmlToCompositeNodeProvider.INSTANCE); + return resourceConfig; + } +} diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/TestUtils.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/TestUtils.java index 4295c29a22..3427fbde38 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/TestUtils.java +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/TestUtils.java @@ -149,7 +149,7 @@ public final class TestUtils { ControllerContext.getInstance().setSchemas(TestUtils.loadSchemaContext(modules)); prepareMocksForRestconf(modules, restconf); - restconf.createConfigurationData(schemaNodePath, compositeNode); + restconf.updateConfigurationData(schemaNodePath, compositeNode); } /** diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/XmlProvidersTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/XmlProvidersTest.java index b18f526a23..7cce34ffb6 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/XmlProvidersTest.java +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/XmlProvidersTest.java @@ -12,7 +12,9 @@ import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URISyntaxException; import java.net.URLEncoder; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; import java.util.concurrent.Future; import java.util.logging.Level; import java.util.logging.LogRecord; @@ -33,9 +35,15 @@ import org.opendaylight.controller.sal.rest.api.Draft01; import org.opendaylight.controller.sal.rest.api.RestconfService; import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider; import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider; -import org.opendaylight.controller.sal.restconf.impl.*; +import org.opendaylight.controller.sal.restconf.impl.BrokerFacade; +import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper; +import org.opendaylight.controller.sal.restconf.impl.ControllerContext; +import org.opendaylight.controller.sal.restconf.impl.RestconfImpl; +import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper; import org.opendaylight.yangtools.yang.common.RpcResult; -import org.opendaylight.yangtools.yang.data.api.*; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.Node; import org.opendaylight.yangtools.yang.model.api.Module; import org.opendaylight.yangtools.yang.model.api.SchemaContext; @@ -140,26 +148,34 @@ public class XmlProvidersTest extends JerseyTest { RpcResult rpcResult = new DummyRpcResult.Builder().result( TransactionStatus.COMMITED).build(); Future> dummyFuture = DummyFuture.builder().rpcResult(rpcResult).build(); - when(brokerFacade.commitOperationalDataPut(any(InstanceIdentifier.class), any(CompositeNode.class))) - .thenReturn(dummyFuture); when(brokerFacade.commitConfigurationDataPut(any(InstanceIdentifier.class), any(CompositeNode.class))) .thenReturn(dummyFuture); + when(brokerFacade.commitConfigurationDataPost(any(InstanceIdentifier.class), any(CompositeNode.class))) + .thenReturn(dummyFuture); String uri = createUri("/config/", "ietf-interfaces:interfaces/interface/eth0"); Response response = target(uri).request(MEDIA_TYPE_DRAFT02).put(entity); assertEquals(200, response.getStatus()); + + uri = createUri("/config/", "ietf-interfaces:interfaces"); response = target(uri).request(MEDIA_TYPE_DRAFT02).post(entity); assertEquals(204, response.getStatus()); uri = createUri("/config/", "ietf-interfaces:interfaces/interface/eth0"); response = target(uri).request(MEDIA_TYPE_DRAFT02).put(entity); assertEquals(200, response.getStatus()); + + uri = createUri("/config/", "ietf-interfaces:interfaces"); response = target(uri).request(MEDIA_TYPE_DRAFT02).post(entity); assertEquals(204, response.getStatus()); uri = createUri("/datastore/", "ietf-interfaces:interfaces/interface/eth0"); + entity = Entity.entity(xml, MEDIA_TYPE); response = target(uri).request(MEDIA_TYPE).put(entity); assertEquals(200, response.getStatus()); + + uri = createUri("/datastore/", "ietf-interfaces:interfaces"); + entity = Entity.entity(xml, MEDIA_TYPE); response = target(uri).request(MEDIA_TYPE).post(entity); assertEquals(204, response.getStatus()); } @@ -172,8 +188,6 @@ public class XmlProvidersTest extends JerseyTest { RpcResult rpcResult = new DummyRpcResult.Builder().result( TransactionStatus.FAILED).build(); Future> dummyFuture = DummyFuture.builder().rpcResult(rpcResult).build(); - when(brokerFacade.commitOperationalDataPut(any(InstanceIdentifier.class), any(CompositeNode.class))) - .thenReturn(dummyFuture); when(brokerFacade.commitConfigurationDataPut(any(InstanceIdentifier.class), any(CompositeNode.class))) .thenReturn(dummyFuture); @@ -190,9 +204,10 @@ public class XmlProvidersTest extends JerseyTest { assertEquals(500, response.getStatus()); uri = createUri("/datastore/", "ietf-interfaces:interfaces/interface/eth0"); - response = target(uri).request(MEDIA_TYPE).put(entity); + entity = Entity.entity(xml, MEDIA_TYPE); + response = target(uri).request().put(entity); assertEquals(500, response.getStatus()); - response = target(uri).request(MEDIA_TYPE).post(entity); + response = target(uri).request().accept(MEDIA_TYPE).post(entity); assertEquals(500, response.getStatus()); } diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/normalize-node/yang/normalize-node-module b/opendaylight/md-sal/sal-rest-connector/src/test/resources/normalize-node/yang/normalize-node-module new file mode 100644 index 0000000000..15e68ef225 --- /dev/null +++ b/opendaylight/md-sal/sal-rest-connector/src/test/resources/normalize-node/yang/normalize-node-module @@ -0,0 +1,14 @@ +module normalize-node-module { + namespace "normalize:node:module"; + + prefix "nonomo"; + revision 2014-01-09 { + } + + container cont { + leaf lf1 { + type int32; + } + } + +} \ No newline at end of file diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/test-config-data/xml/test-interface.xml b/opendaylight/md-sal/sal-rest-connector/src/test/resources/test-config-data/xml/test-interface.xml new file mode 100644 index 0000000000..755c8a9b0f --- /dev/null +++ b/opendaylight/md-sal/sal-rest-connector/src/test/resources/test-config-data/xml/test-interface.xml @@ -0,0 +1,8 @@ + + + eth0 + ethernetCsmacd + false + + + diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/test-config-data/xml/test-interface2.xml b/opendaylight/md-sal/sal-rest-connector/src/test/resources/test-config-data/xml/test-interface2.xml new file mode 100644 index 0000000000..05db4a5ccc --- /dev/null +++ b/opendaylight/md-sal/sal-rest-connector/src/test/resources/test-config-data/xml/test-interface2.xml @@ -0,0 +1,5 @@ + + eth0 + ethernetCsmacd + false + diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/test-config-data/xml/test-interface3.xml b/opendaylight/md-sal/sal-rest-connector/src/test/resources/test-config-data/xml/test-interface3.xml new file mode 100644 index 0000000000..e59ba178b7 --- /dev/null +++ b/opendaylight/md-sal/sal-rest-connector/src/test/resources/test-config-data/xml/test-interface3.xml @@ -0,0 +1,6 @@ + + + Thomas + 23 + + diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/test-config-data/yang1/test-interface.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/test-config-data/yang1/test-interface.yang new file mode 100644 index 0000000000..f683a69444 --- /dev/null +++ b/opendaylight/md-sal/sal-rest-connector/src/test/resources/test-config-data/yang1/test-interface.yang @@ -0,0 +1,30 @@ +module test-interface { + yang-version 1; + namespace "urn:ietf:params:xml:ns:yang:test-interface"; + prefix "sn"; + + description + "test file"; + + revision "2014-07-01" { + description + "Initial revision"; + reference "will be defined"; + } + + container interfaces { + list interface { + key "name"; + + leaf name { + type string; + } + leaf type { + type string; + } + leaf enabled { + type string; + } + } + } +} diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/test-config-data/yang2/test-interface2.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/test-config-data/yang2/test-interface2.yang new file mode 100644 index 0000000000..13bc0ebf9d --- /dev/null +++ b/opendaylight/md-sal/sal-rest-connector/src/test/resources/test-config-data/yang2/test-interface2.yang @@ -0,0 +1,27 @@ +module test-interface2 { + yang-version 1; + namespace "urn:ietf:params:xml:ns:yang:test-interface2"; + prefix "snn"; + + description + "test file"; + + revision "2014-08-01" { + description + "Initial revision"; + reference "will be defined"; + } + + container class { + list student { + key "name"; + + leaf name { + type string; + } + leaf age { + type string; + } + } + } +} diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsUpdateCommiter.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsUpdateCommiter.java index e7f6129aa5..62ba04687e 100644 --- a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsUpdateCommiter.java +++ b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsUpdateCommiter.java @@ -7,10 +7,6 @@ */ package org.opendaylight.controller.md.statistics.manager; -import java.util.HashMap; -import java.util.List; -import java.util.concurrent.ConcurrentMap; - import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector; @@ -111,6 +107,10 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdenti import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.HashMap; +import java.util.List; +import java.util.concurrent.ConcurrentMap; + /** * Class implement statistics manager related listener interface and augment all the * received statistics data to data stores. @@ -500,7 +500,7 @@ public class StatisticsUpdateCommiter implements OpendaylightGroupStatisticsList sucLogger.debug("Associated original flow is not found in data store. Augmenting flow in operational data store"); //TODO: Temporary fix: format [ 1+tableid+1+unaccounted flow counter] long flowKey = Long.parseLong(new String("1"+Short.toString(tableId)+"1"+Integer.toString(this.unaccountedFlowsCounter))); - FlowKey newFlowKey = new FlowKey(new FlowId(flowKey)); + FlowKey newFlowKey = new FlowKey(new FlowId(Long.toString(flowKey))); InstanceIdentifier flowRef = InstanceIdentifier.builder(Nodes.class).child(Node.class, key) .augmentation(FlowCapableNode.class) .child(Table.class, new TableKey(tableId)) diff --git a/opendaylight/netconf/netconf-ssh/pom.xml b/opendaylight/netconf/netconf-ssh/pom.xml index 5dde0448bd..34f131c678 100644 --- a/opendaylight/netconf/netconf-ssh/pom.xml +++ b/opendaylight/netconf/netconf-ssh/pom.xml @@ -61,22 +61,12 @@ org.opendaylight.controller.netconf.osgi.NetconfSSHActivator - - org.opendaylight.controller.netconf.ssh, - - com.google.common.base, ch.ethz.ssh2, ch.ethz.ssh2.signature, - java.net, - javax.annotation, - org.apache.commons.io, - org.opendaylight.controller.netconf.util, org.opendaylight.controller.netconf.util.osgi, org.opendaylight.controller.usermanager, org.opendaylight.controller.sal.authorization, - org.opendaylight.controller.sal.utils, - org.opendaylight.protocol.framework, org.osgi.framework, org.osgi.util.tracker, org.slf4j, diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/flowprogrammer/Flow.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/flowprogrammer/Flow.java index 0df6d4cec4..a823864a67 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/flowprogrammer/Flow.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/flowprogrammer/Flow.java @@ -8,17 +8,6 @@ package org.opendaylight.controller.sal.flowprogrammer; -import java.io.Serializable; -import java.net.Inet6Address; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; - import org.opendaylight.controller.sal.action.Action; import org.opendaylight.controller.sal.action.ActionType; import org.opendaylight.controller.sal.action.SetDlType; @@ -29,6 +18,16 @@ import org.opendaylight.controller.sal.utils.EtherTypes; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; +import java.net.Inet6Address; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + /** * Represent a flow: match + actions + flow specific properties */ @@ -305,4 +304,5 @@ public class Flow implements Cloneable, Serializable { } return true; } + }