<artifactId>clustering.services</artifactId>
<version>0.5.1-SNAPSHOT</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-util</artifactId>
+ <version>0.2.5-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>threadpool-config-impl</artifactId>
+ <version>0.2.5-SNAPSHOT</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-binding</artifactId>
<artifactId>lispflowmapping-commons</artifactId>
<version>${lispflowmapping.version}</version>
</dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.lispflowmapping</groupId>
+ <artifactId>mappingservice.netconf</artifactId>
+ <version>${lispflowmapping.version}</version>
+ </dependency>
</dependencies>
</dependencyManagement>
<dependency>
<groupId>org.opendaylight.lispflowmapping</groupId>
<artifactId>mappingservice.neutron</artifactId>
- </dependency>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.lispflowmapping</groupId>
+ <artifactId>mappingservice.netconf</artifactId>
+ </dependency>
</dependencies>
--- /dev/null
+Manifest-Version: 1.0\r
+Bnd-LastModified: 1409296681049\r
+Build-Jdk: 1.7.0_65\r
+Built-By: fcoras\r
+Bundle-ManifestVersion: 2\r
+Bundle-Name: LISP Flow Mapping Netconf Connector\r
+Bundle-SymbolicName: org.opendaylight.lispflowmapping.mappingservice.net\r
+ conf\r
+Bundle-Version: 1.1.11.SNAPSHOT\r
+Created-By: Apache Maven Bundle Plugin\r
+Export-Package: org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml\r
+ .ns.yang.lispflowmapping.netconf.rev140706;uses:="org.opendaylight.yang\r
+ tools.yang.binding,org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.\r
+ yang.ietf.inet.types.rev100924,com.google.common.collect,org.opendaylig\r
+ ht.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.re\r
+ v130405,org.opendaylight.yangtools.yang.common";version="1.1.11.SNAPSHO\r
+ T",org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lis\r
+ pflowmapping.netconf.impl.rev140706.modules.module.configuration;uses:=\r
+ "org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.contr\r
+ oller.config.rev130405.modules.module,org.opendaylight.yangtools.yang.b\r
+ inding,org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang\r
+ .lispflowmapping.netconf.impl.rev140706.modules.module.configuration.lf\r
+ m.ncc.provider.impl,org.opendaylight.yangtools.yang.common";version="1.\r
+ 1.11.SNAPSHOT",org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml\r
+ .ns.yang.lispflowmapping.netconf.impl.rev140706;uses:="org.opendaylight\r
+ .yangtools.yang.binding,org.opendaylight.yang.gen.v1.urn.opendaylight.p\r
+ arams.xml.ns.yang.controller.md.sal.binding.rev131028,com.google.common\r
+ .collect,org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.ya\r
+ ng.controller.config.rev130405,org.opendaylight.yangtools.yang.common";\r
+ version="1.1.11.SNAPSHOT",org.opendaylight.yang.gen.v1.urn.opendaylight\r
+ .params.xml.ns.yang.lispflowmapping.netconf.impl.rev140706.modules.modu\r
+ le.configuration.lfm.ncc.provider.impl;uses:="org.opendaylight.yang.gen\r
+ .v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405,org\r
+ .opendaylight.yangtools.yang.binding,org.opendaylight.yangtools.yang.co\r
+ mmon";version="1.1.11.SNAPSHOT"\r
+Import-Package: com.google.common.collect;version="[14.0,15)",com.google\r
+ .common.util.concurrent;version="[14.0,15)",javax.management,org.openda\r
+ ylight.controller.config.api;version="[0.2,1)",org.opendaylight.control\r
+ ler.config.api.annotations;version="[0.2,1)",org.opendaylight.controlle\r
+ r.config.api.jmx;version="[0.2,1)",org.opendaylight.controller.config.s\r
+ pi;version="[0.2,1)",org.opendaylight.controller.config.util;version="[\r
+ 0.2,1)",org.opendaylight.controller.config.yang.md.sal.binding,org.open\r
+ daylight.controller.config.yang.md.sal.connector.netconf,org.opendaylig\r
+ ht.controller.sal.binding.api,org.opendaylight.yang.gen.v1.urn.ietf.par\r
+ ams.xml.ns.yang.ietf.inet.types.rev100924;version="[2010.9,2011)",org.o\r
+ pendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.\r
+ config.rev130405;version="[0.2,1)",org.opendaylight.yang.gen.v1.urn.ope\r
+ ndaylight.params.xml.ns.yang.controller.config.rev130405.modules.module\r
+ ;version="[0.2,1)",org.opendaylight.yang.gen.v1.urn.opendaylight.params\r
+ .xml.ns.yang.controller.md.sal.binding.rev131028,org.opendaylight.yang.\r
+ gen.v1.urn.opendaylight.params.xml.ns.yang.lispflowmapping.netconf.rev1\r
+ 40706,org.opendaylight.yangtools.yang.binding;version="[0.6,1)",org.ope\r
+ ndaylight.yangtools.yang.binding.annotations;version="[0.6,1)",org.open\r
+ daylight.yangtools.yang.common;version="[0.6,1)",org.osgi.framework;ver\r
+ sion="[1.7,2)",org.slf4j;version="[1.7,2)"\r
+Tool: Bnd-1.50.0\r
--- /dev/null
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.lispflowmapping</groupId>
+ <artifactId>mappingservice-parent</artifactId>
+ <version>1.1.11-SNAPSHOT</version>
+ <relativePath>..</relativePath>
+ </parent>
+ <artifactId>mappingservice.netconf</artifactId>
+ <name>LISP Flow Mapping Netconf Connector</name>
+ <packaging>bundle</packaging>
+ <scm>
+ <connection>scm:git:https://git.opendaylight.org/gerrit/p/lispflowmapping.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/lispflowmapping.git</developerConnection>
+ <url>https://wiki.opendaylight.org/view/OpenDaylight_Lisp_Flow_Mapping:Main</url>
+ <tag>HEAD</tag>
+ </scm>
+
+ <properties>
+ <ietf-inet-types.version>2010.09.24.4-SNAPSHOT</ietf-inet-types.version>
+ <yang-jmx-generator.version>1.0.0-SNAPSHOT</yang-jmx-generator.version>
+ <yangtools.version>0.6.2-SNAPSHOT</yangtools.version>
+ <mdsal.version>1.1-SNAPSHOT</mdsal.version>
+ <config.version>0.2.5-SNAPSHOT</config.version>
+ <osgi.core.version>5.0.0</osgi.core.version>
+ <salGeneratorPath>src/main/yang-gen-sal</salGeneratorPath>
+ <jmxGeneratorPath>src/main/yang-gen-config</jmxGeneratorPath>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-util</artifactId>
+ </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-broker-impl</artifactId>
+ <version>${mdsal.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ <version>${mdsal.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>threadpool-config-impl</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>threadpool-config-api</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-manager</artifactId>
+ <version>${config.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools.model</groupId>
+ <artifactId>ietf-inet-types</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-binding</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-common-util</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-common</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-data-impl</artifactId>
+ <version>${yangtools.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-parser-impl</artifactId>
+ <version>${yangtools.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-config</artifactId>
+ <version>${mdsal.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <version>${osgi.core.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>mockito-configuration</artifactId>
+ <scope>test</scope>
+ <version>${yangtools.version}</version>
+ </dependency>
+
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <configuration>
+ <instructions>
+ <Private-Package>
+ org.opendaylight.lispflowmapping.netconf.impl,
+ org.opendaylight.lispflowmapping.config.yang.netconf.impl,
+ </Private-Package>
+ <Export-Package>
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lispflowmapping.netconf.rev140706.*,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lispflowmapping.netconf.impl.rev140706.*,
+ </Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-jmx-generator-plugin</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>maven-sal-api-gen-plugin</artifactId>
+ <version>${yangtools.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <version>${osgi.core.version}</version>
+ </dependency>
+ </dependencies>
+ <executions>
+ <execution>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ <configuration>
+ <yangFilesRootDir>src/main/yang</yangFilesRootDir>
+ <codeGenerators>
+ <generator>
+ <codeGeneratorClass>org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl</codeGeneratorClass>
+ <outputBaseDir>${salGeneratorPath}</outputBaseDir>
+ </generator>
+ <generator>
+ <codeGeneratorClass>org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator</codeGeneratorClass>
+ <outputBaseDir>${jmxGeneratorPath}</outputBaseDir>
+ <additionalConfiguration>
+ <namespaceToPackage1>urn:opendaylight:params:xml:ns:yang:lispflowmapping==org.opendaylight.lispflowmapping.config.yang</namespaceToPackage1>
+ <namespaceToPackage2>urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang</namespaceToPackage2>
+ </additionalConfiguration>
+ </generator>
+ </codeGenerators>
+ <inspectDependencies>true</inspectDependencies>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
+
+
--- /dev/null
+/*
+ * Copyright (c) 2014 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.lispflowmapping.config.yang.netconf.impl;
+
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.lispflowmapping.netconf.impl.LispDeviceNetconfConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lispflowmapping.netconf.rev140706.LfmNetconfConnectorService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class LfmNetconfConnectorProviderModule extends org.opendaylight.lispflowmapping.config.yang.netconf.impl.AbstractLfmNetconfConnectorProviderModule {
+ private static final Logger log = LoggerFactory.getLogger(LfmNetconfConnectorProviderModule.class);
+
+ public LfmNetconfConnectorProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public LfmNetconfConnectorProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.lispflowmapping.config.yang.netconf.impl.LfmNetconfConnectorProviderModule oldModule, java.lang.AutoCloseable oldInstance) {
+ super(identifier, dependencyResolver, oldModule, oldInstance);
+ }
+
+ @Override
+ public void customValidation() {
+ // add custom validation form module attributes here.
+ }
+
+ @Override
+ public java.lang.AutoCloseable createInstance() {
+
+ final LispDeviceNetconfConnector lnconfConnector = LispDeviceNetconfConnector.createLispDeviceNetconfConnector();
+
+ final BindingAwareBroker.RpcRegistration<LfmNetconfConnectorService> rpcRegistration = getRpcRegistryDependency()
+ .addRpcImplementation(LfmNetconfConnectorService.class, lnconfConnector);
+
+
+ // Wrap as AutoCloseable and close registrations to md-sal at close()
+ final class AutoCloseableNCC implements AutoCloseable {
+
+ @Override
+ public void close() throws Exception {
+ rpcRegistration.close();
+ lnconfConnector.close();
+ log.info("Lisp netconf connector (instance {}) torn down.", this);
+ }
+ }
+
+ AutoCloseable ret = new AutoCloseableNCC();
+ log.info("Lisp netconf connector provider (instance {}) initialized.", ret);
+ return ret;
+
+ }
+
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2014 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.lispflowmapping.config.yang.netconf.impl;
+public class LfmNetconfConnectorProviderModuleFactory extends org.opendaylight.lispflowmapping.config.yang.netconf.impl.AbstractLfmNetconfConnectorProviderModuleFactory {
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.lispflowmapping.netconf.impl;
+
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+
+import org.opendaylight.lispflowmapping.netconf.impl.LispNetconfConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lispflowmapping.netconf.rev140706.BuildConnectorInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lispflowmapping.netconf.rev140706.LfmNetconfConnectorService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lispflowmapping.netconf.rev140706.RemoveConnectorInput;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
+import org.opendaylight.controller.config.api.ConflictingVersionException;
+import org.opendaylight.controller.config.api.ValidationException;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.slf4j.LoggerFactory;
+import org.slf4j.Logger;
+
+import com.google.common.util.concurrent.SettableFuture;
+
+
+public class LispDeviceNetconfConnector implements AutoCloseable, LfmNetconfConnectorService {
+
+ private static final Logger logger = LoggerFactory.getLogger(LispDeviceNetconfConnector.class);
+
+ private final ExecutorService executor;
+ private LispNetconfConnector nconfConnector;
+
+ public static LispDeviceNetconfConnector createLispDeviceNetconfConnector() {
+ return new LispDeviceNetconfConnector(Executors.newFixedThreadPool(1), new LispNetconfConnector());
+ }
+
+ public LispDeviceNetconfConnector(ExecutorService executor, LispNetconfConnector nconfConnector) {
+ this.executor = executor;
+ this.nconfConnector = nconfConnector;
+ logger.info( "LispDeviceNetconfConnector constructed" );
+ }
+
+ /**
+ * Implemented from the AutoCloseable interface.
+ */
+ @Override
+ public void close() throws ExecutionException, InterruptedException {
+ executor.shutdown();
+ }
+
+
+ /**
+ * RestConf RPC call implemented from the LfmNetconfConnectorService interface.
+ */
+ @Override
+ public Future<RpcResult<Void>> buildConnector(final BuildConnectorInput input) {
+ SettableFuture<RpcResult<Void>> futureResult = SettableFuture.create();
+
+ logger.trace("Received RPC to buildConnector: " + input);
+
+ if (verifyBuildInput(input, futureResult) != true) {
+ return futureResult;
+ }
+
+ return executor.submit(new MakeConnector(input));
+
+ }
+
+ @Override
+ public Future<RpcResult<Void>> removeConnector(final RemoveConnectorInput input) {
+ SettableFuture<RpcResult<Void>> futureResult = SettableFuture.create();
+
+ if (verifyRemoveInput(input, futureResult) != true) {
+ return futureResult;
+ }
+
+ return executor.submit(new RemoveConnector(input) );
+
+ }
+
+ private boolean verifyBuildInput(final BuildConnectorInput req, SettableFuture<RpcResult<Void>> futureResult ) {
+ if (req.getInstance() == null) {
+ logger.error("Instance name not initialized");
+ futureResult.set(RpcResultBuilder.<Void> failed()
+ .withError(ErrorType.APPLICATION, "exception", "Instance name not initialized")
+ .build());
+ return false;
+ }
+
+ if (req.getAddress() == null) {
+ logger.error("IP address not initialized");
+ futureResult.set(RpcResultBuilder.<Void> failed()
+ .withError(ErrorType.APPLICATION, "exception", "IP address not initialized")
+ .build());
+ return false;
+ }
+
+ if (req.getPort() == null) {
+ logger.error("Port not initialized");
+ futureResult.set(RpcResultBuilder.<Void> failed()
+ .withError(ErrorType.APPLICATION, "exception", "Port not initialized")
+ .build());
+ return false;
+ }
+
+ if (req.getUsername() == null) {
+ logger.error("Username not initialized");
+ futureResult.set(RpcResultBuilder.<Void> failed()
+ .withError(ErrorType.APPLICATION, "exception", "Username not initialized")
+ .build());
+ return false;
+ }
+
+ if (req.getPassword() == null) {
+ logger.error("Password not initialized");
+ futureResult.set(RpcResultBuilder.<Void> failed()
+ .withError(ErrorType.APPLICATION, "exception", "Password not initialized")
+ .build());
+ return false;
+ }
+
+ return true;
+ }
+
+ private boolean verifyRemoveInput(final RemoveConnectorInput conn, SettableFuture<RpcResult<Void>> futureResult) {
+ if (conn.getInstance() == null) {
+ logger.error("Instance name not initialized");
+ futureResult.set(RpcResultBuilder.<Void> failed()
+ .withError(ErrorType.APPLICATION, "exception", "Instance name not initialized")
+ .build());
+ return false;
+ }
+
+ return true;
+ }
+
+
+ private class MakeConnector implements Callable<RpcResult<Void>> {
+
+ final BuildConnectorInput buildConnectorInput;
+
+ public MakeConnector(final BuildConnectorInput buildConnectorInput) {
+ this.buildConnectorInput = buildConnectorInput;
+ }
+
+ @Override
+ public RpcResult<Void> call() {
+
+ try {
+ nconfConnector.createNetconfConnector(buildConnectorInput.getInstance(), buildConnectorInput.getAddress(),
+ buildConnectorInput.getPort().getValue(), buildConnectorInput.getUsername(), buildConnectorInput.getPassword());
+ logger.info("LispNetconfConnector {} built", buildConnectorInput.getInstance());
+ return RpcResultBuilder.<Void>success().build();
+ } catch( InstanceAlreadyExistsException e ) {
+ logger.error("LispNetconfConnector {} already exists!", buildConnectorInput.getInstance());
+ return RpcResultBuilder.<Void> failed()
+ .withError(ErrorType.APPLICATION, "exists", "LispNetconfConnector exists")
+ .build();
+ } catch (ConflictingVersionException ex) {
+ logger.error("LispNetconfConnector {} version exception", buildConnectorInput.getInstance());
+ return RpcResultBuilder.<Void> failed()
+ .withError(ErrorType.APPLICATION, "exception", "LispNetconfConnector version exception")
+ .build();
+ } catch ( ValidationException ex) {
+ logger.error("LispNetconfConnector {} validation exception", buildConnectorInput.getInstance());
+ return RpcResultBuilder.<Void> failed()
+ .withError(ErrorType.APPLICATION, "exception", "LispNetconfConnector validation exception")
+ .build();
+ }
+
+ }
+
+ }
+
+ private class RemoveConnector implements Callable<RpcResult<Void>> {
+ final RemoveConnectorInput removeConnectorInput;
+
+ public RemoveConnector(final RemoveConnectorInput connectorInput) {
+ this.removeConnectorInput = connectorInput;
+ }
+
+ @Override
+ public RpcResult<Void> call() {
+ try {
+ nconfConnector.removeNetconfConnector(removeConnectorInput.getInstance());
+ logger.info("LispNetconfConnector {} removed!", removeConnectorInput.getInstance());
+ return RpcResultBuilder.<Void> success().build();
+ } catch( InstanceNotFoundException e ) {
+ logger.info("LispNetconfConnector {} doesn't exists!", removeConnectorInput.getInstance());
+ return RpcResultBuilder.<Void> failed()
+ .withError(ErrorType.APPLICATION, "no-exist", "LispNetconfConnector doesn't exist")
+ .build();
+ } catch( ValidationException e ) {
+ logger.info("LispNetconfConnector {}: Could not validate remove transactions!", removeConnectorInput.getInstance());
+ return RpcResultBuilder.<Void> failed()
+ .withError(ErrorType.APPLICATION, "fail", "LispNetconfConnector doesn't exist")
+ .build();
+ } catch (ConflictingVersionException e) {
+ logger.error("LispNetconfConnector {}: Cannot remove due to conflicting version", removeConnectorInput.getInstance() );
+ return RpcResultBuilder.<Void> failed()
+ .withError(ErrorType.APPLICATION, "fail", "Conflicting version exception")
+ .build();
+ } catch (Exception e) {
+ logger.error("LispNetconfConnector {} exception while removing: {}", removeConnectorInput.getInstance(), e.getClass());
+ return RpcResultBuilder.<Void> failed()
+ .withError(ErrorType.APPLICATION, "fail", "Cannot remove LispNetconfConnector: " + removeConnectorInput.getInstance())
+ .build();
+ }
+
+ }
+ }
+ }
--- /dev/null
+/*
+ * Copyright (c) 2014 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.lispflowmapping.netconf.impl;
+
+import java.lang.management.ManagementFactory;
+import java.util.Set;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+import org.opendaylight.controller.config.api.ConflictingVersionException;
+import org.opendaylight.controller.config.api.ValidationException;
+import org.opendaylight.controller.config.util.ConfigRegistryJMXClient;
+import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
+import org.opendaylight.controller.config.yang.md.sal.binding.impl.BindingBrokerImplModuleFactory;
+import org.opendaylight.controller.config.yang.md.sal.connector.netconf.NetconfConnectorModuleFactory;
+import org.opendaylight.controller.config.yang.md.sal.connector.netconf.NetconfConnectorModuleMXBean;
+import org.opendaylight.controller.config.yang.md.sal.dom.impl.DomBrokerImplModuleFactory;
+import org.opendaylight.controller.config.yang.netty.eventexecutor.GlobalEventExecutorModuleFactory;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Host;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
+import org.opendaylight.controller.config.yang.threadpool.impl.flexible.FlexibleThreadPoolModuleFactory;
+import org.opendaylight.controller.config.yang.config.netconf.client.dispatcher.NetconfClientDispatcherModuleFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class LispNetconfConnector {
+ private ConfigRegistryJMXClient configRegistryClient;
+
+ private static final Logger logger = LoggerFactory.getLogger(LispNetconfConnector.class);
+
+ private MBeanServer platformMBeanServer;
+
+ public LispNetconfConnector() {
+
+ // Obtain the platform's MBeanServer (should've been previously created)
+ // and create a ConfigRegistry JMX client via which modules can be created
+ // and destroyed
+ platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
+ configRegistryClient = new ConfigRegistryJMXClient(platformMBeanServer);
+
+ }
+
+ /**
+ * Build a sal-netconf-connector to device using given credentials. Module instantiation and dependency resolution
+ * are done via a JMX ConfigTransactionClient
+ * @param instanceName
+ * @param host
+ * @param port
+ * @param username
+ * @param password
+ * @throws InstanceAlreadyExistsException
+ * @throws ConflictingVersionException
+ * @throws ValidationException
+ */
+ public void createNetconfConnector(String instanceName, Host host, Integer port, String username, String password) throws InstanceAlreadyExistsException, ConflictingVersionException, ValidationException {
+
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+
+ if (transaction == null) {
+ logger.error("Could not create transaction with ConfigRegistry! Cannot build NETCONF connector!");
+ return;
+ }
+
+ // create sal-netconf-connector module and via an mxBean configure all
+ // yang defined parameters
+ ObjectName connName = transaction.createModule(NetconfConnectorModuleFactory.NAME, instanceName);
+ NetconfConnectorModuleMXBean mxBean = transaction.newMXBeanProxy(connName, NetconfConnectorModuleMXBean.class);
+
+ mxBean.setAddress(host);
+ mxBean.setPassword(password);
+ mxBean.setPort(new PortNumber(port));
+ mxBean.setUsername(username);
+ mxBean.setTcpOnly(false);
+
+ if (solveDependencies(transaction, mxBean) != true) {
+ logger.error("Failed to solve dependencies! Aborting!");
+ return;
+ }
+
+ transaction.commit();
+
+ }
+
+ public void removeNetconfConnector(String instanceName) throws InstanceNotFoundException, ValidationException, ConflictingVersionException {
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+ transaction.destroyModule(NetconfConnectorModuleFactory.NAME, instanceName);
+ transaction.commit();
+ }
+
+ /**
+ * Lookup sal-netconf-connector dependencies using a ConfigTransactionJMXClient and configure them for the module
+ * we are about to instantiate. As long as the netconf module in configuration/initial is loaded, all of
+ * dependencies should be solvable.
+ * @param transaction
+ * @param mxBean
+ * @return
+ */
+ private boolean solveDependencies(ConfigTransactionJMXClient transaction, NetconfConnectorModuleMXBean mxBean) {
+
+ ObjectName bindingBrokerRegistry = findConfigBean(BindingBrokerImplModuleFactory.NAME, transaction);
+ if (bindingBrokerRegistry != null ) {
+ mxBean.setBindingRegistry(bindingBrokerRegistry);
+ } else {
+ logger.debug("No BindingBroker instance found");
+ return false;
+ }
+
+ ObjectName domRegistry = findConfigBean(DomBrokerImplModuleFactory.NAME, transaction);
+ if (domRegistry != null) {
+ mxBean.setDomRegistry(domRegistry);
+ } else {
+ logger.debug("No DomRegistryBroker instance found");
+ return false;
+ }
+
+ ObjectName eventExecutor = findConfigBean(GlobalEventExecutorModuleFactory.NAME, transaction);
+ if (eventExecutor != null) {
+ mxBean.setEventExecutor(eventExecutor);
+ } else {
+ logger.debug("No EventExecutor instance found");
+ return false;
+ }
+
+ ObjectName threadpool = findConfigBean(FlexibleThreadPoolModuleFactory.NAME, transaction);
+ if (threadpool != null) {
+ mxBean.setProcessingExecutor(threadpool);
+ } else {
+ logger.debug("No ThreadPool instance found");
+ return false;
+ }
+
+ ObjectName clientDispatcher = findConfigBean(NetconfClientDispatcherModuleFactory.NAME, transaction);
+ if (clientDispatcher != null) {
+ mxBean.setClientDispatcher(clientDispatcher);
+ } else {
+ logger.debug("No ClientDispatcher instance found");
+ return false;
+ }
+
+ return true;
+
+ }
+
+ /**
+ * Uses a ConfigTransactionJMXClient to find the first object name of an already instantiated MBean
+ * based on the string name of the class.
+ * @param name
+ * @param transaction
+ * @return
+ */
+ private ObjectName findConfigBean(String name, ConfigTransactionJMXClient transaction) {
+ Set<ObjectName> set = transaction.lookupConfigBeans(name);
+ if (set.size() > 0) {
+ return set.iterator().next();
+ } else {
+ return null;
+ }
+ }
+
+
+}
--- /dev/null
+module lfm-ncc-provider-impl {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:lispflowmapping:netconf:impl";
+ prefix "lfm-ncc-provider-impl";
+
+ import config { prefix config; revision-date 2013-04-05; }
+ import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28; }
+
+ description
+ "This module contains the base YANG definitions for lispflowmapping-netconf-connector implementation.";
+
+ revision "2014-07-06" {
+ description
+ "Initial revision.";
+ }
+
+ identity lfm-ncc-provider-impl {
+ base config:module-type;
+ config:java-name-prefix LfmNetconfConnectorProvider;
+ }
+
+ augment "/config:modules/config:module/config:configuration" {
+ case lfm-ncc-provider-impl {
+ when "/config:modules/config:module/config:type = 'lfm-ncc-provider-impl'";
+
+ container rpc-registry {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity mdsal:binding-rpc-registry;
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+module lfm-netconf-connector {
+ yang-version 1;
+
+ namespace "urn:opendaylight:params:xml:ns:yang:lispflowmapping:netconf";
+ prefix "lnc";
+
+ import config { prefix config; revision-date 2013-04-05; }
+ import ietf-inet-types {prefix inet; revision-date "2010-09-24";}
+
+ organization "Cisco Systems, Inc.";
+
+ contact
+ "Florin Coras <fcoras@ac.upc.edu>";
+
+ revision "2014-07-06" {
+ description
+ "Data model for lispflowmapping netconf connector";
+ }
+
+ container nc-connector {
+ presence
+ "Indicates the netconf connector service is available";
+
+ description
+ "Top-level container for all connector database objects.";
+ }
+
+ rpc build-connector {
+ description
+ "Build netconf connector";
+ input {
+ leaf instance {
+ type string;
+ description "instance name";
+ }
+
+ leaf address {
+ type inet:host;
+ description "Device address";
+ }
+
+ leaf port {
+ type inet:port-number;
+ description "Device port";
+ }
+
+ leaf username {
+ type string;
+ description "Username for netconf connection";
+ }
+
+ leaf password {
+ type string;
+ description "Password for netconf connection";
+ }
+ }
+ }
+
+ rpc remove-connector {
+ description
+ "Removes a given netconf connector";
+ input {
+ leaf instance {
+ type string;
+ description "instance name";
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.lispflowmapping.netconf.impl;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+
+import java.util.concurrent.Executors;
+
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Host;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lispflowmapping.netconf.rev140706.BuildConnectorInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lispflowmapping.netconf.rev140706.BuildConnectorInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lispflowmapping.netconf.rev140706.RemoveConnectorInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lispflowmapping.netconf.rev140706.RemoveConnectorInputBuilder;
+
+public class LispDeviceNetconfConnectorTest {
+
+
+ @Test
+ public void testRemoveConnector() throws Exception {
+ LispNetconfConnector mockedConnector = getLispNetconfConnector();
+ LispDeviceNetconfConnector testedLispDeviceNetconfConnector = new LispDeviceNetconfConnector(Executors.newFixedThreadPool(1), mockedConnector);
+
+ assertEquals(testedLispDeviceNetconfConnector.removeConnector(removeInput("n1")).get().isSuccessful(), true);
+ verify(mockedConnector).removeNetconfConnector(any(String.class));
+
+ testedLispDeviceNetconfConnector.close();
+ }
+
+ @Test
+ public void testRemoveConnectorFail() throws Exception {
+ LispNetconfConnector mockedConnector = getLispNetconfConnector();
+ LispDeviceNetconfConnector testedLispDeviceNetconfConnector = new LispDeviceNetconfConnector(Executors.newFixedThreadPool(1), mockedConnector);
+ assertEquals(testedLispDeviceNetconfConnector.removeConnector(removeInput(null)).get().isSuccessful(), false);
+ testedLispDeviceNetconfConnector.close();
+ }
+
+ @Test
+ public void testMakeConnector() throws Exception {
+ LispNetconfConnector mockedConnector = getLispNetconfConnector();
+ LispDeviceNetconfConnector testedLispDeviceNetconfConnector = new LispDeviceNetconfConnector(Executors.newFixedThreadPool(1), mockedConnector);
+ assertEquals(testedLispDeviceNetconfConnector.buildConnector(buildConnectorInput("n1", "1.1.1.1", 830, "user", "pass")).get().isSuccessful(), true);
+
+ verify(mockedConnector).createNetconfConnector(any(String.class), any(Host.class), any(Integer.class), any(String.class), any(String.class));
+ testedLispDeviceNetconfConnector.close();
+ }
+
+ @Test
+ public void testMakeConnectorFail() throws Exception{
+ LispNetconfConnector mockedConnector = getLispNetconfConnector();
+ LispDeviceNetconfConnector testedLispDeviceNetconfConnector = new LispDeviceNetconfConnector(Executors.newFixedThreadPool(1), mockedConnector);
+
+ assertEquals(testedLispDeviceNetconfConnector.buildConnector(buildConnectorInput(null, "1.1.1.1", 830, "user", "pass")).get().isSuccessful(), false);
+ assertEquals(testedLispDeviceNetconfConnector.buildConnector(buildConnectorInput("n1", null, 830, "user", "pass")).get().isSuccessful(), false);
+ assertEquals(testedLispDeviceNetconfConnector.buildConnector(buildConnectorInput("n1", "1.1.1.1", null, "user", "pass")).get().isSuccessful(), false);
+ assertEquals(testedLispDeviceNetconfConnector.buildConnector(buildConnectorInput("n1", "1.1.1.1", 830, null, "pass")).get().isSuccessful(), false);
+ assertEquals(testedLispDeviceNetconfConnector.buildConnector(buildConnectorInput("n1", "1.1.1.1", 830, "user", null)).get().isSuccessful(), false);
+
+ testedLispDeviceNetconfConnector.close();
+ }
+
+ private BuildConnectorInput buildConnectorInput(String instance, String address, Integer port, String user, String pass) {
+ BuildConnectorInputBuilder input = new BuildConnectorInputBuilder();
+ input.setInstance(instance);
+ input.setAddress(address == null ? null : new Host(new IpAddress(new Ipv4Address(address))));
+ input.setPort(port == null ? null : new PortNumber(port));
+ input.setUsername(user);
+ input.setPassword(pass);
+ return input.build();
+ }
+
+ private RemoveConnectorInput removeInput(String instance) {
+ RemoveConnectorInputBuilder input = new RemoveConnectorInputBuilder();
+ input.setInstance(instance);
+ return input.build();
+ }
+
+ private static LispNetconfConnector getLispNetconfConnector() throws Exception{
+ LispNetconfConnector conn = mock(LispNetconfConnector.class);
+ doNothing().when(conn).createNetconfConnector(any(String.class), any(Host.class), any(Integer.class), any(String.class), any(String.class));
+ doNothing().when(conn).removeNetconfConnector(any(String.class));
+ return(conn);
+ }
+}
<module>southbound</module>
<module>northbound</module>
<module>neutron</module>
+ <module>netconf</module>
<module>integrationtest</module>
</modules>
<dependencies>