<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>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>
<!-- 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>
<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
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;