<artifactId>sal-common-util</artifactId>
<version>${mdsal.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-netconf-connector</artifactId>
+ <version>${mdsal.version}</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-core-api</artifactId>
<artifactId>forwardingrules-manager</artifactId>
<version>${mdsal.version}</version>
</dependency>
-
+ <dependency>
+ <groupId>org.opendaylight.controller.md</groupId>
+ <artifactId>statistics-manager</artifactId>
+ <version>${mdsal.version}</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>concepts</artifactId>
<artifactId>yang-jmx-generator</artifactId>
<version>${config.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>netty-event-executor-config</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>netty-threadgroup-config</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>threadpool-config-api</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>threadpool-config-impl</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-store-api</artifactId>
+ <version>${config.version}</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>yang-store-api</artifactId>
import ietf-inet-types {prefix inet; revision-date "2010-09-24";}
import ietf-yang-types {prefix yang; revision-date "2010-09-24";}
- import opendaylight-match-types {prefix match; revision-date 2013-10-26";}
+ import opendaylight-match-types {prefix match; revision-date "2013-10-26";}
import opendaylight-action-types {prefix action;}
revision "2013-10-26" {
import ietf-inet-types {prefix inet; revision-date "2010-09-24";}
import ietf-yang-types {prefix yang; revision-date "2010-09-24";}
- import opendaylight-flow-types {prefix flow;revision-date 2013-10-26";}
+ import opendaylight-flow-types {prefix flow;revision-date "2013-10-26";}
import opendaylight-action-types {prefix action;}
revision "2013-10-26" {
import yang-ext {prefix ext; revision-date "2013-07-09";}
import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
import opendaylight-port-types {prefix port-type;revision-date "2013-09-25";}
+ import flow-capable-transaction {prefix tr;}
revision "2013-11-07" {
description "Initial revision of port service";
rpc update-port {
input {
uses port-update;
+ uses tr:transaction-aware;
+ }
+ output {
+ uses tr:transaction-aware;
}
}
<!-- Connectors -->
<module>sal-connector-api</module>
<module>sal-rest-connector</module>
-
+ <module>sal-netconf-connector</module>
+
<!-- Clustered Data Store -->
<module>clustered-data-store/implementation</module>
import org.osgi.framework.BundleContext
import java.util.Hashtable
import org.osgi.framework.ServiceRegistration
+import org.opendaylight.controller.sal.binding.impl.connect.dom.DeserializationException
+import java.util.concurrent.Callable
class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingService, SchemaServiceListener, AutoCloseable {
val promisedTypeDefinitions = HashMultimap.<Type, SettableFuture<GeneratedTypeBuilder>>create;
val promisedSchemas = HashMultimap.<Type, SettableFuture<SchemaNode>>create;
-
+
ServiceRegistration<SchemaServiceListener> listenerRegistration
override onGlobalContextUpdated(SchemaContext arg0) {
val context = entry.value;
updateBindingFor(context.childNodes, schemaContext);
updateBindingFor(context.cases, schemaContext);
-
val typedefs = context.typedefs;
for (typedef : typedefs.values) {
for (augmentation : augmentations) {
binding.typeToDefinition.put(augmentation, augmentation);
}
-
+
binding.typeToAugmentation.putAll(context.typeToAugmentation);
}
}
}
override dataObjectFromDataDom(InstanceIdentifier<? extends DataObject> path, CompositeNode node) {
- if (node == null) {
- return null;
- }
- val targetType = path.targetType
- val transformer = registry.getCodecForDataObject(targetType);
- val ret = transformer.deserialize(node)?.value as DataObject;
- return ret;
+ return tryDeserialization[ |
+ if (node == null) {
+ return null;
+ }
+ val targetType = path.targetType
+ val transformer = registry.getCodecForDataObject(targetType);
+ val ret = transformer.deserialize(node)?.value as DataObject;
+ return ret;
+ ]
}
-
+
override fromDataDom(org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry) {
- return registry.instanceIdentifierCodec.deserialize(entry);
+ return tryDeserialization[ |
+ registry.instanceIdentifierCodec.deserialize(entry);
+ ]
+ }
+
+ private static def <T> T tryDeserialization(Callable<T> deserializationBlock) throws DeserializationException {
+ try {
+ deserializationBlock.call()
+ } catch (Exception e) {
+ // FIXME: Make this block providing more information.
+ throw new DeserializationException(e);
+ }
}
private def void updateBindingFor(Map<SchemaPath, GeneratedTypeBuilder> map, SchemaContext module) {
for (entry : map.entrySet) {
val schemaNode = SchemaContextUtil.findDataSchemaNode(module, entry.key);
+
//LOG.info("{} : {}",entry.key,entry.value.fullyQualifiedName)
if (schemaNode != null) {
typeToSchemaNode.put(entry.value, schemaNode);
binding.typeToDefinition = typeToDefinition
binding.typeToSchemaNode = typeToSchemaNode
binding.typeDefinitions = typeDefinitions
- if(ctx !== null) {
- listenerRegistration = ctx.registerService(SchemaServiceListener,this,new Hashtable<String,String>());
+ if (ctx !== null) {
+ listenerRegistration = ctx.registerService(SchemaServiceListener, this, new Hashtable<String, String>());
}
}
}
promisedSchemas.removeAll(builder);
}
-
+
override close() throws Exception {
listenerRegistration?.unregister();
}
-
+
}
public class BindingIndependentDataServiceConnector implements //
RuntimeDataProvider, //
- Provider {
+ Provider, AutoCloseable {
private final Logger LOG = LoggerFactory.getLogger(BindingIndependentDataServiceConnector.class);
@Override
public DataObject readOperationalData(InstanceIdentifier<? extends DataObject> path) {
- org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path);
- CompositeNode result = biDataService.readOperationalData(biPath);
- return mappingService.dataObjectFromDataDom(path, result);
+ try {
+ org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path);
+ CompositeNode result = biDataService.readOperationalData(biPath);
+ return mappingService.dataObjectFromDataDom(path, result);
+ } catch (DeserializationException e) {
+ throw new IllegalStateException(e);
+ }
}
@Override
public DataObject readConfigurationData(InstanceIdentifier<? extends DataObject> path) {
- org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path);
- CompositeNode result = biDataService.readConfigurationData(biPath);
- return mappingService.dataObjectFromDataDom(path, result);
+ try {
+ org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path);
+ CompositeNode result = biDataService.readConfigurationData(biPath);
+ return mappingService.dataObjectFromDataDom(path, result);
+ } catch (DeserializationException e) {
+ throw new IllegalStateException(e);
+ }
}
private DataModificationTransaction createBindingToDomTransaction(
.beginTransaction();
for (Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> entry : source
.getUpdatedConfigurationData().entrySet()) {
- InstanceIdentifier<?> baKey = mappingService.fromDataDom(entry.getKey());
- DataObject baData = mappingService.dataObjectFromDataDom(baKey, entry.getValue());
- target.putConfigurationData(baKey, baData);
+ try {
+ InstanceIdentifier<?> baKey = mappingService.fromDataDom(entry.getKey());
+ DataObject baData = mappingService.dataObjectFromDataDom(baKey, entry.getValue());
+ target.putConfigurationData(baKey, baData);
+ } catch (DeserializationException e) {
+ LOG.error("Ommiting from BA transaction: {}. Reason{}.", entry.getKey(), e);
+ }
}
for (Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> entry : source
.getUpdatedOperationalData().entrySet()) {
- InstanceIdentifier<?> baKey = mappingService.fromDataDom(entry.getKey());
- DataObject baData = mappingService.dataObjectFromDataDom(baKey, entry.getValue());
- target.putOperationalData(baKey, baData);
+ try {
+
+ InstanceIdentifier<?> baKey = mappingService.fromDataDom(entry.getKey());
+ DataObject baData = mappingService.dataObjectFromDataDom(baKey, entry.getValue());
+ target.putOperationalData(baKey, baData);
+ } catch (DeserializationException e) {
+ LOG.error("Ommiting from BA transaction: {}. Reason{}.", entry.getKey(), e);
+ }
}
for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry : source.getRemovedConfigurationData()) {
- InstanceIdentifier<?> baEntry = mappingService.fromDataDom(entry);
- target.removeConfigurationData(baEntry);
+ try {
+
+ InstanceIdentifier<?> baEntry = mappingService.fromDataDom(entry);
+ target.removeConfigurationData(baEntry);
+ } catch (DeserializationException e) {
+ LOG.error("Ommiting from BA transaction: {}. Reason{}.", entry, e);
+ }
}
for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry : source.getRemovedOperationalData()) {
- InstanceIdentifier<?> baEntry = mappingService.fromDataDom(entry);
- target.removeOperationalData(baEntry);
+ try {
+
+ InstanceIdentifier<?> baEntry = mappingService.fromDataDom(entry);
+ target.removeOperationalData(baEntry);
+ } catch (DeserializationException e) {
+ LOG.error("Ommiting from BA transaction: {}. Reason{}.", entry, e);
+ }
}
return target;
}
start();
}
+ @Override
+ public void close() throws Exception {
+
+ if (baCommitHandlerRegistration != null) {
+ baCommitHandlerRegistration.close();
+ }
+ if (biCommitHandlerRegistration != null) {
+ biCommitHandlerRegistration.close();
+ }
+
+ }
+
private class DomToBindingTransaction implements
DataCommitTransaction<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> {
@Override
public void onRegister(DataCommitHandlerRegistration<InstanceIdentifier<?>, DataObject> registration) {
-
- org.opendaylight.yangtools.yang.data.api.InstanceIdentifier domPath = mappingService.toDataDom(registration.getPath());
+
+ org.opendaylight.yangtools.yang.data.api.InstanceIdentifier domPath = mappingService.toDataDom(registration
+ .getPath());
// FIXME: do registration based on only active commit handlers.
-
+
}
@Override
org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toDataDom(InstanceIdentifier<? extends DataObject> path);
- DataObject dataObjectFromDataDom(InstanceIdentifier<? extends DataObject> path, CompositeNode result);
+ DataObject dataObjectFromDataDom(InstanceIdentifier<? extends DataObject> path, CompositeNode result) throws DeserializationException;
- InstanceIdentifier<?> fromDataDom(org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry);
+ InstanceIdentifier<?> fromDataDom(org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry) throws DeserializationException;
}
--- /dev/null
+package org.opendaylight.controller.sal.binding.impl.connect.dom;
+
+public class DeserializationException extends Exception {
+
+ public DeserializationException() {
+ }
+
+ public DeserializationException(String message) {
+ super(message);
+ }
+
+ public DeserializationException(Throwable cause) {
+ super(cause);
+ }
+
+ public DeserializationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public DeserializationException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
+
+}
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
import org.opendaylight.yangtools.yang.data.api.CompositeNode
import org.opendaylight.controller.md.sal.common.api.data.DataReader
+import org.opendaylight.yangtools.yang.common.QName
+import java.net.URI
+import java.util.List
+import org.opendaylight.yangtools.yang.data.api.Node
+import java.util.ArrayList
+import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl
+import java.util.Map
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier
+import org.opendaylight.yangtools.yang.data.api.SimpleNode
+import java.util.Collections
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates
+import java.util.HashMap
+import static com.google.common.base.Preconditions.*;
+import java.util.Collection
+import java.util.Set
+import java.util.Map.Entry
+import org.slf4j.LoggerFactory
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
class DataReaderRouter extends AbstractDataReadRouter<InstanceIdentifier, CompositeNode> {
+ private static val LOG = LoggerFactory.getLogger(DataReaderRouter);
+ private static val NETCONF_NAMESPACE = URI.create("urn:ietf:params:xml:ns:netconf:base:1.0")
+ private static val NETCONF_DATA = new QName(NETCONF_NAMESPACE,"data");
override protected merge(InstanceIdentifier path, Iterable<CompositeNode> data) {
+ val pathArgument = path.path.last;
+ var empty = true;
+ var name = pathArgument?.nodeType;
+ val nodes = new ArrayList<Node<?>>();
+ val keyNodes = new HashMap<QName, SimpleNode<?>>();
val iterator = data.iterator;
- if(iterator.hasNext) {
- return data.iterator.next
+ for(dataBit : data) {
+ try {
+ if(pathArgument != null && dataBit != null) {
+ empty = false;
+ val keyNodesLocal = getKeyNodes(pathArgument,dataBit);
+ nodes.addAll(dataBit.childrenWithout(keyNodesLocal.entrySet));
+ } else if (dataBit != null) {
+ empty = false;
+ nodes.addAll(dataBit.children)
+ }
+ } catch (IllegalStateException e) {
+ LOG.error("BUG: Readed data for path {} was invalid",path,e);
+ }
}
- return null;
+ if(empty) {
+ return null;
+ }
+ /**
+ * Reading from Root
+ *
+ */
+ if(pathArgument == null) {
+ return new CompositeNodeTOImpl(NETCONF_DATA,null,nodes);
+ }
+ val finalNodes = new ArrayList<Node<?>>();
+ finalNodes.addAll(keyNodes.values);
+ finalNodes.addAll(nodes);
+ return new CompositeNodeTOImpl(name,null,finalNodes);
}
-
+
+
+
+ dispatch def Map<QName, SimpleNode<?>> getKeyNodes(PathArgument argument, CompositeNode node) {
+ return Collections.emptyMap();
+ }
+
+ dispatch def getKeyNodes(NodeIdentifierWithPredicates argument, CompositeNode node) {
+ val ret = new HashMap<QName, SimpleNode<?>>();
+ for (keyValue : argument.keyValues.entrySet) {
+ val simpleNode = node.getSimpleNodesByName(keyValue.key);
+ if(simpleNode !== null && !simpleNode.empty) {
+ checkState(simpleNode.size <= 1,"Only one simple node for key $s is allowed in node $s",keyValue.key,node);
+ checkState(simpleNode.get(0).value == keyValue.value,"Key node must equals to instance identifier value");
+ ret.put(keyValue.key,simpleNode.get(0));
+ }
+ val compositeNode = node.getCompositesByName(keyValue.key);
+ checkState(compositeNode === null || compositeNode.empty,"Key node must be Simple Node, not composite node.");
+ }
+ return ret;
+ }
+
+ def Collection<? extends Node<?>> childrenWithout(CompositeNode node, Set<Entry<QName, SimpleNode<?>>> entries) {
+ if(entries.empty) {
+ return node.children;
+ }
+ val filteredNodes = new ArrayList<Node<?>>();
+ for(scannedNode : node.children) {
+ if(!entries.contains(scannedNode.nodeType)) {
+ filteredNodes.add(scannedNode);
+ }
+ }
+ return filteredNodes;
+ }
+
}
<groupId>org.eclipse.xtend</groupId>
<artifactId>org.eclipse.xtend.lib</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>netty-threadgroup-config</artifactId>
+ <version>0.2.3-SNAPSHOT</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>netconf-client</artifactId>
<groupId>${project.groupId}</groupId>
<artifactId>config-api</artifactId>
<version>${netconf.version}</version>
- <scope>test</scope>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<version>${netconf.version}</version>
<scope>test</scope>
</dependency>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>netconf-api</artifactId>
- <version>${netconf.version}</version>
- <scope>test</scope>
- </dependency>
<dependency>
<groupId>org.opendaylight.bgpcep</groupId>
<artifactId>util</artifactId>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>netconf-client</artifactId>
- <scope>test</scope>
<version>${netconf.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools.model</groupId>
+ <artifactId>ietf-inet-types</artifactId>
+ <version>2010.09.24.2-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>threadpool-config-api</artifactId>
+ <version>0.2.3-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>netty-config-api</artifactId>
+ <version>0.2.3-SNAPSHOT</version>
+ </dependency>
</dependencies>
<packaging>bundle</packaging>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <configuration>
- <instructions>
- <Bundle-Activator>org.opendaylight.controller.sal.connect.netconf.NetconfProvider</Bundle-Activator>
- </instructions>
- </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <version>0.5.9-SNAPSHOT</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ <configuration>
+ <codeGenerators>
+ <generator>
+ <codeGeneratorClass>
+ org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+ </codeGeneratorClass>
+ <outputBaseDir>${project.build.directory}/generated-sources/config</outputBaseDir>
+ <additionalConfiguration>
+ <namespaceToPackage1>
+ urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang
+ </namespaceToPackage1>
+ </additionalConfiguration>
+ </generator>
+ </codeGenerators>
+ <inspectDependencies>true</inspectDependencies>
+ </configuration>
+ </execution>
+ </executions>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-jmx-generator-plugin</artifactId>
+ <version>0.2.3-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <version>1.8</version>
+ <executions>
+ <execution>
+ <id>add-source</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>add-source</goal>
+ </goals>
+ <configuration>
+ <sources>
+ <source>${project.build.directory}/generated-sources/config</source>
+ </sources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.eclipse.xtend</groupId>
+ <artifactId>xtend-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
--- /dev/null
+/**
+* Generated file
+
+* Generated from: yang module name: opendaylight-sal-netconf-connector yang module local name: sal-netconf-connector
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Mon Nov 18 09:44:16 CET 2013
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.controller.config.yang.md.sal.connector.netconf;
+
+import io.netty.channel.EventLoopGroup;
+
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+
+import javax.net.ssl.SSLContext;
+
+import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
+import org.opendaylight.controller.sal.connect.netconf.NetconfDevice;
+import org.osgi.framework.BundleContext;
+
+import static com.google.common.base.Preconditions.*;
+
+import com.google.common.base.Optional;
+import com.google.common.net.InetAddresses;
+
+/**
+*
+*/
+public final class NetconfConnectorModule extends org.opendaylight.controller.config.yang.md.sal.connector.netconf.AbstractNetconfConnectorModule
+{
+
+ private BundleContext bundleContext;
+
+ public NetconfConnectorModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public NetconfConnectorModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, NetconfConnectorModule oldModule, java.lang.AutoCloseable oldInstance) {
+ super(identifier, dependencyResolver, oldModule, oldInstance);
+ }
+
+ @Override
+ public void validate(){
+ super.validate();
+ checkState(getAddress() != null,"Address must be set.");
+ //checkState(getAddress().getIpv4Address() != null || getAddress().getIpv6Address() != null,"Address must be set.");
+ checkState(getPort() != null,"Port must be set.");
+ checkState(getDomRegistry() != null,"Dom Registry must be provided.");
+ }
+
+
+ @Override
+ public java.lang.AutoCloseable createInstance() {
+
+ getDomRegistryDependency();
+ NetconfDevice device = new NetconfDevice(getIdentifier().getInstanceName());
+ String addressValue = getAddress();
+
+
+ /*
+ * Uncomment after Switch to IP Address
+ if(getAddress().getIpv4Address() != null) {
+ addressValue = getAddress().getIpv4Address().getValue();
+ } else {
+ addressValue = getAddress().getIpv6Address().getValue();
+ }
+
+ */
+ InetAddress addr = InetAddresses.forString(addressValue);
+ InetSocketAddress socketAddress = new InetSocketAddress(addr , getPort().intValue());
+ device.setSocketAddress(socketAddress);
+
+ EventLoopGroup bossGroup = getBossThreadGroupDependency();
+ EventLoopGroup workerGroup = getWorkerThreadGroupDependency();
+ Optional<SSLContext> maybeContext = Optional.absent();
+ NetconfClientDispatcher dispatcher = new NetconfClientDispatcher(maybeContext , bossGroup, workerGroup);
+
+ getDomRegistryDependency().registerProvider(device, bundleContext);
+
+ device.start(dispatcher);
+ return device;
+ }
+
+ public void setBundleContext(BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+ }
+}
--- /dev/null
+/**
+ * Generated file
+
+ * Generated from: yang module name: opendaylight-sal-netconf-connector yang module local name: sal-netconf-connector
+ * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+ * Generated at: Mon Nov 18 09:44:16 CET 2013
+ *
+ * Do not modify this file unless it is present under src/main directory
+ */
+package org.opendaylight.controller.config.yang.md.sal.connector.netconf;
+
+import org.opendaylight.controller.config.api.DependencyResolver;
+import org.opendaylight.controller.config.api.DynamicMBeanWithInstance;
+import org.opendaylight.controller.config.spi.Module;
+import org.osgi.framework.BundleContext;
+
+/**
+*
+*/
+public class NetconfConnectorModuleFactory extends
+ org.opendaylight.controller.config.yang.md.sal.connector.netconf.AbstractNetconfConnectorModuleFactory {
+
+ @Override
+ public Module createModule(String instanceName, DependencyResolver dependencyResolver,
+ DynamicMBeanWithInstance old, BundleContext bundleContext) throws Exception {
+ NetconfConnectorModule module = (NetconfConnectorModule) super.createModule(instanceName, dependencyResolver,
+ old, bundleContext);
+ module.setBundleContext(bundleContext);
+ return module;
+ }
+
+ @Override
+ public Module createModule(String instanceName, DependencyResolver dependencyResolver, BundleContext bundleContext) {
+ NetconfConnectorModule module = (NetconfConnectorModule) super.createModule(instanceName, dependencyResolver,
+ bundleContext);
+ module.setBundleContext(bundleContext);
+ return module;
+ }
+}
import java.util.Collections
import org.opendaylight.controller.netconf.client.NetconfClientDispatcher
import org.opendaylight.yangtools.concepts.Registration
+import org.opendaylight.controller.sal.core.api.Provider
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionService
+import static org.opendaylight.controller.sal.connect.netconf.InventoryUtils.*;
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService
+import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction
+import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
-class NetconfDevice implements DataReader<InstanceIdentifier, CompositeNode>, RpcImplementation {
+class NetconfDevice implements Provider, DataReader<InstanceIdentifier, CompositeNode>, RpcImplementation, AutoCloseable {
var NetconfClient client;
var InetSocketAddress socketAddress;
@Property
- val MountProvisionInstance mountInstance;
+ var MountProvisionInstance mountInstance;
@Property
- val InstanceIdentifier path;
-
- Registration<DataReader<InstanceIdentifier,CompositeNode>> operReaderReg
-
- Registration<DataReader<InstanceIdentifier,CompositeNode>> confReaderReg
-
- public new(MountProvisionInstance mount,InstanceIdentifier path) {
- _mountInstance = mount;
- _path = path;
+ var InstanceIdentifier path;
+
+ Registration<DataReader<InstanceIdentifier, CompositeNode>> operReaderReg
+
+ Registration<DataReader<InstanceIdentifier, CompositeNode>> confReaderReg
+
+ String name
+
+ MountProvisionService mountService
+
+ public new(String name) {
+ this.name = name;
+ this.path = InstanceIdentifier.builder(INVENTORY_PATH).nodeWithKey(INVENTORY_NODE,
+ Collections.singletonMap(INVENTORY_ID, name)).toInstance;
}
def start(NetconfClientDispatcher dispatcher) {
- client = new NetconfClient("sal-netconf-connector", socketAddress, dispatcher);
-
- confReaderReg = mountInstance.registerConfigurationReader(path,this);
- operReaderReg = mountInstance.registerOperationalReader(path,this);
+ client = new NetconfClient(name, socketAddress, dispatcher);
+ confReaderReg = mountInstance.registerConfigurationReader(path, this);
+ operReaderReg = mountInstance.registerOperationalReader(path, this);
}
override readConfigurationData(InstanceIdentifier path) {
return result.toRpcResult();
}
+ override getProviderFunctionality() {
+ Collections.emptySet
+ }
+
+ override onSessionInitiated(ProviderSession session) {
+ val dataBroker = session.getService(DataBrokerService);
+
+
+
+ val transaction = dataBroker.beginTransaction
+ if(transaction.operationalNodeNotExisting) {
+ transaction.putOperationalData(path,nodeWithId)
+ }
+ if(transaction.configurationNodeNotExisting) {
+ transaction.putConfigurationData(path,nodeWithId)
+ }
+ transaction.commit().get();
+ mountService = session.getService(MountProvisionService);
+ mountInstance = mountService.createOrGetMountPoint(path);
+ }
+
+ def getNodeWithId() {
+ val id = new SimpleNodeTOImpl(INVENTORY_ID,null,name);
+ return new CompositeNodeTOImpl(INVENTORY_NODE,null,Collections.singletonList(id));
+ }
+
+ def boolean configurationNodeNotExisting(DataModificationTransaction transaction) {
+ return null === transaction.readConfigurationData(path);
+ }
+
+ def boolean operationalNodeNotExisting(DataModificationTransaction transaction) {
+ return null === transaction.readOperationalData(path);
+ }
+
def Node<?> findNode(CompositeNode node, InstanceIdentifier identifier) {
var Node<?> current = node;
}
return current;
}
-
- public def stop() {
+
+ override close() {
confReaderReg?.close()
operReaderReg?.close()
+ client?.close()
}
}
+++ /dev/null
-package org.opendaylight.controller.sal.connect.netconf
-
-import org.opendaylight.controller.sal.core.api.Broker.ProviderSession
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionService
-import org.opendaylight.controller.md.sal.common.api.data.DataProvisionService
-import org.opendaylight.controller.sal.core.api.data.DataProviderService
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
-import org.opendaylight.yangtools.yang.common.QName
-import static org.opendaylight.controller.sal.connect.netconf.InventoryUtils.*;
-import static extension org.opendaylight.controller.sal.connect.netconf.NetconfInventoryUtils.*;
-
-import org.opendaylight.controller.sal.core.api.data.DataChangeListener
-import org.opendaylight.yangtools.yang.data.api.CompositeNode
-import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent
-import java.util.Map
-import java.util.concurrent.ConcurrentHashMap
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance
-import org.opendaylight.controller.netconf.client.NetconfClientDispatcher
-import java.io.OptionalDataException
-import com.google.common.base.Optional
-import java.net.SocketAddress
-import java.net.InetSocketAddress
-
-class NetconfDeviceManager {
-
- val Map<InstanceIdentifier, NetconfDevice> devices = new ConcurrentHashMap;
-
- var ProviderSession session;
-
- @Property
- var DataProviderService dataService;
-
- @Property
- var MountProvisionService mountService;
-
- val nodeUpdateListener = new NetconfInventoryListener(this);
-
-
- @Property
- var NetconfClientDispatcher dispatcher;
-
- def void start() {
- dataService?.registerDataChangeListener(INVENTORY_PATH, nodeUpdateListener);
- if(dispatcher == null) {
- dispatcher = new NetconfClientDispatcher(Optional.absent);
- }
- }
-
- def netconfNodeAdded(InstanceIdentifier path, CompositeNode node) {
- val address = node.endpointAddress;
- val port = Integer.parseInt(node.endpointPort);
- netconfNodeAdded(path,new InetSocketAddress(address,port))
-
- }
-
- def netconfNodeAdded(InstanceIdentifier path, InetSocketAddress address) {
-
- val mountPointPath = path;
- val mountPoint = mountService.createOrGetMountPoint(mountPointPath);
- val localPath = InstanceIdentifier.builder().toInstance;
- val netconfDevice = new NetconfDevice(mountPoint,localPath);
- netconfDevice.setSocketAddress(address);
- netconfDevice.start(dispatcher);
- }
-
- def netconfNodeRemoved(InstanceIdentifier path) {
-
- }
-
-}
-
-class NetconfInventoryListener implements DataChangeListener {
-
- val NetconfDeviceManager manager;
-
- new(NetconfDeviceManager manager) {
- this.manager = manager;
- }
-
- override onDataChanged(DataChangeEvent<InstanceIdentifier, CompositeNode> change) {
-
- //manager.netconfNodeAdded(path, change);
- }
-}
+++ /dev/null
-package org.opendaylight.controller.sal.connect.netconf;
-
-import java.util.Hashtable;
-
-import org.opendaylight.controller.sal.core.api.AbstractProvider;
-import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
-import org.opendaylight.controller.sal.core.api.data.DataProviderService;
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
-import org.osgi.framework.BundleContext;
-
-public class NetconfProvider extends AbstractProvider {
-
- private NetconfDeviceManager netconfDeviceManager;
-
- @Override
- protected void startImpl(BundleContext context) {
- netconfDeviceManager = new NetconfDeviceManager();
- context.registerService(NetconfDeviceManager.class, netconfDeviceManager, new Hashtable<String,String>());
- }
-
-
- @Override
- public void onSessionInitiated(ProviderSession session) {
- MountProvisionService mountService = session.getService(MountProvisionService.class);
-
-
- netconfDeviceManager.setMountService(mountService);
- netconfDeviceManager.start();
- }
-
- @Override
- protected void stopImpl(BundleContext context) {
-
- }
-}
--- /dev/null
+module odl-sal-netconf-connector-cfg {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf";
+ prefix "sal-netconf";
+
+ import config { prefix config; revision-date 2013-04-05; }
+ import threadpool {prefix th;}
+ import netty {prefix netty;}
+ import ietf-inet-types {prefix inet;}
+ import opendaylight-md-sal-dom {prefix dom;}
+
+ description
+ "Service definition for Binding Aware MD-SAL.";
+
+ revision "2013-10-28" {
+ description
+ "Initial revision";
+ }
+
+ identity sal-netconf-connector {
+ base config:module-type;
+ config:java-name-prefix NetconfConnector;
+ }
+
+
+ grouping server {
+ leaf address {
+ type string;
+ }
+
+ leaf port {
+ type uint32;
+ }
+ }
+
+
+ augment "/config:modules/config:module/config:configuration" {
+ case sal-netconf-connector {
+ when "/config:modules/config:module/config:type = 'sal-netconf-connector'";
+
+ leaf address {
+ type string;
+ }
+
+ leaf port {
+ type uint32;
+ }
+
+ container dom-registry {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity dom:dom-broker-osgi-registry;
+ }
+ }
+ }
+
+ container boss-thread-group {
+ uses config:service-ref {
+ refine type {
+ config:required-identity netty:netty-threadgroup;
+ }
+ }
+ }
+
+ container worker-thread-group {
+ uses config:service-ref {
+ refine type {
+ config:required-identity netty:netty-threadgroup;
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
--- /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.sal.rest.api;
+
+public class Draft01 {
+ public static class MediaTypes {
+ public static final String API = "application/vnd.yang.api";
+ public static final String DATASTORE = "application/vnd.yang.datastore";
+ public static final String DATA = "application/vnd.yang.data";
+ public static final String EVENT = "application/vnd.yang.event";
+ public static final String OPERATION = "application/vnd.yang.operation";
+ public static final String PATCH = "application/vnd.yang.patch";
+ }
+}
*/
package org.opendaylight.controller.sal.rest.api;
-import static org.opendaylight.controller.sal.restconf.impl.MediaTypes.API;
-
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.opendaylight.controller.sal.restconf.impl.StructuredData;
@GET
@Path("/modules")
- @Produces({API+JSON,API+XML})
+ @Produces({Draft01.MediaTypes.API+JSON,Draft01.MediaTypes.API+XML,
+ Draft02.MediaTypes.API+JSON,Draft02.MediaTypes.API+XML})
public StructuredData getModules();
@POST
@Path("/operations/{identifier}")
- @Produces({Draft02.MediaTypes.API+JSON,Draft02.MediaTypes.API+XML,API+JSON,API+XML})
+ @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, CompositeNode payload);
@GET
@Path("/config/{identifier:.+}")
- @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML})
+ @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);
- @PUT
+ @POST
@Path("/config/{identifier:.+}")
- @Produces({API+JSON,API+XML})
+ @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);
- @POST
+ @PUT
@Path("/config/{identifier:.+}")
- @Produces({API+JSON,API+XML})
+ @Produces({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})
+ @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML,
+ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
public StructuredData readOperationalData(@PathParam("identifier") String identifier);
- @PUT
+ @POST
@Path("/operational/{identifier:.+}")
- @Produces({API+JSON,API+XML})
+ @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML,
+ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
public Response createOperationalData(@PathParam("identifier") String identifier, CompositeNode payload);
- @POST
+ @PUT
@Path("/operational/{identifier:.+}")
- @Produces({API+JSON,API+XML})
+ @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML,
+ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
public Response updateOperationalData(@PathParam("identifier") String identifier, CompositeNode payload);
}
package org.opendaylight.controller.sal.rest.api;
-import static org.opendaylight.controller.sal.restconf.impl.MediaTypes.API;
-
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.opendaylight.controller.sal.restconf.impl.StructuredData;
@Deprecated
@GET
@Path("/datastore")
- @Produces({API+JSON,API+XML})
+ @Produces({Draft01.MediaTypes.DATASTORE+JSON,Draft01.MediaTypes.DATASTORE+XML})
public StructuredData readAllData();
@Deprecated
@GET
@Path("/datastore/{identifier:.+}")
- @Produces({API+JSON,API+XML})
+ @Produces({Draft01.MediaTypes.DATA+JSON,Draft01.MediaTypes.DATA+XML,
+ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
public StructuredData readData(@PathParam("identifier") String identifier);
@Deprecated
- @PUT
+ @POST
@Path("/datastore/{identifier:.+}")
- @Produces({API+JSON,API+XML})
+ @Produces({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
- @POST
+ @PUT
@Path("/datastore/{identifier:.+}")
- @Produces({API+JSON,API+XML})
+ @Produces({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);
}
import javax.activation.UnsupportedDataTypeException;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
+import org.opendaylight.yangtools.yang.data.api.*;
import org.opendaylight.yangtools.yang.model.api.*;
import org.opendaylight.yangtools.yang.model.api.type.*;
}
private void writeContainer(JsonWriter writer, CompositeNode node, ContainerSchemaNode schema) throws IOException {
- writer.name(node.getNodeType().getLocalName());
+ writeName(node, schema, writer);
writer.beginObject();
writeChildrenOfParent(writer, node, schema);
writer.endObject();
}
- private void writeList(JsonWriter writer, CompositeNode nodeParent, CompositeNode node, ListSchemaNode schema) throws IOException {
- writer.name(node.getNodeType().getLocalName());
+ private void writeList(JsonWriter writer, CompositeNode nodeParent, CompositeNode node, ListSchemaNode schema)
+ throws IOException {
+ writeName(node, schema, writer);
writer.beginArray();
if (nodeParent != null) {
writer.endArray();
}
- private void writeLeafList(JsonWriter writer, CompositeNode nodeParent, SimpleNode<?> node, LeafListSchemaNode schema) throws IOException {
- writer.name(node.getNodeType().getLocalName());
+ private void writeLeafList(JsonWriter writer, CompositeNode nodeParent, SimpleNode<?> node,
+ LeafListSchemaNode schema) throws IOException {
+ writeName(node, schema, writer);
writer.beginArray();
List<SimpleNode<?>> nodeLeafLists = nodeParent.getSimpleNodesByName(node.getNodeType());
}
private void writeLeaf(JsonWriter writer, SimpleNode<?> node, LeafSchemaNode schema) throws IOException {
- writer.name(node.getNodeType().getLocalName());
+ writeName(node, schema, writer);
writeValueOfNodeByType(writer, node, schema.getType());
}
private void writeValueOfNodeByType(JsonWriter writer, SimpleNode<?> node, TypeDefinition<?> type)
throws IOException {
- if (!(node.getValue() instanceof String)) {
- throw new IllegalStateException("Value in SimpleNode should be type String");
- }
- String value = (String) node.getValue();
+ String value = String.valueOf(node.getValue());
// TODO check Leafref, InstanceIdentifierTypeDefinition,
// IdentityrefTypeDefinition, UnionTypeDefinition
TypeDefinition<?> baseType = resolveBaseTypeFrom(type);
} else if (baseType instanceof EmptyTypeDefinition) {
writeEmptyDataTypeToJson(writer);
} else {
- writer.value(value != null ? value : "");
+ writer.value(value.equals("null") ? "" : value);
}
}
return type.getBaseType() != null ? resolveBaseTypeFrom(type.getBaseType()) : type;
}
+ private void writeName(Node<?> node, DataSchemaNode schema, JsonWriter writer) throws IOException {
+ String nameForOutput = node.getNodeType().getLocalName();
+ if (schema.isAugmenting()) {
+ ControllerContext contContext = ControllerContext.getInstance();
+ CharSequence moduleName;
+ moduleName = contContext.toRestconfIdentifier(schema.getQName());
+ if (moduleName != null) {
+ nameForOutput = moduleName.toString();
+ }
+ }
+ writer.name(nameForOutput);
+ }
+
private static final class NumberForJsonWriter extends Number {
private static final long serialVersionUID = -3147729419814417666L;
package org.opendaylight.controller.sal.rest.impl;
-import static org.opendaylight.controller.sal.restconf.impl.MediaTypes.API;
-
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.Provider;
+import org.opendaylight.controller.sal.rest.api.Draft01;
+import org.opendaylight.controller.sal.rest.api.Draft02;
import org.opendaylight.controller.sal.rest.api.RestconfService;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
@Provider
-@Consumes({API+RestconfService.JSON})
+@Consumes({ Draft01.MediaTypes.DATA + RestconfService.JSON, Draft02.MediaTypes.DATA + RestconfService.JSON,
+ MediaType.APPLICATION_JSON })
public enum JsonToCompositeNodeProvider implements MessageBodyReader<CompositeNode> {
INSTANCE;
-
+
@Override
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return true;
try {
return jsonReader.read(entityStream);
} catch (UnsupportedFormatException e) {
- throw new WebApplicationException(e,Response.status(Response.Status.BAD_REQUEST)
- .entity(e.getMessage()).build());
+ throw new WebApplicationException(e, Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage())
+ .build());
}
}
package org.opendaylight.controller.sal.rest.impl;
-import static org.opendaylight.controller.sal.restconf.impl.MediaTypes.API;
-
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
+import org.opendaylight.controller.sal.rest.api.Draft01;
+import org.opendaylight.controller.sal.rest.api.Draft02;
import org.opendaylight.controller.sal.rest.api.RestconfService;
import org.opendaylight.controller.sal.restconf.impl.StructuredData;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import com.google.gson.stream.JsonWriter;
@Provider
-@Produces({API+RestconfService.JSON})
+@Produces({ Draft01.MediaTypes.DATA + RestconfService.JSON, Draft02.MediaTypes.DATA + RestconfService.JSON,
+ MediaType.APPLICATION_JSON })
public enum StructuredDataToJsonProvider implements MessageBodyWriter<StructuredData> {
INSTANCE;
-
+
@Override
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return true;
package org.opendaylight.controller.sal.rest.impl;
-import static org.opendaylight.controller.sal.restconf.impl.MediaTypes.API;
-
import java.io.IOException;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
+import org.opendaylight.controller.sal.rest.api.Draft01;
+import org.opendaylight.controller.sal.rest.api.Draft02;
import org.opendaylight.controller.sal.rest.api.RestconfService;
+import org.opendaylight.controller.sal.restconf.impl.ResponseException;
import org.opendaylight.controller.sal.restconf.impl.StructuredData;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.impl.NodeUtils;
import org.w3c.dom.Document;
@Provider
-@Produces({API+RestconfService.XML})
+@Produces({ Draft01.MediaTypes.DATA + RestconfService.XML, Draft02.MediaTypes.DATA + RestconfService.XML,
+ MediaType.APPLICATION_XML, MediaType.TEXT_XML })
public enum StructuredDataToXmlProvider implements MessageBodyWriter<StructuredData> {
INSTANCE;
-
+
private final static Logger logger = LoggerFactory.getLogger(StructuredDataToXmlProvider.class);
@Override
throws IOException, WebApplicationException {
CompositeNode data = t.getData();
if (data == null) {
- throw new WebApplicationException(Response.status(Response.Status.NOT_FOUND).build());
+ throw new ResponseException(Response.Status.NOT_FOUND, "No data exists.");
}
-
+
Document domTree = NodeUtils.buildShadowDomTree(data);
try {
TransformerFactory tf = TransformerFactory.newInstance();
transformer.transform(new DOMSource(domTree), new StreamResult(entityStream));
} catch (TransformerException e) {
logger.error("Error during translation of Document to OutputStream", e);
- throw new WebApplicationException(Response.status(Response.Status.INTERNAL_SERVER_ERROR).build());
+ throw new ResponseException(Response.Status.INTERNAL_SERVER_ERROR, e.getMessage());
}
}
package org.opendaylight.controller.sal.rest.impl;
-import static org.opendaylight.controller.sal.restconf.impl.MediaTypes.API;
-
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import javax.ws.rs.ext.Provider;
import javax.xml.stream.XMLStreamException;
+import org.opendaylight.controller.sal.rest.api.Draft01;
+import org.opendaylight.controller.sal.rest.api.Draft02;
import org.opendaylight.controller.sal.rest.api.RestconfService;
+import org.opendaylight.controller.sal.restconf.impl.ResponseException;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
@Provider
-@Consumes({ API + RestconfService.XML })
+@Consumes({ Draft01.MediaTypes.DATA + RestconfService.XML, Draft02.MediaTypes.DATA + RestconfService.XML,
+ MediaType.APPLICATION_XML, MediaType.TEXT_XML })
public enum XmlToCompositeNodeProvider implements MessageBodyReader<CompositeNode> {
INSTANCE;
try {
return xmlReader.read(entityStream);
} catch (XMLStreamException | UnsupportedFormatException e) {
- throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage())
- .build());
+ throw new ResponseException(Response.Status.BAD_REQUEST, e.getMessage());
}
}
private def void checkPreconditions() {
if (context === null || dataService === null) {
- throw new WebApplicationException(Response.status(Response.Status.SERVICE_UNAVAILABLE)
- .entity(RestconfProvider::NOT_INITALIZED_MSG).build())
+ throw new ResponseException(Response.Status.SERVICE_UNAVAILABLE, RestconfProvider::NOT_INITALIZED_MSG)
}
}
import java.util.List
import java.util.Map
import java.util.concurrent.ConcurrentHashMap
-import javax.ws.rs.WebApplicationException
import javax.ws.rs.core.Response
import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener
import org.opendaylight.controller.sal.rest.impl.RestconfProvider
private def void checkPreconditions() {
if (schemas === null) {
- throw new WebApplicationException(Response.status(Response.Status.SERVICE_UNAVAILABLE)
- .entity(RestconfProvider::NOT_INITALIZED_MSG).build())
+ throw new ResponseException(Response.Status.SERVICE_UNAVAILABLE, RestconfProvider::NOT_INITALIZED_MSG)
}
}
private def DataSchemaNode collectPathArguments(InstanceIdentifierBuilder builder, List<String> strings,
DataNodeContainer parentNode) {
checkNotNull(strings)
+ if (parentNode === null) {
+ return null;
+ }
if (strings.empty) {
return parentNode as DataSchemaNode;
}
+++ /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.sal.restconf.impl;
-
-public class MediaTypes {
- public static final String API = "application/vnd.yang.api";
- public static final String DATASTORE = "application/vnd.yang.datastore";
- public static final String DATA = "application/vnd.yang.data";
- public static final String EVENT = "application/vnd.yang.event";
- public static final String OPERATION = "application/vnd.yang.operation";
- public static final String PATCH = "application/vnd.yang.patch";
-}
--- /dev/null
+package org.opendaylight.controller.sal.restconf.impl;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+public class ResponseException extends WebApplicationException {
+
+ private static final long serialVersionUID = -5320114450593021655L;
+
+ public ResponseException(Status status, String msg) {
+ super(Response.status(status).type(MediaType.TEXT_PLAIN_TYPE).entity(msg).build());
+ }
+}
private def InstanceIdWithSchemaNode resolveInstanceIdentifier(String identifier) {
val identifierWithSchemaNode = identifier.toInstanceIdentifier
if (identifierWithSchemaNode === null) {
- throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST).entity("URI has bad format")
- .build());
+ throw new ResponseException(Response.Status.BAD_REQUEST, "URI has bad format");
}
return identifierWithSchemaNode
}
package org.opendaylight.controller.sal.restconf.impl;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.*;
public class StructuredData {
-
+
private final CompositeNode data;
private final DataSchemaNode schema;
-
+
public StructuredData(CompositeNode data, DataSchemaNode schema) {
this.data = data;
this.schema = schema;
public DataSchemaNode getSchema() {
return schema;
}
-
}
import java.util.concurrent.Future;
import javax.ws.rs.WebApplicationException;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.*;
import javax.xml.stream.XMLStreamException;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
import org.opendaylight.controller.sal.restconf.impl.*;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.*;
import org.opendaylight.yangtools.yang.data.api.*;
import org.opendaylight.yangtools.yang.data.impl.XmlTreeBuilder;
import org.opendaylight.yangtools.yang.model.api.*;
}
return (CompositeNode) dataTree;
}
-
+
public static Document loadDocumentFrom(InputStream inputStream) {
try {
DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
}
static String convertCompositeNodeDataAndYangToJson(CompositeNode compositeNode, String yangPath, String outputPath) {
+ return convertCompositeNodeDataAndYangToJson(compositeNode, yangPath, outputPath, null, null);
+ }
+
+ static String convertCompositeNodeDataAndYangToJson(CompositeNode compositeNode, String yangPath,
+ String outputPath, String searchedModuleName, String searchedDataSchemaName) {
String jsonResult = null;
Set<Module> modules = null;
}
assertNotNull("modules can't be null.", modules);
+ Module module = null;
+ if (searchedModuleName != null) {
+ for (Module m : modules) {
+ if (m.getName().equals(searchedModuleName)) {
+ module = m;
+ break;
+ }
+ }
+ } else if (modules.size() == 1) {
+ module = modules.iterator().next();
+ }
+ assertNotNull("Module is missing", module);
+
assertNotNull("Composite node can't be null", compositeNode);
StructuredDataToJsonProvider structuredDataToJsonProvider = StructuredDataToJsonProvider.INSTANCE;
- for (Module module : modules) {
- ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream();
- for (DataSchemaNode dataSchemaNode : module.getChildNodes()) {
- StructuredData structuredData = new StructuredData(compositeNode, dataSchemaNode);
- try {
- structuredDataToJsonProvider.writeTo(structuredData, null, null, null, null, null, byteArrayOS);
- } catch (WebApplicationException | IOException e) {
- e.printStackTrace();
+ ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream();
+ DataSchemaNode dataSchemaNode = null;
+ if (searchedDataSchemaName != null) {
+ for (DataSchemaNode dsn : module.getChildNodes()) {
+ if (dsn.getQName().getLocalName().equals(searchedDataSchemaName)) {
+ dataSchemaNode = dsn;
}
- assertFalse(
- "Returning JSON string can't be empty for node " + dataSchemaNode.getQName().getLocalName(),
- byteArrayOS.toString().isEmpty());
- }
- jsonResult = byteArrayOS.toString();
- try {
- outputToFile(byteArrayOS, outputPath);
- } catch (IOException e) {
- System.out.println("Output file wasn't cloased sucessfuly.");
}
+ } else if (module.getChildNodes().size() == 1) {
+ dataSchemaNode = module.getChildNodes().iterator().next();
+ }
+ assertNotNull(dataSchemaNode);
+ // SchemaContextUtil.
+ ControllerContext controllerContext = ControllerContext.getInstance();
+ controllerContext.setSchemas(loadSchemaContext(modules));
+ StructuredData structuredData = new StructuredData(compositeNode, dataSchemaNode);
+ try {
+ structuredDataToJsonProvider.writeTo(structuredData, null, null, null, null, null, byteArrayOS);
+ } catch (WebApplicationException | IOException e) {
+ e.printStackTrace();
}
+ assertFalse("Returning JSON string can't be empty for node " + dataSchemaNode.getQName().getLocalName(),
+ byteArrayOS.toString().isEmpty());
+
+ jsonResult = byteArrayOS.toString();
+ try {
+ outputToFile(byteArrayOS, outputPath);
+ } catch (IOException e) {
+ System.out.println("Output file wasn't cloased sucessfuly.");
+ }
+
return jsonResult;
}
RpcResult<TransactionStatus> rpcResult = DummyRpcResult.builder().result(TransactionStatus.COMMITED).build();
Future<RpcResult<TransactionStatus>> future = DummyFuture.builder().rpcResult(rpcResult).build();
when(controllerContext.toInstanceIdentifier(any(String.class))).thenReturn(instIdAndSchema);
- when(broker.commitConfigurationDataPut(any(InstanceIdentifier.class), any(CompositeNode.class))).thenReturn(future);
+ when(broker.commitConfigurationDataPut(any(InstanceIdentifier.class), any(CompositeNode.class))).thenReturn(
+ future);
restconf.setControllerContext(controllerContext);
restconf.setBroker(broker);
--- /dev/null
+package org.opendaylight.controller.sal.restconf.impl.test;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+public class ToJsonWithAugmentTest {
+
+ /**
+ * Test of json output when as input are specified composite node with empty
+ * data + YANG file
+ */
+ @Test
+ public void augmentedElementsToJson() {
+ String jsonOutput = TestUtils.convertCompositeNodeDataAndYangToJson(
+ TestUtils.loadCompositeNode("/yang-to-json-conversion/augmentation/xml/data.xml"),
+ "/yang-to-json-conversion/augmentation", "/yang-to-json-conversion/augmentation/xml", "yang", "cont");
+
+ assertTrue(jsonOutput.contains("\"augment-leaf:lf2\": \"lf2\""));
+ assertTrue(jsonOutput.contains("\"augment-container:cont1\": {"));
+ assertTrue(jsonOutput.contains("\"augment-container:lf11\": \"lf11\""));
+ assertTrue(jsonOutput.contains("\"augment-list:lst1\": ["));
+ assertTrue(jsonOutput.contains("\"augment-list:lf11\": \"lf1_1\""));
+ assertTrue(jsonOutput.contains("\"augment-list:lf11\": \"lf1_2\""));
+ assertTrue(jsonOutput.contains("\"augment-leaflist:lflst1\": ["));
+ }
+}
import org.junit.BeforeClass;
import org.junit.Test;
import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.sal.rest.api.Draft01;
import org.opendaylight.controller.sal.rest.api.RestconfService;
import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider;
import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
-import org.opendaylight.controller.sal.restconf.impl.MediaTypes;
import org.opendaylight.controller.sal.restconf.impl.RestconfImpl;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
private static ControllerContext controllerContext;
private static BrokerFacade brokerFacade;
private static RestconfImpl restconfImpl;
- private static final MediaType MEDIA_TYPE = new MediaType("application", "vnd.yang.api+xml");
+ private static final MediaType MEDIA_TYPE = new MediaType("application", "vnd.yang.data+xml");
+ private static final MediaType MEDIA_TYPE_DRAFT02 = new MediaType("application", "yang.data+xml");
@BeforeClass
public static void init() throws FileNotFoundException {
public void testBadFormatXmlToCompositeNodeProvider() throws UnsupportedEncodingException, URISyntaxException {
String uri = createUri("/operations/", "ietf-interfaces:interfaces/interface/eth0");
- Response response = target(uri).request(MediaTypes.API + RestconfService.XML).post(
+ Response response = target(uri).request(Draft01.MediaTypes.DATA + RestconfService.XML).post(
Entity.entity("<SimpleNode/>", MEDIA_TYPE));
assertEquals(400, response.getStatus());
- response = target(uri).request(MediaTypes.API + RestconfService.XML).post(
+ response = target(uri).request(Draft01.MediaTypes.DATA + RestconfService.XML).post(
Entity.entity("<SimpleNode>", MEDIA_TYPE));
assertEquals(400, response.getStatus());
}
when(brokerFacade.readOperationalData(any(InstanceIdentifier.class))).thenReturn(null);
- Response response = target(uri).request(MediaTypes.API+RestconfService.XML).get();
+ Response response = target(uri).request(Draft01.MediaTypes.DATA+RestconfService.XML).get();
assertEquals(404, response.getStatus());
}
when(brokerFacade.readOperationalData(any(InstanceIdentifier.class))).thenReturn(null);
- Response response = target(uri).request(MediaTypes.API+RestconfService.XML).get();
+ Response response = target(uri).request(Draft01.MediaTypes.DATA+RestconfService.XML).get();
assertEquals(400, response.getStatus());
}
public void testRpcResultCommitedToStatusCodes() throws UnsupportedEncodingException {
InputStream xmlStream = RestconfImplTest.class.getResourceAsStream("/parts/ietf-interfaces_interfaces.xml");
String xml = TestUtils.getDocumentInPrintableForm(TestUtils.loadDocumentFrom(xmlStream));
- Entity<String> entity = Entity.entity(xml, MEDIA_TYPE);
+ Entity<String> entity = Entity.entity(xml, MEDIA_TYPE_DRAFT02);
RpcResult<TransactionStatus> rpcResult = DummyRpcResult.builder().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);
String uri = createUri("/config/", "ietf-interfaces:interfaces/interface/eth0");
- Response response = target(uri).request(MEDIA_TYPE).put(entity);
- assertEquals(200, response.getStatus());
- response = target(uri).request(MEDIA_TYPE).post(entity);
+ Response response = target(uri).request(MEDIA_TYPE_DRAFT02).put(entity);
assertEquals(204, response.getStatus());
+ response = target(uri).request(MEDIA_TYPE_DRAFT02).post(entity);
+ assertEquals(200, response.getStatus());
uri = createUri("/operational/", "ietf-interfaces:interfaces/interface/eth0");
- response = target(uri).request(MEDIA_TYPE).put(entity);
- assertEquals(200, response.getStatus());
- response = target(uri).request(MEDIA_TYPE).post(entity);
+ response = target(uri).request(MEDIA_TYPE_DRAFT02).put(entity);
assertEquals(204, response.getStatus());
+ response = target(uri).request(MEDIA_TYPE_DRAFT02).post(entity);
+ assertEquals(200, response.getStatus());
uri = createUri("/datastore/", "ietf-interfaces:interfaces/interface/eth0");
response = target(uri).request(MEDIA_TYPE).put(entity);
- assertEquals(200, response.getStatus());
- response = target(uri).request(MEDIA_TYPE).post(entity);
assertEquals(204, response.getStatus());
+ response = target(uri).request(MEDIA_TYPE).post(entity);
+ assertEquals(200, response.getStatus());
}
@Test
public void testRpcResultOtherToStatusCodes() throws UnsupportedEncodingException {
InputStream xmlStream = RestconfImplTest.class.getResourceAsStream("/parts/ietf-interfaces_interfaces.xml");
String xml = TestUtils.getDocumentInPrintableForm(TestUtils.loadDocumentFrom(xmlStream));
- Entity<String> entity = Entity.entity(xml, MEDIA_TYPE);
+ Entity<String> entity = Entity.entity(xml, MEDIA_TYPE_DRAFT02);
RpcResult<TransactionStatus> rpcResult = DummyRpcResult.builder().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);
String uri = createUri("/config/", "ietf-interfaces:interfaces/interface/eth0");
- Response response = target(uri).request(MEDIA_TYPE).put(entity);
+ Response response = target(uri).request(MEDIA_TYPE_DRAFT02).put(entity);
assertEquals(500, response.getStatus());
- response = target(uri).request(MEDIA_TYPE).post(entity);
+ response = target(uri).request(MEDIA_TYPE_DRAFT02).post(entity);
assertEquals(500, response.getStatus());
uri = createUri("/operational/", "ietf-interfaces:interfaces/interface/eth0");
- response = target(uri).request(MEDIA_TYPE).put(entity);
+ response = target(uri).request(MEDIA_TYPE_DRAFT02).put(entity);
assertEquals(500, response.getStatus());
- response = target(uri).request(MEDIA_TYPE).post(entity);
+ response = target(uri).request(MEDIA_TYPE_DRAFT02).post(entity);
assertEquals(500, response.getStatus());
uri = createUri("/datastore/", "ietf-interfaces:interfaces/interface/eth0");
--- /dev/null
+module augment-container {
+ namespace "ns:augment:container";
+ prefix "augcont";
+
+
+ import yang {prefix yng; revision-date 2013-11-26;}
+
+
+ revision "2013-11-26" {
+ }
+
+ augment "/yng:cont" {
+ container cont1 {
+ leaf lf11 {
+ type string;
+ }
+ }
+ }
+
+
+
+}
\ No newline at end of file
--- /dev/null
+module augment-leaf {
+ namespace "ns:augment:leaf";
+ prefix "auglf";
+
+
+ import yang {prefix yng; revision-date 2013-11-26;}
+
+
+ revision "2013-11-26" {
+ }
+
+ augment "/yng:cont" {
+ leaf lf2 {
+ type string;
+ }
+ }
+
+}
\ No newline at end of file
--- /dev/null
+module augment-leaflist {
+ namespace "ns:augment:leaflist";
+ prefix "auglflst";
+
+
+ import yang {prefix yng; revision-date 2013-11-26;}
+
+
+ revision "2013-11-26" {
+ }
+
+ augment "/yng:cont" {
+ leaf-list lflst1 {
+ type string;
+ }
+ }
+
+
+
+}
\ No newline at end of file
--- /dev/null
+module augment-list {
+ namespace "ns:augment:list";
+ prefix "auglst";
+
+
+ import yang {prefix yng; revision-date 2013-11-26;}
+
+
+ revision "2013-11-26" {
+ }
+
+ augment "/yng:cont" {
+ list lst1 {
+ leaf lf11 {
+ type string;
+ }
+ }
+ }
+
+
+
+}
\ No newline at end of file
--- /dev/null
+<cont>
+ <lf1>lf1</lf1>
+ <lf2>lf2</lf2>
+ <cont1>
+ <lf11>lf11</lf11>
+ </cont1>
+ <lst1>
+ <lf11>lf1_1</lf11>
+ </lst1>
+ <lst1>
+ <lf11>lf1_2</lf11>
+ </lst1>
+ <lflst1>lflst1_1</lflst1>
+ <lflst1>lflst1_2</lflst1>
+ <lflst1>lflst1_3</lflst1>
+</cont>
\ No newline at end of file
--- /dev/null
+module yang {
+ namespace "ns:yang";
+
+ prefix "yng";
+ revision 2013-11-26 {
+ }
+
+ container cont {
+ leaf lf1 {
+ type string;
+ }
+
+ }
+
+
+
+}
\ No newline at end of file
@Override
public void onSessionInitiated(ProviderContext session) {
+ pSession = session;
DataProviderService dps = session.<DataProviderService>getSALService(DataProviderService.class);
StatisticsManagerActivator.statsProvider.setDataService(dps);
NotificationProviderService nps = session.<NotificationProviderService>getSALService(NotificationProviderService.class);
public void run() {
while(true){
try {
- spLogger.info("Statistics requester thread started with timer interval : {}",5000);
-
statsRequestSender();
Thread.sleep(5000);
}
}
});
+
+ spLogger.debug("Statistics requester thread started with timer interval : {}",5000);
+
+ statisticsRequesterThread.start();
+
spLogger.info("Statistics Provider started.");
}
//Need to call API to receive all the nodes connected to controller.
List<Node> targetNodes = getAllConnectedNodes();
+
+ if(targetNodes == null)
+ return;
for (Node targetNode : targetNodes){
spLogger.info("Send request for stats collection to node : {})",targetNode.getId());
private List<Node> getAllConnectedNodes(){
Nodes nodes = (Nodes) dps.readOperationalData(nodesIdentifier);
+ if(nodes == null)
+ return null;
+
spLogger.info("Number of connected nodes : {}",nodes.getNode().size());
return nodes.getNode();
}
import org.junit.runner.RunWith;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
import org.opendaylight.controller.sal.connect.netconf.InventoryUtils;
-import org.opendaylight.controller.sal.connect.netconf.NetconfDeviceManager;
import org.opendaylight.controller.sal.connect.netconf.NetconfInventoryUtils;
import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
@Inject
DataBrokerService dataBroker;
- @Inject
- NetconfDeviceManager netconfManager;
-
@Test
public void properInitialized() throws Exception {
InstanceIdentifier path = InstanceIdentifier.builder(InventoryUtils.INVENTORY_PATH)
.nodeWithKey(InventoryUtils.INVENTORY_NODE, InventoryUtils.INVENTORY_ID, "foo").toInstance();
- netconfManager.netconfNodeAdded(path, new InetSocketAddress("127.0.0.1", 8383));
-
InstanceIdentifier mountPointPath = path;