Merge "BUG-2633 - Netconf northbound mapping."
authorTony Tkacik <ttkacik@cisco.com>
Thu, 19 Feb 2015 08:07:49 +0000 (08:07 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Thu, 19 Feb 2015 08:07:51 +0000 (08:07 +0000)
23 files changed:
opendaylight/netconf/mdsal-netconf-connector/pom.xml [new file with mode: 0644]
opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/CurrentSchemaContext.java [new file with mode: 0644]
opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/MdsalNetconfOperationService.java [new file with mode: 0644]
opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/MdsalNetconfOperationServiceFactory.java [new file with mode: 0644]
opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/OperationProvider.java [new file with mode: 0644]
opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/TransactionProvider.java [new file with mode: 0644]
opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/Commit.java [new file with mode: 0644]
opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/Datastore.java [new file with mode: 0644]
opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/DiscardChanges.java [new file with mode: 0644]
opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/EditConfig.java [new file with mode: 0644]
opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/Lock.java [new file with mode: 0644]
opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/Unlock.java [new file with mode: 0644]
opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/AbstractGet.java [new file with mode: 0644]
opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/Get.java [new file with mode: 0644]
opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/GetConfig.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/pom.xml
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/CommitNotifier.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/DefaultCommitNotificationProducer.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListenerFactory.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionNegotiatorFactory.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCommit.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationRouterImpl.java
opendaylight/netconf/pom.xml

diff --git a/opendaylight/netconf/mdsal-netconf-connector/pom.xml b/opendaylight/netconf/mdsal-netconf-connector/pom.xml
new file mode 100644 (file)
index 0000000..2808672
--- /dev/null
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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.controller</groupId>
+    <artifactId>netconf-subsystem</artifactId>
+    <version>0.3.0-SNAPSHOT</version>
+  </parent>
+  <artifactId>mdsal-netconf-connector</artifactId>
+  <packaging>bundle</packaging>
+  <name>${project.artifactId}</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>netconf-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>netconf-mapping-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>netconf-util</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>yang-data-impl</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-core-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>commons.logback_settings</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>mockito-configuration</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-core-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>config-util</artifactId>
+    </dependency>
+      <dependency>
+          <groupId>org.opendaylight.yangtools</groupId>
+          <artifactId>yang-data-operations</artifactId>
+          <version>0.7.0-SNAPSHOT</version>
+      </dependency>
+
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <configuration>
+          <instructions>
+            <Import-Package>*</Import-Package>
+          </instructions>
+        </configuration>
+      </plugin>
+      <!--FIXME extract yang plugin definition into parent-->
+      <plugin>
+        <groupId>org.opendaylight.yangtools</groupId>
+        <artifactId>yang-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>config</id>
+            <goals>
+              <goal>generate-sources</goal>
+            </goals>
+            <configuration>
+              <codeGenerators>
+                <generator>
+                  <codeGeneratorClass>org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator</codeGeneratorClass>
+                  <outputBaseDir>${jmxGeneratorPath}</outputBaseDir>
+                  <additionalConfiguration>
+                    <namespaceToPackage1>urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang</namespaceToPackage1>
+                  </additionalConfiguration>
+                </generator>
+                <generator>
+                  <codeGeneratorClass>org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl</codeGeneratorClass>
+                  <outputBaseDir>${salGeneratorPath}</outputBaseDir>
+                </generator>
+              </codeGenerators>
+              <inspectDependencies>true</inspectDependencies>
+            </configuration>
+          </execution>
+        </executions>
+        <dependencies>
+          <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>yang-jmx-generator-plugin</artifactId>
+            <version>${config.version}</version>
+          </dependency>
+        </dependencies>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/CurrentSchemaContext.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/CurrentSchemaContext.java
new file mode 100644 (file)
index 0000000..df671e8
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015 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.netconf.mdsal.connector;
+
+import com.google.common.base.Preconditions;
+import java.util.concurrent.atomic.AtomicReference;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
+
+public class CurrentSchemaContext implements SchemaContextListener, AutoCloseable {
+    final AtomicReference<SchemaContext> currentContext = new AtomicReference<SchemaContext>();
+    private final ListenerRegistration<SchemaContextListener> schemaContextListenerListenerRegistration;
+
+    public SchemaContext getCurrentContext() {
+        Preconditions.checkState(currentContext.get() != null, "Current context not received");
+        return currentContext.get();
+    }
+
+    public CurrentSchemaContext(final SchemaService schemaService) {
+        schemaContextListenerListenerRegistration = schemaService.registerSchemaContextListener(this);
+    }
+
+    @Override
+    public void onGlobalContextUpdated(final SchemaContext schemaContext) {
+        currentContext.set(schemaContext);
+    }
+
+    @Override
+    public void close() throws Exception {
+        schemaContextListenerListenerRegistration.close();
+        currentContext.set(null);
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/MdsalNetconfOperationService.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/MdsalNetconfOperationService.java
new file mode 100644 (file)
index 0000000..f54c5e9
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * 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.netconf.mdsal.connector;
+
+import com.google.common.base.Optional;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.netconf.mapping.api.Capability;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
+import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MdsalNetconfOperationService implements NetconfOperationService {
+
+    private static final Logger LOG = LoggerFactory.getLogger(MdsalNetconfOperationService.class);
+
+    private final CurrentSchemaContext schemaContext;
+    private final String netconfSessionIdForReporting;
+    private final OperationProvider operationProvider;
+
+    public MdsalNetconfOperationService(final CurrentSchemaContext schemaContext, final String netconfSessionIdForReporting,
+                                        final DOMDataBroker dataBroker) {
+        this.schemaContext = schemaContext;
+        // TODO schema contexts are different in data broker and the one we receive here ... the one received here should be updated same way as broker is
+        this.netconfSessionIdForReporting = netconfSessionIdForReporting;
+        this.operationProvider = new OperationProvider(netconfSessionIdForReporting, schemaContext, dataBroker);
+    }
+
+    @Override
+    public void close() {
+
+    }
+
+    // TODO does this get called dynamically ?
+    @Override
+    public Set<Capability> getCapabilities() {
+        final Set<Capability> capabilities = new HashSet<>();
+        // [RFC6241] 8.3.  Candidate Configuration Capability
+        capabilities.add(new BasicCapability("urn:ietf:params:netconf:capability:candidate:1.0"));
+
+        final SchemaContext currentContext = schemaContext.getCurrentContext();
+        final Set<Module> modules = currentContext.getModules();
+        for (final Module module : modules) {
+            if(currentContext.getModuleSource(module).isPresent()) {
+                capabilities.add(new YangStoreCapability(module, currentContext.getModuleSource(module).get()));
+            } else {
+                LOG.warn("Missing source for module {}. This module will not be available from netconf server for session {}",
+                        module, netconfSessionIdForReporting);
+            }
+        }
+
+        return capabilities;
+    }
+
+    @Override
+    public Set<NetconfOperation> getNetconfOperations() {
+        return operationProvider.getOperations();
+    }
+
+    // TODO reuse from netconf impl
+    private static class BasicCapability implements Capability {
+
+        private final String capability;
+
+        private BasicCapability(final String capability) {
+            this.capability = capability;
+        }
+
+        @Override
+        public String getCapabilityUri() {
+            return capability;
+        }
+
+        @Override
+        public Optional<String> getModuleNamespace() {
+            return Optional.absent();
+        }
+
+        @Override
+        public Optional<String> getModuleName() {
+            return Optional.absent();
+        }
+
+        @Override
+        public Optional<String> getRevision() {
+            return Optional.absent();
+        }
+
+        @Override
+        public Optional<String> getCapabilitySchema() {
+            return Optional.absent();
+        }
+
+        @Override
+        public Collection<String> getLocation() {
+            return Collections.emptyList();
+        }
+
+        @Override
+        public String toString() {
+            return capability;
+        }
+    }
+
+    private static final class YangStoreCapability extends BasicCapability {
+
+        private final String content;
+        private final String revision;
+        private final String moduleName;
+        private final String moduleNamespace;
+
+        public YangStoreCapability(final Module module, final String moduleContent) {
+            super(toCapabilityURI(module));
+            this.content = moduleContent;
+            this.moduleName = module.getName();
+            this.moduleNamespace = module.getNamespace().toString();
+            this.revision = SimpleDateFormatUtil.getRevisionFormat().format(module.getRevision());
+        }
+
+        @Override
+        public Optional<String> getCapabilitySchema() {
+            return Optional.of(content);
+        }
+
+        private static String toCapabilityURI(final Module module) {
+            return String.valueOf(module.getNamespace()) + "?module="
+                    + module.getName() + "&revision=" + SimpleDateFormatUtil.getRevisionFormat().format(module.getRevision());
+        }
+
+        @Override
+        public Optional<String> getModuleName() {
+            return Optional.of(moduleName);
+        }
+
+        @Override
+        public Optional<String> getModuleNamespace() {
+            return Optional.of(moduleNamespace);
+        }
+
+        @Override
+        public Optional<String> getRevision() {
+            return Optional.of(revision);
+        }
+    }
+}
diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/MdsalNetconfOperationServiceFactory.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/MdsalNetconfOperationServiceFactory.java
new file mode 100644 (file)
index 0000000..098f25b
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * 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.netconf.mdsal.connector;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+
+public class MdsalNetconfOperationServiceFactory implements NetconfOperationServiceFactory, AutoCloseable {
+
+    private final DOMDataBroker dataBroker;
+    private final CurrentSchemaContext currentSchemaContext;
+
+    public MdsalNetconfOperationServiceFactory(final SchemaService schemaService, final DOMDataBroker domDataBroker) {
+        this.currentSchemaContext = new CurrentSchemaContext(Preconditions.checkNotNull(schemaService));
+        this.dataBroker = Preconditions.checkNotNull(domDataBroker);
+    }
+
+    @Override
+    public MdsalNetconfOperationService createService(final String netconfSessionIdForReporting) {
+        return new MdsalNetconfOperationService(currentSchemaContext, netconfSessionIdForReporting, dataBroker);
+    }
+
+    @Override
+    public void close() throws Exception {
+        currentSchemaContext.close();
+    }
+}
diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/OperationProvider.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/OperationProvider.java
new file mode 100644 (file)
index 0000000..c881ae2
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * 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.netconf.mdsal.connector;
+
+import com.google.common.collect.Sets;
+import java.util.Set;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
+import org.opendaylight.controller.netconf.mdsal.connector.ops.Commit;
+import org.opendaylight.controller.netconf.mdsal.connector.ops.DiscardChanges;
+import org.opendaylight.controller.netconf.mdsal.connector.ops.EditConfig;
+import org.opendaylight.controller.netconf.mdsal.connector.ops.Lock;
+import org.opendaylight.controller.netconf.mdsal.connector.ops.Unlock;
+import org.opendaylight.controller.netconf.mdsal.connector.ops.get.Get;
+import org.opendaylight.controller.netconf.mdsal.connector.ops.get.GetConfig;
+
+final class OperationProvider {
+
+    private final String netconfSessionIdForReporting;
+    private final CurrentSchemaContext schemaContext;
+    private final DOMDataBroker dataBroker;
+    private final TransactionProvider transactionProvider;
+
+    public OperationProvider(final String netconfSessionIdForReporting, final CurrentSchemaContext schemaContext, final DOMDataBroker dataBroker) {
+        this.netconfSessionIdForReporting = netconfSessionIdForReporting;
+        this.schemaContext = schemaContext;
+        this.dataBroker = dataBroker;
+        this.transactionProvider = new TransactionProvider(dataBroker, netconfSessionIdForReporting);
+
+    }
+
+    Set<NetconfOperation> getOperations() {
+        return Sets.<NetconfOperation>newHashSet(
+                new Commit(netconfSessionIdForReporting, transactionProvider),
+                new DiscardChanges(netconfSessionIdForReporting, transactionProvider),
+                new EditConfig(netconfSessionIdForReporting, schemaContext, transactionProvider),
+                new Get(netconfSessionIdForReporting, schemaContext, transactionProvider),
+                new GetConfig(netconfSessionIdForReporting, schemaContext, transactionProvider),
+                new Lock(netconfSessionIdForReporting),
+                new Unlock(netconfSessionIdForReporting)
+        );
+    }
+
+}
diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/TransactionProvider.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/TransactionProvider.java
new file mode 100644 (file)
index 0000000..f1b214b
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2015 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.netconf.mdsal.connector;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.CheckedFuture;
+import java.util.ArrayList;
+import java.util.List;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorTag;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+//TODO make a global TransactionProvider for all Netconf sessions instead of each session having one.
+public class TransactionProvider implements AutoCloseable{
+
+    private static final Logger LOG = LoggerFactory.getLogger(TransactionProvider.class);
+
+    private final DOMDataBroker dataBroker;
+
+    private DOMDataReadWriteTransaction candidateTransaction = null;
+    private DOMDataReadWriteTransaction runningTransaction = null;
+    private final List<DOMDataReadWriteTransaction> allOpenReadWriteTransactions = new ArrayList<>();
+
+    private final String netconfSessionIdForReporting;
+
+    private static final String  NO_TRANSACTION_FOUND_FOR_SESSION = "No candidateTransaction found for session ";
+
+
+    public TransactionProvider(DOMDataBroker dataBroker, String netconfSessionIdForReporting) {
+        this.dataBroker = dataBroker;
+        this.netconfSessionIdForReporting = netconfSessionIdForReporting;
+    }
+
+    @Override
+    public synchronized void close() throws Exception {
+        for (DOMDataReadWriteTransaction rwt : allOpenReadWriteTransactions) {
+            rwt.cancel();
+        }
+
+        allOpenReadWriteTransactions.clear();
+    }
+
+    public synchronized Optional<DOMDataReadWriteTransaction> getCandidateTransaction() {
+        if (candidateTransaction == null) {
+            return Optional.absent();
+        }
+
+        return Optional.of(candidateTransaction);
+    }
+
+    public synchronized DOMDataReadWriteTransaction getOrCreateTransaction() {
+        if (getCandidateTransaction().isPresent()) {
+            return getCandidateTransaction().get();
+        }
+
+        candidateTransaction = dataBroker.newReadWriteTransaction();
+        allOpenReadWriteTransactions.add(candidateTransaction);
+        return candidateTransaction;
+    }
+
+    public synchronized boolean commitTransaction() throws NetconfDocumentedException {
+        if (!getCandidateTransaction().isPresent()) {
+            throw new NetconfDocumentedException(NO_TRANSACTION_FOUND_FOR_SESSION + netconfSessionIdForReporting,
+                    ErrorType.application, ErrorTag.operation_failed, ErrorSeverity.error);
+        }
+
+        CheckedFuture<Void, TransactionCommitFailedException> future = candidateTransaction.submit();
+        try {
+            future.checkedGet();
+        } catch (TransactionCommitFailedException e) {
+            LOG.debug("Transaction {} failed on", candidateTransaction, e);
+            throw new NetconfDocumentedException("Transaction commit failed on " + e.getMessage() + " " + netconfSessionIdForReporting,
+                    ErrorType.application, ErrorTag.operation_failed, ErrorSeverity.error);
+        }
+        allOpenReadWriteTransactions.remove(candidateTransaction);
+        candidateTransaction = null;
+
+        return true;
+    }
+
+    public synchronized void abortTransaction() {
+        LOG.debug("Aborting current candidateTransaction");
+        Optional<DOMDataReadWriteTransaction> otx = getCandidateTransaction();
+        Preconditions.checkState(otx.isPresent(), NO_TRANSACTION_FOUND_FOR_SESSION + netconfSessionIdForReporting);
+        candidateTransaction.cancel();
+        allOpenReadWriteTransactions.remove(candidateTransaction);
+        candidateTransaction = null;
+    }
+
+    public synchronized DOMDataReadWriteTransaction createRunningTransaction() {
+        runningTransaction = dataBroker.newReadWriteTransaction();
+        allOpenReadWriteTransactions.add(runningTransaction);
+        return runningTransaction;
+    }
+
+    public synchronized boolean commitRunningTransaction(DOMDataReadWriteTransaction tx) throws NetconfDocumentedException {
+        allOpenReadWriteTransactions.remove(tx);
+
+        CheckedFuture<Void, TransactionCommitFailedException> future = tx.submit();
+        try {
+            future.checkedGet();
+        } catch (TransactionCommitFailedException e) {
+            LOG.debug("Transaction {} failed on", tx, e);
+            throw new NetconfDocumentedException("Transaction commit failed on " + e.getMessage() + " " + netconfSessionIdForReporting,
+                    ErrorType.application, ErrorTag.operation_failed, ErrorSeverity.error);
+        }
+
+        return true;
+    }
+
+    public synchronized void abortRunningTransaction(DOMDataReadWriteTransaction tx) {
+        LOG.debug("Aborting current running Transaction");
+        Preconditions.checkState(runningTransaction != null, NO_TRANSACTION_FOUND_FOR_SESSION + netconfSessionIdForReporting);
+        tx.cancel();
+        allOpenReadWriteTransactions.remove(tx);
+    }
+
+}
diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/Commit.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/Commit.java
new file mode 100644 (file)
index 0000000..15396cf
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015 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.netconf.mdsal.connector.ops;
+
+import com.google.common.base.Optional;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
+import org.opendaylight.controller.netconf.mdsal.connector.TransactionProvider;
+import org.opendaylight.controller.netconf.util.mapping.AbstractLastNetconfOperation;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+public class Commit extends AbstractLastNetconfOperation{
+
+    private static final Logger LOG = LoggerFactory.getLogger(Commit.class);
+
+    private static final String OPERATION_NAME = "commit";
+    private final TransactionProvider transactionProvider;
+
+    public Commit(final String netconfSessionIdForReporting, final TransactionProvider transactionProvider) {
+        super(netconfSessionIdForReporting);
+        this.transactionProvider = transactionProvider;
+
+    }
+
+    @Override
+    protected Element handleWithNoSubsequentOperations(final Document document, final XmlElement operationElement) throws NetconfDocumentedException {
+
+        boolean commitStatus = transactionProvider.commitTransaction();
+        LOG.trace("Transaction commited succesfuly", commitStatus);
+
+        return XmlUtil.createElement(document, XmlNetconfConstants.OK, Optional.<String>absent());
+    }
+
+    @Override
+    protected String getOperationName() {
+        return OPERATION_NAME;
+    }
+
+}
diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/Datastore.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/Datastore.java
new file mode 100644 (file)
index 0000000..0f86c5a
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2015 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.netconf.mdsal.connector.ops;
+
+public enum Datastore {
+    candidate, running
+}
diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/DiscardChanges.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/DiscardChanges.java
new file mode 100644 (file)
index 0000000..36f6d8e
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015 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.netconf.mdsal.connector.ops;
+
+import com.google.common.base.Optional;
+import java.util.HashMap;
+import java.util.Map;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorTag;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorType;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
+import org.opendaylight.controller.netconf.mdsal.connector.TransactionProvider;
+import org.opendaylight.controller.netconf.util.mapping.AbstractLastNetconfOperation;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+public class DiscardChanges extends AbstractLastNetconfOperation{
+
+    private static final Logger LOG = LoggerFactory.getLogger(DiscardChanges.class);
+
+    private static final String OPERATION_NAME = "discard-changes";
+
+    private final TransactionProvider transactionProvider;
+
+    public DiscardChanges(final String netconfSessionIdForReporting, final TransactionProvider transactionProvider) {
+        super(netconfSessionIdForReporting);
+        this.transactionProvider = transactionProvider;
+    }
+
+    @Override
+    protected Element handleWithNoSubsequentOperations(final Document document, final XmlElement operationElement) throws NetconfDocumentedException {
+        operationElement.getOnlyChildElement(OPERATION_NAME);
+
+        try {
+            transactionProvider.abortTransaction();
+        } catch (IllegalStateException e) {
+            LOG.warn("Abort failed ", e);
+            final Map<String, String> errorInfo = new HashMap<>();
+            errorInfo
+                    .put(ErrorTag.operation_failed.name(),
+                            "Operation failed. Use 'get-config' or 'edit-config' before triggering 'discard-changes' operation");
+            throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.application, ErrorTag.operation_failed,
+                    ErrorSeverity.error, errorInfo);
+        }
+        return XmlUtil.createElement(document, XmlNetconfConstants.OK, Optional.<String>absent());
+    }
+
+    @Override
+    protected String getOperationName() {
+        return OPERATION_NAME;
+    }
+}
diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/EditConfig.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/EditConfig.java
new file mode 100644 (file)
index 0000000..09be416
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2015 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.netconf.mdsal.connector.ops;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Collections;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorTag;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorType;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
+import org.opendaylight.controller.netconf.mdsal.connector.CurrentSchemaContext;
+import org.opendaylight.controller.netconf.mdsal.connector.TransactionProvider;
+import org.opendaylight.controller.netconf.util.mapping.AbstractLastNetconfOperation;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser.DomToNormalizedNodeParserFactory;
+import org.opendaylight.yangtools.yang.data.operations.DataModificationException;
+import org.opendaylight.yangtools.yang.data.operations.DataModificationException.DataExistsException;
+import org.opendaylight.yangtools.yang.data.operations.DataModificationException.DataMissingException;
+import org.opendaylight.yangtools.yang.data.operations.DataOperations;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+public class EditConfig extends AbstractLastNetconfOperation {
+
+    private static final Logger LOG = LoggerFactory.getLogger(EditConfig.class);
+
+    private static final String OPERATION_NAME = "edit-config";
+    private static final String CONFIG_KEY = "config";
+
+    private final CurrentSchemaContext schemaContext;
+    private final TransactionProvider transactionProvider;
+
+    public EditConfig(final String netconfSessionIdForReporting, final CurrentSchemaContext schemaContext, final TransactionProvider transactionProvider) {
+        super(netconfSessionIdForReporting);
+        this.schemaContext = schemaContext;
+        this.transactionProvider = transactionProvider;
+    }
+
+    @Override
+    protected Element handleWithNoSubsequentOperations(final Document document, final XmlElement operationElement) throws NetconfDocumentedException {
+        final XmlElement configElement = getConfigElement(operationElement);
+
+        for (XmlElement element : configElement.getChildElements()) {
+            final String ns = element.getNamespace();
+            final DataSchemaNode schemaNode = getSchemaNodeFromNamespace(ns, element).get();
+            YangInstanceIdentifier ident = YangInstanceIdentifier.of(schemaNode.getQName());
+
+            final NormalizedNode storedNode = readStoredNode(LogicalDatastoreType.CONFIGURATION, ident);
+            try {
+                final Optional<NormalizedNode<?,?>> newNode = modifyNode(schemaNode, element, storedNode);
+                final DOMDataReadWriteTransaction rwTx = transactionProvider.getOrCreateTransaction();
+                if (newNode.isPresent()) {
+                    rwTx.put(LogicalDatastoreType.CONFIGURATION, ident, newNode.get());
+                } else {
+                    rwTx.delete(LogicalDatastoreType.CONFIGURATION, ident);
+                }
+            } catch (final DataModificationException e) {
+                if (e instanceof DataExistsException) {
+                    throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.protocol, ErrorTag.data_exists, ErrorSeverity.error);
+                } else if (e instanceof DataMissingException) {
+                    throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.protocol, ErrorTag.data_missing, ErrorSeverity.error);
+                } else {
+                    //should never happen, since in edit-config only the 2 previous cases can happen
+                    throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.protocol, ErrorTag.operation_failed, ErrorSeverity.error);
+                }
+            }
+        }
+
+        return XmlUtil.createElement(document, XmlNetconfConstants.OK, Optional.<String>absent());
+    }
+
+    private NormalizedNode readStoredNode(final LogicalDatastoreType logicalDatastoreType, final YangInstanceIdentifier path) throws NetconfDocumentedException{
+        final  DOMDataReadWriteTransaction rwTx = transactionProvider.getOrCreateTransaction();
+        final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> readFuture = rwTx.read(logicalDatastoreType, path);
+        try {
+            if (readFuture.checkedGet().isPresent()) {
+                final NormalizedNode node = readFuture.checkedGet().get();
+                return node;
+            } else {
+                LOG.warn("Unable to read node : {} from {} datastore", path, logicalDatastoreType);
+            }
+        } catch (final ReadFailedException e) {
+            //only log this since DataOperations.modify will handle throwing an exception or writing the node.
+            LOG.warn("Unable to read stored data: {}", path, e);
+        }
+
+        //we can return null here since DataOperations.modify handles null as input
+        return null;
+    }
+
+    private Optional<DataSchemaNode> getSchemaNodeFromNamespace(final String namespace, final XmlElement element){
+        Optional<DataSchemaNode> dataSchemaNode = Optional.absent();
+        try {
+            //returns module with newest revision since findModuleByNamespace returns a set of modules and we only need the newest one
+            final Module module = schemaContext.getCurrentContext().findModuleByNamespaceAndRevision(new URI(namespace), null);
+            dataSchemaNode = Optional.of(module.getDataChildByName(element.getName()));
+        } catch (URISyntaxException e) {
+            LOG.debug("Unable to create URI for namespace : {}", namespace);
+        }
+
+        return dataSchemaNode;
+    }
+
+    private Optional<NormalizedNode<?, ?>> modifyNode(final DataSchemaNode schemaNode, final XmlElement element, final NormalizedNode storedNode) throws DataModificationException{
+        if (schemaNode instanceof ContainerSchemaNode) {
+            final ContainerNode modifiedNode =
+                    DomToNormalizedNodeParserFactory
+                            .getInstance(DomUtils.defaultValueCodecProvider())
+                            .getContainerNodeParser()
+                            .parse(Collections.singletonList(element.getDomElement()), (ContainerSchemaNode) schemaNode);
+
+            final Optional<ContainerNode> oNode = DataOperations.modify((ContainerSchemaNode) schemaNode, (ContainerNode) storedNode, modifiedNode);
+            if (!oNode.isPresent()) {
+                return Optional.absent();
+            }
+
+            final NormalizedNode<?,?> node = oNode.get();
+            return Optional.<NormalizedNode<?,?>>of(node);
+        } else if (schemaNode instanceof ListSchemaNode) {
+            final MapNode modifiedNode =
+                DomToNormalizedNodeParserFactory
+                        .getInstance(DomUtils.defaultValueCodecProvider())
+                        .getMapNodeParser()
+                        .parse(Collections.singletonList(element.getDomElement()), (ListSchemaNode) schemaNode);
+
+            final Optional<MapNode> oNode = DataOperations.modify((ListSchemaNode) schemaNode, (MapNode) storedNode, modifiedNode);
+            if (!oNode.isPresent()) {
+                return Optional.absent();
+            }
+
+            final NormalizedNode<?, ?> node = oNode.get();
+            return Optional.<NormalizedNode<?,?>>of(node);
+        } else {
+            //this should never happen since edit-config on any other node type should not be possible nor makes sense
+            LOG.debug("DataNode from module is not ContainerSchemaNode nor ListSchemaNode, aborting..");
+            return Optional.absent();
+        }
+
+    }
+
+    private XmlElement getConfigElement(final XmlElement operationElement) throws NetconfDocumentedException{
+        final Optional<XmlElement> configChildNode = operationElement.getOnlyChildElementOptionally(CONFIG_KEY);
+        if (!configChildNode.isPresent()) {
+            throw new NetconfDocumentedException("Can't get child element with name: " + CONFIG_KEY,
+                    ErrorType.application,
+                    ErrorTag.unknown_element,
+                    ErrorSeverity.error);
+        }
+
+        return configChildNode.get();
+    }
+
+    @Override
+    protected String getOperationName() {
+        return OPERATION_NAME;
+    }
+}
diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/Lock.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/Lock.java
new file mode 100644 (file)
index 0000000..db912c5
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015 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.netconf.mdsal.connector.ops;
+
+import com.google.common.base.Optional;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
+import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException;
+import org.opendaylight.controller.netconf.util.exception.UnexpectedNamespaceException;
+import org.opendaylight.controller.netconf.util.mapping.AbstractLastNetconfOperation;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+public class Lock extends AbstractLastNetconfOperation{
+
+    private static final Logger LOG = LoggerFactory.getLogger(Lock.class);
+
+    private static final String OPERATION_NAME = "lock";
+    private static final String TARGET_KEY = "target";
+
+    public Lock(final String netconfSessionIdForReporting) {
+        super(netconfSessionIdForReporting);
+    }
+
+    @Override
+    protected Element handleWithNoSubsequentOperations(final Document document, final XmlElement operationElement) throws NetconfDocumentedException {
+        final Datastore targetDatastore = extractTargetParameter(operationElement);
+        if (targetDatastore == Datastore.candidate) {
+            LOG.debug("Locking candidate datastore on session: {}", getNetconfSessionIdForReporting());
+            return XmlUtil.createElement(document, XmlNetconfConstants.OK, Optional.<String>absent());
+        }
+
+        throw new NetconfDocumentedException("Unable to lock " + targetDatastore + " datastore", NetconfDocumentedException.ErrorType.application,
+                NetconfDocumentedException.ErrorTag.operation_not_supported, NetconfDocumentedException.ErrorSeverity.error);
+    }
+
+    static Datastore extractTargetParameter(final XmlElement operationElement) throws NetconfDocumentedException {
+        final XmlElement targetChildNode;
+        try {
+            final XmlElement targetElement = operationElement.getOnlyChildElementWithSameNamespace(TARGET_KEY);
+            targetChildNode = targetElement.getOnlyChildElementWithSameNamespace();
+        } catch (final MissingNameSpaceException | UnexpectedNamespaceException e) {
+            LOG.trace("Can't get only child element with same namespace", e);
+            throw NetconfDocumentedException.wrap(e);
+        }
+
+        return Datastore.valueOf(targetChildNode.getName());
+    }
+
+    @Override
+    protected String getOperationName() {
+        return OPERATION_NAME;
+    }
+}
diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/Unlock.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/Unlock.java
new file mode 100644 (file)
index 0000000..2dd2663
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015 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.netconf.mdsal.connector.ops;
+
+import com.google.common.base.Optional;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
+import org.opendaylight.controller.netconf.util.mapping.AbstractLastNetconfOperation;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+public class Unlock extends AbstractLastNetconfOperation{
+
+    private static final Logger LOG = LoggerFactory.getLogger(Unlock.class);
+
+    private static final String OPERATION_NAME = "unlock";
+    private static final String TARGET_KEY = "target";
+
+    public Unlock(final String netconfSessionIdForReporting) {
+        super(netconfSessionIdForReporting);
+    }
+
+    @Override
+    protected Element handleWithNoSubsequentOperations(final Document document, final XmlElement operationElement) throws NetconfDocumentedException {
+        final Datastore targetDatastore = Lock.extractTargetParameter(operationElement);
+        if (targetDatastore == Datastore.candidate) {
+            LOG.debug("Unlocking candidate datastore on session: {}", getNetconfSessionIdForReporting());
+            return XmlUtil.createElement(document, XmlNetconfConstants.OK, Optional.<String>absent());
+        }
+
+        throw new NetconfDocumentedException("Unable to unlock " + targetDatastore + " datastore", NetconfDocumentedException.ErrorType.application,
+                NetconfDocumentedException.ErrorTag.operation_not_supported, NetconfDocumentedException.ErrorSeverity.error);
+    }
+
+    @Override
+    protected String getOperationName() {
+        return OPERATION_NAME;
+    }
+
+}
diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/AbstractGet.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/AbstractGet.java
new file mode 100644 (file)
index 0000000..e0c0044
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2015 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.netconf.mdsal.connector.ops.get;
+
+import com.google.common.base.Function;
+import com.google.common.base.Throwables;
+import com.google.common.collect.Iterables;
+import java.io.IOException;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+import javax.xml.transform.dom.DOMResult;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
+import org.opendaylight.controller.netconf.mdsal.connector.CurrentSchemaContext;
+import org.opendaylight.controller.netconf.mdsal.connector.ops.Datastore;
+import org.opendaylight.controller.netconf.util.mapping.AbstractLastNetconfOperation;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XMLStreamNormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+public abstract class AbstractGet extends AbstractLastNetconfOperation {
+
+    protected static final YangInstanceIdentifier ROOT = YangInstanceIdentifier.builder().build();
+
+    protected final CurrentSchemaContext schemaContext;
+
+
+    public AbstractGet(final String netconfSessionIdForReporting, final CurrentSchemaContext schemaContext) {
+        super(netconfSessionIdForReporting);
+        this.schemaContext = schemaContext;
+    }
+
+    private static final XMLOutputFactory XML_OUTPUT_FACTORY;
+
+    static {
+        XML_OUTPUT_FACTORY = XMLOutputFactory.newFactory();
+        XML_OUTPUT_FACTORY.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, true);
+    }
+
+    protected Node transformNormalizedNode(final Document document, final NormalizedNode<?, ?> data, final YangInstanceIdentifier dataRoot) {
+//        boolean isDataRoot = true;
+
+        final DOMResult result = new DOMResult(document.createElement(XmlNetconfConstants.DATA_KEY));
+
+        final XMLStreamWriter xmlWriter = getXmlStreamWriter(result);
+
+        final NormalizedNodeStreamWriter nnStreamWriter = XMLStreamNormalizedNodeStreamWriter.create(xmlWriter,
+                schemaContext.getCurrentContext(), getSchemaPath(dataRoot));
+
+        final NormalizedNodeWriter nnWriter = NormalizedNodeWriter.forStreamWriter(nnStreamWriter);
+
+//        if (isDataRoot) {
+        writeRootElement(xmlWriter, nnWriter, (ContainerNode) data);
+//        } else {
+//            if (data instanceof MapEntryNode) {
+//                // Restconf allows returning one list item. We need to wrap it
+//                // in map node in order to serialize it properly
+//                data = ImmutableNodes.mapNodeBuilder(data.getNodeType()).addChild((MapEntryNode) data).build();
+//            }
+//            nnWriter.write(data);
+//            nnWriter.flush();
+//        }
+        return result.getNode();
+    }
+
+    private XMLStreamWriter getXmlStreamWriter(final DOMResult result) {
+        try {
+            return XML_OUTPUT_FACTORY.createXMLStreamWriter(result);
+        } catch (final XMLStreamException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private static final Function<PathArgument, QName> PATH_ARG_TO_QNAME = new Function<YangInstanceIdentifier.PathArgument, QName>() {
+        @Override
+        public QName apply(final YangInstanceIdentifier.PathArgument input) {
+            return input.getNodeType();
+        }
+    };
+
+    private SchemaPath getSchemaPath(final YangInstanceIdentifier dataRoot) {
+        return SchemaPath.create(Iterables.transform(dataRoot.getPathArguments(), PATH_ARG_TO_QNAME), dataRoot.equals(ROOT));
+    }
+
+    // TODO this code is located in Restconf already
+    private void writeRootElement(final XMLStreamWriter xmlWriter, final NormalizedNodeWriter nnWriter, final ContainerNode data) {
+        try {
+            final QName name = SchemaContext.NAME;
+            for (final DataContainerChild<? extends PathArgument, ?> child : data.getValue()) {
+                nnWriter.write(child);
+            }
+            nnWriter.flush();
+            xmlWriter.flush();
+        } catch (XMLStreamException | IOException e) {
+            Throwables.propagate(e);
+        }
+    }
+
+    protected static final class GetConfigExecution {
+        private final Datastore datastore;
+
+        public GetConfigExecution(final Datastore datastore) {
+            this.datastore = datastore;
+        }
+
+        public Datastore getDatastore() {
+            return datastore;
+        }
+
+        static GetConfigExecution fromXml(final XmlElement xml, final String operationName) throws NetconfDocumentedException {
+            try {
+                validateInputRpc(xml, operationName);
+            } catch (final NetconfDocumentedException e) {
+                throw new NetconfDocumentedException("Incorrect RPC: " + e.getMessage(), e.getErrorType(), e.getErrorTag(), e.getErrorSeverity(), e.getErrorInfo());
+            }
+
+            final Datastore sourceDatastore;
+            try {
+                sourceDatastore = parseSource(xml);
+            } catch (final NetconfDocumentedException e) {
+                throw new NetconfDocumentedException("Get-config source attribute error: " + e.getMessage(), e.getErrorType(), e.getErrorTag(), e.getErrorSeverity(), e.getErrorInfo());
+            }
+
+            // Add filter
+
+            return new GetConfigExecution(sourceDatastore);
+        }
+
+        private static Datastore parseSource(final XmlElement xml) throws NetconfDocumentedException {
+            final Datastore sourceDatastore;
+            final XmlElement sourceElement = xml.getOnlyChildElement(XmlNetconfConstants.SOURCE_KEY,
+                    XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
+
+            final String sourceParsed = sourceElement.getOnlyChildElement().getName();
+            sourceDatastore = Datastore.valueOf(sourceParsed);
+            return sourceDatastore;
+        }
+
+        private static void validateInputRpc(final XmlElement xml, String operationName) throws NetconfDocumentedException{
+            xml.checkName(operationName);
+            xml.checkNamespace(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
+        }
+    }
+
+}
diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/Get.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/Get.java
new file mode 100644 (file)
index 0000000..a2b2fbb
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2015 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.netconf.mdsal.connector.ops.get;
+
+import com.google.common.base.Optional;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorTag;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorType;
+import org.opendaylight.controller.netconf.mdsal.connector.CurrentSchemaContext;
+import org.opendaylight.controller.netconf.mdsal.connector.TransactionProvider;
+import org.opendaylight.controller.netconf.mdsal.connector.ops.Datastore;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+public class Get extends AbstractGet {
+
+    private static final Logger LOG = LoggerFactory.getLogger(Get.class);
+
+    private static final String OPERATION_NAME = "get";
+
+    private final TransactionProvider transactionProvider;
+
+    public Get(final String netconfSessionIdForReporting, final CurrentSchemaContext schemaContext, final TransactionProvider transactionProvider) {
+        super(netconfSessionIdForReporting, schemaContext);
+        this.transactionProvider = transactionProvider;
+    }
+
+    @Override
+    protected Element handleWithNoSubsequentOperations(Document document, XmlElement operationElement) throws NetconfDocumentedException {
+        GetConfigExecution getConfigExecution = null;
+        try {
+            getConfigExecution = GetConfigExecution.fromXml(operationElement, OPERATION_NAME);
+
+        } catch (final NetconfDocumentedException e) {
+            LOG.warn("Get request processing failed on session: {}", getNetconfSessionIdForReporting(), e);
+            throw e;
+        }
+
+        final YangInstanceIdentifier dataRoot = ROOT;
+        DOMDataReadWriteTransaction rwTx = getTransaction(getConfigExecution.getDatastore());
+        try {
+            final Optional<NormalizedNode<?, ?>> normalizedNodeOptional = rwTx.read(LogicalDatastoreType.OPERATIONAL, dataRoot).checkedGet();
+            if (getConfigExecution.getDatastore() == Datastore.running) {
+                transactionProvider.abortRunningTransaction(rwTx);
+                rwTx = null;
+            }
+            return (Element) transformNormalizedNode(document, normalizedNodeOptional.get(), dataRoot);
+        } catch (ReadFailedException e) {
+            LOG.warn("Unable to read data: {}", dataRoot, e);
+            throw new IllegalStateException("Unable to read data " + dataRoot, e);
+        }
+    }
+
+    private DOMDataReadWriteTransaction getTransaction(Datastore datastore) throws NetconfDocumentedException{
+        if (datastore == Datastore.candidate) {
+            return transactionProvider.getOrCreateTransaction();
+        } else if (datastore == Datastore.running) {
+            return transactionProvider.createRunningTransaction();
+        }
+        throw new NetconfDocumentedException("Incorrect Datastore: ", ErrorType.protocol, ErrorTag.bad_element, ErrorSeverity.error);
+    }
+
+    @Override
+    protected String getOperationName() {
+        return OPERATION_NAME;
+    }
+}
diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/GetConfig.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/GetConfig.java
new file mode 100644 (file)
index 0000000..b56bcc7
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2015 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.netconf.mdsal.connector.ops.get;
+
+import com.google.common.base.Optional;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorTag;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorType;
+import org.opendaylight.controller.netconf.mdsal.connector.CurrentSchemaContext;
+import org.opendaylight.controller.netconf.mdsal.connector.TransactionProvider;
+import org.opendaylight.controller.netconf.mdsal.connector.ops.Datastore;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+public class GetConfig extends AbstractGet {
+
+    private static final Logger LOG = LoggerFactory.getLogger(GetConfig.class);
+
+    private static final String OPERATION_NAME = "get-config";
+
+    private final TransactionProvider transactionProvider;
+
+    public GetConfig(final String netconfSessionIdForReporting, final CurrentSchemaContext schemaContext, final TransactionProvider transactionProvider) {
+        super(netconfSessionIdForReporting, schemaContext);
+        this.transactionProvider = transactionProvider;
+    }
+
+    @Override
+    protected Element handleWithNoSubsequentOperations(Document document, XmlElement operationElement) throws NetconfDocumentedException {
+        GetConfigExecution getConfigExecution = null;
+        try {
+            getConfigExecution = GetConfigExecution.fromXml(operationElement, OPERATION_NAME);
+
+        } catch (final NetconfDocumentedException e) {
+            LOG.warn("Get request processing failed on session: {}", getNetconfSessionIdForReporting(), e);
+            throw e;
+        }
+
+        final YangInstanceIdentifier dataRoot = ROOT;
+        DOMDataReadWriteTransaction rwTx = getTransaction(getConfigExecution.getDatastore());
+        try {
+            final Optional<NormalizedNode<?, ?>> normalizedNodeOptional = rwTx.read(LogicalDatastoreType.CONFIGURATION, dataRoot).checkedGet();
+            if (getConfigExecution.getDatastore() == Datastore.running) {
+                transactionProvider.abortRunningTransaction(rwTx);
+                rwTx = null;
+            }
+            return (Element) transformNormalizedNode(document, normalizedNodeOptional.get(), dataRoot);
+        } catch (ReadFailedException e) {
+            LOG.warn("Unable to read data: {}", dataRoot, e);
+            throw new IllegalStateException("Unable to read data " + dataRoot, e);
+        }
+    }
+
+    private DOMDataReadWriteTransaction getTransaction(Datastore datastore) throws NetconfDocumentedException{
+        if (datastore == Datastore.candidate) {
+            return transactionProvider.getOrCreateTransaction();
+        } else if (datastore == Datastore.running) {
+            return transactionProvider.createRunningTransaction();
+        }
+        throw new NetconfDocumentedException("Incorrect Datastore: ", ErrorType.protocol, ErrorTag.bad_element, ErrorSeverity.error);
+    }
+
+    @Override
+    protected String getOperationName() {
+        return OPERATION_NAME;
+    }
+
+}
index 310073fc72e537330c37885fcd7f75748a327b8d..c4a00aa4ee2c69b838444986ff7d28357306afa0 100644 (file)
         <configuration>
           <instructions>
             <Bundle-Activator>org.opendaylight.controller.netconf.impl.osgi.NetconfImplActivator</Bundle-Activator>
+            <Import-Package>*</Import-Package>
           </instructions>
         </configuration>
       </plugin>
           </execution>
         </executions>
       </plugin>
+        <plugin>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-maven-plugin</artifactId>
+            <executions>
+                <execution>
+                    <id>config</id>
+                    <goals>
+                        <goal>generate-sources</goal>
+                    </goals>
+                    <configuration>
+                        <codeGenerators>
+                            <generator>
+                                <codeGeneratorClass>org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator</codeGeneratorClass>
+                                <outputBaseDir>${jmxGeneratorPath}</outputBaseDir>
+                                <additionalConfiguration>
+                                    <namespaceToPackage1>urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang</namespaceToPackage1>
+                                </additionalConfiguration>
+                            </generator>
+                            <generator>
+                                <codeGeneratorClass>org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl</codeGeneratorClass>
+                                <outputBaseDir>${salGeneratorPath}</outputBaseDir>
+                            </generator>
+                        </codeGenerators>
+                        <inspectDependencies>true</inspectDependencies>
+                    </configuration>
+                </execution>
+            </executions>
+            <dependencies>
+                <dependency>
+                    <groupId>org.opendaylight.controller</groupId>
+                    <artifactId>yang-jmx-generator-plugin</artifactId>
+                    <version>${config.version}</version>
+                </dependency>
+            </dependencies>
+        </plugin>
     </plugins>
   </build>
 
diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/CommitNotifier.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/CommitNotifier.java
new file mode 100644 (file)
index 0000000..d9f8e34
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015 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.netconf.impl;
+
+import java.util.Set;
+import org.w3c.dom.Element;
+
+public interface CommitNotifier {
+    void sendCommitNotification(String message, Element cfgSnapshot, Set<String> capabilities);
+
+    public static final class NoopCommitNotifier implements CommitNotifier {
+
+        private static final CommitNotifier INSTANCE = new NoopCommitNotifier();
+
+        private NoopCommitNotifier() {}
+
+        public static CommitNotifier getInstance() {
+            return INSTANCE;
+        }
+
+        @Override
+        public void sendCommitNotification(final String message, final Element cfgSnapshot, final Set<String> capabilities) {
+            // NOOP
+        }
+    }
+}
index ab37bac683829a95cc4e78ec24bcfb56c584faf1..88ff928c515af00eb22a7b03d8075f23aebc9933 100644 (file)
@@ -24,7 +24,7 @@ import org.slf4j.LoggerFactory;
 import org.w3c.dom.Element;
 
 public class DefaultCommitNotificationProducer extends NotificationBroadcasterSupport implements
-        DefaultCommitOperationMXBean, AutoCloseable {
+        DefaultCommitOperationMXBean, AutoCloseable, CommitNotifier {
 
     private static final Logger LOG = LoggerFactory.getLogger(DefaultCommitNotificationProducer.class);
 
@@ -46,6 +46,7 @@ public class DefaultCommitNotificationProducer extends NotificationBroadcasterSu
         }
     }
 
+    @Override
     public void sendCommitNotification(String message, Element cfgSnapshot, Set<String> capabilities) {
         CommitJMXNotification notif = NetconfJMXNotification.afterCommit(this, message, cfgSnapshot, capabilities);
         LOG.debug("Notification about commit {} sent", notif);
index 0537942487296c19d99ffa2dcc10cea4a64bd6af..604cc5f55b94a4d8a41c00efff669ead36a94af3 100644 (file)
@@ -17,12 +17,12 @@ import org.opendaylight.protocol.framework.SessionListenerFactory;
 
 public class NetconfServerSessionListenerFactory implements SessionListenerFactory<NetconfServerSessionListener> {
 
-    private final DefaultCommitNotificationProducer commitNotifier;
+    private final CommitNotifier commitNotifier;
     private final SessionMonitoringService monitor;
     private final NetconfOperationServiceSnapshot netconfOperationServiceSnapshot;
     private final CapabilityProvider capabilityProvider;
 
-    public NetconfServerSessionListenerFactory(final DefaultCommitNotificationProducer commitNotifier,
+    public NetconfServerSessionListenerFactory(final CommitNotifier commitNotifier,
                                                final SessionMonitoringService monitor,
                                                final NetconfOperationServiceSnapshot netconfOperationServiceSnapshot,
                                                final CapabilityProvider capabilityProvider) {
index 34f4f0e653137235a22e917a99224bb96f138ca7..451c066b772f5d705c0904fadd183ef48926a683 100644 (file)
@@ -44,7 +44,7 @@ public class NetconfServerSessionNegotiatorFactory implements SessionNegotiatorF
     private final SessionIdProvider idProvider;
     private final NetconfOperationProvider netconfOperationProvider;
     private final long connectionTimeoutMillis;
-    private final DefaultCommitNotificationProducer commitNotificationProducer;
+    private final CommitNotifier commitNotificationProducer;
     private final SessionMonitoringService monitoringService;
     private static final Logger LOG = LoggerFactory.getLogger(NetconfServerSessionNegotiatorFactory.class);
     private final Set<String> baseCapabilities;
@@ -52,7 +52,7 @@ public class NetconfServerSessionNegotiatorFactory implements SessionNegotiatorF
     // TODO too many params, refactor
     public NetconfServerSessionNegotiatorFactory(Timer timer, NetconfOperationProvider netconfOperationProvider,
                                                  SessionIdProvider idProvider, long connectionTimeoutMillis,
-                                                 DefaultCommitNotificationProducer commitNot,
+                                                 CommitNotifier commitNot,
                                                  SessionMonitoringService monitoringService) {
         this(timer, netconfOperationProvider, idProvider, connectionTimeoutMillis, commitNot, monitoringService, DEFAULT_BASE_CAPABILITIES);
     }
@@ -60,7 +60,7 @@ public class NetconfServerSessionNegotiatorFactory implements SessionNegotiatorF
     // TODO too many params, refactor
     public NetconfServerSessionNegotiatorFactory(Timer timer, NetconfOperationProvider netconfOperationProvider,
                                                  SessionIdProvider idProvider, long connectionTimeoutMillis,
-                                                 DefaultCommitNotificationProducer commitNot,
+                                                 CommitNotifier commitNot,
                                                  SessionMonitoringService monitoringService, Set<String> baseCapabilities) {
         this.timer = timer;
         this.netconfOperationProvider = netconfOperationProvider;
index fbe855f8bebddcb8aeffd728b553ce112fc50f6c..742255f973ca4eaebf79958e4c67d251e3a1b922 100644 (file)
@@ -12,7 +12,7 @@ import com.google.common.base.Preconditions;
 import java.io.InputStream;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
-import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
+import org.opendaylight.controller.netconf.impl.CommitNotifier;
 import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider;
 import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouter;
 import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
@@ -31,11 +31,11 @@ public class DefaultCommit extends AbstractNetconfOperation {
 
     private static final String NOTIFY_ATTR = "notify";
 
-    private final DefaultCommitNotificationProducer notificationProducer;
+    private final CommitNotifier notificationProducer;
     private final CapabilityProvider cap;
     private final NetconfOperationRouter operationRouter;
 
-    public DefaultCommit(DefaultCommitNotificationProducer notifier, CapabilityProvider cap,
+    public DefaultCommit(CommitNotifier notifier, CapabilityProvider cap,
                          String netconfSessionIdForReporting, NetconfOperationRouter netconfOperationRouter) {
         super(netconfSessionIdForReporting);
         this.notificationProducer = notifier;
index 2178d4eedffb1a280b8fa6bfe49a489d8be72138..c8fa3417473219cc284e5a7891726c52c58ad344 100644 (file)
@@ -17,7 +17,7 @@ import java.util.NavigableMap;
 import java.util.Set;
 import java.util.TreeMap;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
-import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
+import org.opendaylight.controller.netconf.impl.CommitNotifier;
 import org.opendaylight.controller.netconf.impl.NetconfServerSession;
 import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider;
 import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCloseSession;
@@ -44,7 +44,7 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
     private final Collection<NetconfOperation> allNetconfOperations;
 
     public NetconfOperationRouterImpl(final NetconfOperationServiceSnapshot netconfOperationServiceSnapshot, final CapabilityProvider capabilityProvider,
-            final DefaultCommitNotificationProducer commitNotifier) {
+            final CommitNotifier commitNotifier) {
         this.netconfOperationServiceSnapshot = Preconditions.checkNotNull(netconfOperationServiceSnapshot);
 
         final String sessionId = netconfOperationServiceSnapshot.getNetconfSessionIdForReporting();
index 653dd70b2986bde1bcb91f058899e949478c31dd..0f1423968625f73963002749910e6d10876e4eae 100644 (file)
@@ -20,6 +20,7 @@
     <module>netconf-config</module>
     <module>netconf-impl</module>
     <module>config-netconf-connector</module>
+    <module>mdsal-netconf-connector</module>
     <module>netconf-util</module>
     <module>netconf-netty-util</module>
     <module>config-persister-impl</module>