Add first work package for REST API implementation
[anna.git] / example / diameter / launcher / resources / HELP.md
index 69f0615..8b453fa 100644 (file)
@@ -94,7 +94,7 @@ All the subsequent operations will be forced to work with this node, which makes
 
 Empty parameter will show the current configuration.
 
-**node_auto**
+**node-auto**
 
 Returns to the default behaviour (smart node selection).
 Depending on the operation, this could imply a global action scope, affecting to all the registered hosts.
@@ -125,14 +125,31 @@ If you need to load services as deltas, you must firstly load the diameter base
 
 Updates the maximum number of accepted connections to diameter server socket.
 
-**context[|<target file>]**
+**change-dir[|directory]**
 
-Application context could also be written by mean this operation (not only through SIGUSR1). If optional path file is missing, default '/var/tmp/anna.context.<pid>' will be used.
+Changes the execution point which could be fine to ease some file system interaction tasks. Be care about some requirements (for example if you have a user defined counters directory as relative path this must exists from the new execution directory). If nothing provided, initial working directory will be restored.
+
+### Client sessions visibility
+
+<action: **hide**, **show**, **hidden**, **shown**>|<address>:<port>|<socket>
+
+*Actions*: hide, show (update state) and hidden, shown (query state).
+Acts over a client session for messages delivery (except CER/A, DWR/A, DPR/A).
+If missing server (first parameter) all applications sockets will be affected.
+If missing socket (second parameter) for specific server, all its sockets will be affected.
+
+All application client sessions are shown on startup, but standard delivery only use primary server ones except if fails. Balance configuration use all the allowed sockets. You could also use command line 'sessionBasedModelsClientSocketSelection' to force traffic flow over certain client sessions, but for this, hide/show feature seems easier.
+
+### Snapshots
 
 **collect**
 
 Reset statistics and counters to start a new test stage of performance measurement. Context data can be written at '/var/tmp/anna.context.<pid>' by mean 'kill -10 <pid>' or sending operation 'context|[target file]'. This operation applies over all the registered host nodes except if one specific working node has been set.
 
+**context[|<target file>]**
+
+Application context could also be written by mean this operation (not only through SIGUSR1). If optional path file is missing, default '/var/tmp/anna.context.<pid>' will be used.
+
 **forceCountersRecord**
 
 Forces dump to file the current counters of the process.
@@ -141,10 +158,6 @@ Forces dump to file the current counters of the process.
 
 Log statistics samples for the provided comma-separated concept id list, over './sample.<concept id>.csv' files. For example: "1,2" will log concepts 1 and 2. Reserved words "all"/"none" activates/deactivates all registered statistics concept identifiers. That ids are shown at context dump.
 
-**change-dir[|directory]**
-
-Changes the execution point which could be fine to ease some file system interaction tasks. Be care about some requirements (for example if you have a user defined counters directory as relative path this must exists from the new execution directory). If nothing provided, initial working directory will be restored.
-
 **show-oam**
 
 Dumps current counters of the process. This is also done at process context dump.
@@ -153,15 +166,6 @@ Dumps current counters of the process. This is also done at process context dump
 
 Dumps statistics of the process. This is also done at process context dump.
 
-**visibility|<action>|<address>:<port>**
-
-*Actions*: hide, show (update state) and hidden, shown (query state).
-Acts over a client session for messages delivery (except CER/A, DWR/A, DPR/A).
-If missing server (first parameter) all applications sockets will be affected.
-If missing socket (second parameter) for specific server, all its sockets will be affected.
-
-All application client sessions are shown on startup, but standard delivery only use primary server ones except if fails. Balance configuration use all the allowed sockets. You could also use command line 'sessionBasedModelsClientSocketSelection' to force traffic flow over certain client sessions, but for this, hide/show feature seems easier.
-
 ### Flow operations
 
 **sendxml2e|<source_file>**
@@ -325,7 +329,7 @@ Adds a new step to the test case with provided identifier. If provided identifie
 > If not, the hex content will be understood as whole message and then, borders will be added (^<content>$) and sequence information bypassed even for diameter answers.
 >
 > **wait<fe/fc>-xml|<source_file>[|strict]**
-> Wait condition from entity (waitfe-xml) or client (waitfc-xml) to match the serialized xml content for received messages against source file (xml representation). Fix mode must be enabled to avoid unexpected matching behaviour. If you need a strict matching you must add parameter 'strict', if not, regexp is built ignoring sequence information (hop-by-hop-id=\"[0-9]+\" end-to-end-id=\"[0-9]+\") and Origin-State-Id value. All LF codes will be internally removed when comparison is executed in order to ease xml content configuration.
+> Wait condition from entity (waitfe-xml) or client (waitfc-xml) to match the serialized xml content for received messages against source file (xml representation). Fix mode must be enabled to avoid unexpected matching behaviour. If you need a strict matching you must add parameter 'strict', if not, regexp is built ignoring sequence information (hop-by-hop-id=\"[0-9]+\" end-to-end-id=\"[0-9]+\") and Origin-State-Id value.
 >
 > **wait<fe/fc>|<condition>**
 >
@@ -523,19 +527,51 @@ This operation requires advanced programming and knowlegde of ANNA Diameter stac
 
 # HTTP Interface
 
-All the operations described above can be used through the optional HTTP interface. You only have
+Most of the operations described above can be used through the optional HTTP1.1 interface. You only have
  to define the http server at the command line with something like: '--httpServer localhost:8000'.
-REST API specification:
+REST API specification.
+
+**We will describe briefly the supported *GET* & *POST* operations, but you could extend the explanation from SIGUSR2 interface description above**.
+
+Implemented status codes: *200* (ok), *400* (bad request) and *405* (method not allowed).
 
 ## GET
 
 > curl -v --request GET localhost:8000<uri>
 
-HTTP2 is not served, so, you should use *nginx* reverse proxy or similar, to pass HTTP1 requests to the server, allowing the external use of HTTP2 clients like *nghttp*:
+You could also expose the service as HTTP2 server through *nginx* working as reverse proxy (*adml-http* image is built in this way although internally provides HTTP operations script only for 1.1). Then you could use HTTP2 clients like *nghttp*:
 
 > nghttp -v -H ":method: GET" "<uri>"
 
-### GET /xxxx
+
+
+### Snapshots
+
+#### GET /show-oam
+
+Retrieve oam xml report (will be *base64-encoded* at response).
+
+**Response body**:
+
+```
+{
+    "result":"<true or false>",
+    "response":"<error description or base64-encoded xml report>"
+}
+```
+
+#### GET /show-stats
+
+Retrieve statistics xml report (will be *base64-encoded* at response).
+
+**Response body**:
+
+```
+{
+    "result":"<true or false>",
+    "response":"<error description or base64-encoded xml report>"
+}
+```
 
 
 
@@ -543,6 +579,685 @@ HTTP2 is not served, so, you should use *nginx* reverse proxy or similar, to pas
 
 > curl -v --request POST -H "Content-Type: application/json" localhost:8000<uri> -d@test.json
 
-HTTP2 is not served, so, you should use *nginx* reverse proxy or similar, to pass HTTP1 requests to the server, allowing the external use of HTTP2 clients like *nghttp*:
+You could also expose the service as HTTP2 server through *nginx* working as reverse proxy (*adml-http* image is built in this way although internally provides HTTP operations script only for 1.1). Then you could use HTTP2 clients like *nghttp*:
+
+> nghttp -v -H ":method: POST" -d test.json "<uri>"
+
+
+
+**Important note:** Anna Suite work natively with xml. Although REST API supports diameter messages (*diameterJson* fields) and services configuration (*servicesJson* fields) in *json* format, these messages are not validated directly with a *json schema*. Instead, the *json* object are converted to *xml*  at ADML and the resulting xml representations are validates against *dtd* schemas:
+
+Schema for diameter messages: [here](../../../../include/anna/diameter/codec/message.dtd).
+
+Schema for configuration services: [here](./services_examples/services.dtd).
+
+There are lots of examples for *xml diameter messages and xml services* (normally deployed with *ADML* at `./xml_examples` and `./services_examples`), then you could transform them to the *json format* accepted by the REST API easily, for example using *xmltodict* python module:
+
+```
+#!/usr/bin/python3
+import xmltodict
+import json
+import sys
+
+try:
+  file = sys.argv[1]
+except:
+  print("Usage: " + sys.argv[0] + " <diameter xml file>")
+  sys.exit(1)
+
+try:
+  with open(file, 'r') as myfile:
+    xml = myfile.read()
+except:
+  print("ERROR reading '" + file + "'")
+  sys.exit(1)
+
+# although default attribute prefix is '@', anyway we will
+# force the value just in case xmltodict implementation
+# changes. The anna::core::functions::json2xml helper,
+# assumes this prefix in order to work properly.
+my_dict=xmltodict.parse(xml, attr_prefix='@')
+json_data=json.dumps(my_dict, indent=3, sort_keys=True)
+print(json_data)
+```
+
+**Former script is packaged** together with REST API component tests under `./diameterJsonHelper/xml2json.py`.
+
+Native example for *AA-Request* diameter message:
+
+```
+<message version="1" name="AA-Request" p-bit="yes" application-id="16777236" hop-by-hop-id="0" end-to-end-id="0">
+   <avp name="Session-Id" data="test1;afNodeHostname.nodeHostRealm.com;1;8033450"/>
+   <avp name="Auth-Application-Id" data="16777236"/>
+   <avp name="Origin-Host" data="afHost.afRealm.com"/>
+   <avp name="Origin-Realm" data="afRealm.com"/>
+   <avp name="Destination-Realm" data="operatorRealm.com"/>
+   <avp name="Destination-Host" data="ownHostId.operatorRealm.com"/>
+   <avp name="AF-Application-Identifier" hex-data="313232"/>
+   <avp name="Media-Component-Description">
+      <avp name="Media-Component-Number" data="0"/>
+      <avp name="AF-Application-Identifier" hex-data="313232"/>
+      <avp name="Max-Requested-Bandwidth-UL" data="127"/>
+      <avp name="Max-Requested-Bandwidth-DL" data="133"/>
+      <avp name="Flow-Status" data="2" alias="ENABLED"/>
+      <avp name="Reservation-Priority" data="0" alias="DEFAULT"/>
+   </avp>
+   <avp name="Service-Info-Status" data="0" alias="FINAL_SERVICE_INFORMATION"/>
+   <avp name="Subscription-Id">
+      <avp name="Subscription-Id-Type" data="0" alias="END_USER_E164"/>
+      <avp name="Subscription-Id-Data" data="626037099"/>
+   </avp>
+   <avp name="Framed-IP-Address" hex-data="3139322e3136382e302e31"/>
+   <avp name="Called-Station-Id" hex-data="5741502e4d4f564953544152"/>
+</message>
+
+```
+
+Corresponding content in *json* format:
+
+```
+{
+   "message": {
+      "@application-id": "16777236",
+      "@end-to-end-id": "0",
+      "@hop-by-hop-id": "0",
+      "@name": "AA-Request",
+      "@p-bit": "yes",
+      "@version": "1",
+      "avp": [
+         {
+            "@data": "test1;afNodeHostname.nodeHostRealm.com;1;8033450",
+            "@name": "Session-Id"
+         },
+         {
+            "@data": "16777236",
+            "@name": "Auth-Application-Id"
+         },
+         {
+            "@data": "afHost.afRealm.com",
+            "@name": "Origin-Host"
+         },
+         {
+            "@data": "afRealm.com",
+            "@name": "Origin-Realm"
+         },
+         {
+            "@data": "operatorRealm.com",
+            "@name": "Destination-Realm"
+         },
+         {
+            "@data": "ownHostId.operatorRealm.com",
+            "@name": "Destination-Host"
+         },
+         {
+            "@hex-data": "313232",
+            "@name": "AF-Application-Identifier"
+         },
+         {
+            "@name": "Media-Component-Description",
+            "avp": [
+               {
+                  "@data": "0",
+                  "@name": "Media-Component-Number"
+               },
+               {
+                  "@hex-data": "313232",
+                  "@name": "AF-Application-Identifier"
+               },
+               {
+                  "@data": "127",
+                  "@name": "Max-Requested-Bandwidth-UL"
+               },
+               {
+                  "@data": "133",
+                  "@name": "Max-Requested-Bandwidth-DL"
+               },
+               {
+                  "@alias": "ENABLED",
+                  "@data": "2",
+                  "@name": "Flow-Status"
+               },
+               {
+                  "@alias": "DEFAULT",
+                  "@data": "0",
+                  "@name": "Reservation-Priority"
+               }
+            ]
+         },
+         {
+            "@alias": "FINAL_SERVICE_INFORMATION",
+            "@data": "0",
+            "@name": "Service-Info-Status"
+         },
+         {
+            "@name": "Subscription-Id",
+            "avp": [
+               {
+                  "@alias": "END_USER_E164",
+                  "@data": "0",
+                  "@name": "Subscription-Id-Type"
+               },
+               {
+                  "@data": "626037099",
+                  "@name": "Subscription-Id-Data"
+               }
+            ]
+         },
+         {
+            "@hex-data": "3139322e3136382e302e31",
+            "@name": "Framed-IP-Address"
+         },
+         {
+            "@hex-data": "5741502e4d4f564953544152",
+            "@name": "Called-Station-Id"
+         }
+      ]
+   }
+}
+```
+
+Native example for a services configuration example:
+
+```
+<services>
+  <!--
+  Stacks
+
+  * Monostack: you could select any id value, normally 0.
+  * Multistack: use the application id for the id value.
+                This eases codec engine selection for
+                processed messages.
+  -->
+  <stack id="0" dictionary="dictionary.xml" fixMode="Always" ignoreFlagsOnValidation="yes"/>
+
+  <!--
+  Nodes
+
+  * Client example:
+
+  <node originHost="<origin host>" applicationId="<application id>"
+        entity="<addr1:port1[,addr2:port2]...[,addrN:portN]>"
+        cer="<cer xml file>" answersTimeout="300000" dumpLog="yes"/>
+
+  * Server example:
+
+  <node originHost="<origin host>" applicationId="<application id>"
+        diameterServer="<addr:port>" diameterServerSessions="10"
+        cea="<cea xml file>" answersTimeout="300000" dumpLog="yes"/>
+  -->
+  <node originHost="afHost.afRealm.com" applicationId="0" entity="localhost:3868"/>
+  <node originHost="ownHostId.operatorRealm.com" applicationId="0"
+        diameterServer="localhost:3868" diameterServerSessions="1"/>
+
+</services>
+```
+
+And the converted *json* equivalent:
+
+```
+{
+   "services": {
+      "node": [
+         {
+            "@applicationId": "0",
+            "@entity": "localhost:3868",
+            "@originHost": "afHost.afRealm.com"
+         },
+         {
+            "@applicationId": "0",
+            "@diameterServer": "localhost:3868",
+            "@diameterServerSessions": "1",
+            "@originHost": "ownHostId.operatorRealm.com"
+         }
+      ],
+      "stack": {
+         "@dictionary": "dictionary.xml",
+         "@fixMode": "Always",
+         "@id": "0",
+         "@ignoreFlagsOnValidation": "yes"
+      }
+   }
+}
+```
+
+
+
+**Note that the '@' character is mandatory to indicate attribute keys, and it is necessary to complete the *"json to xml"* conversion successfully at ADML REST Server endpoint.**
+
+
+
+### Node management
+
+#### POST /node
+
+Selects a context working node by mean a registered name (origin-host). If empty, current node information is retrieved.
+
+**Request body**:
+
+```
+{
+    "name":"[node name]"
+}
+```
+
+**Response body**: 
+
+```
+{
+    "result":"<true or false>",
+    "response":"<error description or base64-encoded xml information>"
+}
+```
+
+#### POST /node-auto
+
+Smart node selection.
+
+**Request body**: none
+
+**Response body**:
+
+```
+{
+    "result":"<true or false>",
+    "response":"<response>"
+}
+```
+
+### Parsing operations
+
+#### POST /code
+
+Encodes a diameter json into hexadecimal representation.
+
+**Request body**:
+
+```
+{
+    "diameterJson":<diameter message json object>
+}
+```
+
+**Response body**:
+
+```
+{
+    "result":"<true or false>",
+    "response":"<error description or diameter hex>"
+}
+```
+
+#### POST /decode
+
+Decodes an hexadecimal string (no spaces, no colons, i.e.: `01000150c0...`), into diameter xml (*base64-encoded*).
+
+**Request body**:
+
+```
+{
+    "diameterHex":"<hex string>"
+}
+```
+
+**Response body**:
+
+```
+{
+    "result":"<true or false>",
+    "response":"<error description or base64-encoded xml diameter message>"
+}
+```
+
+#### POST /loadmsg
+
+Reinterprets diameter json into xml (*base64-encoded*).
+
+**Request body**:
+
+```
+{
+    "diameterJson":<diameter message json object>
+}
+```
+
+**Response body**:
+
+```
+{
+    "result":"<true or false>",
+    "response":"<error description or base64-encoded xml diameter message>"
+}
+```
+
+### Hot changes
+
+#### POST /services
+
+Referred files (*dictionaries, cer, cea, etc.*) shall be accesible for ADML and are not provided in this operation.
+
+**Request body**:
+
+```
+{
+    "servicesJson":<services json object>
+}
+```
+
+**Response body**:
+
+```
+{
+    "result":"<true or false>",
+    "response":"<response>"
+}
+```
+
+#### POST /diameterServerSessions
+
+Updates diameter server sessions to be accepted.
+
+**Request body**:
+
+```
+{
+    "sessions":<integer value>
+}
+```
+
+**Response body**:
+
+```
+{
+    "result":"<true or false>",
+    "response":"<response>"
+}
+```
+
+#### POST /change-dir
+
+Updates ADML working directory.
+
+**Request body**:
+
+```
+{
+    "directory":"<directory path or empty to restore initial working directory>"
+}
+```
+
+**Response body**:
+
+```
+{
+    "result":"<true or false>",
+    "response":"<response>"
+}
+```
+
+### Client sessions visibility
+
+#### POST /visibility
+
+**Request body**:
+
+```
+{
+    "action":"<hide|show|hidden|shown>"
+    [, "addressPort":"<address:port>"]
+    [, "socket":<socket>]
+}
+```
+
+**Response body**:
+
+```
+{
+    "result":"<true or false>",
+    "response":"<response>"
+}
+```
+
+### Snapshots
+
+#### POST /collect
+
+Reset statistics and counters.
+
+**Request body**: none
+
+**Response body**:
+
+```
+{
+    "result":"<true or false>",
+    "response":"<response>"
+}
+```
+
+#### POST /context
+
+Dump ADML context at file path provided. If empty, default path is selected. Context information is not retrieved in the response, so, file is related to ADML execution context.
+
+**Request body**:
+
+```
+{
+    "targetFile":"[file path]"
+}
+```
+
+**Response body**:
+
+```
+{
+    "result":"<true or false>",
+    "response":"<response>"
+}
+```
+
+#### POST /forceCountersRecord
+
+Forces dump to file the current counters of the process.
+
+**Request body**: none
+
+**Response body**:
+
+```
+{
+    "result":"<true or false>",
+    "response":"<response>"
+}
+```
+
+#### POST /log-statistics-samples
+
+Set the statistics concepts to be logged. To know the concept indentifiers registered, get the ADML context information.
+
+**Request body**:
+
+```
+{
+    "list":"<comma-separated list|all|none>"
+}
+```
+
+**Response body**:
+
+```
+{
+    "result":"<true or false>",
+    "response":"<response>"
+}
+```
+
+### Flow operations
+
+#### POST /sendmsg2e
+
+Sends diameter json message **to**(2) the connected **entity**(e).
+
+**Request body**:
+
+```
+{
+    "diameterJson":<diameter message json object>
+}
+```
+
+**Response body**:
+
+```
+{
+    "result":"<true or false>",
+    "response":"<response>"
+}
+```
+
+#### POST /sendmsg2c
+
+Sends diameter json message **to**(2) the connected **client**(c).
+
+**Request body**:
+
+```
+{
+    "diameterJson":<diameter message json object>
+}
+```
+
+**Response body**:
+
+```
+{
+    "result":"<true or false>",
+    "response":"<response>"
+}
+```
+
+#### POST /answermsg2e
+
+Answers diameter json message **to**(2) the connected **entity**(e).
+
+Mocking FIFO queue based in message code.
+
+**Request body**:
+
+```
+{
+    "diameterJson":<diameter message json object>
+}
+```
+
+or
+
+```
+{
+    "action":"<action: list|dump|clear|exhaust|rotate>"
+}
+```
+
+**Response body**:
+
+```
+{
+    "result":"<true or false>",
+    "response":"<response>"
+}
+```
+
+#### POST /answermsg2c
+
+Answers diameter json message **to**(2) the connected **client**(c).
+
+Mocking FIFO queue based in message code.
+
+**Request body**:
+
+```
+{
+    "diameterJson":<diameter message json object>
+}
+```
+
+or
+
+```
+{
+    "action":"<action: list|dump|clear|exhaust|rotate>"
+}
+```
+
+**Response body**:
+
+```
+{
+    "result":"<true or false>",
+    "response":"<response>"
+}
+```
+
+#### POST /sendhex2e
+
+Sends diameter expressed in hexadecimal string (no spaces, no colons, i.e.: `01000150c0...`), **to**(2) the connected **entity**(e).
+
+**Request body**:
+
+```
+{
+    "diameterHex":"<hex string>"
+}
+```
+
+**Response body**:
+
+```
+{
+    "result":"<true or false>",
+    "response":"<response>"
+}
+```
+
+#### POST /sendhex2c
+
+Sends diameter expressed in hexadecimal string (no spaces, no colons, i.e.: `01000150c0...`), **to**(2) the connected **client**(c).
+
+**Request body**:
+
+```
+{
+    "diameterHex":"<hex string>"
+}
+```
+
+**Response body**:
+
+```
+{
+    "result":"<true or false>",
+    "response":"<response>"
+}
+```
+
+### FSM testing
+
+ADML implements a bulting *Finite State Machine* to plan testing flows with a great flexibility.
+
+#### POST /xxxxxxxx
+
+Referred files (*dictionaries, cer, cea, etc.*) shall be accesible for ADML and are not provided in this operation.
+
+**Request body**: { "servicesJson":<services json object>}
+
+**Response body**: { "result":"<true or false>", "response":"<response>"}
+
+#### POST /xxxxxxxx
+
+Referred files (*dictionaries, cer, cea, etc.*) shall be accesible for ADML and are not provided in this operation.
+
+**Request body**: { "servicesJson":<services json object>}
+
+**Response body**: { "result":"<true or false>", "response":"<response>"}
+
+
 
-> nghttp -v -H ":method: POST" -d test.json "<uri>"
\ No newline at end of file