Jump to: navigation, search

OpenDaylight Controller:MD-SAL:Restconf

How to use Restconf

How to start and access Restconf

Restconf is implemented in the sal-rest-connector artifact, which is packed into Karaf bundles/features for easy installation. After successfully starting of Karaf:

  • Install OpenDaylight's Restconf Karaf features. You can view relevant features with feature:list | grep odl-restconf, or install everything with feature:install odl-restconf-all. If you want to work with (for example) OpenFlow structures in the MD-SAL datastore, you also need to install features which contain bundles with YANG models for OpenFlow Plugin - feature:install odl-flow-model odl-flow-services.
  • Restconf is listens on port 8181 for HTTP requests. In old OpenDaylight versions (Hydrogen, pre-Karaf) Restconf listened on port 8080.
  • Restconf can be started in debug mode via karaf debug. It is then possible to connect to port 5005 for remote debugging. In old OpenDaylight versions (Hydrogen, pre-Karaf) Restconf was started in debug mode via karaf -debug and it used 8000 as its' debug port.

Available datastores

Restconf allows access to datastores in the controller. There are two datastores:

  • config - contains data inserted via controller
  • operational - contains other data

Supported data formats

Request and response data can be in XML or JSON format. XML structures according to yang are defined at: XML-YANG.

JSON structures are defined at: JSON-YANG.

The media type of request data (input) has to be set via “Content-Type” field in HTTP header with.

The media type of response data (output) has to be set in the “Accept” field in HTTP header.

Get the media types for each resource by calling the OPTIONS operation.

Restconf URI

Identifier in URI

Most of the Restconf endpoints paths (URI) use Instance Identifier. In following text it will be formatted as <identifier>. Following requirements on <identifier> has to be met:

  • it must start with <moduleName>:<nodeName> where <moduleName> is a name of the YANG module and <nodeName> is the name of the top level node in the module.
  • child nodes has to be specified in format:
    • <nodeName> - can be used everytime expect case when node with the same name was added via agumentation from external YANG model (Concretely: Module A has node A1 with child X. Module B augments node A1 by adding node X.)
    • <moduleName>:<nodeName> - is valid everytime
  • <nodeName> has to be separated by /
  • <nodeName> can represent a data node which is of list or container YANG built-in type. If the data node is a list, there must be defined keys of the list behind the data node name for example, <nodeName>/<valueOfKey1>/<valueOfKey2>.

For more details about encoding see: Restconf 02 - Encoding YANG Instance Identifiers in the Request URI

URI parameters

Uri parameters described below aren't currently working. Functionality was removed and reworked. For more details see [#Known_Issues Known issues] chapter.
There are following URI parameters supported:

  • depth - cut output data to specified level. Leaf value, leaf list value and keyed list with all keys values are specified as one level. Example of using: http://<host>:<port>/restconf/config/<module_name>:<node_name1>/<node_name2>?depth=n where n is positive integer or "unbounded" string value.
    Possible behavior if URI depth parameter is:
    • missing - data won't be pruned,
    • specified but incorrect - then exception will be raised,
    • specified and correct - data will be pruned to specified level

    Depth parameter is implemented according to 3.8.1 chapter of Restconf RFC

  • prettyPrint - is responsible for indentation of output data according to data levels. Example of using: http://<host>:<port>/restconf/config/<module_name>:<node_name1>/<node_name2>?prettyPrint=val where val is boolean value - true or false.
    Possible behavior if URI prettyPrint parameter is:
    • missing - data won't be pretty printed
    • specified but incorrect - data won't be pretty printed
    • specified and correct - data will be pretty printed

Mount point

A Node can be behind a mount point. In this case, the URI has to be in format <identifier>/yang-ext:mount/<identifier>. The first <identifier> is the path to a mount point and the second <identifier> is the path to a node behind the mount point. A URI can end in a mount point itself by using <identifier>/yang-ext:mount

More information on how to actually use mountpoints is available at: OpenDaylight_Controller:Config:Examples:Netconf

Supported operations

Restconf supports OPTIONS, GET, PUT, POST, DELETE, PATCH HTTP operations.
Each URI for rest calls must start with /restconf prefix.

HTTP operationURI linkDescriptionExample
OPTIONS /restconf Returns the XML description of the resources with the required request and response media types in Web Application Description Language (WADL)  
GET /restconf/config/<identifier>

Returns a data node from the Config datastore.

<identifier> points to concrete data node and its data will be returned
 
GET /restconf/operational/<identifier>

Returns the value of the data node from the Operational datastore.

<identifier> points to concrete data node and its data will be returned
 
PUT /restconf/config/<identifier>

Updates or creates data in the Config datastore and returns the state about success.

<identifier> points to a data node which will be updated or created

Example1

PUT http://<host>:8181/restconf/config/module1:foo/bar
Content-Type: applicaton/xml
<bar>
  …
</bar>

Example with mount point:

PUT http://<host>:8181/restconf/config/module1:foo1/foo2/
  yang-ext:mount/module2:foo/bar
Content-Type: applicaton/xml
<bar>
  …
</bar>
POST /restconf/config Creates the data if it does not exist
POST http://localhost:8181/restconf/config/
content-type: application/yang.data+json
JSON payload:
  {
    "toaster:toaster" :
    {
      "toaster:toasterManufacturer" : "General Electric",
      "toaster:toasterModelNumber" : "123",
      "toaster:toasterStatus" : "up"
    }
  }
POST /restconf/config/<identifier>

Creates the data if it does not exist in the Config datastore, and returns the state about success. <identifier> points to a data node where data must be stored. The root element of data must have the namespace (data are in XML) or module name (data are in JSON.)

Example:

POST http://<host>:8181/restconf/config/module1:foo
Content-Type: applicaton/xml/
<bar xmlns=“module1namespace”>
  …
</bar>

Example with mount point:

POST http://<host>:8181/restconf/config/
  module1:foo1/foo2/yang-ext:mount/module2:foo
Content-Type: applicaton/xml
<bar xmlns=“module2namespace”>
  …
</bar>
POST /restconf/operations/<moduleName>:<rpcName>

Invokes RPC. <moduleName>:<rpcName> - <moduleName> is the name of the module and <rpcName> is the name of the RPC in this module. The Root element of the data sent to RPC must have the name “input”. The result can be the status code or the retrieved data having the root element “output”.

Example:

POST http://<host>:8181/restconf/operations/module1:fooRpc
Content-Type: applicaton/xml
Accept: applicaton/xml
<input>
  …
</input>

The answer from the server could be:

<output>
  …
</output>

An example using a JSON payload:

POST http://<host>:8181/restconf/operations/toaster:make-toast
Content-Type: application/yang.data+json
{
  "input" :
  {
     "toaster:toasterDoneness" : "10",
     "toaster:toasterToastType":"wheat-bread" 
  }
}

Note: Even though this is a default for the toasterToastType value in the yang, you still need to define it.

DELETE /restconf/config/<identifier>

Removes the data node in the Config datastore and returns the state about success. <identifier> points to a data node which must be removed.

 
GET /restconf/streams List of all notification event streams.

Example call

GET http://<host>:8181/restconf/streams
Accept: applicaton/xml

Example of response

<streams xmlns="urn:ietf:params:xml:ns:yang:ietf-restconf">
  <stream>
    <name>opendaylight-inventory:nodes/datastore=CONFIGURATION/scope=BASE</name>
    <description>DESCRIPTION_PLACEHOLDER</description>
    <replay-support>true</replay-support>
    <replay-log-creation-timereplay-log-creation-time />
    <events />
  </stream>
</streams>
GET /restconf/streams/stream/<stream_name> Subscribes to stream_name to receive notifications from this stream Example
GET http://<host>:8181/restconf/streams/stream/
  opendaylight-inventory:nodes/datastore=CONFIGURATION/scope=BASE
PATCH /restconf/config/<identifier> PATCH edit operations on Config datastore

Example call

PATCH http://localhost:8181/restconf/config/car:cars

Example of XML payload

Content-Type: application/yang.patch+xml

Accept: application/yang.patch-status+xml

 <yang-patch xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-patch">
 <patch-id>example-patch</patch-id>
 <comment>This is example patch</comment>
 <edit>
   <edit-id>edit1</edit-id>
   <operation>create</operation>
   <target>/car-entry</target>
   <value>
     <car-entry xmlns="urn:opendaylight:params:xml:ns:yang:controller:config:sal-clustering-it:car">
       <id>0</id>
     </car-entry>
   </value>
 </edit>
 <edit>
   <edit-id>edit2</edit-id>
     <operation>delete</operation>
     <target>/car-entry/0</target>
 </edit>
 </yang-patch>

Example of JSON payload

Content-Type: application/yang.patch+json

Accept: application/yang.patch-status+json

{
  "ietf-restconf:yang-patch" : {
    "patch-id" : "0",
    "edit" : [
      {
        "edit-id" : "edit1",
        "operation" : "create",
        "target" : "/car:car-entry[car:id='0']",
        "value" : {
          "car:car-entry" : {
            "id":"0"
          }
        }
     },
     {
         "edit-id" : "edit2",
         "operation" : "delete",
         "target" : "/car:car-entry[car:id='0']"
     }
    ]
  }
}

More information is available at: Restconf RFC

Notifications

Restconf supports data change event notifications and Netconf notification streams.

Known Issues

There are several known issues associated with Restconf usage:

  • Trying to make an RPC which has no inputs returns an exception (HTTP 500 error).
    • Reason: If you have content-type defined when you make an RPC call with no input then you will be directed to a java method which expects non-null/empty input and thus fails accordingly.
    • Workaround: Removing the content-type header results in the rest call getting routed to a different java method which expects an empty body and thus there is success.
  • The cancel-toast method in the MD-SAL toaster example still fails with an exception.
  • This is a bug in either the toaster or MD-SAL core code. Essentially the cancel-toaster call returns a null future object, which the rpc caller chokes on (i.e. doesn't null check). While the simple fix is to change the toaster to return a non-null future, we should consider enhancing the RPC caller to gracefully handle null futures. No bug has been filed on this yet.
  • All query parameters appear to be ignored.
    • patches for support of depth and prettyPrint query parameters are tracked in corresponding bugs