Update old links in user guide
[netconf.git] / docs / user-guide.rst
index 12eea4d956030d5d481f35ae26f8d4f8d08bfc20..5e31ff80544eddb55b8bca14015fbfd6126af9ce 100644 (file)
@@ -16,7 +16,7 @@ Overview
 
 NETCONF is an XML-based protocol used for configuration and monitoring
 devices in the network. The base NETCONF protocol is described in
-`RFC-6241 <http://tools.ietf.org/html/rfc6241>`__.
+`RFC-6241 <https://www.rfc-editor.org/rfc/rfc6241>`__.
 
 **NETCONF in OpenDaylight:.**
 
@@ -35,13 +35,13 @@ mounted devices.
 
 In terms of RFCs, the connector supports:
 
--  `RFC-6241 <http://tools.ietf.org/html/rfc6241>`__
+-  `RFC-6241 <https://www.rfc-editor.org/rfc/rfc6241>`__
 
--  `RFC-5277 <https://tools.ietf.org/html/rfc5277>`__
+-  `RFC-5277 <https://www.rfc-editor.org/rfc/rfc5277>`__
 
--  `RFC-6022 <https://tools.ietf.org/html/rfc6022>`__
+-  `RFC-6022 <https://www.rfc-editor.org/rfc/rfc6022>`__
 
--  `draft-ietf-netconf-yang-library-06 <https://tools.ietf.org/html/draft-ietf-netconf-yang-library-06>`__
+-  `RFC-7895 <https://www.rfc-editor.org/rfc/rfc7895>`__
 
 **Netconf-connector is fully model-driven (utilizing the YANG modeling
 language) so in addition to the above RFCs, it supports any
@@ -63,19 +63,13 @@ focuses on RESTCONF.
 
 .. important::
 
-    There are 2 different endpoints related to RESTCONF protocols:
+    Since 2022.09 Chlorine there is only one RESTCONF endpoint:
 
-    - | ``http://localhost:8181/restconf`` is related to `draft-bierman-netconf-restconf-02 <https://tools.ietf.org/html/draft-bierman-netconf-restconf-02>`__,
-      | can be activated by installing ``odl-restconf-nb-bierman02``
+    - | ``http://localhost:8181/rests`` is related to `RFC-8040 <https://www.rfc-editor.org/rfc/rfc8040>`__,
+      | can be activated by installing ``odl-restconf-nb``
        Karaf feature.
-      | This user guide uses this approach.
 
-    - | ``http://localhost:8181/rests`` is related to `RFC-8040 <https://tools.ietf.org/html/rfc8040>`__,
-      | can be activated by installing ``odl-restconf-nb-rfc8040``
-       Karaf feature.
-
-    | In case of `RFC-8040 <https://tools.ietf.org/html/rfc8040>`__
-     resources for configuration and operational datastores start
+    | Resources for configuration and operational datastores start
      ``/rests/data/``,
     | e. g. GET
      http://localhost:8181/rests/data/network-topology:network-topology
@@ -88,8 +82,7 @@ focuses on RESTCONF.
      http://localhost:8181/rests/data/network-topology:network-topology?content=nonconfig
      for operational datastore.
 
-    | Also in case of `RFC-8040 <https://tools.ietf.org/html/rfc8040>`__,
-     if a data node in the path expression is a YANG leaf-list or list
+    | Also if a data node in the path expression is a YANG leaf-list or list
      node, the path segment has to be constructed by having leaf-list or
      list node name, followed by an "=" character, then followed by the
      leaf-list or list value. Any reserved characters must be
@@ -97,14 +90,7 @@ focuses on RESTCONF.
     | e. g. GET
      http://localhost:8181/rests/data/network-topology:network-topology/topology=topology-netconf?content=config
      for retrieving data from configuration datastore for
-     topology-netconf value of topology list is equivalent to the deprecated request
-    | |ss| GET |se|
-     http://localhost:8181/restconf/config/network-topology:network-topology/topology/topology-netconf,
-     which is related to `draft-bierman-netconf-restconf-02
-     <https://tools.ietf.org/html/draft-bierman-netconf-restconf-02>`__.
-
-    Examples in the `Spawning new NETCONF connectors`_ section include both bierman02 and rfc8040
-    formats
+     topology-netconf value of topology list.
 
 Preconditions
 ^^^^^^^^^^^^^
@@ -114,7 +100,7 @@ Preconditions
 2. In Karaf, you must have the ``odl-netconf-topology`` or
    ``odl-netconf-clustered-topology`` feature installed.
 
-3. Feature ``odl-restconf`` must be installed
+3. Feature ``odl-restconf-nb`` must be installed
 
 Spawning new NETCONF connectors
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -125,8 +111,6 @@ to RESTCONF:
 .. list-table::
    :widths: 1 5
 
-   * - bierman02
-     - http://localhost:8181/restconf/config/network-topology:network-topology/topology/topology-netconf/node/new-netconf-device
    * - rfc8040
      - http://localhost:8181/rests/data/network-topology:network-topology/topology=topology-netconf/node=new-netconf-device
 
@@ -136,8 +120,6 @@ without specifying the node in the URL:
 .. list-table::
    :widths: 1 5
 
-   * - bierman02
-     - http://localhost:8181/restconf/config/network-topology:network-topology/topology/topology-netconf
    * - rfc8040
      - http://localhost:8181/rests/data/network-topology:network-topology/topology=topology-netconf
 
@@ -214,16 +196,16 @@ to be done with a PUT request because the node already exists. A POST
 request will fail for that reason.
 
 Additionally, a PATCH request can be used to modify an existing
-configuration. Currently, only yang-patch (`RFC-8072 <https://tools.ietf.org/html/rfc8072>`__)
+configuration. Currently, only yang-patch (`RFC-8072 <https://www.rfc-editor.org/rfc/rfc8072>`__)
 is supported. The URL would be the same as the above PUT examples.
 Using JSON for the body, the headers needed for the request would
 be:
 
 Headers:
 
--  Accept: application/yang.patch-status+json
+-  Accept: application/yang-data+json
 
--  Content-Type: application/yang.patch+json
+-  Content-Type: application/yang-patch+json
 
 Example JSON payload to modify the password entry:
 
@@ -260,8 +242,6 @@ device:
 .. list-table::
    :widths: 1 5
 
-   * - bierman02
-     - http://localhost:8181/restconf/config/network-topology:network-topology/topology/topology-netconf/node/new-netconf-device
    * - rfc8040
      - http://localhost:8181/rests/data/network-topology:network-topology/topology=topology-netconf/node=new-netconf-device
 
@@ -453,10 +433,10 @@ Reading data from the device
 Just invoke (no body needed):
 
 GET
-http://localhost:8080/restconf/operational/network-topology:network-topology/topology/topology-netconf/node/new-netconf-device/yang-ext:mount/
+http://localhost:8181/rests/data/network-topology:network-topology/topology=topology-netconf/node=new-netconf-device/yang-ext:mount?content=nonconfig
 
 This will return the entire content of operation datastore from the
-device. To view just the configuration datastore, change **operational**
+device. To view just the configuration datastore, change **nonconfig**
 in this URL to **config**.
 
 Writing configuration data to the device
@@ -470,7 +450,7 @@ In fact this request comes from the tutorial dedicated to the
 **ncmount** tutorial app.
 
 POST
-http://localhost:8181/restconf/config/network-topology:network-topology/topology/topology-netconf/node/new-netconf-device/yang-ext:mount/Cisco-IOS-XR-ifmgr-cfg:interface-configurations
+http://localhost:8181/rests/data/network-topology:network-topology/topology=topology-netconf/node=new-netconf-device/yang-ext:mount/Cisco-IOS-XR-ifmgr-cfg:interface-configurations
 
 ::
 
@@ -506,7 +486,7 @@ shows how to invoke the get-schema RPC (get-schema is quite common among
 netconf devices). Invoke:
 
 POST
-http://localhost:8181/restconf/operations/network-topology:network-topology/topology/topology-netconf/node/new-netconf-device/yang-ext:mount/ietf-netconf-monitoring:get-schema
+http://localhost:8181/rests/operations/network-topology:network-topology/topology=topology-netconf/node=new-netconf-device/yang-ext:mount/ietf-netconf-monitoring:get-schema
 
 ::
 
@@ -518,8 +498,8 @@ http://localhost:8181/restconf/operations/network-topology:network-topology/topo
 This call should fetch the source for ietf-yang-types YANG model from
 the mounted device.
 
-Receving Netconf Device Notifications on a http client
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Receiving Netconf Device Notifications on a http client
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 Devices emit netconf alarms and notifictions on certain situtations, which can demand
 attention from Device Administration. The notifications are received as Netconf messages on an
@@ -601,6 +581,351 @@ The response suggests the http url for reading the notifications.
 
     data: <notification xmlns="urn:ietf:params:xml:ns:netconf:notification:1.0"><eventTime>2022-06-17T07:01:12.458258Z</eventTime><netconf-session-end xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-notifications"><username>root</username><source-host>127.0.0.1</source-host><termination-reason>closed</termination-reason><session-id>2</session-id></netconf-session-end></notification>
 
+Change event notification subscription tutorial
+-----------------------------------------------
+
+Subscribing to data change notifications makes it possible to obtain
+notifications about data manipulation (insert, change, delete) which are
+done on any specified **path** of any specified **datastore** with
+specific **scope**. In following examples *{odlAddress}* is address of
+server where ODL is running and *{odlPort}* is port on which
+OpenDaylight is running. OpenDaylight offers two methods for receiving notifications:
+Server-Sent Events (SSE) and WebSocket. SSE is the default notification mechanism used in OpenDaylight.
+
+SSE notifications subscription process
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In this section we will learn what steps need to be taken in order to
+successfully subscribe to data change event notifications.
+
+Create stream
+^^^^^^^^^^^^^
+
+In order to use event notifications you first need to call RPC that
+creates notification stream that you can later listen to. You need to
+provide three parameters to this RPC:
+
+-  **path**: data store path that you plan to listen to. You can
+   register listener on containers, lists and leaves.
+
+-  **datastore**: data store type. *OPERATIONAL* or *CONFIGURATION*.
+
+-  **scope**: Represents scope of data change. Possible options are:
+
+   -  BASE: only changes directly to the data tree node specified in the
+      path will be reported
+
+   -  ONE: changes to the node and to direct child nodes will be
+      reported
+
+   -  SUBTREE: changes anywhere in the subtree starting at the node will
+      be reported
+
+The RPC to create the stream can be invoked via RESTCONF like this:
+
+::
+
+    OPERATION: POST
+    URI:  http://{odlAddress}:{odlPort}/rests/operations/sal-remote:create-data-change-event-subscription
+    HEADER: Content-Type=application/json
+            Accept=application/json
+
+.. code-block:: json
+
+       {
+           "input": {
+               "path": "/toaster:toaster/toaster:toasterStatus",
+               "sal-remote-augment:datastore": "OPERATIONAL",
+               "sal-remote-augment:scope": "ONE"
+           }
+       }
+
+The response should look something like this:
+
+.. code-block:: json
+
+    {
+        "sal-remote:output": {
+            "stream-name": "data-change-event-subscription/toaster:toaster/toaster:toasterStatus/datastore=CONFIGURATION/scope=SUBTREE"
+        }
+    }
+
+**stream-name** is important because you will need to use it when you
+subscribe to the stream in the next step.
+
+.. note::
+
+    Internally, this will create a new listener for *stream-name* if it
+    did not already exist.
+
+Subscribe to stream
+^^^^^^^^^^^^^^^^^^^
+
+In order to subscribe to stream and obtain SSE location you need
+to call *GET* on your stream path. The URI should generally be
+`http://{odlAddress}:{odlPort}/rests/data/ietf-restconf-monitoring:restconf-state/streams/stream/{streamName}`,
+where *{streamName}* is the *stream-name* parameter contained in
+response from *create-data-change-event-subscription* RPC from the
+previous step.
+
+::
+
+   OPERATION: GET
+   URI: http://{odlAddress}:{odlPort}/rests/data/ietf-restconf-monitoring:restconf-state/streams/stream/data-change-event-subscription/toaster:toaster/datastore=CONFIGURATION/scope=SUBTREE
+
+The subscription call may be modified with the following query parameters defined in the RESTCONF RFC:
+
+-  `filter <https://www.rfc-editor.org/rfc/rfc8040#section-4.8.4>`__
+
+-  `start-time <https://www.rfc-editor.org/rfc/rfc8040#section-4.8.7>`__
+
+-  `end-time <https://www.rfc-editor.org/rfc/rfc8040#section-4.8.8>`__
+
+In addition, the following ODL extension query parameter is supported:
+
+:odl-leaf-nodes-only:
+  If this parameter is set to "true", create and update notifications will only
+  contain the leaf nodes modified instead of the entire subscription subtree.
+  This can help in reducing the size of the notifications.
+
+:odl-skip-notification-data:
+  If this parameter is set to "true", create and update notifications will only
+  contain modified leaf nodes without data.
+  This can help in reducing the size of the notifications.
+
+The response should look something like this:
+
+.. code-block:: json
+
+    {
+        "subscribe-to-notification:location": "http://localhost:8181/rests/notif/data-change-event-subscription/network-topology:network-topology/datastore=CONFIGURATION/scope=SUBTREE"
+    }
+
+.. note::
+
+    During this phase there is an internal check for to see if a
+    listener for the *stream-name* from the URI exists. If not, new a
+    new listener is registered with the DOM data broker.
+
+Receive notifications
+^^^^^^^^^^^^^^^^^^^^^
+
+Once you got SSE location you can now connect to it and
+start receiving data change events. The request should look something like this:
+
+::
+
+    curl -v -X GET  http://localhost:8181/rests/notif/data-change-event-subscription/toaster:toaster/toasterStatus/datastore=OPERATIONAL/scope=ONE  -H "Content-Type: text/event-stream" -H "Authorization: Basic YWRtaW46YWRtaW4="
+
+
+WebSocket notifications subscription process
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Enabling WebSocket notifications in OpenDaylight requires a manual setup before starting the application.
+The following steps can be followed to enable WebSocket notifications in OpenDaylight:
+
+1. Open the file `restconf8040.cfg`, at `etc/` folder inside your Karaf distribution.
+2. Locate the `use-sse` configuration parameter and change its value from `true` to `false`.
+3. Uncomment the `use-sse` parameter if it is commented out.
+4. Save the changes made to the `restconf8040.cfg` file.
+5. Restart OpenDaylight if it is already running.
+
+Once these steps are completed, WebSocket notifications will be enabled in OpenDaylight,
+and they can be used for receiving notifications instead of SSE.
+
+WebSocket Notifications subscription process is the same as SSE until you receive a location of WebSocket.
+You can follow steps given above and after subscribing to a notification stream over WebSocket,
+you will receive a response indicating that the subscription was successful:
+
+.. code-block:: json
+
+    {
+        "subscribe-to-notification:location": "ws://localhost:8181/rests/notif/data-change-event-subscription/network-topology:network-topology/datastore=CONFIGURATION/scope=SUBTREE"
+    }
+
+You can use this WebSocket to listen to data
+change notifications. To listen to notifications you can use a
+JavaScript client or if you are using chrome browser you can use the
+`Simple WebSocket
+Client <https://chrome.google.com/webstore/detail/simple-websocket-client/pfdhoblngboilpfeibdedpjgfnlcodoo>`__.
+
+Also, for testing purposes, there is simple Java application named
+WebSocketClient. The application is placed in the
+*/restconf/websocket-client* project. It accepts a WebSocket URI
+as and input parameter. After starting the utility (WebSocketClient
+class directly in Eclipse/InteliJ Idea) received notifications should be
+displayed in console.
+
+Notifications are always in XML format and look like this:
+
+.. code-block:: xml
+
+    <notification xmlns="urn:ietf:params:xml:ns:netconf:notification:1.0">
+        <eventTime>2014-09-11T09:58:23+02:00</eventTime>
+        <data-changed-notification xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote">
+            <data-change-event>
+                <path xmlns:meae="http://netconfcentral.org/ns/toaster">/meae:toaster</path>
+                <operation>updated</operation>
+                <data>
+                   <!-- updated data -->
+                </data>
+            </data-change-event>
+        </data-changed-notification>
+    </notification>
+
+Example use case
+~~~~~~~~~~~~~~~~
+
+The typical use case is listening to data change events to update web
+page data in real-time. In this tutorial we will be using toaster as the
+base.
+
+When you call *make-toast* RPC, it sets *toasterStatus* to "down" to
+reflect that the toaster is busy making toast. When it finishes,
+*toasterStatus* is set to "up" again. We will listen to this toaster
+status changes in data store and will reflect it on our web page in
+real-time thanks to WebSocket data change notification.
+
+Simple javascript client implementation
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+We will create simple JavaScript web application that will listen
+updates on *toasterStatus* leaf and update some element of our web page
+according to new toaster status state.
+
+Create stream
+^^^^^^^^^^^^^
+
+First you need to create stream that you are planing to subscribe to.
+This can be achieved by invoking "create-data-change-event-subscription"
+RPC on RESTCONF via AJAX request. You need to provide data store
+**path** that you plan to listen on, **data store type** and **scope**.
+If the request is successful you can extract the **stream-name** from
+the response and use that to subscribe to the newly created stream. The
+*{username}* and *{password}* fields represent your credentials that you
+use to connect to OpenDaylight via RESTCONF:
+
+.. note::
+
+    The default user name and password are "admin".
+
+.. code-block:: javascript
+
+    function createStream() {
+        $.ajax(
+            {
+                url: 'http://{odlAddress}:{odlPort}/rests/operations/sal-remote:create-data-change-event-subscription',
+                type: 'POST',
+                headers: {
+                  'Authorization': 'Basic ' + btoa('{username}:{password}'),
+                  'Content-Type': 'application/json'
+                },
+                data: JSON.stringify(
+                    {
+                        'input': {
+                            'path': '/toaster:toaster/toaster:toasterStatus',
+                            'sal-remote-augment:datastore': 'OPERATIONAL',
+                            'sal-remote-augment:scope': 'ONE'
+                        }
+                    }
+                )
+            }).done(function (data) {
+                // this function will be called when ajax call is executed successfully
+                subscribeToStream(data.output['stream-name']);
+            }).fail(function (data) {
+                // this function will be called when ajax call fails
+                console.log("Create stream call unsuccessful");
+            })
+    }
+
+Subscribe to stream
+^^^^^^^^^^^^^^^^^^^
+
+The Next step is to subscribe to the stream. To subscribe to the stream
+you need to call *GET* on
+*http://{odlAddress}:{odlPort}/rests/data/ietf-restconf-monitoring:restconf-state/streams/stream/{stream-name}*.
+If the call is successful, you get WebSocket address for this stream in
+**Location** parameter inside response header. You can get response
+header by calling *getResponseHeader(\ *Location*)* on HttpRequest
+object inside *done()* function call:
+
+.. code-block:: javascript
+
+    function subscribeToStream(streamName) {
+        $.ajax(
+            {
+                url: 'http://{odlAddress}:{odlPort}/rests/data/ietf-restconf-monitoring:restconf-state/streams/stream/' + streamName;
+                type: 'GET',
+                headers: {
+                  'Authorization': 'Basic ' + btoa('{username}:{password}'),
+                }
+            }
+        ).done(function (data, textStatus, httpReq) {
+            // we need function that has http request object parameter in order to access response headers.
+            listenToNotifications(httpReq.getResponseHeader('Location'));
+        }).fail(function (data) {
+            console.log("Subscribe to stream call unsuccessful");
+        });
+    }
+
+Receive notifications
+^^^^^^^^^^^^^^^^^^^^^
+
+Once you got WebSocket server location you can now connect to it and
+start receiving data change events. You need to define functions that
+will handle events on WebSocket. In order to process incoming events
+from OpenDaylight you need to provide a function that will handle
+*onmessage* events. The function must have one parameter that represents
+the received event object. The event data will be stored in
+*event.data*. The data will be in an XML format that you can then easily
+parse using jQuery.
+
+.. code-block:: javascript
+
+    function listenToNotifications(socketLocation) {
+        try {
+            var notificatinSocket = new WebSocket(socketLocation);
+
+            notificatinSocket.onmessage = function (event) {
+                // we process our received event here
+                console.log('Received toaster data change event.');
+                $($.parseXML(event.data)).find('data-change-event').each(
+                    function (index) {
+                        var operation = $(this).find('operation').text();
+                        if (operation == 'updated') {
+                            // toaster status was updated so we call function that gets the value of toasterStatus leaf
+                            updateToasterStatus();
+                            return false;
+                        }
+                    }
+                );
+            }
+            notificatinSocket.onerror = function (error) {
+                console.log("Socket error: " + error);
+            }
+            notificatinSocket.onopen = function (event) {
+                console.log("Socket connection opened.");
+            }
+            notificatinSocket.onclose = function (event) {
+                console.log("Socket connection closed.");
+            }
+            // if there is a problem on socket creation we get exception (i.e. when socket address is incorrect)
+        } catch(e) {
+            alert("Error when creating WebSocket" + e );
+        }
+    }
+
+The *updateToasterStatus()* function represents function that calls
+*GET* on the path that was modified and sets toaster status in some web
+page element according to received data. After the WebSocket connection
+has been established you can test events by calling make-toast RPC via
+RESTCONF.
+
+.. note::
+
+    for more information about WebSockets in JavaScript visit `Writing
+    WebSocket client
+    applications <https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications>`__
 
 Netconf-connector + Netopeer
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -614,23 +939,23 @@ Netopeer installation
 
 A `Docker <https://www.docker.com/>`__ container with netopeer will be
 used in this guide. To install Docker and start the `netopeer
-image <https://index.docker.io/u/dockeruser/netopeer/>`__ perform
+image <https://hub.docker.com/r/sysrepo/sysrepo-netopeer2>`__ perform
 following steps:
 
-1. Install docker http://docs.docker.com/linux/step_one/
+1. Install docker https://docs.docker.com/get-started/
 
 2. Start the netopeer image:
 
    ::
 
-       docker run --rm -t -p 1831:830 dockeruser/netopeer
+       docker run -it --name sysrepo -p 830:830 --rm sysrepo/sysrepo-netopeer2:latest
 
 3. Verify netopeer is running by invoking (netopeer should send its
    HELLO message right away:
 
    ::
 
-       ssh root@localhost -p 1831 -s netconf
+       ssh root@localhost -p 830 -s netconf
        (password root)
 
 Mounting netopeer NETCONF server
@@ -658,7 +983,7 @@ After netopeer is mounted successfully, its configuration can be read
 using RESTCONF by invoking:
 
 GET
-http://localhost:8181/restconf/config/network-topology:network-topology/topology/topology-netconf/node/netopeer/yang-ext:mount/
+http://localhost:8181/rests/data/network-topology:network-topology/topology=topology-netconf/node=netopeer/yang-ext:mount?content:config
 
 Northbound (NETCONF servers)
 ----------------------------
@@ -691,7 +1016,7 @@ OpenDaylight provides 2 types of NETCONF servers:
     Since Nitrogen release, there is performance regression in NETCONF
     servers accepting SSH connections. While opening a connection takes
     less than 10 seconds on Carbon, on Nitrogen time can increase up to
-    60 seconds. Please see https://bugs.opendaylight.org/show_bug.cgi?id=9020
+    60 seconds. Please see https://jira.opendaylight.org/browse/ODLPARENT-112
 
 NETCONF server for config-subsystem
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -702,16 +1027,16 @@ NETCONF manner.
 
 In terms of RFCs, these are supported:
 
--  `RFC-6241 <http://tools.ietf.org/html/rfc6241>`__
+-  `RFC-6241 <https://www.rfc-editor.org/rfc/rfc6241>`__
 
--  `RFC-5277 <https://tools.ietf.org/html/rfc5277>`__
+-  `RFC-5277 <https://www.rfc-editor.org/rfc/rfc5277>`__
 
--  `RFC-6470 <https://tools.ietf.org/html/rfc6470>`__
+-  `RFC-6470 <https://www.rfc-editor.org/rfc/rfc6470>`__
 
    -  (partially, only the schema-change notification is available in
       Boron release)
 
--  `RFC-6022 <https://tools.ietf.org/html/rfc6022>`__
+-  `RFC-6022 <https://www.rfc-editor.org/rfc/rfc6022>`__
 
 For regular users it is recommended to use RESTCONF + the
 controller-config loopback mountpoint instead of using pure NETCONF. How
@@ -728,11 +1053,11 @@ and rpcs that are supported by MD-SAL.
 
 In terms of RFCs, these are supported:
 
--  `RFC-6241 <http://tools.ietf.org/html/rfc6241>`__
+-  `RFC-6241 <https://www.rfc-editor.org/rfc/rfc6241>`__
 
--  `RFC-6022 <https://tools.ietf.org/html/rfc6022>`__
+-  `RFC-6022 <https://www.rfc-editor.org/rfc/rfc6022>`__
 
--  `draft-ietf-netconf-yang-library-06 <https://tools.ietf.org/html/draft-ietf-netconf-yang-library-06>`__
+-  `RFC-7895 <https://www.rfc-editor.org/rfc/rfc7895>`__
 
 Notifications over NETCONF are not supported in the Boron release.
 
@@ -780,7 +1105,7 @@ Now the MD-SAL’s datastore can be read over RESTCONF via NETCONF by
 invoking:
 
 GET
-http://localhost:8181/restconf/operational/network-topology:network-topology/topology/topology-netconf/node/controller-mdsal/yang-ext:mount
+http://localhost:8181/rests/data/network-topology:network-topology/topology=topology-netconf/node=controller-mdsal/yang-ext:mount?content:nonconfig
 
 .. note::
 
@@ -868,7 +1193,7 @@ XML
 ::
 
     <yang-library xmlns="urn:opendaylight:netconf-node-topology">
-      <yang-library-url xmlns="urn:opendaylight:netconf-node-topology">http://localhost:8181/restconf/operational/ietf-yang-library:modules-state</yang-library-url>
+      <yang-library-url xmlns="urn:opendaylight:netconf-node-topology">http://localhost:8181/rests/data/ietf-yang-library:modules-state</yang-library-url>
       <username xmlns="urn:opendaylight:netconf-node-topology">admin</username>
       <password xmlns="urn:opendaylight:netconf-node-topology">admin</password>
     </yang-library>
@@ -909,7 +1234,7 @@ Global Configuration
 
 .. important::
   The global configuration is not a part of the `RFC 8071
-  <https://tools.ietf.org/html/rfc8071>`__ and, therefore, subject to change.
+  <https://www.rfc-editor.org/rfc/rfc8071>`__ and, therefore, subject to change.
 
 Configuring global credentials
 ''''''''''''''''''''''''''''''
@@ -926,8 +1251,8 @@ with username and passwords specified.
 
 .. code-block::
 
-    PUT
-    /restconf/config/odl-netconf-callhome-server:netconf-callhome-server/global/credentials HTTP/1.1
+    PUT HTTP/1.1
+    /rests/data/odl-netconf-callhome-server:netconf-callhome-server/global/credentials
     Content-Type: application/json
     Accept: application/json
 
@@ -963,17 +1288,15 @@ to the log.
 
 .. code-block::
 
-    POST
-    /restconf/config/odl-netconf-callhome-server:netconf-callhome-server/global HTTP/1.1
+    PUT HTTP/1.1
+    /rests/data/odl-netconf-callhome-server:netconf-callhome-server/global/accept-all-ssh-keys
     Content-Type: application/json
     Accept: application/json
 
 .. code-block:: json
 
     {
-      "global": {
         "accept-all-ssh-keys": "true"
-      }
     }
 
 Device-Specific Configuration
@@ -1001,15 +1324,15 @@ Configuring Device with Device-specific Credentials
 '''''''''''''''''''''''''''''''''''''''''''''''''''
 
 Adding specific device to the allowed list is done by creating
-``/odl-netconf-callhome-server:netconf-callhome-server/allowed-devices/device/{device}``
+``/odl-netconf-callhome-server:netconf-callhome-server/allowed-devices/device={device}``
 with device-id and connection parameters inside the ssh-client-params container.
 
 *Configuring Device with Credentials*
 
 .. code-block::
 
-    PUT
-    /restconf/config/odl-netconf-callhome-server:netconf-callhome-server/allowed-devices/device/example HTTP/1.1
+    PUT HTTP/1.1
+    /rests/data/odl-netconf-callhome-server:netconf-callhome-server/allowed-devices/device=example
     Content-Type: application/json
     Accept: application/json
 
@@ -1023,7 +1346,7 @@ with device-id and connection parameters inside the ssh-client-params container.
             "username": "example",
             "passwords": [ "password" ]
           },
-          "ssh-host-key": "AAAAB3NzaC1yc2EAAAADAQABAAABAQDHoH1jMjltOJnCt999uaSfc48ySutaD3ISJ9fSECe1Spdq9o9mxj0kBTTTq+2V8hPspuW75DNgN+V/rgJeoUewWwCAasRx9X4eTcRrJrwOQKzb5Fk+UKgQmenZ5uhLAefi2qXX/agFCtZi99vw+jHXZStfHm9TZCAf2zi+HIBzoVksSNJD0VvPo66EAvLn5qKWQD4AdpQQbKqXRf5/W8diPySbYdvOP2/7HFhDukW8yV/7ZtcywFUIu3gdXsrzwMnTqnATSLPPuckoi0V2jd8dQvEcu1DY+rRqmqu0tEkFBurlRZDf1yhNzq5xWY3OXcjgDGN+RxwuWQK3cRimcosH"
+          "host-key": "AAAAB3NzaC1yc2EAAAADAQABAAABAQDHoH1jMjltOJnCt999uaSfc48ySutaD3ISJ9fSECe1Spdq9o9mxj0kBTTTq+2V8hPspuW75DNgN+V/rgJeoUewWwCAasRx9X4eTcRrJrwOQKzb5Fk+UKgQmenZ5uhLAefi2qXX/agFCtZi99vw+jHXZStfHm9TZCAf2zi+HIBzoVksSNJD0VvPo66EAvLn5qKWQD4AdpQQbKqXRf5/W8diPySbYdvOP2/7HFhDukW8yV/7ZtcywFUIu3gdXsrzwMnTqnATSLPPuckoi0V2jd8dQvEcu1DY+rRqmqu0tEkFBurlRZDf1yhNzq5xWY3OXcjgDGN+RxwuWQK3cRimcosH"
         }
       }
     }
@@ -1031,15 +1354,15 @@ with device-id and connection parameters inside the ssh-client-params container.
 Configuring Device with Global Credentials
 '''''''''''''''''''''''''''''''''''''''''''''''''''
 
-It is possible to omit 'username' and 'password' for ssh-client-params,
+It is possible to omit ``username`` and ``password`` for ssh-client-params,
 in such case values from global credentials will be used.
 
 *Example of configuring device*
 
 .. code-block::
 
-    PUT
-    /restconf/config/odl-netconf-callhome-server:netconf-callhome-server/allowed-devices/device/example HTTP/1.1
+    PUT HTTP/1.1
+    /rests/data/odl-netconf-callhome-server:netconf-callhome-server/allowed-devices/device=example
     Content-Type: application/json
     Accept: application/json
 
@@ -1057,7 +1380,7 @@ in such case values from global credentials will be used.
 Deprecated configuration models for devices accessed with SSH protocol
 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
 
-With `RFC 8071 <https://tools.ietf.org/html/rfc8071>`__ alignment and adding
+With `RFC 8071 <https://www.rfc-editor.org/rfc/rfc8071>`__ alignment and adding
 support for TLS transport following configuration models has been marked
 deprecated.
 
@@ -1068,8 +1391,8 @@ Configuring Device with Global Credentials
 
 .. code-block::
 
-    PUT
-    /restconf/config/odl-netconf-callhome-server:netconf-callhome-server/allowed-devices/device/example HTTP/1.1
+    PUT HTTP/1.1
+    /rests/data/odl-netconf-callhome-server:netconf-callhome-server/allowed-devices/device=example
     Content-Type: application/json
     Accept: application/json
 
@@ -1093,8 +1416,8 @@ device-specific configuration. Format is same as in global credentials.
 
 .. code-block::
 
-    PUT
-    /restconf/config/odl-netconf-callhome-server:netconf-callhome-server/allowed-devices/device/example HTTP/1.1
+    PUT HTTP/1.1
+    /rests/data/odl-netconf-callhome-server:netconf-callhome-server/allowed-devices/device=example
     Content-Type: application/json
     Accept: application/json
 
@@ -1126,8 +1449,8 @@ storing them within the netconf-keystore.
 
 .. code-block::
 
-    POST
-    /rests/operations/netconf-keystore:add-keystore-entry HTTP/1.1
+    POST HTTP/1.1
+    /rests/operations/netconf-keystore:add-keystore-entry
     Content-Type: application/json
     Accept: application/json
 
@@ -1149,8 +1472,8 @@ storing them within the netconf-keystore.
 
 .. code-block::
 
-    POST
-    /rests/operations/netconf-keystore:add-private-key HTTP/1.1
+    POST HTTP/1.1
+    /rests/operations/netconf-keystore:add-private-key
     Content-Type: application/json
     Accept: application/json
 
@@ -1174,8 +1497,8 @@ storing them within the netconf-keystore.
 
 .. code-block::
 
-    POST
-    /rests/operations/netconf-keystore:add-trusted-certificate HTTP/1.1
+    POST HTTP/1.1
+    /rests/operations/netconf-keystore:add-trusted-certificate
     Content-Type: application/json
     Accept: application/json
 
@@ -1205,8 +1528,8 @@ among the allowed devices.
 
 .. code-block::
 
-    PUT
-    /restconf/config/odl-netconf-callhome-server:netconf-callhome-server/allowed-devices/device/example-device HTTP/1.1
+    PUT HTTP/1.1
+    /rests/data/odl-netconf-callhome-server:netconf-callhome-server/allowed-devices/device=example-device
     Content-Type: application/json
     Accept: application/json
 
@@ -1290,11 +1613,79 @@ Next advantages:
 
 .. note::
 
-  More information about fields query parameter: `RFC 8071 <https://tools.ietf.org/html/rfc8040#section-4.8.3>`__
+  More information about fields query parameter: `RFC 8071 <https://www.rfc-editor.org/rfc/rfc8040#section-4.8.3>`__
 
 Preparation of data
 ~~~~~~~~~~~~~~~~~~~
 
+For demonstration, we will define next YANG model:
+
+::
+
+    module test-module {
+        yang-version 1.1;
+        namespace "urn:opendaylight:test-module";
+        prefix "tm";
+        revision "2023-02-16";
+
+        container root {
+            container simple-root {
+                leaf leaf-a {
+                    type string;
+                }
+                leaf leaf-b {
+                    type string;
+                }
+                leaf-list ll {
+                    type string;
+                }
+                container nested {
+                    leaf sample-x {
+                        type boolean;
+                    }
+                    leaf sample-y {
+                        type boolean;
+                    }
+                }
+            }
+
+            container list-root {
+                leaf branch-ab {
+                    type int32;
+                }
+                list top-list {
+                    key "key-1 key-2";
+                    ordered-by user;
+                    leaf key-1 {
+                        type string;
+                    }
+                    leaf key-2 {
+                        type string;
+                    }
+                    container next-data {
+                        leaf switch-1 {
+                            type empty;
+                        }
+                        leaf switch-2 {
+                            type empty;
+                        }
+                    }
+                    list nested-list {
+                        key "identifier";
+                        leaf identifier {
+                            type string;
+                        }
+                        leaf foo {
+                            type int32;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+Follow the :doc:`testtool` instructions to save this schema and run it with testtool.
+
 Mounting NETCONF device that runs on NETCONF testtool:
 
 .. code-block:: bash
@@ -1307,7 +1698,7 @@ Mounting NETCONF device that runs on NETCONF testtool:
           {
               "node-id": "testtool",
               "netconf-node-topology:host": "127.0.0.1",
-              "netconf-node-topology:port": 36000,
+              "netconf-node-topology:port": 17830,
               "netconf-node-topology:keepalive-delay": 100,
               "netconf-node-topology:tcp-only": false,
               "netconf-node-topology:username": "admin",