Merge changes If79fa865,Ia6652643
[controller.git] / opendaylight / netconf / netconf-impl / src / main / java / org / opendaylight / controller / netconf / impl / osgi / NetconfOperationRouterImpl.java
index c7e1740ebc5c6e9cb06f857f10f64394ccb3c398..d70a15c18bdf933d56df70d7f7e9be07df6653da 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.controller.netconf.impl.osgi;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
+import org.opendaylight.controller.netconf.api.NetconfSession;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
 import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
@@ -17,13 +18,27 @@ import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider;
 import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCloseSession;
 import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCommit;
 import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultGetSchema;
-import org.opendaylight.controller.netconf.mapping.api.*;
+import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultStartExi;
+import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultStopExi;
+import org.opendaylight.controller.netconf.mapping.api.DefaultNetconfOperation;
+import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationFilter;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationFilterChain;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 
-import java.util.*;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
 
 public class NetconfOperationRouterImpl implements NetconfOperationRouter {
 
@@ -36,6 +51,7 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
 
     private final CapabilityProvider capabilityProvider;
 
+
     public NetconfOperationRouterImpl(NetconfOperationServiceSnapshot netconfOperationServiceSnapshot,
             CapabilityProvider capabilityProvider, DefaultCommitNotificationProducer commitNotifier) {
 
@@ -48,6 +64,10 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
                 .getNetconfSessionIdForReporting()));
         defaultNetconfOperations.add(new DefaultCloseSession(netconfOperationServiceSnapshot
                 .getNetconfSessionIdForReporting()));
+        defaultNetconfOperations.add(new DefaultStartExi(netconfOperationServiceSnapshot
+                .getNetconfSessionIdForReporting()));
+        defaultNetconfOperations.add(new DefaultStopExi(netconfOperationServiceSnapshot
+                .getNetconfSessionIdForReporting()));
 
         allNetconfOperations = getAllNetconfOperations(defaultNetconfOperations, netconfOperationServiceSnapshot);
 
@@ -79,7 +99,8 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
         for (NetconfOperationService netconfOperationService : netconfOperationServiceSnapshot.getServices()) {
             final Set<NetconfOperationFilter> filtersFromService = netconfOperationService.getFilters();
             for (NetconfOperationFilter filter : filtersFromService) {
-                Preconditions.checkState(result.contains(filter) == false, "Filter %s already present", filter);
+                Preconditions.checkState(result.contains(filter) == false,
+                        "Filter %s already present, all filters so far: %s", filter, result);
                 result.add(filter);
             }
         }
@@ -91,9 +112,55 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
     }
 
     @Override
-    public synchronized Document onNetconfMessage(Document message) throws NetconfDocumentedException {
-        NetconfOperationExecution netconfOperationExecution = getNetconfOperationWithHighestPriority(message);
-        logger.debug("Forwarding netconf message {} to {}", XmlUtil.toString(message),
+    public synchronized Document onNetconfMessage(Document message,
+            NetconfSession session) throws NetconfDocumentedException {
+        NetconfOperationExecution netconfOperationExecution;
+
+        String messageAsString = XmlUtil.toString(message);
+
+        try {
+            netconfOperationExecution = getNetconfOperationWithHighestPriority(message, session);
+        } catch (IllegalArgumentException | IllegalStateException e) {
+            logger.warn("Unable to handle rpc {} on session {}", messageAsString, session, e);
+
+            String errorMessage = String.format("Unable to handle rpc %s on session %s", messageAsString, session);
+            Map<String, String> errorInfo = Maps.newHashMap();
+
+            NetconfDocumentedException.ErrorTag tag = null;
+            if (e instanceof IllegalArgumentException) {
+                errorInfo.put(NetconfDocumentedException.ErrorTag.operation_not_supported.toString(), e.getMessage());
+                tag = NetconfDocumentedException.ErrorTag.operation_not_supported;
+            } else if (e instanceof IllegalStateException) {
+                errorInfo.put(NetconfDocumentedException.ErrorTag.operation_failed.toString(), e.getMessage());
+                tag = NetconfDocumentedException.ErrorTag.operation_failed;
+            }
+
+            throw new NetconfDocumentedException(errorMessage, e, NetconfDocumentedException.ErrorType.application,
+                    tag, NetconfDocumentedException.ErrorSeverity.error, errorInfo);
+        } catch (RuntimeException e) {
+            throw handleUnexpectedEx("Unexpected exception during netconf operation sort", e);
+        }
+
+        try {
+            return executeOperationWithHighestPriority(message, netconfOperationExecution, messageAsString);
+        } catch (RuntimeException e) {
+            throw handleUnexpectedEx("Unexpected exception during netconf operation execution", e);
+        }
+    }
+
+    private NetconfDocumentedException handleUnexpectedEx(String s, Exception e) throws NetconfDocumentedException {
+        logger.error(s, e);
+
+        Map<String, String> info = Maps.newHashMap();
+        info.put(NetconfDocumentedException.ErrorSeverity.error.toString(), e.toString());
+        return new NetconfDocumentedException("Unexpected error",
+                NetconfDocumentedException.ErrorType.application,
+                NetconfDocumentedException.ErrorTag.operation_failed,
+                NetconfDocumentedException.ErrorSeverity.error, info);
+    }
+
+    private Document executeOperationWithHighestPriority(Document message, NetconfOperationExecution netconfOperationExecution, String messageAsString) throws NetconfDocumentedException {
+        logger.debug("Forwarding netconf message {} to {}", messageAsString,
                 netconfOperationExecution.operationWithHighestPriority);
 
         final LinkedList<NetconfOperationFilterChain> chain = new LinkedList<>();
@@ -115,12 +182,13 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
         return chain.getFirst().execute(message, this);
     }
 
-    private NetconfOperationExecution getNetconfOperationWithHighestPriority(Document message) {
+    private NetconfOperationExecution getNetconfOperationWithHighestPriority(
+            Document message, NetconfSession session) {
 
-        // TODO test
-        TreeMap<HandlingPriority, Set<NetconfOperation>> sortedPriority = getSortedNetconfOperationsWithCanHandle(message);
+        TreeMap<HandlingPriority, Set<NetconfOperation>> sortedPriority = getSortedNetconfOperationsWithCanHandle(
+                message, session);
 
-        Preconditions.checkState(sortedPriority.isEmpty() == false, "No %s available to handle message %s",
+        Preconditions.checkArgument(sortedPriority.isEmpty() == false, "No %s available to handle message %s",
                 NetconfOperation.class.getName(), XmlUtil.toString(message));
 
         HandlingPriority highestFoundPriority = sortedPriority.lastKey();
@@ -133,12 +201,16 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
         return new NetconfOperationExecution(sortedPriority, highestFoundPriority);
     }
 
-    private TreeMap<HandlingPriority, Set<NetconfOperation>> getSortedNetconfOperationsWithCanHandle(Document message) {
+    private TreeMap<HandlingPriority, Set<NetconfOperation>> getSortedNetconfOperationsWithCanHandle(
+            Document message, NetconfSession session) {
         TreeMap<HandlingPriority, Set<NetconfOperation>> sortedPriority = Maps.newTreeMap();
 
         for (NetconfOperation netconfOperation : allNetconfOperations) {
             final HandlingPriority handlingPriority = netconfOperation.canHandle(message);
-
+            if (netconfOperation instanceof DefaultNetconfOperation) {
+                ((DefaultNetconfOperation) netconfOperation)
+                        .setNetconfSession(session);
+            }
             if (handlingPriority.equals(HandlingPriority.CANNOT_HANDLE) == false) {
                 Set<NetconfOperation> netconfOperations = sortedPriority.get(handlingPriority);
                 netconfOperations = checkIfNoOperationsOnPriority(sortedPriority, handlingPriority, netconfOperations);
@@ -187,4 +259,7 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
         return "NetconfOperationRouterImpl{" + "netconfOperationServiceSnapshot=" + netconfOperationServiceSnapshot
                 + '}';
     }
+
+
+
 }