Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

RESTful API Design Specification

Issues and Decisions

#IssueNotesDecision
1How will hostname and port be provided when DMI-Plugin dmiPlugin register itself and its list of cmHandles with NCMP

The team thinks that the information should instead be provided in the form of a ‘host-name’ and a ‘port’  (there was some debate on service-name v. host-name but it was settled on host-name)


e.g. "dmi-plugindmiPlugin" : { <host-name>,  <port> }


Where the host-name is unique. (the DB might assign an internal unique ID for each entry but that is just for indexing and x-referencing in a relation DB and this ID is not to be used/ exposed externally)

Instead of using ‘host-names’ and ‘ports’ parameters between java applications when in the cloud all we need is ‘service-names’ . The mapping of service-names to hosts and ports is done as part of the cloud configuration, in our case Kubernetes. And these are dynamic! The client application can then use a simple dns-lookup to connect to an instance of the service.

Using service names also allows any plugin to use implement scaling as they see fit e.g. partitioning


For the ONAP DMI Plugin which initial have only 1 instance we can simply hard-code the service-name and us the same name in the Kubernetes configuration e.g. “onap.cps.dmi-plugindmiPlugin"
2Additional information in request body duplicates cmHandleId this is redundant informationSuggested to remove from request body to avoid possible error scenarios.Only the one with the additionalInformation is needed and remove body
3No need for Sync method, this is basic standard read operation at the root level for that cm-handlecmHandle

4Use include 'location' property when request yang-module sourcesSuggestion: do include it in the request but allow DMI-Plugin dmiPlugin to decide to use it or now. Location (this leaf is called schema in older RFC7895) is not mandatory to support in YANG library and nodes may not include it. Another alternative presumably used also by ODL itself is the <get-schema> RPC. The key difference is that the YANG module definition is sent directly over the NETCONF channel, not requiring separate file servers and clients. So this is maybe one more reason that the ONAP DMI plugin currently doesn’t need the location attribute.

Location is not needed for any plugin and could only lead to ambiguity therefore will NOT be included in this request

DMI URI

DMI URI format to follow below pattern Sandeep Shah

<OP>dmi/<v{v-number}>/ch/<cm-handle>/<data|operations|dmi-action>/ds/{datastore}/[rp:]<resource-path>?<query>

...

5Inconsistent use of "Operation" and/or HTTP Methods to distinguish write operationsCurrently this page proposes to use "Operation=update" request body parameter for restconf "Replace" and "Patch" operations and use the HTTP (RESTFul) operation to distinguish between them. It also proposes to use PUT  HTTP for Read and Delete operations (sad) Basically a very confusing an unintuitive use of HTTP operations to distinguish ambiguous operations that instead easily could be defined by just using the 'operation' field in the request body.

Proposal Toine: For Consistent (restful) design I would suggest to think as the operation to DMI-Plugin (always with body) as "creating a new order to do something" toward DMI-Plugin. Ie always a HTTP POST (or PUT?) operation. The "operation " in the body can simple be extended to include both "update" and "patch" as required. If the 'operation' is NOT supplied "read" wil be assumed as the default operation

See also CPS-NCMP - DMI - SDNC Request and Response Mapping


Proposal agreed by stakeholders in meeting  

  • Only 'POST' method needs to be supported
  • use term 'Update' instead of 'replace'

DMI URI

Below table shows the proposed interface, actual implementation might deviate from this but can be accessed from

DMI URI format to follow below pattern

<OP>dmi/<v{vNumber}>/ch/<cmHandle>/<data|operations|dmiAction>/ds/<datastore>/[rp:]<resourcePath>?<query>

URIMandatory or OptionalDescription
<OP>mandatorythe HTTP method
dmimandatorythe dmi root resource
<v{vNumber}>mandatoryversion of the dmi interface is the target resource URI is the query parameter list
<cmHandle>mandatoryunique (string) identifier of a yang tree instance.
<data|operations|dmiAction>mandatoryyang data, rpc operation or a (non-modeled) dmi action
{datastore}mandatorymandatory datastore
<resourcePath>optionalthe path expression identifying the resource that is
being accessed by the operation. If this field is not
present, then the target resource is the API itself.
<query>optionalthe set of parameters associated with the RESTCONF message;
see Section 3.4 of [RFC3986]. RESTCONF parameters have 
the familiar form of "name=value" pairs. Most query parameters are
optional to implement by the server and optional to use by the client. Each optional query parameter is identified by a URI

NCPS-NCMP - DMI Plugin Write Request Flow

See CPS-NCMP - DMI - SDNC Request and Response Mapping

Datastore

If the cmhandle metadata indicates that data is not synched in CPS then the request is forwarded to the dmiPlugin

RESTCONF/NETCONF relationship

Image Added



REST Data API

The DMI APIs for data access are similar to corresponding NCMP APIs. The following list is a summary of the main differences:

  1. The URI prefix is /dmi instead of /ncmp.
  2. For non-passthrough datastores, the resource path will be converted from cpsPath to RESTConfPath
  3. The body for each request will contain additional information and any data provided on the NCMP interface (write operations) will be embedded in a larger JSON structure as described in example below.

  4. Since all requests will have a message body, in some cases the HTTP method will be different to allow passing data. Thus POST can be used, the actual operation will be read from the body.

Excerpt

Request Format for Data Access

Code Block
languagexml
titlerequest body
{
  “operation”: “<operation>”,         // Valid operations are: “create”, “read”, “update”, “patch” and “delete”.
                                      
  "dataType": "<dataType>",           // e.g. "application/yang.data"

    “data”: {                           // Embedded data as a String.
    <data>                            // required for create and update operations. Optional filter-data for read-operations
  },

  “cmHandleProperties”: {           // Additional properties for CM handle previously added by DMI plugin and stored in NCMP.
    <properties>
  }
}




Expand
titleAPI details

Below table shows the proposed interface, actual implementation might deviate from this but can be accessed from


UsecaseREST MethodURI
1Add a data resource for a cmHandlePOST

{dmiRoot}/dmi/v1/ch/<cmhandle>

Datastore

If the cmhandle metadata indicates that data is not synched in CPS then the request is forwarded to the dmi-plugin

RESTCONF/NETCONF relationship

Image Removed

REST Data API

{dmi-root}/dmi/v1/ch/<cm-handle>operationalresource-identifier}?fields={fields-expression}
Expand
titleAPI details

*The examples in the below table refer back to the NCMP interface. The same differences apply to the data calls:

  • The  URI prefix /dmi instead of /ncmp
  • The request body for each request wil include the 'additional properties' as stored for each cm-handle (hence the need for PUT over GET method)  e.g. 

    Code Block
    languagexml
    titleRequest Body
    Request Body : {
        "additionalProperties" : { [ "subsystemId" : "system-001" ] }
    }

    {dmi-root}/dmi/v1/ch/<cm-handle>/data/ds/ncmp-datastore:running/{resource-identifier}

    Content-Type: application/json

    "data" payload : yang-patch+json

    {dmi-root}/dmi/v1/ch/<cm-handle>/data/ds/ncmp-datastore:operational/{resource-identifier}/{action}

    input: {
             "param1Name" :"param1Value”,
              "param2Name" : "param2Value”

    }

    Note : If the "action" statement has no "input" section, the request message MUST NOT include a message-body

    {dmiroot}/dmi/v1/ch/<cm-handle>/data/ds/ncmp-datastore:operational/{resource-identifier}?fields={fields-expression}

    UsecaseREST MethodURIExample*
    1Add a data resource for a cmHandlePOST

    {dmi-root}/dmi/v1/ch/<cmhandle>/data/ds/ncmp-datastore:running/{parent-data-resource-identifier}

    {
    <new-yang-data-resource>
    }

    Content-Type: application/json

    "data" payload : yang-data+json

    see example 4 CPS-391Spike: Define and Agree NCMP REST Interface#RESTAPI
    2Delete a data resource for a cmHandlePUT{dmi-root}/dmi/v1/ch/<cm-handle>/data/ds/ncmp-datastore:running/{resource-identifier}see example 7 CPS-391Spike: Define and Agree NCMP REST Interface#RESTAPI
    3Patch a data resource for a cmHandlePATCH

    {dmi-root}/dmi/v1/ch/<cm-handle>/data/ds/ncmp-datastore:running/{resource-identifier}

    {
    <yang-data-for-merging>
    }

    Content-Type: application/json

    "data" payload : yang-data+json

    see example 5 CPS-391Spike: Define and Agree NCMP REST Interface#RESTAPI
    4Patch multiple child resources for a single cmHandlePATCHsee example 6 CPS-391Spike: Define and Agree NCMP REST Interface#RESTAPI5Execute a yang action on a cmhandle instancePOSTsee example 10 CPS-391Spike: Define and Agree NCMP REST Interface#RESTAPI
    6Execute an rpc operationPOST

    {dmi-root}/dmi/v1/operations/ch/<cm-handle>/ds/ncmp-datastore:operational/ {module-name}:{action}

    { input: {
                "param1Name" : "param1Value”,
                 "param2Name" : "param2Value”
    } }

    Note: If there is no "input" section, the request MUST NOT include a message-body

    see example 11 CPS-391Spike: Define and Agree NCMP REST Interface#RESTAPI
    7Read a filtered set of data under a data resource for a cmHandlePUT
    OptionDescription
    fieldsRequest a subset of the target
    resource contents
    see example 2 CPS-391Spike: Define and Agree NCMP REST Interface#RESTAPI8Read data resources with specified fields under a given data resource for a given cmHandlePUT

    /data/ds/ncmp-datastore:

    running/{

    OptionDescription
    fieldsRequest a subset of the target
    resource contents
    see example 12 CPS-391Spike: Define and Agree NCMP REST Interface#RESTAPI

    parentDataResourceIdentifier}

    {
    <new-yang-data-resource>
    }

    Content-Type: application/json

    "data" payload : yang-data+json

    2Delete a data resource for a cmHandlePUT{dmiRoot9Get data resource with 'fileds' for a cmhandle with a given scope conditionPUT{dmi-root}/dmi/v1/ch/{cm-handle}/data/<cmHandle>/data/ds/ncmp-datastore:operationalrunning/{resourcepath}?fields={fields}&scope={scope}see example 2 CPS-391Spike: Define and Agree NCMP REST Interface#RESTAPI10Read descendant nodes to a given depth for a given cmHandlePUTresourceIdentifier}3Patch a data resource for a cmHandlePATCH

    {dmiRoot{dmi-root}/dmi/v1/ch/{cm-handle}<cmHandle>/data/ds/ncmp-datastore:operationalrunning/{resource-identifier}?depth={level}

    OptionDescription
    depthRequest limited sub-tree depth in
    the reply content
    If '1' then only immediate resource
    is retrieved
    If '2' then resource plus next level
    resources are retrieved
    see example 12 CPS-391Spike: Define and Agree NCMP REST Interface#RESTAPI11Replace data for a CMHandlePUT

    resourceIdentifier}

    {
    <yang-data-for-merging>
    }

    Content-Type: application/json

    "data" payload : yang-data+json

    4Patch multiple child resources for a single cmHandlePATCH

    {dmiRoot{dmi-root}/dmi/v1/ch/<cm-handle><cmHandle>/data/ds/ncmp-datastore:running<dsName>/{resource-identifierresourceIdentifier}

    {data : {


    Content-Type: application/json

    "data" payload : yang-patch+json

    5Execute a yang action on a cmhandle instancePOST

    {dmiRoot}/dmi/v1/ch/<cmHandle>/data/ds/ncmp-datastore:operational/{resourceIdentifier}/{action}


    input: {
                .... the complete tree config to be replaced

          }}

    see example 12 CPS-391Spike: Define and Agree NCMP REST Interface#RESTAPI

    DMI Inventory, Model & Data Sync API

    View file
    nameDMI NCMP Model Sync.pptx
    height150
     This presentation illustrates the API methods #1, #3 and #4 detailed below

    "param1Name" :"param1Value”,
              "param2Name" : "param2Value”

    }


    Note : If the "action" statement has no "input" section, the request message MUST NOT include a message-body

    6Execute an rpc operationPOST

    {dmiRoot}/dmi/v1/operations/ch/<cmHandle>/ds/ncmp-datastore:operational/ {module-name}:{action}

    { input: {
                "param1Name" : "param1Value”,
                 "param2Name" : "param2Value”
    } }

    Note: If there is no "input" section, the request MUST NOT include a message-body

    7Read a filtered set of data under a data resource for a cmHandlePUT

    {dmiroot}/dmi/v1/ch/<cmHandle>/data/ds/ncmp-datastore:operational/{resourceIdentifier}?fields={fields-expression}

    OptionDescription
    fieldsRequest a subset of the target
    resource contents


    8Read data resources with specified fields under a given data resource for a given cmHandlePUT

    {dmiRoot}/dmi/v1/ch/<cmHandle>/data/ds/ncmp-datastore:operational/{resourceIdentifier}?fields={fields-expression}


    OptionDescription
    fieldsRequest a subset of the target
    resource contents


    9Get data resource with 'fileds' for a cmhandle with a given scope conditionPUT{dmiRoot}/dmi/v1/ch/{cmHandle}/data/ds/ncmp-datastore:operational/{resourcepath}?fields={fields}&scope={scope}
    10Read descendant nodes to a given depth for a given cmHandlePUT

    {dmiRoot}/dmi/v1/ch/{cmHandle}/data/ds/ncmp-datastore:operational/{resourceIdentifier}?depth={level}


    OptionDescription
    depthRequest limited sub-tree depth in
    the reply content
    If '1' then only immediate resource
    is retrieved
    If '2' then resource plus next level
    resources are retrieved


    11Replace data for a CMHandlePUT

    {dmiRoot}/dmi/v1/ch/<cmHandle>/data/ds/ncmp-datastore:running/{resourceIdentifier}

    {data : {

                .... the complete tree config to be replaced

          }}


    DMI Inventory, Model & Data Sync API

    View file
    nameDMI NCMP Model Sync.pptx
    height150
     This presentation illustrates the API methods #1, #3 and #4 detailed below


    Scenario : DMI notifies NCMP of new cmhandles
    Method : POST
    URI : {ncmp-root}/ncmp-dmi/v1/ch/
    Header :
    Content-Type: application/json
    Request Body : {
    "dmi-plugin" : "onap.dmi.plugin",
    "created-cm-handles" : [ { "cmhandle" : "rf4er5454",
    "additionalProperties" :
    { "subsystemId" : "system-001" }
    }, {..} ],
    "updated-cm-handles" : [ .. ],
    "removed-cm-handles" : [ "node-1", "node-2" , ... ]
    }Scenario : Get all cmhandles from NCMP for a given dmi-plugin. May be used
    for conciliation
    Method : GET
    URI : {ncmp-root}/ncmp-dmi/v1/dmi-plugins/{dmi-plugin}/ch
    Header :
    Content-Type: application/json
    Success Response :
    HTTP/1.1 200 Ok
    Date: Thu, 26 Jan 2021 20:56:30 GMT
    Server: example-server
    { "cmhandles" : [ {
    "cmhandle" : "node-1",
    "additionalProperties" : { "subSystem" : "system-001" }
    } ]
    }3
    Expand
    titleAPI Details

    Below table shows the proposed interface, actual implementation might deviate from this but can be accessed from

    *For response output, where applicable the yang-library format and conventions are used 'as is'  or extended

    #Use CaseRest MethodURIExample*
    1
    Expand
    titleAPI Details

    *For response output, where applicable the yang-library format and conventions are used 'as is'  or extended

    #Use CaseRest MethodServiceURIExample*
    1DMI notifies NCMP of new , deleted or changed cmhandles DMI Plugin NCMP. Including initial registration

    POST

    json attributes:

    • "dmi-plugin" resolvable servicename
    • "created-cm-handles" used for initial cm handle registrations or subsequent
      cmhandle creations
    • "updated-cm-handles"
      Used for updates to cmhandles. Same structure as for create handles
    • "removed-cm-handles"  array of cmhandles that have been deleted
      from the network (no additional properties
    NCMP

    {ncmp-root}/ncmp-dmi/v1/ch/

    2Get all the registered cmhandles for a given pluginGETNCMP{ncmp-root}/ncmp-dmi/v1/dmi-plugins/{plugin-id}/ch

    Get module set for a cmhandle


    POST
    DMI-Plugin
    {
    dmi-root
    dmiRoot}/dmi/v1/ch/cmhandle
    -001/modules

    Header :
    Content-Type: application/json

    Body :
    { "additionalProperties" : {"subSystem" : "subsystem-001"}}
    Response:
    {
    "ietf-yang-library:yang-library" : [
    { "module-set" : [ {
    "name" : "sample-module",
    "module" : [
    {
    "name" : "_3gpp-nr-nrm-nrsectorcarrier",
    "revision" : "2020-12-09",
    "namespace" : "urn:3gpp:sa5:_3gpp-nr-nrm-nrnetwork-nrsectorcarrier",
    }
    ...
    }4Get yang module source for a list of modulesPOSTDMI-Plugin

    {dmi-root}/dmi/v1/ch/<cm-handle>model

    DMI PLugin will make multiple requests to xNF and combine the result in a list

    -001/modules

    Header :
    Content-Type: application/json


    Code Block
    languagexml
    titleRequest Body
    {
      "operation": "read",
        "cmHandleProperties ": {
          "subSystemId": "system-001"
        }
      }
    }

    Code Block
    languagexml
    titleResponse Body
    Response:  
         "schemas": [
                        {
                          "moduleName": "example-identifier",
                          "revision": "example-version",
                          "namespace": "example-namespace"
                        },
    					{
    						...
    					}
                      ]
                    }

    2Get yang module source for a list of modulesPOST

    {dmiRoot}/dmi/v1/ch/<cmHandle>/moduleResources


    DMI Plugin will make multiple requests to xNF and combine the result in a list


    Code Block
    languagexml
    titleRequest Body
    {
      "operation": "read",
    	"dataType": "application/json",
        "data": {
           "modules": [
            {
              "name": "pnf-sw-upgrade",
              "revision": "2019-12-03"
            }
          ]
        },
        "cmHandleProperties": {
          "subSystemId": "system-001"
        }
    }


    Response: a list yang module references and source for each

    Code Block
    languagexml
    titleResponse Body
    [ {
    "name" : "pnf-sw-upgrade",
    "revision" : "2019-12-03",
    "yang-source": "some-source"
    Body :
    { "additionalProperties" : {"subSystem" : "subsystem-001"}
    "modules" : [ { "namespace": "urn:3gpp:sa5:_3gpp-nr-nrm-nrnetwork-nrsectorcarrier", "name": "_3gpp-nr-nrm-nrsectorcarrier", "revision": "2020-12-09" } , { ... } ] }
    Response: a list yang module references and source for each
    { [
    {
    "name" : "_3gpp-nr-nrm-nrsectorcarrier",
    "revision" : "2020-12-09",
    "namespace": "urn:3gpp:sa5:_3gpp-nr-nrm-nrnetwork-nrsectorcarrier" }
    ,
    "yang-source": "module pnf-sw-upgrade {\n namespace \"http://onap.org/pnf-sw-upgrade\";\n prefix upgrade;\n\n import ietf-yang-types {\n prefix yang;\n }
    \n\n revision 2019-12-03 {\n description\n \"initial version\";\n }\n\n container software-upgrade {\n list upgrade-package {\n key \"id\";\n leaf id {\n type string;\n }
    \n\n leaf current-status {\n type enumeration {\n enum \"CREATED\";\n enum \"INITIALIZED\";\n enum \"DOWNLOAD_IN_PROGRESS\";\n enum \"DOWNLOAD_COMPLETED\";\n
    enum \"ACTIVATION_IN_PROGRESS\";\n enum \"ACTIVATION_COMPLETED\";\n }\n description\n \"List of possible states of the upgrade\";\n }\n\n leaf state-change-time
    {\n type yang:date-and-time;\n mandatory false;\n description\n \"Date and time of the last state change.\";\n }\n\n leaf action {\n type enumeration
    {\n enum \"NONE\";\n enum \"PRE_CHECK\";\n enum \"DOWNLOAD_NE_SW\";\n enum \"ACTIVATE_NE_SW\";\n enum \"CANCEL\";\n }\n mandatory false;\n description\n
    \"List of possible actions for the upgrade\";\n }\n\n leaf software-version {\n type string;\n description\n \"Possible name or release version of the UP\";\n }
    \n\n leaf uri {\n type string;\n description\n \"A URI that points to the directory where the UP can be found.\";\n }\n\n leaf user {\n type string;\n description\n
    \"Indicates the user.\";\n }\n\n leaf password {\n type string;\n description\n \"Indicates the password.\";\n }\n\n leaf user-label {\n type string;\n description\n
    \"Free-text description of the UP.\";\n }\n\n leaf node-health {\n type string;\n description\n \"Reflect Node Health Status\";\n }\n }\n }\n}"
    }
    , {...} ]

    }