Copy latest code 01/2101/1
authorss412g <shuky.har-noy@intl.att.com>
Mon, 2 Dec 2019 14:59:19 +0000 (16:59 +0200)
committerss412g <shuky.har-noy@intl.att.com>
Mon, 23 Dec 2019 22:16:34 +0000 (00:16 +0200)
Change-Id: Ibfcfce723adc532458911ec1df798fcd511fddaa
Signed-off-by: ss412g <shuky.har-noy@intl.att.com>
203 files changed:
.gitignore
Automation/Dockerfile
Automation/Tests/ConfigurationUpdate/ConfigurationUpdate_Verify_logs.robot [deleted file]
Automation/Tests/ConfigurationUpdate/ConfigurationUpdate_prepartations_tests.robot
Automation/Tests/E2Term_Initialization/E2Term_Init_Message_Test.robot [new file with mode: 0644]
Automation/Tests/E2Term_Initialization/__init__.robot [new file with mode: 0755]
Automation/Tests/ENDC-Setup/ENDC_Setup_request_test.robot
Automation/Tests/ENDC_Reset_RAN_TO_RIC/Reset_RAN_Found.robot
Automation/Tests/ENDC_Reset_RAN_TO_RIC/Reset_Verify_logs.robot [deleted file]
Automation/Tests/ENDC_Reset_RIC_TO_RAN/Reset_Happy_no_cause.robot
Automation/Tests/ENDC_Reset_RIC_TO_RAN/Reset_Happy_with_cause.robot
Automation/Tests/KeepAlive/__init__.robot [new file with mode: 0755]
Automation/Tests/KeepAlive/keep_alive_test.robot [new file with mode: 0644]
Automation/Tests/LoadInfomation/Loadinformation_adding_data_and_overwrite.robot
Automation/Tests/Lost_Connection/Lost_Connetion_CONNECTING_TO_DISCONNECTED.robot
Automation/Tests/RSM_Resource_Status/__init__.robot [new file with mode: 0755]
Automation/Tests/RSM_Resource_Status/resource_status_false_start.robot [new file with mode: 0644]
Automation/Tests/RSM_Resource_Status/resource_status_false_stop.robot [new file with mode: 0644]
Automation/Tests/RSM_Resource_Status/resource_status_keywords.robot [new file with mode: 0644]
Automation/Tests/RSM_Resource_Status/resource_status_true_start.robot [new file with mode: 0644]
Automation/Tests/RSM_Resource_Status/resource_status_true_stop.robot [new file with mode: 0644]
Automation/Tests/RedButton/RedButton_CONNECTED_SHUTDOWN_CONNECTED.robot
Automation/Tests/RedButton/RedButton_DISCONNECTED.robot
Automation/Tests/Resource/Keywords.robot
Automation/Tests/Resource/resource.robot
Automation/Tests/Resource/scripts_variables.robot
Automation/Tests/Scripts/cleanup_db.py
Automation/Tests/Scripts/e2mdbscripts.py [new file with mode: 0644]
Automation/Tests/Scripts/e2t_db_script.py [new file with mode: 0644]
Automation/Tests/Scripts/find_rmr_message.py
Automation/Tests/Scripts/getnodes.py
Automation/Tests/Scripts/loadscripts.py
Automation/Tests/Scripts/rsmscripts.py [new file with mode: 0644]
Automation/Tests/Unhappy/Reset_HttpResponse400_wrongstate.robot
Automation/Tests/X2-Setup/X2_Setup_reuqest_test.robot
Automation/Tests/X2-Setup/x2_setup_existing_assoc_test.robot [moved from Automation/Tests/X2_Reset_RAN_TO_RIC/Reset_Verify_logs.robot with 55% similarity]
Automation/Tests/X2-Setup/x2_setup_existing_not_assoc_test.robot [new file with mode: 0644]
Automation/Tests/X2_Reset_RAN_TO_RIC/Reset_RAN_Found.robot
Automation/Tests/X2_Reset_RAN_TO_RIC_Unhappy/Reset_RNIB.robot
Automation/Tests/X2_Reset_RAN_TO_RIC_Unhappy/Reset_Verify_logs.robot [deleted file]
Automation/Tests/X2_Reset_RIC_TO_RAN/Reset_Happy_no_cause.robot
Automation/Tests/X2_Reset_RIC_TO_RAN/Reset_Happy_with_cause.robot
E2Manager/Dockerfile
E2Manager/app/main.go
E2Manager/clients/http_client.go [new file with mode: 0644]
E2Manager/clients/routing_manager_client.go [new file with mode: 0644]
E2Manager/clients/routing_manager_client_test.go [new file with mode: 0644]
E2Manager/configuration/configuration.go
E2Manager/configuration/configuration_test.go
E2Manager/container-tag.yaml
E2Manager/controllers/e2t_controller.go [new file with mode: 0644]
E2Manager/controllers/nodeb_controller.go
E2Manager/controllers/nodeb_controller_test.go
E2Manager/controllers/root_controller_test.go
E2Manager/converters/endc_setup_failure_response_converter.go [moved from E2Manager/converters/endc_x2setupFailureResponseToProtobuf.go with 82% similarity]
E2Manager/converters/endc_setup_failure_response_converter_test.go [moved from E2Manager/converters/endc_x2setupFailureResponseToProtobuf_test.go with 93% similarity]
E2Manager/converters/endc_setup_response_converter.go [moved from E2Manager/converters/endc_x2setupResponseToProtobuf.go with 93% similarity]
E2Manager/converters/endc_setup_response_converter_test.go [moved from E2Manager/converters/endc_x2setupResponseToProtobuf_test.go with 99% similarity]
E2Manager/e2managererrors/e2t_instance_absence_error.go [new file with mode: 0644]
E2Manager/e2managererrors/routing_manager_error.go [new file with mode: 0644]
E2Manager/e2mgr-sonar-scanner.properties [new file with mode: 0644]
E2Manager/e2pdus/configuration_update.go [new file with mode: 0644]
E2Manager/e2pdus/configuration_update_test.go [new file with mode: 0644]
E2Manager/e2pdus/x2_setup_requests_test.go
E2Manager/go.mod
E2Manager/go.sum
E2Manager/handlers/httpmsghandlers/delete_all_request_handler_test.go
E2Manager/handlers/httpmsghandlers/get_e2t_instances_request_handler.go [new file with mode: 0644]
E2Manager/handlers/httpmsghandlers/get_e2t_instances_request_handler_test.go [new file with mode: 0644]
E2Manager/handlers/httpmsghandlers/get_nodeb_id_list_request_handler_test.go
E2Manager/handlers/httpmsghandlers/get_nodeb_request_handler_test.go
E2Manager/handlers/httpmsghandlers/setup_request_handler.go
E2Manager/handlers/httpmsghandlers/setup_request_handler_test.go
E2Manager/handlers/httpmsghandlers/x2_reset_request_handler.go
E2Manager/handlers/httpmsghandlers/x2_reset_request_handler_test.go
E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler.go
E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler_test.go
E2Manager/handlers/rmrmsghandlers/e2t_keep_alive_response_handler.go [new file with mode: 0644]
E2Manager/handlers/rmrmsghandlers/e2t_keep_alive_response_handler_test.go [new file with mode: 0644]
E2Manager/handlers/rmrmsghandlers/enb_load_information_notification_handler.go
E2Manager/handlers/rmrmsghandlers/enb_load_information_notification_handler_test.go
E2Manager/handlers/rmrmsghandlers/endc_configuration_update_handler.go
E2Manager/handlers/rmrmsghandlers/endc_configuration_update_handler_test.go
E2Manager/handlers/rmrmsghandlers/notification_handler.go
E2Manager/handlers/rmrmsghandlers/setup_response_notification_handler_test.go
E2Manager/handlers/rmrmsghandlers/x2_reset_request_notification_handler.go
E2Manager/handlers/rmrmsghandlers/x2_reset_request_notification_handler_test.go
E2Manager/handlers/rmrmsghandlers/x2_reset_response_handler.go
E2Manager/handlers/rmrmsghandlers/x2_reset_response_handler_test.go
E2Manager/handlers/rmrmsghandlers/x2enb_configuration_update_handler.go
E2Manager/handlers/rmrmsghandlers/x2enb_configuration_update_handler_test.go
E2Manager/httpserver/http_server.go
E2Manager/httpserver/http_server_test.go
E2Manager/logger/logger_test.go
E2Manager/managers/e2t_instances_manager.go [new file with mode: 0644]
E2Manager/managers/e2t_instances_manager_test.go [new file with mode: 0644]
E2Manager/managers/e2t_keep_alive_worker.go [new file with mode: 0644]
E2Manager/managers/e2t_keep_alive_worker_test.go [new file with mode: 0644]
E2Manager/managers/e2t_shutdown_manager.go [new file with mode: 0644]
E2Manager/managers/endc_setup_failure_response_manager.go
E2Manager/managers/endc_setup_failure_response_manager_test.go [new file with mode: 0644]
E2Manager/managers/endc_setup_response_manager.go
E2Manager/managers/endc_setup_response_manager_test.go [new file with mode: 0644]
E2Manager/managers/notificationmanager/notification_manager.go
E2Manager/managers/notificationmanager/notification_manager_test.go
E2Manager/managers/ran_reconnection_manager.go
E2Manager/managers/ran_reconnection_manager_test.go
E2Manager/managers/ran_setup_manager.go
E2Manager/managers/ran_setup_manager_test.go
E2Manager/managers/ran_status_change_manager.go
E2Manager/managers/ran_status_change_manager_test.go
E2Manager/managers/x2_setup_failure_response_manager_test.go [new file with mode: 0644]
E2Manager/mocks/controllerMock.go [deleted file]
E2Manager/mocks/e2t_controller_mock.go [new file with mode: 0644]
E2Manager/mocks/e2t_instances_manager_mock.go [new file with mode: 0644]
E2Manager/mocks/e2t_shutdown_manager_mock.go [moved from E2Manager/rnibBuilders/node_info_builder.go with 56% similarity]
E2Manager/mocks/http_client_mock.go [new file with mode: 0644]
E2Manager/mocks/nodebControllerMock.go [deleted file]
E2Manager/mocks/nodeb_controller_mock.go [new file with mode: 0644]
E2Manager/mocks/ran_setup_manager_mock.go [new file with mode: 0644]
E2Manager/mocks/rmrMessengerMock.go
E2Manager/mocks/rnibReaderMock.go
E2Manager/mocks/rnibWriterMock.go
E2Manager/mocks/root_controller_mock.go [new file with mode: 0644]
E2Manager/mocks/routing_manager_client_mock.go [new file with mode: 0644]
E2Manager/models/e2_request_message_test.go
E2Manager/models/e2_term_init_payload.go [new file with mode: 0644]
E2Manager/models/e2t_keep_alive_payload.go [new file with mode: 0644]
E2Manager/models/get_e2t_instances_response.go [new file with mode: 0644]
E2Manager/models/get_nodeb_id_list_response.go
E2Manager/models/get_nodeb_response.go
E2Manager/models/i_response.go
E2Manager/models/notification_request.go
E2Manager/models/rmr_message.go
E2Manager/models/routing_manager_e2t_data.go [new file with mode: 0644]
E2Manager/providers/httpmsghandlerprovider/incoming_request_handler_provider.go
E2Manager/providers/httpmsghandlerprovider/incoming_request_handler_provider_test.go
E2Manager/providers/rmrmsghandlerprovider/notification_handler_provider.go
E2Manager/providers/rmrmsghandlerprovider/notification_handler_provider_test.go
E2Manager/rNibWriter/rNibWriter.go
E2Manager/rNibWriter/rNibWriter_test.go
E2Manager/resources/configuration.yaml
E2Manager/rmrCgo/rmrCgoApi.go
E2Manager/rmrCgo/rmrCgoApi_test.go
E2Manager/rmrCgo/rmrCgoTypes.go
E2Manager/rnibBuilders/node_info_builder_test.go [deleted file]
E2Manager/router.txt
E2Manager/router_test.txt [new file with mode: 0644]
E2Manager/services/rmrreceiver/rmr_receiver.go
E2Manager/services/rmrreceiver/rmr_receiver_test.go
E2Manager/services/rmrsender/rmr_sender.go
E2Manager/services/rmrsender/rmr_sender_test.go
E2Manager/services/rnib_data_service.go
E2Manager/services/rnib_data_service_test.go
E2Manager/tests/dataProvider.go
E2Manager/tests/utils.go [new file with mode: 0644]
Swagger/E2Manager_API.yaml
docs/release-notes.rst
tools/RoutingManagerSimulator/Dockerfile [new file with mode: 0644]
tools/RoutingManagerSimulator/api/swagger.yaml [new file with mode: 0755]
tools/RoutingManagerSimulator/configuration/configuration.go [new file with mode: 0644]
tools/RoutingManagerSimulator/configuration/configuration_test.go [new file with mode: 0644]
tools/RoutingManagerSimulator/go.mod [new file with mode: 0644]
tools/RoutingManagerSimulator/go.sum [new file with mode: 0644]
tools/RoutingManagerSimulator/go/api_handle.go [new file with mode: 0755]
tools/RoutingManagerSimulator/go/api_health.go [new file with mode: 0755]
tools/RoutingManagerSimulator/go/logger.go [new file with mode: 0755]
tools/RoutingManagerSimulator/go/model_e2t_data.go [new file with mode: 0755]
tools/RoutingManagerSimulator/go/model_e2t_delete_data.go [new file with mode: 0755]
tools/RoutingManagerSimulator/go/model_health_status.go [new file with mode: 0755]
tools/RoutingManagerSimulator/go/model_ran_e2t_element.go [new file with mode: 0755]
tools/RoutingManagerSimulator/go/model_ran_e2t_map.go [new file with mode: 0755]
tools/RoutingManagerSimulator/go/model_ran_namelist.go [new file with mode: 0755]
tools/RoutingManagerSimulator/go/model_xapp_callback_data.go [new file with mode: 0755]
tools/RoutingManagerSimulator/go/model_xapp_element.go [new file with mode: 0755]
tools/RoutingManagerSimulator/go/model_xapp_list.go [new file with mode: 0755]
tools/RoutingManagerSimulator/go/model_xapp_subscription_data.go [new file with mode: 0755]
tools/RoutingManagerSimulator/go/routers.go [new file with mode: 0755]
tools/RoutingManagerSimulator/main.go [new file with mode: 0755]
tools/RoutingManagerSimulator/resources/configuration.yaml [new file with mode: 0644]
tools/xapp_mock/configuration.json [deleted file]
tools/xapp_mock/main/xapp_mock.go [deleted file]
tools/xapp_mock/resources/router.txt [deleted file]
tools/xappmock/Dockerfile [moved from tools/xapp_mock/Dockerfile with 68% similarity]
tools/xappmock/dispatcher/dispatcher.go [new file with mode: 0644]
tools/xappmock/enums/command_action.go [new file with mode: 0644]
tools/xappmock/frontend/configfile.go [moved from tools/xapp_mock/frontend/configfile.go with 92% similarity]
tools/xappmock/frontend/jsonDecoder.go [moved from tools/xapp_mock/frontend/jsonDecoder.go with 60% similarity]
tools/xappmock/go.mod [new file with mode: 0644]
tools/xappmock/go.sum [new file with mode: 0644]
tools/xappmock/logger/logger.go [new file with mode: 0644]
tools/xappmock/main/xappmock.go [new file with mode: 0644]
tools/xappmock/models/json_command.go [new file with mode: 0644]
tools/xappmock/models/message_info.go [new file with mode: 0644]
tools/xappmock/models/process_result.go [new file with mode: 0644]
tools/xappmock/resources/conf/configuration.json [new file with mode: 0644]
tools/xappmock/resources/router.txt [new file with mode: 0644]
tools/xappmock/resp [moved from tools/xapp_mock/resp with 100% similarity]
tools/xappmock/rmr/rmrCgoApi.go [moved from tools/xapp_mock/rmr/rmrCgoApi.go with 92% similarity]
tools/xappmock/rmr/rmrCgoTypes.go [moved from tools/xapp_mock/rmr/rmrCgoTypes.go with 97% similarity]
tools/xappmock/rmr/rmrCgoUtils.go [moved from tools/xapp_mock/rmr/rmrCgoUtils.go with 83% similarity]
tools/xappmock/rmr/rmrEndPoint.go [moved from tools/xapp_mock/rmr/rmrEndPoint.go with 65% similarity]
tools/xappmock/sender/jsonSender.go [moved from tools/xapp_mock/sender/jsonSender.go with 69% similarity]

index 53691a3..0baa305 100644 (file)
@@ -11,3 +11,4 @@ __pycache__/
 # documentation
 .tox
 docs/_build/
+/.gitreview
index 6733a6b..e981b44 100755 (executable)
@@ -3,6 +3,7 @@ FROM python:3.6
 RUN python3 -m pip install robotframework \
     && pip install --upgrade RESTinstance \
     && pip install docker \
+    && pip install -U robotframework-requests\
     && apt-get update 
 
 WORKDIR /opt
diff --git a/Automation/Tests/ConfigurationUpdate/ConfigurationUpdate_Verify_logs.robot b/Automation/Tests/ConfigurationUpdate/ConfigurationUpdate_Verify_logs.robot
deleted file mode 100644 (file)
index 5e2933e..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-##############################################################################
-#
-#   Copyright (c) 2019 AT&T Intellectual Property.
-#
-#   Licensed under the Apache License, Version 2.0 (the "License");
-#   you may not use this file except in compliance with the License.
-#   You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-#   Unless required by applicable law or agreed to in writing, software
-#   distributed under the License is distributed on an "AS IS" BASIS,
-#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#   See the License for the specific language governing permissions and
-#   limitations under the License.
-#
-##############################################################################
-#
-#   This source code is part of the near-RT RIC (RAN Intelligent Controller)
-#   platform project (RICP).
-#
-
-
-*** Settings ***
-Resource   ../Resource/resource.robot
-Resource    ../Resource/scripts_variables.robot
-Library     String
-Library     OperatingSystem
-Library     Process
-Library     ../Scripts/find_rmr_message.py
-
-
-
-*** Test Cases ***
-Verify logs - Confiugration update - Begin Tag Get
-    ${Configuration}=   Grep File  ./gnb.log  <ENDCConfigurationUpdate>
-    ${ConfigurationAfterStrip}=     Strip String    ${Configuration}
-    Should Be Equal     ${ConfigurationAfterStrip}        <ENDCConfigurationUpdate>
-
-Verify logs - Confiugration update - End Tag Get
-    ${ConfigurationEnd}=   Grep File  ./gnb.log  </ENDCConfigurationUpdate>
-    ${ConfigurationEndAfterStrip}=     Strip String    ${ConfigurationEnd}
-    Should Be Equal     ${ConfigurationEndAfterStrip}        </ENDCConfigurationUpdate>
-
-Verify logs - Confiugration update - Ack Tag Begin
-    ${ConfigurationAck}=   Grep File  ./gnb.log   <ENDCConfigurationUpdateAcknowledge>
-    ${ConfigurationAckAfter}=     Strip String    ${ConfigurationAck}
-    Should Be Equal     ${ConfigurationAckAfter}        <ENDCConfigurationUpdateAcknowledge>
-
-Verify logs - Confiugration update - Ack Tag End
-    ${ConfigurationAckEnd}=   Grep File  ./gnb.log  </ENDCConfigurationUpdateAcknowledge>
-    ${ConfigurationAckEndAfterStrip}=     Strip String    ${ConfigurationAckEnd}
-    Should Be Equal     ${ConfigurationAckEndAfterStrip}        </ENDCConfigurationUpdateAcknowledge>
-
-Verify logs - find RIC_ENDC_CONF_UPDATE
-   ${result}   find_rmr_message.verify_logs  ${EXECDIR}  ${e2mgr_log_filename}  ${configurationupdate_message_type}  ${Meid_test1}
-   Should Be Equal As Strings    ${result}      True
-Verify logs - find RIC_ENDC_CONF_UPDATE_ACK
-   ${result1}  find_rmr_message.verify_logs  ${EXECDIR}  ${e2mgr_log_filename}  ${configurationupdate_ack_message_type}  ${Meid_test1}
-   Should Be Equal As Strings    ${result1}      True
index a2b741a..f833a3e 100644 (file)
@@ -27,7 +27,10 @@ Resource   ../Resource/resource.robot
 Resource   ../Resource/Keywords.robot
 Library     OperatingSystem
 Library     REST      ${url}
-
+Resource    ../Resource/scripts_variables.robot
+Library     String
+Library     Process
+Library     ../Scripts/find_rmr_message.py
 
 
 *** Test Cases ***
@@ -45,8 +48,32 @@ Prepare logs for tests
     Remove log files
     Save logs
 
-
-
+Verify logs - Confiugration update - Begin Tag Get
+    ${Configuration}=   Grep File  ./${gnb_log_filename}  <ENDCConfigurationUpdate>
+    ${ConfigurationAfterStrip}=     Strip String    ${Configuration}
+    Should Be Equal     ${ConfigurationAfterStrip}        <ENDCConfigurationUpdate>
+
+Verify logs - Confiugration update - End Tag Get
+    ${ConfigurationEnd}=   Grep File  ./${gnb_log_filename}  </ENDCConfigurationUpdate>
+    ${ConfigurationEndAfterStrip}=     Strip String    ${ConfigurationEnd}
+    Should Be Equal     ${ConfigurationEndAfterStrip}        </ENDCConfigurationUpdate>
+
+Verify logs - Confiugration update - Ack Tag Begin
+    ${ConfigurationAck}=   Grep File  ./${gnb_log_filename}   <ENDCConfigurationUpdateAcknowledge>
+    ${ConfigurationAckAfter}=     Strip String    ${ConfigurationAck}
+    Should Be Equal     ${ConfigurationAckAfter}        <ENDCConfigurationUpdateAcknowledge>
+
+Verify logs - Confiugration update - Ack Tag End
+    ${ConfigurationAckEnd}=   Grep File  ./${gnb_log_filename}  </ENDCConfigurationUpdateAcknowledge>
+    ${ConfigurationAckEndAfterStrip}=     Strip String    ${ConfigurationAckEnd}
+    Should Be Equal     ${ConfigurationAckEndAfterStrip}        </ENDCConfigurationUpdateAcknowledge>
+
+Verify logs - find RIC_ENDC_CONF_UPDATE
+   ${result}   find_rmr_message.verify_logs  ${EXECDIR}  ${e2mgr_log_filename}  ${configurationupdate_message_type}  ${Meid_test1}
+   Should Be Equal As Strings    ${result}      True
+Verify logs - find RIC_ENDC_CONF_UPDATE_ACK
+   ${result1}  find_rmr_message.verify_logs  ${EXECDIR}  ${e2mgr_log_filename}  ${configurationupdate_ack_message_type}  ${Meid_test1}
+   Should Be Equal As Strings    ${result1}      True
 
 
 
diff --git a/Automation/Tests/E2Term_Initialization/E2Term_Init_Message_Test.robot b/Automation/Tests/E2Term_Initialization/E2Term_Init_Message_Test.robot
new file mode 100644 (file)
index 0000000..3ce8a50
--- /dev/null
@@ -0,0 +1,37 @@
+*** Settings ***
+Suite Setup   Prepare Enviorment
+Resource   ../Resource/resource.robot
+Resource   ../Resource/Keywords.robot
+Resource    ../Resource/scripts_variables.robot
+Library     OperatingSystem
+Library     ../Scripts/find_rmr_message.py
+Library     ../Scripts/cleanup_db.py
+Library     ../Scripts/e2t_db_script.py
+
+*** Test Cases ***
+
+Test New E2T Send Init
+    Stop E2
+
+    ${result}=    cleanup_db.flush_and_restore_without_e2t_keys
+    Should Be Equal As Strings  ${result}    True
+
+    Start E2
+
+prepare logs for tests
+    Remove log files
+    Save logs
+
+E2M Logs - Verify RMR Message
+    ${result}    find_rmr_message.verify_logs   ${EXECDIR}   ${e2mgr_log_filename}  ${E2_INIT_message_type}    ${None}
+    Should Be Equal As Strings    ${result}      True
+
+Verify E2T keys in DB
+    ${result}=    e2t_db_script.verify_e2t_addresses_key
+    Should Be Equal As Strings  ${result}    True
+
+    ${result}=    e2t_db_script.verify_e2t_instance_key
+    Should Be Equal As Strings  ${result}    True
+
+
+
diff --git a/Automation/Tests/E2Term_Initialization/__init__.robot b/Automation/Tests/E2Term_Initialization/__init__.robot
new file mode 100755 (executable)
index 0000000..7112a73
--- /dev/null
@@ -0,0 +1,20 @@
+##############################################################################
+#
+#   Copyright (c) 2019 AT&T Intellectual Property.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+##############################################################################
+
+*** Settings ***
+Documentation    E2Term-Initialization
index 1c75542..13ef989 100644 (file)
@@ -27,6 +27,7 @@ Resource   ../Resource/Keywords.robot
 Resource    ../Resource/scripts_variables.robot
 Library     OperatingSystem
 Library     ../Scripts/find_rmr_message.py
+Library     ../Scripts/rsmscripts.py
 Library     REST        ${url}
 
 
@@ -70,5 +71,7 @@ RSM RESOURCE STATUS REQUEST message not sent
     ${result}    find_rmr_message.verify_logs     ${EXECDIR}    ${rsm_log_filename}  ${RIC_RES_STATUS_REQ_message_type_successfully_sent}    ${RAN_NAME_test2}
     Should Be Equal As Strings    ${result}      False
 
-
+Verify RSM RAN info doesn't exist in redis
+   ${result}=   rsmscripts.verify_rsm_ran_info_start_false
+   Should Be Equal As Strings  ${result}    False
 
index 089c1a7..9215ebc 100644 (file)
@@ -27,19 +27,26 @@ Resource   ../Resource/Keywords.robot
 Library     OperatingSystem
 Library     Collections
 Library     REST      ${url}
-
-
-
+Resource    ../Resource/scripts_variables.robot
+Library     String
+Library     Process
+Library     ../Scripts/find_rmr_message.py
+Library     ../Scripts/find_error_script.py
+Library     ../Scripts/rsmscripts.py
 
 *** Test Cases ***
 
 Prepare Ran in Connected connectionStatus
-    Post Request setup node b endc-setup
+#    Post Request setup node b endc-setup
+    Set Headers     ${header}
+    POST        /v1/nodeb/endc-setup    ${json}
     Integer     response status       204
     Sleep  1s
-    GET      /v1/nodeb/test2
+#    GET      /v1/nodeb/test2
+    GET      /v1/nodeb/test1
     Integer  response status  200
-    String   response body ranName    test2
+#    String   response body ranName    test2
+    String   response body ranName    test1
     String   response body connectionStatus    CONNECTED
 
 Run Reset from RAN
@@ -50,3 +57,30 @@ Prepare logs for tests
     Remove log files
     Save logs
 
+#Verify logs - Reset Sent by e2adapter
+#    ${result}    find_error_script.find_error  ${EXECDIR}  ${e2adapter_log_filename}  ${E2ADAPTER_Setup_Resp}
+#    Should Be Equal As Strings    ${result}      True
+
+Verify logs - Reset Sent by simulator
+    ${Reset}=   Grep File  ./${gnb_log_filename}  ResetRequest has been sent
+    Should Be Equal     ${Reset}     gnbe2_simu: ResetRequest has been sent
+
+Verify logs - e2mgr logs - messege sent
+    ${result}    find_rmr_message.verify_logs  ${EXECDIR}  ${e2mgr_log_filename}  ${RIC_X2_RESET_REQ_message_type}  ${Meid_test1}
+    Should Be Equal As Strings    ${result}      True
+
+Verify logs - e2mgr logs - messege received
+    ${result}    find_rmr_message.verify_logs  ${EXECDIR}  ${e2mgr_log_filename}  ${RIC_X2_RESET_RESP_message_type}  ${Meid_test1}
+    Should Be Equal As Strings    ${result}      True
+
+RAN Restarted messege sent
+    ${result}    find_rmr_message.verify_logs  ${EXECDIR}  ${e2mgr_log_filename}  ${RAN_RESTARTED_message_type}  ${Meid_test1}
+    Should Be Equal As Strings    ${result}      True
+
+RSM RESOURCE STATUS REQUEST message not sent
+    ${result}    find_rmr_message.verify_logs  ${EXECDIR}    ${rsm_log_filename}  ${RIC_RES_STATUS_REQ_message_type_successfully_sent}    ${RAN_NAME_test2}
+    Should Be Equal As Strings    ${result}      False
+
+Verify RSM RAN info doesn't exist in redis
+   ${result}=   rsmscripts.verify_rsm_ran_info_start_false
+   Should Be Equal As Strings  ${result}    False
\ No newline at end of file
diff --git a/Automation/Tests/ENDC_Reset_RAN_TO_RIC/Reset_Verify_logs.robot b/Automation/Tests/ENDC_Reset_RAN_TO_RIC/Reset_Verify_logs.robot
deleted file mode 100644 (file)
index 6aeb109..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-##############################################################################
-#
-#   Copyright (c) 2019 AT&T Intellectual Property.
-#
-#   Licensed under the Apache License, Version 2.0 (the "License");
-#   you may not use this file except in compliance with the License.
-#   You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-#   Unless required by applicable law or agreed to in writing, software
-#   distributed under the License is distributed on an "AS IS" BASIS,
-#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#   See the License for the specific language governing permissions and
-#   limitations under the License.
-#
-##############################################################################
-#
-#   This source code is part of the near-RT RIC (RAN Intelligent Controller)
-#   platform project (RICP).
-#
-
-
-*** Settings ***
-Resource    ../Resource/scripts_variables.robot
-Resource   ../Resource/Keywords.robot
-Library     String
-Library     OperatingSystem
-Library     Process
-Library     ../Scripts/find_rmr_message.py
-Library     ../Scripts/find_error_script.py
-
-
-
-*** Test Cases ***
-Verify logs - Reset Sent by e2adapter
-    ${result}    find_error_script.find_error  ${EXECDIR}  ${e2adapter_log_filename}  ${E2ADAPTER_Setup_Resp}
-    Should Be Equal As Strings    ${result}      True
-
-Verify logs - e2mgr logs - messege sent
-    ${result}    find_rmr_message.verify_logs  ${EXECDIR}  ${e2mgr_log_filename}  ${RIC_X2_RESET_REQ_message_type}  ${Meid_test1}
-    Should Be Equal As Strings    ${result}      True
-
-Verify logs - e2mgr logs - messege received
-    ${result}    find_rmr_message.verify_logs  ${EXECDIR}  ${e2mgr_log_filename}  ${RIC_X2_RESET_RESP_message_type}  ${Meid_test1}
-    Should Be Equal As Strings    ${result}      True
-
-RAN Restarted messege sent
-    ${result}    find_rmr_message.verify_logs  ${EXECDIR}  ${e2mgr_log_filename}  ${RAN_RESTARTED_message_type}  ${Meid_test1}
-    Should Be Equal As Strings    ${result}      True
-
-RSM RESOURCE STATUS REQUEST message not sent
-    ${result}    find_rmr_message.verify_logs     ${EXECDIR}    ${rsm_log_filename}  ${RIC_RES_STATUS_REQ_message_type_successfully_sent}    ${RAN_NAME_test2}
-    Should Be Equal As Strings    ${result}      False
\ No newline at end of file
index 9010a68..a3ecabe 100644 (file)
@@ -27,6 +27,7 @@ Resource   ../Resource/resource.robot
 Resource   ../Resource/Keywords.robot
 Library     OperatingSystem
 Library     ../Scripts/find_rmr_message.py
+Library     ../Scripts/rsmscripts.py
 Library     REST      ${url}
 
 
@@ -57,4 +58,8 @@ RAN Restarted messege sent
 
 RSM RESOURCE STATUS REQUEST message not sent
     ${result}    find_rmr_message.verify_logs     ${EXECDIR}    ${rsm_log_filename}  ${RIC_RES_STATUS_REQ_message_type_successfully_sent}    ${RAN_NAME_test2}
-    Should Be Equal As Strings    ${result}      False
\ No newline at end of file
+    Should Be Equal As Strings    ${result}      False
+
+Verify RSM RAN info doesn't exist in redis
+   ${result}=   rsmscripts.verify_rsm_ran_info_start_false
+   Should Be Equal As Strings  ${result}    False
index e6b2492..2e5a003 100644 (file)
@@ -27,6 +27,7 @@ Resource   ../Resource/resource.robot
 Resource   ../Resource/Keywords.robot
 Library     OperatingSystem
 Library     ../Scripts/find_rmr_message.py
+Library     ../Scripts/rsmscripts.py
 Library     REST      ${url}
 
 
@@ -58,4 +59,8 @@ RAN Restarted messege sent
 
 RSM RESOURCE STATUS REQUEST message not sent
     ${result}    find_rmr_message.verify_logs     ${EXECDIR}    ${rsm_log_filename}  ${RIC_RES_STATUS_REQ_message_type_successfully_sent}    ${RAN_NAME_test2}
-    Should Be Equal As Strings    ${result}      False
\ No newline at end of file
+    Should Be Equal As Strings    ${result}      False
+
+Verify RSM RAN info doesn't exist in redis
+   ${result}=   rsmscripts.verify_rsm_ran_info_start_false
+   Should Be Equal As Strings  ${result}    False
\ No newline at end of file
diff --git a/Automation/Tests/KeepAlive/__init__.robot b/Automation/Tests/KeepAlive/__init__.robot
new file mode 100755 (executable)
index 0000000..6826893
--- /dev/null
@@ -0,0 +1,20 @@
+##############################################################################
+#
+#   Copyright (c) 2019 AT&T Intellectual Property.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+##############################################################################
+
+*** Settings ***
+Documentation    Keep Alive
diff --git a/Automation/Tests/KeepAlive/keep_alive_test.robot b/Automation/Tests/KeepAlive/keep_alive_test.robot
new file mode 100644 (file)
index 0000000..ac226a2
--- /dev/null
@@ -0,0 +1,43 @@
+##############################################################################
+#
+#   Copyright (c) 2019 AT&T Intellectual Property.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+##############################################################################
+*** Settings ***
+Suite Setup   Prepare Enviorment
+Resource   ../Resource/resource.robot
+Resource   ../Resource/Keywords.robot
+Resource   ../Resource/scripts_variables.robot
+Library    ../Scripts/find_error_script.py
+Library    OperatingSystem
+Library    Collections
+
+
+*** Test Cases ***
+
+Stop E2T
+    stop_e2
+    Sleep  1s
+
+Prepare logs for tests
+    Remove log files
+    Save logs
+
+Verify Is Dead Message Printed
+    ${result}    find_error_script.find_error     ${EXECDIR}    ${e2mgr_log_filename}  ${e2_is_dead_message_printed}
+    Should Be Equal As Strings    ${result}      True
+
+Start E2T
+    start_e2
\ No newline at end of file
index f2e589c..32e81b9 100644 (file)
@@ -50,7 +50,7 @@ Trigger X-2 Setup for load information
     String   response body connectionStatus    CONNECTED
 
 
-Verify Load information does exist in redis
+Verify Load information exists in redis
    ${result}=   loadscripts.verify_value
    Should Be Equal As Strings  ${result}    True
 
index 805d648..90002eb 100644 (file)
@@ -52,7 +52,7 @@ Prepare Ran in Connecting connectionStatus
 
 
 Verfiy Disconnected ConnectionStatus
-    Sleep    1s
+    Sleep    10s
     GET      /v1/nodeb/test1
     Integer  response status  200
     String   response body ranName    test1
diff --git a/Automation/Tests/RSM_Resource_Status/__init__.robot b/Automation/Tests/RSM_Resource_Status/__init__.robot
new file mode 100755 (executable)
index 0000000..4a008d9
--- /dev/null
@@ -0,0 +1,20 @@
+##############################################################################
+#
+#   Copyright (c) 2019 AT&T Intellectual Property.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+##############################################################################
+
+*** Settings ***
+Documentation    Resource status
diff --git a/Automation/Tests/RSM_Resource_Status/resource_status_false_start.robot b/Automation/Tests/RSM_Resource_Status/resource_status_false_start.robot
new file mode 100644 (file)
index 0000000..e6b969a
--- /dev/null
@@ -0,0 +1,56 @@
+##############################################################################
+#
+#   Copyright (c) 2019 AT&T Intellectual Property.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+##############################################################################
+
+*** Settings ***
+Suite Setup   Prepare Enviorment
+Resource   ../Resource/resource.robot
+Resource   ../Resource/Keywords.robot
+Resource   ../Resource/scripts_variables.robot
+Resource   resource_status_keywords.robot
+Library    ../Scripts/rsmscripts.py
+Library     ../Scripts/find_rmr_message.py
+Library    OperatingSystem
+Library    REST      ${url_rsm}
+Suite Teardown  Delete All Sessions
+
+
+*** Test Cases ***
+Run setup
+    rsmscripts.set_general_config_resource_status_false
+
+    Prepare Ran In Connected Status
+
+Put Http Start Request To RSM
+    Put Request Resource Status Start
+    Integer  response status  204
+
+Verify RSM RAN Info Status Is Start And True In Redis
+    ${result}=   rsmscripts.verify_rsm_ran_info_start_true
+    Should Be Equal As Strings  ${result}    True
+
+Verify RSM Enable Resource Status Is True In General Configuration In Redis
+    ${result}=   rsmscripts.verify_general_config_enable_resource_status_true
+    Should Be Equal As Strings  ${result}    True
+    
+prepare logs for tests
+    Remove log files
+    Save logs
+
+Verify RSM Resource Status Request Message Sent
+    ${result}    find_rmr_message.verify_logs     ${EXECDIR}    ${rsm_log_filename}  ${RIC_RES_STATUS_REQ_message_type_successfully_sent}    ${RAN_NAME_test1}
+    Should Be Equal As Strings    ${result}      True
\ No newline at end of file
diff --git a/Automation/Tests/RSM_Resource_Status/resource_status_false_stop.robot b/Automation/Tests/RSM_Resource_Status/resource_status_false_stop.robot
new file mode 100644 (file)
index 0000000..9864e3e
--- /dev/null
@@ -0,0 +1,56 @@
+##############################################################################
+#
+#   Copyright (c) 2019 AT&T Intellectual Property.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+##############################################################################
+
+*** Settings ***
+Suite Setup   Prepare Enviorment
+Resource   ../Resource/resource.robot
+Resource   ../Resource/Keywords.robot
+Resource   ../Resource/scripts_variables.robot
+Resource   resource_status_keywords.robot
+Library    ../Scripts/rsmscripts.py
+Library     ../Scripts/find_rmr_message.py
+Library    OperatingSystem
+Library    REST      ${url_rsm}
+Suite Teardown  Delete All Sessions
+
+
+*** Test Cases ***
+Run setup
+    rsmscripts.set_general_config_resource_status_false
+
+    Prepare Ran In Connected Status
+
+Put Http Stop Request To RSM
+    Put Request Resource Status Stop
+    Integer  response status  204
+
+Verify RSM RAN Info Status Is Stop And True In Redis
+    ${result}=   rsmscripts.verify_rsm_ran_info_stop_true
+    Should Be Equal As Strings  ${result}    True
+
+Verify RSM Enable Resource Status Is False In General Configuration In Redis
+    ${result}=   rsmscripts.verify_general_config_enable_resource_status_false
+    Should Be Equal As Strings  ${result}    True
+    
+prepare logs for tests
+    Remove log files
+    Save logs
+
+Verify RSM Resource Status Request Message Not Sent
+    ${result}    find_rmr_message.verify_logs     ${EXECDIR}    ${rsm_log_filename}  ${RIC_RES_STATUS_REQ_message_type_successfully_sent}    ${RAN_NAME_test1}
+    Should Be Equal As Strings    ${result}      False
\ No newline at end of file
diff --git a/Automation/Tests/RSM_Resource_Status/resource_status_keywords.robot b/Automation/Tests/RSM_Resource_Status/resource_status_keywords.robot
new file mode 100644 (file)
index 0000000..2dc0ec2
--- /dev/null
@@ -0,0 +1,36 @@
+##############################################################################
+#
+#   Copyright (c) 2019 AT&T Intellectual Property.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+##############################################################################
+
+*** Settings ***
+Documentation   Keywords file
+Library     ../Scripts/cleanup_db.py
+Resource   ../Resource/resource.robot
+Library    Collections
+Library    OperatingSystem
+Library    json
+Library    RequestsLibrary
+
+
+
+*** Keywords ***
+Prepare Ran In Connected Status
+    Create Session  x2setup  ${url}
+    ${headers}=  Create Dictionary    Accept=application/json    Content-Type=application/json
+    ${resp}=    Post Request   x2setup    /v1/nodeb/x2-setup    data=${json_setup_rsm_tests}    headers=${headers}
+    Should Be Equal As Strings    ${resp.status_code}    204
+
diff --git a/Automation/Tests/RSM_Resource_Status/resource_status_true_start.robot b/Automation/Tests/RSM_Resource_Status/resource_status_true_start.robot
new file mode 100644 (file)
index 0000000..21f9217
--- /dev/null
@@ -0,0 +1,54 @@
+##############################################################################
+#
+#   Copyright (c) 2019 AT&T Intellectual Property.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+##############################################################################
+
+*** Settings ***
+Suite Setup   Prepare Enviorment
+Resource   ../Resource/resource.robot
+Resource   ../Resource/Keywords.robot
+Resource   ../Resource/scripts_variables.robot
+Resource   resource_status_keywords.robot
+Library    ../Scripts/rsmscripts.py
+Library     ../Scripts/find_rmr_message.py
+Library    OperatingSystem
+Library    REST      ${url_rsm}
+Suite Teardown  Delete All Sessions
+
+
+*** Test Cases ***
+Run setup
+    Prepare Ran In Connected Status
+
+Put Http Start Request To RSM
+    Put Request Resource Status Start
+    Integer  response status  204
+
+Verify RSM RAN Info Status Is Start And True In Redis
+    ${result}=   rsmscripts.verify_rsm_ran_info_start_true
+    Should Be Equal As Strings  ${result}    True
+
+Verify RSM Enable Resource Status Is True In General Configuration In Redis
+    ${result}=   rsmscripts.verify_general_config_enable_resource_status_true
+    Should Be Equal As Strings  ${result}    True
+    
+prepare logs for RSM tests
+    Remove log files
+    Save logs
+
+Verify RSM Resource Status Request Message Sent
+    ${result}    find_rmr_message.verify_logs     ${EXECDIR}    ${rsm_log_filename}  ${RIC_RES_STATUS_REQ_message_type_successfully_sent}    ${RAN_NAME_test1}
+    Should Be Equal As Strings    ${result}      True
\ No newline at end of file
diff --git a/Automation/Tests/RSM_Resource_Status/resource_status_true_stop.robot b/Automation/Tests/RSM_Resource_Status/resource_status_true_stop.robot
new file mode 100644 (file)
index 0000000..32cab38
--- /dev/null
@@ -0,0 +1,54 @@
+##############################################################################
+#
+#   Copyright (c) 2019 AT&T Intellectual Property.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+##############################################################################
+
+*** Settings ***
+Suite Setup   Prepare Enviorment
+Resource   ../Resource/resource.robot
+Resource   ../Resource/Keywords.robot
+Resource   ../Resource/scripts_variables.robot
+Resource   resource_status_keywords.robot
+Library    ../Scripts/rsmscripts.py
+Library     ../Scripts/find_rmr_message.py
+Library    OperatingSystem
+Library    REST      ${url_rsm}
+Suite Teardown  Delete All Sessions
+
+
+*** Test Cases ***
+Run setup
+    Prepare Ran In Connected Status
+
+Put Http Stop Request To RSM
+    Put Request Resource Status Stop
+    Integer  response status  204
+
+#Verify RSM RAN Info Status Is Stop And False In Redis
+#${result}=   rsmscripts.verify_rsm_ran_info_stop_false
+#Should Be Equal As Strings  ${result}    True
+
+Verify RSM Enable Resource Status Is False In General Configuration In Redis
+    ${result}=   rsmscripts.verify_general_config_enable_resource_status_false
+    Should Be Equal As Strings  ${result}    True
+
+prepare logs for tests
+    Remove log files
+    Save logs
+
+Verify RSM Resource Status Request Message Sent
+    ${result}    find_rmr_message.verify_logs     ${EXECDIR}    ${rsm_log_filename}  ${RIC_RES_STATUS_REQ_message_type_successfully_sent}    ${RAN_NAME_test1}
+    Should Be Equal As Strings    ${result}      True
\ No newline at end of file
index 77bfb52..04dee6d 100644 (file)
@@ -29,9 +29,6 @@ Library     Collections
 Library     REST      ${url}
 
 
-*** Variables ***
-${restart_docker_sim}      docker restart gnbe2_simu
-
 
 *** Test Cases ***
 
@@ -59,11 +56,7 @@ Verfiy Shutdown ConnectionStatus
     String   response body connectionStatus    SHUT_DOWN
 
 Restart simualtor
-
-    Run And Return Rc And Output    ${restart_docker_sim}
-    ${result}=  Run And Return Rc And Output     ${docker_command}
-    Should Be Equal As Integers    ${result[1]}    ${docker_number}
-
+    Restart simulator
 
 repare Ran in Connected connectionStatus
     Post Request setup node b x-2
index c6bf324..547d14b 100644 (file)
@@ -43,7 +43,7 @@ Pre Condition for Connecting - no E2ADAPTER
 Prepare Ran in Connecting connectionStatus
     Post Request setup node b endc-setup
     Integer     response status       204
-    Sleep  1s
+    Sleep  10s
     GET      /v1/nodeb/test2
     Integer  response status  200
     String   response body ranName    test2
index 6ed5617..2593c5f 100644 (file)
@@ -36,6 +36,14 @@ Post Request setup node b x-2
     POST        /v1/nodeb/x2-setup    ${json}
 
 
+Put Request Resource Status Start
+    Set Headers     ${header}
+    PUT        /v1/general/resourcestatus  ${resource_status_start_json}
+
+
+Put Request Resource Status Stop
+    Set Headers     ${header}
+    PUT        /v1/general/resourcestatus  ${resource_status_stop_json}
 
 Get Request node b enb test1
     Sleep    1s
@@ -50,14 +58,20 @@ Get Request node b enb test2
 Remove log files
     Remove File  ${EXECDIR}/${gnb_log_filename}
     Remove File  ${EXECDIR}/${e2mgr_log_filename}
+    Remove File  ${EXECDIR}/${e2t_log_filename}
     Remove File  ${EXECDIR}/${rsm_log_filename}
+    Remove File  ${EXECDIR}/${e2e_simu_log_filename}
+    Remove File  ${EXECDIR}/${rm_sim_log_filename}
     Remove File  ${EXECDIR}/${e2adapter_log_filename}
 
 Save logs
     Sleep   1s
     Run     ${Save_sim_log}
     Run     ${Save_e2mgr_log}
+    Run     ${Save_e2t_log}
     Run     ${Save_rsm_log}
+    Run     ${Save_e2e_simu_log}
+    Run     ${Save_rm_sim_log}
     Run     ${Save_e2adapter_log}
 
 
@@ -69,6 +83,7 @@ Stop Simulator
     Run And Return Rc And Output    ${stop_simu}
 
 
+
 Prepare Simulator For Load Information
      Run And Return Rc And Output    ${stop_simu}
      Run And Return Rc And Output    ${docker_Remove}
@@ -79,11 +94,44 @@ Prepare Simulator For Load Information
      Should Be Equal As Integers    ${result[1]}    ${docker_number}
 
 Prepare Enviorment
+     ${starting_timestamp}    Evaluate   datetime.datetime.now(datetime.timezone.utc).isoformat("T")   modules=datetime 
+     ${e2t_log_filename}      Evaluate      "e2t.${SUITE NAME}.log".replace(" ","-")
+     ${e2mgr_log_filename}    Evaluate      "e2mgr.${SUITE NAME}.log".replace(" ","-")
+     ${gnb_log_filename}      Evaluate      "gnb.${SUITE NAME}.log".replace(" ","-")
+     ${rsm_log_filename}      Evaluate      "rsm.${SUITE NAME}.log".replace(" ","-")
+     ${e2e_simu_log_filename}      Evaluate      "e2e_simu.${SUITE NAME}.log".replace(" ","-")
+     ${rm_sim_log_filename}   Evaluate      "rm_sim.${SUITE NAME}.log".replace(" ","-")
+     ${e2adapter_log_filename}    Evaluate  "e2adapter.${SUITE NAME}.log".replace(" ","-")
+     ${Save_sim_log}          Evaluate   'docker logs --since ${starting_timestamp} gnbe2_simu > ${gnb_log_filename}'
+     ${Save_e2mgr_log}        Evaluate   'docker logs --since ${starting_timestamp} e2mgr > ${e2mgr_log_filename}'
+     ${Save_e2t_log}          Evaluate   'docker logs --since ${starting_timestamp} e2 > ${e2t_log_filename}'
+     ${Save_rsm_log}          Evaluate   'docker logs --since ${starting_timestamp} rsm > ${rsm_log_filename}'
+     ${Save_e2e_simu_log}     Evaluate   'docker logs --since ${starting_timestamp} e2e_simu > ${e2e_simu_log_filename}'
+     ${Save_rm_sim_log}       Evaluate   'docker logs --since ${starting_timestamp} rm_sim > ${rm_sim_log_filename}'
+     ${Save_e2adapter_log}    Evaluate   'docker logs --since ${starting_timestamp} e2adapter > ${e2adapter_log_filename}'
+     Set Suite Variable  ${e2t_log_filename}  
+     Set Suite Variable  ${e2mgr_log_filename}  
+     Set Suite Variable  ${gnb_log_filename}   
+     Set Suite Variable  ${rsm_log_filename}  
+     Set Suite Variable  ${e2e_simu_log_filename}
+     Set Suite Variable  ${rm_sim_log_filename}
+     Set Suite Variable  ${e2adapter_log_filename} 
+     Set Suite Variable  ${Save_sim_log}
+     Set Suite Variable  ${Save_e2mgr_log}
+     Set Suite Variable  ${Save_e2t_log}
+     Set Suite Variable  ${Save_rsm_log}
+     Set Suite Variable  ${Save_e2e_simu_log}
+     Set Suite Variable  ${Save_rm_sim_log}
+     Set Suite Variable  ${Save_e2adapter_log}
+       
      ${flush}  cleanup_db.flush
      Should Be Equal As Strings  ${flush}  True
      Run And Return Rc And Output    ${stop_simu}
+     Run And Return Rc And Output    ${stop_e2e_simu}
      Run And Return Rc And Output    ${docker_Remove}
+     Run And Return Rc And Output    ${docker_remove_e2e_simu}
      Run And Return Rc And Output    ${run_simu_regular}
+     Run And Return Rc And Output    ${run_e2e_simu_regular}
      Run And Return Rc And Output    ${restart_e2adapter}
      Sleep  2s
      ${result}=  Run And Return Rc And Output     ${docker_command}
@@ -95,6 +143,12 @@ Start E2
      Should Be Equal As Integers    ${result[1]}    ${docker_number}
      Sleep  2s
 
+Stop E2
+     Run And Return Rc And Output    ${stop_e2}
+     ${result}=  Run And Return Rc And Output     ${docker_command}
+     Should Be Equal As Integers    ${result[1]}    ${docker_number-1}
+     Sleep  2s
+
 Start Dbass
      Run And Return Rc And Output    ${dbass_remove}
      Run And Return Rc And Output    ${dbass_start}
@@ -106,6 +160,12 @@ Stop Dbass
      ${result}=  Run And Return Rc And Output     ${docker_command}
      Should Be Equal As Integers    ${result[1]}    ${docker_number-1}
 
+Restart simulator
+
+    Run And Return Rc And Output    ${restart_docker_sim}
+    ${result}=  Run And Return Rc And Output     ${docker_command}
+    Should Be Equal As Integers    ${result[1]}    ${docker_number}
+
 
 
 
index 4b6bcb3..90c79b2 100644 (file)
@@ -25,46 +25,45 @@ Documentation    Resource file
 
 
 *** Variables ***
-${docker_number}    6
-${docker_number-1}    5
+${docker_number}    8
+${docker_number-1}    7
 ${ip_gnb_simu} 10.0.2.15
 ${ip_e2adapter}        10.0.2.15
 ${url}   http://localhost:3800
+${url_rsm}   http://localhost:4800
+${json_setup_rsm_tests}    {"ranIp": "10.0.2.15","ranPort": 36422,"ranName":"test1"}
 ${json}    {"ranIp": "10.0.2.15","ranPort": 5577,"ranName":"test1"}
 ${endcbadjson}    {"ranIp": "a","ranPort": 49999,"ranName":"test2"}
 ${endcjson}    {"ranIp": "10.0.2.15","ranPort": 49999,"ranName":"test2"}
 ${resetcausejson}   {"cause": "misc:not-enough-user-plane-processing-resources"}
 ${resetbadcausejson}   {"cause": "bla" }
 ${resetbad1causejson}   {"cause":  }
+${resource_status_start_json}   {"enableResourceStatus":true}
+${resource_status_stop_json}    {"enableResourceStatus":false}
 ${header}  {"Content-Type": "application/json"}
 ${docker_command}  docker ps | grep Up | wc --lines
 ${run_simu_load}   docker run -d --name gnbe2_simu --env gNBipv4=localhost  --env gNBport=36422  --env duration=600000000000 --env indicationReportRate=1000000000 --env indicationInsertRate=0 -p 5577:36422/sctp snapshot.docker.ranco-dev-tools.eastus.cloudapp.azure.com:10001/gnbe2_simu:1.0.6
-#${run_simu_load}   docker run -d --name gnbe2_simu  -h gnb-sim --env gNBipv4=gnb-sim  --env gNBport=5577/sctp  --env duration=600000000000 --env indicationReportRate=1000000000 --env indicationInsertRate=0 snapshot.docker.ranco-dev-tools.eastus.cloudapp.azure.com:10001/gnbe2_simu:1.0.6
+${stop_e2e_simu}  docker stop e2e_simu
 ${stop_simu}  docker stop gnbe2_simu
 ${run_simu_regular}  docker run -d --name gnbe2_simu --env gNBipv4=localhost  --env gNBport=36422 --env duration=600000000000 --env indicationReportRate=0 --env indicationInsertRate=0 -p 5577:36422/sctp snapshot.docker.ranco-dev-tools.eastus.cloudapp.azure.com:10001/gnbe2_simu:1.0.6
-#${run_simu_regular}  docker run -d --name gnbe2_simu  -h gnb-sim --env gNBipv4=gnb-sim  --env gNBport=5577/sctp --env duration=600000000000 --env indicationReportRate=0 --env indicationInsertRate=0  snapshot.docker.ranco-dev-tools.eastus.cloudapp.azure.com:10001/gnbe2_simu:1.0.6
+${run_e2e_simu_regular}  docker run -d --name e2e_simu -p 36422:36422 --net host -it snapshot.docker.ranco-dev-tools.eastus.cloudapp.azure.com:10001/e2sim:1.4.0 sh -c "./build/e2sim 10.0.2.15 36422"
 ${docker_Remove}    docker rm gnbe2_simu
+${docker_remove_e2e_simu}    docker rm e2e_simu
 ${docker_restart}   docker restart e2mgr
 ${restart_simu}  docker restart gnbe2_simu
+${restart_e2e_simu}  docker restart e2e_simu
 ${restart_e2adapter}  docker restart e2adapter
+${restart_rsm}  docker restart rsm
 ${start_e2}  docker start e2
-${stop_docker_e2}      docker stop e2
+${stop_e2}      docker stop e2
 ${dbass_start}   docker run -d --name dbass -p 6379:6379 --env DBAAS_SERVICE_HOST=10.0.2.15  snapshot.docker.ranco-dev-tools.eastus.cloudapp.azure.com:10001/dbass:1.0.0
 ${dbass_remove}    docker rm dbass
 ${dbass_stop}      docker stop dbass
 ${restart_simu}  docker restart gnbe2_simu
-${start_e2}  docker start e2
 ${stop_docker_e2}      docker stop e2
+${restart_docker_sim}      docker restart gnbe2_simu
 ${Run_Config}       docker exec gnbe2_simu pkill gnbe2_simu -INT
-${Save_sim_log}      docker logs gnbe2_simu > gnb.log
-${Save_e2mgr_log}   docker logs e2mgr > e2mgr.log
-${Save_rsm_log}   docker logs rsm > rsm.log
-${Save_e2adapter_log}   docker logs e2adapter > e2adapter.log
 ${403_reset_message}    "Activity X2_RESET rejected. RAN current state DISCONNECTED does not allow its execution "
-${e2mgr_log_filename}    e2mgr.log
-${gnb_log_filename}    gnb.log
-${rsm_log_filename}    rsm.log
-${e2adapter_log_filename}    e2adapter.log
 
 
 
index 0c64f32..3d7e46a 100644 (file)
@@ -33,10 +33,15 @@ ${RAN_CONNECTED_message_type}     MType: 1200
 ${RAN_RESTARTED_message_type}     MType: 1210
 ${RIC_X2_RESET_REQ_message_type}    MType: 10070
 ${RIC_X2_RESET_RESP_message_type}    MType: 10070
-${failed_to_retrieve_nodeb_message}     failed to retrieve nodeB entity. RanName: test1.
+${E2_INIT_message_type}    MType: 1100
+#${failed_to_retrieve_nodeb_message}     failed to retrieve nodeB entity. RanName: test1.
+#{#RanReconnectionManager.ReconnectRan - RAN name: test1 - Failed fetching RAN from rNib. Error: dial tcp 172.17.0.2:637 #9: i/o timeout"
+${failed_to_retrieve_nodeb_message}     RAN name: test1 - Failed fetching RAN from rNib
 ${first_retry_to_retrieve_from_db}      RnibDataService.retry - retrying 1 GetNodeb
 ${third_retry_to_retrieve_from_db}      RnibDataService.retry - after 3 attempts of GetNodeb
 ${RIC_RES_STATUS_REQ_message_type_successfully_sent}     Message type: 10090 - Successfully sent RMR message
+${E2_TERM_KEEP_ALIVE_REQ_message_type_successfully_sent}     Message type: 1101 - Successfully sent RMR message
+${e2_is_dead_message_printed}     E2TShutdownManager.Shutdown - E2T e2t.att.com:38000 is Dead, RIP
 ${RAN_NAME_test1}    RAN name: test1
 ${RAN_NAME_test2}    RAN name: test2
 ${E2ADAPTER_Setup_Resp}    Send dummy ENDCX2SetupResponse to RIC
index 61aeffa..02c5f8f 100644 (file)
@@ -21,6 +21,7 @@
 #
 import config
 import redis
+import time
 
 
 def flush():
@@ -33,5 +34,25 @@ def flush():
 
     r.flushall()
 
+    r.set("{rsm},CFG:GENERAL:v1.0.0" , "{\"enableResourceStatus\":true,\"partialSuccessAllowed\":true,\"prbPeriodic\":true,\"tnlLoadIndPeriodic\":true,\"wwLoadIndPeriodic\":true,\"absStatusPeriodic\":true,\"rsrpMeasurementPeriodic\":true,\"csiPeriodic\":true,\"periodicityMs\":1,\"periodicityRsrpMeasurementMs\":3,\"periodicityCsiMs\":3}")
+
+    r.set("{e2Manager},E2TAddresses", "[\"e2t.att.com:38000\"]")
+
+    r.set("{e2Manager},E2TInstance:e2t.att.com:38000", "{\"address\":\"e2t.att.com:38000\",\"associatedRanList\":[],\"keepAliveTimestamp\":" + str(int(time.time())) + ",\"state\":\"ACTIVE\"}")
+
+    return True
+
+def flush_and_restore_without_e2t_keys():
+
+    c = config.redis_ip_address
+
+    p = config.redis_ip_port
+
+    r = redis.Redis(host=c, port=p, db=0)
+
+    r.flushall()
+
+    r.set("{rsm},CFG:GENERAL:v1.0.0" , "{\"enableResourceStatus\":true,\"partialSuccessAllowed\":true,\"prbPeriodic\":true,\"tnlLoadIndPeriodic\":true,\"wwLoadIndPeriodic\":true,\"absStatusPeriodic\":true,\"rsrpMeasurementPeriodic\":true,\"csiPeriodic\":true,\"periodicityMs\":1,\"periodicityRsrpMeasurementMs\":3,\"periodicityCsiMs\":3}")
+
     return True
 
diff --git a/Automation/Tests/Scripts/e2mdbscripts.py b/Automation/Tests/Scripts/e2mdbscripts.py
new file mode 100644 (file)
index 0000000..7b9475b
--- /dev/null
@@ -0,0 +1,49 @@
+##############################################################################
+#
+#   Copyright (c) 2019 AT&T Intellectual Property.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+##############################################################################
+
+import config
+import redis
+import cleanup_db
+import json
+
+def getRedisClientDecodeResponse():
+    c = config.redis_ip_address
+    p = config.redis_ip_port
+    return redis.Redis(host=c, port=p, db=0, decode_responses=True)
+
+def verify_ran_is_associated_with_e2t_instance(ranName, e2tAddress):
+    r = getRedisClientDecodeResponse()
+    e2tInstanceJson = r.get("{e2Manager},E2TInstance:"+e2tAddress)
+    e2tInstanceDic = json.loads(e2tInstanceJson)
+    assocRanList = e2tInstanceDic.get("associatedRanList")
+    return ranName in assocRanList
+
+# def dissociate_ran_from_e2tInstance(ranName, e2tAddress):
+#     r = getRedisClientDecodeResponse()
+#     e2tInstanceJson = r.get("{e2Manager},E2TInstance:"+e2tAddress)
+#     e2tInstanceDic = json.loads(e2tInstanceJson)
+#     assocRanList = e2tInstanceDic.get("associatedRanList")
+#     print(assocRanList)
+#     assocRanList.remove(ranName)
+#     updatedE2tInstanceJson = json.dumps(e2tInstanceDic)
+#     print(updatedE2tInstanceJson)
+#     r.set("{e2Manager},E2TInstance:"+e2tAddress, updatedE2tInstanceJson)
+#     nodebBytes = r.get("{e2Manager},RAN:"+ranName)
+#     encoded = nodebBytes.decode().replace(e2tAddress,"").encode()
+#     r.set("{e2Manager},RAN:"+ranName, encoded)
+
diff --git a/Automation/Tests/Scripts/e2t_db_script.py b/Automation/Tests/Scripts/e2t_db_script.py
new file mode 100644 (file)
index 0000000..add1a9b
--- /dev/null
@@ -0,0 +1,58 @@
+##############################################################################
+#
+#   Copyright (c) 2019 AT&T Intellectual Property.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+##############################################################################
+
+import config
+import redis
+
+
+def getRedisClientDecodeResponse():
+
+    c = config.redis_ip_address
+
+    p = config.redis_ip_port
+
+    return redis.Redis(host=c, port=p, db=0, decode_responses=True)
+
+
+def verify_e2t_addresses_key():
+
+    r = getRedisClientDecodeResponse()
+    
+    value = "[\"e2t.att.com:38000\"]"
+
+    return r.get("{e2Manager},E2TAddresses") == value
+
+
+def verify_e2t_instance_key():
+
+    r = getRedisClientDecodeResponse()
+
+    e2_address = "\"address\":\"e2t.att.com:38000\""
+    e2_associated_ran_list = "\"associatedRanList\":[]"
+    e2_state = "\"state\":\"ACTIVE\""
+
+    e2_db_instance = r.get("{e2Manager},E2TInstance:e2t.att.com:38000")
+
+    if e2_db_instance.find(e2_address) < 0:
+        return False
+    if e2_db_instance.find(e2_associated_ran_list) < 0:
+        return False
+    if e2_db_instance.find(e2_state) < 0:
+        return False
+
+    return True
\ No newline at end of file
index 0253ceb..e75d9c6 100644 (file)
@@ -31,8 +31,12 @@ def verify_logs(directory,filename,mtype,meid):
 
     for l in f:
 
-        if l.find(mtype) > 0 and l.find(meid) > 0:
-            return True
+        if (meid is not None):
+            if l.find(mtype) > 0 and l.find(meid) > 0:
+                return True
+        else:
+            if l.find(mtype) > 0:
+                return True
 
     return False
 
index 5158265..2161094 100644 (file)
@@ -22,6 +22,7 @@
 
 import config
 import redis
+import cleanup_db
 
 
 def add():
@@ -32,7 +33,7 @@ def add():
 
     r = redis.Redis(host=c, port=p, db=0)
 
-    r.flushall()
+    cleanup_db.flush()
 
     r.set("{e2Manager},ENB:02f829:007a80", "\n\x05test1\x12\t10.0.2.15\x18\xc9+ \x01*\x10\n\x0602f829\x12\x06007a800\x01:3\b\x01\x12/\bc\x12\x0f02f829:0007ab50\x1a\x040102\"\x0602f829*\n\n\b\b\x01\x10\x01\x18\x04 \x040\x01")
 
index 5cc862b..aec4b59 100644 (file)
 import redis
 import config
 
-
-def verify_value():
+def getRedisClient():
 
     c = config.redis_ip_address
 
     p = config.redis_ip_port
 
-    r = redis.Redis(host=c, port=p, db=0)
+    return redis.Redis(host=c, port=p, db=0)
+
+
+def verify_value():
+
+    r = getRedisClient()
 
     value = "\b\x98\xf7\xdd\xa3\xc7\xb4\x83\xde\x15\x12\x11\n\x0f02f829:0007ab00"
 
@@ -43,11 +47,7 @@ def verify_value():
 
 def add():
 
-    c = config.redis_ip_address
-
-    p = config.redis_ip_port
-
-    r = redis.Redis(host=c, port=p, db=0)
+    r = getRedisClient()
 
     r.set("{e2Manager},LOAD:test1", "\b\x98\xf7\xdd\xa3\xc7\xb4\x83\xde\x15\x12\x11\n\x0f02f829:0007ab00")
 
@@ -59,13 +59,10 @@ def add():
 
 def verify():
 
-    c = config.redis_ip_address
-
-    p = config.redis_ip_port
-
-    r = redis.Redis(host=c, port=p, db=0)
+    r = getRedisClient()
 
     if r.exists("{e2Manager},LOAD:test1"):
         return True
     else:
         return False
+
diff --git a/Automation/Tests/Scripts/rsmscripts.py b/Automation/Tests/Scripts/rsmscripts.py
new file mode 100644 (file)
index 0000000..db2a869
--- /dev/null
@@ -0,0 +1,97 @@
+##############################################################################
+#
+#   Copyright (c) 2019 AT&T Intellectual Property.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+##############################################################################
+
+import config
+import redis
+import json
+
+
+def getRedisClientDecodeResponse():
+
+    c = config.redis_ip_address
+
+    p = config.redis_ip_port
+
+    return redis.Redis(host=c, port=p, db=0, decode_responses=True)
+
+def set_general_config_resource_status_false():
+
+    r = getRedisClientDecodeResponse()
+    r.set("{rsm},CFG:GENERAL:v1.0.0" , "{\"enableResourceStatus\":false,\"partialSuccessAllowed\":true,\"prbPeriodic\":true,\"tnlLoadIndPeriodic\":true,\"wwLoadIndPeriodic\":true,\"absStatusPeriodic\":true,\"rsrpMeasurementPeriodic\":true,\"csiPeriodic\":true,\"periodicityMs\":1,\"periodicityRsrpMeasurementMs\":3,\"periodicityCsiMs\":3}")
+
+def verify_rsm_ran_info_start_false():
+
+    r = getRedisClientDecodeResponse()
+    
+    value = "{\"ranName\":\"test1\",\"enb1MeasurementId\":1,\"enb2MeasurementId\":0,\"action\":\"start\",\"actionStatus\":false}"
+
+    return r.get("{rsm},RAN:test1") == value
+
+
+def verify_rsm_ran_info_start_true():
+
+    r = getRedisClientDecodeResponse()
+
+    rsmInfoStr = r.get("{rsm},RAN:test1")
+    rsmInfoJson = json.loads(rsmInfoStr)
+
+    response = rsmInfoJson["ranName"] == "test1" and rsmInfoJson["enb1MeasurementId"] == 1 and rsmInfoJson["enb2MeasurementId"] != 1 and rsmInfoJson["action"] == "start" and rsmInfoJson["actionStatus"] == True
+
+    return response
+
+
+def verify_rsm_ran_info_stop_false():
+
+    r = getRedisClientDecodeResponse()
+
+    rsmInfoStr = r.get("{rsm},RAN:test1")
+    rsmInfoJson = json.loads(rsmInfoStr)
+
+    response = rsmInfoJson["ranName"] == "test1" and rsmInfoJson["enb1MeasurementId"] == 1 and rsmInfoJson["action"] == "stop" and rsmInfoJson["actionStatus"] == False
+
+    return response
+
+
+def verify_rsm_ran_info_stop_true():
+
+    r = getRedisClientDecodeResponse()
+
+    rsmInfoStr = r.get("{rsm},RAN:test1")
+    rsmInfoJson = json.loads(rsmInfoStr)
+
+    response = rsmInfoJson["ranName"] == "test1" and rsmInfoJson["action"] == "stop" and rsmInfoJson["actionStatus"] == True
+
+    return response
+
+def verify_general_config_enable_resource_status_true():
+
+    r = getRedisClientDecodeResponse()
+
+    configStr = r.get("{rsm},CFG:GENERAL:v1.0.0")
+    configJson = json.loads(configStr)
+
+    return configJson["enableResourceStatus"] == True
+
+def verify_general_config_enable_resource_status_false():
+
+    r = getRedisClientDecodeResponse()
+
+    configStr = r.get("{rsm},CFG:GENERAL:v1.0.0")
+    configJson = json.loads(configStr)
+
+    return configJson["enableResourceStatus"] == False
\ No newline at end of file
index bd87ad6..f0c36f7 100644 (file)
@@ -42,7 +42,7 @@ Pre Condition for Connecting - no simu
 Reset - 400 http - 403 wrong state
     Post Request setup node b x-2
     Integer     response status       204
-    Sleep  1s
+    Sleep  10s
     GET      /v1/nodeb/test1
     String   response body connectionStatus    DISCONNECTED
     Set Headers     ${header}
index b5dfdc8..337bf7a 100644 (file)
@@ -27,6 +27,8 @@ Resource   ../Resource/Keywords.robot
 Resource    ../Resource/scripts_variables.robot
 Library     OperatingSystem
 Library     ../Scripts/find_rmr_message.py
+Library     ../Scripts/rsmscripts.py
+Library     ../Scripts/e2mdbscripts.py
 Library     REST      ${url}
 
 *** Test Cases ***
@@ -42,6 +44,7 @@ X2 - Get Nodeb
     Integer  response body port     5577
     String   response body connectionStatus    CONNECTED
     String   response body nodeType     ENB
+    String   response body associatedE2tInstanceAddress     e2t.att.com:38000  
     String   response body enb enbType     MACRO_ENB
     Integer  response body enb servedCells 0 pci  99
     String   response body enb servedCells 0 cellId   02f829:0007ab00
@@ -66,3 +69,13 @@ RSM RESOURCE STATUS REQUEST message sent
     ${result}    find_rmr_message.verify_logs     ${EXECDIR}    ${rsm_log_filename}  ${RIC_RES_STATUS_REQ_message_type_successfully_sent}    ${RAN_NAME_test1}
     Should Be Equal As Strings    ${result}      True
 
+Verify RSM RAN info exists in redis
+   ${result}=   rsmscripts.verify_rsm_ran_info_start_false
+   Should Be Equal As Strings  ${result}    True
+
+Verify RAN is associated with E2T instance
+   ${result}    e2mdbscripts.verify_ran_is_associated_with_e2t_instance     test1    e2t.att.com:38000
+   Should Be True    ${result}
+
+
+
 #   platform project (RICP).
 #
 
-
 *** Settings ***
-Resource    ../Resource/scripts_variables.robot
+Suite Setup   Prepare Enviorment
+Resource   ../Resource/resource.robot
 Resource   ../Resource/Keywords.robot
-Library     String
+Resource    ../Resource/scripts_variables.robot
 Library     OperatingSystem
-Library     Process
 Library     ../Scripts/find_rmr_message.py
-
-
+Library     ../Scripts/rsmscripts.py
+Library     ../Scripts/e2mdbscripts.py
+Library     REST      ${url}
 
 *** Test Cases ***
-Verify logs - Reset Sent by simulator
-    ${Reset}=   Grep File  ./gnb.log  ResetRequest has been sent
-    Should Be Equal     ${Reset}     gnbe2_simu: ResetRequest has been sent
+X2 - Setup Test 1
+    Post Request setup node b x-2
+    Integer     response status       204
 
-Verify logs - e2mgr logs - messege sent
-    ${result}    find_rmr_message.verify_logs  ${EXECDIR}  ${e2mgr_log_filename}  ${RIC_X2_RESET_REQ_message_type}  ${Meid_test1}
-    Should Be Equal As Strings    ${result}      True
+X2 - Setup Test 2
+    Post Request setup node b x-2
+    Integer     response status       204
 
-Verify logs - e2mgr logs - messege received
-    ${result}    find_rmr_message.verify_logs  ${EXECDIR}  ${e2mgr_log_filename}  ${RIC_X2_RESET_RESP_message_type}  ${Meid_test1}
-    Should Be Equal As Strings    ${result}      True
+X2 - Get Nodeb
+    Get Request Node B Enb test1
+    Integer  response status  200
+    String   response body ranName    test1
+    String   response body associatedE2tInstanceAddress     e2t.att.com:38000  
+
+prepare logs for tests
+    Remove log files
+    Save logs
 
-RAN Restarted messege sent
-    ${result}    find_rmr_message.verify_logs  ${EXECDIR}  ${e2mgr_log_filename}  ${RAN_RESTARTED_message_type}  ${Meid_test1}
+X2 - RAN Connected message going to be sent
+    ${result}    find_rmr_message.verify_logs     ${EXECDIR}   ${e2mgr_log_filename}  ${RAN_CONNECTED_message_type}    ${Meid_test1}
     Should Be Equal As Strings    ${result}      True
 
 RSM RESOURCE STATUS REQUEST message sent
     ${result}    find_rmr_message.verify_logs     ${EXECDIR}    ${rsm_log_filename}  ${RIC_RES_STATUS_REQ_message_type_successfully_sent}    ${RAN_NAME_test1}
-    Should Be Equal As Strings    ${result}      True
\ No newline at end of file
+    Should Be Equal As Strings    ${result}      True
+
+Verify RSM RAN info exists in redis
+   ${result}=   rsmscripts.verify_rsm_ran_info_start_false
+   Should Be Equal As Strings  ${result}    True
+
+Verify RAN is associated with E2T instance
+   ${result}    e2mdbscripts.verify_ran_is_associated_with_e2t_instance     test1    e2t.att.com:38000
+   Should Be True    ${result}
diff --git a/Automation/Tests/X2-Setup/x2_setup_existing_not_assoc_test.robot b/Automation/Tests/X2-Setup/x2_setup_existing_not_assoc_test.robot
new file mode 100644 (file)
index 0000000..457ca9c
--- /dev/null
@@ -0,0 +1,71 @@
+##############################################################################
+#
+#   Copyright (c) 2019 AT&T Intellectual Property.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+##############################################################################
+
+*** Settings ***
+Suite Setup   Prepare Enviorment
+Resource   ../Resource/resource.robot
+Resource   ../Resource/Keywords.robot
+Resource    ../Resource/scripts_variables.robot
+Library     OperatingSystem
+Library     ../Scripts/find_rmr_message.py
+Library     ../Scripts/rsmscripts.py
+Library     ../Scripts/e2mdbscripts.py
+Library     REST      ${url}
+
+*** Test Cases ***
+X2 - Setup Test 1
+    Post Request setup node b x-2
+    Integer     response status       204
+
+Restart Simulator
+    Restart Simulator
+
+Verify RAN is NOT associated with E2T instance
+   ${result}    e2mdbscripts.verify_ran_is_associated_with_e2t_instance     test1    e2t.att.com:38000
+   Should Be True    ${result} == False
+
+
+X2 - Setup Test 2
+    Post Request setup node b x-2
+    Integer     response status       204
+
+X2 - Get Nodeb
+    Get Request Node B Enb test1
+    Integer  response status  200
+    String   response body ranName    test1
+    String   response body associatedE2tInstanceAddress     e2t.att.com:38000  
+
+prepare logs for tests
+    Remove log files
+    Save logs
+
+X2 - RAN Connected message going to be sent
+    ${result}    find_rmr_message.verify_logs     ${EXECDIR}   ${e2mgr_log_filename}  ${RAN_CONNECTED_message_type}    ${Meid_test1}
+    Should Be Equal As Strings    ${result}      True
+
+RSM RESOURCE STATUS REQUEST message sent
+    ${result}    find_rmr_message.verify_logs     ${EXECDIR}    ${rsm_log_filename}  ${RIC_RES_STATUS_REQ_message_type_successfully_sent}    ${RAN_NAME_test1}
+    Should Be Equal As Strings    ${result}      True
+
+Verify RSM RAN info exists in redis
+   ${result}=   rsmscripts.verify_rsm_ran_info_start_false
+   Should Be Equal As Strings  ${result}    True
+
+Verify RAN is associated with E2T instance
+   ${result}    e2mdbscripts.verify_ran_is_associated_with_e2t_instance     test1    e2t.att.com:38000
+   Should Be True    ${result}
index 780d966..6f50b7e 100644 (file)
@@ -27,7 +27,11 @@ Resource   ../Resource/Keywords.robot
 Library     OperatingSystem
 Library     Collections
 Library     REST      ${url}
-
+Resource    ../Resource/scripts_variables.robot
+Library     String
+Library     Process
+Library     ../Scripts/find_rmr_message.py
+Library     ../Scripts/rsmscripts.py
 
 
 
@@ -50,3 +54,26 @@ Prepare logs for tests
     Remove log files
     Save logs
 
+Verify logs - Reset Sent by simulator
+    ${Reset}=   Grep File  ./${gnb_log_filename}  ResetRequest has been sent
+    Should Be Equal     ${Reset}     gnbe2_simu: ResetRequest has been sent
+
+Verify logs - e2mgr logs - messege sent
+    ${result}    find_rmr_message.verify_logs  ${EXECDIR}  ${e2mgr_log_filename}  ${RIC_X2_RESET_REQ_message_type}  ${Meid_test1}
+    Should Be Equal As Strings    ${result}      True
+
+Verify logs - e2mgr logs - messege received
+    ${result}    find_rmr_message.verify_logs  ${EXECDIR}  ${e2mgr_log_filename}  ${RIC_X2_RESET_RESP_message_type}  ${Meid_test1}
+    Should Be Equal As Strings    ${result}      True
+
+RAN Restarted messege sent
+    ${result}    find_rmr_message.verify_logs  ${EXECDIR}  ${e2mgr_log_filename}  ${RAN_RESTARTED_message_type}  ${Meid_test1}
+    Should Be Equal As Strings    ${result}      True
+
+RSM RESOURCE STATUS REQUEST message sent
+    ${result}    find_rmr_message.verify_logs     ${EXECDIR}    ${rsm_log_filename}  ${RIC_RES_STATUS_REQ_message_type_successfully_sent}    ${RAN_NAME_test1}
+    Should Be Equal As Strings    ${result}      True
+
+Verify RSM RAN info exists in redis
+   ${result}=   rsmscripts.verify_rsm_ran_info_start_false
+   Should Be Equal As Strings  ${result}    True
\ No newline at end of file
index 02f69f1..8dc416b 100644 (file)
@@ -27,9 +27,12 @@ Resource   ../Resource/Keywords.robot
 Library     OperatingSystem
 Library     Collections
 Library     REST      ${url}
-
-
-
+Resource    ../Resource/scripts_variables.robot
+Library     String
+Library     Process
+Library     ../Scripts/find_rmr_message.py
+Library     ../Scripts/find_error_script.py
+Suite Teardown  Start Dbass with 4 dockers
 
 
 *** Test Cases ***
@@ -49,9 +52,30 @@ Stop RNIB
 
 Run Reset from RAN
     Run    ${Run_Config}
-    Sleep   1s
+    Sleep   60s
 
 Prepare logs for tests
     Remove log files
     Save logs
 
+Verify logs - Reset Sent by simulator
+    ${Reset}=   Grep File  ./${gnb_log_filename}  ResetRequest has been sent
+    Should Be Equal     ${Reset}     gnbe2_simu: ResetRequest has been sent
+
+Verify logs for restart received
+    ${result}    find_rmr_message.verify_logs     ${EXECDIR}  ${e2mgr_log_filename}  ${RIC_X2_RESET_REQ_message_type}    ${Meid_test1}
+    Should Be Equal As Strings    ${result}      True
+
+Verify for error on retrying
+    ${result}    find_error_script.find_error    ${EXECDIR}     ${e2mgr_log_filename}   ${failed_to_retrieve_nodeb_message}
+    Should Be Equal As Strings    ${result}      True
+
+
+*** Keywords ***
+Start Dbass with 4 dockers
+     Run And Return Rc And Output    ${dbass_remove}
+     Run And Return Rc And Output    ${dbass_start}
+     Sleep  5s
+     ${result}=  Run And Return Rc And Output     ${docker_command}
+     Should Be Equal As Integers    ${result[1]}    ${docker_number-1}
+
diff --git a/Automation/Tests/X2_Reset_RAN_TO_RIC_Unhappy/Reset_Verify_logs.robot b/Automation/Tests/X2_Reset_RAN_TO_RIC_Unhappy/Reset_Verify_logs.robot
deleted file mode 100644 (file)
index 1328660..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-##############################################################################
-#
-#   Copyright (c) 2019 AT&T Intellectual Property.
-#
-#   Licensed under the Apache License, Version 2.0 (the "License");
-#   you may not use this file except in compliance with the License.
-#   You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-#   Unless required by applicable law or agreed to in writing, software
-#   distributed under the License is distributed on an "AS IS" BASIS,
-#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#   See the License for the specific language governing permissions and
-#   limitations under the License.
-#
-##############################################################################
-#
-#   This source code is part of the near-RT RIC (RAN Intelligent Controller)
-#   platform project (RICP).
-#
-
-
-*** Settings ***
-Resource    ../Resource/scripts_variables.robot
-Library     String
-Library     OperatingSystem
-Library     Process
-Resource   ../Resource/Keywords.robot
-Library     ../Scripts/find_rmr_message.py
-Library     ../Scripts/find_error_script.py
-Test Teardown  Start Dbass with 4 dockers
-
-
-
-*** Test Cases ***
-Verify logs - Reset Sent by simulator
-    ${Reset}=   Grep File  ./gnb.log  ResetRequest has been sent
-    Should Be Equal     ${Reset}     gnbe2_simu: ResetRequest has been sent
-
-Verify logs for restart received
-    ${result}    find_rmr_message.verify_logs     ${EXECDIR}  ${e2mgr_log_filename}  ${RIC_X2_RESET_REQ_message_type}    ${Meid_test1}
-    Should Be Equal As Strings    ${result}      True
-
-Verify for error on retrying
-    ${result}    find_error_script.find_error    ${EXECDIR}     ${e2mgr_log_filename}   ${failed_to_retrieve_nodeb_message}
-    Should Be Equal As Strings    ${result}      True
-
-
-*** Keywords ***
-Start Dbass with 4 dockers
-     Run And Return Rc And Output    ${dbass_remove}
-     Run And Return Rc And Output    ${dbass_start}
-     ${result}=  Run And Return Rc And Output     ${docker_command}
-     Should Be Equal As Integers    ${result[1]}    ${docker_number-1}
-     Sleep  5s
index 83a60cb..3227fe7 100644 (file)
@@ -27,6 +27,7 @@ Resource   ../Resource/resource.robot
 Resource   ../Resource/Keywords.robot
 Library     OperatingSystem
 Library     ../Scripts/find_rmr_message.py
+Library     ../Scripts/rsmscripts.py
 Library     REST      ${url}
 
 
@@ -57,4 +58,8 @@ RAN Restarted messege sent
 
 RSM RESOURCE STATUS REQUEST message sent
     ${result}    find_rmr_message.verify_logs     ${EXECDIR}    ${rsm_log_filename}  ${RIC_RES_STATUS_REQ_message_type_successfully_sent}    ${RAN_NAME_test1}
-    Should Be Equal As Strings    ${result}      True
\ No newline at end of file
+    Should Be Equal As Strings    ${result}      True
+
+Verify RSM RAN info exists in redis
+   ${result}=   rsmscripts.verify_rsm_ran_info_start_false
+   Should Be Equal As Strings  ${result}    True
\ No newline at end of file
index b0c1669..d4103e8 100644 (file)
@@ -27,6 +27,7 @@ Resource   ../Resource/resource.robot
 Resource   ../Resource/Keywords.robot
 Library     OperatingSystem
 Library     ../Scripts/find_rmr_message.py
+Library     ../Scripts/rsmscripts.py
 Library     REST      ${url}
 
 
@@ -58,4 +59,8 @@ RAN Restarted messege sent
 
 RSM RESOURCE STATUS REQUEST message sent
     ${result}    find_rmr_message.verify_logs     ${EXECDIR}    ${rsm_log_filename}  ${RIC_RES_STATUS_REQ_message_type_successfully_sent}    ${RAN_NAME_test1}
-    Should Be Equal As Strings    ${result}      True
\ No newline at end of file
+    Should Be Equal As Strings    ${result}      True
+
+Verify RSM RAN info exists in redis
+   ${result}=   rsmscripts.verify_rsm_ran_info_start_false
+   Should Be Equal As Strings  ${result}    True
\ No newline at end of file
index 74db25b..4f9561b 100644 (file)
 #   platform project (RICP).
 #
 
-FROM nexus3.o-ran-sc.org:10004/bldr-ubuntu16-c-go:2-u16.04-nng as ubuntu
+FROM nexus3.o-ran-sc.org:10004/bldr-ubuntu16-c-go:3-u16.04-nng as ubuntu
 
 WORKDIR /opt/E2Manager
 COPY . . 
 ENV PATH=$PATH:/usr/local/go/bin:/usr/lib/go-1.12/bin
 #RUN git clone https://gerrit.o-ran-sc.org/r/ric-plt/lib/rmr && cd rmr/; mkdir build; cd build; /opt/bin/cmake -DDEV_PKG=1 ..; make install
 # Install RMr library and dev files
-RUN wget --content-disposition  https://packagecloud.io/o-ran-sc/staging/packages/debian/stretch/rmr_1.10.0_amd64.deb/download.deb
-RUN dpkg -i rmr_1.10.0_amd64.deb
-RUN wget --content-disposition https://packagecloud.io/o-ran-sc/staging/packages/debian/stretch/rmr-dev_1.10.0_amd64.deb/download.deb
-RUN dpkg -i rmr-dev_1.10.0_amd64.deb
+RUN wget --content-disposition  https://packagecloud.io/o-ran-sc/staging/packages/debian/stretch/rmr_1.13.0_amd64.deb/download.deb
+RUN dpkg -i rmr_1.13.0_amd64.deb
+RUN wget --content-disposition https://packagecloud.io/o-ran-sc/staging/packages/debian/stretch/rmr-dev_1.13.0_amd64.deb/download.deb
+RUN dpkg -i rmr-dev_1.13.0_amd64.deb
 
 RUN cd 3rdparty/asn1codec && make
 RUN go build app/main.go
@@ -45,7 +45,8 @@ ENV LD_LIBRARY_PATH=/usr/local/lib
 # Setting allocfreetrace=1 causes every allocation to be profiled and a stack trace printed on each object's allocation and free.
 ENV GODEBUG=cgocheck=2,clobberfree=1,gcstoptheworld=2,allocfreetrace=0
 ENV RIC_ID="bbbccc-abcd0e/20"
-RUN go test ./...
+ENV RMR_SEED_RT=/opt/E2Manager/router_test.txt
+RUN go-acc $(go list ./... | grep -v e2mgr/mocks | grep -v e2mgr/tests |grep -v e2mgr/e2managererrors| grep -v e2mgr/enums)
 
 FROM ubuntu:16.04
 
index dd0875d..443b7eb 100644 (file)
@@ -21,9 +21,9 @@
 package main
 
 import (
+       "e2mgr/clients"
        "e2mgr/configuration"
        "e2mgr/controllers"
-       "e2mgr/converters"
        "e2mgr/httpserver"
        "e2mgr/logger"
        "e2mgr/managers"
@@ -37,12 +37,12 @@ import (
        "e2mgr/services/rmrsender"
        "fmt"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
+       "gerrit.o-ran-sc.org/r/ric-plt/sdlgo"
+       "net/http"
        "os"
        "strconv"
 )
 
-const MAX_RNIB_POOL_INSTANCES = 4
-
 func main() {
        config := configuration.ParseConfiguration()
        logLevel, _ := logger.LogLevelTokenToLevel(config.Logging.LogLevel)
@@ -51,32 +51,34 @@ func main() {
                fmt.Printf("#app.main - failed to initialize logger, error: %s", err)
                os.Exit(1)
        }
-       rNibWriter.Init("e2Manager", MAX_RNIB_POOL_INSTANCES)
-       defer rNibWriter.Close()
-       reader.Init("e2Manager", MAX_RNIB_POOL_INSTANCES)
-       defer reader.Close()
-       rnibDataService := services.NewRnibDataService(logger, config, reader.GetRNibReader, rNibWriter.GetRNibWriter)
+       db := sdlgo.NewDatabase()
+       sdl := sdlgo.NewSdlInstance("e2Manager", db)
+       defer sdl.Close()
+       rnibDataService := services.NewRnibDataService(logger, config, reader.GetRNibReader(sdl), rNibWriter.GetRNibWriter( sdl))
        var msgImpl *rmrCgo.Context
        rmrMessenger := msgImpl.Init("tcp:"+strconv.Itoa(config.Rmr.Port), config.Rmr.MaxMsgSize, 0, logger)
        rmrSender := rmrsender.NewRmrSender(logger, rmrMessenger)
        ranSetupManager := managers.NewRanSetupManager(logger, rmrSender, rnibDataService)
-       ranReconnectionManager := managers.NewRanReconnectionManager(logger, config, rnibDataService, ranSetupManager)
-       ranStatusChangeManager := managers.NewRanStatusChangeManager(logger, rmrSender)
-       x2SetupResponseConverter := converters.NewX2SetupResponseConverter(logger)
-       x2SetupResponseManager := managers.NewX2SetupResponseManager(x2SetupResponseConverter)
-       x2SetupFailureResponseConverter := converters.NewX2SetupFailureResponseConverter(logger)
-       x2SetupFailureResponseManager := managers.NewX2SetupFailureResponseManager(x2SetupFailureResponseConverter)
-       rmrNotificationHandlerProvider := rmrmsghandlerprovider.NewNotificationHandlerProvider(logger, rnibDataService, ranReconnectionManager, ranStatusChangeManager, rmrSender, x2SetupResponseManager, x2SetupFailureResponseManager)
+       e2tInstancesManager := managers.NewE2TInstancesManager(rnibDataService, logger)
+       e2tShutdownManager := managers.NewE2TShutdownManager(logger, rnibDataService, e2tInstancesManager)
+       e2tKeepAliveWorker := managers.NewE2TKeepAliveWorker(logger, rmrSender, e2tInstancesManager, e2tShutdownManager, config)
+       routingManagerClient := clients.NewRoutingManagerClient(logger, config, &http.Client{})
+       rmrNotificationHandlerProvider := rmrmsghandlerprovider.NewNotificationHandlerProvider()
+       rmrNotificationHandlerProvider.Init(logger, config, rnibDataService, rmrSender, ranSetupManager, e2tInstancesManager, routingManagerClient)
 
        notificationManager := notificationmanager.NewNotificationManager(logger, rmrNotificationHandlerProvider)
        rmrReceiver := rmrreceiver.NewRmrReceiver(logger, rmrMessenger, notificationManager)
 
-       defer (*rmrMessenger).Close()
+       e2tInstancesManager.ResetKeepAliveTimestampsForAllE2TInstances()
+
+       defer rmrMessenger.Close()
 
        go rmrReceiver.ListenAndHandle()
+       go e2tKeepAliveWorker.Execute()
 
-       httpMsgHandlerProvider := httpmsghandlerprovider.NewIncomingRequestHandlerProvider(logger, rmrSender, config, rnibDataService, ranSetupManager)
+       httpMsgHandlerProvider := httpmsghandlerprovider.NewIncomingRequestHandlerProvider(logger, rmrSender, config, rnibDataService, ranSetupManager, e2tInstancesManager)
        rootController := controllers.NewRootController(rnibDataService)
        nodebController := controllers.NewNodebController(logger, httpMsgHandlerProvider)
-       httpserver.Run(config.Http.Port, rootController, nodebController)
-}
+       e2tController := controllers.NewE2TController(logger, httpMsgHandlerProvider)
+       _ = httpserver.Run(logger, config.Http.Port, rootController, nodebController, e2tController)
+}
\ No newline at end of file
diff --git a/E2Manager/clients/http_client.go b/E2Manager/clients/http_client.go
new file mode 100644 (file)
index 0000000..e3692f5
--- /dev/null
@@ -0,0 +1,30 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+
+package clients
+
+import (
+       "io"
+       "net/http"
+)
+
+type HttpClient interface {
+       Post(url, contentType string, body io.Reader) (resp *http.Response, err error)
+}
\ No newline at end of file
diff --git a/E2Manager/clients/routing_manager_client.go b/E2Manager/clients/routing_manager_client.go
new file mode 100644 (file)
index 0000000..c584f5b
--- /dev/null
@@ -0,0 +1,108 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+package clients
+
+import (
+       "bytes"
+       "e2mgr/configuration"
+       "e2mgr/e2managererrors"
+       "e2mgr/logger"
+       "e2mgr/models"
+       "encoding/json"
+       "net/http"
+)
+
+const (
+       AddE2TInstanceApiSuffix            = "e2t"
+       AssociateRanToE2TInstanceApiSuffix = "associate-ran-to-e2t"
+       DissociateRanE2TInstanceApiSuffix  = "dissociate-ran"
+)
+
+type RoutingManagerClient struct {
+       logger     *logger.Logger
+       config     *configuration.Configuration
+       httpClient HttpClient
+}
+
+type IRoutingManagerClient interface {
+       AddE2TInstance(e2tAddress string) error
+       AssociateRanToE2TInstance(e2tAddress string, ranName string) error
+       DissociateRanE2TInstance(e2tAddress string, ranName string) error
+}
+
+func NewRoutingManagerClient(logger *logger.Logger, config *configuration.Configuration, httpClient HttpClient) *RoutingManagerClient {
+       return &RoutingManagerClient{
+               logger:     logger,
+               config:     config,
+               httpClient: httpClient,
+       }
+}
+
+func (c *RoutingManagerClient) AddE2TInstance(e2tAddress string) error {
+
+       data := models.NewRoutingManagerE2TData(e2tAddress)
+       url := c.config.RoutingManager.BaseUrl + AddE2TInstanceApiSuffix
+
+       return c.PostMessage(data, url)
+}
+
+func (c *RoutingManagerClient) AssociateRanToE2TInstance(e2tAddress string, ranName string) error {
+
+       data := models.NewRoutingManagerE2TData(e2tAddress, ranName)
+       url := c.config.RoutingManager.BaseUrl + AssociateRanToE2TInstanceApiSuffix
+
+       return c.PostMessage(data, url)
+}
+
+func (c *RoutingManagerClient) DissociateRanE2TInstance(e2tAddress string, ranName string) error {
+
+       data := models.NewRoutingManagerE2TData(e2tAddress, ranName)
+       url := c.config.RoutingManager.BaseUrl + DissociateRanE2TInstanceApiSuffix
+
+       return c.PostMessage(data, url)
+}
+
+func (c *RoutingManagerClient) PostMessage(data *models.RoutingManagerE2TData, url string) error {
+       marshaled, err := json.Marshal(data)
+
+       if err != nil {
+               return e2managererrors.NewRoutingManagerError()
+       }
+
+       body := bytes.NewBuffer(marshaled)
+       c.logger.Infof("[E2M -> Routing Manager] #RoutingManagerClient.PostMessage - url: %s, request body: %+v", url, body)
+
+       resp, err := c.httpClient.Post(url, "application/json", body)
+
+       if err != nil {
+               c.logger.Errorf("#RoutingManagerClient.PostMessage - failed sending request. error: %s", err)
+               return e2managererrors.NewRoutingManagerError()
+       }
+
+       defer resp.Body.Close()
+
+       if resp.StatusCode >= http.StatusOK && resp.StatusCode < http.StatusMultipleChoices {
+               c.logger.Infof("[Routing Manager -> E2M] #RoutingManagerClient.PostMessage - success. http status code: %d", resp.StatusCode)
+               return nil
+       }
+
+       c.logger.Errorf("[Routing Manager -> E2M] #RoutingManagerClient.PostMessage - failure. http status code: %d", resp.StatusCode)
+       return e2managererrors.NewRoutingManagerError()
+}
\ No newline at end of file
diff --git a/E2Manager/clients/routing_manager_client_test.go b/E2Manager/clients/routing_manager_client_test.go
new file mode 100644 (file)
index 0000000..2d02cfd
--- /dev/null
@@ -0,0 +1,180 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+
+package clients
+
+import (
+       "bytes"
+       "e2mgr/configuration"
+       "e2mgr/logger"
+       "e2mgr/mocks"
+       "e2mgr/models"
+       "encoding/json"
+       "github.com/pkg/errors"
+       "github.com/stretchr/testify/assert"
+       "io/ioutil"
+       "net/http"
+       "testing"
+)
+
+const E2TAddress = "10.0.2.15:38000"
+const RanName = "test1"
+
+
+func initRoutingManagerClientTest(t *testing.T) (*RoutingManagerClient, *mocks.HttpClientMock, *configuration.Configuration) {
+       logger := initLog(t)
+       config := &configuration.Configuration{}
+       config.RoutingManager.BaseUrl = "http://iltlv740.intl.att.com:8080/ric/v1/handles/"
+       httpClientMock := &mocks.HttpClientMock{}
+       rmClient := NewRoutingManagerClient(logger, config, httpClientMock)
+       return rmClient, httpClientMock, config
+}
+
+func TestAddE2TInstanceSuccess(t *testing.T) {
+       rmClient, httpClientMock, config := initRoutingManagerClientTest(t)
+
+       data := models.NewRoutingManagerE2TData(E2TAddress)
+       marshaled, _ := json.Marshal(data)
+       body := bytes.NewBuffer(marshaled)
+       url := config.RoutingManager.BaseUrl + "e2t"
+       respBody := ioutil.NopCloser(bytes.NewBufferString(""))
+       httpClientMock.On("Post", url, "application/json", body).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil)
+       err := rmClient.AddE2TInstance(E2TAddress)
+       assert.Nil(t, err)
+}
+
+func TestAddE2TInstanceHttpPostFailure(t *testing.T) {
+       rmClient, httpClientMock, config := initRoutingManagerClientTest(t)
+
+       data := models.NewRoutingManagerE2TData(E2TAddress)
+       marshaled, _ := json.Marshal(data)
+       body := bytes.NewBuffer(marshaled)
+       url := config.RoutingManager.BaseUrl + "e2t"
+       httpClientMock.On("Post", url, "application/json", body).Return(&http.Response{}, errors.New("error"))
+       err := rmClient.AddE2TInstance(E2TAddress)
+       assert.NotNil(t, err)
+}
+
+func TestAddE2TInstanceFailure(t *testing.T) {
+       rmClient, httpClientMock, config := initRoutingManagerClientTest(t)
+
+       data := models.NewRoutingManagerE2TData(E2TAddress)
+       marshaled, _ := json.Marshal(data)
+       body := bytes.NewBuffer(marshaled)
+       url := config.RoutingManager.BaseUrl + "e2t"
+       respBody := ioutil.NopCloser(bytes.NewBufferString(""))
+       httpClientMock.On("Post", url, "application/json", body).Return(&http.Response{StatusCode: http.StatusBadRequest, Body:respBody}, nil)
+       err := rmClient.AddE2TInstance(E2TAddress)
+       assert.NotNil(t, err)
+}
+
+func TestAssociateRanToE2TInstance_Success(t *testing.T) {
+       rmClient, httpClientMock, config := initRoutingManagerClientTest(t)
+
+       data := models.NewRoutingManagerE2TData(E2TAddress,RanName)
+       marshaled, _ := json.Marshal(data)
+       body := bytes.NewBuffer(marshaled)
+       url := config.RoutingManager.BaseUrl + AssociateRanToE2TInstanceApiSuffix
+       respBody := ioutil.NopCloser(bytes.NewBufferString(""))
+       httpClientMock.On("Post", url, "application/json", body).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil)
+       err := rmClient.AssociateRanToE2TInstance(E2TAddress, RanName)
+       assert.Nil(t, err)
+}
+
+func TestAssociateRanToE2TInstance_RoutingManagerError(t *testing.T) {
+       rmClient, httpClientMock, config := initRoutingManagerClientTest(t)
+
+       data := models.NewRoutingManagerE2TData(E2TAddress,RanName)
+       marshaled, _ := json.Marshal(data)
+       body := bytes.NewBuffer(marshaled)
+       url := config.RoutingManager.BaseUrl + AssociateRanToE2TInstanceApiSuffix
+       httpClientMock.On("Post", url, "application/json", body).Return(&http.Response{}, errors.New("error"))
+       err := rmClient.AssociateRanToE2TInstance(E2TAddress, RanName)
+       assert.NotNil(t, err)
+}
+
+func TestAssociateRanToE2TInstance_RoutingManager_400(t *testing.T) {
+       rmClient, httpClientMock, config := initRoutingManagerClientTest(t)
+
+       data := models.NewRoutingManagerE2TData(E2TAddress,RanName)
+       marshaled, _ := json.Marshal(data)
+       body := bytes.NewBuffer(marshaled)
+       url := config.RoutingManager.BaseUrl + AssociateRanToE2TInstanceApiSuffix
+       respBody := ioutil.NopCloser(bytes.NewBufferString(""))
+       httpClientMock.On("Post", url, "application/json", body).Return(&http.Response{StatusCode: http.StatusBadRequest, Body:respBody}, nil)
+       err := rmClient.AssociateRanToE2TInstance(E2TAddress, RanName)
+       assert.NotNil(t, err)
+}
+
+func TestDissociateRanE2TInstance_Success(t *testing.T) {
+       rmClient, httpClientMock, config := initRoutingManagerClientTest(t)
+
+       data := models.NewRoutingManagerE2TData(E2TAddress,RanName)
+       marshaled, _ := json.Marshal(data)
+       body := bytes.NewBuffer(marshaled)
+       url := config.RoutingManager.BaseUrl + DissociateRanE2TInstanceApiSuffix
+       respBody := ioutil.NopCloser(bytes.NewBufferString(""))
+       httpClientMock.On("Post", url, "application/json", body).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil)
+       err := rmClient.DissociateRanE2TInstance(E2TAddress, RanName)
+       assert.Nil(t, err)
+}
+
+func TestDissociateRanE2TInstance_RoutingManagerError(t *testing.T) {
+       rmClient, httpClientMock, config := initRoutingManagerClientTest(t)
+
+       data := models.NewRoutingManagerE2TData(E2TAddress,RanName)
+       marshaled, _ := json.Marshal(data)
+       body := bytes.NewBuffer(marshaled)
+       url := config.RoutingManager.BaseUrl + DissociateRanE2TInstanceApiSuffix
+       httpClientMock.On("Post", url, "application/json", body).Return(&http.Response{}, errors.New("error"))
+       err := rmClient.DissociateRanE2TInstance(E2TAddress, RanName)
+       assert.NotNil(t, err)
+}
+
+func TestDissociateRanE2TInstance_RoutingManager_400(t *testing.T) {
+       rmClient, httpClientMock, config := initRoutingManagerClientTest(t)
+
+       data := models.NewRoutingManagerE2TData(E2TAddress,RanName)
+       marshaled, _ := json.Marshal(data)
+       body := bytes.NewBuffer(marshaled)
+       url := config.RoutingManager.BaseUrl + DissociateRanE2TInstanceApiSuffix
+       respBody := ioutil.NopCloser(bytes.NewBufferString(""))
+       httpClientMock.On("Post", url, "application/json", body).Return(&http.Response{StatusCode: http.StatusBadRequest, Body:respBody}, nil)
+       err := rmClient.DissociateRanE2TInstance(E2TAddress, RanName)
+       assert.NotNil(t, err)
+}
+
+// TODO: extract to test_utils
+func initLog(t *testing.T) *logger.Logger {
+       log, err := logger.InitLogger(logger.InfoLevel)
+       if err != nil {
+               t.Errorf("#delete_all_request_handler_test.TestHandleSuccessFlow - failed to initialize logger, error: %s", err)
+       }
+       return log
+}
+
+//func TestAddE2TInstanceInteg(t *testing.T) {
+//     logger := initLog(t)
+//     config := configuration.ParseConfiguration()
+//     httpClient := &http.Client{}
+//     rmClient := NewRoutingManagerClient(logger, config, httpClient)
+//     err := rmClient.AddE2TInstance(E2TAddress)
+//     assert.Nil(t, err)
+//}
index 43fbd71..d37c497 100644 (file)
@@ -36,19 +36,24 @@ type Configuration struct {
                Port       int
                MaxMsgSize int
        }
-       NotificationResponseBuffer int
-       BigRedButtonTimeoutSec     int
-       MaxConnectionAttempts      int
-       MaxRnibConnectionAttempts  int
-       RnibRetryIntervalMs                int
+       RoutingManager struct {
+               BaseUrl    string
+       }
+       NotificationResponseBuffer   int
+       BigRedButtonTimeoutSec       int
+       MaxConnectionAttempts        int
+       MaxRnibConnectionAttempts    int
+       RnibRetryIntervalMs          int
+       KeepAliveResponseTimeoutMs       int
+       KeepAliveDelayMs             int
 }
 
-func ParseConfiguration() *Configuration{
+func ParseConfiguration() *Configuration {
        viper.SetConfigType("yaml")
        viper.SetConfigName("configuration")
        viper.AddConfigPath("E2Manager/resources/")
-       viper.AddConfigPath("./resources/")  //For production
-       viper.AddConfigPath("../resources/") //For test under Docker
+       viper.AddConfigPath("./resources/")     //For production
+       viper.AddConfigPath("../resources/")    //For test under Docker
        viper.AddConfigPath("../../resources/") //For test under Docker
        err := viper.ReadInConfig()
        if err != nil {
@@ -56,37 +61,45 @@ func ParseConfiguration() *Configuration{
        }
 
        config := Configuration{}
-       config.fillRmrConfig(viper.Sub("rmr"))
-       config.fillHttpConfig(viper.Sub("http"))
-       config.fillLoggingConfig(viper.Sub("logging"))
-
+       config.populateRmrConfig(viper.Sub("rmr"))
+       config.populateHttpConfig(viper.Sub("http"))
+       config.populateLoggingConfig(viper.Sub("logging"))
+       config.populateRoutingManagerConfig(viper.Sub("routingManager"))
        config.NotificationResponseBuffer = viper.GetInt("notificationResponseBuffer")
        config.BigRedButtonTimeoutSec = viper.GetInt("bigRedButtonTimeoutSec")
        config.MaxConnectionAttempts = viper.GetInt("maxConnectionAttempts")
        config.MaxRnibConnectionAttempts = viper.GetInt("maxRnibConnectionAttempts")
        config.RnibRetryIntervalMs = viper.GetInt("rnibRetryIntervalMs")
+       config.KeepAliveResponseTimeoutMs = viper.GetInt("keepAliveResponseTimeoutMs")
+       config.KeepAliveDelayMs = viper.GetInt("KeepAliveDelayMs")
        return &config
 }
 
-func (c *Configuration)fillLoggingConfig(logConfig *viper.Viper) {
+func (c *Configuration) populateLoggingConfig(logConfig *viper.Viper) {
        if logConfig == nil {
-               panic(fmt.Sprintf("#configuration.fillLoggingConfig - failed to fill logging configuration: The entry 'logging' not found\n"))
+               panic(fmt.Sprintf("#configuration.populateLoggingConfig - failed to populate logging configuration: The entry 'logging' not found\n"))
        }
        c.Logging.LogLevel = logConfig.GetString("logLevel")
 }
 
-func (c *Configuration)fillHttpConfig(httpConfig *viper.Viper) {
+func (c *Configuration) populateHttpConfig(httpConfig *viper.Viper) {
        if httpConfig == nil {
-               panic(fmt.Sprintf("#configuration.fillHttpConfig - failed to fill HTTP configuration: The entry 'http' not found\n"))
+               panic(fmt.Sprintf("#configuration.populateHttpConfig - failed to populate HTTP configuration: The entry 'http' not found\n"))
        }
        c.Http.Port = httpConfig.GetInt("port")
 }
 
-func (c *Configuration)fillRmrConfig(rmrConfig *viper.Viper) {
+func (c *Configuration) populateRmrConfig(rmrConfig *viper.Viper) {
        if rmrConfig == nil {
-               panic(fmt.Sprintf("#configuration.fillRmrConfig - failed to fill RMR configuration: The entry 'rmr' not found\n"))
+               panic(fmt.Sprintf("#configuration.populateRmrConfig - failed to populate RMR configuration: The entry 'rmr' not found\n"))
        }
        c.Rmr.Port = rmrConfig.GetInt("port")
        c.Rmr.MaxMsgSize = rmrConfig.GetInt("maxMsgSize")
 }
 
+func (c *Configuration) populateRoutingManagerConfig(rmConfig *viper.Viper) {
+       if rmConfig == nil {
+               panic(fmt.Sprintf("#configuration.populateRoutingManagerConfig - failed to populate Routing Manager configuration: The entry 'routingManager' not found\n"))
+       }
+       c.RoutingManager.BaseUrl = rmConfig.GetString("baseUrl")
+}
index e1c5088..ec16c1f 100644 (file)
@@ -36,6 +36,8 @@ func TestParseConfigurationSuccess(t *testing.T) {
        assert.Equal(t, "info", config.Logging.LogLevel)
        assert.Equal(t, 100, config.NotificationResponseBuffer)
        assert.Equal(t, 5, config.BigRedButtonTimeoutSec)
+       assert.Equal(t, 1500, config.KeepAliveResponseTimeoutMs)
+       assert.Equal(t, 500, config.KeepAliveDelayMs)
 }
 
 func TestParseConfigurationFileNotFoundFailure(t *testing.T) {
@@ -70,6 +72,7 @@ func TestRmrConfigNotFoundFailure(t *testing.T) {
        yamlMap := map[string]interface{}{
                "logging": map[string]interface{}{"logLevel": "info"},
                "http":    map[string]interface{}{"port": 3800},
+               "routingManager":    map[string]interface{}{"baseUrl": "http://iltlv740.intl.att.com:8080/ric/v1/handles/"},
        }
        buf, err := yaml.Marshal(yamlMap)
        if err != nil {
@@ -79,7 +82,7 @@ func TestRmrConfigNotFoundFailure(t *testing.T) {
        if err != nil {
                t.Errorf("#TestRmrConfigNotFoundFailure - failed to write configuration file: %s\n", configPath)
        }
-       assert.PanicsWithValue(t, "#configuration.fillRmrConfig - failed to fill RMR configuration: The entry 'rmr' not found\n", func() { ParseConfiguration() })
+       assert.PanicsWithValue(t, "#configuration.populateRmrConfig - failed to populate RMR configuration: The entry 'rmr' not found\n", func() { ParseConfiguration() })
 }
 
 func TestLoggingConfigNotFoundFailure(t *testing.T) {
@@ -98,6 +101,7 @@ func TestLoggingConfigNotFoundFailure(t *testing.T) {
        yamlMap := map[string]interface{}{
                "rmr":  map[string]interface{}{"port": 3801, "maxMsgSize": 4096},
                "http": map[string]interface{}{"port": 3800},
+               "routingManager":    map[string]interface{}{"baseUrl": "http://iltlv740.intl.att.com:8080/ric/v1/handles/"},
        }
        buf, err := yaml.Marshal(yamlMap)
        if err != nil {
@@ -107,7 +111,7 @@ func TestLoggingConfigNotFoundFailure(t *testing.T) {
        if err != nil {
                t.Errorf("#TestRmrConfigNotFoundFailure - failed to write configuration file: %s\n", configPath)
        }
-       assert.PanicsWithValue(t, "#configuration.fillLoggingConfig - failed to fill logging configuration: The entry 'logging' not found\n",
+       assert.PanicsWithValue(t, "#configuration.populateLoggingConfig - failed to populate logging configuration: The entry 'logging' not found\n",
                func() { ParseConfiguration() })
 }
 
@@ -127,6 +131,7 @@ func TestHttpConfigNotFoundFailure(t *testing.T) {
        yamlMap := map[string]interface{}{
                "rmr":     map[string]interface{}{"port": 3801, "maxMsgSize": 4096},
                "logging": map[string]interface{}{"logLevel": "info"},
+               "routingManager":    map[string]interface{}{"baseUrl": "http://iltlv740.intl.att.com:8080/ric/v1/handles/"},
        }
        buf, err := yaml.Marshal(yamlMap)
        if err != nil {
@@ -136,6 +141,36 @@ func TestHttpConfigNotFoundFailure(t *testing.T) {
        if err != nil {
                t.Errorf("#TestHttpConfigNotFoundFailure - failed to write configuration file: %s\n", configPath)
        }
-       assert.PanicsWithValue(t, "#configuration.fillHttpConfig - failed to fill HTTP configuration: The entry 'http' not found\n",
+       assert.PanicsWithValue(t, "#configuration.populateHttpConfig - failed to populate HTTP configuration: The entry 'http' not found\n",
+               func() { ParseConfiguration() })
+}
+
+func TestRoutingManagerConfigNotFoundFailure(t *testing.T) {
+       configPath := "../resources/configuration.yaml"
+       configPathTmp := "../resources/configuration.yaml_tmp"
+       err := os.Rename(configPath, configPathTmp)
+       if err != nil {
+               t.Errorf("#TestRoutingManagerConfigNotFoundFailure - failed to rename configuration file: %s\n", configPath)
+       }
+       defer func() {
+               err = os.Rename(configPathTmp, configPath)
+               if err != nil {
+                       t.Errorf("#TestRoutingManagerConfigNotFoundFailure - failed to rename configuration file: %s\n", configPath)
+               }
+       }()
+       yamlMap := map[string]interface{}{
+               "rmr":     map[string]interface{}{"port": 3801, "maxMsgSize": 4096},
+               "logging": map[string]interface{}{"logLevel": "info"},
+               "http": map[string]interface{}{"port": 3800},
+       }
+       buf, err := yaml.Marshal(yamlMap)
+       if err != nil {
+               t.Errorf("#TestRoutingManagerConfigNotFoundFailure - failed to marshal configuration map\n")
+       }
+       err = ioutil.WriteFile("../resources/configuration.yaml", buf, 0644)
+       if err != nil {
+               t.Errorf("#TestRoutingManagerConfigNotFoundFailure - failed to write configuration file: %s\n", configPath)
+       }
+       assert.PanicsWithValue(t, "#configuration.populateRoutingManagerConfig - failed to populate Routing Manager configuration: The entry 'routingManager' not found\n",
                func() { ParseConfiguration() })
 }
index feb9ae0..d5f8e1e 100644 (file)
@@ -1,4 +1,4 @@
 # The Jenkins job requires a tag to build the Docker image.
 # Global-JJB script assumes this file is in the repo root.
 ---
-tag: 2.0.10
+tag: 3.0.3
diff --git a/E2Manager/controllers/e2t_controller.go b/E2Manager/controllers/e2t_controller.go
new file mode 100644 (file)
index 0000000..2d95542
--- /dev/null
@@ -0,0 +1,121 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package controllers
+
+import (
+       "e2mgr/e2managererrors"
+       "e2mgr/logger"
+       "e2mgr/models"
+       "e2mgr/providers/httpmsghandlerprovider"
+       "encoding/json"
+       "net/http"
+       "net/http/httputil"
+       "strings"
+)
+
+type IE2TController interface {
+       GetE2TInstances(writer http.ResponseWriter, r *http.Request)
+}
+
+type E2TController struct {
+       logger          *logger.Logger
+       handlerProvider *httpmsghandlerprovider.IncomingRequestHandlerProvider
+}
+
+func NewE2TController(logger *logger.Logger, handlerProvider *httpmsghandlerprovider.IncomingRequestHandlerProvider) *E2TController {
+       return &E2TController{
+               logger:          logger,
+               handlerProvider: handlerProvider,
+       }
+}
+
+func (c *E2TController) GetE2TInstances(writer http.ResponseWriter, r *http.Request) {
+       c.logger.Infof("[Client -> E2 Manager] #E2TController.GetE2TInstances - request: %v", c.prettifyRequest(r))
+       c.handleRequest(writer, &r.Header, httpmsghandlerprovider.GetE2TInstancesRequest, nil, false)
+}
+
+func (c *E2TController) handleRequest(writer http.ResponseWriter, header *http.Header, requestName httpmsghandlerprovider.IncomingRequest, request models.Request, validateHeader bool) {
+
+       handler, err := c.handlerProvider.GetHandler(requestName)
+
+       if err != nil {
+               c.handleErrorResponse(err, writer)
+               return
+       }
+
+       response, err := handler.Handle(request)
+
+       if err != nil {
+               c.handleErrorResponse(err, writer)
+               return
+       }
+
+       if response == nil {
+               writer.WriteHeader(http.StatusNoContent)
+               c.logger.Infof("[E2 Manager -> Client] #E2TController.handleRequest - status response: %v", http.StatusNoContent)
+               return
+       }
+
+       result, err := response.Marshal()
+
+       if err != nil {
+               c.handleErrorResponse(err, writer)
+               return
+       }
+
+       c.logger.Infof("[E2 Manager -> Client] #E2TController.handleRequest - response: %s", result)
+       writer.Header().Set("Content-Type", "application/json")
+       writer.Write(result)
+}
+
+func (c *E2TController) handleErrorResponse(err error, writer http.ResponseWriter) {
+
+       var errorResponseDetails models.ErrorResponse
+       var httpError int
+
+       if err != nil {
+               switch err.(type) {
+               case *e2managererrors.RnibDbError:
+                       e2Error, _ := err.(*e2managererrors.RnibDbError)
+                       errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
+                       httpError = http.StatusInternalServerError
+               default:
+                       e2Error := e2managererrors.NewInternalError()
+                       errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
+                       httpError = http.StatusInternalServerError
+               }
+       }
+
+       errorResponse, _ := json.Marshal(errorResponseDetails)
+
+       c.logger.Errorf("[E2 Manager -> Client] #E2TController.handleErrorResponse - http status: %d, error response: %+v", httpError, errorResponseDetails)
+
+       writer.Header().Set("Content-Type", "application/json")
+       writer.WriteHeader(httpError)
+       _, err = writer.Write(errorResponse)
+
+       if err != nil {
+               c.logger.Errorf("#E2TController.handleErrorResponse - Cannot send response. writer:%v", writer)
+       }
+}
+
+func (c *E2TController) prettifyRequest(request *http.Request) string {
+       dump, _ := httputil.DumpRequest(request, true)
+       requestPrettyPrint := strings.Replace(string(dump), "\r\n", " ", -1)
+       return strings.Replace(requestPrettyPrint, "\n", "", -1)
+}
index 912b4a9..cbfa7d6 100644 (file)
@@ -176,7 +176,7 @@ func (c *NodebController) handleRequest(writer http.ResponseWriter, header *http
 
        c.logger.Infof("[E2 Manager -> Client] #NodebController.handleRequest - response: %s", result)
        writer.Header().Set("Content-Type", "application/json")
-       writer.Write([]byte(result))
+       writer.Write(result)
 }
 
 func (c *NodebController) validateRequestHeader(header *http.Header) error {
@@ -228,7 +228,10 @@ func (c *NodebController) handleErrorResponse(err error, writer http.ResponseWri
                        e2Error, _ := err.(*e2managererrors.ResourceNotFoundError)
                        errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
                        httpError = http.StatusNotFound
-
+               case *e2managererrors.E2TInstanceAbsenceError:
+                       e2Error, _ := err.(*e2managererrors.E2TInstanceAbsenceError)
+                       errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
+                       httpError = http.StatusServiceUnavailable
                default:
                        e2Error := e2managererrors.NewInternalError()
                        errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
index 47b217b..f819138 100644 (file)
@@ -30,7 +30,6 @@ import (
        "e2mgr/mocks"
        "e2mgr/models"
        "e2mgr/providers/httpmsghandlerprovider"
-       "e2mgr/rNibWriter"
        "e2mgr/rmrCgo"
        "e2mgr/services"
        "e2mgr/services/rmrsender"
@@ -39,7 +38,6 @@ import (
        "fmt"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
-       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
        "github.com/gorilla/mux"
        "github.com/pkg/errors"
        "github.com/stretchr/testify/assert"
@@ -67,30 +65,27 @@ type controllerGetNodebIdListTestContext struct {
        expectedJsonResponse string
 }
 
-func setupControllerTest(t *testing.T) (*NodebController, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.RmrMessengerMock) {
+func setupControllerTest(t *testing.T) (*NodebController, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.RmrMessengerMock, *mocks.E2TInstancesManagerMock) {
        log := initLog(t)
        config := configuration.ParseConfiguration()
 
        rmrMessengerMock := &mocks.RmrMessengerMock{}
        readerMock := &mocks.RnibReaderMock{}
-       readerProvider := func() reader.RNibReader {
-               return readerMock
-       }
+
        writerMock := &mocks.RnibWriterMock{}
-       writerProvider := func() rNibWriter.RNibWriter {
-               return writerMock
-       }
-       rnibDataService := services.NewRnibDataService(log, config, readerProvider, writerProvider)
+
+       rnibDataService := services.NewRnibDataService(log, config, readerMock, writerMock)
        rmrSender := getRmrSender(rmrMessengerMock, log)
        ranSetupManager := managers.NewRanSetupManager(log, rmrSender, rnibDataService)
-       handlerProvider := httpmsghandlerprovider.NewIncomingRequestHandlerProvider(log, rmrSender, config, rnibDataService, ranSetupManager)
+       e2tInstancesManager := &mocks.E2TInstancesManagerMock{}
+       handlerProvider := httpmsghandlerprovider.NewIncomingRequestHandlerProvider(log, rmrSender, config, rnibDataService, ranSetupManager, e2tInstancesManager)
        controller := NewNodebController(log, handlerProvider)
-       return controller, readerMock, writerMock, rmrMessengerMock
+       return controller, readerMock, writerMock, rmrMessengerMock, e2tInstancesManager
 }
 
 func TestX2SetupInvalidBody(t *testing.T) {
 
-       controller, _, _, _ := setupControllerTest(t)
+       controller, _, _, _, _ := setupControllerTest(t)
 
        header := http.Header{}
        header.Set("Content-Type", "application/json")
@@ -108,20 +103,23 @@ func TestX2SetupInvalidBody(t *testing.T) {
 
 func TestX2SetupSuccess(t *testing.T) {
 
-       controller, readerMock, writerMock, rmrMessengerMock := setupControllerTest(t)
+       controller, readerMock, writerMock, rmrMessengerMock, _ := setupControllerTest(t)
 
        ranName := "test"
-       nb := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
+       nb := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, AssociatedE2TInstanceAddress:"10.0.2.15:8989"}
        readerMock.On("GetNodeb", ranName).Return(nb, nil)
+       var nbUpdated = *nb
+       nbUpdated.ConnectionAttempts = 0
+       writerMock.On("UpdateNodebInfo", &nbUpdated).Return(nil)
 
-       var nbUpdated = &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1}
-       writerMock.On("UpdateNodebInfo", nbUpdated).Return(nil)
+       var nbUpdated2 = &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1, AssociatedE2TInstanceAddress:"10.0.2.15:8989"}
+       writerMock.On("UpdateNodebInfo", nbUpdated2).Return(nil)
 
        payload := e2pdus.PackedX2setupRequest
-       xaction := []byte(ranName)
-       msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ranName, &payload, &xaction)
+       var xAction []byte
+       msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ranName, &payload, &xAction)
 
-       rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, nil)
+       rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg, nil)
 
        header := http.Header{}
        header.Set("Content-Type", "application/json")
@@ -134,22 +132,26 @@ func TestX2SetupSuccess(t *testing.T) {
        assert.Equal(t, http.StatusNoContent, writer.Result().StatusCode)
 }
 
+
 func TestEndcSetupSuccess(t *testing.T) {
 
-       controller, readerMock, writerMock, rmrMessengerMock := setupControllerTest(t)
+       controller, readerMock, writerMock, rmrMessengerMock, _ := setupControllerTest(t)
 
        ranName := "test"
-       nb := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST}
+       nb := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST, AssociatedE2TInstanceAddress:"10.0.2.15:8989"}
        readerMock.On("GetNodeb", ranName).Return(nb, nil)
+       var nbUpdated = *nb
+       nbUpdated.ConnectionAttempts = 0
+       writerMock.On("UpdateNodebInfo", &nbUpdated).Return(nil)
 
-       var nbUpdated = &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST, ConnectionAttempts: 1}
-       writerMock.On("UpdateNodebInfo", nbUpdated).Return(nil)
+       var nbUpdated2 = &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST, ConnectionAttempts: 1, AssociatedE2TInstanceAddress:"10.0.2.15:8989"}
+       writerMock.On("UpdateNodebInfo", nbUpdated2).Return(nil)
 
        payload := e2pdus.PackedEndcX2setupRequest
-       xaction := []byte(ranName)
-       msg := rmrCgo.NewMBuf(rmrCgo.RIC_ENDC_X2_SETUP_REQ, len(payload), ranName, &payload, &xaction)
+       var xAction[]byte
+       msg := rmrCgo.NewMBuf(rmrCgo.RIC_ENDC_X2_SETUP_REQ, len(payload), ranName, &payload, &xAction)
 
-       rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, nil)
+       rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg, nil)
 
        header := http.Header{}
        header.Set("Content-Type", "application/json")
@@ -163,7 +165,7 @@ func TestEndcSetupSuccess(t *testing.T) {
 }
 
 func TestShutdownHandlerRnibError(t *testing.T) {
-       controller, readerMock, _, _ := setupControllerTest(t)
+       controller, readerMock, _, _, _ := setupControllerTest(t)
 
        rnibErr := &common.ResourceNotFoundError{}
        var nbIdentityList []*entities.NbIdentity
@@ -180,7 +182,7 @@ func TestShutdownHandlerRnibError(t *testing.T) {
 }
 
 func controllerGetNodebTestExecuter(t *testing.T, context *controllerGetNodebTestContext) {
-       controller, readerMock, _, _ := setupControllerTest(t)
+       controller, readerMock, _, _, _ := setupControllerTest(t)
        writer := httptest.NewRecorder()
        readerMock.On("GetNodeb", context.ranName).Return(context.nodebInfo, context.rnibError)
        req, _ := http.NewRequest("GET", "/nodeb", nil)
@@ -192,7 +194,7 @@ func controllerGetNodebTestExecuter(t *testing.T, context *controllerGetNodebTes
 }
 
 func controllerGetNodebIdListTestExecuter(t *testing.T, context *controllerGetNodebIdListTestContext) {
-       controller, readerMock, _, _ := setupControllerTest(t)
+       controller, readerMock, _, _, _ := setupControllerTest(t)
        writer := httptest.NewRecorder()
        readerMock.On("GetListNodebIds").Return(context.nodebIdList, context.rnibError)
        req, _ := http.NewRequest("GET", "/nodeb/ids", nil)
@@ -289,7 +291,7 @@ func TestControllerGetNodebIdListInternal(t *testing.T) {
 }
 
 func TestHeaderValidationFailed(t *testing.T) {
-       controller, _, _, _ := setupControllerTest(t)
+       controller, _, _, _, _ := setupControllerTest(t)
 
        writer := httptest.NewRecorder()
 
@@ -306,7 +308,7 @@ func TestHeaderValidationFailed(t *testing.T) {
 }
 
 func TestShutdownStatusNoContent(t *testing.T) {
-       controller, readerMock, _, _ := setupControllerTest(t)
+       controller, readerMock, _, _, _ := setupControllerTest(t)
 
        var rnibError error
        nbIdentityList := []*entities.NbIdentity{}
@@ -319,7 +321,7 @@ func TestShutdownStatusNoContent(t *testing.T) {
 }
 
 func TestHandleInternalError(t *testing.T) {
-       controller, _, _, _ := setupControllerTest(t)
+       controller, _, _, _, _ := setupControllerTest(t)
 
        writer := httptest.NewRecorder()
        err := e2managererrors.NewInternalError()
@@ -333,7 +335,7 @@ func TestHandleInternalError(t *testing.T) {
 }
 
 func TestHandleCommandAlreadyInProgressError(t *testing.T) {
-       controller, _, _, _ := setupControllerTest(t)
+       controller, _, _, _, _ := setupControllerTest(t)
        writer := httptest.NewRecorder()
        err := e2managererrors.NewCommandAlreadyInProgressError()
 
@@ -345,8 +347,22 @@ func TestHandleCommandAlreadyInProgressError(t *testing.T) {
        assert.Equal(t, errorResponse.Message, err.Message)
 }
 
+func TestHandleE2TInstanceAbsenceError(t *testing.T) {
+       controller, _, _, _, _ := setupControllerTest(t)
+
+       writer := httptest.NewRecorder()
+       err := e2managererrors.NewE2TInstanceAbsenceError()
+
+       controller.handleErrorResponse(err, writer)
+       var errorResponse = parseJsonRequest(t, writer.Body)
+
+       assert.Equal(t, http.StatusServiceUnavailable, writer.Result().StatusCode)
+       assert.Equal(t, errorResponse.Code, err.Code)
+       assert.Equal(t, errorResponse.Message, err.Message)
+}
+
 func TestValidateHeaders(t *testing.T) {
-       controller, _, _, _ := setupControllerTest(t)
+       controller, _, _, _, _ := setupControllerTest(t)
 
        header := http.Header{}
        header.Set("Content-Type", "application/json")
@@ -376,12 +392,12 @@ func initLog(t *testing.T) *logger.Logger {
 }
 
 func TestX2ResetHandleSuccessfulRequestedCause(t *testing.T) {
-       controller, readerMock, _, rmrMessengerMock := setupControllerTest(t)
+       controller, readerMock, _, rmrMessengerMock, _ := setupControllerTest(t)
 
        ranName := "test1"
        payload := []byte{0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x05, 0x40, 0x01, 0x40}
-       xaction := []byte(ranName)
-       msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET, len(payload), ranName, &payload, &xaction)
+       var xAction []byte
+       msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET, len(payload), ranName, &payload, &xAction)
        rmrMessengerMock.On("SendMsg", msg, mock.Anything).Return(msg, nil)
 
        writer := httptest.NewRecorder()
@@ -401,14 +417,14 @@ func TestX2ResetHandleSuccessfulRequestedCause(t *testing.T) {
 }
 
 func TestX2ResetHandleSuccessfulRequestedDefault(t *testing.T) {
-       controller, readerMock, _, rmrMessengerMock := setupControllerTest(t)
+       controller, readerMock, _, rmrMessengerMock, _ := setupControllerTest(t)
 
        ranName := "test1"
        // o&m intervention
        payload := []byte{0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x05, 0x40, 0x01, 0x64}
-       xaction := []byte(ranName)
-       msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET, len(payload), ranName, &payload, &xaction)
-       rmrMessengerMock.On("SendMsg", msg).Return(msg, nil)
+       var xAction []byte
+       msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET, len(payload), ranName, &payload, &xAction)
+       rmrMessengerMock.On("SendMsg", msg, true).Return(msg, nil)
 
        writer := httptest.NewRecorder()
 
@@ -426,7 +442,7 @@ func TestX2ResetHandleSuccessfulRequestedDefault(t *testing.T) {
 }
 
 func TestX2ResetHandleFailureInvalidBody(t *testing.T) {
-       controller, _, _, _ := setupControllerTest(t)
+       controller, _, _, _ , _:= setupControllerTest(t)
 
        ranName := "test1"
 
@@ -443,7 +459,7 @@ func TestX2ResetHandleFailureInvalidBody(t *testing.T) {
 }
 
 func TestHandleErrorResponse(t *testing.T) {
-       controller, _, _, _ := setupControllerTest(t)
+       controller, _, _, _ , _:= setupControllerTest(t)
 
        writer := httptest.NewRecorder()
        controller.handleErrorResponse(e2managererrors.NewRnibDbError(), writer)
@@ -481,5 +497,5 @@ func TestHandleErrorResponse(t *testing.T) {
 func getRmrSender(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *rmrsender.RmrSender {
        rmrMessenger := rmrCgo.RmrMessenger(rmrMessengerMock)
        rmrMessengerMock.On("Init", tests.GetPort(), tests.MaxMsgSize, tests.Flags, log).Return(&rmrMessenger)
-       return rmrsender.NewRmrSender(log, &rmrMessenger)
+       return rmrsender.NewRmrSender(log, rmrMessenger)
 }
index 289e20b..42d0bdf 100644 (file)
@@ -24,12 +24,10 @@ import (
        "e2mgr/configuration"
        "e2mgr/logger"
        "e2mgr/mocks"
-       "e2mgr/rNibWriter"
        "e2mgr/services"
        "fmt"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
-       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
        "github.com/stretchr/testify/assert"
        "net"
        "net/http"
@@ -44,13 +42,10 @@ func setupNodebControllerTest(t *testing.T) (services.RNibDataService, *mocks.Rn
        }
        config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
        readerMock := &mocks.RnibReaderMock{}
-       rnibReaderProvider := func() reader.RNibReader {
-               return readerMock
-       }
-       rnibWriterProvider := func() rNibWriter.RNibWriter {
-               return &mocks.RnibWriterMock{}
-       }
-       rnibDataService := services.NewRnibDataService(logger, config, rnibReaderProvider, rnibWriterProvider)
+
+       writerMock := &mocks.RnibWriterMock{}
+
+       rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
        return rnibDataService, readerMock
 }
 
@@ -26,11 +26,27 @@ package converters
 // #include <x2setup_response_wrapper.h>
 import "C"
 import (
+       "e2mgr/e2pdus"
        "e2mgr/logger"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
        "unsafe"
 )
 
+type EndcSetupFailureResponseConverter struct {
+       logger *logger.Logger
+}
+
+type IEndcSetupFailureResponseConverter interface {
+       UnpackEndcSetupFailureResponseAndExtract(packedBuf []byte) (*entities.SetupFailure, error)
+}
+
+func NewEndcSetupFailureResponseConverter(logger *logger.Logger) *EndcSetupFailureResponseConverter {
+       return &EndcSetupFailureResponseConverter{
+               logger: logger,
+       }
+}
+
+
 // Populate and return the EN-DC/X2 setup response failure structure with data from the pdu
 func endcX2SetupFailureResponseToProtobuf(pdu *C.E2AP_PDU_t) (*entities.SetupFailure, error) {
        setupFailure := entities.SetupFailure{}
@@ -71,8 +87,8 @@ func endcX2SetupFailureResponseToProtobuf(pdu *C.E2AP_PDU_t) (*entities.SetupFai
        return &setupFailure, nil
 }
 
-func UnpackEndcX2SetupFailureResponseAndExtract(logger *logger.Logger, allocationBufferSize int, packedBufferSize int, packedBuf []byte, maxMessageBufferSize int) (*entities.SetupFailure, error) {
-       pdu, err := UnpackX2apPdu(logger, allocationBufferSize, packedBufferSize, packedBuf, maxMessageBufferSize)
+func (c *EndcSetupFailureResponseConverter) UnpackEndcSetupFailureResponseAndExtract(packedBuf []byte) (*entities.SetupFailure, error) {
+       pdu, err := UnpackX2apPdu(c.logger, e2pdus.MaxAsn1CodecAllocationBufferSize, len(packedBuf), packedBuf, e2pdus.MaxAsn1CodecMessageBufferSize)
        if err != nil {
                return nil, err
        }
@@ -22,7 +22,6 @@
 package converters
 
 import (
-       "e2mgr/e2pdus"
        "e2mgr/logger"
        "fmt"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
@@ -78,6 +77,8 @@ func TestUnpackEndcX2SetupFailureResponseAndExtract(t *testing.T) {
                /**** shares the same code with x2setup failure response to protobuf ****/
        }
 
+       converter := NewEndcSetupFailureResponseConverter(logger)
+
        for _, tc := range testCases {
                t.Run(tc.packedPdu, func(t *testing.T) {
 
@@ -87,7 +88,7 @@ func TestUnpackEndcX2SetupFailureResponseAndExtract(t *testing.T) {
                                t.Errorf("convert inputPayloadAsStr to payloadAsByte. Error: %v\n", err)
                        }
 
-                       response, err := UnpackEndcX2SetupFailureResponseAndExtract(logger, e2pdus.MaxAsn1CodecAllocationBufferSize /*allocation buffer*/, len(payload), payload, e2pdus.MaxAsn1CodecMessageBufferSize /*message buffer*/)
+                       response, err := converter.UnpackEndcSetupFailureResponseAndExtract(payload)
 
                        if err != nil {
                                if tc.failure == nil {
@@ -26,10 +26,10 @@ package converters
 // #include <x2setup_response_wrapper.h>
 import "C"
 import (
+       "e2mgr/e2pdus"
        "e2mgr/logger"
        "fmt"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
-//     "github.com/pkg/errors"
        "unsafe"
 )
 
@@ -39,6 +39,20 @@ const (
        maxnoofNrCellBands = 32
 )
 
+type EndcSetupResponseConverter struct {
+       logger *logger.Logger
+}
+
+type IEndcSetupResponseConverter interface {
+       UnpackEndcSetupResponseAndExtract(packedBuf []byte) (*entities.GlobalNbId, *entities.Gnb, error)
+}
+
+func NewEndcSetupResponseConverter(logger *logger.Logger) *EndcSetupResponseConverter {
+       return &EndcSetupResponseConverter{
+               logger: logger,
+       }
+}
+
 func getNRFreqInfo(freqInfo C.NRFreqInfo_t) (*entities.NrFrequencyInfo, error) {
        var info *entities.NrFrequencyInfo
        info = &entities.NrFrequencyInfo{NrArFcn: uint64(freqInfo.nRARFCN)}
@@ -60,7 +74,7 @@ func getNRFreqInfo(freqInfo C.NRFreqInfo_t) (*entities.NrFrequencyInfo, error) {
                        frequencyBand := &entities.FrequencyBandItem{NrFrequencyBand: uint32(freqBandNrItem.freqBandIndicatorNr)}
 
                        if freqBandNrItem.supportedSULBandList.list.count > 0 && freqBandNrItem.supportedSULBandList.list.count <= maxnoofNrCellBands {
-                               count:= int(freqBandNrItem.supportedSULBandList.list.count)
+                               count := int(freqBandNrItem.supportedSULBandList.list.count)
                                supportedSULBandList_slice := (*[1 << 30]*C.SupportedSULFreqBandItem_t)(unsafe.Pointer(freqBandNrItem.supportedSULBandList.list.array))[:count:count]
                                for _, supportedSULFreqBandItem := range supportedSULBandList_slice {
                                        frequencyBand.SupportedSulBands = append(frequencyBand.SupportedSulBands, uint32(supportedSULFreqBandItem.freqBandIndicatorNr))
@@ -165,7 +179,7 @@ func getnRNeighbourInfo(neighbour_Information *C.NRNeighbour_Information_t) ([]*
        var neighbours []*entities.NrNeighbourInformation
 
        if neighbour_Information != nil && neighbour_Information.list.count > 0 && neighbour_Information.list.count <= maxofNRNeighbours {
-               count:=int(neighbour_Information.list.count)
+               count := int(neighbour_Information.list.count)
                neighbour_Information_slice := (*[1 << 30]*C.NRNeighbour_Information__Member)(unsafe.Pointer(neighbour_Information.list.array))[:count:count]
                for _, member := range neighbour_Information_slice {
                        info := &entities.NrNeighbourInformation{NrPci: uint32(member.nrpCI)}
@@ -206,7 +220,7 @@ func getServedNRCells(servedNRcellsManagementList *C.ServedNRcellsENDCX2Manageme
        var servedNRCells []*entities.ServedNRCell
 
        if servedNRcellsManagementList != nil && servedNRcellsManagementList.list.count > 0 && servedNRcellsManagementList.list.count <= maxCellinengNB {
-               count :=int(servedNRcellsManagementList.list.count)
+               count := int(servedNRcellsManagementList.list.count)
                servedNRcellsENDCX2ManagementList__Member_slice := (*[1 << 30]*C.ServedNRcellsENDCX2ManagementList__Member)(unsafe.Pointer(servedNRcellsManagementList.list.array))[:count:count]
                for _, servedNRcellsENDCX2ManagementList__Member := range servedNRcellsENDCX2ManagementList__Member_slice {
                        servedNRCellInfo := servedNRcellsENDCX2ManagementList__Member.servedNRCellInfo
@@ -226,7 +240,7 @@ func getServedNRCells(servedNRcellsManagementList *C.ServedNRcellsENDCX2Manageme
                        }
 
                        if servedNRCellInfo.broadcastPLMNs.list.count > 0 && servedNRCellInfo.broadcastPLMNs.list.count <= maxnoofBPLMNs {
-                               count:=int(servedNRCellInfo.broadcastPLMNs.list.count)
+                               count := int(servedNRCellInfo.broadcastPLMNs.list.count)
                                pLMN_Identity_slice := (*[1 << 30]*C.PLMN_Identity_t)(unsafe.Pointer(servedNRCellInfo.broadcastPLMNs.list.array))[:count:count]
                                for _, pLMN_Identity := range pLMN_Identity_slice {
                                        servedNRCell.ServedNrCellInformation.ServedPlmns = append(servedNRCell.ServedNrCellInformation.ServedPlmns, fmt.Sprintf("%02x", C.GoBytes(unsafe.Pointer(pLMN_Identity.buf), C.int(pLMN_Identity.size))))
@@ -274,7 +288,7 @@ func endcX2SetupResponseToProtobuf(pdu *C.E2AP_PDU_t) (*entities.GlobalNbId, *en
                if successfulOutcome != nil && successfulOutcome.value.present == C.SuccessfulOutcome__value_PR_ENDCX2SetupResponse {
                        endcX2SetupResponse := (*C.ENDCX2SetupResponse_t)(unsafe.Pointer(&successfulOutcome.value.choice[0]))
                        if endcX2SetupResponse != nil && endcX2SetupResponse.protocolIEs.list.count > 0 {
-                               count:=int(endcX2SetupResponse.protocolIEs.list.count)
+                               count := int(endcX2SetupResponse.protocolIEs.list.count)
                                endcX2SetupResponse_IEs_slice := (*[1 << 30]*C.ENDCX2SetupResponse_IEs_t)(unsafe.Pointer(endcX2SetupResponse.protocolIEs.list.array))[:count:count]
                                for _, endcX2SetupResponse_IE := range endcX2SetupResponse_IEs_slice {
                                        if endcX2SetupResponse_IE.value.present == C.ENDCX2SetupResponse_IEs__value_PR_RespondingNodeType_EndcX2Setup {
@@ -283,7 +297,7 @@ func endcX2SetupResponseToProtobuf(pdu *C.E2AP_PDU_t) (*entities.GlobalNbId, *en
                                                case C.RespondingNodeType_EndcX2Setup_PR_respond_en_gNB:
                                                        en_gNB_ENDCX2SetupReqAckIEs_Container := *(**C.ProtocolIE_Container_119P89_t)(unsafe.Pointer(&respondingNodeType.choice[0]))
                                                        if en_gNB_ENDCX2SetupReqAckIEs_Container != nil && en_gNB_ENDCX2SetupReqAckIEs_Container.list.count > 0 {
-                                                               count:=int(en_gNB_ENDCX2SetupReqAckIEs_Container.list.count)
+                                                               count := int(en_gNB_ENDCX2SetupReqAckIEs_Container.list.count)
                                                                en_gNB_ENDCX2SetupReqAckIEs_slice := (*[1 << 30]*C.En_gNB_ENDCX2SetupReqAckIEs_t)(unsafe.Pointer(en_gNB_ENDCX2SetupReqAckIEs_Container.list.array))[:count:count]
                                                                for _, en_gNB_ENDCX2SetupReqAckIE := range en_gNB_ENDCX2SetupReqAckIEs_slice {
                                                                        switch en_gNB_ENDCX2SetupReqAckIE.value.present {
@@ -318,8 +332,9 @@ func endcX2SetupResponseToProtobuf(pdu *C.E2AP_PDU_t) (*entities.GlobalNbId, *en
        return globalNbId, gnb, nil
 }
 
-func UnpackEndcX2SetupResponseAndExtract(logger *logger.Logger, allocationBufferSize int, packedBufferSize int, packedBuf []byte, maxMessageBufferSize int) (*entities.GlobalNbId, *entities.Gnb, error) {
-       pdu, err := UnpackX2apPdu(logger, allocationBufferSize, packedBufferSize, packedBuf, maxMessageBufferSize)
+func (c *EndcSetupResponseConverter) UnpackEndcSetupResponseAndExtract(packedBuf []byte) (*entities.GlobalNbId, *entities.Gnb, error) {
+       pdu, err := UnpackX2apPdu(c.logger, e2pdus.MaxAsn1CodecAllocationBufferSize, len(packedBuf), packedBuf, e2pdus.MaxAsn1CodecMessageBufferSize)
+
        if err != nil {
                return nil, nil, err
        }
@@ -22,7 +22,6 @@
 package converters
 
 import (
-       "e2mgr/e2pdus"
        "e2mgr/logger"
        "fmt"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
@@ -559,6 +558,8 @@ func TestUnpackEndcX2SetupResponseAndExtract(t *testing.T) {
                        failure: fmt.Errorf("getList for path [successfulOutcome_t ENDCX2SetupResponse protocolIEs_t ProtocolIE_Container_elm RespondingNodeType-EndcX2Setup respond_en_gNB_t ProtocolIE_Container_elm ServedNRcellsENDCX2ManagementList ServedNRcellsENDCX2ManagementList_elm servedNRCellInfo_t nrpCI_t] failed, rc = 1" /*NO_ITEMS*/),},
        }
 
+       converter := NewEndcSetupResponseConverter(logger)
+
        for _, tc := range testCases {
                t.Run(tc.packedPdu, func(t *testing.T) {
 
@@ -570,7 +571,7 @@ func TestUnpackEndcX2SetupResponseAndExtract(t *testing.T) {
                                t.Errorf("convert inputPayloadAsStr to payloadAsByte. Error: %v\n", err)
                        }
 
-                       key, gnb, err := UnpackEndcX2SetupResponseAndExtract(logger, e2pdus.MaxAsn1CodecAllocationBufferSize, len(payload), payload, e2pdus.MaxAsn1CodecMessageBufferSize)
+                       key, gnb, err := converter.UnpackEndcSetupResponseAndExtract(payload)
 
                        if err != nil {
                                if tc.failure == nil {
diff --git a/E2Manager/e2managererrors/e2t_instance_absence_error.go b/E2Manager/e2managererrors/e2t_instance_absence_error.go
new file mode 100644 (file)
index 0000000..772d62a
--- /dev/null
@@ -0,0 +1,35 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package e2managererrors
+
+type E2TInstanceAbsenceError struct {
+       *BaseError
+}
+
+func NewE2TInstanceAbsenceError() *E2TInstanceAbsenceError {
+       return &E2TInstanceAbsenceError{
+               &BaseError{
+                       Code:    510,
+                       Message: "The New RAN can't be added, please try later.",
+               },
+       }
+}
+
+func (e *E2TInstanceAbsenceError) Error() string {
+       return e.Message
+}
diff --git a/E2Manager/e2managererrors/routing_manager_error.go b/E2Manager/e2managererrors/routing_manager_error.go
new file mode 100644 (file)
index 0000000..529df35
--- /dev/null
@@ -0,0 +1,29 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package e2managererrors
+
+type RoutingManagerError struct {
+}
+
+func NewRoutingManagerError() *RoutingManagerError {
+       return &RoutingManagerError{}
+}
+
+func (e *RoutingManagerError) Error() string {
+       return "Routing Manager Error"
+}
diff --git a/E2Manager/e2mgr-sonar-scanner.properties b/E2Manager/e2mgr-sonar-scanner.properties
new file mode 100644 (file)
index 0000000..a0c9ca9
--- /dev/null
@@ -0,0 +1,14 @@
+#----- Default SonarQube server
+sonar.host.url=http://135.25.121.110:9000
+sonar.projectKey=oran:e2mgr
+sonar.projectName=e2mgr
+sonar.login=admin
+sonar.password=admin
+sonar.go.coverage.reportPaths=coverage.txt
+#----- Default source code encoding
+#sonar.sourceEncoding=UTF-8
+sonar.projectBaseDir=/home/ubuntu/oran_repo/e2mgr/E2Manager/
+sonar.sources=.
+sonar.exclusions=**/*_test.go,**/generate_source.go,**/*_generated.go,**/build/**,**/.gogradle/**,**/mocks/**,**/tests/**,**/e2managererrors/**,**/enums/**
+sonar.go.golangci-lint.reportPaths=sca.xml
+
diff --git a/E2Manager/e2pdus/configuration_update.go b/E2Manager/e2pdus/configuration_update.go
new file mode 100644 (file)
index 0000000..032c6cf
--- /dev/null
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ *
+ *   Copyright (c) 2019 AT&T Intellectual Property.
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ *******************************************************************************/
+package e2pdus
+
+// #cgo CFLAGS: -I../asn1codec/inc/  -I../asn1codec/e2ap_engine/
+// #cgo LDFLAGS: -L ../asn1codec/lib/ -L../asn1codec/e2ap_engine/ -le2ap_codec -lasncodec
+// #include <configuration_update_wrapper.h>
+import "C"
+import (
+       "fmt"
+       "unsafe"
+)
+
+var PackedEndcConfigurationUpdateFailure []byte
+var PackedEndcConfigurationUpdateAck []byte
+var PackedX2EnbConfigurationUpdateFailure []byte
+var PackedX2EnbConfigurationUpdateAck []byte
+
+func prepareEndcConfigurationUpdateFailurePDU(maxAsn1PackedBufferSize int, maxAsn1CodecMessageBufferSize int) error {
+
+       packedBuffer := make([]C.uchar, maxAsn1PackedBufferSize)
+       errorBuffer := make([]C.char, maxAsn1CodecMessageBufferSize)
+       var payloadSize = C.ulong(maxAsn1PackedBufferSize)
+
+       if status := C.build_pack_endc_configuration_update_failure(&payloadSize, &packedBuffer[0], C.ulong(maxAsn1CodecMessageBufferSize), &errorBuffer[0]); !status {
+               return fmt.Errorf("#configuration_update.prepareEndcConfigurationUpdateFailurePDU - failed to build and pack the endc configuration update failure message %s ", C.GoString(&errorBuffer[0]))
+
+       }
+       PackedEndcConfigurationUpdateFailure = C.GoBytes(unsafe.Pointer(&packedBuffer[0]), C.int(payloadSize))
+
+       return nil
+}
+
+func prepareX2EnbConfigurationUpdateFailurePDU(maxAsn1PackedBufferSize int, maxAsn1CodecMessageBufferSize int) error {
+
+       packedBuffer := make([]C.uchar, maxAsn1PackedBufferSize)
+       errorBuffer := make([]C.char, maxAsn1CodecMessageBufferSize)
+       var payloadSize = C.ulong(maxAsn1PackedBufferSize)
+
+       if status := C.build_pack_x2enb_configuration_update_failure(&payloadSize, &packedBuffer[0], C.ulong(maxAsn1CodecMessageBufferSize), &errorBuffer[0]); !status {
+               return fmt.Errorf("#configuration_update.prepareX2EnbConfigurationUpdateFailurePDU - failed to build and pack the x2 configuration update failure message %s ", C.GoString(&errorBuffer[0]))
+
+       }
+       PackedX2EnbConfigurationUpdateFailure = C.GoBytes(unsafe.Pointer(&packedBuffer[0]), C.int(payloadSize))
+
+       return nil
+}
+
+func prepareEndcConfigurationUpdateAckPDU(maxAsn1PackedBufferSize int, maxAsn1CodecMessageBufferSize int) error {
+
+       packedBuffer := make([]C.uchar, maxAsn1PackedBufferSize)
+       errorBuffer := make([]C.char, maxAsn1CodecMessageBufferSize)
+       var payloadSize = C.ulong(maxAsn1PackedBufferSize)
+
+       if status := C.build_pack_endc_configuration_update_ack(&payloadSize, &packedBuffer[0], C.ulong(maxAsn1CodecMessageBufferSize), &errorBuffer[0]); !status {
+               return fmt.Errorf("#configuration_update.prepareEndcConfigurationUpdateAckPDU - failed to build and pack the endc configuration update ack message %s ", C.GoString(&errorBuffer[0]))
+
+       }
+       PackedEndcConfigurationUpdateAck = C.GoBytes(unsafe.Pointer(&packedBuffer[0]), C.int(payloadSize))
+
+       return nil
+}
+
+func prepareX2EnbConfigurationUpdateAckPDU(maxAsn1PackedBufferSize int, maxAsn1CodecMessageBufferSize int) error {
+
+       packedBuffer := make([]C.uchar, maxAsn1PackedBufferSize)
+       errorBuffer := make([]C.char, maxAsn1CodecMessageBufferSize)
+       var payloadSize = C.ulong(maxAsn1PackedBufferSize)
+
+       if status := C.build_pack_x2enb_configuration_update_ack(&payloadSize, &packedBuffer[0], C.ulong(maxAsn1CodecMessageBufferSize), &errorBuffer[0]); !status {
+               return fmt.Errorf("#configuration_update.prepareX2EnbConfigurationUpdateAckPDU - failed to build and pack the x2 configuration update ack message %s ", C.GoString(&errorBuffer[0]))
+
+       }
+       PackedX2EnbConfigurationUpdateAck = C.GoBytes(unsafe.Pointer(&packedBuffer[0]), C.int(payloadSize))
+
+       return nil
+}
+
+func init() {
+       if err := prepareEndcConfigurationUpdateFailurePDU(MaxAsn1PackedBufferSize, MaxAsn1CodecMessageBufferSize); err != nil {
+               panic(err)
+       }
+       if err := prepareEndcConfigurationUpdateAckPDU(MaxAsn1PackedBufferSize, MaxAsn1CodecMessageBufferSize); err != nil {
+               panic(err)
+       }
+       if err := prepareX2EnbConfigurationUpdateFailurePDU(MaxAsn1PackedBufferSize, MaxAsn1CodecMessageBufferSize); err != nil {
+               panic(err)
+       }
+       if err := prepareX2EnbConfigurationUpdateAckPDU(MaxAsn1PackedBufferSize, MaxAsn1CodecMessageBufferSize); err != nil {
+               panic(err)
+       }
+}
diff --git a/E2Manager/e2pdus/configuration_update_test.go b/E2Manager/e2pdus/configuration_update_test.go
new file mode 100644 (file)
index 0000000..a90ba13
--- /dev/null
@@ -0,0 +1,165 @@
+/*******************************************************************************
+ *
+ *   Copyright (c) 2019 AT&T Intellectual Property.
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ *******************************************************************************/
+package e2pdus
+
+import (
+       "e2mgr/logger"
+       "fmt"
+       "strings"
+       "testing"
+)
+
+func TestPrepareEndcConfigurationUpdateFailurePDU(t *testing.T) {
+       _,err := logger.InitLogger(logger.InfoLevel)
+       if err!=nil{
+               t.Errorf("failed to initialize logger, error: %s", err)
+       }
+       packedPdu := "402500080000010005400142"
+       packedEndcConfigurationUpdateFailure := PackedEndcConfigurationUpdateFailure
+
+       tmp := fmt.Sprintf("%x", packedEndcConfigurationUpdateFailure)
+       if len(tmp) != len(packedPdu) {
+               t.Errorf("want packed len:%d, got: %d\n", len(packedPdu)/2, len(packedEndcConfigurationUpdateFailure)/2)
+       }
+
+       if strings.Compare(tmp, packedPdu) != 0 {
+               t.Errorf("\nwant :\t[%s]\n got: \t\t[%s]\n", packedPdu, tmp)
+       }
+}
+
+func TestPrepareEndcConfigurationUpdateFailurePDUFailure(t *testing.T) {
+       _, err := logger.InitLogger(logger.InfoLevel)
+       if err != nil {
+               t.Errorf("failed to initialize logger, error: %s", err)
+       }
+
+       err  = prepareEndcConfigurationUpdateFailurePDU(1, 4096)
+       if err == nil {
+               t.Errorf("want: error, got: success.\n")
+       }
+
+       expected:= "#configuration_update.prepareEndcConfigurationUpdateFailurePDU - failed to build and pack the endc configuration update failure message #src/asn1codec_utils.c.pack_pdu_aux - Encoded output of E2AP-PDU, is too big"
+       if !strings.Contains(err.Error(), expected) {
+               t.Errorf("want :[%s], got: [%s]\n", expected, err)
+       }
+}
+
+func TestPrepareX2EnbConfigurationUpdateFailurePDU(t *testing.T) {
+       _,err := logger.InitLogger(logger.InfoLevel)
+       if err!=nil{
+               t.Errorf("failed to initialize logger, error: %s", err)
+       }
+       packedPdu := "400800080000010005400142"
+       packedEndcX2ConfigurationUpdateFailure := PackedX2EnbConfigurationUpdateFailure
+
+       tmp := fmt.Sprintf("%x", packedEndcX2ConfigurationUpdateFailure)
+       if len(tmp) != len(packedPdu) {
+               t.Errorf("want packed len:%d, got: %d\n", len(packedPdu)/2, len(packedEndcX2ConfigurationUpdateFailure)/2)
+       }
+
+       if strings.Compare(tmp, packedPdu) != 0 {
+               t.Errorf("\nwant :\t[%s]\n got: \t\t[%s]\n", packedPdu, tmp)
+       }
+}
+
+func TestPrepareX2EnbConfigurationUpdateFailurePDUFailure(t *testing.T) {
+       _, err := logger.InitLogger(logger.InfoLevel)
+       if err != nil {
+               t.Errorf("failed to initialize logger, error: %s", err)
+       }
+
+       err  = prepareX2EnbConfigurationUpdateFailurePDU(1, 4096)
+       if err == nil {
+               t.Errorf("want: error, got: success.\n")
+       }
+
+       expected:= "#configuration_update.prepareX2EnbConfigurationUpdateFailurePDU - failed to build and pack the x2 configuration update failure message #src/asn1codec_utils.c.pack_pdu_aux - Encoded output of E2AP-PDU, is too big"
+       if !strings.Contains(err.Error(), expected) {
+               t.Errorf("want :[%s], got: [%s]\n", expected, err)
+       }
+}
+
+func TestPrepareEndcConfigurationUpdateAckPDU(t *testing.T) {
+       _,err := logger.InitLogger(logger.InfoLevel)
+       if err!=nil{
+               t.Errorf("failed to initialize logger, error: %s", err)
+       }
+       packedPdu := "2025000a00000100f70003000000"
+       packedEndcConfigurationUpdateAck := PackedEndcConfigurationUpdateAck
+
+       tmp := fmt.Sprintf("%x", packedEndcConfigurationUpdateAck)
+       if len(tmp) != len(packedPdu) {
+               t.Errorf("want packed len:%d, got: %d\n", len(packedPdu)/2, len(packedEndcConfigurationUpdateAck)/2)
+       }
+
+       if strings.Compare(tmp, packedPdu) != 0 {
+               t.Errorf("\nwant :\t[%s]\n got: \t\t[%s]\n", packedPdu, tmp)
+       }
+}
+
+func TestPrepareEndcConfigurationUpdateAckPDUFailure(t *testing.T) {
+       _, err := logger.InitLogger(logger.InfoLevel)
+       if err != nil {
+               t.Errorf("failed to initialize logger, error: %s", err)
+       }
+
+       err  = prepareEndcConfigurationUpdateAckPDU(1, 4096)
+       if err == nil {
+               t.Errorf("want: error, got: success.\n")
+       }
+
+       expected:= "#configuration_update.prepareEndcConfigurationUpdateAckPDU - failed to build and pack the endc configuration update ack message #src/asn1codec_utils.c.pack_pdu_aux - Encoded output of E2AP-PDU, is too big"
+       if !strings.Contains(err.Error(), expected) {
+               t.Errorf("want :[%s], got: [%s]\n", expected, err)
+       }
+}
+
+func TestPrepareX2EnbConfigurationUpdateAckPDU(t *testing.T) {
+       _,err := logger.InitLogger(logger.InfoLevel)
+       if err!=nil{
+               t.Errorf("failed to initialize logger, error: %s", err)
+       }
+       packedPdu := "200800080000010011400100"
+       packedEndcX2ConfigurationUpdateAck := PackedX2EnbConfigurationUpdateAck
+
+       tmp := fmt.Sprintf("%x", packedEndcX2ConfigurationUpdateAck)
+       if len(tmp) != len(packedPdu) {
+               t.Errorf("want packed len:%d, got: %d\n", len(packedPdu)/2, len(packedEndcX2ConfigurationUpdateAck)/2)
+       }
+
+       if strings.Compare(tmp, packedPdu) != 0 {
+               t.Errorf("\nwant :\t[%s]\n got: \t\t[%s]\n", packedPdu, tmp)
+       }
+}
+
+func TestPrepareX2EnbConfigurationUpdateAckPDUFailure(t *testing.T) {
+       _, err := logger.InitLogger(logger.InfoLevel)
+       if err != nil {
+               t.Errorf("failed to initialize logger, error: %s", err)
+       }
+
+       err  = prepareX2EnbConfigurationUpdateAckPDU(1, 4096)
+       if err == nil {
+               t.Errorf("want: error, got: success.\n")
+       }
+
+       expected:= "#configuration_update.prepareX2EnbConfigurationUpdateAckPDU - failed to build and pack the x2 configuration update ack message #src/asn1codec_utils.c.pack_pdu_aux - Encoded output of E2AP-PDU, is too big"
+       if !strings.Contains(err.Error(), expected) {
+               t.Errorf("want :[%s], got: [%s]\n", expected, err)
+       }
+}
\ No newline at end of file
index 12789ec..e63577b 100644 (file)
@@ -23,81 +23,11 @@ package e2pdus
 
 import (
        "bytes"
-       "e2mgr/logger"
        "fmt"
        "strings"
        "testing"
 )
 
-func TestPreparePackedEndcX2SetupRequest(t *testing.T) {
-       _,err := logger.InitLogger(logger.InfoLevel)
-       if err!=nil{
-               t.Errorf("failed to initialize logger, error: %s", err)
-       }
-       packedPdu := "0024003100000100f4002a0000020015000800bbbccc00abcde000fa0017000001f700bbbcccabcde0000000bbbccc000000000001"
-       packedEndcX2setupRequest := PackedEndcX2setupRequest
-
-       tmp := fmt.Sprintf("%x", packedEndcX2setupRequest)
-       if len(tmp) != len(packedPdu) {
-               t.Errorf("want packed len:%d, got: %d\n", len(packedPdu)/2, len(packedEndcX2setupRequest)/2)
-       }
-
-       if strings.Compare(tmp, packedPdu) != 0 {
-               t.Errorf("\nwant :\t[%s]\n got: \t\t[%s]\n", packedPdu, tmp)
-       }
-}
-
-func TestPreparePackedX2SetupRequest(t *testing.T) {
-       _,err := logger.InitLogger(logger.InfoLevel)
-       if err!=nil{
-               t.Errorf("failed to initialize logger, error: %s", err)
-       }
-       packedPdu := "0006002a0000020015000800bbbccc00abcde000140017000001f700bbbcccabcde0000000bbbccc000000000001"
-       packedX2setupRequest := PackedX2setupRequest
-
-       tmp := fmt.Sprintf("%x", packedX2setupRequest)
-       if len(tmp) != len(packedPdu) {
-               t.Errorf("want packed len:%d, got: %d\n", len(packedPdu)/2, len(packedX2setupRequest)/2)
-       }
-
-       if strings.Compare(tmp, packedPdu) != 0 {
-               t.Errorf("\nwant :\t[%s]\n got: \t\t[%s]\n", packedPdu, tmp)
-       }
-}
-
-func TestPreparePackedX2SetupRequestFailure(t *testing.T) {
-       _, err := logger.InitLogger(logger.InfoLevel)
-       if err != nil {
-               t.Errorf("failed to initialize logger, error: %s", err)
-       }
-
-       _, _, err  = preparePackedX2SetupRequest(1, 4096, pLMNId, eNBId, eNBIdBitqty, ricFlag)
-       if err == nil {
-               t.Errorf("want: error, got: success.\n")
-       }
-
-       expected:= "packing error: #src/asn1codec_utils.c.pack_pdu_aux - Encoded output of E2AP-PDU, is too big"
-       if !strings.Contains(err.Error(), expected) {
-               t.Errorf("want :[%s], got: [%s]\n", expected, err)
-       }
-}
-
-func TestPreparePackedEndcSetupRequestFailure(t *testing.T) {
-       _, err := logger.InitLogger(logger.InfoLevel)
-       if err != nil {
-               t.Errorf("failed to initialize logger, error: %s", err)
-       }
-
-       _, _, err  = preparePackedEndcX2SetupRequest(1, 4096, pLMNId, eNBId, eNBIdBitqty, ricFlag)
-       if err == nil {
-               t.Errorf("want: error, got: success.\n")
-       }
-
-       expected:= "packing error: #src/asn1codec_utils.c.pack_pdu_aux - Encoded output of E2AP-PDU, is too big"
-       if !strings.Contains(err.Error(), expected) {
-               t.Errorf("want :[%s], got: [%s]\n", expected, err)
-       }
-}
 
 func TestParseRicId(t *testing.T) {
        var testCases = []struct {
index 6892b02..1fd1095 100644 (file)
@@ -1,20 +1,30 @@
 module e2mgr
 
 require (
-       gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.23
-       gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.23
-       gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.23
-       gerrit.o-ran-sc.org/r/ric-plt/sdlgo v0.3.1
+       gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.28
+       gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.28
+       gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.28
+       gerrit.o-ran-sc.org/r/ric-plt/sdlgo v0.5.0
        github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a // indirect
        github.com/go-ozzo/ozzo-validation v3.5.0+incompatible
-       github.com/golang/protobuf v1.3.1
-       github.com/gorilla/context v1.1.1 // indirect
-       github.com/gorilla/mux v1.6.2
+       github.com/golang/protobuf v1.3.2
+       github.com/gorilla/mux v1.7.0
+       github.com/magiconair/properties v1.8.1 // indirect
+       github.com/pelletier/go-toml v1.5.0 // indirect
        github.com/pkg/errors v0.8.1
+       github.com/spf13/afero v1.2.2 // indirect
+       github.com/spf13/jwalterweatherman v1.1.0 // indirect
+       github.com/spf13/pflag v1.0.5 // indirect
        github.com/spf13/viper v1.4.0
-       github.com/stretchr/testify v1.3.0
-       go.uber.org/zap v1.10.0
-       gopkg.in/yaml.v2 v2.2.2
+       github.com/stretchr/objx v0.2.0 // indirect
+       github.com/stretchr/testify v1.4.0
+       go.uber.org/multierr v1.2.0 // indirect
+       go.uber.org/zap v1.11.0
+       golang.org/x/net v0.0.0-20191021144547-ec77196f6094 // indirect
+       golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7 // indirect
+       golang.org/x/text v0.3.2 // indirect
+       gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
+       gopkg.in/yaml.v2 v2.2.4
 )
 
-replace gerrit.o-ran-sc.org/r/ric-plt/sdlgo => gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.3.1
+replace gerrit.o-ran-sc.org/r/ric-plt/sdlgo => gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.5.0
index 6576a0b..9c518c1 100644 (file)
@@ -1,12 +1,18 @@
 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.23 h1:JbSOhvj9fVEUF2XZg8cw5QAyeKUi5xXgpwXrrxfDgLM=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.23/go.mod h1:QJ1uPPZosGbhxUWpUpeM5fLqFHdnWTrVnvW2DgyOCes=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.23 h1:akVZc8NWJ9oPujd7cQY3Ti3se4PF1/NoC+Dwt+YzINc=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.23/go.mod h1:GXiXLz4ORBeIr0FLIbzENRykgh3Po5uPkX2jICxnRF0=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.23 h1:TYV3HE2UNwGOWiA4C226/WhB94crwjuHKIFTgDDvo8I=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.23/go.mod h1:uZVjwZjfWV4JJzyQVO/O48Ykph57zfpfMB7nK+WGKX8=
-gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.3.1 h1:ZIhABs0WLMn8lp1Y3719315/3jbV+yLcovOGScL03eM=
-gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.3.1/go.mod h1:y2WhrCvdLkAKdH+ySdHSOSehACJkTMyZghCGVcqoZzc=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.27 h1:frasTDcg8Q8FgYutzJ+xSLHz9YseR2BmPSSBs4GI/1M=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.27/go.mod h1:QJ1uPPZosGbhxUWpUpeM5fLqFHdnWTrVnvW2DgyOCes=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.28 h1:Rewapfbc30ZkBaYB/3gW3W1BEivoiPdQm5UnmUswcMA=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.28/go.mod h1:QJ1uPPZosGbhxUWpUpeM5fLqFHdnWTrVnvW2DgyOCes=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.27 h1:nvZDzuB/SYKDuF1It7M4/Y/iVlVrCZ0Ob8AITAyppKo=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.27/go.mod h1:Fh23KkroYw5CRBh39WzZzxpKSkpQWL3scdzGnMngLo8=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.28 h1:+8Nn+Jn/AvhwBI1LtLsNS1PtOGAOYUHdicOrMn/8mmU=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.28/go.mod h1:Fh23KkroYw5CRBh39WzZzxpKSkpQWL3scdzGnMngLo8=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.27 h1:sWjlU/wBiWIBeSixnr9etCqtNmS2LW8jv+x2JGpf2eI=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.27/go.mod h1:vZ/335+rRSQW82wcbc80fNNICSK3TiCqIxmkqeC2Pfo=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.28 h1:AaYvK59fxDXQUV9NCo6WuxDOvBQbnRU3WTPyJaYhkkg=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.28/go.mod h1:vZ/335+rRSQW82wcbc80fNNICSK3TiCqIxmkqeC2Pfo=
+gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.5.0 h1:+P3XuWKSaMbzh5PNtrW9gkZlCN0hKrZq+Cn8JetwBys=
+gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.5.0/go.mod h1:y2WhrCvdLkAKdH+ySdHSOSehACJkTMyZghCGVcqoZzc=
 github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
@@ -48,12 +54,12 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb
 github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
 github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
-github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
-github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
-github.com/gorilla/mux v1.6.2 h1:Pgr17XVTNXAk3q/r4CpKzC5xBM/qW1uVLV+IhRZpIIk=
-github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
+github.com/gorilla/mux v1.7.0 h1:tOSd0UKHQd6urX6ApfOn4XdBMY6Sh1MfxV3kmaazO+U=
+github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
 github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
 github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
@@ -76,6 +82,8 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
 github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
+github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
+github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
 github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
 github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
 github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
@@ -88,6 +96,8 @@ github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=
 github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
 github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
 github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
+github.com/pelletier/go-toml v1.5.0 h1:5BakdOZdtKJ1FFk6QdL8iSGrMWsXgchNJcrnarjbmJQ=
+github.com/pelletier/go-toml v1.5.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys=
 github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
 github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -108,20 +118,30 @@ github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4k
 github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
 github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
 github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
+github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc=
+github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
 github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
 github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
 github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
 github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
+github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
+github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
 github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
 github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
+github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
+github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
 github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU=
 github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
 github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
+github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
 github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
 github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
@@ -131,8 +151,12 @@ go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
 go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
 go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
 go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
+go.uber.org/multierr v1.2.0 h1:6I+W7f5VwC5SV9dNrZ3qXrDB9mD0dyGOi/ZJmYw03T4=
+go.uber.org/multierr v1.2.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
 go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
 go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
+go.uber.org/zap v1.11.0 h1:gSmpCfs+R47a4yQPAI4xJ0IPDLTRGXskm6UelqNXpqE=
+go.uber.org/zap v1.11.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -144,6 +168,8 @@ golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73r
 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190522155817-f3200d17e092 h1:4QSRKanuywn15aTZvI/mIDEgPQpswuFndXpOj3rKEco=
 golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
+golang.org/x/net v0.0.0-20191021144547-ec77196f6094 h1:5O4U9trLjNpuhpynaDsqwCk+Tw6seqJz1EbqbnzHrc8=
+golang.org/x/net v0.0.0-20191021144547-ec77196f6094/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -156,10 +182,15 @@ golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5h
 golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7 h1:HmbHVPwrPEKPGLAcHSrMe6+hqSUlvZU0rab6x5EXfGU=
+golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
@@ -170,6 +201,8 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
 gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
 gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
@@ -179,4 +212,6 @@ gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bl
 gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
+gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
index 5093589..956a366 100644 (file)
@@ -25,7 +25,6 @@ import (
        "e2mgr/e2managererrors"
        "e2mgr/logger"
        "e2mgr/mocks"
-       "e2mgr/rNibWriter"
        "e2mgr/rmrCgo"
        "e2mgr/services"
        "e2mgr/services/rmrsender"
@@ -33,7 +32,6 @@ import (
        "fmt"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
-       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
        "github.com/stretchr/testify/assert"
        "github.com/stretchr/testify/mock"
        "reflect"
@@ -45,14 +43,10 @@ func setupTest(t *testing.T) (*logger.Logger, *configuration.Configuration, *moc
        config := configuration.ParseConfiguration()
 
        readerMock := &mocks.RnibReaderMock{}
-       readerProvider := func() reader.RNibReader {
-               return readerMock
-       }
+
        writerMock := &mocks.RnibWriterMock{}
-       writerProvider := func() rNibWriter.RNibWriter {
-               return writerMock
-       }
-       rnibDataService := services.NewRnibDataService(log, config, readerProvider, writerProvider)
+
+       rnibDataService := services.NewRnibDataService(log, config, readerMock, writerMock)
        rmrMessengerMock := &mocks.RmrMessengerMock{}
        return log, config, readerMock, writerMock, rnibDataService, rmrMessengerMock
 }
@@ -144,7 +138,7 @@ func TestHandleSuccessFlow(t *testing.T) {
        writerMock.On("SaveNodeb", mock.Anything, updatedNb3AfterTimer).Return(nil)
 
        mbuf := rmrCgo.NewMBuf(tests.MessageType, tests.MaxMsgSize, "RanName", &tests.DummyPayload, &tests.DummyXAction)
-       rmrMessengerMock.On("SendMsg", mock.AnythingOfType(fmt.Sprintf("%T", mbuf))).Return(mbuf, nil)
+       rmrMessengerMock.On("SendMsg", mock.AnythingOfType(fmt.Sprintf("%T", mbuf)), true).Return(mbuf, nil)
 
        _, actual := handler.Handle(nil)
 
@@ -176,7 +170,7 @@ func TestHandleSuccessGetNextStatusFlow(t *testing.T) {
        writerMock.On("SaveNodeb", mock.Anything, updatedNb1AfterTimer).Return(nil)
 
        mbuf := rmrCgo.NewMBuf(tests.MessageType, tests.MaxMsgSize, "RanName", &tests.DummyPayload, &tests.DummyXAction)
-       rmrMessengerMock.On("SendMsg", mock.AnythingOfType(fmt.Sprintf("%T", mbuf))).Return(mbuf, nil)
+       rmrMessengerMock.On("SendMsg", mock.AnythingOfType(fmt.Sprintf("%T", mbuf)), true).Return(mbuf, nil)
 
        _, actual := handler.Handle(nil)
 
@@ -205,7 +199,7 @@ func TestHandleShuttingDownStatusFlow(t *testing.T) {
        writerMock.On("SaveNodeb", mock.Anything, updatedNb1AfterTimer).Return(nil)
 
        mbuf := rmrCgo.NewMBuf(tests.MessageType, tests.MaxMsgSize, "RanName", &tests.DummyPayload, &tests.DummyXAction)
-       rmrMessengerMock.On("SendMsg", mock.AnythingOfType(fmt.Sprintf("%T", mbuf))).Return(mbuf, nil)
+       rmrMessengerMock.On("SendMsg", mock.AnythingOfType(fmt.Sprintf("%T", mbuf)), true).Return(mbuf, nil)
 
        _, actual := handler.Handle(nil)
 
@@ -251,7 +245,7 @@ func TestHandleGetNodebFailedFlow(t *testing.T) {
        writerMock.On("SaveNodeb", mock.Anything, updatedNb3AfterTimer).Return(nil)
 
        mbuf := rmrCgo.NewMBuf(tests.MessageType, tests.MaxMsgSize, "RanName", &tests.DummyPayload, &tests.DummyXAction)
-       rmrMessengerMock.On("SendMsg", mock.AnythingOfType(fmt.Sprintf("%T", mbuf))).Return(mbuf, nil)
+       rmrMessengerMock.On("SendMsg", mock.AnythingOfType(fmt.Sprintf("%T", mbuf)), true).Return(mbuf, nil)
 
        _, actual := handler.Handle(nil)
 
@@ -297,7 +291,7 @@ func TestHandleSaveFailedFlow(t *testing.T) {
        writerMock.On("SaveNodeb", mock.Anything, updatedNb3AfterTimer).Return(errRnib)
 
        mbuf := rmrCgo.NewMBuf(tests.MessageType, tests.MaxMsgSize, "RanName", &tests.DummyPayload, &tests.DummyXAction)
-       rmrMessengerMock.On("SendMsg", mock.AnythingOfType(fmt.Sprintf("%T", mbuf))).Return(mbuf, nil)
+       rmrMessengerMock.On("SendMsg", mock.AnythingOfType(fmt.Sprintf("%T", mbuf)), true).Return(mbuf, nil)
 
        _, actual := handler.Handle(nil)
 
@@ -343,7 +337,7 @@ func TestHandleSendRmrFailedFlow(t *testing.T) {
 
        expected := e2managererrors.NewRmrError()
        mbuf := rmrCgo.NewMBuf(tests.MessageType, tests.MaxMsgSize, "RanName", &tests.DummyPayload, &tests.DummyXAction)
-       rmrMessengerMock.On("SendMsg", mock.AnythingOfType(fmt.Sprintf("%T", mbuf))).Return(mbuf, expected)
+       rmrMessengerMock.On("SendMsg", mock.AnythingOfType(fmt.Sprintf("%T", mbuf)), true).Return(mbuf, expected)
 
        _, actual := handler.Handle(nil)
 
@@ -391,5 +385,5 @@ func initLog(t *testing.T) *logger.Logger {
 func getRmrSender(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *rmrsender.RmrSender {
        rmrMessenger := rmrCgo.RmrMessenger(rmrMessengerMock)
        rmrMessengerMock.On("Init", tests.GetPort(), tests.MaxMsgSize, tests.Flags, log).Return(&rmrMessenger)
-       return rmrsender.NewRmrSender(log, &rmrMessenger)
+       return rmrsender.NewRmrSender(log, rmrMessenger)
 }
diff --git a/E2Manager/handlers/httpmsghandlers/get_e2t_instances_request_handler.go b/E2Manager/handlers/httpmsghandlers/get_e2t_instances_request_handler.go
new file mode 100644 (file)
index 0000000..fd20bdf
--- /dev/null
@@ -0,0 +1,54 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package httpmsghandlers
+
+import (
+       "e2mgr/logger"
+       "e2mgr/managers"
+       "e2mgr/models"
+)
+
+type GetE2TInstancesRequestHandler struct {
+       e2tInstancesManager managers.IE2TInstancesManager
+       logger              *logger.Logger
+}
+
+func NewGetE2TInstancesRequestHandler(logger *logger.Logger, e2tInstancesManager managers.IE2TInstancesManager) *GetE2TInstancesRequestHandler {
+       return &GetE2TInstancesRequestHandler{
+               logger:              logger,
+               e2tInstancesManager: e2tInstancesManager,
+       }
+}
+
+func (h *GetE2TInstancesRequestHandler) Handle(request models.Request) (models.IResponse, error) {
+
+       e2tInstances, err := h.e2tInstancesManager.GetE2TInstances()
+
+       if err != nil {
+               h.logger.Errorf("#GetE2TInstancesRequestHandler.Handle - Error fetching E2T instances from rNib: %s", err)
+               return nil, err
+       }
+
+       mapped := make([]*models.E2TInstanceResponseModel, len(e2tInstances))
+
+       for i, v := range e2tInstances {
+               mapped[i] = models.NewE2TInstanceResponseModel(v.Address, v.AssociatedRanList)
+       }
+
+       return models.E2TInstancesResponse(mapped), nil
+}
diff --git a/E2Manager/handlers/httpmsghandlers/get_e2t_instances_request_handler_test.go b/E2Manager/handlers/httpmsghandlers/get_e2t_instances_request_handler_test.go
new file mode 100644 (file)
index 0000000..b4ee6b4
--- /dev/null
@@ -0,0 +1,75 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package httpmsghandlers
+
+import (
+       "e2mgr/configuration"
+       "e2mgr/managers"
+       "e2mgr/mocks"
+       "e2mgr/models"
+       "e2mgr/services"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+       "github.com/pkg/errors"
+       "github.com/stretchr/testify/assert"
+
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
+       "testing"
+)
+
+const E2TAddress2 = "10.0.2.15:3213"
+
+func setupGetE2TInstancesListRequestHandlerTest(t *testing.T) (*GetE2TInstancesRequestHandler, *mocks.RnibReaderMock) {
+       log := initLog(t)
+       config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
+       readerMock := &mocks.RnibReaderMock{}
+       rnibDataService := services.NewRnibDataService(log, config, readerMock, nil)
+       e2tInstancesManager := managers.NewE2TInstancesManager(rnibDataService, log)
+       handler := NewGetE2TInstancesRequestHandler(log, e2tInstancesManager)
+       return handler, readerMock
+}
+
+func TestGetE2TInstancesFailure(t *testing.T) {
+       handler, rnibReaderMock := setupGetE2TInstancesListRequestHandlerTest(t)
+       rnibReaderMock.On("GetE2TAddresses").Return([]string{}, common.NewInternalError(errors.New("error")))
+       _, err := handler.Handle(nil)
+       assert.NotNil(t, err)
+}
+
+func TestGetE2TInstancesNoInstances(t *testing.T) {
+       handler, rnibReaderMock := setupGetE2TInstancesListRequestHandlerTest(t)
+       rnibReaderMock.On("GetE2TAddresses").Return([]string{}, nil)
+       resp, err := handler.Handle(nil)
+       assert.Nil(t, err)
+       assert.IsType(t, models.E2TInstancesResponse{}, resp)
+       assert.Len(t, resp, 0)
+}
+
+func TestGetE2TInstancesSuccess(t *testing.T) {
+       handler, rnibReaderMock := setupGetE2TInstancesListRequestHandlerTest(t)
+
+       e2tAddresses := []string{E2TAddress, E2TAddress2}
+       rnibReaderMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
+       e2tInstance := entities.E2TInstance{Address: E2TAddress, AssociatedRanList: []string{"test1", "test2"}}
+       e2tInstance2 := entities.E2TInstance{Address: E2TAddress2, AssociatedRanList: []string{"test3", "test4", "test5"}}
+
+       rnibReaderMock.On("GetE2TInstances", e2tAddresses).Return([]*entities.E2TInstance{&e2tInstance, &e2tInstance2}, nil)
+       resp, err := handler.Handle(nil)
+       assert.Nil(t, err)
+       assert.IsType(t, models.E2TInstancesResponse{}, resp)
+       assert.Len(t, resp, 2)
+}
index a835377..eb5bae3 100644 (file)
@@ -27,7 +27,6 @@ import (
        "e2mgr/services"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
-       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
        "github.com/pkg/errors"
        "github.com/stretchr/testify/assert"
        "testing"
@@ -37,10 +36,8 @@ func setupGetNodebIdListRequestHandlerTest(t *testing.T) (*GetNodebIdListRequest
        log := initLog(t)
        config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
        readerMock := &mocks.RnibReaderMock{}
-       readerProvider := func() reader.RNibReader {
-               return readerMock
-       }
-       rnibDataService := services.NewRnibDataService(log, config, readerProvider, nil)
+
+       rnibDataService := services.NewRnibDataService(log, config, readerMock, nil)
        handler := NewGetNodebIdListRequestHandler(log, rnibDataService)
        return handler, readerMock
 }
index 12e3226..0177561 100644 (file)
@@ -27,7 +27,6 @@ import (
        "e2mgr/services"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
-       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
        "github.com/pkg/errors"
        "github.com/stretchr/testify/assert"
        "testing"
@@ -37,10 +36,7 @@ func setupGetNodebRequestHandlerTest(t *testing.T) (*GetNodebRequestHandler, *mo
        log := initLog(t)
        config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
        readerMock := &mocks.RnibReaderMock{}
-       readerProvider := func() reader.RNibReader {
-               return readerMock
-       }
-       rnibDataService := services.NewRnibDataService(log, config, readerProvider, nil)
+       rnibDataService := services.NewRnibDataService(log, config, readerMock, nil)
        handler := NewGetNodebRequestHandler(log, rnibDataService)
        return handler, readerMock
 }
index 9233411..92ec944 100644 (file)
@@ -24,7 +24,6 @@ import (
        "e2mgr/logger"
        "e2mgr/managers"
        "e2mgr/models"
-       "e2mgr/rnibBuilders"
        "e2mgr/services"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
@@ -38,77 +37,173 @@ const (
 )
 
 type SetupRequestHandler struct {
-       rNibDataService services.RNibDataService
-       logger          *logger.Logger
-       ranSetupManager *managers.RanSetupManager
-       protocol        entities.E2ApplicationProtocol
+       rNibDataService     services.RNibDataService
+       logger              *logger.Logger
+       ranSetupManager     managers.IRanSetupManager
+       protocol            entities.E2ApplicationProtocol
+       e2tInstancesManager managers.IE2TInstancesManager
 }
 
 func NewSetupRequestHandler(logger *logger.Logger, rNibDataService services.RNibDataService,
-       ranSetupManager *managers.RanSetupManager, protocol entities.E2ApplicationProtocol) *SetupRequestHandler {
+       ranSetupManager managers.IRanSetupManager, protocol entities.E2ApplicationProtocol, e2tInstancesManager managers.IE2TInstancesManager) *SetupRequestHandler {
        return &SetupRequestHandler{
-               logger:          logger,
-               rNibDataService:  rNibDataService,
-               ranSetupManager: ranSetupManager,
-               protocol:        protocol,
+               logger:              logger,
+               rNibDataService:     rNibDataService,
+               ranSetupManager:     ranSetupManager,
+               protocol:            protocol,
+               e2tInstancesManager: e2tInstancesManager,
        }
 }
 
-func (handler *SetupRequestHandler) Handle(request models.Request) (models.IResponse, error) {
+func (h *SetupRequestHandler) Handle(request models.Request) (models.IResponse, error) {
 
        setupRequest := request.(models.SetupRequest)
 
-       err := handler.validateRequestDetails(setupRequest)
+       err := h.validateRequestDetails(setupRequest)
        if err != nil {
                return nil, err
        }
 
-       nodebInfo, err := handler.rNibDataService.GetNodeb(setupRequest.RanName)
+       nodebInfo, err := h.rNibDataService.GetNodeb(setupRequest.RanName)
+
        if err != nil {
                _, ok := err.(*common.ResourceNotFoundError)
                if !ok {
-                       handler.logger.Errorf("#SetupRequestHandler.Handle - failed to get nodeB entity for ran name: %v from RNIB. Error: %s",
-                               setupRequest.RanName, err.Error())
+                       h.logger.Errorf("#SetupRequestHandler.Handle - failed to get nodeB entity for ran name: %v from RNIB. Error: %s", setupRequest.RanName, err)
                        return nil, e2managererrors.NewRnibDbError()
                }
 
-               result := handler.connectNewRan(&setupRequest, handler.protocol)
+               result := h.connectNewRan(&setupRequest, h.protocol)
+               return nil, result
+       }
+
+       if nodebInfo.ConnectionStatus == entities.ConnectionStatus_SHUTTING_DOWN {
+               h.logger.Errorf("#SetupRequestHandler.connectExistingRanWithAssociatedE2TAddress - RAN: %s in wrong state (%s)", nodebInfo.RanName, entities.ConnectionStatus_name[int32(nodebInfo.ConnectionStatus)])
+               result := e2managererrors.NewWrongStateError(h.getActivityName(h.protocol), entities.ConnectionStatus_name[int32(nodebInfo.ConnectionStatus)])
+               return nil, result
+       }
+
+       if len(nodebInfo.AssociatedE2TInstanceAddress) != 0 {
+               result := h.connectExistingRanWithAssociatedE2TAddress(nodebInfo)
                return nil, result
        }
 
-       result := handler.connectExistingRan(nodebInfo)
+       result := h.connectExistingRanWithoutAssociatedE2TAddress(nodebInfo)
        return nil, result
 }
 
-func (handler *SetupRequestHandler) connectExistingRan(nodebInfo *entities.NodebInfo) error {
+func createInitialNodeInfo(requestDetails *models.SetupRequest, protocol entities.E2ApplicationProtocol, e2tAddress string) (*entities.NodebInfo, *entities.NbIdentity) {
 
-       if nodebInfo.ConnectionStatus == entities.ConnectionStatus_SHUTTING_DOWN {
-               handler.logger.Errorf("#SetupRequestHandler.connectExistingRan - RAN: %s in wrong state (%s)", nodebInfo.RanName, entities.ConnectionStatus_name[int32(nodebInfo.ConnectionStatus)])
-               return e2managererrors.NewWrongStateError(handler.getActivityName(handler.protocol), entities.ConnectionStatus_name[int32(nodebInfo.ConnectionStatus)])
+       nodebInfo := &entities.NodebInfo{
+               Ip:                           requestDetails.RanIp,
+               Port:                         uint32(requestDetails.RanPort),
+               ConnectionStatus:             entities.ConnectionStatus_CONNECTING,
+               E2ApplicationProtocol:        protocol,
+               RanName:                      requestDetails.RanName,
+               ConnectionAttempts:           0,
+               AssociatedE2TInstanceAddress: e2tAddress,
+       }
+
+       nbIdentity := &entities.NbIdentity{
+               InventoryName: requestDetails.RanName,
+       }
+
+       return nodebInfo, nbIdentity
+}
+
+func (h *SetupRequestHandler) connectExistingRanWithoutAssociatedE2TAddress(nodebInfo *entities.NodebInfo) error {
+       e2tAddress, err := h.e2tInstancesManager.SelectE2TInstance()
+
+       if err != nil {
+               h.logger.Errorf("#SetupRequestHandler.connectExistingRanWithoutAssociatedE2TAddress - RAN name: %s - failed selecting E2T instance", nodebInfo.RanName)
+
+               if nodebInfo.ConnectionStatus == entities.ConnectionStatus_DISCONNECTED && nodebInfo.ConnectionAttempts == 0 {
+                       return err
+               }
+
+               nodebInfo.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
+               nodebInfo.ConnectionAttempts = 0
+               updateError := h.rNibDataService.UpdateNodebInfo(nodebInfo)
+
+               if updateError != nil {
+                       h.logger.Errorf("#SetupRequestHandler.connectExistingRanWithoutAssociatedE2TAddress - RAN name: %s - failed updating nodeb. error: %s", nodebInfo.RanName, updateError)
+               }
+
+               return err
+       }
+
+       err = h.e2tInstancesManager.AssociateRan(nodebInfo.RanName, e2tAddress)
+
+       if err != nil {
+               h.logger.Errorf("#SetupRequestHandler.connectExistingRanWithoutAssociatedE2TAddress - RAN name: %s - failed associating ran to e2t address %s. error: %s", nodebInfo.RanName, e2tAddress, err)
+               return err
+       }
+
+       nodebInfo.AssociatedE2TInstanceAddress = e2tAddress
+       nodebInfo.ConnectionAttempts = 0
+
+       err = h.rNibDataService.UpdateNodebInfo(nodebInfo)
+
+       if err != nil {
+               h.logger.Errorf("#SetupRequestHandler.connectExistingRanWithoutAssociatedE2TAddress - RAN name: %s - failed updating nodeb in rNib. error: %s", nodebInfo.RanName, err)
+               return e2managererrors.NewRnibDbError()
        }
 
+       h.logger.Infof("#SetupRequestHandler.connectExistingRanWithoutAssociatedE2TAddress - RAN name: %s - successfully updated nodeb in rNib", nodebInfo.RanName)
+
+       result := h.ranSetupManager.ExecuteSetup(nodebInfo, entities.ConnectionStatus_CONNECTING)
+       return result
+}
+
+func (h *SetupRequestHandler) connectExistingRanWithAssociatedE2TAddress(nodebInfo *entities.NodebInfo) error {
        status := entities.ConnectionStatus_CONNECTING
-       if nodebInfo.ConnectionStatus == entities.ConnectionStatus_CONNECTED{
+       if nodebInfo.ConnectionStatus == entities.ConnectionStatus_CONNECTED {
                status = nodebInfo.ConnectionStatus
        }
        nodebInfo.ConnectionAttempts = 0
+       err := h.rNibDataService.UpdateNodebInfo(nodebInfo)
+
+       if err != nil {
+               h.logger.Errorf("#SetupRequestHandler.connectExistingRanWithAssociatedE2TAddress - RAN name: %s - failed resetting connection attempts of RAN. error: %s", nodebInfo.RanName, err)
+               return e2managererrors.NewRnibDbError()
+       }
 
-       result := handler.ranSetupManager.ExecuteSetup(nodebInfo, status)
+       h.logger.Infof("#SetupRequestHandler.connectExistingRanWithAssociatedE2TAddress - RAN name: %s - successfully reset connection attempts of RAN", nodebInfo.RanName)
+
+
+       result := h.ranSetupManager.ExecuteSetup(nodebInfo, status)
        return result
 }
 
-func (handler *SetupRequestHandler) connectNewRan(request *models.SetupRequest, protocol entities.E2ApplicationProtocol) error {
+func (h *SetupRequestHandler) connectNewRan(request *models.SetupRequest, protocol entities.E2ApplicationProtocol) error {
+
+       e2tAddress, err := h.e2tInstancesManager.SelectE2TInstance()
+
+       if err != nil {
+               h.logger.Errorf("#SetupRequestHandler.connectNewRan - RAN name: %s - failed selecting E2T instance", request.RanName)
+               return err
+       }
+
+       err = h.e2tInstancesManager.AssociateRan(request.RanName, e2tAddress)
 
-       nodebInfo, nodebIdentity := rnibBuilders.CreateInitialNodeInfo(request, protocol)
+       if err != nil {
+               h.logger.Errorf("#SetupRequestHandler.connectNewRan - RAN name: %s - failed associating ran to e2t address %s. error: %s", request.RanName, e2tAddress, err)
+               return err
+       }
+
+       nodebInfo, nodebIdentity := createInitialNodeInfo(request, protocol, e2tAddress)
+
+       err = h.rNibDataService.SaveNodeb(nodebIdentity, nodebInfo)
 
-       rNibErr := handler.rNibDataService.SaveNodeb(nodebIdentity, nodebInfo)
-       if rNibErr != nil {
-               handler.logger.Errorf("#SetupRequestHandler.connectNewRan - failed to initial nodeb entity for ran name: %v in RNIB. Error: %s", request.RanName, rNibErr.Error())
+       if err != nil {
+               h.logger.Errorf("#SetupRequestHandler.connectNewRan - RAN name: %s - failed to save initial nodeb entity in RNIB. error: %s", request.RanName, err)
                return e2managererrors.NewRnibDbError()
        }
-       handler.logger.Infof("#SetupRequestHandler.connectNewRan - initial nodeb entity for ran name: %v was saved to RNIB ", request.RanName)
 
-       result := handler.ranSetupManager.ExecuteSetup(nodebInfo, entities.ConnectionStatus_CONNECTING)
+       h.logger.Infof("#SetupRequestHandler.connectNewRan - RAN name: %s - initial nodeb entity was saved to rNib", request.RanName)
+
+       result := h.ranSetupManager.ExecuteSetup(nodebInfo, entities.ConnectionStatus_CONNECTING)
+
        return result
 }
 
index 23cb44f..5086c91 100644 (file)
 package httpmsghandlers
 
 import (
-       "e2mgr/rnibBuilders"
        "e2mgr/configuration"
        "e2mgr/e2managererrors"
        "e2mgr/e2pdus"
        "e2mgr/managers"
        "e2mgr/mocks"
        "e2mgr/models"
-       "e2mgr/rNibWriter"
        "e2mgr/rmrCgo"
        "e2mgr/services"
+       "fmt"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
-       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
        "github.com/stretchr/testify/assert"
        "github.com/stretchr/testify/mock"
-       "reflect"
        "testing"
 )
 
-func TestSetupHandleNewRanSave_Error(t *testing.T) {
-       readerMock, writerMock, handler, rmrMessengerMock := initSetupRequestTest(t, entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST)
+const E2TAddress = "10.0.2.15:8989"
+const RanName = "test"
 
-       ranName := "RanName"
-       rnibErr := &common.ResourceNotFoundError{}
-       sr := models.SetupRequest{"127.0.0.1", 8080, ranName,}
-
-       nb := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST}
-       readerMock.On("GetNodeb", ranName).Return(nb, rnibErr)
-
-       vErr := &common.ValidationError{}
-       updatedNb, _ := rnibBuilders.CreateInitialNodeInfo(&sr, entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST)
-       writerMock.On("SaveNodeb", mock.Anything, updatedNb).Return(vErr)
-
-       var nbUpdated = &entities.NodebInfo{RanName: ranName, Ip: sr.RanIp, Port: uint32(sr.RanPort), ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST, ConnectionAttempts: 1}
-       writerMock.On("UpdateNodebInfo", nbUpdated).Return(nil)
-
-       payload := e2pdus.PackedEndcX2setupRequest
-       xaction := []byte(ranName)
-       msg := rmrCgo.NewMBuf(rmrCgo.RIC_ENDC_X2_SETUP_REQ, len(payload), ranName, &payload, &xaction)
+func initSetupRequestTest(t *testing.T, protocol entities.E2ApplicationProtocol) (*mocks.RnibReaderMock, *mocks.RnibWriterMock, *SetupRequestHandler, *mocks.E2TInstancesManagerMock, *mocks.RanSetupManagerMock) {
+       log := initLog(t)
+       config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
 
-       rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, nil)
+       readerMock := &mocks.RnibReaderMock{}
+       writerMock := &mocks.RnibWriterMock{}
 
-       _, actual := handler.Handle(sr)
-       expected := &e2managererrors.RnibDbError{}
+       rnibDataService := services.NewRnibDataService(log, config, readerMock, writerMock)
 
-       if reflect.TypeOf(actual) != reflect.TypeOf(expected) {
-               t.Errorf("Error actual = %v, and Expected = %v.", actual, expected)
-       }
+       ranSetupManagerMock := &mocks.RanSetupManagerMock{}
+       e2tInstancesManagerMock := &mocks.E2TInstancesManagerMock{}
+       handler := NewSetupRequestHandler(log, rnibDataService, ranSetupManagerMock, protocol, e2tInstancesManagerMock)
 
-       writerMock.AssertNumberOfCalls(t, "SaveNodeb", 1)
-       writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 0)
-       rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 0)
+       return readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock
 }
 
-func TestSetupHandleNewRan_Success(t *testing.T) {
-       readerMock, writerMock, handler, rmrMessengerMock := initSetupRequestTest(t, entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST)
-
-       ranName := "RanName"
-       rnibErr := &common.ResourceNotFoundError{}
-       sr := models.SetupRequest{"127.0.0.1", 8080, ranName,}
-
-       nb := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST}
-       readerMock.On("GetNodeb", ranName).Return(nb, rnibErr)
-
-       updatedNb, _ := rnibBuilders.CreateInitialNodeInfo(&sr, entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST)
-       writerMock.On("SaveNodeb", mock.Anything, updatedNb).Return(nil)
-
-       var nbUpdated = &entities.NodebInfo{RanName: ranName, Ip: sr.RanIp, Port: uint32(sr.RanPort), ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST, ConnectionAttempts: 1}
-       writerMock.On("UpdateNodebInfo", nbUpdated).Return(nil)
-
-       payload := e2pdus.PackedEndcX2setupRequest
-       xaction := []byte(ranName)
-       msg := rmrCgo.NewMBuf(rmrCgo.RIC_ENDC_X2_SETUP_REQ, len(payload), ranName, &payload, &xaction)
+func initSetupRequestTestBasicMocks(t *testing.T, protocol entities.E2ApplicationProtocol) (*mocks.RnibReaderMock, *mocks.RnibWriterMock, *SetupRequestHandler, *mocks.RmrMessengerMock) {
+       log := initLog(t)
+       config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
 
-       rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, nil)
+       readerMock := &mocks.RnibReaderMock{}
+       writerMock := &mocks.RnibWriterMock{}
 
-       _, actual := handler.Handle(sr)
+       rnibDataService := services.NewRnibDataService(log, config, readerMock, writerMock)
 
-       assert.Nil(t, actual)
+       rmrMessengerMock := &mocks.RmrMessengerMock{}
+       rmrSender := getRmrSender(rmrMessengerMock, log)
+       ranSetupManager := managers.NewRanSetupManager(log, rmrSender, rnibDataService)
+       e2tInstancesManager := managers.NewE2TInstancesManager(rnibDataService, log)
+       handler := NewSetupRequestHandler(log, rnibDataService, ranSetupManager, protocol, e2tInstancesManager)
 
-       writerMock.AssertNumberOfCalls(t, "SaveNodeb", 1)
-       writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1)
-       rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 1)
+       return readerMock, writerMock, handler, rmrMessengerMock
 }
 
-func TestEndcSetupHandleRmr_Error(t *testing.T) {
-       readerMock, writerMock, handler, rmrMessengerMock := initSetupRequestTest(t, entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST)
-
-       ranName := "RanName"
-       nb := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST}
-       readerMock.On("GetNodeb", ranName).Return(nb, nil)
-
-       var nbUpdated = &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST, ConnectionAttempts: 1}
-       writerMock.On("UpdateNodebInfo", nbUpdated).Return(nil)
-
-       var nbDisconnected = &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST, ConnectionAttempts: 0}
-       writerMock.On("UpdateNodebInfo", nbDisconnected).Return(nil)
-
-       payload := e2pdus.PackedEndcX2setupRequest
-       xaction := []byte(ranName)
-       msg := rmrCgo.NewMBuf(rmrCgo.RIC_ENDC_X2_SETUP_REQ, len(payload), ranName, &payload, &xaction)
-
-       rmrErr := &e2managererrors.RmrError{}
-       rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, rmrErr)
-
-       sr := models.SetupRequest{"127.0.0.1", 8080, ranName,}
-       _, actual := handler.Handle(sr)
+func TestX2SetupHandleNoPortError(t *testing.T) {
+       readerMock, _, handler, _, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
 
-       if reflect.TypeOf(actual) != reflect.TypeOf(rmrErr) {
-               t.Errorf("Error actual = %v, and Expected = %v.", actual, rmrErr)
-       }
-
-       writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2)
-       rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 1)
+       sr := models.SetupRequest{"127.0.0.1", 0, RanName,}
+       _, err := handler.Handle(sr)
+       assert.IsType(t, &e2managererrors.RequestValidationError{}, err)
+       readerMock.AssertNotCalled(t, "GetNodeb")
 }
 
-func TestEndcSetupHandleExistingDisconnectedRan_Success(t *testing.T) {
-       readerMock, writerMock, handler, rmrMessengerMock := initSetupRequestTest(t, entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST)
-
-       ranName := "RanName"
-       nb := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST}
-       readerMock.On("GetNodeb", ranName).Return(nb, nil)
-
-       var nbUpdated = &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST, ConnectionAttempts: 1}
-       writerMock.On("UpdateNodebInfo", nbUpdated).Return(nil)
-
-       payload := e2pdus.PackedEndcX2setupRequest
-       xaction := []byte(ranName)
-       msg := rmrCgo.NewMBuf(rmrCgo.RIC_ENDC_X2_SETUP_REQ, len(payload), ranName, &payload, &xaction)
+func TestX2SetupHandleNoRanNameError(t *testing.T) {
+       readerMock, _, handler, _, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
 
-       rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, nil)
-
-       sr := models.SetupRequest{"127.0.0.1", 8080, ranName,}
-       _, actual := handler.Handle(sr)
-
-       assert.Nil(t, actual)
-
-       writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1)
-       rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 1)
+       sr := models.SetupRequest{RanPort: 8080, RanIp: "127.0.0.1"}
+       _, err := handler.Handle(sr)
+       assert.IsType(t, &e2managererrors.RequestValidationError{}, err)
+       readerMock.AssertNotCalled(t, "GetNodeb")
 }
 
-func TestX2SetupHandleExistingConnectedRan_Success(t *testing.T) {
-       readerMock, writerMock, handler, rmrMessengerMock := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
-
-       ranName := "RanName"
-       nb := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
-       readerMock.On("GetNodeb", ranName).Return(nb, nil)
+func TestX2SetupHandleNoIpError(t *testing.T) {
+       readerMock, _, handler, _, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
 
-       var nbUpdated = &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1}
-       writerMock.On("UpdateNodebInfo", nbUpdated).Return(nil)
-
-       payload := e2pdus.PackedX2setupRequest
-       xaction := []byte(ranName)
-       msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ranName, &payload, &xaction)
-
-       rmrMessengerMock.On("SendMsg", mock.Anything, mock.Anything).Return(msg, nil)
-
-       sr := models.SetupRequest{"127.0.0.1", 8080, ranName,}
-       _, actual := handler.Handle(sr)
+       sr := models.SetupRequest{RanPort: 8080, RanName: RanName}
+       _, err := handler.Handle(sr)
+       assert.IsType(t, &e2managererrors.RequestValidationError{}, err)
+       readerMock.AssertNotCalled(t, "GetNodeb")
+}
 
-       assert.Nil(t, actual)
+func TestX2SetupHandleInvalidIpError(t *testing.T) {
+       readerMock, _, handler, _, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
 
-       writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1)
-       rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 1)
+       sr := models.SetupRequest{RanPort: 8080, RanName: RanName, RanIp: "invalid ip"}
+       _, err := handler.Handle(sr)
+       assert.IsType(t, &e2managererrors.RequestValidationError{}, err)
+       readerMock.AssertNotCalled(t, "GetNodeb")
 }
 
-func TestX2SetupHandleRnibGet_Error(t *testing.T) {
-       readerMock, _, handler, rmrMessengerMock := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
+func TestSetupGetNodebFailure(t *testing.T) {
+       readerMock, _, handler, _, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
 
        rnibErr := &common.ValidationError{}
-       nb := &entities.NodebInfo{RanName: "RanName", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,}
-       readerMock.On("GetNodeb", "RanName").Return(nb, rnibErr)
+       nb := &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,}
+       readerMock.On("GetNodeb", RanName).Return(nb, rnibErr)
 
-       sr := models.SetupRequest{"127.0.0.1", 8080, "RanName",}
-       _, actual := handler.Handle(sr)
-
-       expected := &e2managererrors.RnibDbError{}
-       if reflect.TypeOf(actual) != reflect.TypeOf(expected) {
-               t.Errorf("Error actual = %v, and Expected = %v.", actual, expected)
-       }
-       rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 0)
+       sr := models.SetupRequest{"127.0.0.1", 8080, RanName,}
+       _, err := handler.Handle(sr)
+       assert.IsType(t, &e2managererrors.RnibDbError{}, err)
 }
 
-func TestX2SetupHandleShuttingDownRan_Error(t *testing.T) {
-       readerMock, writerMock, handler, rmrMessengerMock := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
-
-       nb := &entities.NodebInfo{RanName: "RanName", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,}
-       readerMock.On("GetNodeb", "RanName").Return(nb, nil)
-
-       sr := models.SetupRequest{"127.0.0.1", 8080, "RanName",}
-       _, actual := handler.Handle(sr)
-
-       expected := &e2managererrors.WrongStateError{}
-       if reflect.TypeOf(actual) != reflect.TypeOf(expected) {
-               t.Errorf("Error actual = %v, and Expected = %v.", actual, expected)
-       }
-       writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 0)
-       rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 0)
+func TestSetupNewRanSelectE2TInstancesDbError(t *testing.T) {
+       readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
+       readerMock.On("GetNodeb", RanName).Return(&entities.NodebInfo{}, common.NewResourceNotFoundError(""))
+       e2tInstancesManagerMock.On("SelectE2TInstance").Return("", e2managererrors.NewRnibDbError())
+       _, err := handler.Handle(models.SetupRequest{"127.0.0.1", 8080, RanName,})
+       assert.IsType(t, &e2managererrors.RnibDbError{}, err)
+       e2tInstancesManagerMock.AssertNotCalled(t, "AssociateRan")
+       writerMock.AssertNotCalled(t, "SaveNodeb")
+       ranSetupManagerMock.AssertNotCalled(t, "ExecuteSetup")
 }
 
-func TestX2SetupHandleNoPort_Error(t *testing.T) {
-       _, writerMock, handler, rmrMessengerMock := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
-
-       sr := models.SetupRequest{"127.0.0.1", 0, "RanName",}
-       _, actual := handler.Handle(sr)
-
-       expected := &e2managererrors.RequestValidationError{}
-       if reflect.TypeOf(actual) != reflect.TypeOf(expected) {
-               t.Errorf("Error actual = %v, and Expected = %v.", actual, expected)
-       }
-       writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 0)
-       rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 0)
+func TestSetupNewRanSelectE2TInstancesNoInstances(t *testing.T) {
+       readerMock, writerMock, handler, rmrMessengerMock := initSetupRequestTestBasicMocks(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
+       readerMock.On("GetNodeb", RanName).Return(&entities.NodebInfo{}, common.NewResourceNotFoundError(""))
+       readerMock.On("GetE2TAddresses").Return([]string{}, nil)
+       _, err := handler.Handle(models.SetupRequest{"127.0.0.1", 8080, RanName,})
+       assert.IsType(t, &e2managererrors.E2TInstanceAbsenceError{}, err)
+       writerMock.AssertNotCalled(t, "SaveNodeb")
+       rmrMessengerMock.AssertNotCalled(t, "SendMsg")
 }
 
-func TestX2SetupHandleNoRanName_Error(t *testing.T) {
-       _, writerMock, handler, rmrMessengerMock := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
+func TestSetupNewRanAssociateRanFailure(t *testing.T) {
+       readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
+       readerMock.On("GetNodeb", RanName).Return(&entities.NodebInfo{}, common.NewResourceNotFoundError(""))
+       e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil)
+       e2tInstancesManagerMock.On("AssociateRan", RanName, E2TAddress).Return(e2managererrors.NewRnibDbError())
+       _, err := handler.Handle(models.SetupRequest{"127.0.0.1", 8080, RanName,})
+       assert.IsType(t, &e2managererrors.RnibDbError{}, err)
+       writerMock.AssertNotCalled(t, "SaveNodeb")
+       ranSetupManagerMock.AssertNotCalled(t, "ExecuteSetup")
+}
 
-       sr := models.SetupRequest{}
-       sr.RanPort = 8080
-       sr.RanIp = "127.0.0.1"
+func TestSetupNewRanSaveNodebFailure(t *testing.T) {
+       readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
+       readerMock.On("GetNodeb", RanName).Return(&entities.NodebInfo{}, common.NewResourceNotFoundError(""))
+       e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil)
+       e2tInstancesManagerMock.On("AssociateRan", RanName, E2TAddress).Return(nil)
+       setupRequest := models.SetupRequest{"127.0.0.1", 8080, RanName,}
+       nodebInfo, nbIdentity := createInitialNodeInfo(&setupRequest, entities.E2ApplicationProtocol_X2_SETUP_REQUEST, E2TAddress)
+       writerMock.On("SaveNodeb", nbIdentity, nodebInfo).Return(common.NewInternalError(fmt.Errorf("")))
+       _, err := handler.Handle(setupRequest)
+       assert.IsType(t, &e2managererrors.RnibDbError{}, err)
+       ranSetupManagerMock.AssertNotCalled(t, "ExecuteSetup")
+}
 
-       _, actual := handler.Handle(sr)
+func TestSetupNewRanSetupDbError(t *testing.T) {
+       readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
+       readerMock.On("GetNodeb", RanName).Return(&entities.NodebInfo{}, common.NewResourceNotFoundError(""))
+       e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil)
+       e2tInstancesManagerMock.On("AssociateRan", RanName, E2TAddress).Return(nil)
+       setupRequest := models.SetupRequest{"127.0.0.1", 8080, RanName,}
+       nodebInfo, nbIdentity := createInitialNodeInfo(&setupRequest, entities.E2ApplicationProtocol_X2_SETUP_REQUEST, E2TAddress)
+       writerMock.On("SaveNodeb", nbIdentity, nodebInfo).Return(nil)
+       ranSetupManagerMock.On("ExecuteSetup", nodebInfo, entities.ConnectionStatus_CONNECTING).Return(e2managererrors.NewRnibDbError())
+       _, err := handler.Handle(setupRequest)
+       assert.IsType(t, &e2managererrors.RnibDbError{}, err)
+}
 
-       expected := &e2managererrors.RequestValidationError{}
-       if reflect.TypeOf(actual) != reflect.TypeOf(expected) {
-               t.Errorf("Error actual = %v, and Expected = %v.", actual, expected)
-       }
-       writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 0)
-       rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 0)
+func TestSetupNewRanSetupRmrError(t *testing.T) {
+       readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
+       readerMock.On("GetNodeb", RanName).Return(&entities.NodebInfo{}, common.NewResourceNotFoundError(""))
+       e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil)
+       e2tInstancesManagerMock.On("AssociateRan", RanName, E2TAddress).Return(nil)
+       setupRequest := models.SetupRequest{"127.0.0.1", 8080, RanName,}
+       nodebInfo, nbIdentity := createInitialNodeInfo(&setupRequest, entities.E2ApplicationProtocol_X2_SETUP_REQUEST, E2TAddress)
+       writerMock.On("SaveNodeb", nbIdentity, nodebInfo).Return(nil)
+       ranSetupManagerMock.On("ExecuteSetup", nodebInfo, entities.ConnectionStatus_CONNECTING).Return(e2managererrors.NewRmrError())
+       _, err := handler.Handle(setupRequest)
+       assert.IsType(t, &e2managererrors.RmrError{}, err)
 }
 
-func TestX2SetupHandleNoIP_Error(t *testing.T) {
-       _, writerMock, handler, rmrMessengerMock := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
+func TestSetupNewRanSetupSuccess(t *testing.T) {
+       readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
+       readerMock.On("GetNodeb", RanName).Return(&entities.NodebInfo{}, common.NewResourceNotFoundError(""))
+       e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil)
+       e2tInstancesManagerMock.On("AssociateRan", RanName, E2TAddress).Return(nil)
+       setupRequest := models.SetupRequest{"127.0.0.1", 8080, RanName,}
+       nodebInfo, nbIdentity := createInitialNodeInfo(&setupRequest, entities.E2ApplicationProtocol_X2_SETUP_REQUEST, E2TAddress)
+       writerMock.On("SaveNodeb", nbIdentity, nodebInfo).Return(nil)
+       ranSetupManagerMock.On("ExecuteSetup", nodebInfo, entities.ConnectionStatus_CONNECTING).Return(nil)
+       _, err := handler.Handle(setupRequest)
+       assert.Nil(t, err)
+}
 
-       sr := models.SetupRequest{}
-       sr.RanPort = 8080
-       sr.RanName = "RanName"
+func TestX2SetupExistingRanShuttingDown(t *testing.T) {
+       readerMock, _, handler, e2tInstancesManagerMock, ranSetupManagerMock := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
+       readerMock.On("GetNodeb", RanName).Return(&entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN}, nil)
+       setupRequest := models.SetupRequest{"127.0.0.1", 8080, RanName,}
+       _, err := handler.Handle(setupRequest)
+       assert.IsType(t, &e2managererrors.WrongStateError{}, err)
+       e2tInstancesManagerMock.AssertNotCalled(t, "SelectE2TInstance")
+       ranSetupManagerMock.AssertNotCalled(t, "ExecuteSetup")
+}
 
-       _, actual := handler.Handle(sr)
+func TestEndcSetupExistingRanShuttingDown(t *testing.T) {
+       readerMock, _, handler, e2tInstancesManagerMock, ranSetupManagerMock := initSetupRequestTest(t, entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST)
+       readerMock.On("GetNodeb", RanName).Return(&entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN}, nil)
+       setupRequest := models.SetupRequest{"127.0.0.1", 8080, RanName,}
+       _, err := handler.Handle(setupRequest)
+       assert.IsType(t, &e2managererrors.WrongStateError{}, err)
+       e2tInstancesManagerMock.AssertNotCalled(t, "SelectE2TInstance")
+       ranSetupManagerMock.AssertNotCalled(t, "ExecuteSetup")
+}
 
-       expected := &e2managererrors.RequestValidationError{}
-       if reflect.TypeOf(actual) != reflect.TypeOf(expected) {
-               t.Errorf("Error actual = %v, and Expected = %v.", actual, expected)
-       }
-       writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 0)
-       rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 0)
+func TestSetupExistingRanWithoutAssocE2TInstanceSelectDbError(t *testing.T) {
+       readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
+       nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
+       readerMock.On("GetNodeb", RanName).Return(nb, nil)
+       e2tInstancesManagerMock.On("SelectE2TInstance").Return("", e2managererrors.NewRnibDbError())
+       updatedNb := *nb
+       updatedNb.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
+       writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
+       setupRequest := models.SetupRequest{"127.0.0.1", 8080, RanName,}
+       _, err := handler.Handle(setupRequest)
+       assert.IsType(t, &e2managererrors.RnibDbError{}, err)
+       ranSetupManagerMock.AssertNotCalled(t, "ExecuteSetup")
 }
 
-func TestX2SetupHandleInvalidIp_Error(t *testing.T) {
-       _, writerMock, handler, rmrMessengerMock := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
+func TestSetupExistingRanWithoutAssocE2TInstanceSelectNoInstanceError(t *testing.T) {
+       readerMock, writerMock, handler, rmrMessengerMock := initSetupRequestTestBasicMocks(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
+       nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
+       readerMock.On("GetNodeb", RanName).Return(nb, nil)
+       readerMock.On("GetE2TAddresses").Return([]string{}, nil)
+       updatedNb := *nb
+       updatedNb.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
+       writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
+       setupRequest := models.SetupRequest{"127.0.0.1", 8080, RanName,}
+       _, err := handler.Handle(setupRequest)
+       assert.IsType(t, &e2managererrors.E2TInstanceAbsenceError{}, err)
+       rmrMessengerMock.AssertNotCalled(t, "SendMsg")
+       writerMock.AssertExpectations(t)
+}
 
-       sr := models.SetupRequest{}
-       sr.RanPort = 8080
-       sr.RanName = "RanName"
-       sr.RanIp = "invalid ip"
+func TestSetupExistingRanWithoutAssocE2TInstanceSelectNoInstanceErrorUpdateFailure(t *testing.T) {
+       readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
+       nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
+       readerMock.On("GetNodeb", RanName).Return(nb, nil)
+       e2tInstancesManagerMock.On("SelectE2TInstance").Return("", e2managererrors.NewE2TInstanceAbsenceError())
+       updatedNb := *nb
+       updatedNb.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
+       writerMock.On("UpdateNodebInfo", &updatedNb).Return(common.NewInternalError(fmt.Errorf("")))
+       setupRequest := models.SetupRequest{"127.0.0.1", 8080, RanName,}
+       _, err := handler.Handle(setupRequest)
+       assert.IsType(t, &e2managererrors.E2TInstanceAbsenceError{}, err)
+       ranSetupManagerMock.AssertNotCalled(t, "ExecuteSetup")
+}
 
-       _, actual := handler.Handle(sr)
+func TestSetupExistingRanWithoutAssocE2TInstanceSelectErrorAlreadyDisconnected(t *testing.T) {
+       readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
+       nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: "", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED}
+       readerMock.On("GetNodeb", RanName).Return(nb, nil)
+       e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, e2managererrors.NewE2TInstanceAbsenceError())
+       setupRequest := models.SetupRequest{"127.0.0.1", 8080, RanName,}
+       _, err := handler.Handle(setupRequest)
+       assert.IsType(t, &e2managererrors.E2TInstanceAbsenceError{}, err)
+       writerMock.AssertNotCalled(t, "UpdateNodebInfo")
+       ranSetupManagerMock.AssertNotCalled(t, "ExecuteSetup")
+}
 
-       expected := &e2managererrors.RequestValidationError{}
-       if reflect.TypeOf(actual) != reflect.TypeOf(expected) {
-               t.Errorf("Error actual = %v, and Expected = %v.", actual, expected)
-       }
-       writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 0)
-       rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 0)
+func TestSetupExistingRanWithoutAssocE2TInstanceAssociateRanFailure(t *testing.T) {
+       readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
+       nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
+       readerMock.On("GetNodeb", RanName).Return(nb, nil)
+       e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil)
+       e2tInstancesManagerMock.On("AssociateRan", RanName, E2TAddress).Return(e2managererrors.NewRnibDbError())
+       _, err := handler.Handle(models.SetupRequest{"127.0.0.1", 8080, RanName,})
+       assert.IsType(t, &e2managererrors.RnibDbError{}, err)
+       writerMock.AssertNotCalled(t, "UpdateNodebInfo")
+       ranSetupManagerMock.AssertNotCalled(t, "ExecuteSetup")
 }
 
-func initSetupRequestTest(t *testing.T, protocol entities.E2ApplicationProtocol) (*mocks.RnibReaderMock, *mocks.RnibWriterMock, *SetupRequestHandler, *mocks.RmrMessengerMock) {
-       log := initLog(t)
-       config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
+func TestSetupExistingRanWithoutAssocE2TInstanceAssociateRanSucceedsUpdateNodebFails(t *testing.T) {
+       readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
+       nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
+       readerMock.On("GetNodeb", RanName).Return(nb, nil)
+       e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil)
+       e2tInstancesManagerMock.On("AssociateRan", RanName, E2TAddress).Return(nil)
+       updatedNb := *nb
+       updatedNb.AssociatedE2TInstanceAddress = E2TAddress
+       updatedNb.ConnectionAttempts = 0
+       writerMock.On("UpdateNodebInfo", &updatedNb).Return(common.NewInternalError(fmt.Errorf("")))
+       _, err := handler.Handle(models.SetupRequest{"127.0.0.1", 8080, RanName,})
+       assert.IsType(t, &e2managererrors.RnibDbError{}, err)
+       ranSetupManagerMock.AssertNotCalled(t, "ExecuteSetup")
+}
 
-       readerMock := &mocks.RnibReaderMock{}
-       readerProvider := func() reader.RNibReader {
-               return readerMock
-       }
-       writerMock := &mocks.RnibWriterMock{}
-       writerProvider := func() rNibWriter.RNibWriter {
-               return writerMock
-       }
+func TestSetupExistingRanWithoutAssocE2TInstanceExecuteSetupFailure(t *testing.T) {
+       readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
+       nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
+       readerMock.On("GetNodeb", RanName).Return(nb, nil)
+       e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil)
+       e2tInstancesManagerMock.On("AssociateRan", RanName, E2TAddress).Return(nil)
+       updatedNb := *nb
+       updatedNb.AssociatedE2TInstanceAddress = E2TAddress
+       updatedNb.ConnectionAttempts = 0
+       writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
+       ranSetupManagerMock.On("ExecuteSetup", &updatedNb, entities.ConnectionStatus_CONNECTING).Return(e2managererrors.NewRnibDbError())
+       _, err := handler.Handle(models.SetupRequest{"127.0.0.1", 8080, RanName,})
+       assert.IsType(t, &e2managererrors.RnibDbError{}, err)
+}
 
-       rmrMessengerMock := &mocks.RmrMessengerMock{}
-       rmrSender := getRmrSender(rmrMessengerMock, log)
+func TestSetupExistingRanWithoutAssocE2TInstanceSuccess(t *testing.T) {
+       readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
+       nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
+       readerMock.On("GetNodeb", RanName).Return(nb, nil)
+       e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil)
+       e2tInstancesManagerMock.On("AssociateRan", RanName, E2TAddress).Return(nil)
+       updatedNb := *nb
+       updatedNb.AssociatedE2TInstanceAddress = E2TAddress
+       updatedNb.ConnectionAttempts = 0
+       writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
+       ranSetupManagerMock.On("ExecuteSetup", &updatedNb, entities.ConnectionStatus_CONNECTING).Return(nil)
+       _, err := handler.Handle(models.SetupRequest{"127.0.0.1", 8080, RanName,})
+       assert.Nil(t, err)
+}
 
-       rnibDataService := services.NewRnibDataService(log, config, readerProvider, writerProvider)
+func TestSetupExistingRanWithAssocE2TInstanceUpdateNodebFailure(t *testing.T) {
+       readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
+       nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress}
+       readerMock.On("GetNodeb", RanName).Return(nb, nil)
+       updatedNb := *nb
+       updatedNb.ConnectionAttempts = 0
+       writerMock.On("UpdateNodebInfo", &updatedNb).Return(common.NewInternalError(fmt.Errorf("")))
+       _, err := handler.Handle(models.SetupRequest{"127.0.0.1", 8080, RanName,})
+       assert.IsType(t, &e2managererrors.RnibDbError{}, err)
+       e2tInstancesManagerMock.AssertNotCalled(t, "SelectE2TInstance")
+       e2tInstancesManagerMock.AssertNotCalled(t, "AssociateRan")
+       ranSetupManagerMock.AssertNotCalled(t, "ExecuteSetup")
+}
 
-       ranSetupManager := managers.NewRanSetupManager(log, rmrSender, rnibDataService)
-       handler := NewSetupRequestHandler(log, rnibDataService, ranSetupManager, protocol)
+func TestSetupExistingRanWithAssocE2TInstanceExecuteSetupRmrError(t *testing.T) {
+       readerMock, writerMock, handler, rmrMessengerMock := initSetupRequestTestBasicMocks(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
+       nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
+       readerMock.On("GetNodeb", RanName).Return(nb, nil)
+       updatedNb := *nb
+       updatedNb.ConnectionAttempts = 0
+       updatedNb2 := updatedNb
+       updatedNb2.ConnectionAttempts++
+       updatedNb3 := updatedNb2
+       updatedNb3.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
+       updatedNb3.ConnectionAttempts--
+       writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
+       writerMock.On("UpdateNodebInfo", &updatedNb2).Return(nil)
+       payload := e2pdus.PackedX2setupRequest
+       xaction := []byte(RanName)
+       msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), RanName, &payload, &xaction)
+       rmrMessengerMock.On("SendMsg",mock.Anything, true).Return(msg, e2managererrors.NewRmrError())
+       writerMock.On("UpdateNodebInfo", &updatedNb3).Return(nil)
+       _, err := handler.Handle(models.SetupRequest{"127.0.0.1", 8080, RanName,})
+       assert.IsType(t, &e2managererrors.RmrError{}, err)
+       writerMock.AssertExpectations(t)
+}
 
-       return readerMock, writerMock, handler, rmrMessengerMock
+func TestSetupExistingRanWithAssocE2TInstanceConnectedSuccess(t *testing.T) {
+       readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
+       nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress, ConnectionStatus: entities.ConnectionStatus_CONNECTED}
+       readerMock.On("GetNodeb", RanName).Return(nb, nil)
+       updatedNb := *nb
+       updatedNb.ConnectionAttempts = 0
+       writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
+       ranSetupManagerMock.On("ExecuteSetup", &updatedNb, entities.ConnectionStatus_CONNECTED).Return(nil)
+       _, err := handler.Handle(models.SetupRequest{"127.0.0.1", 8080, RanName,})
+       assert.Nil(t, err)
+       e2tInstancesManagerMock.AssertNotCalled(t, "SelectE2TInstance")
+       e2tInstancesManagerMock.AssertNotCalled(t, "AssociateRan")
 }
index 0738eae..13a88ad 100644 (file)
@@ -81,7 +81,9 @@ func (handler *X2ResetRequestHandler) Handle(request models.Request) (models.IRe
                return nil, e2managererrors.NewWrongStateError(X2_RESET_ACTIVITY_NAME, entities.ConnectionStatus_name[int32(nodeb.ConnectionStatus)])
        }
 
-       msg := models.NewRmrMessage(rmrCgo.RIC_X2_RESET, resetRequest.RanName, payload)
+       var xAction []byte
+
+       msg := models.NewRmrMessage(rmrCgo.RIC_X2_RESET, resetRequest.RanName, payload, xAction)
 
        err = handler.rmrSender.Send(msg)
 
index 870385b..16def4c 100644 (file)
@@ -5,13 +5,11 @@ import (
        "e2mgr/e2managererrors"
        "e2mgr/mocks"
        "e2mgr/models"
-       "e2mgr/rNibWriter"
        "e2mgr/rmrCgo"
        "e2mgr/services"
        "fmt"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
-       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
        "github.com/stretchr/testify/assert"
        "testing"
 )
@@ -20,14 +18,8 @@ func setupX2ResetRequestHandlerTest(t *testing.T) (*X2ResetRequestHandler, *mock
        log := initLog(t)
        config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
        readerMock := &mocks.RnibReaderMock{}
-       readerProvider := func() reader.RNibReader {
-               return readerMock
-       }
        writerMock := &mocks.RnibWriterMock{}
-       writerProvider := func() rNibWriter.RNibWriter {
-               return writerMock
-       }
-       rnibDataService := services.NewRnibDataService(log, config, readerProvider, writerProvider)
+       rnibDataService := services.NewRnibDataService(log, config, readerMock, writerMock)
        rmrMessengerMock := &mocks.RmrMessengerMock{}
        rmrSender := getRmrSender(rmrMessengerMock, log)
        handler := NewX2ResetRequestHandler(log, rmrSender, rnibDataService)
@@ -40,10 +32,10 @@ func TestHandleSuccessfulDefaultCause(t *testing.T) {
        ranName := "test1"
        // o&m intervention
        payload := []byte{0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x05, 0x40, 0x01, 0x64}
-       xaction := []byte(ranName)
-       msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET, len(payload), ranName, &payload, &xaction)
+       var xAction[]byte
+       msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET, len(payload), ranName, &payload, &xAction)
 
-       rmrMessengerMock.On("SendMsg", msg).Return(msg, nil)
+       rmrMessengerMock.On("SendMsg", msg, true).Return(msg, nil)
 
        var nodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED}
        readerMock.On("GetNodeb", ranName).Return(nodeb, nil)
@@ -58,9 +50,9 @@ func TestHandleSuccessfulRequestedCause(t *testing.T) {
 
        ranName := "test1"
        payload := []byte{0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x05, 0x40, 0x01, 0x40}
-       xaction := []byte(ranName)
-       msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET, len(payload), ranName, &payload, &xaction)
-       rmrMessengerMock.On("SendMsg", msg).Return(msg, nil)
+       var xAction[]byte
+       msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET, len(payload), ranName, &payload, &xAction)
+       rmrMessengerMock.On("SendMsg", msg, true).Return(msg, nil)
 
        var nodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED}
        readerMock.On("GetNodeb", ranName).Return(nodeb, nil)
@@ -125,9 +117,9 @@ func TestHandleFailureRmrError(t *testing.T) {
        ranName := "test1"
        // o&m intervention
        payload := []byte{0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x05, 0x40, 0x01, 0x64}
-       xaction := []byte(ranName)
-       msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET, len(payload), ranName, &payload, &xaction)
-       rmrMessengerMock.On("SendMsg", msg).Return(&rmrCgo.MBuf{}, fmt.Errorf("rmr error"))
+       var xAction[]byte
+       msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET, len(payload), ranName, &payload, &xAction)
+       rmrMessengerMock.On("SendMsg", msg, true).Return(&rmrCgo.MBuf{}, fmt.Errorf("rmr error"))
 
        var nodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED}
        readerMock.On("GetNodeb", ranName).Return(nodeb, nil)
index 6bc047c..283de35 100644 (file)
 package rmrmsghandlers
 
 import (
+       "e2mgr/clients"
        "e2mgr/logger"
        "e2mgr/managers"
        "e2mgr/models"
        "e2mgr/services"
+       "encoding/json"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
 )
 
 type E2TermInitNotificationHandler struct {
        logger                 *logger.Logger
        rnibDataService        services.RNibDataService
        ranReconnectionManager *managers.RanReconnectionManager
+       e2tInstancesManager    managers.IE2TInstancesManager
+       routingManagerClient   clients.IRoutingManagerClient
 }
 
-func NewE2TermInitNotificationHandler(logger *logger.Logger, ranReconnectionManager *managers.RanReconnectionManager, rnibDataService services.RNibDataService) E2TermInitNotificationHandler {
+func NewE2TermInitNotificationHandler(logger *logger.Logger, ranReconnectionManager *managers.RanReconnectionManager, rnibDataService services.RNibDataService, e2tInstancesManager managers.IE2TInstancesManager, routingManagerClient clients.IRoutingManagerClient) E2TermInitNotificationHandler {
        return E2TermInitNotificationHandler{
                logger:                 logger,
                rnibDataService:        rnibDataService,
                ranReconnectionManager: ranReconnectionManager,
+               e2tInstancesManager:    e2tInstancesManager,
+               routingManagerClient:   routingManagerClient,
        }
 }
 
 func (h E2TermInitNotificationHandler) Handle(request *models.NotificationRequest) {
+       unmarshalledPayload := models.E2TermInitPayload{}
+       err := json.Unmarshal(request.Payload, &unmarshalledPayload)
 
-       h.logger.Infof("#E2TermInitNotificationHandler.Handle - Handling E2_TERM_INIT")
+       if err != nil {
+               h.logger.Errorf("#E2TermInitNotificationHandler.Handle - Error unmarshaling E2 Term Init payload: %s", err)
+               return
+       }
+
+       e2tAddress := unmarshalledPayload.Address
+
+       if len(e2tAddress) == 0 {
+               h.logger.Errorf("#E2TermInitNotificationHandler.Handle - Empty E2T address received")
+               return
+       }
+
+       h.logger.Infof("#E2TermInitNotificationHandler.Handle - E2T address: %s - handling E2_TERM_INIT", e2tAddress)
+
+       e2tInstance, err := h.e2tInstancesManager.GetE2TInstance(e2tAddress)
 
-       nbIdentityList, err := h.rnibDataService.GetListNodebIds()
        if err != nil {
-               h.logger.Errorf("#E2TermInitNotificationHandler.Handle - Failed to get nodes list from RNIB. Error: %s", err.Error())
+               _, ok := err.(*common.ResourceNotFoundError)
+
+               if !ok {
+                       h.logger.Errorf("#E2TermInitNotificationHandler.Handle - Failed retrieving E2TInstance. error: %s", err)
+                       return
+               }
+
+               h.HandleNewE2TInstance(e2tAddress)
                return
        }
 
-       if len(nbIdentityList) == 0 {
-               h.logger.Warnf("#E2TermInitNotificationHandler.Handle - The Nodes list in RNIB is empty")
+       if len(e2tInstance.AssociatedRanList) == 0 {
+               h.logger.Infof("#E2TermInitNotificationHandler.Handle - E2T Address: %s - E2T instance has no associated RANs", e2tInstance.Address)
                return
        }
 
-       for _, nbIdentity := range nbIdentityList {
+       if e2tInstance.State == entities.ToBeDeleted{
+               h.logger.Infof("#E2TermInitNotificationHandler.Handle - E2T Address: %s - E2T instance status is: %s, ignore", e2tInstance.Address, e2tInstance.State)
+               return
+       }
 
-               if err := h.ranReconnectionManager.ReconnectRan(nbIdentity.InventoryName); err != nil {
-                       h.logger.Errorf("#E2TermInitNotificationHandler.Handle - Ran name: %s - connection attempt failure, error: %s", (*nbIdentity).GetInventoryName(), err.Error())
+       if e2tInstance.State == entities.RoutingManagerFailure {
+               err := h.e2tInstancesManager.ActivateE2TInstance(e2tInstance)
+               if err != nil {
+                       return
+               }
+       }
+
+       h.HandleExistingE2TInstance(e2tInstance)
+
+       h.logger.Infof("#E2TermInitNotificationHandler.Handle - Completed handling of E2_TERM_INIT")
+}
+
+func (h E2TermInitNotificationHandler) HandleExistingE2TInstance(e2tInstance *entities.E2TInstance) {
+
+       for _, ranName := range e2tInstance.AssociatedRanList {
+
+               if err := h.ranReconnectionManager.ReconnectRan(ranName); err != nil {
+                       h.logger.Errorf("#E2TermInitNotificationHandler.HandleExistingE2TInstance - Ran name: %s - connection attempt failure, error: %s", ranName, err)
                        _, ok := err.(*common.ResourceNotFoundError)
                        if !ok {
                                break
                        }
                }
        }
-
-       h.logger.Infof("#E2TermInitNotificationHandler.Handle - Completed handling of E2_TERM_INIT")
 }
+
+func (h E2TermInitNotificationHandler) HandleNewE2TInstance(e2tAddress string) {
+
+       err := h.routingManagerClient.AddE2TInstance(e2tAddress)
+
+       if err != nil{
+               h.logger.Errorf("#E2TermInitNotificationHandler.HandleNewE2TInstance - e2t address: %s - routing manager failure", e2tAddress)
+               return
+       }
+
+       _ = h.e2tInstancesManager.AddE2TInstance(e2tAddress)
+}
\ No newline at end of file
index ae88cb2..f6779df 100644 (file)
@@ -1,3 +1,19 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
 package rmrmsghandlers
 
 import (
@@ -7,7 +23,6 @@ import (
        "e2mgr/managers"
        "e2mgr/mocks"
        "e2mgr/models"
-       "e2mgr/rNibWriter"
        "e2mgr/rmrCgo"
        "e2mgr/services"
        "e2mgr/services/rmrsender"
@@ -15,12 +30,14 @@ import (
        "fmt"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
-       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
        "github.com/stretchr/testify/mock"
        "testing"
 )
 
-func initRanLostConnectionTest(t *testing.T) (*logger.Logger, E2TermInitNotificationHandler, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.RmrMessengerMock) {
+const e2tInstanceAddress = "10.0.2.15"
+const e2tInitPayload = "{\"address\":\"10.0.2.15\", \"fqdn\":\"\"}"
+
+func initRanLostConnectionTest(t *testing.T) (*logger.Logger, E2TermInitNotificationHandler, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.RmrMessengerMock, *mocks.E2TInstancesManagerMock, *mocks.RoutingManagerClientMock) {
 
        logger := initLog(t)
        config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
@@ -29,78 +46,325 @@ func initRanLostConnectionTest(t *testing.T) (*logger.Logger, E2TermInitNotifica
        rmrSender := initRmrSender(rmrMessengerMock, logger)
 
        readerMock := &mocks.RnibReaderMock{}
-       rnibReaderProvider := func() reader.RNibReader {
-               return readerMock
-       }
+
        writerMock := &mocks.RnibWriterMock{}
-       rnibWriterProvider := func() rNibWriter.RNibWriter {
-               return writerMock
-       }
-       rnibDataService := services.NewRnibDataService(logger, config, rnibReaderProvider, rnibWriterProvider)
+
+       routingManagerClientMock := &mocks.RoutingManagerClientMock{}
+
+       rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
+       ranSetupManager := managers.NewRanSetupManager(logger, rmrSender, rnibDataService)
+
+       e2tInstancesManagerMock := &mocks.E2TInstancesManagerMock{}
+
+       ranReconnectionManager := managers.NewRanReconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, ranSetupManager, e2tInstancesManagerMock)
+       handler := NewE2TermInitNotificationHandler(logger, ranReconnectionManager, rnibDataService, e2tInstancesManagerMock, routingManagerClientMock)
+
+       return logger, handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock
+}
+
+func initRanLostConnectionTestWithRealE2tInstanceManager(t *testing.T) (*logger.Logger, E2TermInitNotificationHandler, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.RmrMessengerMock) {
+
+       logger := initLog(t)
+       config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
+
+       rmrMessengerMock := &mocks.RmrMessengerMock{}
+       rmrSender := initRmrSender(rmrMessengerMock, logger)
+
+       readerMock := &mocks.RnibReaderMock{}
+
+       writerMock := &mocks.RnibWriterMock{}
+       routingManagerClientMock := &mocks.RoutingManagerClientMock{}
+
+       rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
        ranSetupManager := managers.NewRanSetupManager(logger, rmrSender, rnibDataService)
-       ranReconnectionManager := managers.NewRanReconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, ranSetupManager)
-       handler := NewE2TermInitNotificationHandler(logger, ranReconnectionManager, rnibDataService)
+
+       e2tInstancesManager := managers.NewE2TInstancesManager(rnibDataService, logger)
+       ranReconnectionManager := managers.NewRanReconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, ranSetupManager, e2tInstancesManager)
+       handler := NewE2TermInitNotificationHandler(logger, ranReconnectionManager, rnibDataService, e2tInstancesManager, routingManagerClientMock)
        return logger, handler, readerMock, writerMock, rmrMessengerMock
 }
 
-func TestE2TerminInitHandlerSuccessOneRan(t *testing.T) {
-       _, handler, readerMock, writerMock, rmrMessengerMock := initRanLostConnectionTest(t)
-       var rnibErr error
+func TestE2TermInitUnmarshalPayloadFailure(t *testing.T) {
+       _, handler, _, _, _, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t)
+       notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte("asd")}
+       handler.Handle(notificationRequest)
+       e2tInstancesManagerMock.AssertNotCalled(t, "GetE2TInstance")
+       e2tInstancesManagerMock.AssertNotCalled(t, "AddE2TInstance")
+}
 
-       ids := []*entities.NbIdentity{{InventoryName: "test1"}}
-       readerMock.On("GetListNodebIds").Return(ids, rnibErr)
+func TestE2TermInitEmptyE2TAddress(t *testing.T) {
+       _, handler, _, _, _, e2tInstancesManagerMock, _  := initRanLostConnectionTest(t)
+       notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte("{\"address\":\"\"}")}
+       handler.Handle(notificationRequest)
+       e2tInstancesManagerMock.AssertNotCalled(t, "GetE2TInstance")
+       e2tInstancesManagerMock.AssertNotCalled(t, "AddE2TInstance")
+}
+
+func TestE2TermInitGetE2TInstanceFailure(t *testing.T) {
+       _, handler, _, _, _, e2tInstancesManagerMock, _  := initRanLostConnectionTest(t)
+       var e2tInstance *entities.E2TInstance
+       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, common.NewInternalError(fmt.Errorf("internal error")))
+       notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
+       handler.Handle(notificationRequest)
+       e2tInstancesManagerMock.AssertNotCalled(t, "AddE2TInstance")
+}
+
+func TestE2TermInitGetE2TInstanceDbFailure(t *testing.T) {
+       _, handler, readerMock, writerMock, rmrMessengerMock := initRanLostConnectionTestWithRealE2tInstanceManager(t)
+       var e2tInstance *entities.E2TInstance
+       readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, common.NewInternalError(fmt.Errorf("internal error")))
+       notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
+       handler.Handle(notificationRequest)
+       writerMock.AssertNotCalled(t, "UpdateNodebInfo")
+       rmrMessengerMock.AssertNotCalled(t, "SendMsg")
+}
+
+func TestE2TermInitNewE2TInstance(t *testing.T) {
+       _, handler, _, _, _, e2tInstancesManagerMock, routingManagerClient := initRanLostConnectionTest(t)
+       var e2tInstance *entities.E2TInstance
+       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, common.NewResourceNotFoundError("not found"))
+       e2tInstance = entities.NewE2TInstance(e2tInstanceAddress)
+       e2tInstancesManagerMock.On("AddE2TInstance", e2tInstanceAddress).Return(nil)
+       routingManagerClient.On("AddE2TInstance", e2tInstanceAddress).Return(nil)
+       notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
+       handler.Handle(notificationRequest)
+       routingManagerClient.AssertCalled(t, "AddE2TInstance", e2tInstanceAddress)
+       e2tInstancesManagerMock.AssertCalled(t, "AddE2TInstance", e2tInstanceAddress)
+}
+
+func TestE2TermInitNewE2TInstance_RoutingManagerError(t *testing.T) {
+       _, handler, _, _, _, e2tInstancesManagerMock, routingManagerClient := initRanLostConnectionTest(t)
+       var e2tInstance *entities.E2TInstance
+       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, common.NewResourceNotFoundError("not found"))
+       e2tInstance = entities.NewE2TInstance(e2tInstanceAddress)
+       e2tInstancesManagerMock.On("AddE2TInstance", e2tInstanceAddress).Return(nil)
+       routingManagerClient.On("AddE2TInstance", e2tInstanceAddress).Return(fmt.Errorf("error"))
+       notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
+
+       handler.Handle(notificationRequest)
+
+       routingManagerClient.AssertCalled(t, "AddE2TInstance", e2tInstanceAddress)
+       e2tInstancesManagerMock.AssertNotCalled(t, "AddE2TInstance", e2tInstanceAddress)
+}
+
+func TestE2TermInitExistingE2TInstanceNoAssociatedRans(t *testing.T) {
+       _, handler, _, _, _, e2tInstancesManagerMock, _  := initRanLostConnectionTest(t)
+       e2tInstance := entities.NewE2TInstance(e2tInstanceAddress)
+       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil)
+       notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
+       handler.Handle(notificationRequest)
+       e2tInstancesManagerMock.AssertCalled(t, "GetE2TInstance", e2tInstanceAddress)
+}
+
+func TestE2TermInitHandlerSuccessOneRan(t *testing.T) {
+       _, handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, _  := initRanLostConnectionTest(t)
+       var rnibErr error
 
        var initialNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
-       readerMock.On("GetNodeb", ids[0].InventoryName).Return(initialNodeb, rnibErr)
+       readerMock.On("GetNodeb", RanName).Return(initialNodeb, rnibErr)
 
        var argNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1}
        writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr)
 
        payload := e2pdus.PackedX2setupRequest
-       xaction := []byte(ids[0].InventoryName)
-       msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ids[0].InventoryName, &payload, &xaction)
+       xaction := []byte(RanName)
+       msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), RanName, &payload, &xaction)
+
+       rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg, nil)
+
+       e2tInstance := entities.NewE2TInstance(e2tInstanceAddress)
+       e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
+       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil)
+       notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
+
+       handler.Handle(notificationRequest)
+
+       writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1)
+       rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 1)
+}
+
+func TestE2TermInitHandlerSuccessOneRanShuttingdown(t *testing.T) {
+       _, handler, readerMock, writerMock, rmrMessengerMock := initRanLostConnectionTestWithRealE2tInstanceManager(t)
+       var rnibErr error
+
+       var initialNodeb = &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
+       readerMock.On("GetNodeb", RanName).Return(initialNodeb, rnibErr)
+
+       var argNodeb = &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 0}
+       writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr)
+
+       payload := e2pdus.PackedX2setupRequest
+       xaction := []byte(RanName)
+       msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), RanName, &payload, &xaction)
 
        rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, nil)
 
-       handler.Handle(nil)
+       e2tInstance := entities.NewE2TInstance(e2tInstanceAddress)
+       e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
+       readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil)
+       notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
+
+       handler.Handle(notificationRequest)
+
+       writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1)
+       rmrMessengerMock.AssertNotCalled(t, "SendMsg")
+}
+
+func TestE2TermInitHandlerSuccessOneRan_ToBeDeleted(t *testing.T) {
+       _, handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, _  := initRanLostConnectionTest(t)
+       var rnibErr error
+
+       var initialNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
+       readerMock.On("GetNodeb", RanName).Return(initialNodeb, rnibErr)
+
+       var argNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1}
+       writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr)
+
+       payload := e2pdus.PackedX2setupRequest
+       xaction := []byte(RanName)
+       msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), RanName, &payload, &xaction)
+
+       rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg, nil)
+
+       e2tInstance := entities.NewE2TInstance(e2tInstanceAddress)
+       e2tInstance.State = entities.ToBeDeleted
+       e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
+
+       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil)
+       notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
+
+       handler.Handle(notificationRequest)
+
+       writerMock.AssertNotCalled(t, "UpdateNodebInfo")
+       rmrMessengerMock.AssertNotCalled(t, "SendMsg")
+}
+
+func TestE2TermInitHandlerSuccessOneRan_RoutingManagerFailure(t *testing.T) {
+       _, handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, _  := initRanLostConnectionTest(t)
+       var rnibErr error
+
+       var initialNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
+       readerMock.On("GetNodeb", RanName).Return(initialNodeb, rnibErr)
+
+       var argNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1}
+       writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr)
+
+       payload := e2pdus.PackedX2setupRequest
+       xaction := []byte(RanName)
+       msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), RanName, &payload, &xaction)
+
+       rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg, nil)
+
+       e2tInstance := entities.NewE2TInstance(e2tInstanceAddress)
+       e2tInstance.State = entities.RoutingManagerFailure
+       e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
+
+       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil)
+       e2tInstancesManagerMock.On("ActivateE2TInstance", e2tInstance).Return(nil)
+       writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr)
+
+       notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
+
+       handler.Handle(notificationRequest)
 
        writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1)
        rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 1)
 }
 
-func TestE2TerminInitHandlerSuccessTwoRans(t *testing.T) {
-       _, handler, readerMock, writerMock, rmrMessengerMock := initRanLostConnectionTest(t)
+func TestE2TermInitHandlerSuccessOneRan_RoutingManagerFailure_Error(t *testing.T) {
+       _, handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, _  := initRanLostConnectionTest(t)
        var rnibErr error
 
-       ids := []*entities.NbIdentity{{InventoryName: "test1"}, {InventoryName: "test2"}}
-       readerMock.On("GetListNodebIds").Return(ids, rnibErr)
+       var initialNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
+       readerMock.On("GetNodeb", RanName).Return(initialNodeb, rnibErr)
+
+       var argNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1}
+       writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr)
 
+       payload := e2pdus.PackedX2setupRequest
+       xaction := []byte(RanName)
+       msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), RanName, &payload, &xaction)
+
+       rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg, nil)
+
+       e2tInstance := entities.NewE2TInstance(e2tInstanceAddress)
+       e2tInstance.State = entities.RoutingManagerFailure
+       e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
+
+       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil)
+       e2tInstancesManagerMock.On("ActivateE2TInstance", e2tInstance).Return(fmt.Errorf(" Error "))
+       writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr)
+
+       notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
+
+       handler.Handle(notificationRequest)
+
+       writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 0)
+       rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 0)
+}
+
+func TestE2TermInitHandlerSuccessTwoRans(t *testing.T) {
+       _, handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, _  := initRanLostConnectionTest(t)
+       var rnibErr error
        var initialNodeb0 = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
        var initialNodeb1 = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
-       readerMock.On("GetNodeb", ids[0].InventoryName).Return(initialNodeb0, rnibErr)
-       readerMock.On("GetNodeb", ids[1].InventoryName).Return(initialNodeb1, rnibErr)
+       readerMock.On("GetNodeb", RanName).Return(initialNodeb0, rnibErr)
+       readerMock.On("GetNodeb", "test2").Return(initialNodeb1, rnibErr)
 
        var argNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1}
        writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr)
 
        payload := e2pdus.PackedX2setupRequest
-       xaction := []byte(ids[0].InventoryName)
-       msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ids[0].InventoryName, &payload, &xaction)
+       xaction := []byte(RanName)
+       msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), RanName, &payload, &xaction)
 
-       rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, nil)
+       rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg, nil)
+
+       e2tInstance := entities.NewE2TInstance(e2tInstanceAddress)
+       e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName, "test2")
+       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil)
+       notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
 
-       handler.Handle(nil)
+       handler.Handle(notificationRequest)
 
        writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2)
        rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 2)
 }
 
-func TestE2TerminInitHandlerSuccessThreeRansFirstRmrFailure(t *testing.T) {
-       log, handler, readerMock, writerMock, rmrMessengerMock := initRanLostConnectionTest(t)
+func TestE2TermInitHandlerSuccessTwoRansSecondRanShutdown(t *testing.T) {
+       _, handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t)
+       var rnibErr error
+       var initialNodeb0 = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
+       var initialNodeb1 = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
+       readerMock.On("GetNodeb", RanName).Return(initialNodeb0, rnibErr)
+       readerMock.On("GetNodeb", "test2").Return(initialNodeb1, rnibErr)
+
+       var argNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1}
+       writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr)
+
+       payload := e2pdus.PackedX2setupRequest
+       xaction := []byte(RanName)
+       msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), RanName, &payload, &xaction)
+
+       rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg, nil)
+
+       e2tInstance := entities.NewE2TInstance(e2tInstanceAddress)
+       e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName, "test2")
+       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil)
+       notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
+
+       handler.Handle(notificationRequest)
+
+       writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1)
+       rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 1)
+       writerMock.AssertExpectations(t)
+}
+
+func TestE2TermInitHandlerSuccessThreeRansFirstRmrFailure(t *testing.T) {
+       log, handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, _  := initRanLostConnectionTest(t)
        var rnibErr error
 
        ids := []*entities.NbIdentity{{InventoryName: "test1"}, {InventoryName: "test2"}, {InventoryName: "test3"}}
-       readerMock.On("GetListNodebIds").Return(ids, rnibErr)
 
        var initialNodeb0 = &entities.NodebInfo{RanName: ids[0].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
        var initialNodeb1 = &entities.NodebInfo{RanName: ids[1].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
@@ -123,9 +387,14 @@ func TestE2TerminInitHandlerSuccessThreeRansFirstRmrFailure(t *testing.T) {
        //xaction = []byte(ids[1].InventoryName)
        //msg1 := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ids[1].InventoryName, &payload, &xaction)
 
-       rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg0, fmt.Errorf("RMR Error"))
+       rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg0, fmt.Errorf("RMR Error"))
 
-       handler.Handle(nil)
+       e2tInstance := entities.NewE2TInstance(e2tInstanceAddress)
+       e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, "test1", "test2", "test3")
+       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil)
+       notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
+
+       handler.Handle(notificationRequest)
 
        //test1 (before send +1, after failure +1), test2 (0) test3 (0)
        writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2)
@@ -133,12 +402,11 @@ func TestE2TerminInitHandlerSuccessThreeRansFirstRmrFailure(t *testing.T) {
        rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 1)
 }
 
-func TestE2TerminInitHandlerSuccessThreeRansSecondNotFoundFailure(t *testing.T) {
-       log, handler, readerMock, writerMock, rmrMessengerMock := initRanLostConnectionTest(t)
+func TestE2TermInitHandlerSuccessThreeRansSecondNotFoundFailure(t *testing.T) {
+       log, handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, _  := initRanLostConnectionTest(t)
        var rnibErr error
 
        ids := []*entities.NbIdentity{{InventoryName: "test1"}, {InventoryName: "test2"}, {InventoryName: "test3"}}
-       readerMock.On("GetListNodebIds").Return(ids, rnibErr)
 
        var initialNodeb0 = &entities.NodebInfo{RanName: ids[0].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
        var initialNodeb1 = &entities.NodebInfo{RanName: ids[1].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
@@ -166,9 +434,14 @@ func TestE2TerminInitHandlerSuccessThreeRansSecondNotFoundFailure(t *testing.T)
        //xaction = []byte(ids[1].InventoryName)
        //msg1 := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ids[1].InventoryName, &payload, &xaction)
 
-       rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg0, nil)
+       rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg0, nil)
+
+       e2tInstance := entities.NewE2TInstance(e2tInstanceAddress)
+       e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, "test1", "test2", "test3")
+       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil)
+       notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
 
-       handler.Handle(nil)
+       handler.Handle(notificationRequest)
 
        readerMock.AssertNumberOfCalls(t, "GetNodeb", 3)
        //test1 (+1), test2 failure (0) test3 (+1)
@@ -177,12 +450,11 @@ func TestE2TerminInitHandlerSuccessThreeRansSecondNotFoundFailure(t *testing.T)
        rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 2)
 }
 
-func TestE2TerminInitHandlerSuccessThreeRansSecondRnibInternalErrorFailure(t *testing.T) {
-       log, handler, readerMock, writerMock, rmrMessengerMock := initRanLostConnectionTest(t)
+func TestE2TermInitHandlerSuccessThreeRansSecondRnibInternalErrorFailure(t *testing.T) {
+       log, handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, _  := initRanLostConnectionTest(t)
        var rnibErr error
 
        ids := []*entities.NbIdentity{{InventoryName: "test1"}, {InventoryName: "test2"}, {InventoryName: "test3"}}
-       readerMock.On("GetListNodebIds").Return(ids, rnibErr)
 
        var initialNodeb0 = &entities.NodebInfo{RanName: ids[0].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
        var initialNodeb1 = &entities.NodebInfo{RanName: ids[1].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
@@ -210,9 +482,14 @@ func TestE2TerminInitHandlerSuccessThreeRansSecondRnibInternalErrorFailure(t *te
        //xaction = []byte(ids[1].InventoryName)
        //msg1 := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ids[1].InventoryName, &payload, &xaction)
 
-       rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg0, nil)
+       rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg0, nil)
 
-       handler.Handle(nil)
+       e2tInstance := entities.NewE2TInstance(e2tInstanceAddress)
+       e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, "test1", "test2", "test3")
+       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil)
+       notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
+
+       handler.Handle(notificationRequest)
 
        readerMock.AssertNumberOfCalls(t, "GetNodeb", 2)
        //test1 (+1), test2 failure (0) test3 (0)
@@ -221,34 +498,69 @@ func TestE2TerminInitHandlerSuccessThreeRansSecondRnibInternalErrorFailure(t *te
        rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 1)
 }
 
-func TestE2TerminInitHandlerSuccessZeroRans(t *testing.T) {
-       _, handler, readerMock, writerMock, rmrMessengerMock := initRanLostConnectionTest(t)
-       var rnibErr error
+func TestE2TermInitHandlerSuccessZeroRans(t *testing.T) {
+       _, handler, _, writerMock, rmrMessengerMock, e2tInstancesManagerMock, _  := initRanLostConnectionTest(t)
 
-       readerMock.On("GetListNodebIds").Return([]*entities.NbIdentity{}, rnibErr)
+       e2tInstance := entities.NewE2TInstance(e2tInstanceAddress)
+       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil)
+       notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
 
-       handler.Handle(nil)
+       handler.Handle(notificationRequest)
 
-       writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 0)
-       rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 0)
+       writerMock.AssertNotCalled(t, "UpdateNodebInfo")
+       rmrMessengerMock.AssertNotCalled(t, "SendMsg")
 }
 
-func TestE2TerminInitHandlerFailureGetListNodebIds(t *testing.T) {
-       _, handler, readerMock, writerMock, rmrMessengerMock := initRanLostConnectionTest(t)
+func TestE2TermInitHandlerFailureGetNodebInternalError(t *testing.T) {
+       _, handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t)
 
-       readerMock.On("GetListNodebIds").Return([]*entities.NbIdentity{}, common.NewInternalError(fmt.Errorf("internal error")))
+       var nodebInfo *entities.NodebInfo
+       readerMock.On("GetNodeb", "test1").Return(nodebInfo, common.NewInternalError(fmt.Errorf("internal error")))
 
-       handler.Handle(nil)
+       e2tInstance := entities.NewE2TInstance(e2tInstanceAddress)
+       e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, "test1")
+       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil)
+       notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
+       handler.Handle(notificationRequest)
 
-       writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 0)
-       rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 0)
+       writerMock.AssertNotCalled(t, "UpdateNodebInfo")
+       rmrMessengerMock.AssertNotCalled(t, "SendMsg")
+}
+
+func TestE2TermInitHandlerSuccessTwoRansSecondIsDisconnected(t *testing.T) {
+       _, handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t)
+       var rnibErr error
+       var initialNodeb0 = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
+       var initialNodeb1 = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
+       readerMock.On("GetNodeb", RanName).Return(initialNodeb0, rnibErr)
+       readerMock.On("GetNodeb", "test2").Return(initialNodeb1, rnibErr)
+
+       var argNodeb1 = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1}
+       writerMock.On("UpdateNodebInfo", argNodeb1).Return(rnibErr)
+
+       payload := e2pdus.PackedX2setupRequest
+       xaction := []byte(RanName)
+       msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), RanName, &payload, &xaction)
+
+       rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg, nil)
+
+       e2tInstance := entities.NewE2TInstance(e2tInstanceAddress)
+       e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName, "test2")
+       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil)
+       notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
+
+       handler.Handle(notificationRequest)
+
+       writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2)
+       rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 2)
 }
 
+
 // TODO: extract to test_utils
 func initRmrSender(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *rmrsender.RmrSender {
        rmrMessenger := rmrCgo.RmrMessenger(rmrMessengerMock)
        rmrMessengerMock.On("Init", tests.GetPort(), tests.MaxMsgSize, tests.Flags, log).Return(&rmrMessenger)
-       return rmrsender.NewRmrSender(log, &rmrMessenger)
+       return rmrsender.NewRmrSender(log, rmrMessenger)
 }
 
 // TODO: extract to test_utils
diff --git a/E2Manager/handlers/rmrmsghandlers/e2t_keep_alive_response_handler.go b/E2Manager/handlers/rmrmsghandlers/e2t_keep_alive_response_handler.go
new file mode 100644 (file)
index 0000000..73583d4
--- /dev/null
@@ -0,0 +1,51 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+package rmrmsghandlers
+
+import (
+       "e2mgr/logger"
+       "e2mgr/managers"
+       "e2mgr/models"
+       "e2mgr/services"
+       "encoding/json"
+)
+
+type E2TKeepAliveResponseHandler struct {
+       logger              *logger.Logger
+       rnibDataService     services.RNibDataService
+       e2TInstancesManager managers.IE2TInstancesManager
+}
+
+func NewE2TKeepAliveResponseHandler(logger *logger.Logger, rnibDataService services.RNibDataService, e2TInstancesManager managers.IE2TInstancesManager) E2TKeepAliveResponseHandler {
+       return E2TKeepAliveResponseHandler{
+               logger:              logger,
+               rnibDataService:     rnibDataService,
+               e2TInstancesManager: e2TInstancesManager,
+       }
+}
+
+func (h E2TKeepAliveResponseHandler) Handle(request *models.NotificationRequest) {
+       unmarshalledPayload := models.E2TKeepAlivePayload{}
+       err := json.Unmarshal(request.Payload, &unmarshalledPayload)
+
+       if err != nil {
+               h.logger.Errorf("#E2TKeepAliveResponseHandler.Handle - Error unmarshaling RMR request payload: %v", err)
+               return
+       }
+
+       _ = h.e2TInstancesManager.ResetKeepAliveTimestamp(unmarshalledPayload.Address)
+}
diff --git a/E2Manager/handlers/rmrmsghandlers/e2t_keep_alive_response_handler_test.go b/E2Manager/handlers/rmrmsghandlers/e2t_keep_alive_response_handler_test.go
new file mode 100644 (file)
index 0000000..ba9fc43
--- /dev/null
@@ -0,0 +1,59 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+package rmrmsghandlers
+
+import (
+       "e2mgr/configuration"
+       "e2mgr/logger"
+       "e2mgr/mocks"
+       "e2mgr/models"
+       "e2mgr/services"
+       "testing"
+)
+
+func initE2TKeepAliveTest(t *testing.T) (*logger.Logger, E2TKeepAliveResponseHandler, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.E2TInstancesManagerMock) {
+
+       logger := initLog(t)
+       config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
+
+       readerMock := &mocks.RnibReaderMock{}
+       writerMock := &mocks.RnibWriterMock{}
+
+       rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
+
+       e2tInstancesManagerMock := &mocks.E2TInstancesManagerMock{}
+       handler := NewE2TKeepAliveResponseHandler(logger, rnibDataService, e2tInstancesManagerMock)
+       return logger, handler, readerMock, writerMock, e2tInstancesManagerMock
+}
+
+func TestE2TKeepAliveUnmarshalPayloadFailure(t *testing.T) {
+       _, handler, _, _, e2tInstancesManagerMock := initE2TKeepAliveTest(t)
+       notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte("asd")}
+       handler.Handle(notificationRequest)
+       e2tInstancesManagerMock.AssertNotCalled(t, "ResetKeepAliveTimestamp")
+}
+
+func TestE2TKeepAliveUnmarshalPayloadSuccess(t *testing.T) {
+       _, handler, _, _, e2tInstancesManagerMock := initE2TKeepAliveTest(t)
+
+       jsonRequest := "{\"address\":\"10.10.2.15:9800\"}"
+       notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(jsonRequest)}
+
+       e2tInstancesManagerMock.On("ResetKeepAliveTimestamp", "10.10.2.15:9800").Return(nil)
+       handler.Handle(notificationRequest)
+       e2tInstancesManagerMock.AssertCalled(t, "ResetKeepAliveTimestamp", "10.10.2.15:9800")
+}
index a6a6234..8989af5 100644 (file)
@@ -1,6 +1,21 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
 package rmrmsghandlers
 
-import "C"
 import (
        "e2mgr/converters"
        "e2mgr/e2pdus"
@@ -44,7 +59,7 @@ func (h EnbLoadInformationNotificationHandler) Handle(request *models.Notificati
 
        err = h.extractor.ExtractAndBuildRanLoadInformation(pdu, ranLoadInformation)
 
-       if (err != nil) {
+       if err != nil {
                h.logger.Errorf("#EnbLoadInformationNotificationHandler.Handle - RAN name: %s - Failed at ExtractAndBuildRanLoadInformation. Error: %v", request.RanName, err)
                return
        }
index 9c58274..8c5627a 100644 (file)
@@ -34,7 +34,7 @@ const (
        GarbagePdu   string = "12312312"
 )
 
-func createNotificationRequest(ranName string, transactionId string, packedPdu string) (*models.NotificationRequest, error) {
+func createNotificationRequest(ranName string, transactionId []byte, packedPdu string) (*models.NotificationRequest, error) {
        var packedByteSlice []byte
 
        _, err := fmt.Sscanf(packedPdu, "%x", &packedByteSlice)
@@ -46,7 +46,7 @@ func createNotificationRequest(ranName string, transactionId string, packedPdu s
        return models.NewNotificationRequest(ranName, packedByteSlice, time.Now(), transactionId), nil
 }
 
-func createNotificationRequestAndHandle(ranName string, transactionId string, loadInformationHandler EnbLoadInformationNotificationHandler, pdu string) error {
+func createNotificationRequestAndHandle(ranName string, transactionId []byte, loadInformationHandler EnbLoadInformationNotificationHandler, pdu string) error {
        notificationRequest, err := createNotificationRequest(ranName, transactionId, pdu)
 
        if err != nil {
index bfc4e1b..c460941 100644 (file)
@@ -32,7 +32,7 @@ import (
        "e2mgr/models"
        "e2mgr/rmrCgo"
        "e2mgr/services/rmrsender"
-       "unsafe"
+       "e2mgr/utils"
 )
 
 type EndcConfigurationUpdateHandler struct {
@@ -49,35 +49,22 @@ func NewEndcConfigurationUpdateHandler(logger *logger.Logger, rmrSender *rmrsend
 
 func (h EndcConfigurationUpdateHandler) Handle(request *models.NotificationRequest) {
 
-       var payloadSize C.ulong
-       payloadSize = e2pdus.MaxAsn1PackedBufferSize
-       packedBuffer := [e2pdus.MaxAsn1PackedBufferSize]C.uchar{}
-       errorBuffer := [e2pdus.MaxAsn1PackedBufferSize]C.char{}
        refinedMessage, err := converters.UnpackX2apPduAndRefine(h.logger, e2pdus.MaxAsn1CodecAllocationBufferSize /*allocation buffer*/, request.Len, request.Payload, e2pdus.MaxAsn1CodecMessageBufferSize /*message buffer*/)
+
        if err != nil {
-               status := C.build_pack_endc_configuration_update_failure(&payloadSize, &packedBuffer[0], e2pdus.MaxAsn1PackedBufferSize, &errorBuffer[0])
-               if status {
-                       payload := (*[1 << 30]byte)(unsafe.Pointer(&packedBuffer))[:payloadSize:payloadSize]
-                       h.logger.Debugf("#endc_configuration_update_handler.Handle - Endc configuration update negative ack message payload: (%d) %02x", len(payload), payload)
-                       msg := models.NewRmrMessage(rmrCgo.RIC_ENDC_CONF_UPDATE_FAILURE, request.RanName, payload)
-                       _ = h.rmrSender.Send(msg)
-               } else {
-                       h.logger.Errorf("#endc_configuration_update_handler.Handle - failed to build and pack Endc configuration update unsuccessful outcome message. Error: %v", errorBuffer)
-               }
                h.logger.Errorf("#endc_configuration_update_handler.Handle - unpack failed. Error: %v", err)
-       } else {
-               h.logger.Infof("#endc_configuration_update_handler.Handle - Endc configuration update initiating message received")
-               h.logger.Debugf("#endc_configuration_update_handler.Handle - Endc configuration update initiating message payload: %s", refinedMessage.PduPrint)
-               status := C.build_pack_endc_configuration_update_ack(&payloadSize, &packedBuffer[0], e2pdus.MaxAsn1PackedBufferSize, &errorBuffer[0])
-               if status {
-                       payload := (*[1 << 30]byte)(unsafe.Pointer(&packedBuffer))[:payloadSize:payloadSize]
-                       h.logger.Debugf("#endc_configuration_update_handler.Handle - Endc configuration update positive ack message payload: (%d) %02x", len(payload), payload)
-                       msg := models.NewRmrMessage(rmrCgo.RIC_ENDC_CONF_UPDATE_ACK, request.RanName, payload)
-                       _ = h.rmrSender.Send(msg)
-               } else {
-                       h.logger.Errorf("#endc_configuration_update_handler.Handle - failed to build and pack endc configuration update successful outcome message. Error: %v", errorBuffer)
-               }
+
+               msg := models.NewRmrMessage(rmrCgo.RIC_ENDC_CONF_UPDATE_FAILURE, request.RanName, e2pdus.PackedEndcConfigurationUpdateFailure, request.TransactionId)
+               _ = h.rmrSender.Send(msg)
+
+               h.logger.Infof("#EndcConfigurationUpdateHandler.Handle - Summary: elapsed time for receiving and handling endc configuration update initiating message from E2 terminator: %f ms", utils.ElapsedTime(request.StartTime))
+               return
        }
 
-       printHandlingSetupResponseElapsedTimeInMs(h.logger, "#endc_configuration_update_handler.Handle - Summary: Elapsed time for receiving and handling endc configuration update initiating message from E2 terminator", request.StartTime)
+       h.logger.Infof("#endc_configuration_update_handler.Handle - Endc configuration update initiating message received")
+       h.logger.Debugf("#endc_configuration_update_handler.Handle - Endc configuration update initiating message payload: %s", refinedMessage.PduPrint)
+       msg := models.NewRmrMessage(rmrCgo.RIC_ENDC_CONF_UPDATE_ACK, request.RanName, e2pdus.PackedEndcConfigurationUpdateAck, request.TransactionId)
+       _ = h.rmrSender.Send(msg)
+
+       h.logger.Infof("#EndcConfigurationUpdateHandler.Handle - Summary: elapsed time for receiving and handling endc configuration update initiating message from E2 terminator: %f ms", utils.ElapsedTime(request.StartTime))
 }
index db847ad..1c2afe9 100644 (file)
@@ -43,31 +43,33 @@ func TestHandleEndcConfigUpdateSuccess(t *testing.T) {
        h, rmrMessengerMock := initEndcConfigurationUpdateHandlerTest(t)
 
        ranName := "test"
-       xaction := []byte(ranName)
+       xAction := []byte("123456aa")
 
        var payload []byte
        _, _ = fmt.Sscanf(PackedEndcConfigurationUpdateAck, "%x", &payload)
 
-       mBuf := rmrCgo.NewMBuf(rmrCgo.RIC_ENDC_CONF_UPDATE_ACK, len(payload), ranName, &payload, &xaction)
-       notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: mBuf.Len, Payload: *mBuf.Payload, StartTime: time.Now()}
+       mBuf := rmrCgo.NewMBuf(rmrCgo.RIC_ENDC_CONF_UPDATE_ACK, len(payload), ranName, &payload, &xAction)
+       notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: mBuf.Len, Payload: *mBuf.Payload, StartTime: time.Now(),
+               TransactionId: *mBuf.XAction}
        var err error
-       rmrMessengerMock.On("SendMsg", mBuf).Return(&rmrCgo.MBuf{}, err)
+       rmrMessengerMock.On("SendMsg", mBuf, true).Return(&rmrCgo.MBuf{}, err)
        h.Handle(&notificationRequest)
-       rmrMessengerMock.AssertCalled(t, "SendMsg", mBuf)
+       rmrMessengerMock.AssertCalled(t, "SendMsg", mBuf, true)
 }
 
 func TestHandleEndcConfigUpdateFailure(t *testing.T) {
        h, rmrMessengerMock := initEndcConfigurationUpdateHandlerTest(t)
 
        ranName := "test"
-       xaction := []byte(ranName)
+       xAction := []byte("123456aa")
 
        var payload []byte
        _, _ = fmt.Sscanf(PackedEndcConfigurationUpdateFailure, "%x", &payload)
 
-       mBuf := rmrCgo.NewMBuf(rmrCgo.RIC_ENDC_CONF_UPDATE_FAILURE, len(payload), ranName, &payload, &xaction)
-       notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: 0, Payload: []byte{0}, StartTime: time.Now()}
-       rmrMessengerMock.On("SendMsg", mBuf).Return(&rmrCgo.MBuf{}, fmt.Errorf("send failure"))
+       mBuf := rmrCgo.NewMBuf(rmrCgo.RIC_ENDC_CONF_UPDATE_FAILURE, len(payload), ranName, &payload, &xAction)
+       notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: 0, Payload: []byte{0}, StartTime: time.Now(),
+               TransactionId: *mBuf.XAction}
+       rmrMessengerMock.On("SendMsg", mBuf, true).Return(&rmrCgo.MBuf{}, fmt.Errorf("send failure"))
        h.Handle(&notificationRequest)
-       rmrMessengerMock.AssertCalled(t, "SendMsg", mBuf)
+       rmrMessengerMock.AssertCalled(t, "SendMsg", mBuf, true)
 }
index 6ec0720..4a85de2 100644 (file)
 package rmrmsghandlers
 
 import (
-       "e2mgr/logger"
        "e2mgr/models"
-       "time"
 )
 
 type NotificationHandler interface {
        Handle(*models.NotificationRequest)
 }
-
-//TODO: remove that
-func printHandlingSetupResponseElapsedTimeInMs(logger *logger.Logger, msg string, startTime time.Time) {
-       logger.Infof("%s: %f ms", msg, float64(time.Since(startTime))/float64(time.Millisecond))
-}
index 111b1a4..f4bfd63 100644 (file)
@@ -29,7 +29,6 @@ import (
        "e2mgr/managers"
        "e2mgr/mocks"
        "e2mgr/models"
-       "e2mgr/rNibWriter"
        "e2mgr/rmrCgo"
        "e2mgr/services"
        "e2mgr/services/rmrsender"
@@ -37,7 +36,6 @@ import (
        "fmt"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
-       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
        "github.com/pkg/errors"
        "github.com/stretchr/testify/assert"
        "github.com/stretchr/testify/mock"
@@ -84,13 +82,8 @@ func NewSetupResponseTestContext(manager managers.ISetupResponseManager) *setupR
        config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
        readerMock := &mocks.RnibReaderMock{}
        writerMock := &mocks.RnibWriterMock{}
-       rnibReaderProvider := func() reader.RNibReader {
-               return readerMock
-       }
-       rnibWriterProvider := func() rNibWriter.RNibWriter {
-               return writerMock
-       }
-       rnibDataService := services.NewRnibDataService(logger, config, rnibReaderProvider, rnibWriterProvider)
+
+       rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
 
        rmrMessengerMock := &mocks.RmrMessengerMock{}
        rmrSender := initRmrSender(rmrMessengerMock, logger)
@@ -157,17 +150,17 @@ func executeHandleSetupSuccessResponse(t *testing.T, tc setupSuccessResponseTest
 
        testContext.readerMock.On("GetNodeb", RanName).Return(nodebInfo, rnibErr)
        testContext.writerMock.On("SaveNodeb", mock.Anything, mock.Anything).Return(tc.saveNodebMockError)
-       testContext.rmrMessengerMock.On("SendMsg", tc.statusChangeMbuf).Return(&rmrCgo.MBuf{}, tc.sendMsgError)
+       testContext.rmrMessengerMock.On("SendMsg", tc.statusChangeMbuf, true).Return(&rmrCgo.MBuf{}, tc.sendMsgError)
        handler.Handle(&notificationRequest)
 
        return testContext, nodebInfo
 }
 
 func getRanConnectedMbuf(nodeType entities.Node_Type) *rmrCgo.MBuf {
-       xaction := []byte(RanName)
+       var xAction []byte
        resourceStatusPayload := models.NewResourceStatusPayload(nodeType, enums.RIC_TO_RAN)
        resourceStatusJson, _ := json.Marshal(resourceStatusPayload)
-       return rmrCgo.NewMBuf(rmrCgo.RAN_CONNECTED, len(resourceStatusJson), RanName, &resourceStatusJson, &xaction)
+       return rmrCgo.NewMBuf(rmrCgo.RAN_CONNECTED, len(resourceStatusJson), RanName, &resourceStatusJson, &xAction)
 }
 
 func executeHandleSetupFailureResponse(t *testing.T, tc setupFailureResponseTestCase) (*setupResponseTestContext, *entities.NodebInfo) {
@@ -222,7 +215,7 @@ func TestX2SetupResponse(t *testing.T) {
        assert.IsType(t, &entities.NodebInfo_Enb{}, nodebInfo.Configuration)
        i, _ := nodebInfo.Configuration.(*entities.NodebInfo_Enb)
        assert.NotNil(t, i.Enb)
-       testContext.rmrMessengerMock.AssertCalled(t, "SendMsg", tc.statusChangeMbuf)
+       testContext.rmrMessengerMock.AssertCalled(t, "SendMsg", tc.statusChangeMbuf, true)
 }
 
 func TestX2SetupFailureResponse(t *testing.T) {
@@ -246,11 +239,12 @@ func TestX2SetupFailureResponse(t *testing.T) {
 }
 
 func TestEndcSetupResponse(t *testing.T) {
+       logger := initLog(t)
        var saveNodebMockError error
        var sendMsgError error
        tc := setupSuccessResponseTestCase{
                EndcSetupResponsePackedPdu,
-               &managers.EndcSetupResponseManager{},
+               managers.NewEndcSetupResponseManager(converters.NewEndcSetupResponseConverter(logger)),
                rmrCgo.RIC_ENDC_X2_SETUP_RESP,
                saveNodebMockError,
                sendMsgError,
@@ -267,15 +261,15 @@ func TestEndcSetupResponse(t *testing.T) {
 
        i, _ := nodebInfo.Configuration.(*entities.NodebInfo_Gnb)
        assert.NotNil(t, i.Gnb)
-       testContext.rmrMessengerMock.AssertCalled(t, "SendMsg", tc.statusChangeMbuf)
+       testContext.rmrMessengerMock.AssertCalled(t, "SendMsg", tc.statusChangeMbuf, true)
 }
 
 func TestEndcSetupFailureResponse(t *testing.T) {
-
+       logger := initLog(t)
        var saveNodebMockError error
        tc := setupFailureResponseTestCase{
                EndcSetupFailureResponsePackedPdu,
-               &managers.EndcSetupFailureResponseManager{},
+               managers.NewEndcSetupFailureResponseManager(converters.NewEndcSetupFailureResponseConverter(logger)),
                rmrCgo.RIC_ENDC_X2_SETUP_FAILURE,
                saveNodebMockError,
        }
@@ -346,5 +340,5 @@ func TestSetupResponseStatusChangeSendFailure(t *testing.T) {
        assert.IsType(t, &entities.NodebInfo_Enb{}, nodebInfo.Configuration)
        i, _ := nodebInfo.Configuration.(*entities.NodebInfo_Enb)
        assert.NotNil(t, i.Enb)
-       testContext.rmrMessengerMock.AssertCalled(t, "SendMsg", tc.statusChangeMbuf)
+       testContext.rmrMessengerMock.AssertCalled(t, "SendMsg", tc.statusChangeMbuf, true)
 }
index 53af51e..164984a 100644 (file)
@@ -35,9 +35,7 @@ import (
        "e2mgr/services"
        "e2mgr/services/rmrsender"
        "e2mgr/utils"
-       "fmt"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
-       "unsafe"
 )
 
 type X2ResetRequestNotificationHandler struct {
@@ -81,27 +79,9 @@ func (h X2ResetRequestNotificationHandler) Handle(request *models.NotificationRe
                return
        }
 
-       msg, err := createX2ResetResponseNotification(request)
-       if err != nil {
-               h.logger.Errorf("#X2ResetRequestNotificationHandler.Handle - %s", err)
-               return
-       }
+       msg := models.NewRmrMessage(rmrCgo.RIC_X2_RESET_RESP, request.RanName, e2pdus.PackedX2ResetResponse, request.TransactionId)
 
        _ = h.rmrSender.Send(msg)
        h.logger.Infof("#X2ResetRequestNotificationHandler.Handle - Summary: elapsed time for receiving and handling reset request message from E2 terminator: %f ms", utils.ElapsedTime(request.StartTime))
        _ = h.ranStatusChangeManager.Execute(rmrCgo.RAN_RESTARTED, enums.RAN_TO_RIC, nb)
 }
-
-func createX2ResetResponseNotification(request *models.NotificationRequest) (*models.RmrMessage, error) {
-
-       packedBuffer := make([]C.uchar, e2pdus.MaxAsn1PackedBufferSize)
-       errorBuffer := make([]C.char, e2pdus.MaxAsn1CodecMessageBufferSize)
-       var payloadSize = C.ulong(e2pdus.MaxAsn1PackedBufferSize)
-
-       if status := C.build_pack_x2reset_response(&payloadSize, &packedBuffer[0], C.ulong(e2pdus.MaxAsn1CodecMessageBufferSize), &errorBuffer[0]); !status {
-               return nil, fmt.Errorf("failed to build and pack the reset response message %s ", C.GoString(&errorBuffer[0]))
-       }
-       payload := C.GoBytes(unsafe.Pointer(&packedBuffer[0]), C.int(payloadSize))
-       msg := models.NewRmrMessage(rmrCgo.RIC_X2_RESET_RESP, request.RanName, payload)
-       return msg, nil
-}
index 7a7e95c..6b6f00c 100644 (file)
@@ -33,7 +33,6 @@ import (
        "encoding/json"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
-       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
        "testing"
        "time"
 )
@@ -42,10 +41,8 @@ func initX2ResetRequestNotificationHandlerTest(t *testing.T) (X2ResetRequestNoti
        log := initLog(t)
        config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
        readerMock := &mocks.RnibReaderMock{}
-       readerProvider := func() reader.RNibReader {
-               return readerMock
-       }
-       rnibDataService := services.NewRnibDataService(log, config, readerProvider, nil)
+
+       rnibDataService := services.NewRnibDataService(log, config, readerMock, nil)
 
        rmrMessengerMock := &mocks.RmrMessengerMock{}
        rmrSender := initRmrSender(rmrMessengerMock, log)
@@ -55,38 +52,38 @@ func initX2ResetRequestNotificationHandlerTest(t *testing.T) (X2ResetRequestNoti
 }
 
 func getRanRestartedMbuf(nodeType entities.Node_Type, messageDirection enums.MessageDirection) *rmrCgo.MBuf {
-       xaction := []byte(RanName)
+       var xAction []byte
        resourceStatusPayload := models.NewResourceStatusPayload(nodeType, messageDirection)
        resourceStatusJson, _ := json.Marshal(resourceStatusPayload)
-       return rmrCgo.NewMBuf(rmrCgo.RAN_RESTARTED, len(resourceStatusJson), RanName, &resourceStatusJson, &xaction)
+       return rmrCgo.NewMBuf(rmrCgo.RAN_RESTARTED, len(resourceStatusJson), RanName, &resourceStatusJson, &xAction)
 }
 
 func TestHandleX2ResetRequestNotificationSuccess(t *testing.T) {
        h, readerMock, rmrMessengerMock := initX2ResetRequestNotificationHandlerTest(t)
        ranName := "test"
-       xaction := []byte(ranName)
-       notificationRequest := models.NewNotificationRequest(ranName, []byte{}, time.Now(), ranName)
+       xAction := []byte("123456aa")
+       notificationRequest := models.NewNotificationRequest(ranName, []byte{}, time.Now(), xAction)
 
        nb := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, NodeType: entities.Node_ENB}
        var err error
        readerMock.On("GetNodeb", ranName).Return(nb, err)
-       resetResponseMbuf := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET_RESP, len(e2pdus.PackedX2ResetResponse), ranName, &e2pdus.PackedX2ResetResponse, &xaction)
-       rmrMessengerMock.On("SendMsg", resetResponseMbuf).Return(&rmrCgo.MBuf{}, err)
+       resetResponseMbuf := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET_RESP, len(e2pdus.PackedX2ResetResponse), ranName, &e2pdus.PackedX2ResetResponse, &xAction)
+       rmrMessengerMock.On("SendMsg", resetResponseMbuf, true).Return(&rmrCgo.MBuf{}, err)
        ranRestartedMbuf := getRanRestartedMbuf(nb.NodeType, enums.RAN_TO_RIC)
-       rmrMessengerMock.On("SendMsg", ranRestartedMbuf).Return(&rmrCgo.MBuf{}, err)
+       rmrMessengerMock.On("SendMsg", ranRestartedMbuf, true).Return(&rmrCgo.MBuf{}, err)
        h.Handle(notificationRequest)
-       rmrMessengerMock.AssertCalled(t, "SendMsg", resetResponseMbuf)
-       rmrMessengerMock.AssertCalled(t, "SendMsg", ranRestartedMbuf)
+       rmrMessengerMock.AssertCalled(t, "SendMsg", resetResponseMbuf, true)
+       rmrMessengerMock.AssertCalled(t, "SendMsg", ranRestartedMbuf, true)
 }
 
 func TestHandleX2ResetRequestNotificationShuttingDownStatus(t *testing.T) {
        h, readerMock, rmrMessengerMock := initX2ResetRequestNotificationHandlerTest(t)
        var payload []byte
 
-       xaction := []byte("RanName")
-       mBuf := rmrCgo.NewMBuf(tests.MessageType, len(payload), "RanName", &payload, &xaction)
+       xAction := []byte("123456aa")
+       mBuf := rmrCgo.NewMBuf(tests.MessageType, len(payload), "RanName", &payload, &xAction)
        notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: mBuf.Len, Payload: *mBuf.Payload,
-               StartTime: time.Now(), TransactionId: string(xaction)}
+               StartTime: time.Now(), TransactionId: xAction}
 
        nb := &entities.NodebInfo{RanName: mBuf.Meid, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,}
        var rnibErr error
@@ -100,9 +97,9 @@ func TestHandleX2ResetRequestNotificationShuttingDownStatus(t *testing.T) {
 func TestHandleX2ResetRequestNotificationDisconnectStatus(t *testing.T) {
        h, readerMock, rmrMessengerMock := initX2ResetRequestNotificationHandlerTest(t)
        var payload []byte
-       xaction := []byte("RanName")
-       mBuf := rmrCgo.NewMBuf(tests.MessageType, len(payload), "RanName", &payload, &xaction)
-       notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: mBuf.Len, Payload: *mBuf.Payload, StartTime: time.Now(), TransactionId: string(xaction)}
+       xAction := []byte("123456aa")
+       mBuf := rmrCgo.NewMBuf(tests.MessageType, len(payload), "RanName", &payload, &xAction)
+       notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: mBuf.Len, Payload: *mBuf.Payload, StartTime: time.Now(), TransactionId: xAction}
        nb := &entities.NodebInfo{RanName: mBuf.Meid, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED,}
        var rnibErr error
        readerMock.On("GetNodeb", mBuf.Meid).Return(nb, rnibErr)
@@ -115,10 +112,10 @@ func TestHandleX2ResetRequestNotificationGetNodebFailed(t *testing.T) {
 
         h, readerMock, rmrMessengerMock := initX2ResetRequestNotificationHandlerTest(t)
        var payload []byte
-       xaction := []byte("RanName")
-       mBuf := rmrCgo.NewMBuf(tests.MessageType, len(payload), "RanName", &payload, &xaction)
+       var xAction []byte
+       mBuf := rmrCgo.NewMBuf(tests.MessageType, len(payload), "RanName", &payload, &xAction)
        notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: mBuf.Len, Payload: *mBuf.Payload,
-               StartTime: time.Now(), TransactionId: string(xaction)}
+               StartTime: time.Now(), TransactionId: xAction}
 
        var nb *entities.NodebInfo
        rnibErr := &common.ResourceNotFoundError{}
index 2c26b43..1097ed2 100644 (file)
@@ -56,7 +56,7 @@ func (h X2ResetResponseHandler) Handle(request *models.NotificationRequest) {
        ranName := request.RanName
        h.logger.Infof("#X2ResetResponseHandler.Handle - RAN name: %s - received reset response. Payload: %x", ranName, request.Payload)
 
-       nodebInfo, err := h.rnibDataService.GetNodeb(ranName);
+       nodebInfo, err := h.rnibDataService.GetNodeb(ranName)
        if err != nil {
                h.logger.Errorf("#x2ResetResponseHandler.Handle - RAN name: %s - failed to retrieve nodebInfo entity. Error: %s", ranName, err)
                return
index 2ff6094..7a99903 100644 (file)
@@ -33,7 +33,6 @@ import (
        "fmt"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
-       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
        "testing"
        "time"
 )
@@ -51,11 +50,8 @@ func initX2ResetResponseHandlerTest(t *testing.T) (X2ResetResponseHandler, *mock
                t.Errorf("#initX2ResetResponseHandlerTest - failed to initialize logger, error: %s", err)
        }
        readerMock := &mocks.RnibReaderMock{}
-       rnibReaderProvider := func() reader.RNibReader {
-               return readerMock
-       }
 
-       rnibDataService := services.NewRnibDataService(log, config, rnibReaderProvider, nil)
+       rnibDataService := services.NewRnibDataService(log, config, readerMock, nil)
 
        rmrMessengerMock := &mocks.RmrMessengerMock{}
        rmrSender := initRmrSender(rmrMessengerMock, log)
@@ -73,15 +69,15 @@ func TestX2ResetResponseSuccess(t *testing.T) {
                t.Fatalf("Failed converting packed pdu. Error: %v\n", err)
        }
 
-       xaction := []byte(RanName)
-       notificationRequest := models.NotificationRequest{RanName: RanName, Len: len(payload), Payload: payload, StartTime: time.Now(), TransactionId: string(xaction)}
+       var xAction []byte
+       notificationRequest := models.NotificationRequest{RanName: RanName, Len: len(payload), Payload: payload, StartTime: time.Now(), TransactionId: xAction}
        nb := &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, NodeType: entities.Node_ENB}
        var rnibErr error
        readerMock.On("GetNodeb", RanName).Return(nb, rnibErr)
        ranRestartedMbuf := getRanRestartedMbuf(nb.NodeType, enums.RIC_TO_RAN)
-       rmrMessengerMock.On("SendMsg", ranRestartedMbuf).Return(&rmrCgo.MBuf{}, err)
+       rmrMessengerMock.On("SendMsg", ranRestartedMbuf, true).Return(&rmrCgo.MBuf{}, err)
        h.Handle(&notificationRequest)
-       rmrMessengerMock.AssertCalled(t, "SendMsg", ranRestartedMbuf)
+       rmrMessengerMock.AssertCalled(t, "SendMsg", ranRestartedMbuf, true)
 }
 
 func TestX2ResetResponseSuccessEmptyIEs(t *testing.T) {
@@ -92,15 +88,15 @@ func TestX2ResetResponseSuccessEmptyIEs(t *testing.T) {
                t.Fatalf("Failed converting packed pdu. Error: %v\n", err)
        }
 
-       xaction := []byte(RanName)
-       notificationRequest := models.NotificationRequest{RanName: RanName, Len: len(payload), Payload: payload, StartTime: time.Now(), TransactionId: string(xaction)}
+       var xAction []byte
+       notificationRequest := models.NotificationRequest{RanName: RanName, Len: len(payload), Payload: payload, StartTime: time.Now(), TransactionId: xAction}
        nb := &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, NodeType: entities.Node_ENB}
        var rnibErr error
        readerMock.On("GetNodeb", RanName).Return(nb, rnibErr)
        ranRestartedMbuf := getRanRestartedMbuf(nb.NodeType, enums.RIC_TO_RAN)
-       rmrMessengerMock.On("SendMsg", ranRestartedMbuf).Return(&rmrCgo.MBuf{}, err)
+       rmrMessengerMock.On("SendMsg", ranRestartedMbuf, true).Return(&rmrCgo.MBuf{}, err)
        h.Handle(&notificationRequest)
-       rmrMessengerMock.AssertCalled(t, "SendMsg", ranRestartedMbuf)
+       rmrMessengerMock.AssertCalled(t, "SendMsg", ranRestartedMbuf, true)
 }
 
 func TestX2ResetResponseShuttingDown(t *testing.T) {
@@ -111,8 +107,8 @@ func TestX2ResetResponseShuttingDown(t *testing.T) {
                t.Fatalf("Failed converting packed pdu. Error: %v\n", err)
        }
 
-       xaction := []byte(RanName)
-       notificationRequest := models.NotificationRequest{RanName: RanName, Len: len(payload), Payload: payload, StartTime: time.Now(), TransactionId: string(xaction)}
+       var xAction []byte
+       notificationRequest := models.NotificationRequest{RanName: RanName, Len: len(payload), Payload: payload, StartTime: time.Now(), TransactionId: xAction}
        nb := &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN, NodeType: entities.Node_ENB}
        var rnibErr error
        readerMock.On("GetNodeb", RanName).Return(nb, rnibErr)
@@ -128,8 +124,8 @@ func TestX2ResetResponseInvalidConnectionStatus(t *testing.T) {
                t.Fatalf("Failed converting packed pdu. Error: %v\n", err)
        }
 
-       xaction := []byte(RanName)
-       notificationRequest := models.NotificationRequest{RanName: RanName, Len: len(payload), Payload: payload, StartTime: time.Now(), TransactionId: string(xaction)}
+       var xAction []byte
+       notificationRequest := models.NotificationRequest{RanName: RanName, Len: len(payload), Payload: payload, StartTime: time.Now(), TransactionId: xAction}
        nb := &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, NodeType: entities.Node_ENB}
        var rnibErr error
        readerMock.On("GetNodeb", RanName).Return(nb, rnibErr)
@@ -145,8 +141,8 @@ func TestX2ResetResponseError(t *testing.T) {
                t.Fatalf("Failed converting packed pdu. Error: %v\n", err)
        }
 
-       xaction := []byte(RanName)
-       notificationRequest := models.NotificationRequest{RanName: RanName, Len: len(payload), Payload: payload, StartTime: time.Now(), TransactionId: string(xaction)}
+       var xAction []byte
+       notificationRequest := models.NotificationRequest{RanName: RanName, Len: len(payload), Payload: payload, StartTime: time.Now(), TransactionId: xAction}
        nb := &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, NodeType: entities.Node_ENB}
        var rnibErr error
        readerMock.On("GetNodeb", RanName).Return(nb, rnibErr)
@@ -163,8 +159,8 @@ func TestX2ResetResponseGetNodebFailure(t *testing.T) {
                t.Fatalf("Failed converting packed pdu. Error: %v\n", err)
        }
 
-       xaction := []byte(RanName)
-       notificationRequest := models.NotificationRequest{RanName: RanName, Len: len(payload), Payload: payload, StartTime: time.Now(), TransactionId: string(xaction)}
+       var xAction []byte
+       notificationRequest := models.NotificationRequest{RanName: RanName, Len: len(payload), Payload: payload, StartTime: time.Now(), TransactionId: xAction}
 
        var nb *entities.NodebInfo
        rnibErr := common.NewResourceNotFoundError("nodeb not found")
@@ -178,8 +174,8 @@ func TestX2ResetResponseUnpackFailure(t *testing.T) {
        h, readerMock, rmrMessengerMock := initX2ResetResponseHandlerTest(t)
 
        payload := []byte("Invalid payload")
-       xaction := []byte(RanName)
-       notificationRequest := models.NotificationRequest{RanName: RanName, Len: len(payload), Payload: payload, StartTime: time.Now(), TransactionId: string(xaction)}
+       var xAction []byte
+       notificationRequest := models.NotificationRequest{RanName: RanName, Len: len(payload), Payload: payload, StartTime: time.Now(), TransactionId: xAction}
        nb := &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, NodeType: entities.Node_ENB}
        var rnibErr error
        readerMock.On("GetNodeb", RanName).Return(nb, rnibErr)
index d33f784..591acff 100644 (file)
@@ -32,7 +32,7 @@ import (
        "e2mgr/models"
        "e2mgr/rmrCgo"
        "e2mgr/services/rmrsender"
-       "unsafe"
+       "e2mgr/utils"
 )
 
 type X2EnbConfigurationUpdateHandler struct {
@@ -49,40 +49,23 @@ func NewX2EnbConfigurationUpdateHandler(logger *logger.Logger, rmrSender *rmrsen
 
 func (h X2EnbConfigurationUpdateHandler) Handle(request *models.NotificationRequest) {
 
-       var payloadSize C.ulong
-       payloadSize = e2pdus.MaxAsn1PackedBufferSize
-       packedBuffer := [e2pdus.MaxAsn1PackedBufferSize]C.uchar{}
-       errorBuffer := [e2pdus.MaxAsn1PackedBufferSize]C.char{}
-
        refinedMessage, err := converters.UnpackX2apPduAndRefine(h.logger, e2pdus.MaxAsn1CodecAllocationBufferSize, request.Len, request.Payload, e2pdus.MaxAsn1CodecMessageBufferSize)
 
        if err != nil {
-               status := C.build_pack_x2enb_configuration_update_failure(&payloadSize, &packedBuffer[0], e2pdus.MaxAsn1PackedBufferSize, &errorBuffer[0])
-               if status {
-                       payload := (*[1 << 30]byte)(unsafe.Pointer(&packedBuffer))[:payloadSize:payloadSize]
-                       h.logger.Debugf("#x2enb_configuration_update_handler.Handle - Enb configuration update negative ack message payload: (%d) %02x", len(payload), payload)
-                       msg := models.NewRmrMessage(rmrCgo.RIC_ENB_CONFIGURATION_UPDATE_FAILURE, request.RanName, payload)
-                       _ = h.rmrSender.Send(msg)
-               } else {
-                       h.logger.Errorf("#x2enb_configuration_update_handler.Handle - failed to build and pack Enb configuration update unsuccessful outcome message. Error: %v", errorBuffer)
-               }
                h.logger.Errorf("#x2enb_configuration_update_handler.Handle - unpack failed. Error: %v", err)
 
-               printHandlingSetupResponseElapsedTimeInMs(h.logger, "#x2enb_configuration_update_handler.Handle - Summary: Elapsed time for receiving and handling enb configuration update initiating message from E2 terminator", request.StartTime)
+               msg := models.NewRmrMessage(rmrCgo.RIC_ENB_CONFIGURATION_UPDATE_FAILURE, request.RanName, e2pdus.PackedX2EnbConfigurationUpdateFailure, request.TransactionId)
+               _ = h.rmrSender.Send(msg)
+
+               h.logger.Infof("#X2EnbConfigurationUpdateHandler.Handle - Summary: elapsed time for receiving and handling enb configuration update initiating message from E2 terminator: %f ms", utils.ElapsedTime(request.StartTime))
                return
        }
 
        h.logger.Infof("#x2enb_configuration_update_handler.Handle - Enb configuration update initiating message received")
        h.logger.Debugf("#x2enb_configuration_update_handler.Handle - Enb configuration update initiating message payload: %s", refinedMessage.PduPrint)
 
-       status := C.build_pack_x2enb_configuration_update_ack(&payloadSize, &packedBuffer[0], e2pdus.MaxAsn1PackedBufferSize, &errorBuffer[0])
-       if status {
-               payload := (*[1 << 30]byte)(unsafe.Pointer(&packedBuffer))[:payloadSize:payloadSize]
-               h.logger.Debugf("#x2enb_configuration_update_handler.Handle - Enb configuration update positive ack message payload: (%d) %02x", len(payload), payload)
-               msg := models.NewRmrMessage(rmrCgo.RIC_ENB_CONFIGURATION_UPDATE_ACK, request.RanName, payload)
-               _ = h.rmrSender.Send(msg)
-       } else {
-               h.logger.Errorf("#x2enb_configuration_update_handler.Handle - failed to build and pack enb configuration update successful outcome message. Error: %v", errorBuffer)
-       }
-       printHandlingSetupResponseElapsedTimeInMs(h.logger, "#x2enb_configuration_update_handler.Handle - Summary: Elapsed time for receiving and handling enb configuration update initiating message from E2 terminator", request.StartTime)
+       msg := models.NewRmrMessage(rmrCgo.RIC_ENB_CONFIGURATION_UPDATE_ACK, request.RanName, e2pdus.PackedX2EnbConfigurationUpdateAck,request.TransactionId)
+       _ = h.rmrSender.Send(msg)
+
+       h.logger.Infof("#X2EnbConfigurationUpdateHandler.Handle - Summary: elapsed time for receiving and handling enb configuration update initiating message from E2 terminator: %f ms", utils.ElapsedTime(request.StartTime))
 }
index 60a3a96..c29d21b 100644 (file)
@@ -43,31 +43,32 @@ func TestHandleX2EnbConfigUpdateSuccess(t *testing.T) {
        h, rmrMessengerMock := initX2EnbConfigurationUpdateHandlerTest(t)
 
        ranName := "test"
-       xaction := []byte(ranName)
-
+       xAction := []byte("123456aa")
        var payload []byte
        _, _ = fmt.Sscanf(PackedX2EnbConfigurationUpdateAck, "%x", &payload)
 
-       mBuf := rmrCgo.NewMBuf(rmrCgo.RIC_ENB_CONFIGURATION_UPDATE_ACK, len(payload), ranName, &payload, &xaction)
-       notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: mBuf.Len, Payload: *mBuf.Payload, StartTime: time.Now()}
+       mBuf := rmrCgo.NewMBuf(rmrCgo.RIC_ENB_CONFIGURATION_UPDATE_ACK, len(payload), ranName, &payload, &xAction)
+       notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: mBuf.Len, Payload: *mBuf.Payload,
+               StartTime: time.Now(), TransactionId:xAction}
        var err error
-       rmrMessengerMock.On("SendMsg", mBuf).Return(&rmrCgo.MBuf{}, err)
+       rmrMessengerMock.On("SendMsg", mBuf, true).Return(&rmrCgo.MBuf{}, err)
        h.Handle(&notificationRequest)
-       rmrMessengerMock.AssertCalled(t, "SendMsg", mBuf)
+       rmrMessengerMock.AssertCalled(t, "SendMsg", mBuf, true)
 }
 
 func TestHandleX2EnbConfigUpdateFailure(t *testing.T) {
        h, rmrMessengerMock := initX2EnbConfigurationUpdateHandlerTest(t)
 
        ranName := "test"
-       xaction := []byte(ranName)
+       xAction := []byte("123456aa")
 
        var payload []byte
        _, _ = fmt.Sscanf(PackedX2EnbConfigurationUpdateFailure, "%x", &payload)
 
-       mBuf := rmrCgo.NewMBuf(rmrCgo.RIC_ENB_CONFIGURATION_UPDATE_FAILURE, len(payload), ranName, &payload, &xaction)
-       notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: 0, Payload: []byte{0}, StartTime: time.Now()}
-       rmrMessengerMock.On("SendMsg", mBuf).Return(&rmrCgo.MBuf{}, fmt.Errorf("send failure"))
+       mBuf := rmrCgo.NewMBuf(rmrCgo.RIC_ENB_CONFIGURATION_UPDATE_FAILURE, len(payload), ranName, &payload, &xAction)
+       notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: 0, Payload: []byte{0},
+               StartTime: time.Now(), TransactionId:xAction}
+       rmrMessengerMock.On("SendMsg", mBuf, true).Return(&rmrCgo.MBuf{}, fmt.Errorf("send failure"))
        h.Handle(&notificationRequest)
-       rmrMessengerMock.AssertCalled(t, "SendMsg", mBuf)
+       rmrMessengerMock.AssertCalled(t, "SendMsg", mBuf, true)
 }
index 1c087bd..608110f 100644 (file)
@@ -22,27 +22,26 @@ package httpserver
 
 import (
        "e2mgr/controllers"
+       "e2mgr/logger"
        "fmt"
        "github.com/gorilla/mux"
-       "log"
        "net/http"
 )
 
-func Run(port int, controller controllers.IRootController, newController controllers.INodebController) {
+func Run(log *logger.Logger, port int, rootController controllers.IRootController, nodebController controllers.INodebController, e2tController controllers.IE2TController) error {
 
        router := mux.NewRouter();
-       initializeRoutes(router, controller, newController)
+       initializeRoutes(router, rootController, nodebController, e2tController)
 
        addr := fmt.Sprintf(":%d", port)
 
        err := http.ListenAndServe(addr, router)
 
-       if err != nil {
-               log.Fatalf("#http_server.Run - Fail initiating HTTP server. Error: %v", err)
-       }
+       log.Errorf("#http_server.Run - Fail initiating HTTP server. Error: %v", err)
+       return err
 }
 
-func initializeRoutes(router *mux.Router, rootController controllers.IRootController, nodebController controllers.INodebController) {
+func initializeRoutes(router *mux.Router, rootController controllers.IRootController, nodebController controllers.INodebController, e2tController controllers.IE2TController) {
        r := router.PathPrefix("/v1").Subrouter()
        r.HandleFunc("/health", rootController.HandleHealthCheckRequest).Methods("GET")
 
@@ -53,4 +52,7 @@ func initializeRoutes(router *mux.Router, rootController controllers.IRootContro
        rr.HandleFunc("/{ranName}/reset", nodebController.X2Reset).Methods("PUT")
        rr.HandleFunc("/x2-setup", nodebController.X2Setup).Methods("POST")
        rr.HandleFunc("/endc-setup", nodebController.EndcSetup).Methods("POST")
+
+       rrr := r.PathPrefix("/e2t").Subrouter()
+       rrr.HandleFunc("/list", e2tController.GetE2TInstances).Methods("GET")
 }
index c841681..e6e1ef5 100644 (file)
 package httpserver
 
 import (
+       "e2mgr/logger"
        "e2mgr/mocks"
        "github.com/gorilla/mux"
        "github.com/stretchr/testify/assert"
        "net/http"
        "net/http/httptest"
        "testing"
+       "time"
 )
 
-func setupRouterAndMocks() (*mux.Router, *mocks.ControllerMock, *mocks.NodebControllerMock) {
-       controllerMock := &mocks.ControllerMock{}
-       controllerMock.On("Shutdown").Return(nil)
-       controllerMock.On("X2Reset").Return(nil)
-       controllerMock.On("X2Setup").Return(nil)
-       controllerMock.On("EndcSetup").Return(nil)
-       controllerMock.On("GetNodeb").Return(nil)
-       controllerMock.On("GetNodebIdList").Return(nil)
-
-
+func setupRouterAndMocks() (*mux.Router, *mocks.RootControllerMock, *mocks.NodebControllerMock, *mocks.E2TControllerMock) {
+       rootControllerMock := &mocks.RootControllerMock{}
+       rootControllerMock.On("HandleHealthCheckRequest").Return(nil)
 
        nodebControllerMock := &mocks.NodebControllerMock{}
+       nodebControllerMock.On("Shutdown").Return(nil)
+       nodebControllerMock.On("X2Reset").Return(nil)
+       nodebControllerMock.On("X2Setup").Return(nil)
+       nodebControllerMock.On("EndcSetup").Return(nil)
+       nodebControllerMock.On("GetNodeb").Return(nil)
        nodebControllerMock.On("GetNodebIdList").Return(nil)
-       nodebControllerMock.On("GetNodeb").Return(nil) // TODO: remove
-       nodebControllerMock.On("HandleHealthCheckRequest").Return(nil)
+
+       e2tControllerMock := &mocks.E2TControllerMock{}
+
+       e2tControllerMock.On("GetE2TInstances").Return(nil)
 
        router := mux.NewRouter()
-       initializeRoutes(router, nodebControllerMock, controllerMock)
-       return router, controllerMock, nodebControllerMock
+       initializeRoutes(router, rootControllerMock, nodebControllerMock, e2tControllerMock)
+       return router, rootControllerMock, nodebControllerMock, e2tControllerMock
 }
 
 func TestRoutePostEndcSetup(t *testing.T) {
-       router, controllerMock, _ := setupRouterAndMocks()
+       router, _, nodebControllerMock, _ := setupRouterAndMocks()
 
        req, err := http.NewRequest("POST", "/v1/nodeb/endc-setup", nil)
        if err != nil {
@@ -60,11 +62,11 @@ func TestRoutePostEndcSetup(t *testing.T) {
        rr := httptest.NewRecorder()
        router.ServeHTTP(rr, req)
 
-       controllerMock.AssertNumberOfCalls(t,"EndcSetup", 1)
+       nodebControllerMock.AssertNumberOfCalls(t, "EndcSetup", 1)
 }
 
 func TestRoutePostX2Setup(t *testing.T) {
-       router, controllerMock, _ := setupRouterAndMocks()
+       router, _, nodebControllerMock, _ := setupRouterAndMocks()
 
        req, err := http.NewRequest("POST", "/v1/nodeb/x2-setup", nil)
        if err != nil {
@@ -73,11 +75,11 @@ func TestRoutePostX2Setup(t *testing.T) {
        rr := httptest.NewRecorder()
        router.ServeHTTP(rr, req)
 
-       controllerMock.AssertNumberOfCalls(t,"X2Setup", 1)
+       nodebControllerMock.AssertNumberOfCalls(t, "X2Setup", 1)
 }
 
 func TestRouteGetNodebIds(t *testing.T) {
-       router, controllerMock, _ := setupRouterAndMocks()
+       router, _, nodebControllerMock, _ := setupRouterAndMocks()
 
        req, err := http.NewRequest("GET", "/v1/nodeb/ids", nil)
        if err != nil {
@@ -86,11 +88,11 @@ func TestRouteGetNodebIds(t *testing.T) {
        rr := httptest.NewRecorder()
        router.ServeHTTP(rr, req)
 
-       controllerMock.AssertNumberOfCalls(t, "GetNodebIdList", 1)
+       nodebControllerMock.AssertNumberOfCalls(t, "GetNodebIdList", 1)
 }
 
 func TestRouteGetNodebRanName(t *testing.T) {
-       router, controllerMock,_ := setupRouterAndMocks()
+       router, _, nodebControllerMock, _ := setupRouterAndMocks()
 
        req, err := http.NewRequest("GET", "/v1/nodeb/ran1", nil)
        if err != nil {
@@ -101,11 +103,11 @@ func TestRouteGetNodebRanName(t *testing.T) {
 
        assert.Equal(t, http.StatusOK, rr.Code, "handler returned wrong status code")
        assert.Equal(t, "ran1", rr.Body.String(), "handler returned wrong body")
-       controllerMock.AssertNumberOfCalls(t, "GetNodeb", 1)
+       nodebControllerMock.AssertNumberOfCalls(t, "GetNodeb", 1)
 }
 
 func TestRouteGetHealth(t *testing.T) {
-       router, _, nodebControllerMock := setupRouterAndMocks()
+       router, rootControllerMock, _, _ := setupRouterAndMocks()
 
        req, err := http.NewRequest("GET", "/v1/health", nil)
        if err != nil {
@@ -114,11 +116,11 @@ func TestRouteGetHealth(t *testing.T) {
        rr := httptest.NewRecorder()
        router.ServeHTTP(rr, req)
 
-       nodebControllerMock.AssertNumberOfCalls(t, "HandleHealthCheckRequest", 1)
+       rootControllerMock.AssertNumberOfCalls(t, "HandleHealthCheckRequest", 1)
 }
 
 func TestRoutePutNodebShutdown(t *testing.T) {
-       router, controllerMock, _ := setupRouterAndMocks()
+       router, _, nodebControllerMock, _ := setupRouterAndMocks()
 
        req, err := http.NewRequest("PUT", "/v1/nodeb/shutdown", nil)
        if err != nil {
@@ -127,11 +129,11 @@ func TestRoutePutNodebShutdown(t *testing.T) {
        rr := httptest.NewRecorder()
        router.ServeHTTP(rr, req)
 
-       controllerMock.AssertNumberOfCalls(t, "Shutdown", 1)
+       nodebControllerMock.AssertNumberOfCalls(t, "Shutdown", 1)
 }
 
 func TestRoutePutNodebResetRanName(t *testing.T) {
-       router, controllerMock, _ := setupRouterAndMocks()
+       router, _, nodebControllerMock, _ := setupRouterAndMocks()
 
        req, err := http.NewRequest("PUT", "/v1/nodeb/ran1/reset", nil)
        if err != nil {
@@ -142,11 +144,11 @@ func TestRoutePutNodebResetRanName(t *testing.T) {
 
        assert.Equal(t, http.StatusOK, rr.Code, "handler returned wrong status code")
        assert.Equal(t, "ran1", rr.Body.String(), "handler returned wrong body")
-       controllerMock.AssertNumberOfCalls(t, "X2Reset", 1)
+       nodebControllerMock.AssertNumberOfCalls(t, "X2Reset", 1)
 }
 
 func TestRouteNotFound(t *testing.T) {
-       router, _, _ := setupRouterAndMocks()
+       router, _, _,_ := setupRouterAndMocks()
 
        req, err := http.NewRequest("GET", "/v1/no/such/route", nil)
        if err != nil {
@@ -156,4 +158,31 @@ func TestRouteNotFound(t *testing.T) {
        router.ServeHTTP(rr, req)
 
        assert.Equal(t, http.StatusNotFound, rr.Code, "handler returned wrong status code")
-}
\ No newline at end of file
+}
+
+func TestRunError(t *testing.T) {
+       log := initLog(t)
+       err := Run(log, 1234567, &mocks.RootControllerMock{}, &mocks.NodebControllerMock{}, &mocks.E2TControllerMock{})
+       assert.NotNil(t, err)
+}
+
+func TestRun(t *testing.T) {
+       log := initLog(t)
+       _, rootControllerMock, nodebControllerMock, e2tControllerMock := setupRouterAndMocks()
+       go Run(log, 11223, rootControllerMock, nodebControllerMock, e2tControllerMock)
+
+       time.Sleep(time.Millisecond * 100)
+       resp, err := http.Get("http://localhost:11223/v1/health")
+       if err != nil {
+               t.Fatalf("failed to perform GET to http://localhost:11223/v1/health")
+       }
+       assert.Equal(t, 200, resp.StatusCode)
+}
+
+func initLog(t *testing.T) *logger.Logger {
+       log, err := logger.InitLogger(logger.InfoLevel)
+       if err != nil {
+               t.Errorf("#initLog test - failed to initialize logger, error: %s", err)
+       }
+       return log
+}
index 9921ce1..d1d00d2 100644 (file)
@@ -44,6 +44,34 @@ func TestInitInfoLoggerSuccess(t *testing.T) {
        assert.True(t, log.Logger.Core().Enabled(zap.InfoLevel))
 }
 
+func TestInitWarnLoggerSuccess(t *testing.T) {
+       log, err := InitLogger(WarnLevel)
+       assert.Nil(t, err)
+       assert.NotNil(t, log)
+       assert.True(t, log.Logger.Core().Enabled(zap.WarnLevel))
+}
+
+func TestInitErrorLoggerSuccess(t *testing.T) {
+       log, err := InitLogger(ErrorLevel)
+       assert.Nil(t, err)
+       assert.NotNil(t, log)
+       assert.True(t, log.Logger.Core().Enabled(zap.ErrorLevel))
+}
+
+func TestInitDPanicLoggerSuccess(t *testing.T) {
+       log, err := InitLogger(DPanicLevel)
+       assert.Nil(t, err)
+       assert.NotNil(t, log)
+       assert.True(t, log.Logger.Core().Enabled(zap.DPanicLevel))
+}
+
+func TestInitPanicLoggerSuccess(t *testing.T) {
+       log, err := InitLogger(PanicLevel)
+       assert.Nil(t, err)
+       assert.NotNil(t, log)
+       assert.True(t, log.Logger.Core().Enabled(zap.PanicLevel))
+}
+
 func TestInitInfoLoggerFailure(t *testing.T) {
        log, err := InitLogger(99)
        assert.NotNil(t, err)
@@ -63,7 +91,7 @@ func TestSyncSuccess(t *testing.T){
        }
        err = log.Sync()
        assert.Nil(t, err)
-       
+
        os.Stdout = old
        logFile, err = os.Open("./loggerTest.txt")
        if err != nil{
@@ -144,6 +172,22 @@ func TestDebugfFatalLevel(t *testing.T)  {
        assert.False(t,validateRecordExists(FatalLevel, zap.DebugLevel, t))
 }
 
+func TestWarnfWarnLevel(t *testing.T)  {
+       assert.True(t,validateRecordExists(WarnLevel, zap.WarnLevel, t))
+}
+
+func TestWarnfDebugLevel(t *testing.T)  {
+       assert.True(t,validateRecordExists(DebugLevel, zap.WarnLevel, t))
+}
+
+func TestWarnfInfoLevel(t *testing.T)  {
+       assert.True(t,validateRecordExists(InfoLevel, zap.WarnLevel, t))
+}
+
+func TestWarnfFatalLevel(t *testing.T)  {
+       assert.False(t,validateRecordExists(FatalLevel, zap.WarnLevel, t))
+}
+
 func TestLogLevelTokenToLevel(t *testing.T) {
        level, ok := LogLevelTokenToLevel("deBug")
        assert.True(t, ok)
@@ -218,14 +262,16 @@ func validateRecordExists(logLevel LogLevel, recordLevel zapcore.Level, t *testi
                t.Errorf("logger_test.TestSyncFailure - failed to initialize logger, error: %s", err)
        }
        switch recordLevel{
-               case  zap.DebugLevel:
-                       log.Debugf("%v, %v, %v", 1, "abc", 0.1)
-               case zap.InfoLevel:
-                       log.Infof("%v, %v, %v", 1, "abc", 0.1)
-               case zap.ErrorLevel:
-                       log.Errorf("%v, %v, %v", 1, "abc", 0.1)
-               case zap.DPanicLevel:
-                       log.DPanicf("%v, %v, %v", 1, "abc", 0.1)
+       case  zap.DebugLevel:
+               log.Debugf("%v, %v, %v", 1, "abc", 0.1)
+       case zap.InfoLevel:
+               log.Infof("%v, %v, %v", 1, "abc", 0.1)
+       case zap.WarnLevel:
+               log.Warnf("%v, %v, %v", 1, "abc", 0.1)
+       case zap.ErrorLevel:
+               log.Errorf("%v, %v, %v", 1, "abc", 0.1)
+       case zap.DPanicLevel:
+               log.DPanicf("%v, %v, %v", 1, "abc", 0.1)
        }
        err = w.Close()
        if err != nil {
@@ -244,4 +290,4 @@ func validateRecordExists(logLevel LogLevel, recordLevel zapcore.Level, t *testi
                s,_= buf.ReadString('\n')
        }
        return entryNum == 1
-}
+}
\ No newline at end of file
diff --git a/E2Manager/managers/e2t_instances_manager.go b/E2Manager/managers/e2t_instances_manager.go
new file mode 100644 (file)
index 0000000..74f6a51
--- /dev/null
@@ -0,0 +1,359 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package managers
+
+import (
+       "e2mgr/e2managererrors"
+       "e2mgr/logger"
+       "e2mgr/services"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+       "math"
+       "sync"
+       "time"
+)
+
+type E2TInstancesManager struct {
+       rnibDataService services.RNibDataService
+       logger          *logger.Logger
+       mux             sync.Mutex
+}
+
+type IE2TInstancesManager interface {
+       GetE2TInstance(e2tAddress string) (*entities.E2TInstance, error)
+       GetE2TInstances() ([]*entities.E2TInstance, error)
+       GetE2TInstancesNoLogs() ([]*entities.E2TInstance, error)
+       AddE2TInstance(e2tAddress string) error
+       RemoveE2TInstance(e2tInstance *entities.E2TInstance) error
+       SelectE2TInstance() (string, error)
+       AssociateRan(ranName string, e2tAddress string) error
+       DissociateRan(ranName string, e2tAddress string) error
+       ActivateE2TInstance(e2tInstance *entities.E2TInstance) error
+       ResetKeepAliveTimestamp(e2tAddress string) error
+}
+
+func NewE2TInstancesManager(rnibDataService services.RNibDataService, logger *logger.Logger) *E2TInstancesManager {
+       return &E2TInstancesManager{
+               rnibDataService: rnibDataService,
+               logger:          logger,
+       }
+}
+
+func (m *E2TInstancesManager) GetE2TInstance(e2tAddress string) (*entities.E2TInstance, error) {
+       e2tInstance, err := m.rnibDataService.GetE2TInstance(e2tAddress)
+
+       if err != nil {
+
+               _, ok := err.(*common.ResourceNotFoundError)
+
+               if !ok {
+                       m.logger.Errorf("#E2TInstancesManager.GetE2TInstance - E2T Instance address: %s - Failed retrieving E2TInstance. error: %s", e2tAddress, err)
+               } else {
+                       m.logger.Infof("#E2TInstancesManager.GetE2TInstance - E2T Instance address: %s not found on DB", e2tAddress)
+               }
+       }
+
+       return e2tInstance, err
+}
+
+func (m *E2TInstancesManager) GetE2TInstancesNoLogs() ([]*entities.E2TInstance, error) {
+       e2tAddresses, err := m.rnibDataService.GetE2TAddressesNoLogs()
+
+       if err != nil {
+               _, ok := err.(*common.ResourceNotFoundError)
+
+               if !ok {
+                       m.logger.Errorf("#E2TInstancesManager.GetE2TInstancesNoLogs - Failed retrieving E2T addresses. error: %s", err)
+                       return nil, e2managererrors.NewRnibDbError()
+               }
+
+               return []*entities.E2TInstance{}, nil
+       }
+
+       if len(e2tAddresses) == 0 {
+               return []*entities.E2TInstance{}, nil
+       }
+
+       e2tInstances, err := m.rnibDataService.GetE2TInstancesNoLogs(e2tAddresses)
+
+       if err != nil {
+               _, ok := err.(*common.ResourceNotFoundError)
+
+               if !ok {
+                       m.logger.Errorf("#E2TInstancesManager.GetE2TInstancesNoLogs - Failed retrieving E2T instances list. error: %s", err)
+               }
+               return e2tInstances, err
+       }
+
+       return e2tInstances, nil
+}
+
+func (m *E2TInstancesManager) GetE2TInstances() ([]*entities.E2TInstance, error) {
+       e2tAddresses, err := m.rnibDataService.GetE2TAddresses()
+
+       if err != nil {
+
+               _, ok := err.(*common.ResourceNotFoundError)
+
+               if !ok {
+                       m.logger.Errorf("#E2TInstancesManager.GetE2TInstances - Failed retrieving E2T addresses. error: %s", err)
+                       return nil, e2managererrors.NewRnibDbError()
+               }
+
+               m.logger.Infof("#E2TInstancesManager.GetE2TInstances - Empty E2T addresses list")
+               return []*entities.E2TInstance{}, nil
+       }
+
+       if len(e2tAddresses) == 0 {
+               m.logger.Infof("#E2TInstancesManager.GetE2TInstances - Empty E2T addresses list")
+               return []*entities.E2TInstance{}, nil
+       }
+
+       e2tInstances, err := m.rnibDataService.GetE2TInstances(e2tAddresses)
+
+       if err != nil {
+               m.logger.Errorf("#E2TInstancesManager.GetE2TInstances - Failed retrieving E2T instances list. error: %s", err)
+               return e2tInstances, e2managererrors.NewRnibDbError()
+       }
+
+       if len(e2tInstances) == 0 {
+               m.logger.Warnf("#E2TInstancesManager.GetE2TInstances - Empty E2T instances list")
+               return e2tInstances, nil
+       }
+
+       return e2tInstances, nil
+}
+
+func (m *E2TInstancesManager) ResetKeepAliveTimestampsForAllE2TInstances() {
+
+       e2tInstances, err := m.GetE2TInstances()
+
+       if err != nil {
+               m.logger.Errorf("E2TInstancesManager.ResetKeepAliveTimestampForAllE2TInstances - Couldn't reset timestamps due to a DB error")
+               return
+       }
+
+       if len(e2tInstances) == 0 {
+               m.logger.Infof("E2TInstancesManager.ResetKeepAliveTimestampForAllE2TInstances - No instances, ignoring reset")
+               return
+       }
+
+       for _, v := range e2tInstances {
+
+               if v.State != entities.Active {
+                       continue
+               }
+
+               v.KeepAliveTimestamp = time.Now().UnixNano()
+
+               err := m.rnibDataService.SaveE2TInstance(v)
+
+               if err != nil {
+                       m.logger.Errorf("E2TInstancesManager.ResetKeepAliveTimestampForAllE2TInstances - E2T address: %s - failed resetting e2t instance keep alive timestamp. error: %s", v.Address, err)
+               }
+       }
+
+       m.logger.Infof("E2TInstancesManager.ResetKeepAliveTimestampForAllE2TInstances - Done with reset")
+}
+
+func findActiveE2TInstanceWithMinimumAssociatedRans(e2tInstances []*entities.E2TInstance) *entities.E2TInstance {
+       var minInstance *entities.E2TInstance
+       minAssociatedRanCount := math.MaxInt32
+
+       for _, v := range e2tInstances {
+               if v.State == entities.Active && len(v.AssociatedRanList) < minAssociatedRanCount {
+                       minAssociatedRanCount = len(v.AssociatedRanList)
+                       minInstance = v
+               }
+       }
+
+       return minInstance
+}
+
+func (m *E2TInstancesManager) AddE2TInstance(e2tAddress string) error {
+
+       m.mux.Lock()
+       defer m.mux.Unlock()
+
+       e2tInstance := entities.NewE2TInstance(e2tAddress)
+       err := m.rnibDataService.SaveE2TInstance(e2tInstance)
+
+       if err != nil {
+               m.logger.Errorf("#E2TInstancesManager.AddE2TInstance - E2T Instance address: %s - Failed saving E2T instance. error: %s", e2tInstance.Address, err)
+               return err
+       }
+
+       e2tAddresses, err := m.rnibDataService.GetE2TAddresses()
+
+       if err != nil {
+
+               _, ok := err.(*common.ResourceNotFoundError)
+
+               if !ok {
+                       m.logger.Errorf("#E2TInstancesManager.AddE2TInstance - E2T Instance address: %s - Failed retrieving E2T addresses list. error: %s", e2tInstance.Address, err)
+                       return err
+               }
+       }
+
+       e2tAddresses = append(e2tAddresses, e2tInstance.Address)
+
+       err = m.rnibDataService.SaveE2TAddresses(e2tAddresses)
+
+       if err != nil {
+               m.logger.Errorf("#E2TInstancesManager.AddE2TInstance - E2T Instance address: %s - Failed saving E2T addresses list. error: %s", e2tInstance.Address, err)
+               return err
+       }
+
+       m.logger.Infof("#E2TInstancesManager.AddE2TInstance - E2T Instance address: %s - successfully added E2T instance", e2tInstance.Address)
+       return nil
+}
+
+func (m *E2TInstancesManager) DissociateRan(ranName string, e2tAddress string) error {
+
+       m.mux.Lock()
+       defer m.mux.Unlock()
+
+       e2tInstance, err := m.rnibDataService.GetE2TInstance(e2tAddress)
+
+       if err != nil {
+               m.logger.Errorf("#E2TInstancesManager.DissociateRan - E2T Instance address: %s - Failed retrieving E2TInstance. error: %s", e2tAddress, err)
+               return err
+       }
+
+       i := 0 // output index
+       for _, v := range e2tInstance.AssociatedRanList {
+               if v != ranName {
+                       // copy and increment index
+                       e2tInstance.AssociatedRanList[i] = v
+                       i++
+               }
+       }
+
+       e2tInstance.AssociatedRanList = e2tInstance.AssociatedRanList[:i]
+
+       err = m.rnibDataService.SaveE2TInstance(e2tInstance)
+
+       if err != nil {
+               m.logger.Errorf("#E2TInstancesManager.DissociateRan - E2T Instance address: %s - Failed saving E2TInstance. error: %s", e2tAddress, err)
+               return err
+       }
+
+       m.logger.Infof("#E2TInstancesManager.DissociateRan - successfully dissociated RAN %s from E2T %s", ranName, e2tInstance.Address)
+       return nil
+}
+
+func (m *E2TInstancesManager) RemoveE2TInstance(e2tInstance *entities.E2TInstance) error {
+       return nil
+}
+func (m *E2TInstancesManager) SelectE2TInstance() (string, error) {
+
+       e2tInstances, err := m.GetE2TInstances()
+
+       if err != nil {
+               return "", err
+       }
+
+       if len(e2tInstances) == 0 {
+               m.logger.Errorf("#E2TInstancesManager.SelectE2TInstance - No E2T instance found")
+               return "", e2managererrors.NewE2TInstanceAbsenceError()
+       }
+
+       min := findActiveE2TInstanceWithMinimumAssociatedRans(e2tInstances)
+
+       if min == nil {
+               m.logger.Errorf("#E2TInstancesManager.SelectE2TInstance - No active E2T instance found")
+               return "", e2managererrors.NewE2TInstanceAbsenceError()
+       }
+
+       m.logger.Infof("#E2TInstancesManager.SelectE2TInstance - successfully selected E2T instance. address: %s", min.Address)
+       return min.Address, nil
+}
+
+func (m *E2TInstancesManager) AssociateRan(ranName string, e2tAddress string) error {
+
+       m.mux.Lock()
+       defer m.mux.Unlock()
+
+       e2tInstance, err := m.rnibDataService.GetE2TInstance(e2tAddress)
+
+       if err != nil {
+               m.logger.Errorf("#E2TInstancesManager.AssociateRan - E2T Instance address: %s - Failed retrieving E2TInstance. error: %s", e2tAddress, err)
+               return e2managererrors.NewRnibDbError()
+       }
+
+       e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, ranName)
+
+       err = m.rnibDataService.SaveE2TInstance(e2tInstance)
+
+       if err != nil {
+               m.logger.Errorf("#E2TInstancesManager.AssociateRan - E2T Instance address: %s - Failed saving E2TInstance. error: %s", e2tAddress, err)
+               return e2managererrors.NewRnibDbError()
+       }
+
+       m.logger.Infof("#E2TInstancesManager.AssociateRan - successfully associated RAN %s with E2T %s", ranName, e2tInstance.Address)
+       return nil
+}
+
+func (h E2TInstancesManager) ActivateE2TInstance(e2tInstance *entities.E2TInstance) error{
+
+       if e2tInstance == nil {
+               h.logger.Errorf("#E2TInstancesManager.ActivateE2TInstance - e2tInstance empty")
+               return e2managererrors.NewInternalError()
+       }
+
+       h.logger.Infof("#E2TInstancesManager.ActivateE2TInstance - E2T Address: %s - activate E2T instance", e2tInstance.Address)
+
+       e2tInstance.State = entities.Active
+       e2tInstance.KeepAliveTimestamp = time.Now().UnixNano()
+
+       err := h.rnibDataService.SaveE2TInstance(e2tInstance)
+       if err != nil {
+               h.logger.Errorf("#E2TInstancesManager.ActivateE2TInstance - E2T Instance address: %s - Failed saving E2TInstance. error: %s", e2tInstance.Address, err)
+               return err
+       }
+       return nil
+}
+
+func (m *E2TInstancesManager) ResetKeepAliveTimestamp(e2tAddress string) error {
+
+       m.mux.Lock()
+       defer m.mux.Unlock()
+
+       e2tInstance, err := m.rnibDataService.GetE2TInstanceNoLogs(e2tAddress)
+
+       if err != nil {
+               m.logger.Errorf("#E2TInstancesManager.ResetKeepAliveTimestamp - E2T Instance address: %s - Failed retrieving E2TInstance. error: %s", e2tAddress, err)
+               return err
+       }
+
+       if e2tInstance.State == entities.ToBeDeleted || e2tInstance.State == entities.RoutingManagerFailure {
+               m.logger.Warnf("#E2TInstancesManager.ResetKeepAliveTimestamp - Ignore. This Instance is about to deleted")
+               return nil
+
+       }
+
+       e2tInstance.KeepAliveTimestamp = time.Now().UnixNano()
+       err = m.rnibDataService.SaveE2TInstanceNoLogs(e2tInstance)
+
+       if err != nil {
+               m.logger.Errorf("#E2TInstancesManager.ResetKeepAliveTimestamp - E2T Instance address: %s - Failed saving E2TInstance. error: %s", e2tAddress, err)
+               return err
+       }
+
+       return nil
+}
diff --git a/E2Manager/managers/e2t_instances_manager_test.go b/E2Manager/managers/e2t_instances_manager_test.go
new file mode 100644 (file)
index 0000000..fb564e5
--- /dev/null
@@ -0,0 +1,459 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+package managers
+
+import (
+       "e2mgr/configuration"
+       "e2mgr/logger"
+       "e2mgr/mocks"
+       "e2mgr/services"
+       "fmt"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+       "github.com/pkg/errors"
+       "github.com/stretchr/testify/assert"
+       "github.com/stretchr/testify/mock"
+       "testing"
+)
+
+const E2TAddress = "10.10.2.15:9800"
+const E2TAddress2 = "10.10.2.16:9800"
+
+func initE2TInstancesManagerTest(t *testing.T) (*mocks.RnibReaderMock, *mocks.RnibWriterMock, *E2TInstancesManager) {
+       logger, err := logger.InitLogger(logger.DebugLevel)
+       if err != nil {
+               t.Errorf("#... - failed to initialize logger, error: %s", err)
+       }
+       config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
+
+       readerMock := &mocks.RnibReaderMock{}
+       writerMock := &mocks.RnibWriterMock{}
+       rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
+       e2tInstancesManager := NewE2TInstancesManager(rnibDataService, logger)
+       return readerMock, writerMock, e2tInstancesManager
+}
+
+func TestAddNewE2TInstanceSaveE2TInstanceFailure(t *testing.T) {
+       rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+       rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(common.NewInternalError(errors.New("Error")))
+       err := e2tInstancesManager.AddE2TInstance(E2TAddress)
+       assert.NotNil(t, err)
+       rnibReaderMock.AssertNotCalled(t, "GetE2TAddresses")
+}
+
+func TestAddNewE2TInstanceGetE2TAddressesInternalFailure(t *testing.T) {
+       rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+       rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(nil)
+       e2tAddresses := []string{}
+       rnibReaderMock.On("GetE2TAddresses").Return(e2tAddresses, common.NewInternalError(errors.New("Error")))
+       err := e2tInstancesManager.AddE2TInstance(E2TAddress)
+       assert.NotNil(t, err)
+       rnibReaderMock.AssertNotCalled(t, "SaveE2TAddresses")
+}
+
+func TestAddNewE2TInstanceSaveE2TAddressesFailure(t *testing.T) {
+       rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+       rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(nil)
+       E2TAddresses := []string{}
+       rnibReaderMock.On("GetE2TAddresses").Return(E2TAddresses, nil)
+       E2TAddresses = append(E2TAddresses, E2TAddress)
+       rnibWriterMock.On("SaveE2TAddresses", E2TAddresses).Return(common.NewResourceNotFoundError(""))
+       err := e2tInstancesManager.AddE2TInstance(E2TAddress)
+       assert.NotNil(t, err)
+}
+
+func TestAddNewE2TInstanceNoE2TAddressesSuccess(t *testing.T) {
+       rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+       rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(nil)
+       e2tAddresses := []string{}
+       rnibReaderMock.On("GetE2TAddresses").Return(e2tAddresses, common.NewResourceNotFoundError(""))
+       e2tAddresses = append(e2tAddresses, E2TAddress)
+       rnibWriterMock.On("SaveE2TAddresses", e2tAddresses).Return(nil)
+       err := e2tInstancesManager.AddE2TInstance(E2TAddress)
+       assert.Nil(t, err)
+       rnibWriterMock.AssertCalled(t, "SaveE2TAddresses", e2tAddresses)
+}
+
+func TestAddNewE2TInstanceEmptyE2TAddressesSuccess(t *testing.T) {
+       rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+       rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(nil)
+       e2tAddresses := []string{}
+       rnibReaderMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
+       e2tAddresses = append(e2tAddresses, E2TAddress)
+       rnibWriterMock.On("SaveE2TAddresses", e2tAddresses).Return(nil)
+       err := e2tInstancesManager.AddE2TInstance(E2TAddress)
+       assert.Nil(t, err)
+       rnibWriterMock.AssertCalled(t, "SaveE2TAddresses", e2tAddresses)
+}
+
+func TestAddNewE2TInstanceExistingE2TAddressesSuccess(t *testing.T) {
+       rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+       rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(nil)
+       E2TAddresses := []string{"10.0.1.15:3030"}
+       rnibReaderMock.On("GetE2TAddresses").Return(E2TAddresses, nil)
+       E2TAddresses = append(E2TAddresses, E2TAddress)
+       rnibWriterMock.On("SaveE2TAddresses", E2TAddresses).Return(nil)
+       err := e2tInstancesManager.AddE2TInstance(E2TAddress)
+       assert.Nil(t, err)
+}
+
+func TestGetE2TInstanceFailure(t *testing.T) {
+       rnibReaderMock, _, e2tInstancesManager := initE2TInstancesManagerTest(t)
+       var e2tInstance *entities.E2TInstance
+       rnibReaderMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, common.NewInternalError(fmt.Errorf("for test")))
+       res, err := e2tInstancesManager.GetE2TInstance(E2TAddress)
+       assert.NotNil(t, err)
+       assert.Nil(t, res)
+}
+
+func TestGetE2TInstanceSuccess(t *testing.T) {
+       rnibReaderMock, _, e2tInstancesManager := initE2TInstancesManagerTest(t)
+       address := "10.10.2.15:9800"
+       e2tInstance := entities.NewE2TInstance(address)
+       rnibReaderMock.On("GetE2TInstance", address).Return(e2tInstance, nil)
+       res, err := e2tInstancesManager.GetE2TInstance(address)
+       assert.Nil(t, err)
+       assert.Equal(t, e2tInstance, res)
+}
+
+func TestAssociateRanGetInstanceFailure(t *testing.T) {
+       rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+
+       var e2tInstance1 *entities.E2TInstance
+       rnibReaderMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance1, common.NewInternalError(fmt.Errorf("for test")))
+
+       err := e2tInstancesManager.AssociateRan("test1", E2TAddress)
+       assert.NotNil(t, err)
+       rnibWriterMock.AssertNotCalled(t, "SaveE2TInstance")
+}
+
+func TestAssociateRanSaveInstanceFailure(t *testing.T) {
+       rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       rnibReaderMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance1, nil)
+       rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(common.NewInternalError(fmt.Errorf("for test")))
+
+       err := e2tInstancesManager.AssociateRan("test1", E2TAddress)
+       assert.NotNil(t, err)
+       rnibReaderMock.AssertExpectations(t)
+       rnibWriterMock.AssertExpectations(t)
+}
+
+func TestAssociateRanSuccess(t *testing.T) {
+       rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+       e2tInstance := entities.NewE2TInstance(E2TAddress)
+       rnibReaderMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil)
+
+       updateE2TInstance := *e2tInstance
+       updateE2TInstance.AssociatedRanList = append(updateE2TInstance.AssociatedRanList, "test1")
+
+       rnibWriterMock.On("SaveE2TInstance", &updateE2TInstance).Return(nil)
+
+       err := e2tInstancesManager.AssociateRan("test1", E2TAddress)
+       assert.Nil(t, err)
+       rnibReaderMock.AssertExpectations(t)
+       rnibWriterMock.AssertExpectations(t)
+}
+
+func TestDissociateRanGetInstanceFailure(t *testing.T) {
+       rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+
+       var e2tInstance1 *entities.E2TInstance
+       rnibReaderMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance1, common.NewInternalError(fmt.Errorf("for test")))
+       err := e2tInstancesManager.DissociateRan("test1", E2TAddress)
+       assert.NotNil(t, err)
+       rnibWriterMock.AssertNotCalled(t, "SaveE2TInstance")
+}
+
+func TestDissociateRanSaveInstanceFailure(t *testing.T) {
+       rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       rnibReaderMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance1, nil)
+       rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(common.NewInternalError(fmt.Errorf("for test")))
+
+       err := e2tInstancesManager.DissociateRan("test1", E2TAddress)
+       assert.NotNil(t, err)
+       rnibReaderMock.AssertExpectations(t)
+       rnibWriterMock.AssertExpectations(t)
+}
+
+func TestDissociateRanSuccess(t *testing.T) {
+       rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+
+       e2tInstance := entities.NewE2TInstance(E2TAddress)
+       e2tInstance.AssociatedRanList = []string{"test0", "test1"}
+       updatedE2TInstance := *e2tInstance
+       updatedE2TInstance.AssociatedRanList = []string{"test0"}
+       rnibReaderMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil)
+       rnibWriterMock.On("SaveE2TInstance", &updatedE2TInstance).Return(nil)
+
+       err := e2tInstancesManager.DissociateRan("test1", E2TAddress)
+       assert.Nil(t, err)
+       rnibReaderMock.AssertExpectations(t)
+       rnibWriterMock.AssertExpectations(t)
+}
+
+func TestSelectE2TInstancesGetE2TAddressesFailure(t *testing.T) {
+       rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+
+       rnibReaderMock.On("GetE2TAddresses").Return([]string{}, common.NewInternalError(fmt.Errorf("for test")))
+       address, err := e2tInstancesManager.SelectE2TInstance()
+       assert.NotNil(t, err)
+       assert.Empty(t, address)
+       rnibReaderMock.AssertExpectations(t)
+       rnibWriterMock.AssertNotCalled(t, "GetE2TInstances")
+}
+
+func TestSelectE2TInstancesEmptyE2TAddressList(t *testing.T) {
+       rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+
+       rnibReaderMock.On("GetE2TAddresses").Return([]string{}, nil)
+       address, err := e2tInstancesManager.SelectE2TInstance()
+       assert.NotNil(t, err)
+       assert.Empty(t, address)
+       rnibReaderMock.AssertExpectations(t)
+       rnibWriterMock.AssertNotCalled(t, "GetE2TInstances")
+}
+
+func TestSelectE2TInstancesGetE2TInstancesFailure(t *testing.T) {
+       rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+
+       addresses := []string{E2TAddress}
+       rnibReaderMock.On("GetE2TAddresses").Return(addresses, nil)
+       rnibReaderMock.On("GetE2TInstances", addresses).Return([]*entities.E2TInstance{}, common.NewInternalError(fmt.Errorf("for test")))
+       address, err := e2tInstancesManager.SelectE2TInstance()
+       assert.NotNil(t, err)
+       assert.Empty(t, address)
+       rnibReaderMock.AssertExpectations(t)
+       rnibWriterMock.AssertExpectations(t)
+}
+
+func TestSelectE2TInstancesEmptyE2TInstancesList(t *testing.T) {
+       rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+
+       addresses := []string{E2TAddress}
+       rnibReaderMock.On("GetE2TAddresses").Return(addresses, nil)
+       rnibReaderMock.On("GetE2TInstances", addresses).Return([]*entities.E2TInstance{}, nil)
+       address, err := e2tInstancesManager.SelectE2TInstance()
+       assert.NotNil(t, err)
+       assert.Empty(t, address)
+       rnibReaderMock.AssertExpectations(t)
+       rnibWriterMock.AssertExpectations(t)
+}
+
+func TestSelectE2TInstancesNoActiveE2TInstance(t *testing.T) {
+       rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+       addresses := []string{E2TAddress, E2TAddress2}
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       e2tInstance1.State = entities.ToBeDeleted
+       e2tInstance1.AssociatedRanList = []string{"test1", "test2", "test3"}
+       e2tInstance2 := entities.NewE2TInstance(E2TAddress2)
+       e2tInstance2.State = entities.ToBeDeleted
+       e2tInstance2.AssociatedRanList = []string{"test4", "test5", "test6", "test7"}
+
+       rnibReaderMock.On("GetE2TAddresses").Return(addresses, nil)
+       rnibReaderMock.On("GetE2TInstances", addresses).Return([]*entities.E2TInstance{e2tInstance1, e2tInstance2}, nil)
+       address, err := e2tInstancesManager.SelectE2TInstance()
+       assert.NotNil(t, err)
+       assert.Equal(t, "", address)
+       rnibReaderMock.AssertExpectations(t)
+       rnibWriterMock.AssertExpectations(t)
+}
+
+func TestSelectE2TInstancesSuccess(t *testing.T) {
+       rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+       addresses := []string{E2TAddress, E2TAddress2}
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       e2tInstance1.AssociatedRanList = []string{"test1", "test2", "test3"}
+       e2tInstance2 := entities.NewE2TInstance(E2TAddress2)
+       e2tInstance2.AssociatedRanList = []string{"test4", "test5", "test6", "test7"}
+
+       rnibReaderMock.On("GetE2TAddresses").Return(addresses, nil)
+       rnibReaderMock.On("GetE2TInstances", addresses).Return([]*entities.E2TInstance{e2tInstance1, e2tInstance2}, nil)
+       address, err := e2tInstancesManager.SelectE2TInstance()
+       assert.Nil(t, err)
+       assert.Equal(t, E2TAddress, address)
+       rnibReaderMock.AssertExpectations(t)
+       rnibWriterMock.AssertExpectations(t)
+}
+
+func TestActivateE2TInstanceSuccess(t *testing.T) {
+       _, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       e2tInstance1.State = entities.RoutingManagerFailure
+       e2tInstance1.AssociatedRanList = []string{"test1","test2","test3"}
+
+       rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(nil)
+
+       err := e2tInstancesManager.ActivateE2TInstance(e2tInstance1)
+       assert.Nil(t, err)
+       assert.Equal(t, entities.Active, e2tInstance1.State)
+       rnibWriterMock.AssertExpectations(t)
+}
+
+func TestActivateE2TInstance_RnibError(t *testing.T) {
+       _, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       e2tInstance1.State = entities.RoutingManagerFailure
+       e2tInstance1.AssociatedRanList = []string{"test1","test2","test3"}
+
+       rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(common.NewInternalError(errors.New("Error")))
+
+       err := e2tInstancesManager.ActivateE2TInstance(e2tInstance1)
+       assert.NotNil(t, err)
+}
+
+func TestActivateE2TInstance_NoInstance(t *testing.T) {
+       _, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+
+       err := e2tInstancesManager.ActivateE2TInstance(nil)
+
+       assert.NotNil(t, err)
+       rnibWriterMock.AssertNotCalled(t, "SaveE2TInstance")
+}
+
+func TestResetKeepAliveTimestampGetInternalFailure(t *testing.T) {
+       rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+
+       address := "10.10.2.15:9800"
+       e2tInstance := entities.NewE2TInstance(address)
+       rnibReaderMock.On("GetE2TInstance", address).Return(e2tInstance, common.NewInternalError(errors.New("Error")))
+       rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(nil)
+
+       err := e2tInstancesManager.ResetKeepAliveTimestamp(address)
+       assert.NotNil(t, err)
+       rnibReaderMock.AssertNotCalled(t, "SaveE2TInstance")
+}
+
+func TestAResetKeepAliveTimestampSaveInternalFailure(t *testing.T) {
+       rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+
+       address := "10.10.2.15:9800"
+       e2tInstance := entities.NewE2TInstance(address)
+       rnibReaderMock.On("GetE2TInstance", address).Return(e2tInstance, nil)
+       rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(common.NewInternalError(errors.New("Error")))
+
+       err := e2tInstancesManager.ResetKeepAliveTimestamp(address)
+       assert.NotNil(t, err)
+}
+
+func TestResetKeepAliveTimestampSuccess(t *testing.T) {
+       rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+
+       address := "10.10.2.15:9800"
+       e2tInstance := entities.NewE2TInstance(address)
+       rnibReaderMock.On("GetE2TInstance", address).Return(e2tInstance, nil)
+       rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(nil)
+
+       err := e2tInstancesManager.ResetKeepAliveTimestamp(address)
+       assert.Nil(t, err)
+       rnibReaderMock.AssertCalled(t, "GetE2TInstance", address)
+       rnibWriterMock.AssertNumberOfCalls(t, "SaveE2TInstance", 1)
+}
+
+func TestResetKeepAliveTimestampToBeDeleted(t *testing.T) {
+       rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+
+       address := "10.10.2.15:9800"
+       e2tInstance := entities.NewE2TInstance(address)
+       e2tInstance.State = entities.ToBeDeleted
+       rnibReaderMock.On("GetE2TInstance", address).Return(e2tInstance, nil)
+
+       err := e2tInstancesManager.ResetKeepAliveTimestamp(address)
+       assert.Nil(t, err)
+       rnibReaderMock.AssertCalled(t, "GetE2TInstance", address)
+       rnibWriterMock.AssertNotCalled(t, "SaveE2TInstance")
+}
+
+func TestResetKeepAliveTimestampRoutingManagerFailure(t *testing.T) {
+       rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+
+       address := "10.10.2.15:9800"
+       e2tInstance := entities.NewE2TInstance(address)
+       e2tInstance.State = entities.RoutingManagerFailure
+       rnibReaderMock.On("GetE2TInstance", address).Return(e2tInstance, nil)
+
+       err := e2tInstancesManager.ResetKeepAliveTimestamp(address)
+       assert.Nil(t, err)
+       rnibReaderMock.AssertCalled(t, "GetE2TInstance", address)
+       rnibWriterMock.AssertNotCalled(t, "SaveE2TInstance")
+}
+
+func TestRemoveE2TInstance(t *testing.T) {
+       _, _, e2tInstancesManager := initE2TInstancesManagerTest(t)
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       err := e2tInstancesManager.RemoveE2TInstance(e2tInstance1)
+       assert.Nil(t, err)
+}
+
+func TestResetKeepAliveTimestampsForAllE2TInstancesGetE2TInstancesFailure(t *testing.T) {
+       rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+       rnibReaderMock.On("GetE2TAddresses").Return([]string{}, common.NewInternalError(errors.New("Error")))
+       e2tInstancesManager.ResetKeepAliveTimestampsForAllE2TInstances()
+       rnibWriterMock.AssertNotCalled(t, "SaveE2TInstance")
+}
+
+func TestResetKeepAliveTimestampsForAllE2TInstancesNoInstances(t *testing.T) {
+       rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+       rnibReaderMock.On("GetE2TAddresses").Return([]string{}, nil)
+       e2tInstancesManager.ResetKeepAliveTimestampsForAllE2TInstances()
+       rnibWriterMock.AssertNotCalled(t, "SaveE2TInstance")
+}
+
+func TestResetKeepAliveTimestampsForAllE2TInstancesNoActiveInstances(t *testing.T) {
+       rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+       e2tAddresses := []string{E2TAddress, E2TAddress2}
+       rnibReaderMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       e2tInstance1.State = entities.ToBeDeleted
+       e2tInstance2 := entities.NewE2TInstance(E2TAddress2)
+       e2tInstance2.State = entities.RoutingManagerFailure
+       rnibReaderMock.On("GetE2TInstances", e2tAddresses).Return([]*entities.E2TInstance{e2tInstance1, e2tInstance2}, nil)
+       e2tInstancesManager.ResetKeepAliveTimestampsForAllE2TInstances()
+       rnibWriterMock.AssertNotCalled(t, "SaveE2TInstance")
+}
+
+func TestResetKeepAliveTimestampsForAllE2TInstancesOneActiveInstance(t *testing.T) {
+       rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+       e2tAddresses := []string{E2TAddress, E2TAddress2}
+       rnibReaderMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       e2tInstance1.State = entities.Active
+       e2tInstance2 := entities.NewE2TInstance(E2TAddress2)
+       e2tInstance2.State = entities.ToBeDeleted
+       rnibReaderMock.On("GetE2TInstances", e2tAddresses).Return([]*entities.E2TInstance{e2tInstance1, e2tInstance2}, nil)
+       rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(nil)
+       e2tInstancesManager.ResetKeepAliveTimestampsForAllE2TInstances()
+       rnibWriterMock.AssertNumberOfCalls(t, "SaveE2TInstance",1)
+}
+
+func TestResetKeepAliveTimestampsForAllE2TInstancesSaveE2TInstanceFailure(t *testing.T) {
+       rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
+       e2tAddresses := []string{E2TAddress, E2TAddress2}
+       rnibReaderMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       e2tInstance1.State = entities.Active
+       e2tInstance2 := entities.NewE2TInstance(E2TAddress2)
+       e2tInstance2.State = entities.ToBeDeleted
+       rnibReaderMock.On("GetE2TInstances", e2tAddresses).Return([]*entities.E2TInstance{e2tInstance1, e2tInstance2}, nil)
+       rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(common.NewInternalError(errors.New("Error")))
+       e2tInstancesManager.ResetKeepAliveTimestampsForAllE2TInstances()
+       rnibWriterMock.AssertNumberOfCalls(t, "SaveE2TInstance",1)
+}
diff --git a/E2Manager/managers/e2t_keep_alive_worker.go b/E2Manager/managers/e2t_keep_alive_worker.go
new file mode 100644 (file)
index 0000000..45c5c08
--- /dev/null
@@ -0,0 +1,85 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+package managers
+
+import (
+       "e2mgr/configuration"
+       "e2mgr/logger"
+       "e2mgr/models"
+       "e2mgr/rmrCgo"
+       "e2mgr/services/rmrsender"
+       "time"
+)
+
+type E2TKeepAliveWorker struct {
+       logger              *logger.Logger
+       e2tShutdownManager  IE2TShutdownManager
+       e2TInstancesManager IE2TInstancesManager
+       rmrSender           *rmrsender.RmrSender
+       config              *configuration.Configuration
+}
+
+func NewE2TKeepAliveWorker(logger *logger.Logger, rmrSender *rmrsender.RmrSender, e2TInstancesManager IE2TInstancesManager, e2tShutdownManager IE2TShutdownManager, config *configuration.Configuration) E2TKeepAliveWorker {
+       return E2TKeepAliveWorker{
+               logger:              logger,
+               e2tShutdownManager:  e2tShutdownManager,
+               e2TInstancesManager: e2TInstancesManager,
+               rmrSender:           rmrSender,
+               config:              config,
+       }
+}
+
+func (h E2TKeepAliveWorker) Execute() {
+
+       h.logger.Infof("#E2TKeepAliveWorker.Execute - keep alive started")
+
+       ticker := time.NewTicker(time.Duration(h.config.KeepAliveDelayMs) * time.Millisecond)
+
+       for _= range ticker.C {
+
+               h.SendKeepAliveRequest()
+               h.E2TKeepAliveExpired()
+       }
+}
+
+func (h E2TKeepAliveWorker) E2TKeepAliveExpired() {
+
+       e2tInstances, err := h.e2TInstancesManager.GetE2TInstancesNoLogs()
+
+       if err != nil || len(e2tInstances) == 0 {
+               return
+       }
+
+       for _, e2tInstance := range e2tInstances {
+
+               delta := int64(time.Now().UnixNano()) - e2tInstance.KeepAliveTimestamp
+               timestampNanosec := int64(time.Duration(h.config.KeepAliveResponseTimeoutMs) * time.Millisecond)
+
+               if delta > timestampNanosec {
+
+                       h.logger.Warnf("#E2TKeepAliveWorker.E2TKeepAliveExpired - e2t address: %s time expired, shutdown e2 instance", e2tInstance.Address)
+
+                       h.e2tShutdownManager.Shutdown(e2tInstance)
+               }
+       }
+}
+
+func (h E2TKeepAliveWorker) SendKeepAliveRequest() {
+
+       request := models.RmrMessage{MsgType: rmrCgo.E2_TERM_KEEP_ALIVE_REQ}
+       h.rmrSender.SendWithoutLogs(&request)
+}
\ No newline at end of file
diff --git a/E2Manager/managers/e2t_keep_alive_worker_test.go b/E2Manager/managers/e2t_keep_alive_worker_test.go
new file mode 100644 (file)
index 0000000..00714ca
--- /dev/null
@@ -0,0 +1,198 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+package managers
+
+import (
+       "e2mgr/configuration"
+       "e2mgr/logger"
+       "e2mgr/mocks"
+       "e2mgr/rmrCgo"
+       "e2mgr/services"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+       "github.com/pkg/errors"
+       "github.com/stretchr/testify/mock"
+       "testing"
+       "time"
+)
+
+func initE2TKeepAliveTest(t *testing.T) (*mocks.RmrMessengerMock, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.E2TShutdownManagerMock, *E2TKeepAliveWorker) {
+       logger, err := logger.InitLogger(logger.DebugLevel)
+       if err != nil {
+               t.Errorf("#... - failed to initialize logger, error: %s", err)
+       }
+       config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3, KeepAliveResponseTimeoutMs: 400, KeepAliveDelayMs: 100}
+
+       readerMock := &mocks.RnibReaderMock{}
+       writerMock := &mocks.RnibWriterMock{}
+       e2tShutdownManagerMock := &mocks.E2TShutdownManagerMock{}
+
+       rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
+       e2tInstancesManager := NewE2TInstancesManager(rnibDataService, logger)
+
+       rmrMessengerMock := &mocks.RmrMessengerMock{}
+       rmrSender := initRmrSender(rmrMessengerMock, logger)
+
+       e2tKeepAliveWorker := NewE2TKeepAliveWorker(logger, rmrSender, e2tInstancesManager, e2tShutdownManagerMock, config)
+
+       return rmrMessengerMock, readerMock, writerMock, e2tShutdownManagerMock, &e2tKeepAliveWorker
+}
+
+func TestSendKeepAliveRequest(t *testing.T) {
+       rmrMessengerMock, _, _, _, e2tKeepAliveWorker := initE2TKeepAliveTest(t)
+
+       rmrMessengerMock.On("SendMsg", mock.Anything, false).Return(&rmrCgo.MBuf{}, nil)
+
+       e2tKeepAliveWorker.SendKeepAliveRequest()
+
+       var payload, xAction []byte
+       req := rmrCgo.NewMBuf(rmrCgo.E2_TERM_KEEP_ALIVE_REQ, 0, "", &payload, &xAction)
+
+       rmrMessengerMock.AssertCalled(t, "SendMsg", req, false)
+}
+
+func TestShutdownExpiredE2T_InternalError(t *testing.T) {
+       rmrMessengerMock, readerMock, _, _, e2tKeepAliveWorker := initE2TKeepAliveTest(t)
+
+       readerMock.On("GetE2TAddresses").Return([]string{}, common.NewInternalError(errors.New("#reader.GetNodeb - Internal Error")))
+
+       e2tKeepAliveWorker.E2TKeepAliveExpired()
+
+       rmrMessengerMock.AssertNotCalled(t, "Shutdown")
+}
+
+func TestShutdownExpiredE2T_NoAddresses(t *testing.T) {
+       rmrMessengerMock, readerMock, _, _, e2tKeepAliveWorker := initE2TKeepAliveTest(t)
+
+       addresses := []string{}
+
+       readerMock.On("GetE2TAddresses").Return(addresses, nil)
+
+       e2tKeepAliveWorker.E2TKeepAliveExpired()
+
+       rmrMessengerMock.AssertNotCalled(t, "Shutdown")
+}
+
+func TestShutdownExpiredE2T_NotExpired_InternalError(t *testing.T) {
+       rmrMessengerMock, readerMock, _, _, e2tKeepAliveWorker := initE2TKeepAliveTest(t)
+
+       addresses := []string{E2TAddress,E2TAddress2}
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       e2tInstance1.AssociatedRanList = []string{"test1","test2","test3"}
+       e2tInstance2 := entities.NewE2TInstance(E2TAddress2)
+       e2tInstance2.AssociatedRanList = []string{"test4","test5","test6", "test7"}
+
+       readerMock.On("GetE2TAddresses").Return(addresses, nil)
+       readerMock.On("GetE2TInstances",addresses).Return([]*entities.E2TInstance{e2tInstance1, e2tInstance2}, common.NewInternalError(errors.New("#reader.GetNodeb - Internal Error")))
+
+       e2tKeepAliveWorker.E2TKeepAliveExpired()
+
+       rmrMessengerMock.AssertNotCalled(t, "Shutdown")
+}
+
+func TestShutdownExpiredE2T_NoE2T(t *testing.T) {
+       rmrMessengerMock, readerMock, _, _, e2tKeepAliveWorker := initE2TKeepAliveTest(t)
+
+       readerMock.On("GetE2TAddresses").Return([]string{}, common.NewResourceNotFoundError("not found"))
+
+       e2tKeepAliveWorker.E2TKeepAliveExpired()
+
+       rmrMessengerMock.AssertNotCalled(t, "Shutdown")
+}
+
+func TestShutdownExpiredE2T_NotExpired(t *testing.T) {
+       rmrMessengerMock, readerMock, _, _, e2tKeepAliveWorker := initE2TKeepAliveTest(t)
+
+       addresses := []string{E2TAddress,E2TAddress2}
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       e2tInstance1.AssociatedRanList = []string{"test1","test2","test3"}
+       e2tInstance2 := entities.NewE2TInstance(E2TAddress2)
+       e2tInstance2.AssociatedRanList = []string{"test4","test5","test6", "test7"}
+
+       readerMock.On("GetE2TAddresses").Return(addresses, nil)
+       readerMock.On("GetE2TInstances",addresses).Return([]*entities.E2TInstance{e2tInstance1, e2tInstance2}, nil)
+
+       e2tKeepAliveWorker.E2TKeepAliveExpired()
+
+       rmrMessengerMock.AssertNotCalled(t, "Shutdown")
+}
+
+func TestShutdownExpiredE2T_One_E2TExpired(t *testing.T) {
+       _, readerMock, _, e2tShutdownManagerMock, e2tKeepAliveWorker := initE2TKeepAliveTest(t)
+
+       addresses := []string{E2TAddress,E2TAddress2}
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       e2tInstance1.AssociatedRanList = []string{"test1","test2","test3"}
+
+       time.Sleep(time.Duration(400) * time.Millisecond)
+
+       e2tInstance2 := entities.NewE2TInstance(E2TAddress2)
+       e2tInstance2.AssociatedRanList = []string{"test4","test5","test6", "test7"}
+
+       readerMock.On("GetE2TAddresses").Return(addresses, nil)
+       readerMock.On("GetE2TInstances",addresses).Return([]*entities.E2TInstance{e2tInstance1, e2tInstance2}, nil)
+       e2tShutdownManagerMock.On("Shutdown", e2tInstance1).Return(nil)
+
+       e2tKeepAliveWorker.E2TKeepAliveExpired()
+
+       e2tShutdownManagerMock.AssertNumberOfCalls(t, "Shutdown", 1)
+}
+
+func TestShutdownExpiredE2T_Two_E2TExpired(t *testing.T) {
+       _, readerMock, _, e2tShutdownManagerMock, e2tKeepAliveWorker := initE2TKeepAliveTest(t)
+
+       addresses := []string{E2TAddress,E2TAddress2}
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       e2tInstance1.AssociatedRanList = []string{"test1","test2","test3"}
+
+       e2tInstance2 := entities.NewE2TInstance(E2TAddress2)
+       e2tInstance2.AssociatedRanList = []string{"test4","test5","test6", "test7"}
+
+       time.Sleep(time.Duration(400) * time.Millisecond)
+
+       readerMock.On("GetE2TAddresses").Return(addresses, nil)
+       readerMock.On("GetE2TInstances",addresses).Return([]*entities.E2TInstance{e2tInstance1, e2tInstance2}, nil)
+       e2tShutdownManagerMock.On("Shutdown", e2tInstance1).Return(nil)
+       e2tShutdownManagerMock.On("Shutdown", e2tInstance2).Return(nil)
+
+       e2tKeepAliveWorker.E2TKeepAliveExpired()
+
+       e2tShutdownManagerMock.AssertNumberOfCalls(t, "Shutdown", 2)
+}
+
+func TestExecute_Two_E2TExpired(t *testing.T) {
+       rmrMessengerMock, readerMock, _, e2tShutdownManagerMock, e2tKeepAliveWorker := initE2TKeepAliveTest(t)
+
+       addresses := []string{E2TAddress,E2TAddress2}
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       e2tInstance1.AssociatedRanList = []string{"test1","test2","test3"}
+
+       readerMock.On("GetE2TAddresses").Return(addresses, nil)
+       readerMock.On("GetE2TInstances",addresses).Return([]*entities.E2TInstance{e2tInstance1}, nil)
+       e2tShutdownManagerMock.On("Shutdown", e2tInstance1).Return(nil)
+       rmrMessengerMock.On("SendMsg", mock.Anything, false).Return(&rmrCgo.MBuf{}, nil)
+
+       go e2tKeepAliveWorker.Execute()
+
+       time.Sleep(time.Duration(500) * time.Millisecond)
+
+       var payload, xAction []byte
+       req := rmrCgo.NewMBuf(rmrCgo.E2_TERM_KEEP_ALIVE_REQ, 0, "", &payload, &xAction)
+
+       rmrMessengerMock.AssertCalled(t, "SendMsg", req, false)
+       e2tShutdownManagerMock.AssertCalled(t, "Shutdown", e2tInstance1)
+}
\ No newline at end of file
diff --git a/E2Manager/managers/e2t_shutdown_manager.go b/E2Manager/managers/e2t_shutdown_manager.go
new file mode 100644 (file)
index 0000000..e789689
--- /dev/null
@@ -0,0 +1,48 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+package managers
+
+import (
+       "e2mgr/logger"
+       "e2mgr/services"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+)
+
+
+type IE2TShutdownManager interface {
+       Shutdown(e2tInstance *entities.E2TInstance) error
+}
+
+type E2TShutdownManager struct {
+       logger              *logger.Logger
+       rnibDataService     services.RNibDataService
+       e2TInstancesManager IE2TInstancesManager
+}
+
+func NewE2TShutdownManager(logger *logger.Logger, rnibDataService services.RNibDataService, e2TInstancesManager IE2TInstancesManager) E2TShutdownManager {
+       return E2TShutdownManager{
+               logger:              logger,
+               rnibDataService:     rnibDataService,
+               e2TInstancesManager: e2TInstancesManager,
+       }
+}
+
+func (h E2TShutdownManager) Shutdown(e2tInstance *entities.E2TInstance) error{
+       h.logger.Infof("#E2TShutdownManager.Shutdown - E2T %s is Dead, RIP", e2tInstance.Address)
+
+       return nil
+}
index 1b7a34a..8ef22c9 100644 (file)
@@ -22,20 +22,23 @@ package managers
 
 import (
        "e2mgr/converters"
-       "e2mgr/e2pdus"
        "e2mgr/logger"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
 )
 
-type EndcSetupFailureResponseManager struct{}
+type EndcSetupFailureResponseManager struct {
+       converter converters.IEndcSetupFailureResponseConverter
+}
 
-func NewEndcSetupFailureResponseManager() *EndcSetupFailureResponseManager {
-       return &EndcSetupFailureResponseManager{}
+func NewEndcSetupFailureResponseManager(converter converters.IEndcSetupFailureResponseConverter) *EndcSetupFailureResponseManager {
+       return &EndcSetupFailureResponseManager{
+               converter: converter,
+       }
 }
 
 func (m *EndcSetupFailureResponseManager) PopulateNodebByPdu(logger *logger.Logger, nbIdentity *entities.NbIdentity, nodebInfo *entities.NodebInfo, payload []byte) error {
 
-       failureResponse, err := converters.UnpackEndcX2SetupFailureResponseAndExtract(logger, e2pdus.MaxAsn1CodecAllocationBufferSize, len(payload), payload, e2pdus.MaxAsn1CodecMessageBufferSize)
+       failureResponse, err := m.converter.UnpackEndcSetupFailureResponseAndExtract(payload)
 
        if err != nil {
                logger.Errorf("#EndcSetupFailureResponseManager.PopulateNodebByPdu - RAN name: %s - Unpack and extract failed. Error: %v", nodebInfo.RanName, err)
diff --git a/E2Manager/managers/endc_setup_failure_response_manager_test.go b/E2Manager/managers/endc_setup_failure_response_manager_test.go
new file mode 100644 (file)
index 0000000..4bdc9fa
--- /dev/null
@@ -0,0 +1,66 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+package managers
+
+import (
+       "e2mgr/converters"
+       "e2mgr/tests"
+       "fmt"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+       "github.com/stretchr/testify/assert"
+       "math/rand"
+       "testing"
+)
+
+func TestPopulateNodebByPduFailure(t *testing.T) {
+       logger := tests.InitLog(t)
+       nodebInfo := &entities.NodebInfo{}
+       nodebIdentity := &entities.NbIdentity{}
+       converter := converters.NewEndcSetupFailureResponseConverter(logger)
+       handler := NewEndcSetupFailureResponseManager(converter)
+       err := handler.PopulateNodebByPdu(logger, nodebIdentity, nodebInfo, createRandomPayload())
+       assert.NotNil(t, err)
+}
+
+func TestPopulateNodebByPduSuccess(t *testing.T) {
+       logger := tests.InitLog(t)
+       nodebInfo := &entities.NodebInfo{}
+       nodebIdentity := &entities.NbIdentity{}
+       converter := converters.NewEndcSetupFailureResponseConverter(logger)
+       handler := NewEndcSetupFailureResponseManager(converter)
+       err := handler.PopulateNodebByPdu(logger, nodebIdentity, nodebInfo, createSetupFailureResponsePayload(t))
+       assert.Nil(t, err)
+       assert.Equal(t, entities.ConnectionStatus_CONNECTED_SETUP_FAILED, nodebInfo.ConnectionStatus)
+       assert.Equal(t, entities.Failure_ENDC_X2_SETUP_FAILURE, nodebInfo.FailureType)
+
+}
+
+func createSetupFailureResponsePayload(t *testing.T) []byte {
+       packedPdu := "4024001a0000030005400200000016400100001140087821a00000008040"
+       var payload []byte
+       _, err := fmt.Sscanf(packedPdu, "%x", &payload)
+       if err != nil {
+               t.Errorf("convert inputPayloadAsStr to payloadAsByte. Error: %v\n", err)
+       }
+       return payload
+}
+
+func createRandomPayload() []byte {
+       payload := make([]byte, 20)
+       rand.Read(payload)
+       return payload
+}
index 60da306..a6118c4 100644 (file)
@@ -22,20 +22,23 @@ package managers
 
 import (
        "e2mgr/converters"
-       "e2mgr/e2pdus"
        "e2mgr/logger"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
 )
 
-type EndcSetupResponseManager struct{}
+type EndcSetupResponseManager struct{
+       converter converters.IEndcSetupResponseConverter
+}
 
-func NewEndcSetupResponseManager() *EndcSetupResponseManager {
-       return &EndcSetupResponseManager{}
+func NewEndcSetupResponseManager(converter converters.IEndcSetupResponseConverter) *EndcSetupResponseManager {
+       return &EndcSetupResponseManager{
+               converter: converter,
+       }
 }
 
 func (m *EndcSetupResponseManager) PopulateNodebByPdu(logger *logger.Logger, nbIdentity *entities.NbIdentity, nodebInfo *entities.NodebInfo, payload []byte) error {
 
-       gnbId, gnb, err := converters.UnpackEndcX2SetupResponseAndExtract(logger, e2pdus.MaxAsn1CodecAllocationBufferSize, len(payload), payload, e2pdus.MaxAsn1CodecMessageBufferSize)
+       gnbId, gnb, err := m.converter.UnpackEndcSetupResponseAndExtract(payload)
 
        if err != nil {
                logger.Errorf("#EndcSetupResponseManager.PopulateNodebByPdu - RAN name: %s - Unpack and extract failed. Error: %v", nodebInfo.RanName, err)
diff --git a/E2Manager/managers/endc_setup_response_manager_test.go b/E2Manager/managers/endc_setup_response_manager_test.go
new file mode 100644 (file)
index 0000000..55726c2
--- /dev/null
@@ -0,0 +1,59 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+package managers
+
+import (
+       "e2mgr/converters"
+       "e2mgr/tests"
+       "fmt"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+       "github.com/stretchr/testify/assert"
+       "testing"
+)
+
+func TestSetupResponsePopulateNodebByPduFailure(t *testing.T) {
+       logger := tests.InitLog(t)
+       nodebInfo := &entities.NodebInfo{}
+       nodebIdentity := &entities.NbIdentity{}
+       converter:= converters.NewEndcSetupResponseConverter(logger)
+       handler := NewEndcSetupResponseManager(converter)
+       err := handler.PopulateNodebByPdu(logger, nodebIdentity, nodebInfo, createRandomPayload())
+       assert.NotNil(t, err)
+}
+
+func TestSetupResponsePopulateNodebByPduSuccess(t *testing.T) {
+       logger := tests.InitLog(t)
+       nodebInfo := &entities.NodebInfo{}
+       nodebIdentity := &entities.NbIdentity{}
+       converter:= converters.NewEndcSetupResponseConverter(logger)
+       handler := NewEndcSetupResponseManager(converter)
+       err := handler.PopulateNodebByPdu(logger, nodebIdentity, nodebInfo, createSetupResponsePayload(t))
+       assert.Nil(t, err)
+       assert.Equal(t, entities.ConnectionStatus_CONNECTED, nodebInfo.ConnectionStatus)
+       assert.Equal(t, entities.Node_GNB, nodebInfo.NodeType)
+
+}
+
+func createSetupResponsePayload(t *testing.T) []byte {
+       packedPdu := "202400808e00000100f600808640000200fc00090002f829504a952a0a00fd007200010c0005001e3f271f2e3d4ff03d44d34e4f003e4e5e4400010000150400000a000211e148033e4e5e4c0005001e3f271f2e3d4ff03d44d34e4f003e4e5e4400010000150400000a00021a0044033e4e5e000000002c001e3f271f2e3d4ff0031e3f274400010000150400000a00020000"
+       var payload []byte
+       _, err := fmt.Sscanf(packedPdu, "%x", &payload)
+       if err != nil {
+               t.Errorf("convert inputPayloadAsStr to payloadAsByte. Error: %v\n", err)
+       }
+       return payload
+}
index 9583ea2..a44608b 100644 (file)
@@ -49,7 +49,7 @@ func (m NotificationManager) HandleMessage(mbuf *rmrCgo.MBuf) error {
                return err
        }
 
-       notificationRequest := models.NewNotificationRequest(mbuf.Meid, *mbuf.Payload, time.Now(), string(*mbuf.XAction))
+       notificationRequest := models.NewNotificationRequest(mbuf.Meid, *mbuf.Payload, time.Now(), *mbuf.XAction)
        go notificationHandler.Handle(notificationRequest)
        return nil
 }
index 770ed02..5bce096 100644 (file)
@@ -1,20 +1,18 @@
 package notificationmanager
 
 import (
+       "e2mgr/clients"
        "e2mgr/configuration"
-       "e2mgr/converters"
        "e2mgr/logger"
        "e2mgr/managers"
        "e2mgr/mocks"
        "e2mgr/providers/rmrmsghandlerprovider"
-       "e2mgr/rNibWriter"
        "e2mgr/rmrCgo"
        "e2mgr/services"
        "e2mgr/services/rmrsender"
        "e2mgr/tests"
        "fmt"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
-       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
        "github.com/stretchr/testify/assert"
        "testing"
 )
@@ -24,24 +22,16 @@ func initNotificationManagerTest(t *testing.T) (*logger.Logger, *mocks.RnibReade
        config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
 
        readerMock := &mocks.RnibReaderMock{}
-       rnibReaderProvider := func() reader.RNibReader {
-               return readerMock
-       }
        writerMock := &mocks.RnibWriterMock{}
-       rnibWriterProvider := func() rNibWriter.RNibWriter {
-               return writerMock
-       }
+       httpClient := &mocks.HttpClientMock{}
 
        rmrSender := initRmrSender(&mocks.RmrMessengerMock{}, logger)
-       rnibDataService := services.NewRnibDataService(logger, config, rnibReaderProvider, rnibWriterProvider)
+       rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
        ranSetupManager := managers.NewRanSetupManager(logger, rmrSender, rnibDataService)
-       ranReconnectionManager := managers.NewRanReconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, ranSetupManager)
-       ranStatusChangeManager := managers.NewRanStatusChangeManager(logger, rmrSender)
-       x2SetupResponseConverter := converters.NewX2SetupResponseConverter(logger)
-       x2SetupResponseManager := managers.NewX2SetupResponseManager(x2SetupResponseConverter)
-       x2SetupFailureResponseConverter := converters.NewX2SetupFailureResponseConverter(logger)
-       x2SetupFailureResponseManager := managers.NewX2SetupFailureResponseManager(x2SetupFailureResponseConverter)
-       rmrNotificationHandlerProvider := rmrmsghandlerprovider.NewNotificationHandlerProvider(logger, rnibDataService, ranReconnectionManager, ranStatusChangeManager, rmrSender, x2SetupResponseManager, x2SetupFailureResponseManager)
+       e2tInstancesManager := managers.NewE2TInstancesManager(rnibDataService, logger)
+       routingManagerClient := clients.NewRoutingManagerClient(logger, config, httpClient)
+       rmrNotificationHandlerProvider := rmrmsghandlerprovider.NewNotificationHandlerProvider()
+       rmrNotificationHandlerProvider.Init(logger, config, rnibDataService, rmrSender, ranSetupManager, e2tInstancesManager,routingManagerClient)
        notificationManager := NewNotificationManager(logger, rmrNotificationHandlerProvider )
        return logger, readerMock, notificationManager
 }
@@ -69,7 +59,7 @@ func TestHandleMessageExistingMessageType(t *testing.T) {
 func initRmrSender(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *rmrsender.RmrSender {
        rmrMessenger := rmrCgo.RmrMessenger(rmrMessengerMock)
        rmrMessengerMock.On("Init", tests.GetPort(), tests.MaxMsgSize, tests.Flags, log).Return(&rmrMessenger)
-       return rmrsender.NewRmrSender(log, &rmrMessenger)
+       return rmrsender.NewRmrSender(log, rmrMessenger)
 }
 
 // TODO: extract to test_utils
index 8e2ff8d..530a2cf 100644 (file)
@@ -32,21 +32,27 @@ type IRanReconnectionManager interface {
 }
 
 type RanReconnectionManager struct {
-       logger          *logger.Logger
-       config          *configuration.Configuration
-       rnibDataService services.RNibDataService
-       ranSetupManager *RanSetupManager
+       logger              *logger.Logger
+       config              *configuration.Configuration
+       rnibDataService     services.RNibDataService
+       ranSetupManager     *RanSetupManager
+       e2tInstancesManager IE2TInstancesManager
 }
 
-func NewRanReconnectionManager(logger *logger.Logger, config *configuration.Configuration, rnibDataService services.RNibDataService, ranSetupManager *RanSetupManager) *RanReconnectionManager {
+func NewRanReconnectionManager(logger *logger.Logger, config *configuration.Configuration, rnibDataService services.RNibDataService, ranSetupManager *RanSetupManager, e2tInstancesManager IE2TInstancesManager) *RanReconnectionManager {
        return &RanReconnectionManager{
-               logger:          logger,
-               config:          config,
-               rnibDataService: rnibDataService,
-               ranSetupManager: ranSetupManager,
+               logger:              logger,
+               config:              config,
+               rnibDataService:     rnibDataService,
+               ranSetupManager:     ranSetupManager,
+               e2tInstancesManager: e2tInstancesManager,
        }
 }
 
+func (m *RanReconnectionManager) isRanExceededConnectionAttempts(nodebInfo *entities.NodebInfo) bool {
+       return int(nodebInfo.GetConnectionAttempts()) >= m.config.MaxConnectionAttempts
+}
+
 func (m *RanReconnectionManager) ReconnectRan(inventoryName string) error {
        nodebInfo, rnibErr := m.rnibDataService.GetNodeb(inventoryName)
 
@@ -58,7 +64,18 @@ func (m *RanReconnectionManager) ReconnectRan(inventoryName string) error {
        m.logger.Infof("#RanReconnectionManager.ReconnectRan - RAN name: %s - RAN's connection status: %s, RAN's connection attempts: %d", nodebInfo.RanName, nodebInfo.ConnectionStatus, nodebInfo.ConnectionAttempts)
 
        if !m.canReconnectRan(nodebInfo) {
-               return m.setConnectionStatusOfUnconnectableRan(nodebInfo)
+               e2tAddress := nodebInfo.AssociatedE2TInstanceAddress
+               err := m.updateUnconnectableRan(nodebInfo)
+
+               if err != nil {
+                       return err
+               }
+
+               if m.isRanExceededConnectionAttempts(nodebInfo) {
+                       return m.e2tInstancesManager.DissociateRan(nodebInfo.RanName, e2tAddress)
+               }
+
+               return nil
        }
 
        err := m.ranSetupManager.ExecuteSetup(nodebInfo, entities.ConnectionStatus_CONNECTING)
@@ -77,39 +94,41 @@ func (m *RanReconnectionManager) canReconnectRan(nodebInfo *entities.NodebInfo)
                int(nodebInfo.GetConnectionAttempts()) < m.config.MaxConnectionAttempts
 }
 
-func (m *RanReconnectionManager) updateNodebInfoStatus(nodebInfo *entities.NodebInfo, connectionStatus entities.ConnectionStatus) error {
-       if nodebInfo.ConnectionStatus == connectionStatus {
-               return nil
-       }
+func (m *RanReconnectionManager) updateNodebInfo(nodebInfo *entities.NodebInfo, connectionStatus entities.ConnectionStatus, resetE2tAddress bool) error {
 
        nodebInfo.ConnectionStatus = connectionStatus;
+
+       if resetE2tAddress {
+               nodebInfo.AssociatedE2TInstanceAddress = ""
+       }
+
        err := m.rnibDataService.UpdateNodebInfo(nodebInfo)
 
        if err != nil {
-               m.logger.Errorf("#RanReconnectionManager.updateNodebInfoStatus - RAN name: %s - Failed updating RAN's connection status to %s in rNib. Error: %v", nodebInfo.RanName, connectionStatus, err)
+               m.logger.Errorf("#RanReconnectionManager.updateNodebInfo - RAN name: %s - Failed updating RAN's connection status to %s in rNib. Error: %v", nodebInfo.RanName, connectionStatus, err)
                return err
        }
 
-       m.logger.Infof("#RanReconnectionManager.updateNodebInfoStatus - RAN name: %s - Successfully updated rNib. RAN's current connection status: %s", nodebInfo.RanName, nodebInfo.ConnectionStatus)
+       m.logger.Infof("#RanReconnectionManager.updateNodebInfo - RAN name: %s - Successfully updated rNib. RAN's current connection status: %s", nodebInfo.RanName, nodebInfo.ConnectionStatus)
        return nil
 }
 
-func (m *RanReconnectionManager) setConnectionStatusOfUnconnectableRan(nodebInfo *entities.NodebInfo) error {
+func (m *RanReconnectionManager) updateUnconnectableRan(nodebInfo *entities.NodebInfo) error {
        connectionStatus := nodebInfo.GetConnectionStatus()
 
        if connectionStatus == entities.ConnectionStatus_SHUT_DOWN {
-               m.logger.Warnf("#RanReconnectionManager.ReconnectRan - RAN name: %s - Cannot reconnect RAN. Reason: connection status is SHUT_DOWN", nodebInfo.RanName)
+               m.logger.Warnf("#RanReconnectionManager.updateUnconnectableRan - RAN name: %s - Cannot reconnect RAN. Reason: connection status is SHUT_DOWN", nodebInfo.RanName)
                return nil
        }
 
        if connectionStatus == entities.ConnectionStatus_SHUTTING_DOWN {
-               m.logger.Warnf("#RanReconnectionManager.ReconnectRan - RAN name: %s - Cannot reconnect RAN. Reason: connection status is SHUTTING_DOWN", nodebInfo.RanName)
-               return m.updateNodebInfoStatus(nodebInfo, entities.ConnectionStatus_SHUT_DOWN)
+               m.logger.Warnf("#RanReconnectionManager.updateUnconnectableRan - RAN name: %s - Cannot reconnect RAN. Reason: connection status is SHUTTING_DOWN", nodebInfo.RanName)
+               return m.updateNodebInfo(nodebInfo, entities.ConnectionStatus_SHUT_DOWN, false)
        }
 
-       if int(nodebInfo.GetConnectionAttempts()) >= m.config.MaxConnectionAttempts {
-               m.logger.Warnf("#RanReconnectionManager.ReconnectRan - RAN name: %s - Cannot reconnect RAN. Reason: RAN's connection attempts exceeded the limit (%d)", nodebInfo.RanName, m.config.MaxConnectionAttempts)
-               return m.updateNodebInfoStatus(nodebInfo, entities.ConnectionStatus_DISCONNECTED)
+       if m.isRanExceededConnectionAttempts(nodebInfo) {
+               m.logger.Warnf("#RanReconnectionManager.updateUnconnectableRan - RAN name: %s - Cannot reconnect RAN. Reason: RAN's connection attempts exceeded the limit (%d)", nodebInfo.RanName, m.config.MaxConnectionAttempts)
+               return m.updateNodebInfo(nodebInfo, entities.ConnectionStatus_DISCONNECTED, true)
        }
 
        return nil
index 9ccb1fd..44a3c78 100644 (file)
@@ -24,14 +24,12 @@ import (
        "e2mgr/configuration"
        "e2mgr/logger"
        "e2mgr/mocks"
-       "e2mgr/rNibWriter"
        "e2mgr/rmrCgo"
        "e2mgr/services"
        "e2mgr/services/rmrsender"
        "e2mgr/tests"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
-       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
        "github.com/pkg/errors"
        "github.com/stretchr/testify/assert"
        "github.com/stretchr/testify/mock"
@@ -49,19 +47,37 @@ func initRanLostConnectionTest(t *testing.T) (*logger.Logger, *mocks.RmrMessenge
        rmrSender := initRmrSender(rmrMessengerMock, logger)
 
        readerMock := &mocks.RnibReaderMock{}
-       rnibReaderProvider := func() reader.RNibReader {
-               return readerMock
-       }
+
        writerMock := &mocks.RnibWriterMock{}
-       rnibWriterProvider := func() rNibWriter.RNibWriter {
-               return writerMock
-       }
-       rnibDataService := services.NewRnibDataService(logger, config, rnibReaderProvider, rnibWriterProvider)
+
+       rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
+       e2tInstancesManager := NewE2TInstancesManager(rnibDataService, logger)
        ranSetupManager := NewRanSetupManager(logger, rmrSender, rnibDataService)
-       ranReconnectionManager := NewRanReconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, ranSetupManager)
+       ranReconnectionManager := NewRanReconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, ranSetupManager, e2tInstancesManager)
        return logger, rmrMessengerMock, readerMock, writerMock, ranReconnectionManager
 }
 
+func initRanLostConnectionTestBasicMocks(t *testing.T) (*logger.Logger, *mocks.RmrMessengerMock, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *RanReconnectionManager, *mocks.E2TInstancesManagerMock) {
+       logger, err := logger.InitLogger(logger.DebugLevel)
+       if err != nil {
+               t.Errorf("#... - failed to initialize logger, error: %s", err)
+       }
+       config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
+
+       rmrMessengerMock := &mocks.RmrMessengerMock{}
+       rmrSender := initRmrSender(rmrMessengerMock, logger)
+
+       readerMock := &mocks.RnibReaderMock{}
+
+       writerMock := &mocks.RnibWriterMock{}
+
+       rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
+       e2tInstancesManagerMock := &mocks.E2TInstancesManagerMock{}
+       ranSetupManager := NewRanSetupManager(logger, rmrSender, rnibDataService)
+       ranReconnectionManager := NewRanReconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, ranSetupManager, e2tInstancesManagerMock)
+       return logger, rmrMessengerMock, readerMock, writerMock, ranReconnectionManager, e2tInstancesManagerMock
+}
+
 func TestRanReconnectionGetNodebFailure(t *testing.T) {
        _, _, readerMock, writerMock, ranReconnectionManager := initRanLostConnectionTest(t)
        ranName := "test"
@@ -100,21 +116,48 @@ func TestShuttingdownRanReconnection(t *testing.T) {
        writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1)
 }
 
-func TestConnectingRanWithMaxAttemptsReconnection(t *testing.T) {
+func TestConnectingRanWithMaxAttemptsReconnectionDissociateSucceeds(t *testing.T) {
        _, _, readerMock, writerMock, ranReconnectionManager := initRanLostConnectionTest(t)
        ranName := "test"
-       origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_CONNECTING, ConnectionAttempts: 20}
+       e2tAddress := "10.0.2.15"
+       origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_CONNECTING, ConnectionAttempts: 20, AssociatedE2TInstanceAddress: e2tAddress}
        var rnibErr error
        readerMock.On("GetNodeb", ranName).Return(origNodebInfo, rnibErr)
        updatedNodebInfo := *origNodebInfo
        updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
+       updatedNodebInfo.AssociatedE2TInstanceAddress = ""
        writerMock.On("UpdateNodebInfo", &updatedNodebInfo).Return(rnibErr)
+       e2tInstance := &entities.E2TInstance{Address:e2tAddress, AssociatedRanList:[]string{ranName}}
+       readerMock.On("GetE2TInstance",e2tAddress).Return(e2tInstance, nil)
+       e2tInstanceToSave := * e2tInstance
+       e2tInstanceToSave .AssociatedRanList = []string{}
+       writerMock.On("SaveE2TInstance", &e2tInstanceToSave).Return(nil)
        err := ranReconnectionManager.ReconnectRan(ranName)
        assert.Nil(t, err)
        readerMock.AssertCalled(t, "GetNodeb", ranName)
        writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1)
 }
 
+func TestConnectingRanWithMaxAttemptsReconnectionDissociateFails(t *testing.T) {
+       _, _, readerMock, writerMock, ranReconnectionManager := initRanLostConnectionTest(t)
+       ranName := "test"
+       e2tAddress := "10.0.2.15"
+       origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_CONNECTING, ConnectionAttempts: 20, AssociatedE2TInstanceAddress: e2tAddress}
+       var rnibErr error
+       readerMock.On("GetNodeb", ranName).Return(origNodebInfo, rnibErr)
+       updatedNodebInfo := *origNodebInfo
+       updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
+       updatedNodebInfo.AssociatedE2TInstanceAddress = ""
+       writerMock.On("UpdateNodebInfo", &updatedNodebInfo).Return(rnibErr)
+       e2tInstance := &entities.E2TInstance{Address:e2tAddress, AssociatedRanList:[]string{ranName}}
+       readerMock.On("GetE2TInstance",e2tAddress).Return(e2tInstance, common.NewInternalError(errors.New("Error")))
+       err := ranReconnectionManager.ReconnectRan(ranName)
+       assert.NotNil(t, err)
+       readerMock.AssertCalled(t, "GetNodeb", ranName)
+       writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1)
+       writerMock.AssertNotCalled(t, "SaveE2TInstance", )
+}
+
 func TestUnconnectableRanUpdateNodebInfoFailure(t *testing.T) {
        _, _, readerMock, writerMock, ranReconnectionManager := initRanLostConnectionTest(t)
        ranName := "test"
@@ -140,7 +183,7 @@ func TestConnectedRanExecuteSetupSuccess(t *testing.T) {
        updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_CONNECTING
        updatedNodebInfo.ConnectionAttempts++
        writerMock.On("UpdateNodebInfo", &updatedNodebInfo).Return(nil)
-       rmrMessengerMock.On("SendMsg", mock.Anything).Return(&rmrCgo.MBuf{}, nil)
+       rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(&rmrCgo.MBuf{}, nil)
        err := ranReconnectionManager.ReconnectRan(ranName)
        assert.Nil(t, err)
        readerMock.AssertCalled(t, "GetNodeb", ranName)
@@ -164,8 +207,15 @@ func TestConnectedRanExecuteSetupFailure(t *testing.T) {
        writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1)
 }
 
+func TestNoSetConnectionStatus(t *testing.T) {
+       _, _, _, _, ranReconnectionManager := initRanLostConnectionTest(t)
+       nodebInfo := &entities.NodebInfo{RanName: "ranName", GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_CONNECTED}
+       err := ranReconnectionManager.updateUnconnectableRan(nodebInfo)
+       assert.Nil(t, err)
+}
+
 func initRmrSender(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *rmrsender.RmrSender {
        rmrMessenger := rmrCgo.RmrMessenger(rmrMessengerMock)
        rmrMessengerMock.On("Init", tests.GetPort(), tests.MaxMsgSize, tests.Flags, log).Return(&rmrMessenger)
-       return rmrsender.NewRmrSender(log, &rmrMessenger)
+       return rmrsender.NewRmrSender(log, rmrMessenger)
 }
index 40b4d00..de54308 100644 (file)
@@ -37,6 +37,10 @@ type RanSetupManager struct {
        rmrSender       *rmrsender.RmrSender
 }
 
+type IRanSetupManager interface {
+       ExecuteSetup(nodebInfo *entities.NodebInfo, status entities.ConnectionStatus) error
+}
+
 func NewRanSetupManager(logger *logger.Logger, rmrSender *rmrsender.RmrSender, rnibDataService services.RNibDataService) *RanSetupManager {
        return &RanSetupManager{
                logger:          logger,
@@ -105,7 +109,8 @@ func (m *RanSetupManager) ExecuteSetup(nodebInfo *entities.NodebInfo, status ent
        }
 
        // Send the endc/x2 setup request
-       msg := models.NewRmrMessage(rmrMsgType, nodebInfo.RanName, request.GetMessageAsBytes(m.logger))
+       var xAction []byte
+       msg := models.NewRmrMessage(rmrMsgType, nodebInfo.RanName, request.GetMessageAsBytes(m.logger), xAction)
 
        err = m.rmrSender.Send(msg)
 
index 4ea7919..4178062 100644 (file)
@@ -26,13 +26,11 @@ import (
        "e2mgr/e2pdus"
        "e2mgr/logger"
        "e2mgr/mocks"
-       "e2mgr/rNibWriter"
        "e2mgr/rmrCgo"
        "e2mgr/services"
        "fmt"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
-       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
        "github.com/stretchr/testify/assert"
        "github.com/stretchr/testify/mock"
        "testing"
@@ -49,14 +47,10 @@ func initRanSetupManagerTest(t *testing.T) (*mocks.RmrMessengerMock, *mocks.Rnib
        rmrSender := initRmrSender(rmrMessengerMock, logger)
 
        readerMock := &mocks.RnibReaderMock{}
-       rnibReaderProvider := func() reader.RNibReader {
-               return readerMock
-       }
+
        writerMock := &mocks.RnibWriterMock{}
-       rnibWriterProvider := func() rNibWriter.RNibWriter {
-               return writerMock
-       }
-       rnibDataService := services.NewRnibDataService(logger, config, rnibReaderProvider, rnibWriterProvider)
+
+       rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
        ranSetupManager := NewRanSetupManager(logger, rmrSender, rnibDataService)
        return rmrMessengerMock, writerMock, ranSetupManager
 }
@@ -74,7 +68,7 @@ func TestExecuteSetupConnectingX2Setup(t *testing.T) {
        payload := e2pdus.PackedX2setupRequest
        xaction := []byte(ranName)
        msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ranName, &payload, &xaction)
-       rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, nil)
+       rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg, nil)
 
        if err := mgr.ExecuteSetup(initialNodeb, entities.ConnectionStatus_CONNECTING); err != nil {
                t.Errorf("want: success, got: error: %s", err)
@@ -97,7 +91,7 @@ func TestExecuteSetupConnectingEndcX2Setup(t *testing.T) {
        payload := e2pdus.PackedEndcX2setupRequest
        xaction := []byte(ranName)
        msg := rmrCgo.NewMBuf(rmrCgo.RIC_ENDC_X2_SETUP_REQ, len(payload), ranName, &payload, &xaction)
-       rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, nil)
+       rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg, nil)
 
        if err := mgr.ExecuteSetup(initialNodeb, entities.ConnectionStatus_CONNECTING); err != nil {
                t.Errorf("want: success, got: error: %s", err)
@@ -122,7 +116,7 @@ func TestExecuteSetupDisconnected(t *testing.T) {
        payload := []byte{0}
        xaction := []byte(ranName)
        msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ranName, &payload, &xaction)
-       rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, fmt.Errorf("send failure"))
+       rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg, fmt.Errorf("send failure"))
 
        if err := mgr.ExecuteSetup(initialNodeb, entities.ConnectionStatus_CONNECTING); err == nil {
                t.Errorf("want: failure, got: success")
@@ -147,7 +141,7 @@ func TestExecuteSetupConnectingRnibError(t *testing.T) {
        payload := []byte{0}
        xaction := []byte(ranName)
        msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ranName, &payload, &xaction)
-       rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, fmt.Errorf("send failure"))
+       rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg, fmt.Errorf("send failure"))
 
        if err := mgr.ExecuteSetup(initialNodeb, entities.ConnectionStatus_CONNECTING); err == nil {
                t.Errorf("want: failure, got: success")
@@ -174,7 +168,7 @@ func TestExecuteSetupDisconnectedRnibError(t *testing.T) {
        payload := []byte{0}
        xaction := []byte(ranName)
        msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ranName, &payload, &xaction)
-       rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, fmt.Errorf("send failure"))
+       rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg, fmt.Errorf("send failure"))
 
        if err := mgr.ExecuteSetup(initialNodeb, entities.ConnectionStatus_CONNECTING); err == nil {
                t.Errorf("want: failure, got: success")
@@ -199,7 +193,7 @@ func TestExecuteSetupUnsupportedProtocol(t *testing.T) {
        payload := e2pdus.PackedX2setupRequest
        xaction := []byte(ranName)
        msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ranName, &payload, &xaction)
-       rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, nil)
+       rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg, nil)
 
        if err := mgr.ExecuteSetup(initialNodeb, entities.ConnectionStatus_CONNECTING); err == nil {
                t.Errorf("want: error, got: success")
index 153255a..049cc86 100644 (file)
@@ -35,6 +35,7 @@ func (m *RanStatusChangeManager) Execute(msgType int, msgDirection enums.Message
                return err
        }
 
-       rmrMessage := models.NewRmrMessage(msgType, nodebInfo.RanName, resourceStatusJson)
+       var xAction []byte
+       rmrMessage := models.NewRmrMessage(msgType, nodebInfo.RanName, resourceStatusJson, xAction)
        return m.rmrSender.Send(rmrMessage)
 }
index be8642e..ea9bfcd 100644 (file)
@@ -40,7 +40,7 @@ func TestMarshalSuccess(t *testing.T) {
 
        nodebInfo := entities.NodebInfo{NodeType: entities.Node_ENB}
        var err error
-       rmrMessengerMock.On("SendMsg", mock.Anything).Return(&rmrCgo.MBuf{}, err)
+       rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(&rmrCgo.MBuf{}, err)
        err  = m.Execute(rmrCgo.RAN_CONNECTED, enums.RIC_TO_RAN, &nodebInfo)
 
        assert.Nil(t, err)
diff --git a/E2Manager/managers/x2_setup_failure_response_manager_test.go b/E2Manager/managers/x2_setup_failure_response_manager_test.go
new file mode 100644 (file)
index 0000000..b5e1849
--- /dev/null
@@ -0,0 +1,57 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+package managers
+
+import (
+       "e2mgr/converters"
+       "e2mgr/tests"
+       "fmt"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+       "github.com/stretchr/testify/assert"
+       "testing"
+)
+
+func TestPopulateX2NodebByPduFailure(t *testing.T) {
+       logger := tests.InitLog(t)
+       nodebInfo := &entities.NodebInfo{}
+       nodebIdentity := &entities.NbIdentity{}
+       handler := NewX2SetupFailureResponseManager(converters.NewX2SetupFailureResponseConverter(logger))
+       err := handler.PopulateNodebByPdu(logger, nodebIdentity, nodebInfo, createRandomPayload())
+       assert.NotNil(t, err)
+}
+
+func TestPopulateX2NodebByPduSuccess(t *testing.T) {
+       logger := tests.InitLog(t)
+       nodebInfo := &entities.NodebInfo{}
+       nodebIdentity := &entities.NbIdentity{}
+       handler := NewX2SetupFailureResponseManager(converters.NewX2SetupFailureResponseConverter(logger))
+       err := handler.PopulateNodebByPdu(logger, nodebIdentity, nodebInfo, createX2SetupFailureResponsePayload(t))
+       assert.Nil(t, err)
+       assert.Equal(t, entities.ConnectionStatus_CONNECTED_SETUP_FAILED, nodebInfo.ConnectionStatus)
+       assert.Equal(t, entities.Failure_X2_SETUP_FAILURE, nodebInfo.FailureType)
+
+}
+
+func createX2SetupFailureResponsePayload(t *testing.T) []byte {
+       packedPdu := "4006001a0000030005400200000016400100001140087821a00000008040"
+       var payload []byte
+       _, err := fmt.Sscanf(packedPdu, "%x", &payload)
+       if err != nil {
+               t.Errorf("convert inputPayloadAsStr to payloadAsByte. Error: %v\n", err)
+       }
+       return payload
+}
diff --git a/E2Manager/mocks/controllerMock.go b/E2Manager/mocks/controllerMock.go
deleted file mode 100644 (file)
index 7575f72..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-package mocks
-
-import (
-       "github.com/gorilla/mux"
-       "github.com/stretchr/testify/mock"
-       "net/http"
-)
-
-type ControllerMock struct {
-       mock.Mock
-}
-
-func (c *ControllerMock) GetNodeb(writer http.ResponseWriter, r *http.Request){
-               writer.Header().Set("Content-Type", "application/json")
-               writer.WriteHeader(http.StatusOK)
-
-               vars := mux.Vars(r)
-               ranName := vars["ranName"]
-
-               writer.Write([]byte(ranName))
-
-               c.Called()
-}
-
-func (c *ControllerMock) GetNodebIdList(writer http.ResponseWriter, r *http.Request){
-       c.Called()
-}
-
-
-func (c *ControllerMock) Shutdown(writer http.ResponseWriter, r *http.Request){
-       c.Called()
-}
-
-func (c *ControllerMock) X2Reset(writer http.ResponseWriter, r *http.Request){
-       writer.Header().Set("Content-Type", "application/json")
-       writer.WriteHeader(http.StatusOK)
-
-       vars := mux.Vars(r)
-       ranName := vars["ranName"]
-
-       writer.Write([]byte(ranName))
-
-       c.Called()
-}
-
-func (c *ControllerMock) X2Setup(writer http.ResponseWriter, r *http.Request){
-       writer.Header().Set("Content-Type", "application/json")
-       writer.WriteHeader(http.StatusOK)
-
-       c.Called()
-}
-
-func (c *ControllerMock) EndcSetup(writer http.ResponseWriter, r *http.Request){
-       writer.Header().Set("Content-Type", "application/json")
-       writer.WriteHeader(http.StatusOK)
-
-       c.Called()
-}
\ No newline at end of file
diff --git a/E2Manager/mocks/e2t_controller_mock.go b/E2Manager/mocks/e2t_controller_mock.go
new file mode 100644 (file)
index 0000000..d72c292
--- /dev/null
@@ -0,0 +1,35 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package mocks
+
+import (
+       "github.com/stretchr/testify/mock"
+       "net/http"
+)
+
+type E2TControllerMock struct {
+       mock.Mock
+}
+
+func (m *E2TControllerMock) HandleRequest(writer http.ResponseWriter, request *http.Request) {
+       m.Called()
+}
+
+func (m *E2TControllerMock) GetE2TInstances(writer http.ResponseWriter, request *http.Request) {
+       m.Called()
+}
diff --git a/E2Manager/mocks/e2t_instances_manager_mock.go b/E2Manager/mocks/e2t_instances_manager_mock.go
new file mode 100644 (file)
index 0000000..235c76a
--- /dev/null
@@ -0,0 +1,82 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+package mocks
+
+import (
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+       "github.com/stretchr/testify/mock"
+)
+
+type E2TInstancesManagerMock struct {
+       mock.Mock
+}
+
+func (m *E2TInstancesManagerMock) GetE2TInstance(e2tAddress string) (*entities.E2TInstance, error) {
+       args := m.Called(e2tAddress)
+
+       return args.Get(0).(*entities.E2TInstance), args.Error(1)
+}
+
+func (m *E2TInstancesManagerMock) AddE2TInstance(e2tInstanceAddress string) error {
+       args := m.Called(e2tInstanceAddress)
+       return args.Error(0)
+}
+
+func (m *E2TInstancesManagerMock) RemoveE2TInstance(e2tInstance *entities.E2TInstance) error {
+       args := m.Called(e2tInstance)
+       return args.Error(0)
+}
+
+func (m *E2TInstancesManagerMock) SelectE2TInstance() (string, error) {
+       args := m.Called()
+       return args.String(0), args.Error(1)
+}
+
+func (m *E2TInstancesManagerMock) AssociateRan(ranName string, e2tAddress string) error {
+       args := m.Called(ranName, e2tAddress)
+       return args.Error(0)
+
+}
+func (m *E2TInstancesManagerMock) DissociateRan(ranName string, e2tAddress string) error {
+       args := m.Called(ranName, e2tAddress)
+       return args.Error(0)
+
+}
+
+func (m *E2TInstancesManagerMock) GetE2TInstances() ([]*entities.E2TInstance, error) {
+       args := m.Called()
+
+       return args.Get(0).([]*entities.E2TInstance), args.Error(1)
+}
+
+func (m *E2TInstancesManagerMock) GetE2TInstancesNoLogs() ([]*entities.E2TInstance, error) {
+       args := m.Called()
+
+       return args.Get(0).([]*entities.E2TInstance), args.Error(1)
+}
+
+func (m *E2TInstancesManagerMock) ResetKeepAliveTimestamp(e2tAddress string) error {
+       args := m.Called(e2tAddress)
+       return args.Error(0)
+
+}
+
+func (m *E2TInstancesManagerMock) ActivateE2TInstance(e2tInstance *entities.E2TInstance) error {
+       args := m.Called(e2tInstance)
+       return args.Error(0)
+
+}
\ No newline at end of file
similarity index 56%
rename from E2Manager/rnibBuilders/node_info_builder.go
rename to E2Manager/mocks/e2t_shutdown_manager_mock.go
index bfee4f6..c560f1d 100644 (file)
 //  platform project (RICP).
 
 
-package rnibBuilders
+package mocks
 
 import (
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
-       "e2mgr/models"
+       "github.com/stretchr/testify/mock"
 )
 
-func CreateInitialNodeInfo(requestDetails *models.SetupRequest, protocol entities.E2ApplicationProtocol) (*entities.NodebInfo, *entities.NbIdentity) {
-       nodebInfo := &entities.NodebInfo{}
-       nodebInfo.Ip = requestDetails.RanIp
-       nodebInfo.Port = uint32(requestDetails.RanPort)
-       nodebInfo.ConnectionStatus = entities.ConnectionStatus_CONNECTING
-       nodebInfo.E2ApplicationProtocol = protocol
-       nodebInfo.RanName = requestDetails.RanName
-       nodebInfo.ConnectionAttempts = 0
+type E2TShutdownManagerMock struct {
+       mock.Mock
+}
 
-       nodebIdentity := &entities.NbIdentity{}
-       nodebIdentity.InventoryName = requestDetails.RanName
-       return nodebInfo, nodebIdentity
+func (m *E2TShutdownManagerMock) Shutdown(e2tInstance *entities.E2TInstance) error {
+       args := m.Called(e2tInstance)
+       return args.Error(0)
 }
\ No newline at end of file
diff --git a/E2Manager/mocks/http_client_mock.go b/E2Manager/mocks/http_client_mock.go
new file mode 100644 (file)
index 0000000..1294c48
--- /dev/null
@@ -0,0 +1,41 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+
+package mocks
+
+import (
+       "github.com/stretchr/testify/mock"
+       "io"
+       "net/http"
+)
+
+type HttpClientMock struct {
+       mock.Mock
+}
+
+func (c *HttpClientMock) Post(url, contentType string, body io.Reader) (resp *http.Response, err error) {
+               args := c.Called(url, contentType, body)
+               return args.Get(0).(*http.Response), args.Error(1)
+}
+
+//func (c *HttpClientMock) Do(req *http.Request) (*http.Response, error) {
+//     args := c.Called(req)
+//     return args.Get(0).(*http.Response), args.Error(1)
+//}
diff --git a/E2Manager/mocks/nodebControllerMock.go b/E2Manager/mocks/nodebControllerMock.go
deleted file mode 100644 (file)
index 51b5bf0..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-package mocks
-
-import (
-       "github.com/gorilla/mux"
-       "github.com/stretchr/testify/mock"
-       "net/http"
-)
-
-type NodebControllerMock struct {
-       mock.Mock
-}
-
-func (rc *NodebControllerMock) HandleRequest(writer http.ResponseWriter, request *http.Request) {
-       rc.Called()
-}
-
-func (rc *NodebControllerMock) GetNodebIdList (writer http.ResponseWriter, request *http.Request) {
-       rc.Called()
-}
-
-func (rc *NodebControllerMock) GetNodeb(writer http.ResponseWriter, request *http.Request) {
-       writer.Header().Set("Content-Type", "application/json")
-       writer.WriteHeader(http.StatusOK)
-
-       vars := mux.Vars(request)
-       ranName := vars["ranName"]
-
-       writer.Write([]byte(ranName))
-
-       rc.Called()
-}
-
-func (rc *NodebControllerMock) HandleHealthCheckRequest(writer http.ResponseWriter, request *http.Request) {
-       rc.Called()
-}
diff --git a/E2Manager/mocks/nodeb_controller_mock.go b/E2Manager/mocks/nodeb_controller_mock.go
new file mode 100644 (file)
index 0000000..eafc935
--- /dev/null
@@ -0,0 +1,73 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package mocks
+
+import (
+       "github.com/gorilla/mux"
+       "github.com/stretchr/testify/mock"
+       "net/http"
+)
+
+type NodebControllerMock struct {
+       mock.Mock
+}
+
+func (c *NodebControllerMock) GetNodeb(writer http.ResponseWriter, r *http.Request) {
+       writer.Header().Set("Content-Type", "application/json")
+       writer.WriteHeader(http.StatusOK)
+
+       vars := mux.Vars(r)
+       ranName := vars["ranName"]
+
+       writer.Write([]byte(ranName))
+       c.Called()
+}
+
+func (c *NodebControllerMock) GetNodebIdList(writer http.ResponseWriter, r *http.Request) {
+       c.Called()
+}
+
+func (c *NodebControllerMock) Shutdown(writer http.ResponseWriter, r *http.Request) {
+       c.Called()
+}
+
+func (c *NodebControllerMock) X2Reset(writer http.ResponseWriter, r *http.Request) {
+       writer.Header().Set("Content-Type", "application/json")
+       writer.WriteHeader(http.StatusOK)
+
+       vars := mux.Vars(r)
+       ranName := vars["ranName"]
+
+       writer.Write([]byte(ranName))
+
+       c.Called()
+}
+
+func (c *NodebControllerMock) X2Setup(writer http.ResponseWriter, r *http.Request) {
+       writer.Header().Set("Content-Type", "application/json")
+       writer.WriteHeader(http.StatusOK)
+
+       c.Called()
+}
+
+func (c *NodebControllerMock) EndcSetup(writer http.ResponseWriter, r *http.Request) {
+       writer.Header().Set("Content-Type", "application/json")
+       writer.WriteHeader(http.StatusOK)
+
+       c.Called()
+}
diff --git a/E2Manager/mocks/ran_setup_manager_mock.go b/E2Manager/mocks/ran_setup_manager_mock.go
new file mode 100644 (file)
index 0000000..656657c
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+package mocks
+
+import (
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+       "github.com/stretchr/testify/mock"
+)
+
+type RanSetupManagerMock struct {
+       mock.Mock
+}
+
+func (m *RanSetupManagerMock) ExecuteSetup(nodebInfo *entities.NodebInfo, status entities.ConnectionStatus) error {
+       args := m.Called(nodebInfo, status)
+
+       return args.Error(0)
+}
index dccd7d0..b517fe9 100644 (file)
@@ -30,13 +30,13 @@ type RmrMessengerMock struct {
        mock.Mock
 }
 
-func (m *RmrMessengerMock) Init(port string, maxMsgSize int, flags int, logger *logger.Logger) *rmrCgo.RmrMessenger{
+func (m *RmrMessengerMock) Init(port string, maxMsgSize int, flags int, logger *logger.Logger) rmrCgo.RmrMessenger{
        args := m.Called(port, maxMsgSize, flags, logger)
-       return args.Get(0).(*rmrCgo.RmrMessenger)
+       return args.Get(0).(rmrCgo.RmrMessenger)
 }
 
-func (m *RmrMessengerMock) SendMsg(msg *rmrCgo.MBuf) (*rmrCgo.MBuf, error){
-       args := m.Called(msg)
+func (m *RmrMessengerMock) SendMsg(msg *rmrCgo.MBuf, printLogs bool) (*rmrCgo.MBuf, error){
+       args := m.Called(msg, printLogs)
        return args.Get(0).(*rmrCgo.MBuf), args.Error(1)
 }
 
index 237cdac..59c635e 100644 (file)
@@ -32,7 +32,6 @@ func (m *RnibReaderMock) GetNodeb(inventoryName string) (*entities.NodebInfo, er
        args := m.Called(inventoryName)
 
        errArg := args.Get(1);
-
        if errArg != nil {
                return args.Get(0).(*entities.NodebInfo), errArg.(error);
        }
@@ -44,7 +43,6 @@ func (m *RnibReaderMock) GetNodebByGlobalNbId(nodeType entities.Node_Type, globa
        args := m.Called(nodeType, globalNbId)
 
        errArg := args.Get(1);
-
        if errArg != nil {
                return args.Get(0).(*entities.NodebInfo), errArg.(error);
        }
@@ -56,7 +54,6 @@ func (m *RnibReaderMock) GetCellList(inventoryName string) (*entities.Cells, err
        args := m.Called(inventoryName)
 
        errArg := args.Get(1);
-
        if errArg != nil {
                return args.Get(0).(*entities.Cells), errArg.(error);
        }
@@ -68,7 +65,6 @@ func (m *RnibReaderMock) GetListGnbIds() ([]*entities.NbIdentity, error) {
        args := m.Called()
 
        errArg := args.Get(1);
-
        if errArg != nil {
                return args.Get(0).([]*entities.NbIdentity), errArg.(error);
        }
@@ -80,7 +76,6 @@ func (m *RnibReaderMock) GetListEnbIds() ([]*entities.NbIdentity, error) {
        args := m.Called()
 
        errArg := args.Get(1);
-
        if errArg != nil {
                return args.Get(0).([]*entities.NbIdentity), errArg.(error);
        }
@@ -93,7 +88,6 @@ func (m *RnibReaderMock) GetCountGnbList() (int, error) {
        args := m.Called()
 
        errArg := args.Get(1);
-
        if errArg != nil {
                return args.Int(0), errArg.(error);
        }
@@ -106,7 +100,6 @@ func (m *RnibReaderMock) GetCell(inventoryName string, pci uint32) (*entities.Ce
        args := m.Called(inventoryName, pci)
 
        errArg := args.Get(1);
-
        if errArg != nil {
                return args.Get(0).(*entities.Cell), errArg.(error);
        }
@@ -118,7 +111,6 @@ func (m *RnibReaderMock) GetCellById(cellType entities.Cell_Type, cellId string)
        args := m.Called(cellType, cellId)
 
        errArg := args.Get(1);
-
        if errArg != nil {
                return args.Get(0).(*entities.Cell), errArg.(error);
        }
@@ -149,3 +141,18 @@ func (m *RnibReaderMock) GetRanLoadInformation(inventoryName string) (*entities.
 
        return args.Get(0).(*entities.RanLoadInformation), nil
 }
+
+func (m *RnibReaderMock) GetE2TInstance(e2taddress string) (*entities.E2TInstance, error) {
+       args := m.Called(e2taddress)
+       return args.Get(0).(*entities.E2TInstance), args.Error(1)
+}
+
+func (m *RnibReaderMock) GetE2TInstances(addresses []string) ([]*entities.E2TInstance, error) {
+       args := m.Called(addresses)
+       return args.Get(0).([]*entities.E2TInstance), args.Error(1)
+}
+
+func (m *RnibReaderMock) GetE2TAddresses() ([]string, error) {
+       args := m.Called()
+       return args.Get(0).([]string), args.Error(1)
+}
index 53ec47a..5ca925f 100644 (file)
@@ -64,3 +64,15 @@ func (rnibWriterMock *RnibWriterMock) SaveRanLoadInformation(inventoryName strin
 
        return nil
 }
+
+func (rnibWriterMock *RnibWriterMock) SaveE2TInstance(e2tInstance *entities.E2TInstance) error {
+       args := rnibWriterMock.Called(e2tInstance)
+
+       return args.Error(0)
+}
+
+func (rnibWriterMock *RnibWriterMock) SaveE2TAddresses(addresses []string) error {
+       args := rnibWriterMock.Called(addresses)
+
+       return args.Error(0)
+}
diff --git a/E2Manager/mocks/root_controller_mock.go b/E2Manager/mocks/root_controller_mock.go
new file mode 100644 (file)
index 0000000..df58b61
--- /dev/null
@@ -0,0 +1,31 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package mocks
+
+import (
+       "github.com/stretchr/testify/mock"
+       "net/http"
+)
+
+type RootControllerMock struct {
+       mock.Mock
+}
+
+func (rc *RootControllerMock) HandleHealthCheckRequest(writer http.ResponseWriter, request *http.Request) {
+       rc.Called()
+}
diff --git a/E2Manager/mocks/routing_manager_client_mock.go b/E2Manager/mocks/routing_manager_client_mock.go
new file mode 100644 (file)
index 0000000..24edd55
--- /dev/null
@@ -0,0 +1,46 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+package mocks
+
+import (
+       "github.com/stretchr/testify/mock"
+)
+
+type RoutingManagerClientMock struct {
+       mock.Mock
+}
+
+func (m *RoutingManagerClientMock) AddE2TInstance(e2tAddress string) error {
+
+       args := m.Called(e2tAddress)
+       return args.Error(0)
+}
+
+func (m *RoutingManagerClientMock) AssociateRanToE2TInstance(e2tAddress string, ranName string) error {
+
+       args := m.Called(e2tAddress, ranName)
+       return args.Error(0)
+}
+
+func (m *RoutingManagerClientMock) DissociateRanE2TInstance(e2tAddress string, ranName string) error {
+
+       args := m.Called(e2tAddress, ranName)
+       return args.Error(0)
+}
\ No newline at end of file
index eac92b0..e7ca8c7 100644 (file)
 //  platform project (RICP).
 
 
-package models
+package models_test
 
 import (
        "e2mgr/logger"
+       "e2mgr/models"
        "e2mgr/tests"
        "encoding/hex"
        "github.com/stretchr/testify/assert"
@@ -29,12 +30,12 @@ import (
 )
 
 const transactionId = "transactionId"
-const expectedMessageAsBytesHex = "31302e302e302e337c353535357c746573747c347c01020304"
+const expectedMessageAsBytesHex = "31302e302e302e337c333830317c746573747c347c01020304"
 
 func TestNewE2RequestMessage(t *testing.T){
-       e2 :=NewE2RequestMessage(transactionId, tests.RanIp, uint16(tests.Port), tests.RanName, tests.DummyPayload)
+       e2 :=models.NewE2RequestMessage(transactionId, tests.RanIp, uint16(tests.Port), tests.RanName, tests.DummyPayload)
        assert.NotNil(t, e2)
-       assert.IsType(t, *e2, E2RequestMessage{})
+       assert.IsType(t, *e2, models.E2RequestMessage{})
        assert.Equal(t, tests.RanName, e2.RanName())
        assert.Equal(t, transactionId, e2.TransactionId())
 }
@@ -45,7 +46,7 @@ func TestGetMessageAsBytes(t *testing.T){
                t.Errorf("#nodeb_controller_test.TestHandleRequestSuccess - failed to initialize logger, error: %s", err)
        }
 
-       e2 :=NewE2RequestMessage(transactionId, tests.RanIp, uint16(tests.Port), tests.RanName, tests.DummyPayload)
+       e2 := models.NewE2RequestMessage(transactionId, tests.RanIp, uint16(tests.Port), tests.RanName, tests.DummyPayload)
        bytes := e2.GetMessageAsBytes(log)
        assert.Equal(t, expectedMessageAsBytesHex, hex.EncodeToString(bytes))
 }
\ No newline at end of file
diff --git a/E2Manager/models/e2_term_init_payload.go b/E2Manager/models/e2_term_init_payload.go
new file mode 100644 (file)
index 0000000..e533582
--- /dev/null
@@ -0,0 +1,22 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+package models
+
+type E2TermInitPayload struct {
+       Address string     `json:"address"`
+       Fqdn string     `json:"fqdn"`
+}
\ No newline at end of file
diff --git a/E2Manager/models/e2t_keep_alive_payload.go b/E2Manager/models/e2t_keep_alive_payload.go
new file mode 100644 (file)
index 0000000..cdc8ba6
--- /dev/null
@@ -0,0 +1,21 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+package models
+
+type E2TKeepAlivePayload struct {
+       Address string     `json:"address"`
+}
\ No newline at end of file
diff --git a/E2Manager/models/get_e2t_instances_response.go b/E2Manager/models/get_e2t_instances_response.go
new file mode 100644 (file)
index 0000000..f39c1ff
--- /dev/null
@@ -0,0 +1,49 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package models
+
+import (
+       "e2mgr/e2managererrors"
+       "encoding/json"
+)
+
+type E2TInstancesResponse []*E2TInstanceResponseModel
+
+type E2TInstanceResponseModel struct {
+       E2TAddress string   `json:"e2tAddress"`
+       RanNames   []string `json:"ranNames"`
+}
+
+func NewE2TInstanceResponseModel(e2tAddress string, ranNames []string) *E2TInstanceResponseModel {
+       return &E2TInstanceResponseModel{
+               E2TAddress: e2tAddress,
+               RanNames:   ranNames,
+       }
+}
+
+func (response E2TInstancesResponse) Marshal() ([]byte, error) {
+
+       data, err := json.Marshal(response)
+
+       if err != nil {
+               return nil, e2managererrors.NewInternalError()
+       }
+
+       return data, nil
+
+}
index dfafab5..7ed83aa 100644 (file)
@@ -36,13 +36,13 @@ func NewGetNodebIdListResponse(nodebIdList []*entities.NbIdentity) *GetNodebIdLi
        }
 }
 
-func (response *GetNodebIdListResponse) Marshal() (string, error) {
+func (response *GetNodebIdListResponse) Marshal() ([]byte, error) {
        pmList := utils.ConvertNodebIdListToProtoMessageList(response.nodebIdList)
        result, err := utils.MarshalProtoMessageListToJsonArray(pmList)
 
        if err != nil {
-               return "", e2managererrors.NewInternalError();
+               return nil, e2managererrors.NewInternalError();
        }
 
-       return result, nil
+       return []byte(result), nil
 }
index 9474465..1eaa32a 100644 (file)
@@ -36,14 +36,14 @@ func NewGetNodebResponse(nodebInfo *entities.NodebInfo) *GetNodebResponse {
        }
 }
 
-func (response *GetNodebResponse) Marshal() (string, error) {
+func (response *GetNodebResponse) Marshal() ([]byte, error) {
        m := jsonpb.Marshaler{}
        result, err := m.MarshalToString(response.nodebInfo)
 
        if err != nil {
-               return "", e2managererrors.NewInternalError()
+               return nil, e2managererrors.NewInternalError()
        }
 
-       return result, nil
+       return []byte(result), nil
 
 }
index 531fbbd..9620297 100644 (file)
@@ -21,5 +21,5 @@
 package models
 
 type IResponse interface {
-       Marshal() (string, error)
+       Marshal() ([]byte, error)
 }
index 7e3892a..b275587 100644 (file)
@@ -27,10 +27,10 @@ type NotificationRequest struct {
        Len           int
        Payload       []byte
        StartTime     time.Time
-       TransactionId string
+       TransactionId []byte
 }
 
-func NewNotificationRequest(ranName string, payload []byte, startTime time.Time, transactionId string) *NotificationRequest {
+func NewNotificationRequest(ranName string, payload []byte, startTime time.Time, transactionId []byte) *NotificationRequest {
        return &NotificationRequest{
                ranName,
                len(payload),
index 5fd39f8..1971b1e 100644 (file)
 
 package models
 
-import (
-       "e2mgr/logger"
-)
-
 type RmrMessage struct {
        MsgType int
        RanName string
        Payload []byte
+       XAction []byte
 }
 
-func NewRmrMessage(msgType int, ranName string, payload []byte) *RmrMessage {
+func NewRmrMessage(msgType int, ranName string, payload []byte, xAction []byte) *RmrMessage {
        return &RmrMessage{
                MsgType: msgType,
                RanName: ranName,
                Payload: payload,
+               XAction: xAction,
        }
 }
-
-func (response RmrMessage) GetMessageAsBytes(logger *logger.Logger) []byte {
-       return response.Payload
-}
diff --git a/E2Manager/models/routing_manager_e2t_data.go b/E2Manager/models/routing_manager_e2t_data.go
new file mode 100644 (file)
index 0000000..9e8e313
--- /dev/null
@@ -0,0 +1,41 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+package models
+
+type RoutingManagerE2TData struct {
+       E2TAddress  string   `json:"E2TAddress"`
+       RanNamelist []string `json:"ranNamelist,omitempty"`
+}
+
+func NewRoutingManagerE2TData (e2tAddress string, ranNameList ...string) *RoutingManagerE2TData {
+       data := &RoutingManagerE2TData{
+               E2TAddress: e2tAddress,
+       }
+
+       if len(ranNameList) == 0 {
+               return data
+       }
+
+       for _, ranName := range ranNameList {
+               data.RanNamelist = append(data.RanNamelist, ranName)
+       }
+
+       return data
+}
index 70c2327..1e601f9 100644 (file)
@@ -33,12 +33,13 @@ import (
 type IncomingRequest string
 
 const (
-       ShutdownRequest       IncomingRequest = "Shutdown"
-       ResetRequest          IncomingRequest = "Reset"
-       X2SetupRequest        IncomingRequest = "X2SetupRequest"
-       EndcSetupRequest      IncomingRequest = "EndcSetupRequest"
-       GetNodebRequest       IncomingRequest = "GetNodebRequest"
-       GetNodebIdListRequest IncomingRequest = "GetNodebIdListRequest"
+       ShutdownRequest        IncomingRequest = "Shutdown"
+       ResetRequest           IncomingRequest = "Reset"
+       X2SetupRequest         IncomingRequest = "X2SetupRequest"
+       EndcSetupRequest       IncomingRequest = "EndcSetupRequest"
+       GetNodebRequest        IncomingRequest = "GetNodebRequest"
+       GetNodebIdListRequest  IncomingRequest = "GetNodebIdListRequest"
+       GetE2TInstancesRequest IncomingRequest = "GetE2TInstancesRequest"
 )
 
 type IncomingRequestHandlerProvider struct {
@@ -46,23 +47,24 @@ type IncomingRequestHandlerProvider struct {
        logger     *logger.Logger
 }
 
-func NewIncomingRequestHandlerProvider(logger *logger.Logger, rmrSender *rmrsender.RmrSender, config *configuration.Configuration, rNibDataService services.RNibDataService, ranSetupManager *managers.RanSetupManager) *IncomingRequestHandlerProvider {
+func NewIncomingRequestHandlerProvider(logger *logger.Logger, rmrSender *rmrsender.RmrSender, config *configuration.Configuration, rNibDataService services.RNibDataService, ranSetupManager *managers.RanSetupManager, e2tInstancesManager managers.IE2TInstancesManager) *IncomingRequestHandlerProvider {
 
        return &IncomingRequestHandlerProvider{
-               requestMap: initRequestHandlerMap(logger, rmrSender, config, rNibDataService, ranSetupManager),
+               requestMap: initRequestHandlerMap(logger, rmrSender, config, rNibDataService, ranSetupManager, e2tInstancesManager),
                logger:     logger,
        }
 }
 
-func initRequestHandlerMap(logger *logger.Logger, rmrSender *rmrsender.RmrSender, config *configuration.Configuration, rNibDataService services.RNibDataService, ranSetupManager *managers.RanSetupManager) map[IncomingRequest]httpmsghandlers.RequestHandler {
+func initRequestHandlerMap(logger *logger.Logger, rmrSender *rmrsender.RmrSender, config *configuration.Configuration, rNibDataService services.RNibDataService, ranSetupManager *managers.RanSetupManager, e2tInstancesManager managers.IE2TInstancesManager) map[IncomingRequest]httpmsghandlers.RequestHandler {
 
        return map[IncomingRequest]httpmsghandlers.RequestHandler{
-               ShutdownRequest:  httpmsghandlers.NewDeleteAllRequestHandler(logger, rmrSender, config, rNibDataService), //TODO change to pointer
-               ResetRequest:     httpmsghandlers.NewX2ResetRequestHandler(logger, rmrSender, rNibDataService),
-               X2SetupRequest:   httpmsghandlers.NewSetupRequestHandler(logger, rNibDataService, ranSetupManager, entities.E2ApplicationProtocol_X2_SETUP_REQUEST),
-               EndcSetupRequest: httpmsghandlers.NewSetupRequestHandler(logger, rNibDataService, ranSetupManager, entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST), //TODO change to pointer
-               GetNodebRequest:  httpmsghandlers.NewGetNodebRequestHandler(logger, rNibDataService),
-               GetNodebIdListRequest: httpmsghandlers.NewGetNodebIdListRequestHandler(logger, rNibDataService),
+               ShutdownRequest:        httpmsghandlers.NewDeleteAllRequestHandler(logger, rmrSender, config, rNibDataService), //TODO change to pointer
+               ResetRequest:           httpmsghandlers.NewX2ResetRequestHandler(logger, rmrSender, rNibDataService),
+               X2SetupRequest:         httpmsghandlers.NewSetupRequestHandler(logger, rNibDataService, ranSetupManager, entities.E2ApplicationProtocol_X2_SETUP_REQUEST, e2tInstancesManager),
+               EndcSetupRequest:       httpmsghandlers.NewSetupRequestHandler(logger, rNibDataService, ranSetupManager, entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST, e2tInstancesManager),
+               GetNodebRequest:        httpmsghandlers.NewGetNodebRequestHandler(logger, rNibDataService),
+               GetNodebIdListRequest:  httpmsghandlers.NewGetNodebIdListRequestHandler(logger, rNibDataService),
+               GetE2TInstancesRequest: httpmsghandlers.NewGetE2TInstancesRequestHandler(logger, e2tInstancesManager),
        }
 }
 
index 73dfbf6..840d9c2 100644 (file)
@@ -27,12 +27,10 @@ import (
        "e2mgr/logger"
        "e2mgr/managers"
        "e2mgr/mocks"
-       "e2mgr/rNibWriter"
        "e2mgr/rmrCgo"
        "e2mgr/services"
        "e2mgr/services/rmrsender"
        "e2mgr/tests"
-       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
        "github.com/stretchr/testify/assert"
        "reflect"
        "testing"
@@ -41,23 +39,20 @@ import (
 func getRmrSender(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *rmrsender.RmrSender {
        rmrMessenger := rmrCgo.RmrMessenger(rmrMessengerMock)
        rmrMessengerMock.On("Init", tests.GetPort(), tests.MaxMsgSize, tests.Flags, log).Return(&rmrMessenger)
-       return rmrsender.NewRmrSender(log, &rmrMessenger)
+       return rmrsender.NewRmrSender(log, rmrMessenger)
 }
 
 func setupTest(t *testing.T) *IncomingRequestHandlerProvider {
        rmrMessengerMock := &mocks.RmrMessengerMock{}
        log := initLog(t)
        config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
-       readerProvider := func() reader.RNibReader {
-               return &mocks.RnibReaderMock{}
-       }
-       writerProvider := func() rNibWriter.RNibWriter {
-               return &mocks.RnibWriterMock{}
-       }
-       rnibDataService := services.NewRnibDataService(log, config, readerProvider, writerProvider)
+       readerMock := &mocks.RnibReaderMock{}
+       writerMock := &mocks.RnibWriterMock{}
+       rnibDataService := services.NewRnibDataService(log, config, readerMock, writerMock)
        rmrSender := getRmrSender(rmrMessengerMock, log)
        ranSetupManager := managers.NewRanSetupManager(log, rmrSender, rnibDataService)
-       return NewIncomingRequestHandlerProvider(log, rmrSender, configuration.ParseConfiguration(), rnibDataService, ranSetupManager)
+       e2tInstancesManager := managers.NewE2TInstancesManager(rnibDataService, log)
+       return NewIncomingRequestHandlerProvider(log, rmrSender, configuration.ParseConfiguration(), rnibDataService, ranSetupManager, e2tInstancesManager)
 }
 
 func TestNewIncomingRequestHandlerProvider(t *testing.T) {
index 55c786b..b161c93 100644 (file)
@@ -21,6 +21,8 @@
 package rmrmsghandlerprovider
 
 import (
+       "e2mgr/clients"
+       "e2mgr/configuration"
        "e2mgr/converters"
        "e2mgr/handlers/rmrmsghandlers"
        "e2mgr/logger"
@@ -35,28 +37,13 @@ type NotificationHandlerProvider struct {
        notificationHandlers map[int]rmrmsghandlers.NotificationHandler
 }
 
-func NewNotificationHandlerProvider(logger *logger.Logger, rnibDataService services.RNibDataService, ranReconnectionManager *managers.RanReconnectionManager, ranStatusChangeManager *managers.RanStatusChangeManager, rmrSender *rmrsender.RmrSender, x2SetupResponseManager *managers.X2SetupResponseManager, x2SetupFailureResponseManager *managers.X2SetupFailureResponseManager) *NotificationHandlerProvider {
+func NewNotificationHandlerProvider() *NotificationHandlerProvider {
        return &NotificationHandlerProvider{
-               notificationHandlers: initNotificationHandlersMap(logger, rnibDataService, ranReconnectionManager, ranStatusChangeManager, rmrSender, x2SetupResponseManager, x2SetupFailureResponseManager),
-       }
-}
-
-func initNotificationHandlersMap(logger *logger.Logger, rnibDataService services.RNibDataService, ranReconnectionManager *managers.RanReconnectionManager, ranStatusChangeManager *managers.RanStatusChangeManager, rmrSender *rmrsender.RmrSender, x2SetupResponseManager *managers.X2SetupResponseManager, x2SetupFailureResponseManager *managers.X2SetupFailureResponseManager) map[int]rmrmsghandlers.NotificationHandler {
-       return map[int]rmrmsghandlers.NotificationHandler{
-               rmrCgo.RIC_X2_SETUP_RESP:           rmrmsghandlers.NewSetupResponseNotificationHandler(logger, rnibDataService, x2SetupResponseManager, ranStatusChangeManager, rmrCgo.RIC_X2_SETUP_RESP),
-               rmrCgo.RIC_X2_SETUP_FAILURE:        rmrmsghandlers.NewSetupResponseNotificationHandler(logger, rnibDataService, x2SetupFailureResponseManager, nil, rmrCgo.RIC_X2_SETUP_FAILURE),
-               rmrCgo.RIC_ENDC_X2_SETUP_RESP:      rmrmsghandlers.NewSetupResponseNotificationHandler(logger, rnibDataService, managers.NewEndcSetupResponseManager(), ranStatusChangeManager, rmrCgo.RIC_ENDC_X2_SETUP_RESP),
-               rmrCgo.RIC_ENDC_X2_SETUP_FAILURE:   rmrmsghandlers.NewSetupResponseNotificationHandler(logger, rnibDataService, managers.NewEndcSetupFailureResponseManager(), nil, rmrCgo.RIC_ENDC_X2_SETUP_FAILURE),
-               rmrCgo.RIC_SCTP_CONNECTION_FAILURE: rmrmsghandlers.NewRanLostConnectionHandler(logger, ranReconnectionManager),
-               rmrCgo.RIC_ENB_LOAD_INFORMATION:    rmrmsghandlers.NewEnbLoadInformationNotificationHandler(logger, rnibDataService, converters.NewEnbLoadInformationExtractor(logger)),
-               rmrCgo.RIC_ENB_CONF_UPDATE:         rmrmsghandlers.NewX2EnbConfigurationUpdateHandler(logger, rmrSender),
-               rmrCgo.RIC_ENDC_CONF_UPDATE:        rmrmsghandlers.NewEndcConfigurationUpdateHandler(logger, rmrSender),
-               rmrCgo.RIC_X2_RESET_RESP:           rmrmsghandlers.NewX2ResetResponseHandler(logger, rnibDataService, ranStatusChangeManager, converters.NewX2ResetResponseExtractor(logger)),
-               rmrCgo.RIC_X2_RESET:                rmrmsghandlers.NewX2ResetRequestNotificationHandler(logger, rnibDataService, ranStatusChangeManager, rmrSender),
-               rmrCgo.RIC_E2_TERM_INIT:            rmrmsghandlers.NewE2TermInitNotificationHandler(logger, ranReconnectionManager, rnibDataService),
+               notificationHandlers: map[int]rmrmsghandlers.NotificationHandler{},
        }
 }
 
+// TODO: check whether it has been initialized
 func (provider NotificationHandlerProvider) GetNotificationHandler(messageType int) (rmrmsghandlers.NotificationHandler, error) {
        handler, ok := provider.notificationHandlers[messageType]
 
@@ -66,3 +53,53 @@ func (provider NotificationHandlerProvider) GetNotificationHandler(messageType i
 
        return handler, nil
 }
+
+func (provider *NotificationHandlerProvider) Register(msgType int, handler rmrmsghandlers.NotificationHandler) {
+       provider.notificationHandlers[msgType] = handler
+}
+
+func (provider *NotificationHandlerProvider) Init(logger *logger.Logger, config *configuration.Configuration, rnibDataService services.RNibDataService, rmrSender *rmrsender.RmrSender, ranSetupManager *managers.RanSetupManager, e2tInstancesManager managers.IE2TInstancesManager, routingManagerClient clients.IRoutingManagerClient) {
+
+       // Init converters
+       x2SetupResponseConverter := converters.NewX2SetupResponseConverter(logger)
+       x2SetupFailureResponseConverter := converters.NewX2SetupFailureResponseConverter(logger)
+       endcSetupResponseConverter := converters.NewEndcSetupResponseConverter(logger)
+       endcSetupFailureResponseConverter := converters.NewEndcSetupFailureResponseConverter(logger)
+       enbLoadInformationExtractor := converters.NewEnbLoadInformationExtractor(logger)
+       x2ResetResponseExtractor := converters.NewX2ResetResponseExtractor(logger)
+
+       // Init managers
+       ranReconnectionManager := managers.NewRanReconnectionManager(logger, config, rnibDataService, ranSetupManager, e2tInstancesManager)
+       ranStatusChangeManager := managers.NewRanStatusChangeManager(logger, rmrSender)
+       x2SetupResponseManager := managers.NewX2SetupResponseManager(x2SetupResponseConverter)
+       x2SetupFailureResponseManager := managers.NewX2SetupFailureResponseManager(x2SetupFailureResponseConverter)
+       endcSetupResponseManager := managers.NewEndcSetupResponseManager(endcSetupResponseConverter)
+       endcSetupFailureResponseManager := managers.NewEndcSetupFailureResponseManager(endcSetupFailureResponseConverter)
+
+       // Init handlers
+       x2SetupResponseHandler := rmrmsghandlers.NewSetupResponseNotificationHandler(logger, rnibDataService, x2SetupResponseManager, ranStatusChangeManager, rmrCgo.RIC_X2_SETUP_RESP)
+       x2SetupFailureResponseHandler := rmrmsghandlers.NewSetupResponseNotificationHandler(logger, rnibDataService, x2SetupFailureResponseManager, nil, rmrCgo.RIC_X2_SETUP_FAILURE)
+       endcSetupResponseHandler := rmrmsghandlers.NewSetupResponseNotificationHandler(logger, rnibDataService, endcSetupResponseManager, ranStatusChangeManager, rmrCgo.RIC_ENDC_X2_SETUP_RESP)
+       endcSetupFailureResponseHandler := rmrmsghandlers.NewSetupResponseNotificationHandler(logger, rnibDataService, endcSetupFailureResponseManager, nil, rmrCgo.RIC_ENDC_X2_SETUP_FAILURE)
+       ranLostConnectionHandler := rmrmsghandlers.NewRanLostConnectionHandler(logger, ranReconnectionManager)
+       enbLoadInformationNotificationHandler := rmrmsghandlers.NewEnbLoadInformationNotificationHandler(logger, rnibDataService, enbLoadInformationExtractor)
+       x2EnbConfigurationUpdateHandler := rmrmsghandlers.NewX2EnbConfigurationUpdateHandler(logger, rmrSender)
+       endcConfigurationUpdateHandler := rmrmsghandlers.NewEndcConfigurationUpdateHandler(logger, rmrSender)
+       x2ResetResponseHandler := rmrmsghandlers.NewX2ResetResponseHandler(logger, rnibDataService, ranStatusChangeManager, x2ResetResponseExtractor)
+       x2ResetRequestNotificationHandler := rmrmsghandlers.NewX2ResetRequestNotificationHandler(logger, rnibDataService, ranStatusChangeManager, rmrSender)
+       e2TermInitNotificationHandler := rmrmsghandlers.NewE2TermInitNotificationHandler(logger, ranReconnectionManager, rnibDataService, e2tInstancesManager, routingManagerClient)
+       e2TKeepAliveResponseHandler := rmrmsghandlers.NewE2TKeepAliveResponseHandler(logger, rnibDataService, e2tInstancesManager)
+
+       provider.Register(rmrCgo.RIC_X2_SETUP_RESP, x2SetupResponseHandler)
+       provider.Register(rmrCgo.RIC_X2_SETUP_FAILURE, x2SetupFailureResponseHandler)
+       provider.Register(rmrCgo.RIC_ENDC_X2_SETUP_RESP, endcSetupResponseHandler)
+       provider.Register(rmrCgo.RIC_ENDC_X2_SETUP_FAILURE, endcSetupFailureResponseHandler)
+       provider.Register(rmrCgo.RIC_SCTP_CONNECTION_FAILURE, ranLostConnectionHandler)
+       provider.Register(rmrCgo.RIC_ENB_LOAD_INFORMATION, enbLoadInformationNotificationHandler)
+       provider.Register(rmrCgo.RIC_ENB_CONF_UPDATE, x2EnbConfigurationUpdateHandler)
+       provider.Register(rmrCgo.RIC_ENDC_CONF_UPDATE, endcConfigurationUpdateHandler)
+       provider.Register(rmrCgo.RIC_X2_RESET_RESP, x2ResetResponseHandler)
+       provider.Register(rmrCgo.RIC_X2_RESET, x2ResetRequestNotificationHandler)
+       provider.Register(rmrCgo.RIC_E2_TERM_INIT, e2TermInitNotificationHandler)
+       provider.Register(rmrCgo.E2_TERM_KEEP_ALIVE_RESP, e2TKeepAliveResponseHandler)
+}
index d86b55d..fb5dadb 100644 (file)
 package rmrmsghandlerprovider
 
 import (
+       "e2mgr/clients"
        "e2mgr/configuration"
        "e2mgr/converters"
        "e2mgr/handlers/rmrmsghandlers"
        "e2mgr/logger"
        "e2mgr/managers"
        "e2mgr/mocks"
-       "e2mgr/rNibWriter"
        "e2mgr/services"
        "e2mgr/services/rmrsender"
        "e2mgr/tests"
        "fmt"
-       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
        "strings"
        "testing"
 
@@ -43,23 +42,28 @@ import (
  * Verify support for known providers.
  */
 
-func initTestCase(t *testing.T) (*logger.Logger, services.RNibDataService, *managers.RanReconnectionManager, *managers.RanStatusChangeManager, *rmrsender.RmrSender, *managers.X2SetupResponseManager, *managers.X2SetupFailureResponseManager) {
+func initTestCase(t *testing.T) (*logger.Logger, *configuration.Configuration, services.RNibDataService, *rmrsender.RmrSender, *managers.RanSetupManager, managers.IE2TInstancesManager, clients.IRoutingManagerClient) {
        logger := initLog(t)
        config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
 
        readerMock := &mocks.RnibReaderMock{}
-       rnibReaderProvider := func() reader.RNibReader {
-               return readerMock
-       }
        writerMock := &mocks.RnibWriterMock{}
-       rnibWriterProvider := func() rNibWriter.RNibWriter {
-               return writerMock
-       }
+       httpClient := &mocks.HttpClientMock{}
 
        rmrSender := initRmrSender(&mocks.RmrMessengerMock{}, logger)
-       rnibDataService := services.NewRnibDataService(logger, config, rnibReaderProvider, rnibWriterProvider)
+       rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
        ranSetupManager := managers.NewRanSetupManager(logger, rmrSender, rnibDataService)
-       ranReconnectionManager := managers.NewRanReconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, ranSetupManager)
+       e2tInstancesManager := managers.NewE2TInstancesManager(rnibDataService, logger)
+       routingManagerClient := clients.NewRoutingManagerClient(logger, config, httpClient)
+
+       return logger, config, rnibDataService, rmrSender, ranSetupManager, e2tInstancesManager, routingManagerClient
+}
+
+func TestGetNotificationHandlerSuccess(t *testing.T) {
+
+       logger, config, rnibDataService, rmrSender, ranSetupManager, e2tInstancesManager, routingManagerClient := initTestCase(t)
+
+       ranReconnectionManager := managers.NewRanReconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, ranSetupManager, e2tInstancesManager)
        ranStatusChangeManager := managers.NewRanStatusChangeManager(logger, rmrSender)
 
        x2SetupResponseConverter := converters.NewX2SetupResponseConverter(logger)
@@ -68,34 +72,36 @@ func initTestCase(t *testing.T) (*logger.Logger, services.RNibDataService, *mana
        x2SetupFailureResponseConverter := converters.NewX2SetupFailureResponseConverter(logger)
        x2SetupFailureResponseManager := managers.NewX2SetupFailureResponseManager(x2SetupFailureResponseConverter)
 
+       endcSetupResponseConverter := converters.NewEndcSetupResponseConverter(logger)
+       endcSetupResponseManager := managers.NewEndcSetupResponseManager(endcSetupResponseConverter)
 
-       return logger, rnibDataService, ranReconnectionManager, ranStatusChangeManager, rmrSender, x2SetupResponseManager, x2SetupFailureResponseManager
-}
 
-func TestGetNotificationHandlerSuccess(t *testing.T) {
+       endcSetupFailureResponseConverter := converters.NewEndcSetupFailureResponseConverter(logger)
+       endcSetupFailureResponseManager := managers.NewEndcSetupFailureResponseManager(endcSetupFailureResponseConverter)
 
-       logger, rnibDataService, ranReconnectionManager, ranStatusChangeManager, rmrSender, x2SetupResponseManager, x2SetupFailureResponseManager := initTestCase(t)
 
        var testCases = []struct {
                msgType int
                handler rmrmsghandlers.NotificationHandler
        }{
-               {rmrCgo.RIC_X2_SETUP_RESP, rmrmsghandlers.NewSetupResponseNotificationHandler(logger,rnibDataService, x2SetupResponseManager, ranStatusChangeManager, rmrCgo.RIC_X2_SETUP_RESP)},
-               {rmrCgo.RIC_X2_SETUP_FAILURE, rmrmsghandlers.NewSetupResponseNotificationHandler(logger,rnibDataService, x2SetupFailureResponseManager, ranStatusChangeManager, rmrCgo.RIC_X2_SETUP_FAILURE)},
-               {rmrCgo.RIC_ENDC_X2_SETUP_RESP, rmrmsghandlers.NewSetupResponseNotificationHandler(logger,rnibDataService, managers.NewEndcSetupResponseManager(), ranStatusChangeManager, rmrCgo.RIC_ENDC_X2_SETUP_RESP)},
-               {rmrCgo.RIC_ENDC_X2_SETUP_FAILURE, rmrmsghandlers.NewSetupResponseNotificationHandler(logger,rnibDataService, managers.NewEndcSetupFailureResponseManager(), ranStatusChangeManager, rmrCgo.RIC_ENDC_X2_SETUP_FAILURE),},
-               {rmrCgo.RIC_SCTP_CONNECTION_FAILURE, rmrmsghandlers.NewRanLostConnectionHandler(logger,ranReconnectionManager)},
-               {rmrCgo.RIC_ENB_LOAD_INFORMATION, rmrmsghandlers.NewEnbLoadInformationNotificationHandler(logger,rnibDataService, converters.NewEnbLoadInformationExtractor(logger))},
+               {rmrCgo.RIC_X2_SETUP_RESP, rmrmsghandlers.NewSetupResponseNotificationHandler(logger, rnibDataService, x2SetupResponseManager, ranStatusChangeManager, rmrCgo.RIC_X2_SETUP_RESP)},
+               {rmrCgo.RIC_X2_SETUP_FAILURE, rmrmsghandlers.NewSetupResponseNotificationHandler(logger, rnibDataService, x2SetupFailureResponseManager, ranStatusChangeManager, rmrCgo.RIC_X2_SETUP_FAILURE)},
+               {rmrCgo.RIC_ENDC_X2_SETUP_RESP, rmrmsghandlers.NewSetupResponseNotificationHandler(logger, rnibDataService, endcSetupResponseManager, ranStatusChangeManager, rmrCgo.RIC_ENDC_X2_SETUP_RESP)},
+               {rmrCgo.RIC_ENDC_X2_SETUP_FAILURE, rmrmsghandlers.NewSetupResponseNotificationHandler(logger, rnibDataService, endcSetupFailureResponseManager, ranStatusChangeManager, rmrCgo.RIC_ENDC_X2_SETUP_FAILURE),},
+               {rmrCgo.RIC_SCTP_CONNECTION_FAILURE, rmrmsghandlers.NewRanLostConnectionHandler(logger, ranReconnectionManager)},
+               {rmrCgo.RIC_ENB_LOAD_INFORMATION, rmrmsghandlers.NewEnbLoadInformationNotificationHandler(logger, rnibDataService, converters.NewEnbLoadInformationExtractor(logger))},
                {rmrCgo.RIC_ENB_CONF_UPDATE, rmrmsghandlers.NewX2EnbConfigurationUpdateHandler(logger, rmrSender)},
                {rmrCgo.RIC_ENDC_CONF_UPDATE, rmrmsghandlers.NewEndcConfigurationUpdateHandler(logger, rmrSender)},
-               {rmrCgo.RIC_E2_TERM_INIT, rmrmsghandlers.NewE2TermInitNotificationHandler(logger,ranReconnectionManager, rnibDataService)},
+               {rmrCgo.RIC_E2_TERM_INIT, rmrmsghandlers.NewE2TermInitNotificationHandler(logger, ranReconnectionManager, rnibDataService, e2tInstancesManager, routingManagerClient)},
+               {rmrCgo.E2_TERM_KEEP_ALIVE_RESP, rmrmsghandlers.NewE2TKeepAliveResponseHandler(logger, rnibDataService, e2tInstancesManager)},
                {rmrCgo.RIC_X2_RESET_RESP, rmrmsghandlers.NewX2ResetResponseHandler(logger, rnibDataService, ranStatusChangeManager, converters.NewX2ResetResponseExtractor(logger))},
-               {rmrCgo.RIC_X2_RESET, rmrmsghandlers.NewX2ResetRequestNotificationHandler(logger,rnibDataService, ranStatusChangeManager, rmrSender)},
+               {rmrCgo.RIC_X2_RESET, rmrmsghandlers.NewX2ResetRequestNotificationHandler(logger, rnibDataService, ranStatusChangeManager, rmrSender)},
        }
 
        for _, tc := range testCases {
 
-               provider := NewNotificationHandlerProvider(logger, rnibDataService, ranReconnectionManager, ranStatusChangeManager, rmrSender, x2SetupResponseManager, x2SetupFailureResponseManager)
+               provider := NewNotificationHandlerProvider()
+               provider.Init(logger, config, rnibDataService, rmrSender, ranSetupManager, e2tInstancesManager, routingManagerClient)
                t.Run(fmt.Sprintf("%d", tc.msgType), func(t *testing.T) {
                        handler, err := provider.GetNotificationHandler(tc.msgType)
                        if err != nil {
@@ -124,8 +130,9 @@ func TestGetNotificationHandlerFailure(t *testing.T) {
        }
        for _, tc := range testCases {
 
-               logger, rnibDataService, ranReconnectionManager, ranStatusChangeManager, rmrSender, x2SetupResponseManager, x2SetupFailureResponseManager := initTestCase(t)
-               provider := NewNotificationHandlerProvider(logger, rnibDataService, ranReconnectionManager, ranStatusChangeManager, rmrSender, x2SetupResponseManager, x2SetupFailureResponseManager)
+               logger, config, rnibDataService, rmrSender, ranSetupManager, e2tInstancesManager, routingManagerClient := initTestCase(t)
+               provider := NewNotificationHandlerProvider()
+               provider.Init(logger, config, rnibDataService, rmrSender, ranSetupManager, e2tInstancesManager, routingManagerClient)
                t.Run(fmt.Sprintf("%d", tc.msgType), func(t *testing.T) {
                        _, err := provider.GetNotificationHandler(tc.msgType)
                        if err == nil {
@@ -142,7 +149,7 @@ func TestGetNotificationHandlerFailure(t *testing.T) {
 func initRmrSender(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *rmrsender.RmrSender {
        rmrMessenger := rmrCgo.RmrMessenger(rmrMessengerMock)
        rmrMessengerMock.On("Init", tests.GetPort(), tests.MaxMsgSize, tests.Flags, log).Return(&rmrMessenger)
-       return rmrsender.NewRmrSender(log, &rmrMessenger)
+       return rmrsender.NewRmrSender(log, rmrMessenger)
 }
 
 // TODO: extract to test_utils
index c996a1e..13a31f3 100644 (file)
 package rNibWriter
 
 import (
+       "encoding/json"
        "fmt"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
-       "gerrit.o-ran-sc.org/r/ric-plt/sdlgo"
        "github.com/golang/protobuf/proto"
 )
 
-var writerPool *common.Pool
+const E2TAddressesKey = "E2TAddresses"
 
 type rNibWriterInstance struct {
-       sdl       *common.ISdlInstance
-       namespace string
+       sdl common.ISdlInstance
 }
 
 /*
@@ -42,45 +41,27 @@ type RNibWriter interface {
        SaveNodeb(nbIdentity *entities.NbIdentity, nb *entities.NodebInfo) error
        UpdateNodebInfo(nodebInfo *entities.NodebInfo) error
        SaveRanLoadInformation(inventoryName string, ranLoadInformation *entities.RanLoadInformation) error
+       SaveE2TInstance(e2tInstance *entities.E2TInstance) error
+       SaveE2TAddresses(addresses []string) error
 }
 
-/*
-Init initializes the infrastructure required for the RNibWriter instance
-*/
-func Init(namespace string, poolSize int) {
-       initPool(poolSize,
-               func() interface{} {
-                       var sdlI common.ISdlInstance = sdlgo.NewSdlInstance(namespace, sdlgo.NewDatabase())
-                       return &rNibWriterInstance{sdl: &sdlI, namespace: namespace}
-               },
-               func(obj interface{}) {
-                       (*obj.(*rNibWriterInstance).sdl).Close()
-               })
-}
-
-/*
-InitPool initializes the writer's instances pool
-*/
-func initPool(poolSize int, newObj func() interface{}, destroyObj func(interface{})) {
-       writerPool = common.NewPool(poolSize, newObj, destroyObj)
-}
 /*
 GetRNibWriter returns reference to RNibWriter
 */
-func GetRNibWriter() RNibWriter {
-       return &rNibWriterInstance{}
+
+func GetRNibWriter(sdl common.ISdlInstance) RNibWriter {
+       return &rNibWriterInstance{sdl: sdl}
 }
+
 /*
 SaveNodeb saves nodeB entity data in the redis DB according to the specified data model
 */
-func (*rNibWriterInstance) SaveNodeb(nbIdentity *entities.NbIdentity, entity *entities.NodebInfo) error {
-       w := writerPool.Get().(*rNibWriterInstance)
+func (w *rNibWriterInstance) SaveNodeb(nbIdentity *entities.NbIdentity, entity *entities.NodebInfo) error {
        isNotEmptyIdentity := isNotEmpty(nbIdentity)
 
        if isNotEmptyIdentity && entity.GetNodeType() == entities.Node_UNKNOWN {
                return common.NewValidationError(fmt.Sprintf("#rNibWriter.saveNodeB - Unknown responding node type, entity: %v", entity))
        }
-       defer writerPool.Put(w)
        data, err := proto.Marshal(entity)
        if err != nil {
                return common.NewInternalError(err)
@@ -112,7 +93,7 @@ func (*rNibWriterInstance) SaveNodeb(nbIdentity *entities.NbIdentity, entity *en
                        return rNibErr
                }
        }
-       err = (*w.sdl).Set(pairs)
+       err = w.sdl.Set(pairs)
        if err != nil {
                return common.NewInternalError(err)
        }
@@ -124,7 +105,7 @@ func (*rNibWriterInstance) SaveNodeb(nbIdentity *entities.NbIdentity, entity *en
                if err != nil {
                        return common.NewInternalError(err)
                }
-               err = (*w.sdl).RemoveMember(entities.Node_UNKNOWN.String(), nbIdData)
+               err = w.sdl.RemoveMember(entities.Node_UNKNOWN.String(), nbIdData)
                if err != nil {
                        return common.NewInternalError(err)
                }
@@ -136,7 +117,7 @@ func (*rNibWriterInstance) SaveNodeb(nbIdentity *entities.NbIdentity, entity *en
        if err != nil {
                return common.NewInternalError(err)
        }
-       err = (*w.sdl).AddMember(entity.GetNodeType().String(), nbIdData)
+       err = w.sdl.AddMember(entity.GetNodeType().String(), nbIdData)
        if err != nil {
                return common.NewInternalError(err)
        }
@@ -146,9 +127,7 @@ func (*rNibWriterInstance) SaveNodeb(nbIdentity *entities.NbIdentity, entity *en
 /*
 UpdateNodebInfo...
 */
-func (*rNibWriterInstance) UpdateNodebInfo(nodebInfo *entities.NodebInfo) error {
-       w := writerPool.Get().(*rNibWriterInstance)
-       defer writerPool.Put(w)
+func (w *rNibWriterInstance) UpdateNodebInfo(nodebInfo *entities.NodebInfo) error {
 
        nodebNameKey, rNibErr := common.ValidateAndBuildNodeBNameKey(nodebInfo.GetRanName())
 
@@ -171,7 +150,7 @@ func (*rNibWriterInstance) UpdateNodebInfo(nodebInfo *entities.NodebInfo) error
                pairs = append(pairs, nodebIdKey, data)
        }
 
-       err = (*w.sdl).Set(pairs)
+       err = w.sdl.Set(pairs)
 
        if err != nil {
                return common.NewInternalError(err)
@@ -183,9 +162,7 @@ func (*rNibWriterInstance) UpdateNodebInfo(nodebInfo *entities.NodebInfo) error
 /*
 SaveRanLoadInformation stores ran load information for the provided ran
 */
-func (*rNibWriterInstance) SaveRanLoadInformation(inventoryName string, ranLoadInformation *entities.RanLoadInformation) error {
-       w := writerPool.Get().(*rNibWriterInstance)
-       defer writerPool.Put(w)
+func (w *rNibWriterInstance) SaveRanLoadInformation(inventoryName string, ranLoadInformation *entities.RanLoadInformation) error {
 
        key, rnibErr := common.ValidateAndBuildRanLoadInformationKey(inventoryName)
 
@@ -202,7 +179,53 @@ func (*rNibWriterInstance) SaveRanLoadInformation(inventoryName string, ranLoadI
        var pairs []interface{}
        pairs = append(pairs, key, data)
 
-       err = (*w.sdl).Set(pairs)
+       err = w.sdl.Set(pairs)
+
+       if err != nil {
+               return common.NewInternalError(err)
+       }
+
+       return nil
+}
+
+func (w *rNibWriterInstance) SaveE2TInstance(e2tInstance *entities.E2TInstance) error {
+
+       key, rnibErr := common.ValidateAndBuildE2TInstanceKey(e2tInstance.Address)
+
+       if rnibErr != nil {
+               return rnibErr
+       }
+
+       data, err := json.Marshal(e2tInstance)
+
+       if err != nil {
+               return common.NewInternalError(err)
+       }
+
+       var pairs []interface{}
+       pairs = append(pairs, key, data)
+
+       err = w.sdl.Set(pairs)
+
+       if err != nil {
+               return common.NewInternalError(err)
+       }
+
+       return nil
+}
+
+func (w *rNibWriterInstance) SaveE2TAddresses(addresses []string) error {
+
+       data, err := json.Marshal(addresses)
+
+       if err != nil {
+               return common.NewInternalError(err)
+       }
+
+       var pairs []interface{}
+       pairs = append(pairs, E2TAddressesKey, data)
+
+       err = w.sdl.Set(pairs)
 
        if err != nil {
                return common.NewInternalError(err)
@@ -212,10 +235,10 @@ func (*rNibWriterInstance) SaveRanLoadInformation(inventoryName string, ranLoadI
 }
 
 /*
-Close closes writer's pool
+Close the writer
 */
 func Close() {
-       writerPool.Close()
+       //Nothing to do
 }
 
 func appendEnbCells(nbIdentity *entities.NbIdentity, cells []*entities.ServedCellInfo, pairs []interface{}) ([]interface{}, error) {
index f16228b..34ef4c8 100644 (file)
@@ -22,6 +22,7 @@ package rNibWriter
 
 import (
        "e2mgr/mocks"
+       "encoding/json"
        "errors"
        "fmt"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
@@ -32,55 +33,19 @@ import (
        "time"
 )
 
-func TestInitRNibWriter(t *testing.T) {
-       writerPool = nil
-       initSdlInstanceMock(namespace, 1)
-       available, created := writerPool.Stats()
-       assert.Equal(t, available, 0, "number of available objects in the writerPool should be 0")
-       assert.Equal(t, created, 0, "number of created objects in the writerPool should be 0")
-       w := GetRNibWriter()
-       assert.NotNil(t, w)
-}
-
-func TestInitPool(t *testing.T) {
-       writerPool = nil
-       sdlInstanceMock := new(mocks.MockSdlInstance)
-       initPool(1, func() interface{} {
-               sdlI := common.ISdlInstance(sdlInstanceMock)
-               return &rNibWriterInstance{sdl: &sdlI, namespace: namespace}
-       },
-               func(obj interface{}) {
-               },
-       )
-       assert.NotNil(t, writerPool)
-       assert.NotNil(t, writerPool.New)
-       assert.NotNil(t, writerPool.Destroy)
-       available, created := writerPool.Stats()
-       assert.Equal(t, 0, available, "number of available objects in the writerPool should be 0")
-       assert.Equal(t, 0, created, "number of created objects in the writerPool should be 0")
+func initSdlInstanceMock(namespace string) (w RNibWriter, sdlInstanceMock *mocks.MockSdlInstance) {
+       sdlInstanceMock = new(mocks.MockSdlInstance)
+       w = GetRNibWriter(sdlInstanceMock)
+       return
 }
 
 var namespace = "namespace"
 
-func initSdlInstanceMock(namespace string, poolSize int) *mocks.MockSdlInstance {
-       sdlInstanceMock := new(mocks.MockSdlInstance)
-       initPool(poolSize, func() interface{} {
-               sdlI := common.ISdlInstance(sdlInstanceMock)
-               return &rNibWriterInstance{sdl: &sdlI, namespace: namespace}
-       },
-               func(obj interface{}) {
-               },
-       )
-       return sdlInstanceMock
-}
-
 func TestUpdateNodebInfoSuccess(t *testing.T) {
        inventoryName := "name"
        plmnId := "02f829"
        nbId := "4a952a0a"
-       writerPool = nil
-       sdlInstanceMock := initSdlInstanceMock(namespace, 1)
-       w := GetRNibWriter()
+       w, sdlInstanceMock := initSdlInstanceMock(namespace)
        nodebInfo := &entities.NodebInfo{}
        nodebInfo.RanName = inventoryName
        nodebInfo.GlobalNbId = &entities.GlobalNbId{PlmnId: plmnId, NbId: nbId}
@@ -110,9 +75,7 @@ func TestUpdateNodebInfoMissingInventoryNameFailure(t *testing.T) {
        inventoryName := "name"
        plmnId := "02f829"
        nbId := "4a952a0a"
-       writerPool = nil
-       sdlInstanceMock := initSdlInstanceMock(namespace, 1)
-       w := GetRNibWriter()
+       w, sdlInstanceMock := initSdlInstanceMock(namespace)
        nodebInfo := &entities.NodebInfo{}
        data, err := proto.Marshal(nodebInfo)
        if err != nil {
@@ -136,9 +99,7 @@ func TestUpdateNodebInfoMissingInventoryNameFailure(t *testing.T) {
 
 func TestUpdateNodebInfoMissingGlobalNbId(t *testing.T) {
        inventoryName := "name"
-       writerPool = nil
-       sdlInstanceMock := initSdlInstanceMock(namespace, 1)
-       w := GetRNibWriter()
+       w, sdlInstanceMock := initSdlInstanceMock(namespace)
        nodebInfo := &entities.NodebInfo{}
        nodebInfo.RanName = inventoryName
        data, err := proto.Marshal(nodebInfo)
@@ -160,9 +121,7 @@ func TestUpdateNodebInfoMissingGlobalNbId(t *testing.T) {
 func TestSaveEnb(t *testing.T) {
        name := "name"
        ranName := "RAN:" + name
-       writerPool = nil
-       sdlInstanceMock := initSdlInstanceMock(namespace, 1)
-       w := GetRNibWriter()
+       w, sdlInstanceMock := initSdlInstanceMock(namespace)
        nb := entities.NodebInfo{}
        nb.NodeType = entities.Node_ENB
        nb.ConnectionStatus = 1
@@ -210,9 +169,7 @@ func TestSaveEnb(t *testing.T) {
 
 func TestSaveEnbCellIdValidationFailure(t *testing.T) {
        name := "name"
-       writerPool = nil
-       initSdlInstanceMock(namespace, 1)
-       w := GetRNibWriter()
+       w, _ := initSdlInstanceMock(namespace)
        nb := entities.NodebInfo{}
        nb.NodeType = entities.Node_ENB
        nb.ConnectionStatus = 1
@@ -231,9 +188,7 @@ func TestSaveEnbCellIdValidationFailure(t *testing.T) {
 }
 
 func TestSaveEnbInventoryNameValidationFailure(t *testing.T) {
-       writerPool = nil
-       initSdlInstanceMock(namespace, 1)
-       w := GetRNibWriter()
+       w, _ := initSdlInstanceMock(namespace)
        nb := entities.NodebInfo{}
        nb.NodeType = entities.Node_ENB
        nb.ConnectionStatus = 1
@@ -251,35 +206,9 @@ func TestSaveEnbInventoryNameValidationFailure(t *testing.T) {
        assert.Equal(t, "#utils.ValidateAndBuildNodeBNameKey - an empty inventory name received", rNibErr.Error())
 }
 
-func TestSaveEnbOnClosedPool(t *testing.T) {
-       name := "name"
-       writerPool = nil
-       sdlInstanceMock := initSdlInstanceMock(namespace, 1)
-       w := GetRNibWriter()
-       nb := entities.NodebInfo{}
-       nb.NodeType = entities.Node_ENB
-       nb.ConnectionStatus = 1
-       nb.Ip = "localhost"
-       nb.Port = 5656
-       enb := entities.Enb{}
-       nb.Configuration = &entities.NodebInfo_Enb{Enb: &enb}
-       data, err := proto.Marshal(&nb)
-       if err != nil {
-               t.Errorf("#rNibWriter_test.TestSaveEnbOnClosedPool - Failed to marshal NodeB entity. Error: %v", err)
-       }
-       setExpected := []interface{}{name, data}
-       var e error
-       sdlInstanceMock.On("Set", setExpected).Return(e)
-       writerPool.Close()
-       nbIdentity := &entities.NbIdentity{}
-       assert.Panics(t, func() { w.SaveNodeb(nbIdentity, &nb) })
-}
-
 func TestSaveGnbCellIdValidationFailure(t *testing.T) {
        name := "name"
-       writerPool = nil
-       initSdlInstanceMock(namespace, 1)
-       w := GetRNibWriter()
+       w, _ := initSdlInstanceMock(namespace)
        nb := entities.NodebInfo{}
        nb.NodeType = entities.Node_GNB
        nb.ConnectionStatus = 1
@@ -301,9 +230,7 @@ func TestSaveGnbCellIdValidationFailure(t *testing.T) {
 func TestSaveGnb(t *testing.T) {
        name := "name"
        ranName := "RAN:" + name
-       writerPool = nil
-       sdlInstanceMock := initSdlInstanceMock(namespace, 1)
-       w := GetRNibWriter()
+       w, sdlInstanceMock := initSdlInstanceMock(namespace)
        nb := entities.NodebInfo{}
        nb.NodeType = entities.Node_GNB
        nb.ConnectionStatus = 1
@@ -357,9 +284,7 @@ func TestSaveRanLoadInformationSuccess(t *testing.T) {
                t.Errorf("#rNibWriter_test.TestSaveRanLoadInformationSuccess - Failed to build ran load infromation key. Error: %v", validationErr)
        }
 
-       writerPool = nil
-       sdlInstanceMock := initSdlInstanceMock(namespace, 1)
-       w := GetRNibWriter()
+       w, sdlInstanceMock := initSdlInstanceMock(namespace)
 
        ranLoadInformation := generateRanLoadInformation()
        data, err := proto.Marshal(ranLoadInformation)
@@ -379,9 +304,7 @@ func TestSaveRanLoadInformationSuccess(t *testing.T) {
 
 func TestSaveRanLoadInformationMarshalNilFailure(t *testing.T) {
        inventoryName := "name2"
-       writerPool = nil
-       initSdlInstanceMock(namespace, 1)
-       w := GetRNibWriter()
+       w, _ := initSdlInstanceMock(namespace)
 
        expectedErr := common.NewInternalError(errors.New("proto: Marshal called with nil"))
        err := w.SaveRanLoadInformation(inventoryName, nil)
@@ -390,9 +313,7 @@ func TestSaveRanLoadInformationMarshalNilFailure(t *testing.T) {
 
 func TestSaveRanLoadInformationEmptyInventoryNameFailure(t *testing.T) {
        inventoryName := ""
-       writerPool = nil
-       initSdlInstanceMock(namespace, 1)
-       w := GetRNibWriter()
+       w, _ := initSdlInstanceMock(namespace)
 
        err := w.SaveRanLoadInformation(inventoryName, nil)
        assert.NotNil(t, err)
@@ -408,9 +329,7 @@ func TestSaveRanLoadInformationSdlFailure(t *testing.T) {
                t.Errorf("#rNibWriter_test.TestSaveRanLoadInformationSuccess - Failed to build ran load infromation key. Error: %v", validationErr)
        }
 
-       writerPool = nil
-       sdlInstanceMock := initSdlInstanceMock(namespace, 1)
-       w := GetRNibWriter()
+       w, sdlInstanceMock := initSdlInstanceMock(namespace)
 
        ranLoadInformation := generateRanLoadInformation()
        data, err := proto.Marshal(ranLoadInformation)
@@ -503,9 +422,7 @@ func generateRanLoadInformation() *entities.RanLoadInformation {
 }
 
 func TestSaveNilEntityFailure(t *testing.T) {
-       writerPool = nil
-       initSdlInstanceMock(namespace, 1)
-       w := GetRNibWriter()
+       w, _ := initSdlInstanceMock(namespace)
        expectedErr := common.NewInternalError(errors.New("proto: Marshal called with nil"))
        nbIdentity := &entities.NbIdentity{}
        actualErr := w.SaveNodeb(nbIdentity, nil)
@@ -513,9 +430,7 @@ func TestSaveNilEntityFailure(t *testing.T) {
 }
 
 func TestSaveUnknownTypeEntityFailure(t *testing.T) {
-       writerPool = nil
-       initSdlInstanceMock(namespace, 1)
-       w := GetRNibWriter()
+       w, _ := initSdlInstanceMock(namespace)
        expectedErr := common.NewValidationError("#rNibWriter.saveNodeB - Unknown responding node type, entity: ip:\"localhost\" port:5656 ")
        nbIdentity := &entities.NbIdentity{InventoryName: "name", GlobalNbId: &entities.GlobalNbId{PlmnId: "02f829", NbId: "4a952a0a"}}
        nb := &entities.NodebInfo{}
@@ -530,9 +445,7 @@ func TestSaveEntityFailure(t *testing.T) {
        plmnId := "02f829"
        nbId := "4a952a0a"
 
-       writerPool = nil
-       sdlInstanceMock := initSdlInstanceMock(namespace, 1)
-       w := GetRNibWriter()
+       w, sdlInstanceMock := initSdlInstanceMock(namespace)
        gnb := entities.NodebInfo{}
        gnb.NodeType = entities.Node_GNB
        data, err := proto.Marshal(&gnb)
@@ -548,77 +461,120 @@ func TestSaveEntityFailure(t *testing.T) {
        assert.NotEmpty(t, rNibErr)
 }
 
-func TestGetRNibWriterPoolNotInitializedFailure(t *testing.T) {
-       writerPool = nil
-       assert.Panics(t, func() { GetRNibWriter().SaveNodeb(nil,nil) })
-}
-
 func TestGetRNibWriter(t *testing.T) {
-       writerPool = nil
-       initSdlInstanceMock(namespace, 1)
-       received := GetRNibWriter()
-       assert.Empty(t, received)
-       available, created := writerPool.Stats()
-       assert.Equal(t, 0, available, "number of available objects in the writerPool should be 0")
-       assert.Equal(t, 0, created, "number of created objects in the writerPool should be 0")
-       writerPool.Close()
+       received, _ := initSdlInstanceMock(namespace)
+       assert.NotEmpty(t, received)
 }
 
-func TestClose(t *testing.T) {
-       writerPool = nil
-       instanceMock := initSdlInstanceMock(namespace, 2)
-       w1 := GetRNibWriter()
-       w2 := GetRNibWriter()
-       writerPool.Put(w1)
-       writerPool.Put(w2)
-       available, created := writerPool.Stats()
-       assert.Equal(t, 2, available, "number of available objects in the writerPool should be 2")
-       assert.Equal(t, 0, created, "number of created objects in the writerPool should be 0")
+func TestSaveE2TInstanceSuccess(t *testing.T) {
+       address := "10.10.2.15:9800"
+       loadKey, validationErr := common.ValidateAndBuildE2TInstanceKey(address)
+
+       if validationErr != nil {
+               t.Errorf("#rNibWriter_test.TestSaveE2TInstanceSuccess - Failed to build E2T Instance key. Error: %v", validationErr)
+       }
+
+       w, sdlInstanceMock := initSdlInstanceMock(namespace)
+
+       e2tInstance := generateE2tInstance(address)
+       data, err := json.Marshal(e2tInstance)
+
+       if err != nil {
+               t.Errorf("#rNibWriter_test.TestSaveE2TInstanceSuccess - Failed to marshal E2tInstance entity. Error: %v", err)
+       }
+
        var e error
-       instanceMock.On("Close").Return(e)
-       Close()
-       available, created = writerPool.Stats()
-       assert.Equal(t, 0, available, "number of available objects in the writerPool should be 0")
+       var setExpected []interface{}
+       setExpected = append(setExpected, loadKey, data)
+       sdlInstanceMock.On("Set", []interface{}{setExpected}).Return(e)
+
+       rNibErr := w.SaveE2TInstance(e2tInstance)
+       assert.Nil(t, rNibErr)
 }
 
-func TestCloseOnClosedPoolFailure(t *testing.T) {
-       writerPool = nil
-       instanceMock := initSdlInstanceMock(namespace, 1)
-       w1 := GetRNibWriter()
-       writerPool.Put(w1)
-       available, created := writerPool.Stats()
-       assert.Equal(t, 1, available, "number of available objects in the writerPool should be 1")
-       assert.Equal(t, 0, created, "number of created objects in the writerPool should be 0")
-       var e error
-       instanceMock.On("Close").Return(e)
-       Close()
-       assert.Panics(t, func() { Close() })
+func TestSaveE2TInstanceNullE2tInstanceFailure(t *testing.T) {
+       w, _ := initSdlInstanceMock(namespace)
+       var address string
+       e2tInstance := entities.NewE2TInstance(address)
+       err := w.SaveE2TInstance(e2tInstance)
+       assert.NotNil(t, err)
+       assert.IsType(t, &common.ValidationError{}, err)
 }
 
-func TestCloseFailure(t *testing.T) {
-       writerPool = nil
-       instanceMock := initSdlInstanceMock(namespace, 2)
-       w1 := GetRNibWriter()
-       writerPool.Put(w1)
-       available, created := writerPool.Stats()
-       assert.Equal(t, 1, available, "number of available objects in the writerPool should be 1")
-       assert.Equal(t, 0, created, "number of created objects in the writerPool should be 0")
-       e := errors.New("expected error")
-       instanceMock.On("Close").Return(e)
-       Close()
-       available, created = writerPool.Stats()
-       assert.Equal(t, 0, available, "number of available objects in the writerPool should be 0")
+func TestSaveE2TInstanceSdlFailure(t *testing.T) {
+       address := "10.10.2.15:9800"
+       loadKey, validationErr := common.ValidateAndBuildE2TInstanceKey(address)
+
+       if validationErr != nil {
+               t.Errorf("#rNibWriter_test.TestSaveE2TInstanceSdlFailure - Failed to build E2T Instance key. Error: %v", validationErr)
+       }
+
+       w, sdlInstanceMock := initSdlInstanceMock(namespace)
+
+       e2tInstance := generateE2tInstance(address)
+       data, err := json.Marshal(e2tInstance)
+
+       if err != nil {
+               t.Errorf("#rNibWriter_test.TestSaveE2TInstanceSdlFailure - Failed to marshal E2tInstance entity. Error: %v", err)
+       }
+
+       expectedErr := errors.New("expected error")
+       var setExpected []interface{}
+       setExpected = append(setExpected, loadKey, data)
+       sdlInstanceMock.On("Set", []interface{}{setExpected}).Return(expectedErr)
+
+       rNibErr := w.SaveE2TInstance(e2tInstance)
+       assert.NotNil(t, rNibErr)
+       assert.IsType(t, &common.InternalError{}, rNibErr)
+}
+
+func generateE2tInstance(address string) *entities.E2TInstance {
+       e2tInstance := entities.NewE2TInstance(address)
+
+       e2tInstance.AssociatedRanList = []string{"test1", "test2"}
+
+       return e2tInstance
 }
 
-func TestInit(t *testing.T) {
-       writerPool = nil
-       Init("", 1)
-       assert.NotNil(t, writerPool)
-       assert.NotNil(t, writerPool.New)
-       assert.NotNil(t, writerPool.Destroy)
-       available, created := writerPool.Stats()
-       assert.Equal(t, 0, available, "number of available objects in the writerPool should be 0")
-       assert.Equal(t, 0, created, "number of created objects in the writerPool should be 0")
+func TestSaveE2TAddressesSuccess(t *testing.T) {
+       address := "10.10.2.15:9800"
+       w, sdlInstanceMock := initSdlInstanceMock(namespace)
+
+       e2tAddresses := []string{address}
+       data, err := json.Marshal(e2tAddresses)
+
+       if err != nil {
+               t.Errorf("#rNibWriter_test.TestSaveE2TInfoListSuccess - Failed to marshal E2TInfoList. Error: %v", err)
+       }
+
+       var e error
+       var setExpected []interface{}
+       setExpected = append(setExpected, E2TAddressesKey, data)
+       sdlInstanceMock.On("Set", []interface{}{setExpected}).Return(e)
+
+       rNibErr := w.SaveE2TAddresses(e2tAddresses)
+       assert.Nil(t, rNibErr)
+}
+
+func TestSaveE2TAddressesSdlFailure(t *testing.T) {
+       address := "10.10.2.15:9800"
+       w, sdlInstanceMock := initSdlInstanceMock(namespace)
+
+       e2tAddresses := []string{address}
+       data, err := json.Marshal(e2tAddresses)
+
+       if err != nil {
+               t.Errorf("#rNibWriter_test.TestSaveE2TInfoListSdlFailure - Failed to marshal E2TInfoList. Error: %v", err)
+       }
+
+       expectedErr := errors.New("expected error")
+       var setExpected []interface{}
+       setExpected = append(setExpected, E2TAddressesKey, data)
+       sdlInstanceMock.On("Set", []interface{}{setExpected}).Return(expectedErr)
+
+       rNibErr := w.SaveE2TAddresses(e2tAddresses)
+       assert.NotNil(t, rNibErr)
+       assert.IsType(t, &common.InternalError{}, rNibErr)
 }
 
 //Integration tests
index 0b73b60..f10d275 100644 (file)
@@ -5,8 +5,12 @@ http:
 rmr:
   port: 3801
   maxMsgSize: 65536
+routingManager:
+  baseUrl: http://10.0.2.15:12020/ric/v1/handles/v1/
 notificationResponseBuffer: 100
 bigRedButtonTimeoutSec: 5
 maxConnectionAttempts: 3
 maxRnibConnectionAttempts: 3
 rnibRetryIntervalMs: 10
+keepAliveResponseTimeoutMs: 1500
+keepAliveDelayMs: 500
index d7d0870..f65d10d 100644 (file)
@@ -34,7 +34,7 @@ import (
        "e2mgr/logger"
 )
 
-func (*Context) Init(port string, maxMsgSize int, flags int, logger *logger.Logger) *RmrMessenger {//TODO remove pointer from interface
+func (*Context) Init(port string, maxMsgSize int, flags int, logger *logger.Logger) RmrMessenger {
        pp := C.CString(port)
        defer C.free(unsafe.Pointer(pp))
        logger.Debugf("#rmrCgoApi.Init - Going to initiate RMR router")
@@ -54,10 +54,10 @@ func (*Context) Init(port string, maxMsgSize int, flags int, logger *logger.Logg
        // Each round is about 1000 attempts with a short sleep between each round.
        C.rmr_set_stimeout(ctx.RmrCtx, C.int(1000))
        r := RmrMessenger(ctx)
-       return &r
+       return r
 }
 
-func (ctx *Context) SendMsg(msg *MBuf) (*MBuf, error) {
+func (ctx *Context) SendMsg(msg *MBuf, printLogs bool) (*MBuf, error) {
        ctx.checkContextInitialized()
        ctx.Logger.Debugf("#rmrCgoApi.SendMsg - Going to send message. MBuf: %v", *msg)
        allocatedCMBuf := ctx.getAllocatedCRmrMBuf(ctx.Logger, msg, ctx.MaxMsgSize)
@@ -68,21 +68,21 @@ func (ctx *Context) SendMsg(msg *MBuf) (*MBuf, error) {
                return nil, errors.New(errorMessage)
        }
 
-       //TODO: if debug enabled
-       transactionId := string(*msg.XAction)
-       tmpTid := strings.TrimSpace(transactionId)
-       ctx.Logger.Infof("[E2 Manager -> RMR] #rmrCgoApi.SendMsg - Going to send message %v for transaction id: %s", *msg, tmpTid)
+       if printLogs {
+               //TODO: if debug enabled
+               transactionId := string(*msg.XAction)
+               tmpTid := strings.TrimSpace(transactionId)
+               ctx.Logger.Infof("[E2 Manager -> RMR] #rmrCgoApi.SendMsg - Going to send message %v for transaction id: %s", *msg, tmpTid)
+       }
 
        currCMBuf := C.rmr_send_msg(ctx.RmrCtx, allocatedCMBuf)
        state = currCMBuf.state
-       ctx.Logger.Debugf("#rmrCgoApi.SendMsg - The current message  state: %v, message buffer:%v", state, currCMBuf)
 
        if state != RMR_OK {
                errorMessage := fmt.Sprintf("#rmrCgoApi.SendMsg - Failed to send message. state: %v - %s", state, states[int(state)])
                return nil, errors.New(errorMessage)
        }
 
-       ctx.Logger.Debugf("#rmrCgoApi.SendMsg - The message has been sent successfully ")
        return convertToMBuf(ctx.Logger, currCMBuf), nil
 }
 
@@ -102,18 +102,14 @@ func (ctx *Context) RecvMsg() (*MBuf, error) {
        }
 
        mbuf := convertToMBuf(ctx.Logger, currCMBuf)
-       transactionId := string(*mbuf.XAction)
-       tmpTid := strings.TrimSpace(transactionId)
-       ctx.Logger.Infof("[RMR -> E2 Manager] #rmrCgoApi.RecvMsg - message %v has been received for transaction id: %s", *mbuf, tmpTid)
-       return mbuf, nil
-}
 
-func (ctx *Context) RtsMsg(msg *MBuf) {
-       ctx.checkContextInitialized()
-       ctx.Logger.Debugf("#rmrCgoApi.RtsMsg - Going to return message to the sender")
-       allocatedCMBuf := C.rmr_alloc_msg(ctx.RmrCtx, C.int(ctx.MaxMsgSize))
-       defer C.rmr_free_msg(allocatedCMBuf)
-       C.rmr_rts_msg(ctx.RmrCtx, allocatedCMBuf)
+       if mbuf.MType != E2_TERM_KEEP_ALIVE_RESP {
+
+               transactionId := string(*mbuf.XAction)
+               tmpTid := strings.TrimSpace(transactionId)
+               ctx.Logger.Infof("[RMR -> E2 Manager] #rmrCgoApi.RecvMsg - message %v has been received for transaction id: %s", *mbuf, tmpTid)
+       }
+       return mbuf, nil
 }
 
 func (ctx *Context) IsReady() bool {
index f675b5a..5d226a8 100644 (file)
 //  platform project (RICP).
 
 
-package rmrCgo
+package rmrCgo_test
 
 import (
+       "bytes"
        "e2mgr/logger"
+       "e2mgr/rmrCgo"
        "e2mgr/tests"
-       "bytes"
        "encoding/json"
        "github.com/stretchr/testify/assert"
        "io/ioutil"
        "testing"
-       "time"
 )
 
 var (
-       log     *logger.Logger
-       msgr *RmrMessenger
+       log  *logger.Logger
+       msgr rmrCgo.RmrMessenger
 )
 
-func TestLogger(t *testing.T){
-       var err error
-       log, err = logger.InitLogger(logger.DebugLevel)
-       if err != nil {
-               t.Errorf("#rmrCgoApi_test.TestLogger - failed to initialize logger, error: %s", err)
-       }
-       data :=  map[string]interface{}{"messageType": 1001, "ranIp":"10.0.0.3", "ranPort": 879, "ranName":"test1"}
+func TestLogger(t *testing.T) {
+       log := initLog(t)
+       data := map[string]interface{}{"messageType": 1001, "ranIp": "10.0.0.3", "ranPort": 879, "ranName": "test1"}
        b := new(bytes.Buffer)
        _ = json.NewEncoder(b).Encode(data)
        req := tests.GetHttpRequest()
        boo, _ := ioutil.ReadAll(req.Body)
-       log.Debugf("#rmrCgoApi_test.TestLogger - request header: %v\n; request body: %s\n", req.Header, string(boo))
+       log.Debugf("#rmr_c_go_api_test.TestLogger - request header: %v\n; request body: %s\n", req.Header, string(boo))
 }
 
-
 func TestNewMBufSuccess(t *testing.T) {
-       var err error
-       log, err = logger.InitLogger(logger.DebugLevel)
-       if err != nil {
-               t.Errorf("#rmrCgoApi_test.TestNewMBufSuccess - failed to initialize logger, error: %s", err)
-       }
-       msg := NewMBuf(tests.MessageType, len(tests.DummyPayload),"RanName", &tests.DummyPayload, &tests.DummyXAction)
+       msg := rmrCgo.NewMBuf(tests.MessageType, len(tests.DummyPayload), "RanName", &tests.DummyPayload, &tests.DummyXAction)
        assert.NotNil(t, msg)
        assert.NotEmpty(t, msg.Payload)
        assert.NotEmpty(t, msg.XAction)
@@ -66,80 +56,81 @@ func TestNewMBufSuccess(t *testing.T) {
        assert.Equal(t, msg.Len, len(tests.DummyPayload))
 }
 
-func TestInitFailure(t *testing.T) {
-       var err error
-       log, err = logger.InitLogger(logger.DebugLevel)
-       if err != nil {
-               t.Errorf("#rmrCgoApi_test.TestInitFailure - failed to initialize logger, error: %s", err)
+/*func TestIsReadySuccess(t *testing.T) {
+       log := initLog(t)
+
+       initRmr(tests.GetPort(), tests.MaxMsgSize, tests.Flags, log)
+       if msgr == nil || !msgr.IsReady() {
+               t.Errorf("#rmr_c_go_api_test.TestIsReadySuccess - The rmr router is not ready")
        }
-       go initRmr(tests.GetPort(), tests.MaxMsgSize, tests.Flags, log)
-       time.Sleep(time.Second)
-       if msgr != nil {
-               t.Errorf("The rmr router is ready, should be not ready")
+       msgr.Close()
+}
+func TestSendRecvMsgSuccess(t *testing.T) {
+       log := initLog(t)
+
+       initRmr(tests.GetPort(), tests.MaxMsgSize, tests.Flags, log)
+       if msgr == nil || !msgr.IsReady() {
+               t.Errorf("#rmr_c_go_api_test.TestSendRecvMsgSuccess - The rmr router is not ready")
+       }
+       msg := rmrCgo.NewMBuf(1, tests.MaxMsgSize, "test 1", &tests.DummyPayload, &tests.DummyXAction)
+       log.Debugf("#rmr_c_go_api_test.TestSendRecvMsgSuccess - Going to send the message: %#v\n", msg)
+       result, err := msgr.SendMsg(msg, true)
+
+       assert.Nil(t, err)
+       assert.NotNil(t, result)
+
+       msgR, err := msgr.RecvMsg()
+
+       assert.Nil(t, err)
+       assert.NotNil(t, msgR)
+       msgr.Close()
+}
+
+func TestSendMsgRmrInvalidMsgNumError(t *testing.T) {
+       log := initLog(t)
+
+       initRmr(tests.GetPort(), tests.MaxMsgSize, tests.Flags, log)
+       if msgr == nil || !msgr.IsReady() {
+               t.Errorf("#rmr_c_go_api_test.TestSendMsgRmrInvalidMsgNumError - The rmr router is not ready")
        }
+
+       msg := rmrCgo.NewMBuf(10, tests.MaxMsgSize, "test 1", &tests.DummyPayload, &tests.DummyXAction)
+       log.Debugf("#rmr_c_go_api_test.TestSendMsgRmrInvalidMsgNumError - Going to send the message: %#v\n", msg)
+       result, err := msgr.SendMsg(msg, true)
+
+       assert.NotNil(t, err)
+       assert.Nil(t, result)
+
+       msgr.Close()
 }
 
-//func TestInitSuccess(t *testing.T) {
-//     var err error
-//     log, err = logger.InitLogger(true)
-//     if err != nil {
-//             t.Errorf("#rmrCgoApi_test.TestInitSuccess - failed to initialize logger, error: %s", err)
-//     }
-//     go initRmr(tests.GetPort(), tests.MaxMsgSize, tests.Flags, log)
-//     time.Sleep(time.Second)
-//     if msgr == nil {
-//             t.Errorf("The rmr router is not ready, should be ready")
-//     }
-//}
-
-func TestIsReadyFailure(t *testing.T) {
-       var err error
-       log, err = logger.InitLogger(logger.InfoLevel)
-       if err != nil {
-               t.Errorf("#rmrCgoApi_test.TestIsReadyFailure - failed to initialize logger, error: %s", err)
+func TestSendMsgRmrInvalidPortError(t *testing.T) {
+       log := initLog(t)
+
+       initRmr("tcp:"+strconv.Itoa(5555), tests.MaxMsgSize, tests.Flags, log)
+       if msgr == nil || !msgr.IsReady() {
+               t.Errorf("#rmr_c_go_api_test.TestSendMsgRmrInvalidPortError - The rmr router is not ready")
        }
 
-       go initRmr(tests.GetPort(), tests.MaxMsgSize, tests.Flags, log)
-       time.Sleep(time.Second)
-       assert.True(t, msgr == nil || !(*msgr).IsReady())
+       msg := rmrCgo.NewMBuf(1, tests.MaxMsgSize, "test 1", &tests.DummyPayload, &tests.DummyXAction)
+       log.Debugf("#rmr_c_go_api_test.TestSendMsgRmrInvalidPortError - Going to send the message: %#v\n", msg)
+       result, err := msgr.SendMsg(msg, true)
+
+       assert.NotNil(t, err)
+       assert.Nil(t, result)
+
+       msgr.Close()
 }
 
-//func TestSendRecvMsgSuccess(t *testing.T) {
-//     var err error
-//     log, err = logger.InitLogger(true)
-//     if err != nil {
-//             t.Errorf("#rmrCgoApi_test.TestSendRecvMsgSuccess - failed to initialize logger, error: %s", err)
-//     }
-//     go initRmr(tests.GetPort(), tests.MaxMsgSize, tests.Flags, log)
-//     time.Sleep(time.Second)
-//     if msgr == nil || !(*msgr).IsReady()  {
-//             t.Errorf("#rmrCgoApi_test.TestSendRecvMsgSuccess - The rmr router is not ready")
-//     }
-//     msg := NewMBuf(1, tests.MaxMsgSize, &tests.DummyPayload, &tests.DummyXAction)
-//     log.Debugf("#rmrCgoApi_test.TestSendRecvMsgSuccess - Going to send the message: %#v\n", msg)
-//     msgR, _ := (*msgr).SendMsg(msg)
-//     log.Debugf("#rmrCgoApi_test.TestSendRecvMsgSuccess - The message has been sent %#v\n", msgR)
-//     log.Debugf("#rmrCgoApi_test.TestSendRecvMsgSuccess - The payload: %#v\n", msgR.Payload)
-//     msgR = (*msgr).RecvMsg()
-//     log.Debugf("#rmrCgoApi_test.TestSendRecvMsgSuccess - The message has been received: %#v\n", msgR)
-//     log.Debugf("#rmrCgoApi_test.TestSendRecvMsgSuccess - The payload: %#v\n", msgR.Payload)
-//     (*msgr).Close()
-//}
-
-//func TestIsReadySuccess(t *testing.T) {
-//     var err error
-//     log, err = logger.InitLogger(true)
-//     if err != nil {
-//             t.Errorf("#rmrCgoApi_test.TestIsReadySuccess - The rmr router is not ready")
-//     }
-//     go initRmr(tests.GetPort(), tests.MaxMsgSize, tests.Flags, log)
-//     time.Sleep(time.Second)
-//     if msgr == nil || !(*msgr).IsReady()  {
-//             t.Errorf("#rmrCgoApi_test.TestIsReadySuccess - The rmr router is not ready")
-//     }
-//}
-
-func initRmr(port string, maxMsgSize int, flags int, log *logger.Logger){
-       var ctx *Context
+func initRmr(port string, maxMsgSize int, flags int, log *logger.Logger) {
+       var ctx *rmrCgo.Context
        msgr = ctx.Init(port, maxMsgSize, flags, log)
+}*/
+
+func initLog(t *testing.T) *logger.Logger {
+       log, err := logger.InitLogger(logger.DebugLevel)
+       if err != nil {
+               t.Errorf("#rmr_c_go_api_test.initLog - failed to initialize logger, error: %s", err)
+       }
+       return log
 }
index 3f8b189..eff707c 100644 (file)
@@ -74,6 +74,8 @@ const (
        RAN_CONNECTED                                            = C.RAN_CONNECTED
        RAN_RESTARTED                                            = C.RAN_RESTARTED
        RAN_RECONFIGURED                                         = C.RAN_RECONFIGURED
+       E2_TERM_KEEP_ALIVE_REQ                           = C.E2_TERM_KEEP_ALIVE_REQ
+       E2_TERM_KEEP_ALIVE_RESP                          = C.E2_TERM_KEEP_ALIVE_RESP
 )
 
 const (
@@ -138,10 +140,9 @@ type Context struct {
 }
 
 type RmrMessenger interface {
-       Init(port string, maxMsgSize int, flags int, logger *logger.Logger) *RmrMessenger
-       SendMsg(msg *MBuf) (*MBuf, error)
+       Init(port string, maxMsgSize int, flags int, logger *logger.Logger) RmrMessenger
+       SendMsg(msg *MBuf, printLogs bool) (*MBuf, error)
        RecvMsg() (*MBuf, error)
-       RtsMsg(msg *MBuf)
        IsReady() bool
        Close()
 }
diff --git a/E2Manager/rnibBuilders/node_info_builder_test.go b/E2Manager/rnibBuilders/node_info_builder_test.go
deleted file mode 100644 (file)
index fb95f8a..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-//
-// Copyright 2019 AT&T Intellectual Property
-// Copyright 2019 Nokia
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
-//  platform project (RICP).
-
-
-package rnibBuilders
-
-import (
-       "e2mgr/models"
-       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
-       "github.com/stretchr/testify/assert"
-       "testing"
-)
-
-const ranName = "name"
-const ranIP = "ip"
-const ranPort = uint16(30000)
-
-func TestCreateInitialNodeInfo(t *testing.T) {
-       requestDetails :=  &models.SetupRequest{
-               RanName: ranName,
-               RanPort:ranPort,
-               RanIp:ranIP,
-       }
-       nodebInfo, identity := CreateInitialNodeInfo(requestDetails, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
-       assert.Equal(t, identity.InventoryName, ranName)
-       assert.Equal(t, nodebInfo.Ip, ranIP)
-       assert.Equal(t, nodebInfo.ConnectionStatus, entities.ConnectionStatus_CONNECTING)
-       assert.Equal(t, nodebInfo.E2ApplicationProtocol, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
-       assert.Equal(t, nodebInfo.Port, uint32(ranPort))
-}
\ No newline at end of file
index db4c6b0..8dfc5bc 100644 (file)
@@ -20,4 +20,5 @@ rte|1200|10.0.2.15:4801
 rte|1210|10.0.2.15:4801
 rte|1220|10.0.2.15:4801
 rte|10090|10.0.2.15:38000
+rte|1101|10.0.2.15:38000
 newrt|end
diff --git a/E2Manager/router_test.txt b/E2Manager/router_test.txt
new file mode 100644 (file)
index 0000000..2315519
--- /dev/null
@@ -0,0 +1,3 @@
+newrt|start
+rte|1|127.0.0.1:3801
+newrt|end
index 60f3330..0a8eb8d 100644 (file)
@@ -29,10 +29,10 @@ import (
 type RmrReceiver struct {
        logger    *logger.Logger
        nManager  *notificationmanager.NotificationManager
-       messenger *rmrCgo.RmrMessenger
+       messenger rmrCgo.RmrMessenger
 }
 
-func NewRmrReceiver(logger *logger.Logger, messenger *rmrCgo.RmrMessenger, nManager *notificationmanager.NotificationManager) *RmrReceiver {
+func NewRmrReceiver(logger *logger.Logger, messenger rmrCgo.RmrMessenger, nManager *notificationmanager.NotificationManager) *RmrReceiver {
        return &RmrReceiver{
                logger:    logger,
                nManager:  nManager,
@@ -43,14 +43,15 @@ func NewRmrReceiver(logger *logger.Logger, messenger *rmrCgo.RmrMessenger, nMana
 func (r *RmrReceiver) ListenAndHandle() {
 
        for {
-               mbuf, err := (*r.messenger).RecvMsg()
-               r.logger.Debugf("#RmrReceiver.ListenAndHandle - Going to handle received message: %#v\n", mbuf)
+               mbuf, err := r.messenger.RecvMsg()
 
                if err != nil {
-                       // TODO: error handling?
+                       r.logger.Errorf("#RmrReceiver.ListenAndHandle - error: %s", err)
                        continue
                }
 
+               r.logger.Debugf("#RmrReceiver.ListenAndHandle - Going to handle received message: %#v\n", mbuf)
+
                // TODO: go routine?
                _ = r.nManager.HandleMessage(mbuf)
        }
index c1729ce..5e766f7 100644 (file)
 package rmrreceiver
 
 import (
+       "e2mgr/clients"
        "e2mgr/configuration"
-       "e2mgr/converters"
        "e2mgr/logger"
        "e2mgr/managers"
        "e2mgr/managers/notificationmanager"
        "e2mgr/mocks"
        "e2mgr/providers/rmrmsghandlerprovider"
-       "e2mgr/rNibWriter"
        "e2mgr/rmrCgo"
        "e2mgr/services"
        "e2mgr/services/rmrsender"
        "e2mgr/tests"
        "fmt"
-       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
        "testing"
        "time"
 )
@@ -49,7 +47,7 @@ func TestListenAndHandle(t *testing.T) {
        time.Sleep(time.Microsecond * 10)
 }
 
-func initRmrMessenger(log *logger.Logger) *rmrCgo.RmrMessenger {
+func initRmrMessenger(log *logger.Logger) rmrCgo.RmrMessenger {
        rmrMessengerMock := &mocks.RmrMessengerMock{}
        rmrMessenger := rmrCgo.RmrMessenger(rmrMessengerMock)
        rmrMessengerMock.On("Init", tests.GetPort(), tests.MaxMsgSize, tests.Flags, log).Return(&rmrMessenger)
@@ -58,32 +56,24 @@ func initRmrMessenger(log *logger.Logger) *rmrCgo.RmrMessenger {
        var buf *rmrCgo.MBuf
        e := fmt.Errorf("test error")
        rmrMessengerMock.On("RecvMsg").Return(buf, e)
-       return &rmrMessenger
+       return rmrMessenger
 }
 
 func initRmrReceiver(logger *logger.Logger) *RmrReceiver {
        config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
 
        readerMock := &mocks.RnibReaderMock{}
-       rnibReaderProvider := func() reader.RNibReader {
-               return readerMock
-       }
        writerMock := &mocks.RnibWriterMock{}
-       rnibWriterProvider := func() rNibWriter.RNibWriter {
-               return writerMock
-       }
+       httpClient := &mocks.HttpClientMock{}
 
-       rnibDataService := services.NewRnibDataService(logger, config, rnibReaderProvider, rnibWriterProvider)
+       rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
        rmrMessenger := initRmrMessenger(logger)
        rmrSender := rmrsender.NewRmrSender(logger, rmrMessenger)
        ranSetupManager := managers.NewRanSetupManager(logger, rmrSender, rnibDataService)
-       ranReconnectionManager := managers.NewRanReconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, ranSetupManager)
-       ranStatusChangeManager := managers.NewRanStatusChangeManager(logger, rmrSender)
-       x2SetupResponseConverter := converters.NewX2SetupResponseConverter(logger)
-       x2SetupResponseManager := managers.NewX2SetupResponseManager(x2SetupResponseConverter)
-       x2SetupFailureResponseConverter := converters.NewX2SetupFailureResponseConverter(logger)
-       x2SetupFailureResponseManager := managers.NewX2SetupFailureResponseManager(x2SetupFailureResponseConverter)
-       rmrNotificationHandlerProvider := rmrmsghandlerprovider.NewNotificationHandlerProvider(logger, rnibDataService, ranReconnectionManager, ranStatusChangeManager, rmrSender, x2SetupResponseManager, x2SetupFailureResponseManager )
+       e2tInstancesManager := managers.NewE2TInstancesManager(rnibDataService, logger)
+       routingManagerClient := clients.NewRoutingManagerClient(logger, config, httpClient)
+       rmrNotificationHandlerProvider := rmrmsghandlerprovider.NewNotificationHandlerProvider()
+       rmrNotificationHandlerProvider.Init(logger, config, rnibDataService, rmrSender, ranSetupManager, e2tInstancesManager, routingManagerClient)
        notificationManager := notificationmanager.NewNotificationManager(logger, rmrNotificationHandlerProvider)
        return NewRmrReceiver(logger, rmrMessenger, notificationManager)
 }
index 1d832d9..10e6a42 100644 (file)
@@ -28,10 +28,10 @@ import (
 
 type RmrSender struct {
        logger    *logger.Logger
-       messenger *rmrCgo.RmrMessenger
+       messenger rmrCgo.RmrMessenger
 }
 
-func NewRmrSender(logger *logger.Logger, messenger *rmrCgo.RmrMessenger) *RmrSender {
+func NewRmrSender(logger *logger.Logger, messenger rmrCgo.RmrMessenger) *RmrSender {
        return &RmrSender{
                logger:    logger,
                messenger: messenger,
@@ -39,10 +39,9 @@ func NewRmrSender(logger *logger.Logger, messenger *rmrCgo.RmrMessenger) *RmrSen
 }
 
 func (r *RmrSender) Send(rmrMessage *models.RmrMessage) error {
-       transactionIdByteArr := []byte(rmrMessage.RanName)
-       msg := rmrCgo.NewMBuf(rmrMessage.MsgType, len(rmrMessage.Payload), rmrMessage.RanName, &rmrMessage.Payload, &transactionIdByteArr)
+       msg := rmrCgo.NewMBuf(rmrMessage.MsgType, len(rmrMessage.Payload), rmrMessage.RanName, &rmrMessage.Payload, &rmrMessage.XAction)
 
-       _, err := (*r.messenger).SendMsg(msg)
+       _, err := r.messenger.SendMsg(msg, true)
 
        if err != nil {
                r.logger.Errorf("#RmrSender.Send - RAN name: %s , Message type: %d - Failed sending message. Error: %v", rmrMessage.RanName, rmrMessage.MsgType, err)
@@ -52,3 +51,16 @@ func (r *RmrSender) Send(rmrMessage *models.RmrMessage) error {
        r.logger.Infof("#RmrSender.Send - RAN name: %s , Message type: %d - Successfully sent RMR message", rmrMessage.RanName, rmrMessage.MsgType)
        return nil
 }
+
+func (r *RmrSender) SendWithoutLogs(rmrMessage *models.RmrMessage) error {
+       msg := rmrCgo.NewMBuf(rmrMessage.MsgType, len(rmrMessage.Payload), rmrMessage.RanName, &rmrMessage.Payload, &rmrMessage.XAction)
+
+       _, err := r.messenger.SendMsg(msg, false)
+
+       if err != nil {
+               r.logger.Errorf("#RmrSender.Send - RAN name: %s , Message type: %d - Failed sending message. Error: %v", rmrMessage.RanName, rmrMessage.MsgType, err)
+               return err
+       }
+
+       return nil
+}
index df53959..bc45307 100644 (file)
@@ -53,15 +53,15 @@ func TestRmrSenderSendSuccess(t *testing.T) {
 
        ranName := "test"
        payload := []byte("some payload")
-       xaction := []byte(ranName)
-       mbuf := rmrCgo.NewMBuf(123, len(payload), ranName, &payload, &xaction)
-       rmrMessengerMock.On("SendMsg", mbuf).Return(&rmrCgo.MBuf{}, nil)
-       rmrMsg := models.NewRmrMessage(123, ranName, payload)
+       var xAction []byte
+       mbuf := rmrCgo.NewMBuf(123, len(payload), ranName, &payload, &xAction)
+       rmrMessengerMock.On("SendMsg", mbuf, true).Return(&rmrCgo.MBuf{}, nil)
+       rmrMsg := models.NewRmrMessage(123, ranName, payload, xAction)
        rmrMessenger := rmrCgo.RmrMessenger(rmrMessengerMock)
-       rmrSender := NewRmrSender(logger, &rmrMessenger)
+       rmrSender := NewRmrSender(logger, rmrMessenger)
        err := rmrSender.Send(rmrMsg)
        assert.Nil(t, err)
-       rmrMessengerMock.AssertCalled(t, "SendMsg",mbuf)
+       rmrMessengerMock.AssertCalled(t, "SendMsg",mbuf, true)
 
 }
 
@@ -70,14 +70,14 @@ func TestRmrSenderSendFailure(t *testing.T) {
 
        ranName := "test"
        payload := []byte("some payload")
-       xaction := []byte(ranName)
-       mbuf := rmrCgo.NewMBuf(123, len(payload), ranName, &payload, &xaction)
-       rmrMessengerMock.On("SendMsg", mbuf).Return(mbuf, fmt.Errorf("rmr send failure"))
-       rmrMsg := models.NewRmrMessage(123, ranName, payload)
+       var xAction []byte
+       mbuf := rmrCgo.NewMBuf(123, len(payload), ranName, &payload, &xAction)
+       rmrMessengerMock.On("SendMsg", mbuf, true).Return(mbuf, fmt.Errorf("rmr send failure"))
+       rmrMsg := models.NewRmrMessage(123, ranName, payload, xAction)
        rmrMessenger := rmrCgo.RmrMessenger(rmrMessengerMock)
-       rmrSender := NewRmrSender(logger, &rmrMessenger)
+       rmrSender := NewRmrSender(logger, rmrMessenger)
        err := rmrSender.Send(rmrMsg)
-       rmrMessengerMock.AssertCalled(t, "SendMsg",mbuf)
+       rmrMessengerMock.AssertCalled(t, "SendMsg",mbuf, true)
        assert.NotNil(t, err)
 }
 
index 38b4723..1274c53 100644 (file)
@@ -24,9 +24,9 @@ import (
        "e2mgr/configuration"
        "e2mgr/logger"
        "e2mgr/rNibWriter"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
-       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
        "net"
        "time"
 )
@@ -38,23 +38,32 @@ type RNibDataService interface {
        GetNodeb(ranName string) (*entities.NodebInfo, error)
        GetListNodebIds() ([]*entities.NbIdentity, error)
        PingRnib() bool
+       GetE2TInstance(address string) (*entities.E2TInstance, error)
+       GetE2TInstances(addresses []string) ([]*entities.E2TInstance, error)
+       GetE2TAddresses() ([]string, error)
+       SaveE2TInstance(e2tInstance *entities.E2TInstance) error
+       SaveE2TAddresses(addresses []string) error
+       GetE2TInstanceNoLogs(address string) (*entities.E2TInstance, error)
+       GetE2TInstancesNoLogs(addresses []string) ([]*entities.E2TInstance, error)
+       SaveE2TInstanceNoLogs(e2tInstance *entities.E2TInstance) error
+       GetE2TAddressesNoLogs() ([]string, error)
 }
 
 type rNibDataService struct {
-       logger             *logger.Logger
-       rnibReaderProvider func() reader.RNibReader
-       rnibWriterProvider func() rNibWriter.RNibWriter
-       maxAttempts        int
-       retryInterval      time.Duration
+       logger        *logger.Logger
+       rnibReader    reader.RNibReader
+       rnibWriter    rNibWriter.RNibWriter
+       maxAttempts   int
+       retryInterval time.Duration
 }
 
-func NewRnibDataService(logger *logger.Logger, config *configuration.Configuration, rnibReaderProvider func() reader.RNibReader, rnibWriterProvider func() rNibWriter.RNibWriter) *rNibDataService {
+func NewRnibDataService(logger *logger.Logger, config *configuration.Configuration, rnibReader reader.RNibReader, rnibWriter rNibWriter.RNibWriter) *rNibDataService {
        return &rNibDataService{
-               logger:             logger,
-               rnibReaderProvider: rnibReaderProvider,
-               rnibWriterProvider: rnibWriterProvider,
-               maxAttempts:        config.MaxRnibConnectionAttempts,
-               retryInterval:      time.Duration(config.RnibRetryIntervalMs) * time.Millisecond,
+               logger:        logger,
+               rnibReader:    rnibReader,
+               rnibWriter:    rnibWriter,
+               maxAttempts:   config.MaxRnibConnectionAttempts,
+               retryInterval: time.Duration(config.RnibRetryIntervalMs) * time.Millisecond,
        }
 }
 
@@ -62,7 +71,7 @@ func (w *rNibDataService) UpdateNodebInfo(nodebInfo *entities.NodebInfo) error {
        w.logger.Infof("#RnibDataService.UpdateNodebInfo - nodebInfo: %s", nodebInfo)
 
        err := w.retry("UpdateNodebInfo", func() (err error) {
-               err = w.rnibWriterProvider().UpdateNodebInfo(nodebInfo)
+               err = w.rnibWriter.UpdateNodebInfo(nodebInfo)
                return
        })
 
@@ -73,7 +82,7 @@ func (w *rNibDataService) SaveNodeb(nbIdentity *entities.NbIdentity, nb *entitie
        w.logger.Infof("#RnibDataService.SaveNodeb - nbIdentity: %s, nodebInfo: %s", nbIdentity, nb)
 
        err := w.retry("SaveNodeb", func() (err error) {
-               err = w.rnibWriterProvider().SaveNodeb(nbIdentity, nb)
+               err = w.rnibWriter.SaveNodeb(nbIdentity, nb)
                return
        })
 
@@ -84,7 +93,7 @@ func (w *rNibDataService) SaveRanLoadInformation(inventoryName string, ranLoadIn
        w.logger.Infof("#RnibDataService.SaveRanLoadInformation - inventoryName: %s, ranLoadInformation: %s", inventoryName, ranLoadInformation)
 
        err := w.retry("SaveRanLoadInformation", func() (err error) {
-               err = w.rnibWriterProvider().SaveRanLoadInformation(inventoryName, ranLoadInformation)
+               err = w.rnibWriter.SaveRanLoadInformation(inventoryName, ranLoadInformation)
                return
        })
 
@@ -97,7 +106,7 @@ func (w *rNibDataService) GetNodeb(ranName string) (*entities.NodebInfo, error)
        var nodeb *entities.NodebInfo = nil
 
        err := w.retry("GetNodeb", func() (err error) {
-               nodeb, err = w.rnibReaderProvider().GetNodeb(ranName)
+               nodeb, err = w.rnibReader.GetNodeb(ranName)
                return
        })
 
@@ -110,16 +119,121 @@ func (w *rNibDataService) GetListNodebIds() ([]*entities.NbIdentity, error) {
        var nodeIds []*entities.NbIdentity = nil
 
        err := w.retry("GetListNodebIds", func() (err error) {
-               nodeIds, err = w.rnibReaderProvider().GetListNodebIds()
+               nodeIds, err = w.rnibReader.GetListNodebIds()
                return
        })
 
        return nodeIds, err
 }
 
+func (w *rNibDataService) GetE2TInstance(address string) (*entities.E2TInstance, error) {
+       var e2tInstance *entities.E2TInstance = nil
+
+       err := w.retry("GetE2TInstance", func() (err error) {
+               e2tInstance, err = w.rnibReader.GetE2TInstance(address)
+               return
+       })
+
+       if err == nil {
+               w.logger.Infof("#RnibDataService.GetE2TInstance - E2T instance address: %s, state: %s, associated RANs count: %d, keep Alive ts: %d", e2tInstance.Address, e2tInstance.State, len(e2tInstance.AssociatedRanList), e2tInstance.KeepAliveTimestamp)
+       }
+
+       return e2tInstance, err
+}
+
+func (w *rNibDataService) GetE2TInstanceNoLogs(address string) (*entities.E2TInstance, error) {
+       var e2tInstance *entities.E2TInstance = nil
+
+       err := w.retry("GetE2TInstance", func() (err error) {
+               e2tInstance, err = w.rnibReader.GetE2TInstance(address)
+               return
+       })
+
+       return e2tInstance, err
+}
+
+func (w *rNibDataService) GetE2TInstances(addresses []string) ([]*entities.E2TInstance, error) {
+       w.logger.Infof("#RnibDataService.GetE2TInstances - addresses: %s", addresses)
+       var e2tInstances []*entities.E2TInstance = nil
+
+       err := w.retry("GetE2TInstance", func() (err error) {
+               e2tInstances, err = w.rnibReader.GetE2TInstances(addresses)
+               return
+       })
+
+       return e2tInstances, err
+}
+
+func (w *rNibDataService) GetE2TInstancesNoLogs(addresses []string) ([]*entities.E2TInstance, error) {
+
+       var e2tInstances []*entities.E2TInstance = nil
+
+       err := w.retry("GetE2TInstance", func() (err error) {
+               e2tInstances, err = w.rnibReader.GetE2TInstances(addresses)
+               return
+       })
+
+       return e2tInstances, err
+}
+
+func (w *rNibDataService) GetE2TAddresses() ([]string, error) {
+
+       var e2tAddresses []string = nil
+
+       err := w.retry("GetE2TAddresses", func() (err error) {
+               e2tAddresses, err = w.rnibReader.GetE2TAddresses()
+               return
+       })
+
+       if err == nil {
+               w.logger.Infof("#RnibDataService.GetE2TAddresses - addresses: %s", e2tAddresses)
+       }
+
+       return e2tAddresses, err
+}
+
+func (w *rNibDataService) GetE2TAddressesNoLogs() ([]string, error) {
+
+       var e2tAddresses []string = nil
+
+       err := w.retry("GetE2TAddresses", func() (err error) {
+               e2tAddresses, err = w.rnibReader.GetE2TAddresses()
+               return
+       })
+
+       return e2tAddresses, err
+}
+
+func (w *rNibDataService) SaveE2TInstance(e2tInstance *entities.E2TInstance) error {
+       w.logger.Infof("#RnibDataService.SaveE2TInstance - E2T instance address: %s, state: %s, associated RANs count: %d, keep Alive ts: %d", e2tInstance.Address, e2tInstance.State, len(e2tInstance.AssociatedRanList), e2tInstance.KeepAliveTimestamp)
+
+       return w.SaveE2TInstanceNoLogs(e2tInstance)
+}
+
+func (w *rNibDataService) SaveE2TInstanceNoLogs(e2tInstance *entities.E2TInstance) error {
+
+       err := w.retry("SaveE2TInstance", func() (err error) {
+               err = w.rnibWriter.SaveE2TInstance(e2tInstance)
+               return
+       })
+
+       return err
+}
+
+func (w *rNibDataService) SaveE2TAddresses(addresses []string) error {
+       w.logger.Infof("#RnibDataService.SaveE2TAddresses - addresses: %s", addresses)
+
+       err := w.retry("SaveE2TAddresses", func() (err error) {
+               err = w.rnibWriter.SaveE2TAddresses(addresses)
+               return
+       })
+
+       return err
+}
+
 func (w *rNibDataService) PingRnib() bool {
        err := w.retry("GetListNodebIds", func() (err error) {
-               _, err = w.rnibReaderProvider().GetListNodebIds()
+               _, err = w.rnibReader.GetListNodebIds()
                return
        })
 
@@ -147,7 +261,6 @@ func (w *rNibDataService) retry(rnibFunc string, f func() error) (err error) {
        }
 }
 
-
 func isRnibConnectionError(err error) bool {
        internalErr, ok := err.(*common.InternalError)
        if !ok {
index fb86fe8..ab67a32 100644 (file)
@@ -24,11 +24,9 @@ import (
        "e2mgr/configuration"
        "e2mgr/logger"
        "e2mgr/mocks"
-       "e2mgr/rNibWriter"
        "fmt"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
-       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
        "github.com/stretchr/testify/assert"
        "net"
        "strings"
@@ -48,16 +46,12 @@ func setupRnibDataServiceTestWithMaxAttempts(t *testing.T, maxAttempts int) (*rN
        config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: maxAttempts}
 
        readerMock := &mocks.RnibReaderMock{}
-       rnibReaderProvider := func() reader.RNibReader {
-               return readerMock
-       }
+
 
        writerMock := &mocks.RnibWriterMock{}
-       rnibWriterProvider := func() rNibWriter.RNibWriter {
-               return writerMock
-       }
 
-       rnibDataService := NewRnibDataService(logger, config, rnibReaderProvider, rnibWriterProvider)
+
+       rnibDataService := NewRnibDataService(logger, config, readerMock, writerMock)
        assert.NotNil(t, rnibDataService)
 
        return rnibDataService, readerMock, writerMock
@@ -277,3 +271,44 @@ func TestPingRnibOkOtherError(t *testing.T) {
 //     assert.True(t, strings.Contains(err.Error(),"connection failure", ))
 //     assert.Equal(t, nodeIds, res)
 //}
+
+func TestGetE2TInstanceConnFailure(t *testing.T) {
+       rnibDataService, readerMock, _ := setupRnibDataServiceTest(t)
+
+       address := "10.10.5.20:3200"
+       var e2tInstance *entities.E2TInstance = nil
+       mockErr := &common.InternalError{Err: &net.OpError{Err: fmt.Errorf("connection error")}}
+       readerMock.On("GetE2TInstance", address).Return(e2tInstance, mockErr)
+
+       res, err := rnibDataService.GetE2TInstance(address)
+       readerMock.AssertNumberOfCalls(t, "GetE2TInstance", 3)
+       assert.Nil(t, res)
+       assert.NotNil(t, err)
+}
+
+func TestGetE2TInstanceOkNoError(t *testing.T) {
+       rnibDataService, readerMock, _ := setupRnibDataServiceTest(t)
+
+       address := "10.10.5.20:3200"
+       e2tInstance := &entities.E2TInstance{}
+       readerMock.On("GetE2TInstance", address).Return(e2tInstance, nil)
+
+       res, err := rnibDataService.GetE2TInstance(address)
+       readerMock.AssertNumberOfCalls(t, "GetE2TInstance", 1)
+       assert.Nil(t, err)
+       assert.Equal(t, e2tInstance, res)
+}
+
+func TestGetE2TInstanceOkOtherError(t *testing.T) {
+       rnibDataService, readerMock, _ := setupRnibDataServiceTest(t)
+
+       address := "10.10.5.20:3200"
+       var e2tInstance *entities.E2TInstance = nil
+       mockErr := &common.InternalError{Err: fmt.Errorf("non connection error")}
+       readerMock.On("GetE2TInstance", address).Return(e2tInstance, mockErr)
+
+       res, err := rnibDataService.GetE2TInstance(address)
+       readerMock.AssertNumberOfCalls(t, "GetE2TInstance", 1)
+       assert.Nil(t, res)
+       assert.NotNil(t, err)
+}
index 82df174..8095663 100644 (file)
@@ -31,7 +31,7 @@ import (
 
 const (
        MaxMsgSize  int    = 4096
-       Port        int    = 5555
+       Port        int    = 3801
        Flags       int    = 0
        MessageType int    = 1001
        RanPort     uint16 = 879
diff --git a/E2Manager/tests/utils.go b/E2Manager/tests/utils.go
new file mode 100644 (file)
index 0000000..894f554
--- /dev/null
@@ -0,0 +1,59 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package tests
+
+import (
+       "e2mgr/configuration"
+       "e2mgr/logger"
+       "e2mgr/mocks"
+       "e2mgr/rmrCgo"
+       "e2mgr/services"
+       "e2mgr/services/rmrsender"
+       "testing"
+)
+
+func InitLog(t *testing.T) *logger.Logger {
+       log, err := logger.InitLogger(logger.InfoLevel)
+       if err != nil {
+               t.Errorf("#test.utils.InitLog - failed to initialize logger, error: %s", err)
+       }
+       return log
+}
+
+func InitRmrSender(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *rmrsender.RmrSender {
+       rmrMessenger := rmrCgo.RmrMessenger(rmrMessengerMock)
+       rmrMessengerMock.On("Init", GetPort(), MaxMsgSize, Flags, log).Return(&rmrMessenger)
+       return rmrsender.NewRmrSender(log, rmrMessenger)
+}
+
+func InitRnibDataService(t *testing.T) services.RNibDataService{
+
+       logger := InitLog(t)
+       config := InitConfiguration()
+
+       readerMock := &mocks.RnibReaderMock{}
+       writerMock := &mocks.RnibWriterMock{}
+
+       return services.NewRnibDataService(logger, config, readerMock, writerMock)
+}
+
+func InitConfiguration() *configuration.Configuration{
+       return &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
+}
+
+
index 685ac2d..65d5014 100644 (file)
@@ -20,7 +20,7 @@ openapi: 3.0.0
 info:
   title: E2 Manager Service
   description: E2 Manager Service APIs
-  version: 2.0.5
+  version: 3.0.3
 servers:
   - url: 'http://{apiRoot}/v1'
     variables:
@@ -205,6 +205,26 @@ paths:
       responses:
         '200':
           description: OK
+  /e2t/list:
+    get:
+      tags:
+        - e2t
+      summary: Gets a list of all E2T Instances address and their associated RANs
+      responses:
+        '200':
+          description: Successful operation
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  $ref: '#/components/schemas/E2tIdentity'
+        '500':
+          description: Internal Error
+          content:
+            application/problem+json:
+              schema:
+                $ref: '#/components/schemas/ErrorResponse'
 components:
   schemas:
     SetupRequest:
@@ -919,3 +939,27 @@ radioNetwork:pDCP-Overload]
         errorMessage:
           type: string
           description: Human readable text
+    E2tIdentity:
+      type: object
+      required:
+        - e2tAddress
+        - ranNames
+      properties:
+        e2tAddress:
+          type: string
+        ranNames:
+          items:
+            type: string
+          type: array
+    E2tErrorResponse:
+      type: object
+      required:
+        - errorCode
+        - errorMessage
+      properties:
+        errorCode:
+          type: string
+          description: '500 - RNIB error, 501 - internal problem'
+        errorMessage:
+          type: string
+          description: Human readable text
\ No newline at end of file
index 81c71b6..09e3399 100644 (file)
@@ -20,7 +20,7 @@ Release-Notes
 =============
 
 
-This document provides the release notes for the Amber Release of E2Manager
+This document provides the release notes for the Amber release of E2Manager
 
 .. contents::
    :depth: 3
@@ -44,7 +44,7 @@ Version history
 
 Summary
 -------
-The Amber release of E2Manager supports The following flows:
+The Amber release of E2Manager supports the following flows:
        - ENDC Setup
        - X2 Setup
        - ENDC Configuration Update
diff --git a/tools/RoutingManagerSimulator/Dockerfile b/tools/RoutingManagerSimulator/Dockerfile
new file mode 100644 (file)
index 0000000..66bff79
--- /dev/null
@@ -0,0 +1,34 @@
+##############################################################################
+#
+#   Copyright (c) 2019 AT&T Intellectual Property.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+##############################################################################
+
+FROM nexus3.o-ran-sc.org:10004/bldr-ubuntu16-c-go:2-u16.04-nng as ubuntu
+
+WORKDIR /opt/rmsimulator
+COPY . . 
+ENV PATH=$PATH:/usr/local/go/bin:/usr/lib/go-1.12/bin
+
+RUN go build main.go
+
+
+FROM ubuntu:16.04
+COPY --from=ubuntu /opt/rmsimulator/main /opt/rmsimulator/main
+COPY --from=ubuntu /opt/rmsimulator/resources /opt/rmsimulator/resources
+
+WORKDIR /opt/rmsimulator
+#CMD mkdir -p resources/conf  exec ./xappmock
+CMD exec ./main
diff --git a/tools/RoutingManagerSimulator/api/swagger.yaml b/tools/RoutingManagerSimulator/api/swagger.yaml
new file mode 100755 (executable)
index 0000000..db343d7
--- /dev/null
@@ -0,0 +1,363 @@
+---
+swagger: "2.0"
+info:
+  description: "This is the Swagger/OpenAPI 2.0 definition of Routing Manager's Northbound\
+    \ API."
+  version: "0.4.0"
+  title: "Routing Manager"
+  license:
+    name: "Apache 2.0"
+    url: "http://www.apache.org/licenses/LICENSE-2.0.html"
+host: "rtmgr"
+basePath: "/ric/v1"
+tags:
+- name: "handle"
+  description: "Available handles"
+- name: "health"
+  description: "Health of the system"
+schemes:
+- "http"
+paths:
+  /health:
+    get:
+      tags:
+      - "health"
+      summary: "Retrive the health of Routing Manager"
+      description: "By performing a GET method on the health resource, the API caller\
+        \ is able to retrieve the health of Routing Manager"
+      operationId: "get_health"
+      consumes:
+      - "application/json"
+      produces:
+      - "application/json"
+      parameters: []
+      responses:
+        "200":
+          description: "The health of the system"
+          schema:
+            $ref: "#/definitions/health-status"
+  /handles:
+    get:
+      tags:
+      - "handle"
+      summary: "Placeholder for further usage"
+      description: "Placeholder for further usage."
+      operationId: "get_handles"
+      consumes:
+      - "application/json"
+      produces:
+      - "application/json"
+      parameters: []
+      responses:
+        "200":
+          description: "Dummy response"
+  /handles/xapp-handle:
+    post:
+      tags:
+      - "handle"
+      summary: "Provide callback"
+      description: "By performing a POST method on the xapp-handle resource, the API\
+        \ caller is able to perform a callback on Routing Manager."
+      operationId: "provide_xapp_handle"
+      consumes:
+      - "application/json"
+      produces:
+      - "application/json"
+      parameters:
+      - in: "body"
+        name: "xapp-callback-data"
+        description: "xApp related callback data"
+        required: true
+        schema:
+          $ref: "#/definitions/xapp-callback-data"
+        x-exportParamName: "XappCallbackData"
+      responses:
+        "201":
+          description: "Callback received"
+        "400":
+          description: "Invalid data"
+  /handles/xapp-subscription-handle:
+    post:
+      tags:
+      - "handle"
+      summary: "API for updating about new xapp subscription"
+      description: "By performing a POST method on the xapp-subscription-handle resource,\
+        \ the API caller is able to update the Routing manager about the creation\
+        \ of new subscription by an Xapp instance."
+      operationId: "provide_xapp_subscription_handle"
+      consumes:
+      - "application/json"
+      produces:
+      - "application/json"
+      parameters:
+      - in: "body"
+        name: "xapp-subscription-data"
+        description: "xApp related subscription data"
+        required: true
+        schema:
+          $ref: "#/definitions/xapp-subscription-data"
+        x-exportParamName: "XappSubscriptionData"
+      responses:
+        "201":
+          description: "Xapp Subscription data received"
+        "400":
+          description: "Invalid data"
+    delete:
+      tags:
+      - "handle"
+      summary: "API for deleting an xapp subscription"
+      description: "By performing the delete operation on xapp-subscription-handle\
+        \ resource, the API caller will be able to update routing manager about the\
+        \ deletion of an xapp's subscription"
+      operationId: "delete_xapp_subscription_handle"
+      consumes:
+      - "application/json"
+      parameters:
+      - in: "body"
+        name: "xapp-subscription-data"
+        description: "xApp related subscription data"
+        required: true
+        schema:
+          $ref: "#/definitions/xapp-subscription-data"
+        x-exportParamName: "XappSubscriptionData"
+      responses:
+        "200":
+          description: "Xapp Subscription deleted"
+        "204":
+          description: "Content not found"
+  /handles/xapp-subscription-handle/{subscription_id}:
+    put:
+      tags:
+      - "handle"
+      summary: "API for updating the subscriber xApp list"
+      description: "By performing a PUT method on a xapp-subscription-handle/{subscription_id}\
+        \ resource, the API caller is able to update the Routing manager about the\
+        \ list of subscriber xApps related to the subscription denoted by the {subsription_id}."
+      operationId: "update_xapp_subscription_handle"
+      consumes:
+      - "application/json"
+      produces:
+      - "application/json"
+      parameters:
+      - name: "subscription_id"
+        in: "path"
+        description: "Subscription ID"
+        required: true
+        type: "integer"
+        format: "uint16"
+        x-exportParamName: "SubscriptionId"
+      - in: "body"
+        name: "xapp-list"
+        description: "xApp list"
+        required: true
+        schema:
+          $ref: "#/definitions/xapp-list"
+        x-exportParamName: "XappList"
+      responses:
+        "201":
+          description: "Xapp list received"
+        "400":
+          description: "Invalid data"
+  /handles/v1/e2t:
+    post:
+      tags:
+      - "handle"
+      summary: "API for establishing platform routes when a new e2t instance gets\
+        \ added to platform"
+      description: "E2T updates its FQDN to E2M  during its initialisation, hence\
+        \ after E2M informs routing manager about new E2T instances FQDN. At this\
+        \ point Routing Mgr would establish platform routes"
+      operationId: "create_new_e2t_handle"
+      consumes:
+      - "application/json"
+      produces:
+      - "application/json"
+      parameters:
+      - in: "body"
+        name: "e2t-data"
+        description: "FQDN of the newly joined E2T instance"
+        required: true
+        schema:
+          $ref: "#/definitions/e2t-data"
+        x-exportParamName: "E2tData"
+      responses:
+        "201":
+          description: "new e2t instance is considered and platform routes are established"
+        "400":
+          description: "Invalid data"
+    delete:
+      tags:
+      - "handle"
+      summary: "API for clearing routes specific to a particular e2T instance"
+      description: "E2M would monitor E2T instances using its keep alive based mechanism\
+        \ during this time if an E2T instance is detected to be dead, E2M would distribute\
+        \ already associated ran's to other available/healthy E2T instances. Here\
+        \ E2M would share E2T instance address to be removed OR which is unhealthy\
+        \ and list of RAN instances to be dissociated and an association list which\
+        \ contains E2T FQDN and associated RAN names"
+      operationId: "delete_e2t_handle"
+      consumes:
+      - "application/json"
+      produces:
+      - "application/json"
+      parameters:
+      - in: "body"
+        name: "e2t-data"
+        description: "FQDN of the newly joined E2T instance"
+        required: true
+        schema:
+          $ref: "#/definitions/e2t-delete-data"
+        x-exportParamName: "E2tData"
+      responses:
+        "201":
+          description: "new e2t instance is considered and platform routes are established"
+        "400":
+          description: "Invalid data"
+  /handles/v1/associate-ran-to-e2t:
+    post:
+      tags:
+      - "handle"
+      summary: "API for associating a ran to e2t instance"
+      description: "By performing a POST method on rane2tmapping, the API caller is\
+        \ able to update the Routing manager about the ran to e2t mapping which would\
+        \ be finally used to distribute routes to corresponding xApp and E2T instance"
+      operationId: "associate_ran_to_e2t_handle"
+      consumes:
+      - "application/json"
+      produces:
+      - "application/json"
+      parameters:
+      - in: "body"
+        name: "ran-e2t-list"
+        description: "ran to e2t mapping"
+        required: true
+        schema:
+          $ref: "#/definitions/ran-e2t-map"
+        x-exportParamName: "RanE2tList"
+      responses:
+        "201":
+          description: "e2t ran mapping recieved, platform routes"
+        "400":
+          description: "Invalid data"
+  /handles/v1/dissociate-ran:
+    post:
+      tags:
+      - "handle"
+      summary: "API to dissociate ran from e2t"
+      description: "By performing a POST method on rane2tmapping, routing manager\
+        \ will dissociate ran name from e2t instance by updating or clearing routes"
+      operationId: "dissociate_ran"
+      consumes:
+      - "application/json"
+      produces:
+      - "application/json"
+      parameters:
+      - in: "body"
+        name: "dissociate-list"
+        description: "list of RAN to dissociate"
+        required: true
+        schema:
+          $ref: "#/definitions/ran-e2t-map"
+        x-exportParamName: "DissociateList"
+      responses:
+        "201":
+          description: "ran instances disociated"
+        "400":
+          description: "Invalid data"
+definitions:
+  health-status:
+    type: "object"
+    properties:
+      status:
+        type: "string"
+        enum:
+        - "healthy"
+        - "unhealthy"
+    example:
+      status: "healthy"
+  xapp-callback-data:
+    type: "object"
+    properties:
+      id:
+        type: "string"
+      event:
+        type: "string"
+      version:
+        type: "integer"
+        format: "int64"
+      xApps:
+        type: "string"
+  xapp-subscription-data:
+    type: "object"
+    required:
+    - "address"
+    - "port"
+    - "subscription_id"
+    properties:
+      address:
+        type: "string"
+      port:
+        type: "integer"
+        format: "uint16"
+        minimum: 0
+        maximum: 65535
+      subscription_id:
+        type: "integer"
+        format: "int32"
+  xapp-list:
+    type: "array"
+    items:
+      $ref: "#/definitions/xapp-element"
+  xapp-element:
+    type: "object"
+    required:
+    - "address"
+    - "port"
+    properties:
+      address:
+        type: "string"
+      port:
+        type: "integer"
+        format: "uint16"
+        minimum: 0
+        maximum: 65535
+  ran-e2t-map:
+    type: "array"
+    items:
+      $ref: "#/definitions/ran-e2t-element"
+  ran-e2t-element:
+    type: "object"
+    required:
+    - "E2TAddress"
+    properties:
+      E2TAddress:
+        type: "string"
+      ranNamelist:
+        $ref: "#/definitions/ranNamelist"
+  ranNamelist:
+    type: "array"
+    items:
+      type: "string"
+  e2t-data:
+    type: "object"
+    required:
+    - "E2TAddress"
+    properties:
+      E2TAddress:
+        type: "string"
+      ranNamelist:
+        $ref: "#/definitions/ranNamelist"
+  e2t-delete-data:
+    type: "object"
+    required:
+    - "E2TAddress"
+    properties:
+      E2TAddress:
+        type: "string"
+      ranNamelistTobeDissociated:
+        $ref: "#/definitions/ranNamelist"
+      ranAssocList:
+        $ref: "#/definitions/ran-e2t-map"
+externalDocs:
+  description: "Routing Manager"
+  url: "http://placeholder"
diff --git a/tools/RoutingManagerSimulator/configuration/configuration.go b/tools/RoutingManagerSimulator/configuration/configuration.go
new file mode 100644 (file)
index 0000000..7e2cdef
--- /dev/null
@@ -0,0 +1,57 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+
+package configuration
+
+import (
+       "fmt"
+       "github.com/spf13/viper"
+)
+
+type Configuration struct {
+       Http struct {
+               Port int
+       }
+
+}
+
+func ParseConfiguration() *Configuration{
+       viper.SetConfigType("yaml")
+       viper.SetConfigName("configuration")
+       viper.AddConfigPath("RoutingManagerSimulator/resources/")
+       viper.AddConfigPath("./resources/")  //For production
+       viper.AddConfigPath("../resources/") //For test under Docker
+       viper.AddConfigPath("../../resources/") //For test under Docker
+       err := viper.ReadInConfig()
+       if err != nil {
+               panic(fmt.Sprintf("#configuration.ParseConfiguration - failed to read configuration file: %s\n", err))
+       }
+
+       config := Configuration{}
+       config.fillHttpConfig(viper.Sub("http"))
+       return &config
+}
+
+func (c *Configuration)fillHttpConfig(httpConfig *viper.Viper) {
+       if httpConfig == nil {
+               panic(fmt.Sprintf("#configuration.fillHttpConfig - failed to fill HTTP configuration: The entry 'http' not found\n"))
+       }
+       c.Http.Port = httpConfig.GetInt("port")
+}
diff --git a/tools/RoutingManagerSimulator/configuration/configuration_test.go b/tools/RoutingManagerSimulator/configuration/configuration_test.go
new file mode 100644 (file)
index 0000000..a12f525
--- /dev/null
@@ -0,0 +1,76 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+
+package configuration
+
+import (
+       "github.com/stretchr/testify/assert"
+       "gopkg.in/yaml.v2"
+       "io/ioutil"
+       "os"
+       "testing"
+)
+
+func TestParseConfigurationSuccess(t *testing.T) {
+       config := ParseConfiguration()
+       assert.Equal(t, 12020, config.Http.Port)
+}
+
+func TestParseConfigurationFileNotFoundFailure(t *testing.T) {
+       configPath := "../resources/configuration.yaml"
+       configPathTmp := "../resources/configuration.yaml_tmp"
+       err := os.Rename(configPath, configPathTmp)
+       if err != nil {
+               t.Errorf("#TestParseConfigurationFileNotFoundFailure - failed to rename configuration file: %s\n", configPath)
+       }
+       defer func() {
+               err = os.Rename(configPathTmp, configPath)
+               if err != nil {
+                       t.Errorf("#TestParseConfigurationFileNotFoundFailure - failed to rename configuration file: %s\n", configPath)
+               }
+       }()
+       assert.Panics(t, func() { ParseConfiguration() })
+}
+
+func TestHttpConfigNotFoundFailure(t *testing.T) {
+       configPath := "../resources/configuration.yaml"
+       configPathTmp := "../resources/configuration.yaml_tmp"
+       err := os.Rename(configPath, configPathTmp)
+       if err != nil {
+               t.Errorf("#TestHttpConfigNotFoundFailure - failed to rename configuration file: %s\n", configPath)
+       }
+       defer func() {
+               err = os.Rename(configPathTmp, configPath)
+               if err != nil {
+                       t.Errorf("#TestHttpConfigNotFoundFailure - failed to rename configuration file: %s\n", configPath)
+               }
+       }()
+       yamlMap := map[string]interface{}{}
+       buf, err := yaml.Marshal(yamlMap)
+       if err != nil {
+               t.Errorf("#TestHttpConfigNotFoundFailure - failed to marshal configuration map\n")
+       }
+       err = ioutil.WriteFile("../resources/configuration.yaml", buf, 0644)
+       if err != nil {
+               t.Errorf("#TestHttpConfigNotFoundFailure - failed to write configuration file: %s\n", configPath)
+       }
+       assert.PanicsWithValue(t, "#configuration.fillHttpConfig - failed to fill HTTP configuration: The entry 'http' not found\n",
+               func() { ParseConfiguration() })
+}
diff --git a/tools/RoutingManagerSimulator/go.mod b/tools/RoutingManagerSimulator/go.mod
new file mode 100644 (file)
index 0000000..4ca14f1
--- /dev/null
@@ -0,0 +1,13 @@
+module rmsimulator
+
+go 1.12
+
+require (
+       github.com/gorilla/mux v1.7.0
+       github.com/pkg/errors v0.8.1
+       github.com/spf13/viper v1.6.1
+       github.com/stretchr/testify v1.4.0
+       go.uber.org/atomic v1.5.0
+       go.uber.org/zap v1.13.0
+       gopkg.in/yaml.v2 v2.2.4
+)
diff --git a/tools/RoutingManagerSimulator/go.sum b/tools/RoutingManagerSimulator/go.sum
new file mode 100644 (file)
index 0000000..0d7ed5a
--- /dev/null
@@ -0,0 +1,174 @@
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
+github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
+github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
+github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
+github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
+github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
+github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
+github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
+github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
+github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
+github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
+github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
+github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
+github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
+github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
+github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
+github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
+github.com/gorilla/mux v1.7.0 h1:tOSd0UKHQd6urX6ApfOn4XdBMY6Sh1MfxV3kmaazO+U=
+github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
+github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
+github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
+github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
+github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
+github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
+github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
+github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
+github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
+github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
+github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
+github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
+github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
+github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
+github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
+github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
+github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
+github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
+github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
+github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
+github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
+github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
+github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
+github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
+github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
+github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
+github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
+github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
+github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
+github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
+github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
+github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
+github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
+github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
+github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
+github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
+github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
+github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
+github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
+github.com/spf13/viper v1.6.1 h1:VPZzIkznI1YhVMRi6vNFLHSwhnhReBfgTxIPccpfdZk=
+github.com/spf13/viper v1.6.1/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfDi5k=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
+github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
+github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
+github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
+github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
+github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
+go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
+go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
+go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY=
+go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
+go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
+go.uber.org/multierr v1.3.0 h1:sFPn2GLc3poCkfrpIXGhBD2X0CMIo4Q/zSULXrj/+uc=
+go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
+go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
+go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
+go.uber.org/zap v1.13.0 h1:nR6NoDBgAf67s68NhaXbsojM+2gxp3S1hWkHDl27pVU=
+go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
+golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
+gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
+gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
+gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
+gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
+gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
+gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
diff --git a/tools/RoutingManagerSimulator/go/api_handle.go b/tools/RoutingManagerSimulator/go/api_handle.go
new file mode 100755 (executable)
index 0000000..cb8936d
--- /dev/null
@@ -0,0 +1,79 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+
+/*
+ * Routing Manager
+ *
+ * This is the Swagger/OpenAPI 2.0 definition of Routing Manager's Northbound API.
+ *
+ * API version: 0.4.0
+ * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
+ */
+
+package swagger
+
+import (
+       "net/http"
+)
+
+func AssociateRanToE2tHandle(w http.ResponseWriter, r *http.Request) {
+       w.Header().Set("Content-Type", "application/json; charset=UTF-8")
+       w.WriteHeader(http.StatusOK)
+}
+
+func CreateNewE2tHandle(w http.ResponseWriter, r *http.Request) {
+       w.Header().Set("Content-Type", "application/json; charset=UTF-8")
+       w.WriteHeader(http.StatusOK)
+}
+
+func DeleteE2tHandle(w http.ResponseWriter, r *http.Request) {
+       w.Header().Set("Content-Type", "application/json; charset=UTF-8")
+       w.WriteHeader(http.StatusOK)
+}
+
+func DeleteXappSubscriptionHandle(w http.ResponseWriter, r *http.Request) {
+       w.Header().Set("Content-Type", "application/json; charset=UTF-8")
+       w.WriteHeader(http.StatusOK)
+}
+
+func DissociateRan(w http.ResponseWriter, r *http.Request) {
+       w.Header().Set("Content-Type", "application/json; charset=UTF-8")
+       w.WriteHeader(http.StatusOK)
+}
+
+func GetHandles(w http.ResponseWriter, r *http.Request) {
+       w.Header().Set("Content-Type", "application/json; charset=UTF-8")
+       w.WriteHeader(http.StatusOK)
+}
+
+func ProvideXappHandle(w http.ResponseWriter, r *http.Request) {
+       w.Header().Set("Content-Type", "application/json; charset=UTF-8")
+       w.WriteHeader(http.StatusOK)
+}
+
+func ProvideXappSubscriptionHandle(w http.ResponseWriter, r *http.Request) {
+       w.Header().Set("Content-Type", "application/json; charset=UTF-8")
+       w.WriteHeader(http.StatusOK)
+}
+
+func UpdateXappSubscriptionHandle(w http.ResponseWriter, r *http.Request) {
+       w.Header().Set("Content-Type", "application/json; charset=UTF-8")
+       w.WriteHeader(http.StatusOK)
+}
diff --git a/tools/RoutingManagerSimulator/go/api_health.go b/tools/RoutingManagerSimulator/go/api_health.go
new file mode 100755 (executable)
index 0000000..455f2d2
--- /dev/null
@@ -0,0 +1,38 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+/*
+ * Routing Manager
+ *
+ * This is the Swagger/OpenAPI 2.0 definition of Routing Manager's Northbound API.
+ *
+ * API version: 0.4.0
+ * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
+ */
+
+package swagger
+
+import (
+       "net/http"
+)
+
+func GetHealth(w http.ResponseWriter, r *http.Request) {
+       w.Header().Set("Content-Type", "application/json; charset=UTF-8")
+       w.WriteHeader(http.StatusOK)
+}
diff --git a/tools/RoutingManagerSimulator/go/logger.go b/tools/RoutingManagerSimulator/go/logger.go
new file mode 100755 (executable)
index 0000000..4e0d47b
--- /dev/null
@@ -0,0 +1,64 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+/*
+ * Routing Manager
+ *
+ * This is the Swagger/OpenAPI 2.0 definition of Routing Manager's Northbound API.
+ *
+ * API version: 0.4.0
+ * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
+ */
+
+package swagger
+
+import (
+    "bytes"
+    "encoding/json"
+    "io/ioutil"
+    "log"
+    "net/http"
+    "time"
+)
+
+func Logger(inner http.Handler, name string) http.Handler {
+    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+        start := time.Now()
+
+        inner.ServeHTTP(w, r)
+
+        body, err := ioutil.ReadAll(r.Body)
+        if err != nil {
+            log.Printf("Error reading body: %v", err)
+            http.Error(w, "can't read body", http.StatusBadRequest)
+            return
+        }
+
+        buffer := new(bytes.Buffer)
+        _ =json.Compact(buffer, body)
+
+        log.Printf(
+            "%s %s  body: %s elapsed: %s",
+            r.Method,
+            r.RequestURI,
+            buffer,
+            time.Since(start),
+        )
+    })
+}
diff --git a/tools/RoutingManagerSimulator/go/model_e2t_data.go b/tools/RoutingManagerSimulator/go/model_e2t_data.go
new file mode 100755 (executable)
index 0000000..a939e90
--- /dev/null
@@ -0,0 +1,36 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+/*
+ * Routing Manager
+ *
+ * This is the Swagger/OpenAPI 2.0 definition of Routing Manager's Northbound API.
+ *
+ * API version: 0.4.0
+ * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
+ */
+
+package swagger
+
+type E2tData struct {
+
+       E2TAddress string `json:"E2TAddress"`
+
+       RanNamelist *RanNamelist `json:"ranNamelist,omitempty"`
+}
diff --git a/tools/RoutingManagerSimulator/go/model_e2t_delete_data.go b/tools/RoutingManagerSimulator/go/model_e2t_delete_data.go
new file mode 100755 (executable)
index 0000000..88c21cc
--- /dev/null
@@ -0,0 +1,38 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+/*
+ * Routing Manager
+ *
+ * This is the Swagger/OpenAPI 2.0 definition of Routing Manager's Northbound API.
+ *
+ * API version: 0.4.0
+ * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
+ */
+
+package swagger
+
+type E2tDeleteData struct {
+
+       E2TAddress string `json:"E2TAddress"`
+
+       RanNamelistTobeDissociated *RanNamelist `json:"ranNamelistTobeDissociated,omitempty"`
+
+       RanAssocList *RanE2tMap `json:"ranAssocList,omitempty"`
+}
diff --git a/tools/RoutingManagerSimulator/go/model_health_status.go b/tools/RoutingManagerSimulator/go/model_health_status.go
new file mode 100755 (executable)
index 0000000..a238b06
--- /dev/null
@@ -0,0 +1,34 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+/*
+ * Routing Manager
+ *
+ * This is the Swagger/OpenAPI 2.0 definition of Routing Manager's Northbound API.
+ *
+ * API version: 0.4.0
+ * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
+ */
+
+package swagger
+
+type HealthStatus struct {
+
+       Status string `json:"status,omitempty"`
+}
diff --git a/tools/RoutingManagerSimulator/go/model_ran_e2t_element.go b/tools/RoutingManagerSimulator/go/model_ran_e2t_element.go
new file mode 100755 (executable)
index 0000000..1cf7397
--- /dev/null
@@ -0,0 +1,36 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+/*
+ * Routing Manager
+ *
+ * This is the Swagger/OpenAPI 2.0 definition of Routing Manager's Northbound API.
+ *
+ * API version: 0.4.0
+ * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
+ */
+
+package swagger
+
+type RanE2tElement struct {
+
+       E2TAddress string `json:"E2TAddress"`
+
+       RanNamelist *RanNamelist `json:"ranNamelist,omitempty"`
+}
diff --git a/tools/RoutingManagerSimulator/go/model_ran_e2t_map.go b/tools/RoutingManagerSimulator/go/model_ran_e2t_map.go
new file mode 100755 (executable)
index 0000000..8ed6edc
--- /dev/null
@@ -0,0 +1,32 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+/*
+ * Routing Manager
+ *
+ * This is the Swagger/OpenAPI 2.0 definition of Routing Manager's Northbound API.
+ *
+ * API version: 0.4.0
+ * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
+ */
+
+package swagger
+
+type RanE2tMap struct {
+}
diff --git a/tools/RoutingManagerSimulator/go/model_ran_namelist.go b/tools/RoutingManagerSimulator/go/model_ran_namelist.go
new file mode 100755 (executable)
index 0000000..ed69175
--- /dev/null
@@ -0,0 +1,32 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+/*
+ * Routing Manager
+ *
+ * This is the Swagger/OpenAPI 2.0 definition of Routing Manager's Northbound API.
+ *
+ * API version: 0.4.0
+ * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
+ */
+
+package swagger
+
+type RanNamelist struct {
+}
diff --git a/tools/RoutingManagerSimulator/go/model_xapp_callback_data.go b/tools/RoutingManagerSimulator/go/model_xapp_callback_data.go
new file mode 100755 (executable)
index 0000000..1807b1e
--- /dev/null
@@ -0,0 +1,40 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+/*
+ * Routing Manager
+ *
+ * This is the Swagger/OpenAPI 2.0 definition of Routing Manager's Northbound API.
+ *
+ * API version: 0.4.0
+ * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
+ */
+
+package swagger
+
+type XappCallbackData struct {
+
+       Id string `json:"id,omitempty"`
+
+       Event string `json:"event,omitempty"`
+
+       Version int64 `json:"version,omitempty"`
+
+       XApps string `json:"xApps,omitempty"`
+}
diff --git a/tools/RoutingManagerSimulator/go/model_xapp_element.go b/tools/RoutingManagerSimulator/go/model_xapp_element.go
new file mode 100755 (executable)
index 0000000..1439dec
--- /dev/null
@@ -0,0 +1,36 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+/*
+ * Routing Manager
+ *
+ * This is the Swagger/OpenAPI 2.0 definition of Routing Manager's Northbound API.
+ *
+ * API version: 0.4.0
+ * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
+ */
+
+package swagger
+
+type XappElement struct {
+
+       Address string `json:"address"`
+
+       Port int32 `json:"port"`
+}
diff --git a/tools/RoutingManagerSimulator/go/model_xapp_list.go b/tools/RoutingManagerSimulator/go/model_xapp_list.go
new file mode 100755 (executable)
index 0000000..f561145
--- /dev/null
@@ -0,0 +1,32 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+/*
+ * Routing Manager
+ *
+ * This is the Swagger/OpenAPI 2.0 definition of Routing Manager's Northbound API.
+ *
+ * API version: 0.4.0
+ * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
+ */
+
+package swagger
+
+type XappList struct {
+}
diff --git a/tools/RoutingManagerSimulator/go/model_xapp_subscription_data.go b/tools/RoutingManagerSimulator/go/model_xapp_subscription_data.go
new file mode 100755 (executable)
index 0000000..b36067d
--- /dev/null
@@ -0,0 +1,38 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+/*
+ * Routing Manager
+ *
+ * This is the Swagger/OpenAPI 2.0 definition of Routing Manager's Northbound API.
+ *
+ * API version: 0.4.0
+ * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
+ */
+
+package swagger
+
+type XappSubscriptionData struct {
+
+       Address string `json:"address"`
+
+       Port int32 `json:"port"`
+
+       SubscriptionId int32 `json:"subscription_id"`
+}
diff --git a/tools/RoutingManagerSimulator/go/routers.go b/tools/RoutingManagerSimulator/go/routers.go
new file mode 100755 (executable)
index 0000000..6c34230
--- /dev/null
@@ -0,0 +1,146 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+/*
+ * Routing Manager
+ *
+ * This is the Swagger/OpenAPI 2.0 definition of Routing Manager's Northbound API.
+ *
+ * API version: 0.4.0
+ * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
+ */
+
+package swagger
+
+import (
+       "fmt"
+       "net/http"
+       "strings"
+
+       "github.com/gorilla/mux"
+)
+
+type Route struct {
+       Name        string
+       Method      string
+       Pattern     string
+       HandlerFunc http.HandlerFunc
+}
+
+type Routes []Route
+
+func NewRouter() *mux.Router {
+       router := mux.NewRouter().StrictSlash(true)
+       for _, route := range routes {
+               var handler http.Handler
+               handler = route.HandlerFunc
+               handler = Logger(handler, route.Name)
+
+               router.
+                       Methods(route.Method).
+                       Path(route.Pattern).
+                       Name(route.Name).
+                       Handler(handler)
+       }
+
+       return router
+}
+
+func Index(w http.ResponseWriter, r *http.Request) {
+       fmt.Fprintf(w, "Hello World!")
+}
+
+var routes = Routes{
+       Route{
+               "Index",
+               "GET",
+               "/ric/v1/",
+               Index,
+       },
+
+       Route{
+               "AssociateRanToE2tHandle",
+               strings.ToUpper("Post"),
+               "/ric/v1/handles/v1/associate-ran-to-e2t",
+               AssociateRanToE2tHandle,
+       },
+
+       Route{
+               "CreateNewE2tHandle",
+               strings.ToUpper("Post"),
+               "/ric/v1/handles/v1/e2t",
+               CreateNewE2tHandle,
+       },
+
+       Route{
+               "DeleteE2tHandle",
+               strings.ToUpper("Delete"),
+               "/ric/v1/handles/v1/e2t",
+               DeleteE2tHandle,
+       },
+
+       Route{
+               "DeleteXappSubscriptionHandle",
+               strings.ToUpper("Delete"),
+               "/ric/v1/handles/xapp-subscription-handle",
+               DeleteXappSubscriptionHandle,
+       },
+
+       Route{
+               "DissociateRan",
+               strings.ToUpper("Post"),
+               "/ric/v1/handles/v1/dissociate-ran",
+               DissociateRan,
+       },
+
+       Route{
+               "GetHandles",
+               strings.ToUpper("Get"),
+               "/ric/v1/handles",
+               GetHandles,
+       },
+
+       Route{
+               "ProvideXappHandle",
+               strings.ToUpper("Post"),
+               "/ric/v1/handles/xapp-handle",
+               ProvideXappHandle,
+       },
+
+       Route{
+               "ProvideXappSubscriptionHandle",
+               strings.ToUpper("Post"),
+               "/ric/v1/handles/xapp-subscription-handle",
+               ProvideXappSubscriptionHandle,
+       },
+
+       Route{
+               "UpdateXappSubscriptionHandle",
+               strings.ToUpper("Put"),
+               "/ric/v1/handles/xapp-subscription-handle/{subscription_id}",
+               UpdateXappSubscriptionHandle,
+       },
+
+       Route{
+               "GetHealth",
+               strings.ToUpper("Get"),
+               "/ric/v1/health",
+               GetHealth,
+       },
+}
diff --git a/tools/RoutingManagerSimulator/main.go b/tools/RoutingManagerSimulator/main.go
new file mode 100755 (executable)
index 0000000..f9f4824
--- /dev/null
@@ -0,0 +1,49 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+
+/*
+ * Routing Manager
+ *
+ * This is the Swagger/OpenAPI 2.0 definition of Routing Manager's Northbound API.
+ *
+ * API version: 0.4.0
+ * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
+ */
+
+package main
+
+import (
+       "fmt"
+       "log"
+       "net/http"
+       "rmsimulator/configuration"
+       "rmsimulator/go"
+)
+
+func main() {
+       config := configuration.ParseConfiguration()
+       port := config.Http.Port
+
+       log.Printf("Server started on port %d", port)
+
+       router := swagger.NewRouter()
+
+       log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", port), router))
+}
diff --git a/tools/RoutingManagerSimulator/resources/configuration.yaml b/tools/RoutingManagerSimulator/resources/configuration.yaml
new file mode 100644 (file)
index 0000000..e6fb1c2
--- /dev/null
@@ -0,0 +1,2 @@
+http:
+  port: 12020
diff --git a/tools/xapp_mock/configuration.json b/tools/xapp_mock/configuration.json
deleted file mode 100644 (file)
index 9df43a1..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-[ 
-       {“id”: “RIC_X2_SETUP_REQ” , “rmrMessageType”: 10060, “transactionId”: “e2e$”, “payloadHeader”: “$ranIp|$ranPort|$ranName|#packedPayload|”,  “packedPayload”: "3137322e31372e302e357c353537377c74657374327c34367c0006002a000002001500080013302300fffff000140017000001f700133023fffff0000000133023000000000001" },
-       {“id”: “RIC_ENB_CONF_UPDATE_ACK_positive” ,  “rmrMessageType”: 10081, “transactionId”: “e2e$”, “payloadHeader”: “$ranIp|$ranPort|$ranName|#packedPayload|”,  “packedPayload”: "2025000a00000100f70003000000" } 
-]
diff --git a/tools/xapp_mock/main/xapp_mock.go b/tools/xapp_mock/main/xapp_mock.go
deleted file mode 100644 (file)
index fd259f5..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-//
-// Copyright 2019 AT&T Intellectual Property
-// Copyright 2019 Nokia
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
-//  platform project (RICP).
-
-package main
-
-import (
-       "../frontend"
-       "../rmr"
-       "../sender"
-       "flag"
-       "fmt"
-       "github.com/pkg/errors"
-       "log"
-       "os"
-       "strconv"
-)
-
-const (
-       ENV_RMR_PORT = "RMR_PORT"
-       RMR_PORT_DEFAULT = 5001
-)
-
-var rmrService *rmr.Service
-
-func main() {
-       var rmrContext *rmr.Context
-
-       var rmrConfig rmr.Config = rmr.Config{Port: RMR_PORT_DEFAULT, MaxMsgSize: rmr.RMR_MAX_MSG_SIZE, MaxRetries: 3, Flags: 0}
-       if port, err := strconv.ParseUint(os.Getenv(ENV_RMR_PORT), 10, 16); err == nil {
-               rmrConfig.Port = int(port)
-       } else {
-               log.Printf("%s: %s, using default (%d).", ENV_RMR_PORT, err,RMR_PORT_DEFAULT)
-       }
-       rmrService = rmr.NewService(rmrConfig, rmrContext)
-
-       /* Load configuration file*/
-       err := frontend.ProcessConfigurationFile("resources","conf",  ".json",
-               func(data []byte) error {
-                       return  frontend.JsonCommandsDecoder(data,jsonCommandsDecoderCB)
-               })
-       if err != nil {
-               log.Fatalf("processing Error: %s", err)
-       }
-
-       log.Print("xapp_mock is up and running.")
-
-       cmd:= flag.Arg(0) /*first remaining argument after flags have been processed*/
-       if err :=  frontend.JsonCommandDecoder([]byte(cmd),jsonCommandDecoderCB); err != nil {
-               log.Printf("command processing Error: %s", err)
-       }
-
-       rmrService.CloseContext()
-
-       log.Print("xapp_mock is down.")
-}
-
-
-// TODO: move callbacks to Dispatcher.
-func jsonCommandsDecoderCB(command *frontend.JsonCommand) error {
-       if len(command.Id) == 0{
-               return errors.New(fmt.Sprintf("invalid command, no Id"))
-       }
-       frontend.Configuration[command.Id] = command
-       if rmrMsgId, err := rmr.MessageIdToUint(command.WaitForRmrMessageType); err != nil {
-               return errors.New(fmt.Sprintf("invalid rmr message id: %s",command.WaitForRmrMessageType))
-       } else {
-               frontend.WaitedForRmrMessageType[int(rmrMsgId)] = command
-       }
-       return nil
-}
-
-// TODO: merge command with configuration
-func jsonCommandDecoderCB(command *frontend.JsonCommand) error {
-       if len(command.Id) == 0{
-               return errors.New(fmt.Sprintf("invalid command, no Id"))
-       }
-       switch command.Action {
-       case frontend.SendRmrMessage:
-               if  err := sender.SendJsonRmrMessage(*command, nil, rmrService); err != nil {
-                       return err
-               }
-               if len(command.WaitForRmrMessageType) > 0 {
-                       rmrService.ListenAndHandle() //TODO: handle error
-               }
-       case frontend.ReceiveRmrMessage:
-               if rmrMsgId, err := rmr.MessageIdToUint(command.RmrMessageType); err != nil {
-                       return errors.New(fmt.Sprintf("invalid rmr message id: %s",command.WaitForRmrMessageType))
-               } else {
-                       frontend.WaitedForRmrMessageType[int(rmrMsgId)] = command
-               }
-               rmrService.ListenAndHandle() //TODO: handle error
-       default:
-               return errors.New(fmt.Sprintf("invalid command action %s", command.Action))
-       }
-       return nil
-}
\ No newline at end of file
diff --git a/tools/xapp_mock/resources/router.txt b/tools/xapp_mock/resources/router.txt
deleted file mode 100644 (file)
index 1d3fea3..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-newrt|start
-rte|1001|10.0.2.15:38000
-rte|2002|10.0.2.15:3801
-newrt|end
similarity index 68%
rename from tools/xapp_mock/Dockerfile
rename to tools/xappmock/Dockerfile
index 4e08703..38db680 100644 (file)
 #   platform project (RICP).
 #
 
-FROM nexus3.o-ran-sc.org:10004/bldr-ubuntu16-c-go:1-u16.04-nng1.1.1 as ubuntu
+FROM nexus3.o-ran-sc.org:10004/bldr-ubuntu16-c-go:2-u16.04-nng as ubuntu
 
-WORKDIR /opt/xapp_mock
+WORKDIR /opt/xappmock
 COPY . . 
 ENV PATH=$PATH:/usr/local/go/bin:/usr/lib/go-1.12/bin
 # Install RMr library and dev files
-RUN wget --content-disposition https://packagecloud.io/o-ran-sc/master/packages/debian/stretch/rmr_1.3.0_amd64.deb/download.deb
-RUN dpkg -i rmr_1.3.0_amd64.deb
-RUN wget --content-disposition https://packagecloud.io/o-ran-sc/master/packages/debian/stretch/rmr-dev_1.3.0_amd64.deb/download.deb
-RUN dpkg -i rmr-dev_1.3.0_amd64.deb
+RUN wget --content-disposition  https://packagecloud.io/o-ran-sc/staging/packages/debian/stretch/rmr_1.10.0_amd64.deb/download.deb
+RUN dpkg -i rmr_1.10.0_amd64.deb
+RUN wget --content-disposition https://packagecloud.io/o-ran-sc/staging/packages/debian/stretch/rmr-dev_1.10.0_amd64.deb/download.deb
+RUN dpkg -i rmr-dev_1.10.0_amd64.deb
 
-RUN go get github.com/pkg/errors 
-RUN go build main/xapp_mock.go 
+RUN go build main/xappmock.go
     
 
 
 FROM ubuntu:16.04
-COPY --from=ubuntu /opt/xapp_mock/xapp_mock /opt/xapp_mock/xapp_mock
-COPY --from=ubuntu /opt/xapp_mock/resources /opt/xapp_mock/resources
+COPY --from=ubuntu /opt/xappmock/xappmock /opt/xappmock/xappmock
+COPY --from=ubuntu /opt/xappmock/resources /opt/xappmock/resources
 COPY --from=ubuntu /usr/local/lib/librmr_nng.so.1 /usr/local/lib/librmr_nng.so.1
 COPY --from=ubuntu /usr/local/lib/libnng.so.1 /usr/local/lib/libnng.so.1
-WORKDIR /opt/xapp_mock
+WORKDIR /opt/xappmock
 ENV LD_LIBRARY_PATH=/usr/local/lib 
 ENV RMR_SEED_RT=resources/router.txt
 ENV RMR_PORT=5001
-#CMD mkdir -p resources/conf  exec ./xapp_mock
+#CMD mkdir -p resources/conf  exec ./xappmock
 CMD mkdir -p resources/conf &&  exec /bin/bash 
diff --git a/tools/xappmock/dispatcher/dispatcher.go b/tools/xappmock/dispatcher/dispatcher.go
new file mode 100644 (file)
index 0000000..6e00592
--- /dev/null
@@ -0,0 +1,384 @@
+package dispatcher
+
+import (
+       "context"
+       "fmt"
+       "github.com/pkg/errors"
+       "reflect"
+       "sync"
+       "time"
+       "xappmock/enums"
+       "xappmock/logger"
+       "xappmock/models"
+       "xappmock/rmr"
+       "xappmock/sender"
+)
+
+// Id -> Command
+var configuration = make(map[string]*models.JsonCommand)
+
+// Rmr Message Id -> Command
+var waitForRmrMessageType = make(map[int]*models.JsonCommand)
+
+func addRmrMessageToWaitFor(rmrMessageToWaitFor string, command models.JsonCommand) error {
+       rmrMsgId, err := rmr.MessageIdToUint(rmrMessageToWaitFor)
+
+       if err != nil {
+               return errors.New(fmt.Sprintf("invalid rmr message id: %s", rmrMessageToWaitFor))
+       }
+
+       waitForRmrMessageType[int(rmrMsgId)] = &command
+       return nil
+}
+
+type Dispatcher struct {
+       rmrService    *rmr.Service
+       processResult models.ProcessResult
+       logger        *logger.Logger
+       jsonSender    *sender.JsonSender
+}
+
+func (d *Dispatcher) GetProcessResult() models.ProcessResult {
+       return d.processResult
+}
+
+func New(logger *logger.Logger, rmrService *rmr.Service, jsonSender *sender.JsonSender) *Dispatcher {
+       return &Dispatcher{
+               rmrService: rmrService,
+               logger:     logger,
+               jsonSender: jsonSender,
+       }
+}
+
+func (d *Dispatcher) JsonCommandsDecoderCB(cmd models.JsonCommand) error {
+       if len(cmd.Id) == 0 {
+               return errors.New(fmt.Sprintf("invalid cmd, no id"))
+       }
+       configuration[cmd.Id] = &cmd
+       return nil
+
+       //      if len(cmd.ReceiveCommandId) == 0 {
+       //              return nil
+       //      }
+       //
+       //      return addRmrMessageToWaitFor(cmd.ReceiveCommandId, cmd)
+}
+
+func (d *Dispatcher) sendNoRepeat(command models.JsonCommand) error {
+
+       if enums.CommandAction(command.Action) == enums.SendRmrMessage && d.processResult.StartTime == nil {
+               now := time.Now()
+               d.processResult.StartTime = &now
+       }
+
+       err := d.jsonSender.SendJsonRmrMessage(command, nil, d.rmrService)
+
+       if err != nil {
+               d.logger.Errorf("#Dispatcher.sendNoRepeat - error sending rmr message: %s", err)
+               d.processResult.Err = err
+               d.processResult.Stats.SentErrorCount.Inc()
+               return err
+       }
+
+       d.processResult.Stats.SentCount.Inc()
+       return nil
+}
+
+func (d *Dispatcher) sendWithRepeat(ctx context.Context, command models.JsonCommand) {
+
+       if enums.CommandAction(command.Action) == enums.SendRmrMessage && d.processResult.StartTime == nil {
+               now := time.Now()
+               d.processResult.StartTime = &now
+       }
+
+       for repeatCount := command.RepeatCount; repeatCount > 0; repeatCount-- {
+
+               select {
+               case <-ctx.Done():
+                       return
+               default:
+               }
+
+               err := d.jsonSender.SendJsonRmrMessage(command, nil, d.rmrService)
+
+               if err != nil {
+                       d.logger.Errorf("#Dispatcher.sendWithRepeat - error sending rmr message: %s", err)
+                       d.processResult.Stats.SentErrorCount.Inc()
+                       continue
+               }
+
+               d.processResult.Stats.SentCount.Inc()
+               time.Sleep(time.Duration(command.RepeatDelayInMs) * time.Millisecond)
+       }
+}
+
+func getReceiveRmrMessageType(receiveCommandId string) (string, error) {
+       command, ok := configuration[receiveCommandId]
+
+       if !ok {
+               return "", errors.New(fmt.Sprintf("invalid receive command id: %s", receiveCommandId))
+       }
+
+       if len(command.RmrMessageType) == 0 {
+               return "", errors.New(fmt.Sprintf("missing RmrMessageType for command id: %s", receiveCommandId))
+       }
+
+       return command.RmrMessageType, nil
+}
+
+func (d *Dispatcher) sendHandler(ctx context.Context, sendAndReceiveWg *sync.WaitGroup, command models.JsonCommand) {
+
+       defer sendAndReceiveWg.Done()
+       var listenAndHandleWg sync.WaitGroup
+
+       if len(command.ReceiveCommandId) > 0 {
+               rmrMessageToWaitFor, err := getReceiveRmrMessageType(command.ReceiveCommandId)
+
+               if err != nil {
+                       d.processResult.Err = err
+                       return
+               }
+
+               err = addRmrMessageToWaitFor(rmrMessageToWaitFor, command)
+
+               if err != nil {
+                       d.processResult.Err = err
+                       return
+               }
+
+               listenAndHandleWg.Add(1)
+               go d.listenAndHandle(ctx, &listenAndHandleWg, command)
+       }
+
+       if command.RepeatCount == 0 {
+               err := d.sendNoRepeat(command)
+
+               if err != nil {
+                       return
+               }
+
+       } else {
+               d.sendWithRepeat(ctx, command)
+       }
+
+       if len(command.ReceiveCommandId) > 0 {
+               listenAndHandleWg.Wait()
+       }
+}
+
+func (d *Dispatcher) receiveHandler(ctx context.Context, sendAndReceiveWg *sync.WaitGroup, command models.JsonCommand) {
+
+       defer sendAndReceiveWg.Done()
+
+       err := addRmrMessageToWaitFor(command.RmrMessageType, command)
+
+       if err != nil {
+               d.processResult.Err = err
+               return
+       }
+
+       var listenAndHandleWg sync.WaitGroup
+       listenAndHandleWg.Add(1) // this is due to the usage of listenAndHandle as a goroutine in the sender case
+       d.listenAndHandle(ctx, &listenAndHandleWg, command)
+}
+
+func getMergedCommand(cmd *models.JsonCommand) (models.JsonCommand, error) {
+       var command models.JsonCommand
+       if len(cmd.Id) == 0 {
+               return command, errors.New(fmt.Sprintf("invalid command, no id"))
+       }
+
+       command = *cmd
+
+       conf, ok := configuration[cmd.Id]
+
+       if ok {
+               command = *conf
+               mergeConfigurationAndCommand(&command, cmd)
+       }
+
+       return command, nil
+}
+
+func (d *Dispatcher) ProcessJsonCommand(ctx context.Context, cmd *models.JsonCommand) {
+
+       command, err := getMergedCommand(cmd)
+
+       if err != nil {
+               d.processResult.Err = err
+               return
+       }
+
+       var sendAndReceiveWg sync.WaitGroup
+
+       commandAction := enums.CommandAction(command.Action)
+
+       switch commandAction {
+
+       case enums.SendRmrMessage:
+               sendAndReceiveWg.Add(1)
+               go d.sendHandler(ctx, &sendAndReceiveWg, command)
+       case enums.ReceiveRmrMessage:
+               sendAndReceiveWg.Add(1)
+               go d.receiveHandler(ctx, &sendAndReceiveWg, command)
+       default:
+               d.processResult = models.ProcessResult{Err: errors.New(fmt.Sprintf("invalid command action %s", command.Action))}
+               return
+       }
+
+       sendAndReceiveWg.Wait()
+}
+
+func getResponseCommand(command models.JsonCommand) (*models.JsonCommand, error) {
+       responseCommand, ok := configuration[command.SendCommandId]
+
+       if !ok {
+               return nil, errors.New(fmt.Sprintf("invalid SendCommandId %s", command.SendCommandId))
+       }
+
+       return responseCommand, nil
+}
+
+func (d *Dispatcher) listenAndHandleNoRepeat(ctx context.Context, command models.JsonCommand) {
+       for {
+               select {
+               case <-ctx.Done():
+                       return
+               default:
+               }
+
+               mbuf, err := d.rmrService.RecvMessage()
+
+               if err != nil {
+                       d.logger.Errorf("#Dispatcher.listenAndHandleNoRepeat - error receiving message: %s", err)
+                       d.processResult.Err = err
+                       d.processResult.Stats.ReceivedErrorCount.Inc()
+                       return
+               }
+
+               if enums.CommandAction(command.Action) == enums.ReceiveRmrMessage && d.processResult.StartTime == nil {
+                       now := time.Now()
+                       d.processResult.StartTime = &now
+               }
+
+               messageInfo := models.NewMessageInfo(mbuf.MType, mbuf.Meid, mbuf.Payload, mbuf.XAction)
+
+               _, ok := waitForRmrMessageType[mbuf.MType]
+
+               if !ok {
+                       d.logger.Infof("#Dispatcher.listenAndHandleNoRepeat - received unexpected msg: %s", messageInfo)
+                       d.processResult.Stats.ReceivedUnexpectedCount.Inc()
+                       continue
+               }
+
+               d.logger.Infof("#Dispatcher.listenAndHandleNoRepeat - received expected msg: %s", messageInfo)
+               d.processResult.Stats.ReceivedExpectedCount.Inc()
+
+               if len(command.SendCommandId) > 0 {
+                       responseCommand, err := getResponseCommand(command)
+
+                       if err != nil {
+                               d.processResult.Err = err
+                               return
+                       }
+
+                       _ = d.sendNoRepeat(*responseCommand)
+               }
+
+               return
+       }
+}
+
+func (d *Dispatcher) listenAndHandleWithRepeat(ctx context.Context, command models.JsonCommand) {
+
+       var responseCommand *models.JsonCommand
+
+       if len(command.SendCommandId) > 0 {
+               var err error
+               responseCommand, err = getResponseCommand(command)
+
+               if err != nil {
+                       d.processResult.Err = err
+                       return
+               }
+       }
+
+       for d.processResult.Stats.ReceivedExpectedCount.Load() < int32(command.RepeatCount) {
+               select {
+               case <-ctx.Done():
+                       return
+               default:
+               }
+
+               mbuf, err := d.rmrService.RecvMessage()
+
+               if err != nil {
+                       d.logger.Errorf("#Dispatcher.listenAndHandleWithRepeat - error receiving message: %s", err)
+                       d.processResult.Stats.ReceivedErrorCount.Inc()
+                       continue
+               }
+
+               if enums.CommandAction(command.Action) == enums.ReceiveRmrMessage && d.processResult.StartTime == nil {
+                       now := time.Now()
+                       d.processResult.StartTime = &now
+               }
+
+               messageInfo := models.NewMessageInfo(mbuf.MType, mbuf.Meid, mbuf.Payload, mbuf.XAction)
+
+               _, ok := waitForRmrMessageType[mbuf.MType]
+
+               if !ok {
+                       d.logger.Infof("#Dispatcher.listenAndHandleWithRepeat - received unexpected msg: %s", messageInfo)
+                       d.processResult.Stats.ReceivedUnexpectedCount.Inc()
+                       continue
+               }
+
+               d.logger.Infof("#Dispatcher.listenAndHandleWithRepeat - received expected msg: %s", messageInfo)
+               d.processResult.Stats.ReceivedExpectedCount.Inc()
+
+               if responseCommand != nil {
+                       _ = d.sendNoRepeat(*responseCommand) // TODO: goroutine? + error handling
+               }
+       }
+}
+
+func (d *Dispatcher) listenAndHandle(ctx context.Context, listenAndHandleWg *sync.WaitGroup, command models.JsonCommand) {
+
+       defer listenAndHandleWg.Done()
+
+       if command.RepeatCount == 0 {
+               d.listenAndHandleNoRepeat(ctx, command)
+               return
+       }
+
+       d.listenAndHandleWithRepeat(ctx, command)
+}
+
+func mergeConfigurationAndCommand(conf *models.JsonCommand, cmd *models.JsonCommand) {
+       nFields := reflect.Indirect(reflect.ValueOf(cmd)).NumField()
+
+       for i := 0; i < nFields; i++ {
+               if fieldValue := reflect.Indirect(reflect.ValueOf(cmd)).Field(i); fieldValue.IsValid() {
+                       switch fieldValue.Kind() {
+                       case reflect.String:
+                               if fieldValue.Len() > 0 {
+                                       reflect.Indirect(reflect.ValueOf(conf)).Field(i).Set(fieldValue)
+                               }
+                       case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+                               if fieldValue.Int() != 0 {
+                                       reflect.Indirect(reflect.ValueOf(conf)).Field(i).Set(fieldValue)
+                               }
+                       case reflect.Bool:
+                               if fieldValue.Bool() {
+                                       reflect.Indirect(reflect.ValueOf(conf)).Field(i).Set(fieldValue)
+                               }
+                       case reflect.Float64, reflect.Float32:
+                               if fieldValue.Float() != 0 {
+                                       reflect.Indirect(reflect.ValueOf(conf)).Field(i).Set(fieldValue)
+                               }
+                       default:
+                               reflect.Indirect(reflect.ValueOf(conf)).Field(i).Set(fieldValue)
+                       }
+               }
+       }
+}
diff --git a/tools/xappmock/enums/command_action.go b/tools/xappmock/enums/command_action.go
new file mode 100644 (file)
index 0000000..7e31239
--- /dev/null
@@ -0,0 +1,25 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package enums
+
+type CommandAction string
+
+const (
+       SendRmrMessage    CommandAction = "send"
+       ReceiveRmrMessage CommandAction = "receive"
+)
similarity index 92%
rename from tools/xapp_mock/frontend/configfile.go
rename to tools/xappmock/frontend/configfile.go
index 2f1923f..105d1dc 100644 (file)
@@ -27,7 +27,7 @@ import (
        "strings"
 )
 
-func ProcessConfigurationFile(resourcesFolder, inputFolder,  suffix string, processor func(data []byte) error) error {
+func ProcessConfigurationFile(resourcesFolder, inputFolder, suffix string, processor func(data []byte) error) error {
        cwd, err := os.Getwd()
        if err != nil {
                return errors.New(err.Error())
similarity index 60%
rename from tools/xapp_mock/frontend/jsonDecoder.go
rename to tools/xappmock/frontend/jsonDecoder.go
index e5ee02a..844e63d 100644 (file)
@@ -25,57 +25,31 @@ import (
        "fmt"
        "github.com/pkg/errors"
        "io"
+       "xappmock/models"
 )
 
-const (
-       SendRmrMessage  = "send"
-       ReceiveRmrMessage  = "receive"
-)
-
-
-type JsonCommand struct {
- Id string
- RmrMessageType  string
- TransactionId string
- RanName string
- RanIp string
- RanPort int
- PayloadHeader string
- PackedPayload string
- Payload string
- Action string
- WaitForRmrMessageType string
-}
-
-// Id -> Command
-var Configuration = make(map[string]*JsonCommand)
-// Rmr Message Id -> Command
-var WaitedForRmrMessageType = make(map[int]*JsonCommand)
-
-func JsonCommandDecoder(data []byte, processor func (*JsonCommand) error ) error {
+func DecodeJsonCommand(data []byte) (*models.JsonCommand, error) {
        dec := json.NewDecoder(bytes.NewReader(data))
-       var cmd JsonCommand
+       var cmd models.JsonCommand
        if err := dec.Decode(&cmd); err != nil && err != io.EOF {
-               return errors.New(err.Error())
-       }
-       if err := processor (&cmd); err != nil {
-               return err
+               return nil, errors.New(err.Error())
        }
-       return nil
+
+       return &cmd, nil
 }
 
-func JsonCommandsDecoder(data []byte, processor func (*JsonCommand) error ) error {
+func JsonCommandsDecoder(data []byte, processor func(models.JsonCommand) error) error {
        dec := json.NewDecoder(bytes.NewReader(data))
        for {
-               var commands []JsonCommand
+               var commands []models.JsonCommand
                if err := dec.Decode(&commands); err == io.EOF {
                        break
                } else if err != nil {
                        return errors.New(err.Error())
                }
                for i, cmd := range commands {
-                       if err := processor(&cmd); err != nil {
-                               return errors.New(fmt.Sprintf("processing error at #%d, %s",i,err))
+                       if err := processor(cmd); err != nil {
+                               return errors.New(fmt.Sprintf("processing error at #%d, %s", i, err))
                        }
                }
        }
diff --git a/tools/xappmock/go.mod b/tools/xappmock/go.mod
new file mode 100644 (file)
index 0000000..b61ff4a
--- /dev/null
@@ -0,0 +1,9 @@
+module xappmock
+
+go 1.12
+
+require (
+       github.com/pkg/errors v0.8.1
+       go.uber.org/atomic v1.5.0
+       go.uber.org/zap v1.13.0
+)
diff --git a/tools/xappmock/go.sum b/tools/xappmock/go.sum
new file mode 100644 (file)
index 0000000..81ca7d4
--- /dev/null
@@ -0,0 +1,57 @@
+github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY=
+go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
+go.uber.org/multierr v1.3.0 h1:sFPn2GLc3poCkfrpIXGhBD2X0CMIo4Q/zSULXrj/+uc=
+go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
+go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4=
+go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
+go.uber.org/zap v1.13.0 h1:nR6NoDBgAf67s68NhaXbsojM+2gxp3S1hWkHDl27pVU=
+go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
+golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c h1:IGkKhmfzcztjm6gYkykvu/NiS8kaqbCWAEWWAyf8J5U=
+golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5 h1:hKsoRgsbwY1NafxrwTs+k64bikrLBkAgPir1TNCj3Zs=
+golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
+honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
diff --git a/tools/xappmock/logger/logger.go b/tools/xappmock/logger/logger.go
new file mode 100644 (file)
index 0000000..0c168d7
--- /dev/null
@@ -0,0 +1,184 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package logger
+
+import (
+       "fmt"
+       "go.uber.org/zap"
+       "go.uber.org/zap/zapcore"
+       "strings"
+       "time"
+)
+
+type Logger struct {
+       Logger     *zap.Logger
+}
+
+// Copied from zap logger
+//
+// A Level is a logging priority. Higher levels are more important.
+type LogLevel int8
+
+const (
+       // DebugLevel logs are typically voluminous, and are usually disabled in
+       // production.
+       DebugLevel LogLevel = iota - 1
+       // InfoLevel is the default logging priority.
+       InfoLevel
+       // WarnLevel logs are more important than Info, but don't need individual
+       // human review.
+       WarnLevel
+       // ErrorLevel logs are high-priority. If an application is running smoothly,
+       // it shouldn't generate any error-level logs.
+       ErrorLevel
+       // DPanicLevel logs are particularly important errors. In development the
+       // logger panics after writing the message.
+       DPanicLevel
+       // PanicLevel logs a message, then panics.
+       PanicLevel
+       // FatalLevel logs a message, then calls os.Exit(1).
+       FatalLevel
+
+       _minLevel = DebugLevel
+       _maxLevel = FatalLevel
+)
+
+var logLevelTokenToLevel = map[string] LogLevel {
+       "debug" : DebugLevel,
+       "info": InfoLevel,
+       "warn": WarnLevel,
+       "error": ErrorLevel,
+       "dpanic": DPanicLevel,
+       "panic": PanicLevel,
+       "fatal": FatalLevel,
+}
+
+func LogLevelTokenToLevel(level string) (LogLevel, bool) {
+       if level, ok := logLevelTokenToLevel[strings.TrimSpace(strings.ToLower(level))];ok {
+               return level, true
+       }
+       return _maxLevel+1, false
+}
+
+func InitLogger(requested LogLevel) (*Logger, error) {
+       var logger *zap.Logger
+       var err error
+       switch requested {
+       case DebugLevel:
+               logger, err = initLoggerByLevel(zapcore.DebugLevel)
+       case InfoLevel:
+               logger, err = initLoggerByLevel(zapcore.InfoLevel)
+       case WarnLevel:
+               logger, err = initLoggerByLevel(zapcore.WarnLevel)
+       case ErrorLevel:
+               logger, err = initLoggerByLevel(zapcore.ErrorLevel)
+       case DPanicLevel:
+               logger, err = initLoggerByLevel(zapcore.DPanicLevel)
+       case PanicLevel:
+               logger, err = initLoggerByLevel(zapcore.PanicLevel)
+       case FatalLevel:
+               logger, err = initLoggerByLevel(zapcore.FatalLevel)
+       default:
+               err = fmt.Errorf("Invalid logging Level :%d",requested)
+       }
+       if err != nil {
+               return nil, err
+       }
+       return &Logger{Logger:logger}, nil
+
+}
+func(l *Logger)Sync() error {
+       l.Debugf("#logger.Sync - Going to flush buffered log")
+       return l.Logger.Sync()
+}
+
+func (l *Logger)Infof(formatMsg string, a ...interface{})  {
+       if l.InfoEnabled() {
+               msg := fmt.Sprintf(formatMsg, a...)
+               l.Logger.Info(msg, zap.Any("mdc", l.getTimeStampMdc()))
+       }
+}
+
+func (l *Logger)Debugf(formatMsg string, a ...interface{})  {
+       if l.DebugEnabled(){
+               msg := fmt.Sprintf(formatMsg, a...)
+               l.Logger.Debug(msg, zap.Any("mdc", l.getTimeStampMdc()))
+       }
+}
+
+func (l *Logger)Errorf(formatMsg string, a ...interface{})  {
+       msg := fmt.Sprintf(formatMsg, a...)
+       l.Logger.Error(msg, zap.Any("mdc", l.getTimeStampMdc()))
+}
+
+func (l *Logger)Warnf(formatMsg string, a ...interface{})  {
+       msg := fmt.Sprintf(formatMsg, a...)
+       l.Logger.Warn(msg, zap.Any("mdc", l.getTimeStampMdc()))
+}
+
+func (l *Logger) getTimeStampMdc() map[string]string {
+       timeStr := time.Now().Format("2006-01-02 15:04:05.000")
+       mdc := map[string]string{"time": timeStr}
+       return mdc
+}
+
+func (l *Logger)InfoEnabled()bool{
+       return l.Logger.Core().Enabled(zap.InfoLevel)
+}
+
+func (l *Logger)DebugEnabled()bool{
+       return l.Logger.Core().Enabled(zap.DebugLevel)
+}
+
+func (l *Logger)DPanicf(formatMsg string, a ...interface{})  {
+       msg := fmt.Sprintf(formatMsg, a...)
+       l.Logger.DPanic(msg, zap.Any("mdc", l.getTimeStampMdc()))
+}
+
+func initLoggerByLevel(l zapcore.Level) (*zap.Logger, error) {
+       cfg := zap.Config{
+               Encoding:         "json",
+               Level:            zap.NewAtomicLevelAt(l),
+               OutputPaths:      []string{"stdout"},
+               ErrorOutputPaths: []string{"stderr"},
+               EncoderConfig: zapcore.EncoderConfig{
+                       MessageKey: "msg",
+
+                       LevelKey:    "crit",
+                       EncodeLevel: zapcore.CapitalLevelEncoder,
+
+                       TimeKey:    "ts",
+                       EncodeTime: epochMillisIntegerTimeEncoder,
+
+                       CallerKey: "id",
+                       EncodeCaller: xAppMockCallerEncoder,
+               },
+       }
+       return cfg.Build()
+}
+
+func xAppMockCallerEncoder(caller zapcore.EntryCaller, enc zapcore.PrimitiveArrayEncoder) {
+       enc.AppendString("xAppMock")
+}
+
+func epochMillisIntegerTimeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
+       nanos := t.UnixNano()
+       millis := int64(nanos) / int64(time.Millisecond)
+       enc.AppendInt64(millis)
+}
+
diff --git a/tools/xappmock/main/xappmock.go b/tools/xappmock/main/xappmock.go
new file mode 100644 (file)
index 0000000..8ae62f7
--- /dev/null
@@ -0,0 +1,115 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+package main
+
+import (
+       "context"
+       "flag"
+       "fmt"
+       "os"
+       "os/signal"
+       "strconv"
+       "time"
+       "xappmock/dispatcher"
+       "xappmock/frontend"
+       "xappmock/logger"
+       "xappmock/rmr"
+       "xappmock/sender"
+)
+
+const (
+       ENV_RMR_PORT     = "RMR_PORT"
+       RMR_PORT_DEFAULT = 5001
+)
+
+var rmrService *rmr.Service
+
+func main() {
+
+       logLevel, _ := logger.LogLevelTokenToLevel("info")
+       logger, err := logger.InitLogger(logLevel)
+       if err != nil {
+               fmt.Printf("#app.main - failed to initialize logger, error: %s", err)
+               os.Exit(1)
+       }
+
+       var rmrContext *rmr.Context
+       var rmrConfig = rmr.Config{Port: RMR_PORT_DEFAULT, MaxMsgSize: rmr.RMR_MAX_MSG_SIZE, MaxRetries: 10, Flags: 0}
+
+       if port, err := strconv.ParseUint(os.Getenv(ENV_RMR_PORT), 10, 16); err == nil {
+               rmrConfig.Port = int(port)
+       } else {
+               logger.Infof("#main - %s: %s, using default (%d).", ENV_RMR_PORT, err, RMR_PORT_DEFAULT)
+       }
+
+       rmrService = rmr.NewService(rmrConfig, rmrContext)
+       jsonSender := sender.NewJsonSender(logger)
+       dispatcherDesc := dispatcher.New(logger, rmrService, jsonSender)
+
+       /* Load configuration file*/
+       err = frontend.ProcessConfigurationFile("resources", "conf", ".json",
+               func(data []byte) error {
+                       return frontend.JsonCommandsDecoder(data, dispatcherDesc.JsonCommandsDecoderCB)
+               })
+
+       if err != nil {
+               logger.Errorf("#main - processing error: %s", err)
+               os.Exit(1)
+       }
+
+       logger.Infof("#main - xApp Mock is up and running...")
+
+       flag.Parse()
+       cmd := flag.Arg(0) /*first remaining argument after flags have been processed*/
+
+       command, err := frontend.DecodeJsonCommand([]byte(cmd))
+
+       if err != nil {
+               logger.Errorf("#main - command decoding error: %s", err)
+               rmrService.CloseContext()
+               logger.Infof("#main - xApp Mock is down")
+               return
+       }
+
+       c := make(chan os.Signal, 1)
+       signal.Notify(c, os.Interrupt)
+       ctx, cancel := context.WithCancel(context.Background())
+
+       go func() {
+               oscall := <-c
+               logger.Infof("system call:%+v", oscall)
+               cancel()
+               rmrService.CloseContext()
+       }()
+
+       dispatcherDesc.ProcessJsonCommand(ctx, command)
+       pr := dispatcherDesc.GetProcessResult()
+
+       if pr.Err != nil {
+               logger.Errorf("#main - command processing Error: %s", pr.Err)
+       }
+
+       if pr.StartTime != nil {
+               processElapsedTimeInMs := float64(time.Since(*pr.StartTime)) / float64(time.Millisecond)
+               logger.Infof("#main - processing (sending/receiving) messages took %.2f ms", processElapsedTimeInMs)
+
+       }
+       logger.Infof("#main - process stats: %s", pr.Stats)
+
+       rmrService.CloseContext() // TODO: called twice
+       logger.Infof("#main - xApp Mock is down")
+}
diff --git a/tools/xappmock/models/json_command.go b/tools/xappmock/models/json_command.go
new file mode 100644 (file)
index 0000000..6ebd731
--- /dev/null
@@ -0,0 +1,35 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package models
+
+type JsonCommand struct {
+       Id               string
+       RmrMessageType   string
+       SendCommandId    string
+       ReceiveCommandId string
+       TransactionId    string
+       RanName          string
+       RanIp            string
+       RanPort          int
+       PayloadHeader    string
+       PackedPayload    string
+       Payload          string
+       Action           string
+       RepeatCount      int
+       RepeatDelayInMs  int
+}
diff --git a/tools/xappmock/models/message_info.go b/tools/xappmock/models/message_info.go
new file mode 100644 (file)
index 0000000..0833ffa
--- /dev/null
@@ -0,0 +1,48 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package models
+
+import (
+       "fmt"
+       "time"
+)
+
+// TODO: message command id / source / dest
+
+type MessageInfo struct {
+       MessageTimestamp int64  `json:"messageTimestamp"`
+       MessageType      int    `json:"messageType"`
+       Meid             string `json:"meid"`
+       Payload          []byte `json:"payload"`
+       TransactionId    string `json:"transactionId"`
+}
+
+func NewMessageInfo(messageType int, meid string, payload []byte, transactionId []byte) MessageInfo {
+       return MessageInfo{
+               MessageTimestamp: time.Now().Unix(),
+               MessageType:      messageType,
+               Meid:             meid,
+               Payload:          payload,
+               TransactionId:    string(transactionId),
+       }
+}
+
+func (mi MessageInfo) String() string {
+       return fmt.Sprintf("message timestamp: %d | message type: %d | meid: %s | payload: %x | transaction id: %s",
+               mi.MessageTimestamp, mi.MessageType, mi.Meid, mi.Payload, mi.TransactionId)
+}
diff --git a/tools/xappmock/models/process_result.go b/tools/xappmock/models/process_result.go
new file mode 100644 (file)
index 0000000..8847d2d
--- /dev/null
@@ -0,0 +1,43 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package models
+
+import (
+       "fmt"
+       "go.uber.org/atomic"
+       "time"
+)
+
+type ProcessStats struct {
+       SentCount               atomic.Int32
+       SentErrorCount          atomic.Int32
+       ReceivedExpectedCount   atomic.Int32
+       ReceivedUnexpectedCount atomic.Int32
+       ReceivedErrorCount      atomic.Int32
+}
+
+type ProcessResult struct {
+       StartTime *time.Time
+       Stats     ProcessStats
+       Err       error
+}
+
+func (ps ProcessStats) String() string {
+       return fmt.Sprintf("sent messages: %d | send errors: %d | expected received messages: %d | unexpected received messages: %d | receive errors: %d",
+               ps.SentCount, ps.SentErrorCount, ps.ReceivedExpectedCount, ps.ReceivedUnexpectedCount, ps.ReceivedErrorCount)
+}
diff --git a/tools/xappmock/resources/conf/configuration.json b/tools/xappmock/resources/conf/configuration.json
new file mode 100644 (file)
index 0000000..212a955
--- /dev/null
@@ -0,0 +1,75 @@
+[
+  {
+    "id": "X2_SETUP_REQUEST",
+    "rmrMessageType": "10060",
+    "transactionId": "e2e$",
+    "payloadHeader": "$ranIp|$ranPort|$ranName|#packedPayload|",
+    "packedPayload": "0006002a000002001500080013302300fffff000140017000001f700133023fffff0000000133023000000000001"
+  },
+  {
+    "id": "X2_SETUP_RESPONSE",
+    "rmrMessageType": "10061",
+    "packedPayload": "2006002a000002001500080002f82900007ab000140017000000630002f8290007ab00102002f829000001000133"
+  },
+  {
+    "id": "RIC_SUBSCRIPTION_REQUEST",
+    "rmrMessageType": "12010",
+    "transactionId": "e2e$",
+    "packedPayload": "00c9002b000003ea7e0005004eec0182ea6300020001ea810015000a0011121300212224264000ea6b000420000000"
+  },
+  {
+    "id": "RIC_SUBSCRIPTION_RESPONSE",
+    "rmrMessageType": "12011",
+    "transactionId": "e2e$",
+    "packedPayload": "20c9001d000003ea7e0005004eec0182ea6300020001ea6c000700ea6d40020000"
+  },
+  {
+    "id": "RIC_SUBSCRIPTION_FAILURE",
+    "rmrMessageType": "12012",
+    "transactionId": "e2e$",
+    "packedPayload": "40c9001f000003ea7e00050000010001ea6300020000ea6e000908ea6f400400014100"
+  },
+  {
+    "id": "RIC_SUBSCRIPTION_DELETE_REQUEST",
+    "rmrMessageType": "12020",
+    "transactionId": "e2e$",
+    "packedPayload": "00ca0012000002ea7e0005004eec0182ea6300020001"
+  },
+  {
+    "id": "RIC_SUBSCRIPTION_DELETE_RESPONSE",
+    "rmrMessageType": "12021",
+    "transactionId": "e2e$",
+    "packedPayload": "20ca0012000002ea7e0005004eec0182ea6300020001"
+  },
+  {
+    "id": "RIC_INDICATION",
+    "rmrMessageType": "12050"
+  },
+  {
+    "id": "RESOURCE_STATUS_REQUEST",
+    "rmrMessageType": "10090",
+    "transactionId": "e2e$",
+    "packedPayload": "0009003c0000080027000300000e001c00010000260004fe000000001d400d00001f4008000a0b0cabcd8000001e4001000040400100006d4001000091400100"
+  },
+  {
+    "id": "RESOURCE_STATUS_RESPONSE",
+    "rmrMessageType": "10091",
+    "transactionId": "e2e$",
+    "packedPayload": "20090065000003002700030000000028000300004a00414050000042404b4013302302b030a2800043400700020000000a000043400700040000000a000043400700080000000a000043400700200000000a000043400700400000000a000043400700800000000a00"
+  },
+  {
+    "id": "RESOURCE_STATUS_FAILURE",
+    "rmrMessageType": "10092",
+    "transactionId": "e2e$",
+    "packedPayload": "400900320000040027000300000e0028000300000c00054001620044401800004540130002f8290007ab500000434006000000000740"
+  },
+  {
+    "id": "RESOURCE_STATUS_UPDATE",
+    "rmrMessageType": "10090"
+  },
+  {
+    "id": "LOAD_INFORMATION",
+    "rmrMessageType": "10020"
+  }
+]
+
diff --git a/tools/xappmock/resources/router.txt b/tools/xappmock/resources/router.txt
new file mode 100644 (file)
index 0000000..015ca2e
--- /dev/null
@@ -0,0 +1,29 @@
+newrt|start
+rte|10060|10.0.2.15:38000
+rte|10360|10.0.2.15:38000
+rte|10070|10.0.2.15:38000
+rte|10071|10.0.2.15:3801
+rte|10061|10.0.2.15:3801
+rte|10361|10.0.2.15:3801
+rte|10062|10.0.2.15:3801
+rte|10362|10.0.2.15:3801
+rte|1080|10.0.2.15:3801
+rte|10020|10.0.2.15:5557
+rte|10370|10.0.2.15:3801
+rte|10371|10.0.2.15:38000
+rte|10372|10.0.2.15:38000
+rte|10080|10.0.2.15:3801
+rte|10081|10.0.2.15:38000
+rte|10082|10.0.2.15:38000
+rte|1100|10.0.2.15:3801
+rte|1090|10.0.2.15:38000
+rte|1200|10.0.2.15:4801
+rte|1210|10.0.2.15:4801
+rte|1220|10.0.2.15:4801
+rte|10090|10.0.2.15:38000
+rte|12010|10.0.2.15:38000
+rte|12011|10.0.2.15:5555
+rte|12020|10.0.2.15:38000
+rte|10091|10.0.2.15:4801
+rte|10092|10.0.2.15:4801
+newrt|end
similarity index 100%
rename from tools/xapp_mock/resp
rename to tools/xappmock/resp
similarity index 92%
rename from tools/xapp_mock/rmr/rmrCgoApi.go
rename to tools/xappmock/rmr/rmrCgoApi.go
index 86b2c81..489591e 100644 (file)
@@ -52,7 +52,7 @@ func (*Context) Init(port string, maxMsgSize int, maxRetries int, flags int) *Me
 func (ctx *Context) SendMsg(msg *MBuf) (*MBuf, error) {
 
        allocatedCMBuf, err := ctx.getAllocatedCRmrMBuf(msg, ctx.MaxMsgSize)
-       if err != nil{
+       if err != nil {
                return nil, err
        }
        if state := allocatedCMBuf.state; state != RMR_OK {
@@ -61,14 +61,14 @@ func (ctx *Context) SendMsg(msg *MBuf) (*MBuf, error) {
        }
        defer C.rmr_free_msg(allocatedCMBuf)
 
-       for i:=0; i < ctx.MaxRetries; i++ {
+       for i := 0; i < ctx.MaxRetries; i++ {
                currCMBuf := C.rmr_send_msg(ctx.RmrCtx, allocatedCMBuf)
                if state := currCMBuf.state; state != RMR_OK {
                        if state != RMR_ERR_RETRY {
                                errorMessage := fmt.Sprintf("#rmrCgoApi.SendMsg - Failed to send message. state: %v - %s", state, states[int(state)])
                                return nil, errors.New(errorMessage)
                        }
-                       time.Sleep(100*time.Millisecond)
+                       time.Sleep(100 * time.Millisecond)
                        continue
                }
                return convertToMBuf(currCMBuf)
@@ -78,11 +78,11 @@ func (ctx *Context) SendMsg(msg *MBuf) (*MBuf, error) {
 }
 
 func (ctx *Context) RecvMsg() (*MBuf, error) {
-       allocatedCMBuf, err :=C.rmr_alloc_msg(ctx.RmrCtx, C.int(ctx.MaxMsgSize))
-       if err != nil{
+       allocatedCMBuf, err := C.rmr_alloc_msg(ctx.RmrCtx, C.int(ctx.MaxMsgSize))
+       if err != nil {
                return nil, err
        }
-       if state := allocatedCMBuf.state;state != RMR_OK {
+       if state := allocatedCMBuf.state; state != RMR_OK {
                errorMessage := fmt.Sprintf("#rmrCgoApi.SendMsg - Failed to get allocated message. state: %v - %s", state, states[int(state)])
                return nil, errors.New(errorMessage)
        }
@@ -97,7 +97,6 @@ func (ctx *Context) RecvMsg() (*MBuf, error) {
        return convertToMBuf(currCMBuf)
 }
 
-
 func (ctx *Context) IsReady() bool {
        return int(C.rmr_ready(ctx.RmrCtx)) != 0
 }
similarity index 97%
rename from tools/xapp_mock/rmr/rmrCgoTypes.go
rename to tools/xappmock/rmr/rmrCgoTypes.go
index 7307aac..3f1ce24 100644 (file)
@@ -98,17 +98,15 @@ type MBuf struct {
        XAction []byte
 }
 
-
 func (m MBuf) String() string {
        return fmt.Sprintf("{ MType: %d, Len: %d, Meid: %q, Xaction: %q, Payload: [%x] }", m.MType, m.Len, m.Meid, m.XAction, m.Payload)
 }
 
-
 type Context struct {
-       MaxMsgSize     int
-       MaxRetries     int
-       Flags          int
-       RmrCtx         unsafe.Pointer
+       MaxMsgSize int
+       MaxRetries int
+       Flags      int
+       RmrCtx     unsafe.Pointer
 }
 
 type Messenger interface {
similarity index 83%
rename from tools/xapp_mock/rmr/rmrCgoUtils.go
rename to tools/xappmock/rmr/rmrCgoUtils.go
index 868b79c..d2fa040 100644 (file)
@@ -38,9 +38,9 @@ import (
 Allocates an mBuf and initialize it with the content of C.rmr_mbuf_t.
 The xAction field is assigned a a value without trailing spaces.
 */
-func convertToMBuf( m *C.rmr_mbuf_t) (*MBuf, error) {
-       payloadArr := C.GoBytes(unsafe.Pointer(m.payload),C.int(m.len))
-       xActionArr := C.GoBytes(unsafe.Pointer(m.xaction),C.int(RMR_MAX_XACTION_LEN))
+func convertToMBuf(m *C.rmr_mbuf_t) (*MBuf, error) {
+       payloadArr := C.GoBytes(unsafe.Pointer(m.payload), C.int(m.len))
+       xActionArr := C.GoBytes(unsafe.Pointer(m.xaction), C.int(RMR_MAX_XACTION_LEN))
 
        // Trim padding (space and 0)
        xActionStr := strings.TrimRight(string(xActionArr), "\040\000")
@@ -57,7 +57,7 @@ func convertToMBuf( m *C.rmr_mbuf_t) (*MBuf, error) {
 
        meidBuf := make([]byte, RMR_MAX_MEID_LEN)
        if meidCstr := C.rmr_get_meid(m, (*C.uchar)(unsafe.Pointer(&meidBuf[0]))); meidCstr != nil {
-               mbuf.Meid =     strings.TrimRight(string(meidBuf), "\000")
+               mbuf.Meid = strings.TrimRight(string(meidBuf), "\000")
        }
 
        return mbuf, nil
@@ -67,9 +67,9 @@ func convertToMBuf( m *C.rmr_mbuf_t) (*MBuf, error) {
 Allocates an C.rmr_mbuf_t and initialize it with the content of mBuf.
 The xAction field is padded with trailing spaces upto capacity
 */
-func (ctx *Context) getAllocatedCRmrMBuf( mBuf *MBuf, maxMsgSize int) (cMBuf *C.rmr_mbuf_t, rc error) {
+func (ctx *Context) getAllocatedCRmrMBuf(mBuf *MBuf, maxMsgSize int) (cMBuf *C.rmr_mbuf_t, rc error) {
        var xActionBuf [RMR_MAX_XACTION_LEN]byte
-       var meidBuf[RMR_MAX_MEID_LEN]byte
+       var meidBuf [RMR_MAX_MEID_LEN]byte
 
        cMBuf = C.rmr_alloc_msg(ctx.RmrCtx, C.int(maxMsgSize))
        cMBuf.mtype = C.int(mBuf.MType)
@@ -79,13 +79,13 @@ func (ctx *Context) getAllocatedCRmrMBuf( mBuf *MBuf, maxMsgSize int) (cMBuf *C.
        xActionLen := len(mBuf.XAction)
 
        copy(xActionBuf[:], mBuf.XAction)
-       for i:= xActionLen; i < RMR_MAX_XACTION_LEN; i++{
+       for i := xActionLen; i < RMR_MAX_XACTION_LEN; i++ {
                xActionBuf[i] = '\040' //space
        }
 
        // Add padding
        copy(meidBuf[:], mBuf.Meid)
-       for i:= len(mBuf.Meid); i < RMR_MAX_MEID_LEN; i++{
+       for i := len(mBuf.Meid); i < RMR_MAX_MEID_LEN; i++ {
                meidBuf[i] = 0
        }
 
@@ -101,19 +101,19 @@ func (ctx *Context) getAllocatedCRmrMBuf( mBuf *MBuf, maxMsgSize int) (cMBuf *C.
                return nil, errors.New(fmt.Sprintf("#rmrCgoUtils.getAllocatedCRmrMBuf - Failed to read xAction data to allocated RMR message buffer, %s", err))
        }
 
-       len := C.rmr_bytes2meid(cMBuf,  (*C.uchar)(unsafe.Pointer(&meidBuf[0])), C.int(RMR_MAX_XACTION_LEN))
+       len := C.rmr_bytes2meid(cMBuf, (*C.uchar)(unsafe.Pointer(&meidBuf[0])), C.int(RMR_MAX_XACTION_LEN))
        if int(len) != RMR_MAX_MEID_LEN {
                return nil, errors.New(
                        "#rmrCgoUtils.getAllocatedCRmrMBuf - Failed to copy meid data to allocated RMR message buffer")
        }
-       return cMBuf,nil
+       return cMBuf, nil
 }
 
 func MessageIdToUint(id string) (msgId uint64, err error) {
        if len(id) == 0 {
                msgId, err = 0, nil
-       } else{
+       } else {
                msgId, err = strconv.ParseUint(id, 10, 16)
        }
        return
-}
\ No newline at end of file
+}
similarity index 65%
rename from tools/xapp_mock/rmr/rmrEndPoint.go
rename to tools/xappmock/rmr/rmrEndPoint.go
index 03c0852..c8c8ae2 100644 (file)
 package rmr
 
 import (
-       "../frontend"
-       "log"
        "strconv"
 )
+
 // RmrService holds an instance of RMR messenger as well as its configuration
 type Service struct {
-       messenger  *Messenger
+       messenger *Messenger
 }
 
 // NewRmrService instantiates a new Rmr service instance
@@ -36,36 +35,17 @@ func NewService(rmrConfig Config, messenger Messenger) *Service {
        }
 }
 
-func (r *Service) SendMessage(messageType int, msg []byte, transactionId []byte) (*MBuf, error){
-       log.Printf( "SendMessage (type: %d, tid: %s, msg: %v", messageType, transactionId, msg)
+func (r *Service) SendMessage(messageType int, ranName string, msg []byte, transactionId []byte) (*MBuf, error) {
        mbuf := NewMBuf(messageType, len(msg), msg, transactionId)
+       mbuf.Meid = ranName
        return (*r.messenger).SendMsg(mbuf)
 }
 
-// ListenAndHandle waits for messages coming from rmr_rcv_msg and sends it to a designated message handler
-func (r *Service) ListenAndHandle() error {
-       for {
-               mbuf, err := (*r.messenger).RecvMsg()
-
-               if err != nil {
-                       return err
-               }
-
-               if _, ok := frontend.WaitedForRmrMessageType[mbuf.MType]; ok {
-                       log.Printf( "ListenAndHandle Expected msg: %s", mbuf)
-                       break
-               } else {
-                       log.Printf( "ListenAndHandle Unexpected msg: %s", mbuf)
-               }
-       }
-       return nil
+func (r *Service) RecvMessage() (*MBuf, error) {
+       return (*r.messenger).RecvMsg()
 }
 
-
 func (r *Service) CloseContext() {
        (*r.messenger).Close()
 
 }
-
-
-
similarity index 69%
rename from tools/xapp_mock/sender/jsonSender.go
rename to tools/xappmock/sender/jsonSender.go
index d7d4ffb..f890add 100644 (file)
@@ -20,22 +20,33 @@ Binary file (standard input) matches
 package sender
 
 import (
-       "../frontend"
-       "../rmr"
        "fmt"
        "github.com/pkg/errors"
-       "log"
+       "os"
        "reflect"
        "strconv"
        "strings"
        "sync/atomic"
        "time"
        "unicode"
+       "xappmock/logger"
+       "xappmock/models"
+       "xappmock/rmr"
 )
 
 var counter uint64
 
-func SendJsonRmrMessage(command frontend.JsonCommand /*the copy is modified locally*/, xAction *[]byte, r *rmr.Service) error {
+type JsonSender struct {
+       logger *logger.Logger
+}
+
+func NewJsonSender(logger *logger.Logger) *JsonSender {
+       return &JsonSender{
+               logger: logger,
+       }
+}
+
+func (s *JsonSender) SendJsonRmrMessage(command models.JsonCommand /*the copy is modified locally*/, xAction *[]byte, r *rmr.Service) error {
        var payload []byte
        _, err := fmt.Sscanf(command.PackedPayload, "%x", &payload)
        if err != nil {
@@ -46,12 +57,18 @@ func SendJsonRmrMessage(command frontend.JsonCommand /*the copy is modified loca
        if len(command.TransactionId) == 0 {
                command.TransactionId = string(*xAction)
        }
-       command.PayloadHeader = expandPayloadHeader(command.PayloadHeader, &command)
+       command.PayloadHeader = s.expandPayloadHeader(command.PayloadHeader, &command)
+       s.logger.Infof("#JsonSender.SendJsonRmrMessage - command payload header: %s", command.PayloadHeader)
        rmrMsgId, err := rmr.MessageIdToUint(command.RmrMessageType)
        if err != nil {
-               return errors.New(fmt.Sprintf("invalid rmr message id: %s",command.WaitForRmrMessageType))
+               return errors.New(fmt.Sprintf("invalid rmr message id: %s", command.RmrMessageType))
        }
-       _, err = r.SendMessage(int(rmrMsgId), append([]byte(command.PayloadHeader), payload...), []byte(command.TransactionId))
+
+       msg := append([]byte(command.PayloadHeader), payload...)
+       messageInfo := models.NewMessageInfo(int(rmrMsgId), command.RanName, msg, []byte(command.TransactionId))
+       s.logger.Infof("#JsonSender.SendJsonRmrMessage - going to send message: %s", messageInfo)
+
+       _, err = r.SendMessage(int(rmrMsgId), command.RanName, msg, []byte(command.TransactionId))
        return err
 }
 
@@ -78,7 +95,7 @@ func expandTransactionId(id string) string {
  * Example: “payloadHeader”: “$ranIp|$ranPort|$ranName|#packedPayload|”
  */
 
-func expandPayloadHeader(header string, command *frontend.JsonCommand) string {
+func (s *JsonSender) expandPayloadHeader(header string, command *models.JsonCommand) string {
        var name strings.Builder
        var expandedHeader strings.Builder
 
@@ -88,12 +105,17 @@ func expandPayloadHeader(header string, command *frontend.JsonCommand) string {
                if err != nil {
                        break
                }
+
                switch ch {
                case '$':
                        for {
-                               ch, err = r.ReadByte()  //on error ch == 0
+                               ch, err = r.ReadByte() //on error ch == 0
                                if unicode.IsDigit(rune(ch)) || unicode.IsLetter(rune(ch)) {
-                                       name.WriteByte(ch)
+                                       if name.Len() == 0 {
+                                               name.WriteByte(byte(unicode.ToUpper(rune(ch))))
+                                       } else {
+                                               name.WriteByte(ch)
+                                       }
                                } else {
                                        if fieldValue := reflect.Indirect(reflect.ValueOf(command)).FieldByName(name.String()); fieldValue.IsValid() {
                                                switch fieldValue.Kind() {
@@ -106,7 +128,8 @@ func expandPayloadHeader(header string, command *frontend.JsonCommand) string {
                                                case reflect.Float64, reflect.Float32:
                                                        expandedHeader.WriteString(fmt.Sprintf("%g", fieldValue.Float()))
                                                default:
-                                                       log.Fatalf("invalid type for $%s, value must be a string, an int, a bool or a float", name.String())
+                                                       s.logger.Errorf("#JsonSender.expandPayloadHeader - invalid type for $%s, value must be a string, an int, a bool or a float", name.String())
+                                                       os.Exit(1)
                                                }
                                        }
                                        name.Reset()
@@ -115,15 +138,20 @@ func expandPayloadHeader(header string, command *frontend.JsonCommand) string {
                        }
                case '#':
                        for {
-                               ch, err = r.ReadByte()  //on error ch == 0
+                               ch, err = r.ReadByte() //on error ch == 0
                                if unicode.IsDigit(rune(ch)) || unicode.IsLetter(rune(ch)) {
-                                       name.WriteByte(ch)
+                                       if name.Len() == 0 {
+                                               name.WriteByte(byte(unicode.ToUpper(rune(ch))))
+                                       } else {
+                                               name.WriteByte(ch)
+                                       }
                                } else {
                                        if fieldValue := reflect.Indirect(reflect.ValueOf(command)).FieldByName(name.String()); fieldValue.IsValid() {
                                                if fieldValue.Kind() == reflect.String {
                                                        expandedHeader.WriteString(strconv.FormatInt(int64(len(fieldValue.String())), 10))
                                                } else {
-                                                       log.Fatalf("invalid type for #%s, value must be a string", name.String())
+                                                       s.logger.Errorf("#JsonSender.expandPayloadHeader - invalid type for #%s, value must be a string", name.String())
+                                                       os.Exit(1)
                                                }
                                        }
                                        name.Reset()
@@ -145,5 +173,5 @@ func incAndGetCounter() uint64 {
 }
 
 func init() {
-       counter = uint64(time.Now().Second())
+       counter = uint64(time.Now().Unix() - 1572000000)
 }