Purpose
The purpose of SNIRO Emulator is to mock SNIRO homing functionality, which can be used to demo use cases.
It consists of a HTTP server that we could connect to as we would to an actual web service.
Set up SNIRO emulator is built using microservices architecture to support portability and evolution. It is built based on wiremock testing tool wireMock .
It is deployed as dedicated docker container either using OOM based kubernetes deployment or as an additional container inside Robot VM using Heat template deployment technique.
OOM based deployment Since emulator is not core component of ONAP, it is not included in the list of all components that are deployed by "all" option of OOM oneclick/createALL.bash script. In order to run it, one should explicitly deploy is using "-a" option :
Heat based deployment
SNIRO emulator container is added into Robot VM and exposed at the port 8080
It will be up and running automatically once Robot VM is spun up
Using emulator Admin API Reference The server provides various admin API to handle stubbing.
The API can be viewed through swagger page:
http://<ROBOT_VM_HOST>:8080/__admin/swagger-ui/
Some of the most useful APIs:
/__admin/mappings
GET /__admin/mappings --> Gets all defined mappings
POST /__admin/mappings --> Create a new stub mapping
GET /__admin/mappings/{guid} --> Get a single stub mapping
/__admin/requests
POST /__admin/requests/count --> Count requests logged in the journal matching the specified criteria
POST /__admin/mappings/reset --> Reset stub mappings (restore to defaults defined back the backing store)
Stubbing the server via Robot Framework
The following steps are needed to stub emulator server to be able to respond for Rest-API calls originated in SO:
Create Session alias=session url=${SNIRO_EMULATOR_URL}
${body} Get File Template/sniro_data/sniro_stub_request.json
${sniro_stub_response} Post Request alias=session uri=/__admin/mappings data=${body}
Create Session alias=session url=${SNIRO_EMULATOR_URL}
${body} Get File Template/sniro_data/sniro_stub_request.json
${sniro_stub_response} Post Request alias=session uri=/__admin/mappings data=${body}
sniro_stub_request.json contains the following mapping:
{ "request" : { "urlPath" : "/sniro/api/v2/placement", "method" : "POST" }, "response" : { "status" : 202, "body": "{\"requestId\": \"1111-111-11\"}" }, "postServeActions" : { "webhook" : { "headers" : { "Content-Type" : "application/json" }, "method" : "POST", "base64Body" : "ew0KICAidHJhbnNhY3Rpb25JZCI6ICIxMTEtMTExLTExMTEiLA0KICAicmVxdWVzdElkIjogIjExMS0xMTEtMTExMSIsDQogICJyZXF1ZXN0U3RhdGUiOiAiY29tcGxldGUiLA0KICAic3RhdHVzTWVzc2FnZSI6ICIiLA0KICAic29sdXRpb25JbmZvIjogew0KICAgICJwbGFjZW1lbnQiOiBbDQogICAgICB7DQogICAgICAgICJzZXJ2aWNlUmVzb3VyY2VJZCI6ICI2MWQ1NjNlOC1lNzE0LTQzOTMtOGY5OS1jYzQ4MDE0NGEwNWUiLA0KICAgICAgICAicmVzb3VyY2VNb2R1bGVOYW1lIjogIlR1bm5lbFhDb25uIiwNCiAgICAgICAgImludmVudG9yeVR5cGUiOiAic2VydmljZSIsDQogICAgICAgICJzZXJ2aWNlSW5zdGFuY2VJZCI6ICJHTXV4SW5mcmEgVVVJRCIsDQogICAgICAgICJjbG91ZFJlZ2lvbklkIjogIiIsDQogICAgICB9LA0KICAgICAgew0KICAgICAgICAic2VydmljZVJlc291cmNlSWQiOiAiOTFkNTYzZTgtZTcxNC00MzkzLThmOTktY2M0ODAxNDRhMDVlIiwNCiAgICAgICAgInJlc291cmNlTW9kdWxlTmFtZSI6ICJ2RyIsDQogICAgICAgICJpbnZlbnRvcnlUeXBlIjogImNsb3VkIiwNCiAgICAgICAgInNlcnZpY2VJbnN0YW5jZUlkIjogIiIsDQogICAgICAgICJjbG91ZFJlZ2lvbklkIjogImRhMTAyIiwNCiAgICAgIH0sDQogICAgICB7DQogICAgICAgICJzZXJ2aWNlUmVzb3VyY2VJZCI6ICI3MWQ1NjNlOC1lNzE0LTQzOTMtOGY5OS1jYzQ4MDE0NGEwNWUiLA0KICAgICAgICAicmVzb3VyY2VNb2R1bGVOYW1lIjogIkJSRyIsDQogICAgICAgICJpbnZlbnRvcnlUeXBlIjogInNlcnZpY2UiLA0KICAgICAgICAic2VydmljZUluc3RhbmNlSWQiOiAiQlJHX0VNVV9VVUlEIiwNCiAgICAgICAgImNsb3VkUmVnaW9uSWQiOiAiIg0KICAgICAgfQ0KICAgIF0NCiAgfQ0KfQ==", "url" : "https://{{mso_ip}}:8080/adapters/rest/SDNCNotify/SNIROResponse " } } }
{ "request" : { "urlPath" : "/sniro/api/v2/placement", "method" : "POST" }, "response" : { "status" : 202, "body": "{\"requestId\": \"1111-111-11\"}" }, "postServeActions" : { "webhook" : { "headers" : { "Content-Type" : "application/json" }, "method" : "POST", "base64Body" : "ew0KICAidHJhbnNhY3Rpb25JZCI6ICIxMTEtMTExLTExMTEiLA0KICAicmVxdWVzdElkIjogIjExMS0xMTEtMTExMSIsDQogICJyZXF1ZXN0U3RhdGUiOiAiY29tcGxldGUiLA0KICAic3RhdHVzTWVzc2FnZSI6ICIiLA0KICAic29sdXRpb25JbmZvIjogew0KICAgICJwbGFjZW1lbnQiOiBbDQogICAgICB7DQogICAgICAgICJzZXJ2aWNlUmVzb3VyY2VJZCI6ICI2MWQ1NjNlOC1lNzE0LTQzOTMtOGY5OS1jYzQ4MDE0NGEwNWUiLA0KICAgICAgICAicmVzb3VyY2VNb2R1bGVOYW1lIjogIlR1bm5lbFhDb25uIiwNCiAgICAgICAgImludmVudG9yeVR5cGUiOiAic2VydmljZSIsDQogICAgICAgICJzZXJ2aWNlSW5zdGFuY2VJZCI6ICJHTXV4SW5mcmEgVVVJRCIsDQogICAgICAgICJjbG91ZFJlZ2lvbklkIjogIiIsDQogICAgICB9LA0KICAgICAgew0KICAgICAgICAic2VydmljZVJlc291cmNlSWQiOiAiOTFkNTYzZTgtZTcxNC00MzkzLThmOTktY2M0ODAxNDRhMDVlIiwNCiAgICAgICAgInJlc291cmNlTW9kdWxlTmFtZSI6ICJ2RyIsDQogICAgICAgICJpbnZlbnRvcnlUeXBlIjogImNsb3VkIiwNCiAgICAgICAgInNlcnZpY2VJbnN0YW5jZUlkIjogIiIsDQogICAgICAgICJjbG91ZFJlZ2lvbklkIjogImRhMTAyIiwNCiAgICAgIH0sDQogICAgICB7DQogICAgICAgICJzZXJ2aWNlUmVzb3VyY2VJZCI6ICI3MWQ1NjNlOC1lNzE0LTQzOTMtOGY5OS1jYzQ4MDE0NGEwNWUiLA0KICAgICAgICAicmVzb3VyY2VNb2R1bGVOYW1lIjogIkJSRyIsDQogICAgICAgICJpbnZlbnRvcnlUeXBlIjogInNlcnZpY2UiLA0KICAgICAgICAic2VydmljZUluc3RhbmNlSWQiOiAiQlJHX0VNVV9VVUlEIiwNCiAgICAgICAgImNsb3VkUmVnaW9uSWQiOiAiIg0KICAgICAgfQ0KICAgIF0NCiAgfQ0KfQ==", "url" : "https://{{mso_ip}}:8080/adapters/rest/SDNCNotify/SNIROResponse " } } }
The above base64Body encoded value represents the following call back request:
{ "transactionId": "111-111-1111", "requestId": "111-111-1111", "requestState": "complete", "statusMessage": "", "solutionInfo": { "placement": [ { "serviceResourceId": "61d563e8-e714-4393-8f99-cc480144a05e", "resourceModuleName": "TunnelXConn", "inventoryType": "service", "serviceInstanceId": "${GMuxInfra UUID}", "cloudRegionId": "", }, { "serviceResourceId": "91d563e8-e714-4393-8f99-cc480144a05e", "resourceModuleName": "vG", "inventoryType": "cloud", "serviceInstanceId": "", "cloudRegionId": "${cloud_region_id}", }, { "serviceResourceId": "71d563e8-e714-4393-8f99-cc480144a05e", "resourceModuleName": "BRG", "inventoryType": "service", "serviceInstanceId": "${BRG_EMU_UUID}", "cloudRegionId": "" } ] } }
{ "transactionId": "111-111-1111", "requestId": "111-111-1111", "requestState": "complete", "statusMessage": "", "solutionInfo": { "placement": [ { "serviceResourceId": "61d563e8-e714-4393-8f99-cc480144a05e", "resourceModuleName": "TunnelXConn", "inventoryType": "service", "serviceInstanceId": "${GMuxInfra UUID}", "cloudRegionId": "", }, { "serviceResourceId": "91d563e8-e714-4393-8f99-cc480144a05e", "resourceModuleName": "vG", "inventoryType": "cloud", "serviceInstanceId": "", "cloudRegionId": "${cloud_region_id}", }, { "serviceResourceId": "71d563e8-e714-4393-8f99-cc480144a05e", "resourceModuleName": "BRG", "inventoryType": "service", "serviceInstanceId": "${BRG_EMU_UUID}", "cloudRegionId": "" } ] } }
Verify Emulator stubbing via Robot framework:
Create Session alias=session url=${SNIRO_EMULATOR_URL}
${body} Get File Template/sniro_data/verify_placement_request.json
${verify_response} Post Request alias=session uri=/sniro/api/v2/placement data=${body}
Should Be Equal As String ${verify_response.status} 202
Create Session alias=session url=${SNIRO_EMULATOR_URL}
${body} Get File Template/sniro_data/verify_placement_request.json
${verify_response} Post Request alias=session uri=/sniro/api/v2/placement data=${body}
Should Be Equal As String ${verify_response.status} 202
SNIRO homing placement functionality is implemented in ASYNC way, it means that successful Post request to the server is acknowledged first by return status 202 (the request is accepted), followed by another POST request to SO server which is sent to URL specified in "url" attribute of PostServeActions entity in the stubbing request.
References:
SO / SNIRO Interface AID
Wiremock tool : Wiremock