Add restconf-{client,server} 02/110002/3
authorRobert Varga <robert.varga@pantheon.tech>
Thu, 25 Jan 2024 21:31:03 +0000 (22:31 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Thu, 25 Jan 2024 22:53:21 +0000 (23:53 +0100)
This patch adds the bare-bones ietf-restconf-{client,server} models from
draft-ietf-netconf-restconf-client-server-29 without packaging or
implementing them.

JIRA: NETCONF-773
Change-Id: Ie1070076544e4b3b30f75f641cdc66bfb0efff43
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
artifacts/pom.xml
protocol/pom.xml
protocol/restconf-client/pom.xml [new file with mode: 0644]
protocol/restconf-client/src/main/java/org/opendaylight/restconf/client/impl/IetfRestconfClientFeatureProvider.java [new file with mode: 0644]
protocol/restconf-client/src/main/yang/ietf-restconf-client.yang [new file with mode: 0644]
protocol/restconf-server/pom.xml [new file with mode: 0644]
protocol/restconf-server/src/main/java/org/opendaylight/restconf/server/impl/IetfRestconfServerFeatureProvider.java [new file with mode: 0644]
protocol/restconf-server/src/main/yang/ietf-restconf-server.yang [new file with mode: 0644]

index 052f00f274925d2cc6e574c618d1ff614d0831d2..1d0f84cca93bbfc5ca7c50234812464147c2512f 100644 (file)
                 <artifactId>restconf-common</artifactId>
                 <version>${project.version}</version>
             </dependency>
+            <dependency>
+                <groupId>org.opendaylight.netconf</groupId>
+                <artifactId>restconf-client</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.opendaylight.netconf</groupId>
+                <artifactId>restconf-server</artifactId>
+                <version>${project.version}</version>
+            </dependency>
             <dependency>
                 <groupId>${project.groupId}</groupId>
                 <artifactId>restconf-nb</artifactId>
index 48eb815a3e677c728d68f07106d924129f79e377..17726d5ae72f1c9c505b326ea79aac07cafb5c80 100644 (file)
@@ -34,5 +34,7 @@
         <module>netconf-server</module>
         <module>netconf-test-util</module>
         <module>restconf-api</module>
+        <module>restconf-client</module>
+        <module>restconf-server</module>
     </modules>
 </project>
diff --git a/protocol/restconf-client/pom.xml b/protocol/restconf-client/pom.xml
new file mode 100644 (file)
index 0000000..cba881c
--- /dev/null
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2024 PANTHEON.tech, 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
+-->
+<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.netconf</groupId>
+        <artifactId>netconf-parent</artifactId>
+        <version>7.0.0-SNAPSHOT</version>
+        <relativePath>../../parent</relativePath>
+    </parent>
+
+    <artifactId>restconf-client</artifactId>
+    <name>${project.artifactId}</name>
+    <packaging>bundle</packaging>
+    <description>RESTCONF protocol client</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.kohsuke.metainf-services</groupId>
+            <artifactId>metainf-services</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.mdsal.binding.model.ietf</groupId>
+            <artifactId>rfc6991-ietf-inet-types</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.mdsal.binding.model.ietf</groupId>
+            <artifactId>rfc6991-ietf-yang-types</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.netconf</groupId>
+            <artifactId>transport-http</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.netconf</groupId>
+            <artifactId>transport-tcp</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.netconf</groupId>
+            <artifactId>transport-tls</artifactId>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/protocol/restconf-client/src/main/java/org/opendaylight/restconf/client/impl/IetfRestconfClientFeatureProvider.java b/protocol/restconf-client/src/main/java/org/opendaylight/restconf/client/impl/IetfRestconfClientFeatureProvider.java
new file mode 100644 (file)
index 0000000..2be1da9
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2024 PANTHEON.tech, 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.restconf.client.impl;
+
+import java.util.Set;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.kohsuke.MetaInfServices;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.restconf.client.rev230417.IetfRestconfClientData;
+import org.opendaylight.yangtools.yang.binding.YangFeature;
+import org.opendaylight.yangtools.yang.binding.YangFeatureProvider;
+
+/**
+ * Baseline features supported from {@code ietf-restconf-client.yang}.
+ */
+@MetaInfServices
+@NonNullByDefault
+public final class IetfRestconfClientFeatureProvider implements YangFeatureProvider<IetfRestconfClientData> {
+    @Override
+    public Class<IetfRestconfClientData> boundModule() {
+        return IetfRestconfClientData.class;
+    }
+
+    @Override
+    public Set<? extends YangFeature<?, IetfRestconfClientData>> supportedFeatures() {
+        // FIXME: support some features
+        return Set.of();
+    }
+}
diff --git a/protocol/restconf-client/src/main/yang/ietf-restconf-client.yang b/protocol/restconf-client/src/main/yang/ietf-restconf-client.yang
new file mode 100644 (file)
index 0000000..c19225a
--- /dev/null
@@ -0,0 +1,547 @@
+module ietf-restconf-client {
+  yang-version 1.1;
+  namespace "urn:ietf:params:xml:ns:yang:ietf-restconf-client";
+  prefix rcc;
+
+  import ietf-yang-types {
+    prefix yang;
+    reference
+      "RFC 6991: Common YANG Data Types";
+  }
+
+  import ietf-tcp-client {
+    prefix tcpc;
+    reference
+      "RFC DDDD: YANG Groupings for TCP Clients and TCP Servers";
+  }
+
+  import ietf-tcp-server {
+    prefix tcps;
+    reference
+      "RFC DDDD: YANG Groupings for TCP Clients and TCP Servers";
+  }
+
+  import ietf-tls-client {
+    prefix tlsc;
+    reference
+      "RFC FFFF: YANG Groupings for TLS Clients and TLS Servers";
+  }
+
+  import ietf-http-client {
+    prefix httpc;
+    reference
+      "RFC GGGG: YANG Groupings for HTTP Clients and HTTP Servers";
+  }
+
+  organization
+    "IETF NETCONF (Network Configuration) Working Group";
+
+  contact
+    "WG Web:   https://datatracker.ietf.org/wg/netconf
+     WG List:  NETCONF WG list <mailto:netconf@ietf.org>
+     Author:   Kent Watsen <mailto:kent+ietf@watsen.net>";
+
+  description
+    "This module contains a collection of YANG definitions
+     for configuring RESTCONF clients.
+
+     Copyright (c) 2023 IETF Trust and the persons identified
+     as authors of the code. All rights reserved.
+
+     Redistribution and use in source and binary forms, with
+     or without modification, is permitted pursuant to, and
+     subject to the license terms contained in, the Revised
+     BSD License set forth in Section 4.c of the IETF Trust's
+     Legal Provisions Relating to IETF Documents
+     (https://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC IIII
+     (https://www.rfc-editor.org/info/rfcIIII); see the RFC
+     itself for full legal notices.
+
+     The key words 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL',
+     'SHALL NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED',
+     'NOT RECOMMENDED', 'MAY', and 'OPTIONAL' in this document
+     are to be interpreted as described in BCP 14 (RFC 2119)
+     (RFC 8174) when, and only when, they appear in all
+     capitals, as shown here.";
+
+  revision 2023-04-17 {
+    description
+      "Initial version";
+    reference
+      "RFC IIII: RESTCONF Client and Server Models";
+  }
+
+  // Features
+
+  feature https-initiate {
+    description
+      "The 'https-initiate' feature indicates that the RESTCONF
+       client supports initiating HTTPS connections to RESTCONF
+       servers. This feature exists as HTTPS might not be a
+       mandatory to implement transport in the future.";
+    reference
+      "RFC 8040: RESTCONF Protocol";
+  }
+
+  feature http-listen {
+    description
+      "The 'http-listen' feature indicates that the RESTCONF client
+       supports opening a port to listen for incoming RESTCONF
+       server call-home connections.  This feature exists as not
+       all RESTCONF clients may support RESTCONF call home.";
+    reference
+      "RFC 8071: NETCONF Call Home and RESTCONF Call Home";
+  }
+
+  feature https-listen {
+    description
+      "The 'https-listen' feature indicates that the RESTCONF client
+       supports opening a port to listen for incoming RESTCONF
+       server call-home connections.  This feature exists as not
+       all RESTCONF clients may support RESTCONF call home.";
+    reference
+      "RFC 8071: NETCONF Call Home and RESTCONF Call Home";
+  }
+
+  feature central-restconf-client-supported {
+   description
+      "The 'central-restconf-client-supported' feature indicates
+       that the server that implements this module supports
+       the top-level 'restconf-client' node.
+
+       This feature is needed as some servers may want to use
+       features defined in this module, which requires this
+       module to be implemented, without having to support
+       the top-level 'restconf-client' node.";
+  }
+
+  // Groupings
+
+  grouping restconf-client-grouping {
+    description
+      "A reusable grouping for configuring a RESTCONF client
+       without any consideration for how underlying transport
+       sessions are established.
+
+       This grouping currently does not define any nodes. It
+       exists only so the model can be consistent with other
+       'client-server' models.";
+  }
+
+  grouping restconf-client-initiate-stack-grouping {
+    description
+      "A reusable grouping for configuring a RESTCONF client
+       'initiate' protocol stack for a single connection.";
+
+    choice transport {
+      mandatory true;
+      description
+        "Selects between available transports. This is a
+         'choice' statement so as to support additional
+         transport options to be augmented in.";
+      case https {
+        if-feature "https-initiate";
+        container https {
+          must 'tls-client-parameters/client-identity
+                or http-client-parameters/client-identity';
+          description
+            "Specifies HTTPS-specific transport
+             configuration.";
+          container tcp-client-parameters {
+            description
+              "A wrapper around the TCP client parameters
+               to avoid name collisions.";
+            uses tcpc:tcp-client-grouping {
+              refine "remote-port" {
+                default "443";
+                description
+                  "The RESTCONF client will attempt to
+                   connect to the IANA-assigned well-known
+                   port value for 'https' (443) if no value
+                   is specified.";
+              }
+            }
+          }
+          container tls-client-parameters {
+            description
+              "A wrapper around the TLS client parameters
+               to avoid name collisions.";
+            uses tlsc:tls-client-grouping;
+          }
+          container http-client-parameters {
+            description
+              "A wrapper around the HTTP client parameters
+               to avoid name collisions.";
+            uses httpc:http-client-grouping;
+          }
+          container restconf-client-parameters {
+            description
+              "A wrapper around the RESTCONF client parameters
+               to avoid name collisions.
+
+               This container does not define any nodes.  It
+               exists as a potential augmentation target by
+               other modules.";
+            uses rcc:restconf-client-grouping;
+          }
+        }
+      }
+    }
+  } // restconf-client-initiate-stack-grouping
+
+  grouping restconf-client-listen-stack-grouping {
+    description
+      "A reusable grouping for configuring a RESTCONF client
+       'listen' protocol stack for a single connection.  The
+       'listen' stack supports call home connections, as
+       described in RFC 8071";
+    reference
+      "RFC 8071: NETCONF Call Home and RESTCONF Call Home";
+    choice transport {
+      mandatory true;
+      description
+        "Selects between available transports. This is a
+         'choice' statement so as to support additional
+         transport options to be augmented in.";
+      case http {
+        if-feature "http-listen";
+        container http {
+          description
+            "HTTP-specific listening configuration for inbound
+             connections.
+
+             This transport option is made available to support
+             deployments where the TLS connections are terminated
+             by another system (e.g., a load balancer) fronting
+             the client.";
+          container tcp-server-parameters {
+            description
+              "A wrapper around the TCP client parameters
+               to avoid name collisions.";
+            uses tcps:tcp-server-grouping {
+              refine "local-port" {
+                default "4336";
+                description
+                  "The RESTCONF client will listen on the IANA-
+                   assigned well-known port for 'restconf-ch-tls'
+                   (4336) if no value is specified.";
+              }
+            }
+          }
+          container http-client-parameters {
+            description
+              "A wrapper around the HTTP client parameters
+               to avoid name collisions.";
+            uses httpc:http-client-grouping;
+          }
+          container restconf-client-parameters {
+            description
+              "A wrapper around the RESTCONF client parameters
+               to avoid name collisions.
+
+               This container does not define any nodes.  It
+               exists as a potential augmentation target by
+               other modules.";
+            uses rcc:restconf-client-grouping;
+          }
+        }
+      }
+      case https {
+        if-feature "https-listen";
+        container https {
+          must 'tls-client-parameters/client-identity
+                or http-client-parameters/client-identity';
+          description
+            "HTTPS-specific listening configuration for inbound
+             connections.";
+          container tcp-server-parameters {
+            description
+              "A wrapper around the TCP client parameters
+               to avoid name collisions.";
+            uses tcps:tcp-server-grouping {
+              refine "local-port" {
+                default "4336";
+                description
+                  "The RESTCONF client will listen on the IANA-
+                   assigned well-known port for 'restconf-ch-tls'
+                   (4336) if no value is specified.";
+              }
+            }
+          }
+          container tls-client-parameters {
+            description
+              "A wrapper around the TLS client parameters
+               to avoid name collisions.";
+            uses tlsc:tls-client-grouping;
+          }
+          container http-client-parameters {
+            description
+              "A wrapper around the HTTP client parameters
+               to avoid name collisions.";
+            uses httpc:http-client-grouping;
+          }
+          container restconf-client-parameters {
+            description
+              "A wrapper around the RESTCONF client parameters
+               to avoid name collisions.
+
+               This container does not define any nodes.  It
+               exists as a potential augmentation target by
+               other modules.";
+            uses rcc:restconf-client-grouping;
+          }
+        }
+      }
+    }
+  } // restconf-client-listen-stack-grouping
+
+  grouping restconf-client-app-grouping {
+    description
+      "A reusable grouping for configuring a RESTCONF client
+       application that supports both 'initiate' and 'listen'
+       protocol stacks for a multiplicity of connections.";
+    container initiate {
+      if-feature "https-initiate";
+      presence
+        "Indicates that client-initiated connections have been
+         configured.  This statement is present so the mandatory
+         descendant nodes do not imply that this node must be
+         configured.";
+      description
+        "Configures client initiating underlying TCP connections.";
+      list restconf-server {
+        key "name";
+        min-elements 1;
+        description
+          "List of RESTCONF servers the RESTCONF client is to
+           maintain simultaneous connections with.";
+        leaf name {
+          type string;
+          description
+            "An arbitrary name for the RESTCONF server.";
+        }
+        container endpoints {
+          description
+            "Container for the list of endpoints.";
+          list endpoint {
+            key "name";
+            min-elements 1;
+            ordered-by user;
+            description
+              "A non-empty user-ordered list of endpoints for this
+               RESTCONF client to try to connect to in sequence.
+               Defining more than one enables high-availability.";
+            leaf name {
+              type string;
+              description
+                "An arbitrary name for this endpoint.";
+            }
+            uses restconf-client-initiate-stack-grouping;
+          }
+        }
+        container connection-type {
+          description
+            "Indicates the RESTCONF client's preference for how
+             the RESTCONF connection is maintained.";
+          choice connection-type {
+            mandatory true;
+            description
+              "Selects between available connection types.";
+            case persistent-connection {
+              container persistent {
+                presence
+                  "Indicates that a persistent connection is to be
+                   maintained.";
+                description
+                  "Maintain a persistent connection to the
+                   RESTCONF server. If the connection goes down,
+                   immediately start trying to reconnect to the
+                   RESTCONF server, using the reconnection strategy.
+
+                   This connection type minimizes any RESTCONF server
+                   to RESTCONF client data-transfer delay, albeit
+                   at the expense of holding resources longer.";
+              }
+            }
+            case periodic-connection {
+              container periodic {
+                presence
+                  "Indicates that a periodic connection is to be
+                   maintained.";
+                description
+                  "Periodically connect to the RESTCONF server.
+
+                   This connection type decreases resource
+                   utilization, albeit with increased delay
+                   in RESTCONF server to RESTCONF client
+                   interactions.
+
+                   The RESTCONF client SHOULD gracefully close
+                   the underlying TLS connection upon completing
+                   planned activities.
+
+                   Connections are established at the same start
+                   time regardless how long the previous connection
+                   stayed open.
+
+                   In the case that the previous connection is
+                   still active, establishing a new connection
+                   is NOT RECOMMENDED.";
+                leaf period {
+                  type uint16;
+                  units "minutes";
+                  default "60";
+                  description
+                    "Duration of time between periodic
+                     connections.";
+                }
+                leaf anchor-time {
+                  type yang:date-and-time {
+                    // constrained to minute-level granularity
+                    pattern '[0-9]{4}-(1[0-2]|0[1-9])-(0[1-9]|[1-2]'
+                          + '[0-9]|3[0-1])T(0[0-9]|1[0-9]|2[0-3]):['
+                          + '0-5][0-9]:00(Z|[\+\-]((1[0-3]|0[0-9]):'
+                          + '([0-5][0-9])|14:00))?';
+                  }
+                  description
+                    "Designates a timestamp before or after which a
+                     series of periodic connections are determined.
+                     The periodic connections occur at a whole
+                     multiple interval from the anchor time.
+
+                     If an 'anchor-time' is not provided, then the
+                     server may implicitly set it to the time when
+                     this configuraton is applied (e.g., on boot).
+
+                     For example, for an anchor time is 15 minutes
+                     past midnight and a period interval of 24 hours,
+                     then a periodic connection will occur 15 minutes
+                     past midnight everyday.";
+                }
+                leaf idle-timeout {
+                  type uint16;
+                  units "seconds";
+                  default "180"; // three minutes
+                  description
+                    "Specifies the maximum number of seconds
+                     that the underlying TCP session may remain
+                     idle. A TCP session will be dropped if it
+                     is idle for an interval longer than this
+                     number of seconds If set to zero, then the
+                     RESTCONF client will never drop a session
+                     because it is idle.";
+                }
+              }
+            } // periodic-connection
+          } // connection-type
+        } // connection-type
+        container reconnect-strategy {
+          description
+            "The reconnection strategy directs how a RESTCONF
+             client reconnects to a RESTCONF server, after
+             discovering its connection to the server has
+             dropped, even if due to a reboot.  The RESTCONF
+             client starts with the specified endpoint and
+             tries to connect to it max-attempts times before
+             trying the next endpoint in the list (round
+             robin).";
+          leaf start-with {
+            type enumeration {
+              enum first-listed {
+                description
+                  "Indicates that reconnections should start
+                   with the first endpoint listed.";
+              }
+              enum last-connected {
+                description
+                  "Indicates that reconnections should start
+                   with the endpoint last connected to.  If
+                   no previous connection has ever been
+                   established, then the first endpoint
+                   configured is used.   RESTCONF clients
+                   SHOULD be able to remember the last
+                   endpoint connected to across reboots.";
+              }
+              enum random-selection {
+                description
+                  "Indicates that reconnections should start with
+                   a random endpoint.";
+              }
+            }
+            default "first-listed";
+            description
+              "Specifies which of the RESTCONF server's
+               endpoints the RESTCONF client should start
+               with when trying to connect to the RESTCONF
+               server.";
+          }
+          leaf max-wait {
+            type uint16 {
+              range "1..max";
+            }
+            units "seconds";
+            default "5";
+            description
+              "Specifies the amount of time in seconds after which,
+               if the connection is not established, an endpoint
+               connection attempt is considered unsuccessful.";
+          }
+          leaf max-attempts {
+            type uint8 {
+              range "1..max";
+            }
+            default "3";
+            description
+              "Specifies the number times the RESTCONF client
+               tries to connect to a specific endpoint before
+               moving on to the next endpoint in the list
+               (round robin).";
+          }
+        }
+      }
+    } // initiate
+    container listen {
+      if-feature "http-listen or https-listen";
+      presence
+        "Indicates that client-listening ports have been configured.
+         This statement is present so the mandatory descendant nodes
+         do not imply that this node must be configured.";
+      description
+        "Configures the client to accept call-home TCP connections.";
+      leaf idle-timeout {
+        type uint16;
+        units "seconds";
+        default "180"; // three minutes
+        description
+          "Specifies the maximum number of seconds that an
+           underlying TCP session may remain idle. A TCP session
+           will be dropped if it is idle for an interval longer
+           then this number of seconds.  If set to zero, then
+           the server will never drop a session because it is
+           idle.";
+      }
+      list endpoint {
+        key "name";
+        min-elements 1;
+        description
+          "List of endpoints to listen for RESTCONF connections.";
+        leaf name {
+          type string;
+          description
+            "An arbitrary name for the RESTCONF listen endpoint.";
+        }
+        uses restconf-client-listen-stack-grouping;
+      }
+    }
+  } // restconf-client-app-grouping
+
+  // Protocol accessible node for servers that implement this module.
+  container restconf-client {
+    if-feature central-restconf-client-supported;
+    uses restconf-client-app-grouping;
+    description
+      "Top-level container for RESTCONF client configuration.";
+  }
+}
diff --git a/protocol/restconf-server/pom.xml b/protocol/restconf-server/pom.xml
new file mode 100644 (file)
index 0000000..5c59c9f
--- /dev/null
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2024 PANTHEON.tech, 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
+-->
+<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.netconf</groupId>
+        <artifactId>netconf-parent</artifactId>
+        <version>7.0.0-SNAPSHOT</version>
+        <relativePath>../../parent</relativePath>
+    </parent>
+
+    <artifactId>restconf-server</artifactId>
+    <name>${project.artifactId}</name>
+    <packaging>bundle</packaging>
+    <description>RESTCONF protocol server</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.kohsuke.metainf-services</groupId>
+            <artifactId>metainf-services</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.mdsal.binding.model.ietf</groupId>
+            <artifactId>rfc6991-ietf-inet-types</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.mdsal.binding.model.ietf</groupId>
+            <artifactId>rfc6991-ietf-yang-types</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.netconf</groupId>
+            <artifactId>transport-http</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.netconf</groupId>
+            <artifactId>transport-tcp</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.netconf</groupId>
+            <artifactId>transport-tls</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.netconf.model</groupId>
+            <artifactId>rfc7407-ietf-x509-cert-to-name</artifactId>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/protocol/restconf-server/src/main/java/org/opendaylight/restconf/server/impl/IetfRestconfServerFeatureProvider.java b/protocol/restconf-server/src/main/java/org/opendaylight/restconf/server/impl/IetfRestconfServerFeatureProvider.java
new file mode 100644 (file)
index 0000000..cb9b6b2
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2024 PANTHEON.tech, 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.restconf.server.impl;
+
+import java.util.Set;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.kohsuke.MetaInfServices;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.restconf.server.rev230417.IetfRestconfServerData;
+import org.opendaylight.yangtools.yang.binding.YangFeature;
+import org.opendaylight.yangtools.yang.binding.YangFeatureProvider;
+
+/**
+ * Baseline features supported from {@code ietf-restconf-client.yang}.
+ */
+@MetaInfServices
+@NonNullByDefault
+public final class IetfRestconfServerFeatureProvider implements YangFeatureProvider<IetfRestconfServerData> {
+    @Override
+    public Class<IetfRestconfServerData> boundModule() {
+        return IetfRestconfServerData.class;
+    }
+
+    @Override
+    public Set<? extends YangFeature<?, IetfRestconfServerData>> supportedFeatures() {
+        // FIXME: support some features
+        return Set.of();
+    }
+}
diff --git a/protocol/restconf-server/src/main/yang/ietf-restconf-server.yang b/protocol/restconf-server/src/main/yang/ietf-restconf-server.yang
new file mode 100644 (file)
index 0000000..e81b282
--- /dev/null
@@ -0,0 +1,585 @@
+module ietf-restconf-server {
+  yang-version 1.1;
+  namespace "urn:ietf:params:xml:ns:yang:ietf-restconf-server";
+  prefix rcs;
+
+  import ietf-yang-types {
+    prefix yang;
+    reference
+      "RFC 6991: Common YANG Data Types";
+  }
+
+  import ietf-inet-types {
+    prefix inet;
+    reference
+      "RFC 6991: Common YANG Data Types";
+  }
+
+  import ietf-x509-cert-to-name {
+    prefix x509c2n;
+    reference
+      "RFC 7407: A YANG Data Model for SNMP Configuration";
+  }
+
+  import ietf-tcp-client {
+    prefix tcpc;
+    reference
+      "RFC DDDD: YANG Groupings for TCP Clients and TCP Servers";
+  }
+
+  import ietf-tcp-server {
+    prefix tcps;
+    reference
+      "RFC DDDD: YANG Groupings for TCP Clients and TCP Servers";
+  }
+
+  import ietf-tls-server {
+    prefix tlss;
+    reference
+      "RFC FFFF: YANG Groupings for TLS Clients and TLS Servers";
+  }
+
+  import ietf-http-server {
+    prefix https;
+    reference
+      "RFC GGGG: YANG Groupings for HTTP Clients and HTTP Servers";
+  }
+
+  organization
+    "IETF NETCONF (Network Configuration) Working Group";
+
+  contact
+    "WG Web:   https://datatracker.ietf.org/wg/netconf
+     WG List:  NETCONF WG list <mailto:netconf@ietf.org>
+     Author:   Kent Watsen <mailto:kent+ietf@watsen.net>";
+
+  description
+    "This module contains a collection of YANG definitions
+     for configuring RESTCONF servers.
+
+     Copyright (c) 2023 IETF Trust and the persons identified
+     as authors of the code. All rights reserved.
+
+     Redistribution and use in source and binary forms, with
+     or without modification, is permitted pursuant to, and
+     subject to the license terms contained in, the Revised
+     BSD License set forth in Section 4.c of the IETF Trust's
+     Legal Provisions Relating to IETF Documents
+     (https://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC IIII
+     (https://www.rfc-editor.org/info/rfcIIII); see the RFC
+     itself for full legal notices.
+
+     The key words 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL',
+     'SHALL NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED',
+     'NOT RECOMMENDED', 'MAY', and 'OPTIONAL' in this document
+     are to be interpreted as described in BCP 14 (RFC 2119)
+     (RFC 8174) when, and only when, they appear in all
+     capitals, as shown here.";
+
+  revision 2023-04-17 {
+    description
+      "Initial version";
+    reference
+      "RFC IIII: RESTCONF Client and Server Models";
+  }
+
+  // Features
+
+  feature http-listen {
+    description
+      "The 'http-listen' feature indicates that the RESTCONF server
+       supports opening a port to listen for incoming RESTCONF over
+       TCP client connections, whereby the TLS connections are
+       terminated by an external system.";
+    reference
+      "RFC 8040: RESTCONF Protocol";
+  }
+
+  feature https-listen {
+    description
+      "The 'https-listen' feature indicates that the RESTCONF server
+       supports opening a port to listen for incoming RESTCONF over
+       TLS client connections, whereby the TLS connections are
+       terminated by the server itself.";
+    reference
+      "RFC 8040: RESTCONF Protocol";
+  }
+
+  feature https-call-home {
+    description
+      "The 'https-call-home' feature indicates that the RESTCONF
+       server supports initiating connections to RESTCONF clients.";
+    reference
+      "RFC 8071: NETCONF Call Home and RESTCONF Call Home";
+  }
+
+  feature central-restconf-server-supported {
+   description
+      "The 'central-restconf-server-supported' feature indicates
+       that the server supports the top-level 'restconf-server'
+       node.
+
+       This feature is needed as some servers may want to use
+       features defined in this module, which requires this
+       module to be implemented, without having to support
+       the top-level 'restconf-server' node.";
+  }
+
+  // Groupings
+
+  grouping restconf-server-grouping {
+    description
+      "A reusable grouping for configuring a RESTCONF server
+       without any consideration for how underlying transport
+       sessions are established.
+
+       Note that this grouping uses a fairly typical descendant
+       node name such that a stack of 'uses' statements will
+       have name conflicts.  It is intended that the consuming
+       data model will resolve the issue by wrapping the 'uses'
+       statement in a container called, e.g.,
+       'restconf-server-parameters'.  This model purposely does
+       not do this itself so as to provide maximum flexibility
+       to consuming models.";
+
+    container client-identity-mappings {
+      description
+        "Specifies mappings through which RESTCONF client X.509
+         certificates are used to determine a RESTCONF username.
+         If no matching and valid cert-to-name list entry can be
+         found, then the RESTCONF server MUST close the connection,
+         and MUST NOT accept RESTCONF messages over it.";
+      reference
+        "RFC 7407: A YANG Data Model for SNMP Configuration.";
+      uses x509c2n:cert-to-name {
+        refine "cert-to-name/fingerprint" {
+          mandatory false;
+          description
+            "A 'fingerprint' value does not need to be specified
+             when the 'cert-to-name' mapping is independent of
+             fingerprint matching.  A 'cert-to-name' having no
+             fingerprint value will match any client certificate
+             and therefore should only be present at the end of
+             the user-ordered 'cert-to-name' list.";
+        }
+      }
+    }
+  }
+
+  grouping restconf-server-listen-stack-grouping {
+    description
+      "A reusable grouping for configuring a RESTCONF server
+       'listen' protocol stack for a single connection.";
+    choice transport {
+      mandatory true;
+      description
+        "Selects between available transports. This is a
+         'choice' statement so as to support additional
+         transport options to be augmented in.";
+      case http {
+        if-feature "http-listen";
+        container http {
+          description
+            "Configures RESTCONF server stack assuming that
+             TLS-termination is handled externally.";
+          container external-endpoint {
+            presence
+              "Identifies that an external endpoint has been
+               configured.  This statement is present so the
+               mandatory descendant nodes do not imply that
+               this node must be configured.";
+            description
+              "Identifies contact information for the external
+               system that terminates connections before passing
+               them thru to this server (e.g., a network address
+               translator or a load balancer).  These values have
+               no effect on the local operation of this server,
+               but may be used by the application when needing to
+               inform other systems how to contact this server.";
+            leaf address {
+              type inet:host;
+              mandatory true;
+              description
+                "The IP address or hostname of the external system
+                 that terminates incoming RESTCONF client
+                 connections before forwarding them to this
+                 server.";
+            }
+            leaf port {
+              type inet:port-number;
+              default "443";
+              description
+                "The port number that the external system listens
+                 on for incoming RESTCONF client connections that
+                 are forwarded to this server.  The default HTTPS
+                 port (443) is used, as expected for a RESTCONF
+                 connection.";
+            }
+          }
+          container tcp-server-parameters {
+            description
+              "A wrapper around the TCP server parameters
+               to avoid name collisions.";
+            uses tcps:tcp-server-grouping {
+              refine "local-port" {
+                default "80";
+                description
+                  "The RESTCONF server will listen on the IANA-
+                   assigned well-known port value for 'http'
+                   (80) if no value is specified.";
+              }
+            }
+          }
+          container http-server-parameters {
+            description
+              "A wrapper around the HTTP server parameters
+               to avoid name collisions.";
+            uses https:http-server-grouping;
+          }
+          container restconf-server-parameters {
+            description
+              "A wrapper around the RESTCONF server parameters
+               to avoid name collisions.";
+            uses rcs:restconf-server-grouping;
+          }
+        }
+      }
+      case https {
+        if-feature "https-listen";
+        container https {
+          description
+            "Configures RESTCONF server stack assuming that
+             TLS-termination is handled internally (i.e.,
+             not by a TLS-terminator in front of the RESTCONF
+             server).";
+          container tcp-server-parameters {
+            description
+              "A wrapper around the TCP server parameters
+               to avoid name collisions.";
+            uses tcps:tcp-server-grouping {
+              refine "local-port" {
+                default "443";
+                description
+                  "The RESTCONF server will listen on the IANA-
+                   assigned well-known port value for 'https'
+                   (443) if no value is specified.";
+              }
+            }
+          }
+          container tls-server-parameters {
+            description
+              "A wrapper around the TLS server parameters
+               to avoid name collisions.";
+            uses tlss:tls-server-grouping;
+          }
+          container http-server-parameters {
+            description
+              "A wrapper around the HTTP server parameters
+               to avoid name collisions.";
+            uses https:http-server-grouping;
+          }
+          container restconf-server-parameters {
+            description
+              "A wrapper around the RESTCONF server parameters
+               to avoid name collisions.";
+            uses rcs:restconf-server-grouping;
+          }
+        }
+      }
+    }
+  }
+
+  grouping restconf-server-callhome-stack-grouping {
+    description
+      "A reusable grouping for configuring a RESTCONF server
+       'call-home' protocol stack, for a single connection.";
+    choice transport {
+      mandatory true;
+      description
+        "Selects between available transports. This is a
+         'choice' statement so as to support additional
+         transport options to be augmented in.";
+      case https {
+        if-feature "https-listen";
+        container https {
+          description
+            "Configures RESTCONF server stack assuming that
+             TLS-termination is handled internally.";
+          container tcp-client-parameters {
+            description
+              "A wrapper around the TCP client parameters
+               to avoid name collisions.";
+            uses tcpc:tcp-client-grouping {
+              refine "remote-port" {
+                default "4336";
+                description
+                  "The RESTCONF server will attempt to
+                   connect to the IANA-assigned well-known
+                   port for 'restconf-ch-tls' (4336) if no
+                   value is specified.";
+              }
+            }
+          }
+          container tls-server-parameters {
+            description
+              "A wrapper around the TLS server parameters
+               to avoid name collisions.";
+            uses tlss:tls-server-grouping;
+          }
+          container http-server-parameters {
+            description
+              "A wrapper around the HTTP server parameters
+               to avoid name collisions.";
+            uses https:http-server-grouping;
+          }
+          container restconf-server-parameters {
+            description
+              "A wrapper around the RESTCONF server parameters
+               to avoid name collisions.";
+            uses rcs:restconf-server-grouping;
+          }
+        }
+      }
+    }
+  }
+
+  grouping restconf-server-app-grouping {
+    description
+      "A reusable grouping for configuring a RESTCONF server
+       application that supports both 'listen' and 'call-home'
+       protocol stacks for a multiplicity of connections.";
+    container listen {
+      if-feature "http-listen or https-listen";
+      presence
+        "Identifies that the server has been configured to
+         listen for incoming client connections.  This statement
+         is present so the mandatory descendant nodes do not
+         imply that this node must be configured.";
+      description
+        "Configures the RESTCONF server to listen for RESTCONF
+         client connections.";
+      list endpoint {
+        key "name";
+        min-elements 1;
+        description
+          "List of endpoints to listen for RESTCONF connections.";
+        leaf name {
+          type string;
+          description
+            "An arbitrary name for the RESTCONF listen endpoint.";
+        }
+        uses restconf-server-listen-stack-grouping;
+      }
+    }
+    container call-home {
+      if-feature "https-call-home";
+      presence
+        "Identifies that the server has been configured to initiate
+         call home connections.  This statement is present so the
+         mandatory descendant nodes do not imply that this node
+         must be configured.";
+      description
+        "Configures the RESTCONF server to initiate the underlying
+         transport connection to RESTCONF clients.";
+      list restconf-client {
+        key "name";
+        min-elements 1;
+        description
+          "List of RESTCONF clients the RESTCONF server is to
+           maintain simultaneous call-home connections with.";
+        leaf name {
+          type string;
+          description
+            "An arbitrary name for the remote RESTCONF client.";
+        }
+        container endpoints {
+          description
+            "Container for the list of endpoints.";
+          list endpoint {
+            key "name";
+            min-elements 1;
+            ordered-by user;
+            description
+              "User-ordered list of endpoints for this RESTCONF
+               client.  Defining more than one enables high-
+               availability.";
+            leaf name {
+              type string;
+              description
+                "An arbitrary name for this endpoint.";
+            }
+            uses restconf-server-callhome-stack-grouping;
+          }
+        }
+        container connection-type {
+          description
+            "Indicates the RESTCONF server's preference for how the
+             RESTCONF connection is maintained.";
+          choice connection-type {
+            mandatory true;
+            description
+              "Selects between available connection types.";
+            case persistent-connection {
+              container persistent {
+                presence
+                  "Indicates that a persistent connection is to be
+                   maintained.";
+                description
+                  "Maintain a persistent connection to the RESTCONF
+                   client. If the connection goes down, immediately
+                   start trying to reconnect to the RESTCONF client,
+                   using the reconnection strategy.
+
+                   This connection type minimizes any RESTCONF
+                   client to RESTCONF server data-transfer delay,
+                   albeit at the expense of holding resources
+                   longer.";
+              }
+            }
+            case periodic-connection {
+              container periodic {
+                presence
+                  "Indicates that a periodic connection is to be
+                   maintained.";
+                description
+                  "Periodically connect to the RESTCONF client.
+
+                   This connection type decreases resource
+                   utilization, albeit with increased delay in
+                   RESTCONF client to RESTCONF server interactions.
+
+                   The RESTCONF client SHOULD gracefully close
+                   the underlying TLS connection upon completing
+                   planned activities.  If the underlying TLS
+                   connection is not closed gracefully, the
+                   RESTCONF server MUST immediately attempt
+                   to reestablish the connection.
+
+                   Connections are established at the same start
+                   time regardless how long the previous connection
+                   stayed open.
+
+                   In the case that the previous connection is
+                   still active (i.e., the RESTCONF client has not
+                   closed it yet), establishing a new connection
+                   is NOT RECOMMENDED.";
+
+                leaf period {
+                  type uint16;
+                  units "minutes";
+                  default "60";
+                  description
+                    "Duration of time between periodic connections.";
+                }
+                leaf anchor-time {
+                  type yang:date-and-time {
+                    // constrained to minute-level granularity
+                    pattern '[0-9]{4}-(1[0-2]|0[1-9])-(0[1-9]|[1-2]'
+                          + '[0-9]|3[0-1])T(0[0-9]|1[0-9]|2[0-3]):['
+                          + '0-5][0-9]:00(Z|[\+\-]((1[0-3]|0[0-9]):'
+                          + '([0-5][0-9])|14:00))?';
+                  }
+                  description
+                    "Designates a timestamp before or after which a
+                     series of periodic connections are determined.
+                     The periodic connections occur at a whole
+                     multiple interval from the anchor time.
+
+                     If an 'anchor-time' is not provided, then the
+                     server may implicitly set it to the time when
+                     this configuraton is applied (e.g., on boot).
+
+                     For example, for an anchor time is 15 minutes
+                     past midnight and a period interval of 24 hours,
+                     then a periodic connection will occur 15 minutes
+                     past midnight everyday.";
+                }
+                leaf idle-timeout {
+                  type uint16;
+                  units "seconds";
+                  default "180"; // three minutes
+                  description
+                    "Specifies the maximum number of seconds that
+                     the underlying TCP session may remain idle.
+                     A TCP session will be dropped if it is idle
+                     for an interval longer than this number of
+                     seconds.  If set to zero, then the server
+                     will never drop a session because it is idle.";
+                }
+              }
+            }
+          }
+        }
+        container reconnect-strategy {
+          description
+            "The reconnection strategy directs how a RESTCONF server
+             reconnects to a RESTCONF client after discovering its
+             connection to the client has dropped, even if due to a
+             reboot.  The RESTCONF server starts with the specified
+             endpoint and tries to connect to it max-attempts times
+             before trying the next endpoint in the list (round
+             robin).";
+          leaf start-with {
+            type enumeration {
+              enum first-listed {
+                description
+                  "Indicates that reconnections should start with
+                   the first endpoint listed.";
+              }
+              enum last-connected {
+                description
+                  "Indicates that reconnections should start with
+                   the endpoint last connected to.  If no previous
+                   connection has ever been established, then the
+                   first endpoint configured is used.   RESTCONF
+                   servers SHOULD be able to remember the last
+                   endpoint connected to across reboots.";
+              }
+              enum random-selection {
+                description
+                  "Indicates that reconnections should start with
+                   a random endpoint.";
+              }
+            }
+            default "first-listed";
+            description
+              "Specifies which of the RESTCONF client's endpoints
+               the RESTCONF server should start with when trying
+               to connect to the RESTCONF client.";
+          }
+          leaf max-wait {
+            type uint16 {
+              range "1..max";
+            }
+            units "seconds";
+            default "5";
+            description
+              "Specifies the amount of time in seconds after which,
+               if the connection is not established, an endpoint
+               connection attempt is considered unsuccessful.";
+          }
+          leaf max-attempts {
+            type uint8 {
+              range "1..max";
+            }
+            default "3";
+            description
+              "Specifies the number times the RESTCONF server tries
+               to connect to a specific endpoint before moving on to
+               the next endpoint in the list (round robin).";
+          }
+        }
+      } // restconf-client
+    } // call-home
+  } // restconf-server-app-grouping
+
+  // Protocol accessible node for servers that implement this module.
+  container restconf-server {
+    if-feature central-restconf-server-supported;
+    uses restconf-server-app-grouping;
+    description
+      "Top-level container for RESTCONF server configuration.";
+  }
+}