.idea
xtend-gen
classes
+out/
<osgi.core.version>5.0.0</osgi.core.version>
<ietf-inet-types.version>2010.09.24.2-SNAPSHOT</ietf-inet-types.version>
<ietf-yang-types.version>2010.09.24.2-SNAPSHOT</ietf-yang-types.version>
+ <ietf-topology.version>2013.10.21.0-SNAPSHOT</ietf-topology.version>
<opendaylight-l2-types.version>2013.08.27.1</opendaylight-l2-types.version>
<yang-ext.version>2013.09.07.1</yang-ext.version>
<javassist.version>3.17.1-GA</javassist.version>
<artifactId>ietf-yang-types</artifactId>
<version>${ietf-yang-types.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools.model</groupId>
+ <artifactId>ietf-topology</artifactId>
+ <version>${ietf-topology.version}</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.yangtools.model</groupId>
<artifactId>opendaylight-l2-types</artifactId>
<build>
<plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ </plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
--- /dev/null
+/*
+ * 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<String,String> 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;
+ }
+}
<artifactId>mockito-configuration</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>config-persister-api</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
</dependencies>
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.<ConfigSnapshotHolder>emptyList(), tested.loadLastConfigs());
try {
@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<ConfigSnapshotHolder> results = tested.loadLastConfigs();
assertEquals(1, results.size());
ConfigSnapshotHolder result = results.get(0);
@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<ConfigSnapshotHolder> results = tested.loadLastConfigs();
assertEquals(2, results.size());
assertSnapshot(results.get(0), "twoFilesExpected1");
<artifactId>mockito-configuration</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>config-persister-api</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
</dependencies>
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 {
@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<ConfigSnapshotHolder> results = tested.loadLastConfigs();
assertEquals(1, results.size());
ConfigSnapshotHolder result = results.get(0);
@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<ConfigSnapshotHolder> results = tested.loadLastConfigs();
assertEquals(2, results.size());
<artifactId>mockito-configuration</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>config-persister-api</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
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;
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);
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;
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<String> getCapabilities() {
+ return createCaps();
+ }
+ };
+ configPersister.persistConfig(holder);
+
+ configPersister.persistConfig(holder);
+
+ Collection<String> readLines = Collections2.filter(com.google.common.io.Files.readLines(file, Charsets.UTF_8),
+ new Predicate<String>() {
+
+ @Override
+ public boolean apply(String input) {
+ if (input.equals(""))
+ return false;
+ return true;
+ }
+ });
+ assertEquals(14, readLines.size());
+
+ List<ConfigSnapshotHolder> lastConf = storage.loadLastConfigs();
+ assertEquals(1, lastConf.size());
+ ConfigSnapshotHolder configSnapshotHolder = lastConf.get(0);
+ assertEquals("<config>2</config>",
+ configSnapshotHolder.getConfigSnapshot().replaceAll("\\s", ""));
+ assertEquals(createCaps(), configSnapshotHolder.getCapabilities());
+ }
@Test
public void testFileAdapter() throws Exception {
FileStorageAdapter storage = new FileStorageAdapter();
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);
}
}
@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();
<artifactId>config-persister-api</artifactId>
<version>${config.version}</version>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>config-persister-api</artifactId>
+ <version>${config.version}</version>
+ <type>test-jar</type>
+ </dependency>
<dependency>
<groupId>org.opendaylight.bgpcep</groupId>
<artifactId>mockito-configuration</artifactId>
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;
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";
}
@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();
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.<ObjectName>emptyList());
}
private void assertTestingDeps(List<ObjectName> testingDeps, int i) {
<dependency>
<groupId>org.opendaylight.yangtools.model</groupId>
<artifactId>ietf-topology</artifactId>
- <version>2013.07.12.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
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;
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.
}
Flow flow = new Flow(match, getActionList());
+
if (this.cookie != null) {
flow.setId(Long.parseLong(cookie));
}
if (this.priority != null) {
flow.setPriority(Integer.decode(this.priority).shortValue());
}
+
+
return flow;
}
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal</artifactId>
- <version>0.5.1-SNAPSHOT</version>
+ <version>0.7.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller.model</groupId>
<artifactId>sal-binding-util</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>clustering.services</artifactId>
+ <version>0.4.1-SNAPSHOT</version>
+ </dependency>
</dependencies>
<packaging>bundle</packaging>
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
.setService(IPluginOutFlowProgrammerService) //
.setCallbacks("setFlowProgrammerPublisher", "setFlowProgrammerPublisher") //
.setRequired(false))
+
+ add(
+ createServiceDependency() //
+ .setService(IClusterGlobalServices) //
+ .setCallbacks("setClusterGlobalServices", "unsetClusterGlobalServices") //
+ .setRequired(false))
+
}
private def dispatch configure(InventoryAndReadAdapter imp, Component it) {
.setService(IDiscoveryService) //
.setCallbacks("setDiscoveryPublisher", "setDiscoveryPublisher") //
.setRequired(false))
+
}
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
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.*
class FlowProgrammerAdapter implements IPluginInFlowProgrammerService, SalFlowListener {
private static val LOG = LoggerFactory.getLogger(FlowProgrammerAdapter);
+ private static val CACHE_NAME = "flowprogrammeradapter.flowtoid";
@Property
private SalFlowService delegate;
@Property
private IPluginOutFlowProgrammerService flowProgrammerPublisher;
+ @Property
+ private IClusterGlobalServices clusterGlobalServices;
+
+
+ @Property
+ private Map<Flow, UUID> flowToFlowId = new ConcurrentHashMap<Flow, UUID>();
+
+
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);
}
}
}
-
- 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());
}
NodeExperimenterErrorNotification notification) {
// NOOP : Not supported by AD SAL
}
+
+ private def Future<RpcResult<TransactionStatus>> 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<RpcResult<TransactionStatus>> 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<RpcResult<TransactionStatus>> 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<RpcResult<TransactionStatus>> 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<RpcResult<TransactionStatus>> 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<Flow, UUID> getCache(){
+ if(clusterGlobalServices == null){
+ return new ConcurrentHashMap<Flow, UUID>();
+ }
+
+ 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<Flow, UUID>;
+
+ }
+
}
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);
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));
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 ");
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);
}
override onNodeUpdated(NodeUpdated notification) {
- val properties = Collections.<org.opendaylight.controller.sal.core.Property>emptySet();
val InstanceIdentifier<? extends DataObject> identifier = notification.nodeRef.value as InstanceIdentifier<? extends DataObject>;
var updateType = UpdateType.CHANGED;
* 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) {
return it;
}
+
+ override getConfiguredNotConnectedNodes() {
+ return Collections.emptySet();
+ }
}
}
- public static def toMDFlow(Flow sourceFlow) {
+ public static def toMDFlow(Flow sourceFlow, String flowId) {
if (sourceFlow == null)
throw new IllegalArgumentException();
val it = new FlowBuilder();
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<Action>();
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<InstanceIdentifier<? extends DataObject>, DataObject> modification,SalFlowService salFlowService) {
- super(modification)
+ super(modification)
_salFlowService = salFlowService;
}
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());
}
}
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());
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());
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<InstanceIdentifier<? extends DataObject>, DataObject> modification,SalGroupService groupService) {
- super(modification)
+ super(modification)
_groupService = groupService;
}
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());
}
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());
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());
}
}
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<InstanceIdentifier<? extends DataObject>, DataObject> modification,SalMeterService salMeterService) {
- super(modification)
+ super(modification)
_salMeterService = salMeterService;
}
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());
}
}
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());
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());
}
}
}
leaf max-length {
- type uint16 {
- range "0..65294";
- }
+ type uint16;
}
}
}
case controller-action-case {
container controller-action {
leaf max-length {
- type uint16 {
- range "0..65294";
- }
+ type uint16;
}
}
}
}
typedef flow-id {
- type uint32; // Note: This doesn't really belong here, and not sure if unint32 is right
+ type inet:uri;
}
grouping tables {
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 "";
}
}
+ 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;
}
uses raw-packet;
}
}
-}
\ No newline at end of file
+}
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" {
typedef flow-id {
description "flow id";
- type yang:counter32;
+ type inet:uri;
}
grouping flow-and-statistics-map-list {
--- /dev/null
+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
<packaging>bundle</packaging>
<dependencies>
- <dependency>
- <groupId>org.opendaylight.controller.model</groupId>
- <artifactId>model-inventory</artifactId>
- <version>1.0-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools.model</groupId>
- <artifactId>ietf-topology</artifactId>
- <version>2013.07.12.2-SNAPSHOT</version>
- </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.model</groupId>
+ <artifactId>model-inventory</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools.model</groupId>
+ <artifactId>ietf-topology</artifactId>
+ <version>2013.10.21.0-SNAPSHOT</version>
+ </dependency>
</dependencies>
</project>
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";
type inv:node-connector-ref;
}
}
-}
\ No newline at end of file
+}
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";
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";
ext:augment-identifier "aggregated-node";
uses aggregate-node;
}
-}
\ No newline at end of file
+}
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;
@Override
public ValueWithQName<A> deserialize(Node<?> input);
+
+ public QName getAugmentationQName();
}
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 {
void bindingClassEncountered(Class<?> cls);
void putPathToClass(List<QName> names, Class<?> cls);
+
+ public abstract QName getQNameForAugmentation(Class<?> cls);
}
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<Class<?>,QName> classToQName = new WeakHashMap;
val Map<Class<?>, Map<List<QName>, Class<?>>> classToPreviousAugment = new WeakHashMap;
public new(CodecRegistry registry) {
previousAugmentation = null;
} else {
- previousQName = resolveQname(baArg.type);
+ previousQName = codecRegistry.getQNameForAugmentation(baArg.type as Class);
previousAugmentation = baArg.type;
}
}
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);
}
val Map<QName,Object> 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) {
}
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
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;
}
return codec;
}
+
+ @Override
+ public QName getQNameForAugmentation(Class<?> cls) {
+ checkArgument(Augmentation.class.isAssignableFrom(cls));
+ return getCodecForAugmentation((Class<? extends Augmentation>)cls).getAugmentationQName();
+ }
private static Class<? extends Augmentable<?>> getAugmentableArgumentFrom(
final Class<? extends Augmentation<?>> augmentation) {
Delegator<BindingCodec> {
private BindingCodec delegate;
+ private QName augmentationQName;
public AugmentationCodecWrapper(BindingCodec<Map<QName, Object>, Object> rawCodec) {
this.delegate = rawCodec;
+ this.augmentationQName = BindingReflections.findQName(rawCodec.getClass());
}
@Override
Object rawCodecValue = getDelegate().deserialize((Map<QName, Object>) input);
return new ValueWithQName<T>(input.getNodeType(), (T) rawCodecValue);
}
+
+ @Override
+ public QName getAugmentationQName() {
+ return augmentationQName;
+ }
}
private class IdentityCompositeCodec implements IdentitityCodec {
import org.opendaylight.yangtools.concepts.ListenerRegistration\r
import org.opendaylight.yangtools.concepts.Registration\r
import org.opendaylight.yangtools.yang.binding.Notification\r
-import org.slf4j.LoggerFactory\rimport org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder
-
+import org.slf4j.LoggerFactory\r
+import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder\r
+\r
class NotificationBrokerImpl implements NotificationProviderService, AutoCloseable {\r
\r
val Multimap<Class<? extends Notification>, NotificationListener<?>> listeners;\r
val Notification notification;\r
\r
override call() {\r
+ //Only logging the complete notification in debug mode\r
try {\r
- log.info("Delivering notification {} to {}",notification,listener);\r
+ if(log.isDebugEnabled){\r
+ log.debug("Delivering notification {} to {}",notification,listener);\r
+ } else {\r
+ log.info("Delivering notification {} to {}",notification.class.name,listener);\r
+ }\r
listener.onNotification(notification);\r
- log.info("Notification delivered {} to {}",notification,listener);\r
+ if(log.isDebugEnabled){\r
+ log.debug("Notification delivered {} to {}",notification,listener);\r
+ } else {\r
+ log.info("Notification delivered {} to {}",notification.class.name,listener);\r
+ }\r
} catch (Exception e) {\r
log.error("Unhandled exception thrown by listener: {}", listener, e);\r
}\r
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;
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;
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";
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;
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;
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;
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 {
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));
<artifactId>sal-common-impl</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-common-impl</artifactId>
- <version>1.0-SNAPSHOT</version>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-core-spi</artifactId>
<scope>test</scope>
<version>${netconf.version}</version>
</dependency>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>yang-test</artifactId>
- <scope>test</scope>
- <version>${netconf.version}</version>
- </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>config-manager</artifactId>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-data-impl</artifactId>
</dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-common</artifactId>
- </dependency>
<!-- Third Party -->
<dependency>
<artifactId>yang-data-impl</artifactId>
<version>${yang.version}</version>
</dependency>
- <dependency>
+ <dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-model-util</artifactId>
<version>${yang.version}</version>
<version>2.4</version>
<scope>test</scope>
</dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-model-util</artifactId>
- <version>0.5.9-SNAPSHOT</version>
- </dependency>
</dependencies>
<build>
*/
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;
@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);
}
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;
@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);
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 {
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);
}
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
+ }
+
}
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() {
public Set<java.util.Map.Entry<QName, List<Node<?>>>> entrySet() {
return unwrap().entrySet();
}
+
}
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
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)
}
public def InstanceIdWithSchemaNode toInstanceIdentifier(String restconfInstance) {
+ checkPreconditions
val ret = InstanceIdentifier.builder();
val pathArgs = restconfInstance.split("/");
if (pathArgs.empty) {
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<Module> modules) {
var latestModule = modules.head
for (module : modules) {
if (module.revision.after(latestModule.revision)) {
}
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
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;
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)
}
private def DataSchemaNode collectPathArguments(InstanceIdentifierBuilder builder, List<String> strings,
- DataNodeContainer parentNode) {
+ DataNodeContainer parentNode, List<InstanceIdentifier> mountPoints) {
checkNotNull(strings)
if (parentNode === null) {
return null;
// 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
}
}
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
}
val allCases = container.childNodes.filter(ChoiceNode).map[cases].flatten
for (caze : allCases) {
potentialNode = caze.findInstanceDataChild(name);
- if(potentialNode != null) {
+ if(potentialNode !== null) {
return potentialNode;
}
}
this.namespace = namespace;
}
+ @Override
+ public boolean isChangeAllowed() {
+ return unwrapped == null ? true : false;
+ }
+
@Override
public Node<?> unwrap() {
if (unwrapped == null) {
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() {
return schemaNode;
}
+ public InstanceIdentifier getMountPoint() {
+ return mountPoint;
+ }
+
}
T unwrap();
+ boolean isChangeAllowed();
+
URI getNamespace();
void setNamespace(URI namespace);
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);
}
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
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
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 {
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<Node<?>> 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<Node<?>> 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")
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);
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) {
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<QName, Object>();
+ 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;
} 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) {
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
}
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 + "\"")
}
}
}
this.namespace = namespace;
}
+ @Override
+ public boolean isChangeAllowed() {
+ return simpleNode == null ? true : false;
+ }
+
@Override
public SimpleNode<Object> unwrap() {
if (simpleNode == null) {
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;
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
--- /dev/null
+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<Module> 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<TransactionStatus> rpcResult = new DummyRpcResult.Builder<TransactionStatus>().result(
+ TransactionStatus.COMMITED).build();
+ Future<RpcResult<TransactionStatus>> 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<TransactionStatus>().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;
+ }
+}
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);
}
--- /dev/null
+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;
+ }
+
+}
--- /dev/null
+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<Module> 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<TransactionStatus> rpcResult = new DummyRpcResult.Builder<TransactionStatus>().result(
+ TransactionStatus.COMMITED).build();
+ Future<RpcResult<TransactionStatus>> dummyFuture = DummyFuture.builder().rpcResult(rpcResult).build();
+
+ when(brokerFacade.commitConfigurationDataPost(any(InstanceIdentifier.class), any(CompositeNode.class)))
+ .thenReturn(dummyFuture);
+
+ ArgumentCaptor<InstanceIdentifier> instanceIdCaptor = ArgumentCaptor.forClass(InstanceIdentifier.class);
+ ArgumentCaptor<CompositeNode> compNodeCaptor = ArgumentCaptor.forClass(CompositeNode.class);
+
+ // Test URI_1
+ Entity<String> 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<Module> 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<String> 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<Module> 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<String> createEntity(final String relativePathToXml) {
+ InputStream inputStream = XmlMapper.class.getResourceAsStream(relativePathToXml);
+ String xml = TestUtils.getDocumentInPrintableForm(TestUtils.loadDocumentFrom(inputStream));
+ Entity<String> 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;
+ }
+}
ControllerContext.getInstance().setSchemas(TestUtils.loadSchemaContext(modules));
prepareMocksForRestconf(modules, restconf);
- restconf.createConfigurationData(schemaNodePath, compositeNode);
+ restconf.updateConfigurationData(schemaNodePath, compositeNode);
}
/**
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;
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;
RpcResult<TransactionStatus> rpcResult = new DummyRpcResult.Builder<TransactionStatus>().result(
TransactionStatus.COMMITED).build();
Future<RpcResult<TransactionStatus>> 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());
}
RpcResult<TransactionStatus> rpcResult = new DummyRpcResult.Builder<TransactionStatus>().result(
TransactionStatus.FAILED).build();
Future<RpcResult<TransactionStatus>> 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);
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());
}
--- /dev/null
+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
--- /dev/null
+<interfaces xmlns="urn:ietf:params:xml:ns:yang:test-interface">
+ <interface>
+ <name>eth0</name>
+ <type>ethernetCsmacd</type>
+ <enabled>false</enabled>
+ </interface>
+</interfaces>
+
--- /dev/null
+<interface>
+ <name>eth0</name>
+ <type>ethernetCsmacd</type>
+ <enabled>false</enabled>
+</interface>
--- /dev/null
+<class xmlns="urn:ietf:params:xml:ns:yang:test-interface2">
+ <student>
+ <name>Thomas</name>
+ <age>23</age>
+ </student>
+</class>
--- /dev/null
+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;
+ }
+ }
+ }
+}
--- /dev/null
+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;
+ }
+ }
+ }
+}
*/
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;
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.
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<Flow> flowRef = InstanceIdentifier.builder(Nodes.class).child(Node.class, key)
.augmentation(FlowCapableNode.class)
.child(Table.class, new TableKey(tableId))
<configuration>
<instructions>
<Bundle-Activator>org.opendaylight.controller.netconf.osgi.NetconfSSHActivator</Bundle-Activator>
- <Export-Package>
- org.opendaylight.controller.netconf.ssh,
- </Export-Package>
<Import-Package>
- 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,
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;
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
*/
}
return true;
}
+
}