NETCONF-542: PUT request return 500 if operational data are used 46/72446/3
authormiroslav.kovac <miroslav.kovac@pantheon.tech>
Tue, 29 May 2018 18:09:24 +0000 (20:09 +0200)
committerJakubToth <jakub.toth@pantheon.tech>
Mon, 4 Jun 2018 09:23:21 +0000 (09:23 +0000)
  * Cherry-pick

Change-Id: I5e45b0276e39c3a6af647b6632b67b3f96751464
Signed-off-by: miroslav.kovac <miroslav.kovac@pantheon.tech>
netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/AbstractWriteTx.java
restconf/restconf-nb-rfc8040/pom.xml
restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/utils/FutureCallbackTx.java
restconf/restconf-parent/pom.xml

index 60bf213f88880b4575aa80e4d6141d4005a6e15f..56b3dab7d94ca1c779824fd48e38d7d1a0e5fac7 100644 (file)
@@ -235,19 +235,8 @@ public abstract class AbstractWriteTx implements DOMDataWriteTransaction {
         Futures.addCallback(Futures.allAsList(resultsFutures), new FutureCallback<List<DOMRpcResult>>() {
             @Override
             public void onSuccess(@Nonnull final List<DOMRpcResult> domRpcResults) {
-                domRpcResults.forEach(domRpcResult -> {
-                    if (!domRpcResult.getErrors().isEmpty() && !transformed.isDone()) {
-                        final NetconfDocumentedException exception =
-                                new NetconfDocumentedException(id + ":RPC during tx failed",
-                                        DocumentedException.ErrorType.APPLICATION,
-                                        DocumentedException.ErrorTag.OPERATION_FAILED,
-                                        DocumentedException.ErrorSeverity.ERROR);
-                        transformed.setException(exception);
-                    }
-                });
-
                 if (!transformed.isDone()) {
-                    transformed.set(RpcResultBuilder.<Void>success().build());
+                    extractResult(domRpcResults, transformed);
                 }
             }
 
@@ -267,6 +256,61 @@ public abstract class AbstractWriteTx implements DOMDataWriteTransaction {
         return transformed;
     }
 
+    private void extractResult(final List<DOMRpcResult> domRpcResults,
+                               final SettableFuture<RpcResult<Void>> transformed) {
+        for (final DOMRpcResult domRpcResult : domRpcResults) {
+            if (!domRpcResult.getErrors().isEmpty()) {
+                final RpcError error = domRpcResult.getErrors().iterator().next();
+                final RpcError.ErrorType errorType = error.getErrorType();
+                final DocumentedException.ErrorType eType;
+                switch (errorType) {
+                    case RPC:
+                        eType = DocumentedException.ErrorType.RPC;
+                        break;
+                    case PROTOCOL:
+                        eType = DocumentedException.ErrorType.PROTOCOL;
+                        break;
+                    case TRANSPORT:
+                        eType = DocumentedException.ErrorType.TRANSPORT;
+                        break;
+                    case APPLICATION:
+                        eType = DocumentedException.ErrorType.APPLICATION;
+                        break;
+                    default:
+                        eType = DocumentedException.ErrorType.APPLICATION;
+                        break;
+                }
+                final RpcError.ErrorSeverity severity = error.getSeverity();
+                final DocumentedException.ErrorSeverity eSeverity;
+                switch (severity) {
+                    case ERROR:
+                        eSeverity = DocumentedException.ErrorSeverity.ERROR;
+                        break;
+                    case WARNING:
+                        eSeverity = DocumentedException.ErrorSeverity.WARNING;
+                        break;
+                    default:
+                        eSeverity = DocumentedException.ErrorSeverity.ERROR;
+                        break;
+                }
+                final String message;
+                if (error.getMessage() == null || error.getMessage().isEmpty()) {
+                    message = id + ":RPC during tx failed";
+                } else {
+                    message = error.getMessage();
+                }
+                final NetconfDocumentedException exception = new NetconfDocumentedException(message,
+                        eType,
+                        DocumentedException.ErrorTag.from(error.getTag()),
+                        eSeverity);
+                transformed.setException(exception);
+                return;
+            }
+        }
+
+        transformed.set(RpcResultBuilder.<Void>success().build());
+    }
+
     AutoCloseable addListener(final TxListener listener) {
         listeners.add(listener);
         return () -> listeners.remove(listener);
index 83f562986968beae8f29c7a7bcc251c510ee7d9a..ac9f586a6b2aa201050bbbe2ec126dd006b4d94c 100644 (file)
     <dependency>
       <groupId>org.opendaylight.netconf</groupId>
       <artifactId>restconf-common-models</artifactId>
-      </dependency>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.netconf</groupId>
       <artifactId>restconf-common</artifactId>
-      </dependency>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.netconf</groupId>
       <artifactId>ietf-yang-library</artifactId>
-      </dependency>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.netconf</groupId>
+      <artifactId>netconf-api</artifactId>
+    </dependency>
 
     <dependency>
       <groupId>org.opendaylight.yangtools</groupId>
index 4969942ac46955f41d769671c8eee6af04b1288a..447836260bca9a607f8c2524e854e1a3321ada2c 100644 (file)
@@ -7,12 +7,16 @@
  */
 package org.opendaylight.restconf.nb.rfc8040.rests.utils;
 
+import com.google.common.base.Throwables;
 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.DOMRpcException;
 import org.opendaylight.controller.md.sal.dom.spi.DefaultDOMRpcResult;
+import org.opendaylight.netconf.api.NetconfDocumentedException;
 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
+import org.opendaylight.restconf.common.errors.RestconfError;
 import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.slf4j.Logger;
@@ -58,9 +62,26 @@ final class FutureCallbackTx {
                 rpcErrorList.add(
                         RpcResultBuilder.newError(RpcError.ErrorType.RPC, "operation-failed", e.getMessage()));
                 dataFactory.setResult((T) new DefaultDOMRpcResult(rpcErrorList));
+            } else if (e instanceof TransactionCommitFailedException) {
+                /* If device send some error message we want this message to get to client
+                   and not just to throw it away or override it with new generic message.
+                   We search for NetconfDocumentedException that was send from netconfSB
+                   and we create RestconfDocumentedException accordingly.
+                */
+                final List<Throwable> causalChain = Throwables.getCausalChain(e);
+                for (Throwable error : causalChain) {
+                    if (error instanceof NetconfDocumentedException) {
+                        throw new RestconfDocumentedException(error.getMessage(),
+                                RestconfError.ErrorType.valueOfCaseInsensitive(
+                                        ((NetconfDocumentedException) error).getErrorType().getTypeValue()),
+                                RestconfError.ErrorTag.valueOfCaseInsensitive(
+                                        ((NetconfDocumentedException) error).getErrorTag().getTagValue()), e);
+                    }
+                }
+
+                throw new RestconfDocumentedException("Transaction(" + txType + ") not committed correctly", e);
             } else {
-                throw new RestconfDocumentedException(
-                        "Transaction(" + txType + ") not committed correctly", e);
+                throw new RestconfDocumentedException("Transaction failed", e);
             }
         }
     }
index d1c2ac50bb8d995e8e16c0df7acb2cc049ee8cce..7e6a0dd9c9bd3179b3da1331aced2b06e14a977d 100644 (file)
         <type>pom</type>
         <scope>import</scope>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.netconf</groupId>
+        <artifactId>netconf-artifacts</artifactId>
+        <version>1.5.0-SNAPSHOT</version>
+        <type>pom</type>
+        <scope>import</scope>
+      </dependency>
       <dependency>
         <groupId>org.opendaylight.netconf</groupId>
         <artifactId>restconf-artifacts</artifactId>