Add NETCONF/RFC7952 compatibility 48/80648/5
authorRobert Varga <robert.varga@pantheon.tech>
Thu, 28 Feb 2019 15:52:40 +0000 (16:52 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Fri, 1 Mar 2019 08:48:47 +0000 (09:48 +0100)
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 <robert.varga@pantheon.tech>
artifacts/pom.xml
docs/pom.xml
features/odl-yangtools-parser/pom.xml
yang/pom.xml
yang/rfc7952-model-netconf/pom.xml [new file with mode: 0644]
yang/rfc7952-model-netconf/src/main/java/org/opendaylight/yangtools/rfc7952/model/netconf/Operation.java [new file with mode: 0644]
yang/rfc7952-model-netconf/src/main/resources/ietf-netconf.yang [new file with mode: 0644]
yang/rfc7952-model-netconf/src/test/java/org/opendaylight/yangtools/rfc7952/model/netconf/OperationTest.java [new file with mode: 0644]
yang/rfc7952-parser-support/src/main/resources/ietf-yang-metadata@2016-08-05.yang [moved from yang/rfc7952-parser-support/src/test/resources/ietf-yang-metadata@2016-08-05.yang with 100% similarity]

index 8f166773b4303ed9c9b9ff943719526b40dd0c4b..562731f1b93bc260fcd46b3dcad1c75adbdb7252 100644 (file)
                 <artifactId>rfc7952-model-api</artifactId>
                 <version>3.0.0-SNAPSHOT</version>
             </dependency>
+            <dependency>
+                <groupId>org.opendaylight.yangtools</groupId>
+                <artifactId>rfc7952-model-netconf</artifactId>
+                <version>3.0.0-SNAPSHOT</version>
+            </dependency>
             <dependency>
                 <groupId>org.opendaylight.yangtools</groupId>
                 <artifactId>rfc7952-parser-support</artifactId>
index 8d4f412b22e1c9b1ce91588c8b326b88cc6fe5de..ebe1fefd62024a453742894571dac29f0f909f3a 100644 (file)
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>rfc7952-model-api</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>rfc7952-model-netconf</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>rfc7952-parser-support</artifactId>
index fd4759cefd764620f45a060c0357e2c4c6db7810..bbfdd3198b8fe5cda1e7d36ef619d46d60e6052e 100644 (file)
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>rfc6536-parser-support</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>rfc7952-model-netconf</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>rfc7952-parser-support</artifactId>
index 73c9914334a1884cf3cfc2452fe7aa64eca7afdb..fe6c0145926e66baa0eb0c81ff303e04d3374926 100644 (file)
@@ -75,6 +75,7 @@
 
         <!-- Metadata (annotation) metamodel support -->
         <module>rfc7952-model-api</module>
+        <module>rfc7952-model-netconf</module>
         <module>rfc7952-parser-support</module>
 
         <!-- RFC8040 (yang-data) metamodel support -->
diff --git a/yang/rfc7952-model-netconf/pom.xml b/yang/rfc7952-model-netconf/pom.xml
new file mode 100644 (file)
index 0000000..eee1885
--- /dev/null
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ Copyright (c) 2013 Cisco Systems, Inc. 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
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.opendaylight.yangtools</groupId>
+        <artifactId>bundle-parent</artifactId>
+        <version>3.0.0-SNAPSHOT</version>
+        <relativePath>../../bundle-parent</relativePath>
+    </parent>
+
+    <artifactId>rfc7952-model-netconf</artifactId>
+    <packaging>bundle</packaging>
+    <name>${project.artifactId}</name>
+    <description>RFC7952 compatibility with RFC6241</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>concepts</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-common</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>rfc7952-model-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>rfc7952-parser-support</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-parser-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-parser-impl</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-checkstyle-plugin</artifactId>
+                <configuration>
+                    <propertyExpansion>checkstyle.violationSeverity=error</propertyExpansion>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>com.github.spotbugs</groupId>
+                <artifactId>spotbugs-maven-plugin</artifactId>
+                <configuration>
+                    <failOnError>true</failOnError>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
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 (file)
index 0000000..51a59ef
--- /dev/null
@@ -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 &lt;target&gt;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 &lt;target&gt; parameter. If no such configuration data exists in the
+     * configuration datastore, it is created. Unlike a &lt;copy-config&gt;
+     * operation, which replaces the entire target configuration, only the configuration
+     * actually present in the &lt;config&gt; 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
+     * &lt;rpc-error&gt; element is returned with an &lt;error-tag&gt;
+     * 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 &lt;rpc-error&gt;element is returned with an
+     * &lt;error-tag&gt; 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<String, Operation> NAME_MAP;
+    private static final Map<Integer, Operation> VALUE_MAP;
+
+    static {
+        final Builder<String, Operation> nb = ImmutableMap.builder();
+        final Builder<Integer, Operation> 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<YangParserFactory> 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<UnknownSchemaNode> 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<Operation> 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 (file)
index 0000000..3742c3e
--- /dev/null
@@ -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 <config> 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 <config> 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 <target>
+                     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 <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.";
+        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 <rpc-error> element is
+                     returned with an <error-tag> 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 <rpc-error>
+                     element is returned with an <error-tag> 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 (file)
index 0000000..dde3ded
--- /dev/null
@@ -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());
+    }
+}