X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=docs%2Fuser-guide.rst;h=5e31ff80544eddb55b8bca14015fbfd6126af9ce;hb=a661ef1b6f3d5fcaca695a28f26c46c8a54f104c;hp=12eea4d956030d5d481f35ae26f8d4f8d08bfc20;hpb=0139fd42f0e24970693b99ca773b236c71aa6c2b;p=netconf.git diff --git a/docs/user-guide.rst b/docs/user-guide.rst index 12eea4d956..5e31ff8054 100644 --- a/docs/user-guide.rst +++ b/docs/user-guide.rst @@ -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 `__. +`RFC-6241 `__. **NETCONF in OpenDaylight:.** @@ -35,13 +35,13 @@ mounted devices. In terms of RFCs, the connector supports: -- `RFC-6241 `__ +- `RFC-6241 `__ -- `RFC-5277 `__ +- `RFC-5277 `__ -- `RFC-6022 `__ +- `RFC-6022 `__ -- `draft-ietf-netconf-yang-library-06 `__ +- `RFC-7895 `__ **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 `__, - | can be activated by installing ``odl-restconf-nb-bierman02`` + - | ``http://localhost:8181/rests`` is related to `RFC-8040 `__, + | 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 `__, - | can be activated by installing ``odl-restconf-nb-rfc8040`` - Karaf feature. - - | In case of `RFC-8040 `__ - 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 `__, - 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 - `__. - - 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 `__) +configuration. Currently, only yang-patch (`RFC-8072 `__) 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: 2022-06-17T07:01:12.458258Zroot127.0.0.1closed2 +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 `__ + +- `start-time `__ + +- `end-time `__ + +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 `__. + +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 + + + 2014-09-11T09:58:23+02:00 + + + /meae:toaster + updated + + + + + + + +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 `__ Netconf-connector + Netopeer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -614,23 +939,23 @@ Netopeer installation A `Docker `__ container with netopeer will be used in this guide. To install Docker and start the `netopeer -image `__ perform +image `__ 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 `__ +- `RFC-6241 `__ -- `RFC-5277 `__ +- `RFC-5277 `__ -- `RFC-6470 `__ +- `RFC-6470 `__ - (partially, only the schema-change notification is available in Boron release) -- `RFC-6022 `__ +- `RFC-6022 `__ 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 `__ +- `RFC-6241 `__ -- `RFC-6022 `__ +- `RFC-6022 `__ -- `draft-ietf-netconf-yang-library-06 `__ +- `RFC-7895 `__ 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 :: - http://localhost:8181/restconf/operational/ietf-yang-library:modules-state + http://localhost:8181/rests/data/ietf-yang-library:modules-state admin admin @@ -909,7 +1234,7 @@ Global Configuration .. important:: The global configuration is not a part of the `RFC 8071 - `__ and, therefore, subject to change. + `__ 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 `__ alignment and adding +With `RFC 8071 `__ 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 `__ + More information about fields query parameter: `RFC 8071 `__ 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",