From 0b86189513b25601ba12a4a38230017315914344 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Thu, 28 Feb 2019 16:52:40 +0100 Subject: [PATCH] Add NETCONF/RFC7952 compatibility RFC6241 pre-dates RFC7952 and defines an attribute which should be modeled as a metadata annotation. For legacy reasons, we are carrying support for this attribute in yang-data-api, which does not quite fit the semantic model and requires special-casing. Since ietf-netconf.yang does not define the metadata annotation, which would make RFC7952 work seamlessly, we need to hack this around a bit and make the correspoding schema definition available. JIRA: YANGTOOLS-961 Change-Id: Ib6c98e9bb8a7c9ae8351b61522c3fbfdd943393c Signed-off-by: Robert Varga --- artifacts/pom.xml | 5 + docs/pom.xml | 4 + features/odl-yangtools-parser/pom.xml | 4 + yang/pom.xml | 1 + yang/rfc7952-model-netconf/pom.xml | 71 ++++++++ .../rfc7952/model/netconf/Operation.java | 171 ++++++++++++++++++ .../src/main/resources/ietf-netconf.yang | 97 ++++++++++ .../rfc7952/model/netconf/OperationTest.java | 20 ++ .../ietf-yang-metadata@2016-08-05.yang | 0 9 files changed, 373 insertions(+) create mode 100644 yang/rfc7952-model-netconf/pom.xml create mode 100644 yang/rfc7952-model-netconf/src/main/java/org/opendaylight/yangtools/rfc7952/model/netconf/Operation.java create mode 100644 yang/rfc7952-model-netconf/src/main/resources/ietf-netconf.yang create mode 100644 yang/rfc7952-model-netconf/src/test/java/org/opendaylight/yangtools/rfc7952/model/netconf/OperationTest.java rename yang/rfc7952-parser-support/src/{test => main}/resources/ietf-yang-metadata@2016-08-05.yang (100%) diff --git a/artifacts/pom.xml b/artifacts/pom.xml index 8f166773b4..562731f1b9 100644 --- a/artifacts/pom.xml +++ b/artifacts/pom.xml @@ -169,6 +169,11 @@ rfc7952-model-api 3.0.0-SNAPSHOT + + org.opendaylight.yangtools + rfc7952-model-netconf + 3.0.0-SNAPSHOT + org.opendaylight.yangtools rfc7952-parser-support diff --git a/docs/pom.xml b/docs/pom.xml index 8d4f412b22..ebe1fefd62 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -131,6 +131,10 @@ org.opendaylight.yangtools rfc7952-model-api + + org.opendaylight.yangtools + rfc7952-model-netconf + org.opendaylight.yangtools rfc7952-parser-support diff --git a/features/odl-yangtools-parser/pom.xml b/features/odl-yangtools-parser/pom.xml index fd4759cefd..bbfdd3198b 100644 --- a/features/odl-yangtools-parser/pom.xml +++ b/features/odl-yangtools-parser/pom.xml @@ -60,6 +60,10 @@ org.opendaylight.yangtools rfc6536-parser-support + + org.opendaylight.yangtools + rfc7952-model-netconf + org.opendaylight.yangtools rfc7952-parser-support diff --git a/yang/pom.xml b/yang/pom.xml index 73c9914334..fe6c014592 100644 --- a/yang/pom.xml +++ b/yang/pom.xml @@ -75,6 +75,7 @@ rfc7952-model-api + rfc7952-model-netconf rfc7952-parser-support diff --git a/yang/rfc7952-model-netconf/pom.xml b/yang/rfc7952-model-netconf/pom.xml new file mode 100644 index 0000000000..eee1885ae5 --- /dev/null +++ b/yang/rfc7952-model-netconf/pom.xml @@ -0,0 +1,71 @@ + + + + + 4.0.0 + + org.opendaylight.yangtools + bundle-parent + 3.0.0-SNAPSHOT + ../../bundle-parent + + + rfc7952-model-netconf + bundle + ${project.artifactId} + RFC7952 compatibility with RFC6241 + + + + org.opendaylight.yangtools + concepts + + + org.opendaylight.yangtools + yang-common + + + org.opendaylight.yangtools + rfc7952-model-api + + + org.opendaylight.yangtools + rfc7952-parser-support + + + org.opendaylight.yangtools + yang-parser-api + + + org.opendaylight.yangtools + yang-parser-impl + test + + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + + checkstyle.violationSeverity=error + + + + com.github.spotbugs + spotbugs-maven-plugin + + true + + + + + + diff --git a/yang/rfc7952-model-netconf/src/main/java/org/opendaylight/yangtools/rfc7952/model/netconf/Operation.java b/yang/rfc7952-model-netconf/src/main/java/org/opendaylight/yangtools/rfc7952/model/netconf/Operation.java new file mode 100644 index 0000000000..51a59efb06 --- /dev/null +++ b/yang/rfc7952-model-netconf/src/main/java/org/opendaylight/yangtools/rfc7952/model/netconf/Operation.java @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2019 Pantheon Technologies, s.r.o. 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.yangtools.rfc7952.model.netconf; + +import static com.google.common.base.Preconditions.checkState; +import static java.util.Objects.requireNonNull; + +import com.google.common.annotations.Beta; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMap.Builder; +import java.io.IOException; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.ServiceLoader; +import org.opendaylight.yangtools.rfc7952.model.api.AnnotationEffectiveStatement; +import org.opendaylight.yangtools.rfc7952.model.api.AnnotationSchemaNode; +import org.opendaylight.yangtools.rfc7952.parser.AnnotationStatementSupport; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode; +import org.opendaylight.yangtools.yang.model.parser.api.YangParser; +import org.opendaylight.yangtools.yang.model.parser.api.YangParserException; +import org.opendaylight.yangtools.yang.model.parser.api.YangParserFactory; +import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource; + +/** + * Enumeration covering possible values of "operation" attribute as defined in RFC6241 section 7.2. This class mimics + * to a large extent what would be generated for MD-SAL Binding representation of the type. + */ +@Beta +public enum Operation { + /** + * The configuration data identified by the element containing this attribute is + * merged with the configuration at the corresponding level in the configuration + * datastore identified by the <target>parameter. This is the default + * behavior. + */ + Merge(0, "merge"), + + /** + * The configuration data identified by the element containing this attribute + * replaces any related configuration in the configuration datastore identified by + * the <target> parameter. If no such configuration data exists in the + * configuration datastore, it is created. Unlike a <copy-config> + * operation, which replaces the entire target configuration, only the configuration + * actually present in the <config> parameter is affected. + */ + Replace(1, "replace"), + + /** + * The configuration data identified by the element containing this attribute is + * added to the configuration if and only if the configuration data does not + * already exist in the configuration datastore. If the configuration data exists, an + * <rpc-error> element is returned with an <error-tag> + * value of "data-exists". + */ + Create(2, "create"), + + /** + * The configuration data identified by the element containing this attribute is + * deleted from the configuration if and only if the configuration data currently + * exists in the configuration datastore. If the configuration data does not exist, + * an <rpc-error>element is returned with an + * <error-tag> value of "data-missing". + */ + Delete(3, "delete"), + + /** + * The configuration data identified by the element containing this attribute is + * deleted from the configuration if the configuration data currently exists in the + * configuration datastore. If the configuration data does not exist, the "remove" + * operation is silently ignored by the server. + * + */ + Remove(4, "remove"); + + private static final Map NAME_MAP; + private static final Map VALUE_MAP; + + static { + final Builder nb = ImmutableMap.builder(); + final Builder vb = ImmutableMap.builder(); + for (Operation enumItem : Operation.values()) { + vb.put(enumItem.value, enumItem); + nb.put(enumItem.name, enumItem); + } + + NAME_MAP = nb.build(); + VALUE_MAP = vb.build(); + } + + /** + * SchemaNode representing the definition of "nc:operation" metadata. + */ + private static final AnnotationEffectiveStatement OPERATION_ANNOTATION; + + static { + final Iterator it = ServiceLoader.load(YangParserFactory.class).iterator(); + checkState(it.hasNext(), "Cannot load YangParserFactory"); + final YangParser parser = it.next().createParser(); + + final SchemaContext context; + try { + context = parser.addSource(YangTextSchemaSource.forResource(Operation.class, "/ietf-netconf.yang")) + .addLibSource(YangTextSchemaSource.forResource(AnnotationStatementSupport.class, + "/ietf-yang-metadata@2016-08-05.yang")) + .buildSchemaContext(); + } catch (YangParserException | IOException e) { + throw new ExceptionInInitializerError(e); + } + + final List nodes = context.getUnknownSchemaNodes(); + checkState(nodes.size() == 1, "Unexpected unknown nodes %s", nodes); + final UnknownSchemaNode first = nodes.get(0); + checkState(first instanceof AnnotationEffectiveStatement, "Unexpected node %s", first); + final AnnotationEffectiveStatement node = (AnnotationEffectiveStatement)first; + checkState("operation".equals(node.getNodeParameter()), "Unexpected node parameter in %s", node); + OPERATION_ANNOTATION = node; + } + + private final String name; + private final int value; + + Operation(final int value, final String name) { + this.value = value; + this.name = name; + } + + public String getName() { + return name; + } + + public int getIntValue() { + return value; + } + + /** + * Return the enumeration member whose {@link #getName()} matches specified value. + * + * @param name YANG assigned name + * @return corresponding Operation item, if present + * @throws NullPointerException if name is null + */ + public static Optional forName(final String name) { + return Optional.ofNullable(NAME_MAP.get(requireNonNull(name))); + } + + /** + * Return the enumeration member whose {@link #getIntValue()} matches specified value. + * + * @param intValue integer value + * @return corresponding Operation item, or null if no such item exists + */ + public static Operation forValue(final int intValue) { + return VALUE_MAP.get(intValue); + } + + public static AnnotationSchemaNode getSchemaNode() { + return OPERATION_ANNOTATION; + } + + public static AnnotationEffectiveStatement getEffectiveStatement() { + return OPERATION_ANNOTATION; + } +} diff --git a/yang/rfc7952-model-netconf/src/main/resources/ietf-netconf.yang b/yang/rfc7952-model-netconf/src/main/resources/ietf-netconf.yang new file mode 100644 index 0000000000..3742c3e74b --- /dev/null +++ b/yang/rfc7952-model-netconf/src/main/resources/ietf-netconf.yang @@ -0,0 +1,97 @@ +module ietf-netconf { + namespace "urn:ietf:params:xml:ns:netconf:base:1.0"; + + prefix nc; + + import ietf-yang-metadata { + prefix md; + } + + description + "Fake module to define edit-config attribute 'operation' in terms + of RFC7952. This module should not leak to the outside world and + is used only internally by OpenDaylight."; + + revision 2011-06-01 { + description + "Initial revision;"; + reference + "RFC 6241: Network Configuration Protocol"; + } + + md:annotation "operation" { + description "Elements in the subtree MAY contain an + \"operation\" attribute, which belongs to the NETCONF + namespace defined in Section 3.1. The attribute + identifies the point in the configuration to perform + the operation and MAY appear on multiple elements + throughout the subtree. + + If the \"operation\" attribute is not specified, the + configuration is merged into the configuration + datastore."; + reference + "RFC 6241: Network Configuration Protocol"; + + type enumeration { + enum merge { + description "The configuration data identified by the element + containing this attribute is merged with the + configuration at the corresponding level in the + configuration datastore identified by the + parameter. This is the default behavior."; + reference + "RFC 6241: Network Configuration Protocol"; + } + + enum replace { + description "The configuration data identified by the element + containing this attribute replaces any related + configuration in the configuration datastore identified + by the parameter. If no such configuration + data exists in the configuration datastore, it is + created. Unlike a operation, which + replaces the entire target configuration, only the + configuration actually present in the parameter + is affected."; + reference + "RFC 6241: Network Configuration Protocol"; + } + + enum create { + description "The configuration data identified by the element + containing this attribute is added to the configuration + if and only if the configuration data does not already + exist in the configuration datastore. If the + configuration data exists, an element is + returned with an value of \"data-exists\"."; + reference + "RFC 6241: Network Configuration Protocol"; + } + + enum delete { + description "The configuration data identified by the element + containing this attribute is deleted from the + configuration if and only if the configuration data + currently exists in the configuration datastore. If the + configuration data does not exist, an + element is returned with an value of + \"data-missing\"."; + reference + "RFC 6241: Network Configuration Protocol"; + } + + enum remove { + description "The configuration data identified by the element + containing this attribute is deleted from the + configuration if the configuration data currently exists + in the configuration datastore. If the configuration + data does not exist, the \"remove\" operation is silently + ignored by the server."; + reference + "RFC 6241: Network Configuration Protocol"; + } + } + } +} + diff --git a/yang/rfc7952-model-netconf/src/test/java/org/opendaylight/yangtools/rfc7952/model/netconf/OperationTest.java b/yang/rfc7952-model-netconf/src/test/java/org/opendaylight/yangtools/rfc7952/model/netconf/OperationTest.java new file mode 100644 index 0000000000..dde3ded8b5 --- /dev/null +++ b/yang/rfc7952-model-netconf/src/test/java/org/opendaylight/yangtools/rfc7952/model/netconf/OperationTest.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2019 Pantheon Technologies, s.r.o. 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.yangtools.rfc7952.model.netconf; + +import static org.junit.Assert.assertNotNull; + +import org.junit.Test; + +public class OperationTest { + @Test + public void testAnnotation() { + assertNotNull(Operation.getSchemaNode()); + assertNotNull(Operation.getEffectiveStatement()); + } +} diff --git a/yang/rfc7952-parser-support/src/test/resources/ietf-yang-metadata@2016-08-05.yang b/yang/rfc7952-parser-support/src/main/resources/ietf-yang-metadata@2016-08-05.yang similarity index 100% rename from yang/rfc7952-parser-support/src/test/resources/ietf-yang-metadata@2016-08-05.yang rename to yang/rfc7952-parser-support/src/main/resources/ietf-yang-metadata@2016-08-05.yang -- 2.36.6