References
CPS-390
-
Getting issue details...
STATUS
RESTful API Design Specification
Issues and Decisions
| Issue | Notes | Decision |
---|
1 | How will hostname and port be provided when DMI-Plugin 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-plugin" : { <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-plugin" |
2 | Additional information in request body duplicates cmHandleId this is redundant information | Suggested to remove from request body to avoid possible error scenarios. | Only the one with the additionalInformation is needed and remove body |
3 | No need for Sync method, this is basic standard read operation at the root level for that cm-handle |
|
|
4 | Use include 'location' property when request yang-module sources | Suggestion: do include it in the request but allow DMI-Plugin 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>
URI | Mandatory or Optional | Description |
---|
<OP> | mandatory | the HTTP method |
dmi | mandatory | the dmi root resource |
<v{v-number}> | mandatory | version of the dmi interface is the target resource URI is the query parameter list |
<cm-handle> | mandatory | unique (string) identifier of a yang tree instance. |
<data|operations|dmi-action> | mandatory | yang data, rpc operation or a (non-modeled) api action |
{datastore} | optional | optional datastore |
<resource-path> | optional | the 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> | optional | the 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 |
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
REST Data API
API 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.
Request Body : {
"additionalProperties" : { [ "subsystemId" : "system-001" ] }
}
| Usecase | REST Method | URI | Example* |
---|
1 | Add a data resource for a cmHandle | POST | {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 |
2 | Delete a data resource for a cmHandle | PUT | {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 |
3 | Patch a data resource for a cmHandle | PATCH | {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 |
4 | Patch multiple child resources for a single cmHandle | PATCH | {dmi-root}/dmi/v1/ch/<cm-handle>/data/ds/ncmp-datastore:running/{resource-identifier}
Content-Type: application/json "data" payload : yang-patch+json | see example 6 CPS-391Spike: Define and Agree NCMP REST Interface#RESTAPI |
5 | Execute a yang action on a cmhandle instance | POST | {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 | see example 10 CPS-391Spike: Define and Agree NCMP REST Interface#RESTAPI |
6 | Execute an rpc operation | POST | {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 |
7 | | PUT | {dmiroot}/dmi/v1/ch/<cm-handle>/data/ds/ncmp-datastore:operational/{resource-identifier}?fields={fields-expression} Option | Description |
---|
fields | Request a subset of the target resource contents |
| see example 2 CPS-391Spike: Define and Agree NCMP REST Interface#RESTAPI |
8 | Read data resources with specified fields under a given data resource for a given cmHandle | PUT | {dmi-root}/dmi/v1/ch/<cm-handle>/data/ds/ncmp-datastore:operational/{resource-identifier}?fields={fields-expression}
Option | Description |
---|
fields | Request a subset of the target resource contents |
| see example 12 CPS-391Spike: Define and Agree NCMP REST Interface#RESTAPI |
9 | Get data resource with 'fileds' for a cmhandle with a given scope condition | PUT | {dmi-root}/dmi/v1/ch/{cm-handle}/data/ds/ncmp-datastore:operational/{resourcepath}?fields={fields}&scope={scope} | see example 2 CPS-391Spike: Define and Agree NCMP REST Interface#RESTAPI |
10 | Read descendant nodes to a given depth for a given cmHandle | PUT | {dmi-root}/dmi/v1/ch/{cm-handle}/data/ds/ncmp-datastore:operational/{resource-identifier}?depth={level}
Option | Description |
---|
depth | Request 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#RESTAPI |
11 | Replace data for a CMHandle | PUT | {dmi-root}/dmi/v1/ch/<cm-handle>/data/ds/ncmp-datastore:running/{resource-identifier} {data : { .... 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
API Details
# | Use Case | Rest Method | Service | URI | Example |
---|
1 | DMI notifies NCMP of new , deleted or changed cmhandles DMI Plugin NCMP. Including initial registration | POST json attributes: - "dmi-plugin" resolvable servicename
- "createdcmhandles" used for initial cm handle registrations or subsequent
cmhandle creations - "updatedcmhandles"
Used for updates to cmhandles. Same structure as for create handles
- "removedcmhandles" array of cmhandles that have been deleted
from the network (no additional properties
| NCMP | {ncmp-root}/ncmp-dmi/v1/ch/ | 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", "createdcmhandles" : [ { "cmhandle" : "rf4er5454", "additionalProperties" : { "subsystemId" : "system-001" } }, {..} ], "updatedcmhandles" : [ .. ], "removedcmhandles" : [ "node-1", "node-2" , ... ] } |
2 | Get all the registered cmhandles for a given plugin | GET | NCMP | {ncmp-root}/ncmp-dmi/v1/dmi-plugins/{plugin-id}/ch | 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 | Get module set for a cmhandle
| | DMI-Plugin | {dmi-root}/dmi/v1/ch/cmhandle-001/ | Header : Content-Type: application/json
Body : { "cmhandle" : "cmhandle-001", "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", } ... }
|
4 | Get yang module source for a list of modules | POST | DMI-Plugin | {dmi-root}/dmi/v1/model/
DMI PLugin will make multiple requests to xNF and combine the result in a list | Body : { "additionalProperties" : ["subSystem" : "subsystem-001"] "modules" : [ { "namespace": "urn:3gpp:sa5:_3gpp-nr-nrm-nrnetwork-nrsectorcarrier", "name": "_3gpp-nr-nrm-nrsectorcarrier", "revision": "2020-12-09" } , { ... } ] }
{ [ { "name" : "_3gpp-nr-nrm-nrsectorcarrier", "revision" : "2020-12-09", "namespace": "urn:3gpp:sa5:_3gpp-nr-nrm-nrnetwork-nrsectorcarrier", "name": "_3gpp-nr-nrm-nrsectorcarrier", "revision": "2020-12-09" }, "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}" }, {...} ] } |
GET Request with body
The HTTP libraries of certain languages (notably JavaScript) don’t allow GET requests to have a request body. In fact, some users are surprised that GET requests are ever allowed to have a body.
The truth is that RFC 7231—the RFC that deals with HTTP semantics and content—does not define what should happen to a GET request with a body! As a result, some HTTP servers allow it, and some—especially caching proxies—don’t.
The authors of Elasticsearch prefer using GET for a search request because they feel that it describes the action—retrieving information—better than the POST verb. However, because GET with a request body is not universally supported, the search API also accepts POST requests: }
The same rule applies to any other GET API that requires a request body.
See Elasticsearch details here for more info
yang-patch operations (see rfc8072)
"create", "delete", "insert", "merge", "move", "replace", and "remove"
YANG Data Structure Extensions
https://tools.ietf.org/html/rfc8791
References
Follow principles/patterns of RESTCONF RFC-8040 https://datatracker.ietf.org/doc/html/rfc8040
Follow principles/patterns of yang-patch RFC-8072 https://datatracker.ietf.org/doc/html/rfc8040
Follow principles/patterns of RESTCONF NMDA RFC-8527 https://datatracker.ietf.org/doc/html/rfc8527