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%2Fschema%2FNetconfRemoteSchemaYangSourceProvider.java;h=ad82c716ce86ac44b4bab8d486cd09e8a14acc95;hb=1447e0132075bbd3013aa41b98384a373bd82d1a;hp=5a528bc418ea386a04b428e047c58fe7d47c74bb;hpb=36f7cda0765248e257702addbff6f50da7ab0dd6;p=controller.git diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/schema/NetconfRemoteSchemaYangSourceProvider.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/schema/NetconfRemoteSchemaYangSourceProvider.java index 5a528bc418..ad82c716ce 100644 --- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/schema/NetconfRemoteSchemaYangSourceProvider.java +++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/schema/NetconfRemoteSchemaYangSourceProvider.java @@ -7,38 +7,47 @@ */ package org.opendaylight.controller.sal.connect.netconf.schema; +import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.GET_SCHEMA_QNAME; +import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_DATA_QNAME; +import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.toId; +import com.google.common.base.Charsets; import com.google.common.base.Function; -import com.google.common.base.Objects; +import com.google.common.base.MoreObjects; import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.util.concurrent.CheckedFuture; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; +import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; -import org.apache.commons.io.IOUtils; +import javax.xml.transform.dom.DOMSource; +import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult; +import org.opendaylight.controller.md.sal.dom.api.DOMRpcService; import org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil; import org.opendaylight.controller.sal.connect.util.RemoteDeviceId; -import org.opendaylight.controller.sal.core.api.RpcImplementation; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.Yang; import org.opendaylight.yangtools.util.concurrent.ExceptionMapper; import org.opendaylight.yangtools.yang.common.QName; -import org.opendaylight.yangtools.yang.common.RpcResult; -import org.opendaylight.yangtools.yang.data.api.CompositeNode; -import org.opendaylight.yangtools.yang.data.api.SimpleNode; -import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode; -import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode; +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.LeafNode; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.opendaylight.yangtools.yang.data.impl.schema.Builders; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder; +import org.opendaylight.yangtools.yang.model.api.SchemaPath; import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceException; import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier; import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource; import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; public final class NetconfRemoteSchemaYangSourceProvider implements SchemaSourceProvider { - public static final QName GET_SCHEMA_QNAME = QName.create(NetconfMessageTransformUtil.IETF_NETCONF_MONITORING,"get-schema"); - public static final QName GET_DATA_QNAME = QName.create(NetconfMessageTransformUtil.IETF_NETCONF_MONITORING, "data"); - private static final Logger logger = LoggerFactory.getLogger(NetconfRemoteSchemaYangSourceProvider.class); private static final ExceptionMapper MAPPER = new ExceptionMapper( @@ -49,36 +58,57 @@ public final class NetconfRemoteSchemaYangSourceProvider implements SchemaSource } }; - private final RpcImplementation rpc; + private final DOMRpcService rpc; private final RemoteDeviceId id; - public NetconfRemoteSchemaYangSourceProvider(final RemoteDeviceId id, final RpcImplementation rpc) { + public NetconfRemoteSchemaYangSourceProvider(final RemoteDeviceId id, final DOMRpcService rpc) { this.id = id; this.rpc = Preconditions.checkNotNull(rpc); } - private ImmutableCompositeNode createGetSchemaRequest(final String moduleName, final Optional revision) { - final CompositeNodeBuilder request = ImmutableCompositeNode.builder(); - request.setQName(GET_SCHEMA_QNAME).addLeaf("identifier", moduleName); - if (revision.isPresent()) { - request.addLeaf("version", revision.get()); + public static ContainerNode createGetSchemaRequest(final String moduleName, final Optional revision) { + final QName identifierQName = QName.cachedReference(QName.create(NetconfMessageTransformUtil.GET_SCHEMA_QNAME, "identifier")); + final YangInstanceIdentifier.NodeIdentifier identifierId = new YangInstanceIdentifier.NodeIdentifier(identifierQName); + final LeafNode identifier = Builders.leafBuilder().withNodeIdentifier(identifierId).withValue(moduleName).build(); + + final QName formatQName = QName.cachedReference(QName.create(NetconfMessageTransformUtil.GET_SCHEMA_QNAME, "format")); + final YangInstanceIdentifier.NodeIdentifier formatId = new YangInstanceIdentifier.NodeIdentifier(formatQName); + final LeafNode format = Builders.leafBuilder().withNodeIdentifier(formatId).withValue(Yang.QNAME).build(); + + final DataContainerNodeAttrBuilder builder = Builders.containerBuilder(); + + builder.withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(NetconfMessageTransformUtil.GET_SCHEMA_QNAME)) + .withChild(identifier) + .withChild(format); + + if(revision.isPresent()) { + final QName revisionQName = QName.cachedReference(QName.create(NetconfMessageTransformUtil.GET_SCHEMA_QNAME, "version")); + final YangInstanceIdentifier.NodeIdentifier revisionId = new YangInstanceIdentifier.NodeIdentifier(revisionQName); + final LeafNode revisionNode = Builders.leafBuilder().withNodeIdentifier(revisionId).withValue(revision.get()).build(); + + builder.withChild(revisionNode); } - request.addLeaf("format", "yang"); - return request.toInstance(); + + return builder.build(); } - private static Optional getSchemaFromRpc(final RemoteDeviceId id, final CompositeNode result) { + private static Optional getSchemaFromRpc(final RemoteDeviceId id, final NormalizedNode result) { if (result == null) { return Optional.absent(); } - final SimpleNode simpleNode = result.getFirstSimpleByName(GET_DATA_QNAME.withoutRevision()); - Preconditions.checkNotNull(simpleNode, + final QName schemaWrapperNode = QName.cachedReference(QName.create(GET_SCHEMA_QNAME, NETCONF_DATA_QNAME.getLocalName())); + final Optional> child = ((ContainerNode) result).getChild(toId(schemaWrapperNode)); + + Preconditions.checkState(child.isPresent() && child.get() instanceof AnyXmlNode, "%s Unexpected response to get-schema, expected response with one child %s, but was %s", id, - GET_DATA_QNAME.withoutRevision(), result); + schemaWrapperNode, result); + + final DOMSource wrappedNode = ((AnyXmlNode) child.get()).getValue(); + Preconditions.checkNotNull(wrappedNode.getNode()); + final Element dataNode = (Element) wrappedNode.getNode(); - final Object potential = simpleNode.getValue(); - return potential instanceof String ? Optional.of((String) potential) : Optional. absent(); + return Optional.of(dataNode.getTextContent().trim()); } @Override @@ -88,18 +118,19 @@ public final class NetconfRemoteSchemaYangSourceProvider implements SchemaSource // If formatted revision is SourceIdentifier.NOT_PRESENT_FORMATTED_REVISION, we have to omit it from request final String formattedRevision = sourceIdentifier.getRevision().equals(SourceIdentifier.NOT_PRESENT_FORMATTED_REVISION) ? null : sourceIdentifier.getRevision(); final Optional revision = Optional.fromNullable(formattedRevision); - final ImmutableCompositeNode getSchemaRequest = createGetSchemaRequest(moduleName, revision); + final NormalizedNode getSchemaRequest = createGetSchemaRequest(moduleName, revision); logger.trace("{}: Loading YANG schema source for {}:{}", id, moduleName, revision); final ListenableFuture transformed = Futures.transform( - rpc.invokeRpc(GET_SCHEMA_QNAME, getSchemaRequest), + rpc.invokeRpc(SchemaPath.create(true, NetconfMessageTransformUtil.GET_SCHEMA_QNAME), getSchemaRequest), new ResultToYangSourceTransformer(id, sourceIdentifier, moduleName, revision)); final CheckedFuture checked = Futures.makeChecked(transformed, MAPPER); // / FIXME remove this get, it is only present to wait until source is retrieved // (goal is to limit concurrent schema download, since NetconfDevice listener does not handle concurrent messages properly) + // TODO retest this try { logger.trace("{}: Blocking for {}", id, sourceIdentifier); checked.checkedGet(); @@ -114,7 +145,7 @@ public final class NetconfRemoteSchemaYangSourceProvider implements SchemaSource * Transform composite node to string schema representation and then to ASTSchemaSource */ private static final class ResultToYangSourceTransformer implements - Function, YangTextSchemaSource> { + Function { private final RemoteDeviceId id; private final SourceIdentifier sourceIdentifier; @@ -130,9 +161,9 @@ public final class NetconfRemoteSchemaYangSourceProvider implements SchemaSource } @Override - public YangTextSchemaSource apply(final RpcResult input) { + public YangTextSchemaSource apply(final DOMRpcResult input) { - if (input.isSuccessful()) { + if (input.getErrors().isEmpty()) { final Optional schemaString = getSchemaFromRpc(id, input.getResult()); @@ -140,7 +171,6 @@ public final class NetconfRemoteSchemaYangSourceProvider implements SchemaSource "%s: Unexpected response to get-schema, schema not present in message for: %s", id, sourceIdentifier); logger.debug("{}: YANG Schema successfully retrieved for {}:{}", id, moduleName, revision); - return new NetconfYangTextSchemaSource(id, sourceIdentifier, schemaString); } @@ -150,7 +180,6 @@ public final class NetconfRemoteSchemaYangSourceProvider implements SchemaSource throw new IllegalStateException(String.format( "%s: YANG schema was not successfully retrieved for %s. Errors: %s", id, sourceIdentifier, input.getErrors())); - } } @@ -166,13 +195,13 @@ public final class NetconfRemoteSchemaYangSourceProvider implements SchemaSource } @Override - protected Objects.ToStringHelper addToStringAttributes(final Objects.ToStringHelper toStringHelper) { + protected MoreObjects.ToStringHelper addToStringAttributes(final MoreObjects.ToStringHelper toStringHelper) { return toStringHelper.add("device", id); } @Override public InputStream openStream() throws IOException { - return IOUtils.toInputStream(schemaString.get()); + return new ByteArrayInputStream(schemaString.get().getBytes(Charsets.UTF_8)); } } }