X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fsal-netconf-connector%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fsal%2Fconnect%2Fnetconf%2FNetconfMapping.java;h=2b3a992fc1c3eebaa45a33220731b4c80d2a0181;hb=797699ffcb8cf2eabbc1fe3159c5e5c7b5ecbe98;hp=ce2661a7b3f9cfcacc2dd6bf9f930fd1bd0b0597;hpb=2b379f8680220cf2a387cbb120deb38f299d4596;p=controller.git diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfMapping.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfMapping.java index ce2661a7b3..2b3a992fc1 100644 --- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfMapping.java +++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfMapping.java @@ -18,7 +18,10 @@ import java.util.concurrent.atomic.AtomicInteger; import javax.activation.UnsupportedDataTypeException; import javax.annotation.Nullable; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.api.NetconfMessage; +import org.opendaylight.controller.netconf.util.messages.NetconfMessageUtil; +import org.opendaylight.controller.netconf.util.xml.XmlUtil; import org.opendaylight.controller.sal.common.util.Rpcs; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.RpcError; @@ -34,17 +37,14 @@ import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl; import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils; import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder; import org.opendaylight.yangtools.yang.model.api.NotificationDefinition; -import org.opendaylight.yangtools.yang.model.api.RpcDefinition; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.w3c.dom.Document; import org.w3c.dom.Element; import com.google.common.base.Optional; -import com.google.common.base.Preconditions; import com.google.common.base.Predicate; import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableList; -import com.google.common.collect.Iterables; import com.google.common.collect.Lists; public class NetconfMapping { @@ -52,6 +52,7 @@ public class NetconfMapping { public static URI NETCONF_URI = URI.create("urn:ietf:params:xml:ns:netconf:base:1.0"); public static String NETCONF_MONITORING_URI = "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring"; public static URI NETCONF_NOTIFICATION_URI = URI.create("urn:ietf:params:xml:ns:netconf:notification:1.0"); + public static URI NETCONF_ROLLBACK_ON_ERROR_URI = URI.create("urn:ietf:params:netconf:capability:rollback-on-error:1.0"); public static QName NETCONF_QNAME = QName.create(NETCONF_URI, null, "netconf"); public static QName NETCONF_RPC_QNAME = QName.create(NETCONF_QNAME, "rpc"); @@ -71,6 +72,9 @@ public class NetconfMapping { public static QName NETCONF_CANDIDATE_QNAME = QName.create(NETCONF_QNAME, "candidate"); public static QName NETCONF_RUNNING_QNAME = QName.create(NETCONF_QNAME, "running"); + public static QName NETCONF_ERROR_OPTION_QNAME = QName.create(NETCONF_QNAME, "error-option"); + public static String ROLLBACK_ON_ERROR_OPTION = "rollback-on-error"; + public static QName NETCONF_RPC_REPLY_QNAME = QName.create(NETCONF_QNAME, "rpc-reply"); public static QName NETCONF_OK_QNAME = QName.create(NETCONF_QNAME, "ok"); public static QName NETCONF_DATA_QNAME = QName.create(NETCONF_QNAME, "data"); @@ -88,7 +92,7 @@ public class NetconfMapping { static AtomicInteger messageId = new AtomicInteger(0); - static Node toFilterStructure(InstanceIdentifier identifier) { + static Node toFilterStructure(final InstanceIdentifier identifier) { Node previous = null; if (identifier.getPath().isEmpty()) { return null; @@ -96,12 +100,16 @@ public class NetconfMapping { for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument component : Lists .reverse(identifier.getPath())) { - previous = toNode(component, previous); + if (component instanceof NodeIdentifierWithPredicates) { + previous = toNode((NodeIdentifierWithPredicates)component, previous); + } else { + previous = toNode(component, previous); + } } return filter("subtree", previous); } - static Node toNode(NodeIdentifierWithPredicates argument, Node node) { + static Node toNode(final NodeIdentifierWithPredicates argument, final Node node) { List> list = new ArrayList<>(); for (Map.Entry arg : argument.getKeyValues().entrySet()) { list.add(new SimpleNodeTOImpl(arg.getKey(), null, arg.getValue())); @@ -112,7 +120,7 @@ public class NetconfMapping { return new CompositeNodeTOImpl(argument.getNodeType(), null, list); } - static Node toNode(PathArgument argument, Node node) { + static Node toNode(final PathArgument argument, final Node node) { if (node != null) { return new CompositeNodeTOImpl(argument.getNodeType(), null, Collections.> singletonList(node)); } else { @@ -120,31 +128,30 @@ public class NetconfMapping { } } - static CompositeNode toCompositeNode(NetconfMessage message, Optional ctx) { + static CompositeNode toCompositeNode(final NetconfMessage message, final Optional ctx) { // TODO: implement general normalization to normalize incoming Netconf // Message // for Schema Context counterpart return null; } - static CompositeNode toNotificationNode(NetconfMessage message, Optional ctx) { + static CompositeNode toNotificationNode(final NetconfMessage message, final Optional ctx) { if (ctx.isPresent()) { SchemaContext schemaContext = ctx.get(); Set notifications = schemaContext.getNotifications(); Document document = message.getDocument(); - return XmlDocumentUtils.notificationToDomNodes(document, Optional.fromNullable(notifications)); + return XmlDocumentUtils.notificationToDomNodes(document, Optional.fromNullable(notifications), ctx.get()); } return null; } - static NetconfMessage toRpcMessage(QName rpc, CompositeNode node, Optional ctx) { + static NetconfMessage toRpcMessage(final QName rpc, final CompositeNode node, final Optional ctx) { CompositeNodeTOImpl rpcPayload = wrap(NETCONF_RPC_QNAME, flattenInput(node)); Document w3cPayload = null; try { w3cPayload = XmlDocumentUtils.toDocument(rpcPayload, XmlDocumentUtils.defaultValueCodecProvider()); } catch (UnsupportedDataTypeException e) { - // FIXME Ex handling - e.printStackTrace(); + throw new IllegalArgumentException("Unable to create message", e); } w3cPayload.getDocumentElement().setAttribute("message-id", "m-" + messageId.getAndIncrement()); return new NetconfMessage(w3cPayload); @@ -158,8 +165,8 @@ public class NetconfMapping { if (input instanceof CompositeNode) { List> nodes = ImmutableList.> builder() // - .addAll(input.getChildren()) // - .addAll(Collections2.filter(node.getChildren(), new Predicate>() { + .addAll(input.getValue()) // + .addAll(Collections2.filter(node.getValue(), new Predicate>() { @Override public boolean apply(@Nullable final Node input) { return input.getNodeType() != inputQName; @@ -173,7 +180,7 @@ public class NetconfMapping { return input; } - static RpcResult toRpcResult(NetconfMessage message, final QName rpc, Optional context) { + static RpcResult toRpcResult(final NetconfMessage message, final QName rpc, final Optional context) { CompositeNode rawRpc; if (context.isPresent()) if (isDataRetrieQNameReply(rpc)) { @@ -190,13 +197,7 @@ public class NetconfMapping { rawRpc = it.toInstance(); // sys(xmlData) } else { - RpcDefinition rpcSchema = Iterables.find(context.get().getOperations(), new Predicate() { - @Override - public boolean apply(final RpcDefinition input) { - return rpc == input.getQName(); - } - }); - rawRpc = (CompositeNode) toCompositeNode(message.getDocument()); + rawRpc = toCompositeNode(message, context); } else { rawRpc = (CompositeNode) toCompositeNode(message.getDocument()); @@ -205,17 +206,17 @@ public class NetconfMapping { return Rpcs.getRpcResult(true, rawRpc, Collections. emptySet()); } - static Element getDataSubtree(Document doc) { + static Element getDataSubtree(final Document doc) { return (Element) doc.getElementsByTagNameNS(NETCONF_URI.toString(), "data").item(0); } - static boolean isDataRetrieQNameReply(QName it) { + static boolean isDataRetrieQNameReply(final QName it) { return NETCONF_URI == it.getNamespace() && (it.getLocalName() == NETCONF_GET_CONFIG_QNAME.getLocalName() || it.getLocalName() == NETCONF_GET_QNAME - .getLocalName()); + .getLocalName()); } - static CompositeNodeTOImpl wrap(QName name, Node node) { + static CompositeNodeTOImpl wrap(final QName name, final Node node) { if (node != null) { return new CompositeNodeTOImpl(name, null, Collections.> singletonList(node)); } else { @@ -223,7 +224,7 @@ public class NetconfMapping { } } - static CompositeNodeTOImpl wrap(QName name, Node additional, Node node) { + static CompositeNodeTOImpl wrap(final QName name, final Node additional, final Node node) { if (node != null) { return new CompositeNodeTOImpl(name, null, ImmutableList.of(additional, node)); } else { @@ -231,7 +232,7 @@ public class NetconfMapping { } } - static ImmutableCompositeNode filter(String type, Node node) { + static ImmutableCompositeNode filter(final String type, final Node node) { CompositeNodeBuilder it = ImmutableCompositeNode.builder(); // it.setQName(NETCONF_FILTER_QNAME); it.setAttribute(NETCONF_TYPE_QNAME, type); @@ -242,14 +243,24 @@ public class NetconfMapping { } } - public static Node toCompositeNode(Document document) { + public static Node toCompositeNode(final Document document) { return XmlDocumentUtils.toDomNode(document); } - public static void checkValidReply(NetconfMessage input, NetconfMessage output) { + public static void checkValidReply(final NetconfMessage input, final NetconfMessage output) { String inputMsgId = input.getDocument().getDocumentElement().getAttribute("message-id"); String outputMsgId = output.getDocument().getDocumentElement().getAttribute("message-id"); - Preconditions.checkState(inputMsgId == outputMsgId, "Rpc request and reply message IDs must be same."); + + if(inputMsgId.equals(outputMsgId) == false) { + String requestXml = XmlUtil.toString(input.getDocument()); + String responseXml = XmlUtil.toString(output.getDocument()); + throw new IllegalStateException(String.format("Rpc request and reply message IDs must be same. Request: %s, response: %s", requestXml, responseXml)); + } } + public static void checkSuccessReply(final NetconfMessage output) throws NetconfDocumentedException { + if(NetconfMessageUtil.isErrorMessage(output)) { + throw new IllegalStateException(String.format("Response contains error: %s", XmlUtil.toString(output.getDocument()))); + } + } }