# documentation
.tox
docs/_build/
+/.gitreview
RUN python3 -m pip install robotframework \
&& pip install --upgrade RESTinstance \
&& pip install docker \
+ && pip install -U robotframework-requests\
&& apt-get update
WORKDIR /opt
+++ /dev/null
-##############################################################################
-#
-# 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
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 ***
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
--- /dev/null
+*** 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
+
+
+
--- /dev/null
+##############################################################################
+#
+# 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
Resource ../Resource/scripts_variables.robot
Library OperatingSystem
Library ../Scripts/find_rmr_message.py
+Library ../Scripts/rsmscripts.py
Library REST ${url}
${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
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
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
+++ /dev/null
-##############################################################################
-#
-# 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
Resource ../Resource/Keywords.robot
Library OperatingSystem
Library ../Scripts/find_rmr_message.py
+Library ../Scripts/rsmscripts.py
Library REST ${url}
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
Resource ../Resource/Keywords.robot
Library OperatingSystem
Library ../Scripts/find_rmr_message.py
+Library ../Scripts/rsmscripts.py
Library REST ${url}
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
--- /dev/null
+##############################################################################
+#
+# 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
--- /dev/null
+##############################################################################
+#
+# 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
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
Verfiy Disconnected ConnectionStatus
- Sleep 1s
+ Sleep 10s
GET /v1/nodeb/test1
Integer response status 200
String response body ranName test1
--- /dev/null
+##############################################################################
+#
+# 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
--- /dev/null
+##############################################################################
+#
+# 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
--- /dev/null
+##############################################################################
+#
+# 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
--- /dev/null
+##############################################################################
+#
+# 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
+
--- /dev/null
+##############################################################################
+#
+# 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
--- /dev/null
+##############################################################################
+#
+# 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
Library REST ${url}
-*** Variables ***
-${restart_docker_sim} docker restart gnbe2_simu
-
*** Test Cases ***
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
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
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
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}
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}
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}
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}
${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}
+
*** 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
${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
#
import config
import redis
+import time
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
--- /dev/null
+##############################################################################
+#
+# 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)
+
--- /dev/null
+##############################################################################
+#
+# 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
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
import config
import redis
+import cleanup_db
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")
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"
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")
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
+
--- /dev/null
+##############################################################################
+#
+# 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
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}
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 ***
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
${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}
--- /dev/null
+##############################################################################
+#
+# 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}
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
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
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 ***
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}
+
+++ /dev/null
-##############################################################################
-#
-# 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
Resource ../Resource/Keywords.robot
Library OperatingSystem
Library ../Scripts/find_rmr_message.py
+Library ../Scripts/rsmscripts.py
Library REST ${url}
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
Resource ../Resource/Keywords.robot
Library OperatingSystem
Library ../Scripts/find_rmr_message.py
+Library ../Scripts/rsmscripts.py
Library REST ${url}
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
# 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
# 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
package main
import (
+ "e2mgr/clients"
"e2mgr/configuration"
"e2mgr/controllers"
- "e2mgr/converters"
"e2mgr/httpserver"
"e2mgr/logger"
"e2mgr/managers"
"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)
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
--- /dev/null
+//
+// 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
--- /dev/null
+//
+// 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
--- /dev/null
+//
+// 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)
+//}
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 {
}
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")
+}
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) {
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 {
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) {
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 {
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() })
}
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 {
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() })
}
# 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
--- /dev/null
+//
+// 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)
+}
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 {
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}
"e2mgr/mocks"
"e2mgr/models"
"e2mgr/providers/httpmsghandlerprovider"
- "e2mgr/rNibWriter"
"e2mgr/rmrCgo"
"e2mgr/services"
"e2mgr/services/rmrsender"
"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"
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")
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")
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")
}
func TestShutdownHandlerRnibError(t *testing.T) {
- controller, readerMock, _, _ := setupControllerTest(t)
+ controller, readerMock, _, _, _ := setupControllerTest(t)
rnibErr := &common.ResourceNotFoundError{}
var nbIdentityList []*entities.NbIdentity
}
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)
}
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)
}
func TestHeaderValidationFailed(t *testing.T) {
- controller, _, _, _ := setupControllerTest(t)
+ controller, _, _, _, _ := setupControllerTest(t)
writer := httptest.NewRecorder()
}
func TestShutdownStatusNoContent(t *testing.T) {
- controller, readerMock, _, _ := setupControllerTest(t)
+ controller, readerMock, _, _, _ := setupControllerTest(t)
var rnibError error
nbIdentityList := []*entities.NbIdentity{}
}
func TestHandleInternalError(t *testing.T) {
- controller, _, _, _ := setupControllerTest(t)
+ controller, _, _, _, _ := setupControllerTest(t)
writer := httptest.NewRecorder()
err := e2managererrors.NewInternalError()
}
func TestHandleCommandAlreadyInProgressError(t *testing.T) {
- controller, _, _, _ := setupControllerTest(t)
+ controller, _, _, _, _ := setupControllerTest(t)
writer := httptest.NewRecorder()
err := e2managererrors.NewCommandAlreadyInProgressError()
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")
}
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()
}
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()
}
func TestX2ResetHandleFailureInvalidBody(t *testing.T) {
- controller, _, _, _ := setupControllerTest(t)
+ controller, _, _, _ , _:= setupControllerTest(t)
ranName := "test1"
}
func TestHandleErrorResponse(t *testing.T) {
- controller, _, _, _ := setupControllerTest(t)
+ controller, _, _, _ , _:= setupControllerTest(t)
writer := httptest.NewRecorder()
controller.handleErrorResponse(e2managererrors.NewRnibDbError(), writer)
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)
}
"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"
}
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
}
// #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{}
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
}
package converters
import (
- "e2mgr/e2pdus"
"e2mgr/logger"
"fmt"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
/**** 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) {
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 {
// #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"
)
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)}
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))
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)}
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
}
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))))
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 {
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 {
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
}
package converters
import (
- "e2mgr/e2pdus"
"e2mgr/logger"
"fmt"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
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) {
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 {
--- /dev/null
+//
+// 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
+}
--- /dev/null
+//
+// 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"
+}
--- /dev/null
+#----- 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
+
--- /dev/null
+/*******************************************************************************
+ *
+ * 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)
+ }
+}
--- /dev/null
+/*******************************************************************************
+ *
+ * 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
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 {
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
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=
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=
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=
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=
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=
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=
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=
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=
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=
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=
"e2mgr/e2managererrors"
"e2mgr/logger"
"e2mgr/mocks"
- "e2mgr/rNibWriter"
"e2mgr/rmrCgo"
"e2mgr/services"
"e2mgr/services/rmrsender"
"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"
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
}
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)
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)
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)
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)
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)
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)
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)
}
--- /dev/null
+//
+// 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
+}
--- /dev/null
+//
+// 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)
+}
"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"
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
}
"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"
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
}
"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"
)
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
}
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")
}
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)
"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"
)
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)
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)
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)
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)
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
+//
+// 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/managers"
"e2mgr/mocks"
"e2mgr/models"
- "e2mgr/rNibWriter"
"e2mgr/rmrCgo"
"e2mgr/services"
"e2mgr/services/rmrsender"
"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}
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}
//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)
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}
//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)
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}
//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)
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
--- /dev/null
+//
+// 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)
+}
--- /dev/null
+//
+// 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")
+}
+//
+// 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"
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
}
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)
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 {
"e2mgr/models"
"e2mgr/rmrCgo"
"e2mgr/services/rmrsender"
- "unsafe"
+ "e2mgr/utils"
)
type EndcConfigurationUpdateHandler struct {
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))
}
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(¬ificationRequest)
- 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(¬ificationRequest)
- rmrMessengerMock.AssertCalled(t, "SendMsg", mBuf)
+ rmrMessengerMock.AssertCalled(t, "SendMsg", mBuf, true)
}
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))
-}
"e2mgr/managers"
"e2mgr/mocks"
"e2mgr/models"
- "e2mgr/rNibWriter"
"e2mgr/rmrCgo"
"e2mgr/services"
"e2mgr/services/rmrsender"
"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"
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)
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(¬ificationRequest)
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) {
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) {
}
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,
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,
}
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)
}
"e2mgr/services"
"e2mgr/services/rmrsender"
"e2mgr/utils"
- "fmt"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
- "unsafe"
)
type X2ResetRequestNotificationHandler struct {
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
-}
"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"
)
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)
}
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
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)
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{}
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
"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"
)
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)
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(¬ificationRequest)
- rmrMessengerMock.AssertCalled(t, "SendMsg", ranRestartedMbuf)
+ rmrMessengerMock.AssertCalled(t, "SendMsg", ranRestartedMbuf, true)
}
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(¬ificationRequest)
- rmrMessengerMock.AssertCalled(t, "SendMsg", ranRestartedMbuf)
+ rmrMessengerMock.AssertCalled(t, "SendMsg", ranRestartedMbuf, true)
}
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)
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)
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)
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")
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)
"e2mgr/models"
"e2mgr/rmrCgo"
"e2mgr/services/rmrsender"
- "unsafe"
+ "e2mgr/utils"
)
type X2EnbConfigurationUpdateHandler struct {
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))
}
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(¬ificationRequest)
- 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(¬ificationRequest)
- rmrMessengerMock.AssertCalled(t, "SendMsg", mBuf)
+ rmrMessengerMock.AssertCalled(t, "SendMsg", mBuf, true)
}
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")
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")
}
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 {
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 {
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 {
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 {
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 {
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 {
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 {
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 {
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
+}
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)
}
err = log.Sync()
assert.Nil(t, err)
-
+
os.Stdout = old
logFile, err = os.Open("./loggerTest.txt")
if err != nil{
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)
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 {
s,_= buf.ReadString('\n')
}
return entryNum == 1
-}
+}
\ No newline at end of file
--- /dev/null
+//
+// 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
+}
--- /dev/null
+//
+// 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)
+}
--- /dev/null
+//
+// 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
--- /dev/null
+//
+// 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
--- /dev/null
+//
+// 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
+}
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)
--- /dev/null
+//
+// 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
+}
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)
--- /dev/null
+//
+// 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
+}
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
}
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"
)
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
}
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
}
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)
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)
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
"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"
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"
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"
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)
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)
}
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,
}
// 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)
"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"
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
}
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)
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)
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")
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")
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")
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")
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)
}
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)
--- /dev/null
+//
+// 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
+}
+++ /dev/null
-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
--- /dev/null
+//
+// 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()
+}
--- /dev/null
+//
+// 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
// 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
--- /dev/null
+//
+// 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)
+//}
+++ /dev/null
-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()
-}
--- /dev/null
+//
+// 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()
+}
--- /dev/null
+// 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)
+}
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)
}
args := m.Called(inventoryName)
errArg := args.Get(1);
-
if errArg != nil {
return args.Get(0).(*entities.NodebInfo), errArg.(error);
}
args := m.Called(nodeType, globalNbId)
errArg := args.Get(1);
-
if errArg != nil {
return args.Get(0).(*entities.NodebInfo), errArg.(error);
}
args := m.Called(inventoryName)
errArg := args.Get(1);
-
if errArg != nil {
return args.Get(0).(*entities.Cells), errArg.(error);
}
args := m.Called()
errArg := args.Get(1);
-
if errArg != nil {
return args.Get(0).([]*entities.NbIdentity), errArg.(error);
}
args := m.Called()
errArg := args.Get(1);
-
if errArg != nil {
return args.Get(0).([]*entities.NbIdentity), errArg.(error);
}
args := m.Called()
errArg := args.Get(1);
-
if errArg != nil {
return args.Int(0), errArg.(error);
}
args := m.Called(inventoryName, pci)
errArg := args.Get(1);
-
if errArg != nil {
return args.Get(0).(*entities.Cell), errArg.(error);
}
args := m.Called(cellType, cellId)
errArg := args.Get(1);
-
if errArg != nil {
return args.Get(0).(*entities.Cell), errArg.(error);
}
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)
+}
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)
+}
--- /dev/null
+//
+// 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()
+}
--- /dev/null
+//
+// 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
// platform project (RICP).
-package models
+package models_test
import (
"e2mgr/logger"
+ "e2mgr/models"
"e2mgr/tests"
"encoding/hex"
"github.com/stretchr/testify/assert"
)
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())
}
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
--- /dev/null
+//
+// 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
--- /dev/null
+//
+// 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
--- /dev/null
+//
+// 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
+
+}
}
}
-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
}
}
}
-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
}
package models
type IResponse interface {
- Marshal() (string, error)
+ Marshal() ([]byte, error)
}
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),
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
-}
--- /dev/null
+//
+// 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
+}
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 {
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),
}
}
"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"
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) {
package rmrmsghandlerprovider
import (
+ "e2mgr/clients"
+ "e2mgr/configuration"
"e2mgr/converters"
"e2mgr/handlers/rmrmsghandlers"
"e2mgr/logger"
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]
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)
+}
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"
* 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)
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 {
}
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 {
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
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
}
/*
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)
return rNibErr
}
}
- err = (*w.sdl).Set(pairs)
+ err = w.sdl.Set(pairs)
if err != nil {
return common.NewInternalError(err)
}
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)
}
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)
}
/*
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())
pairs = append(pairs, nodebIdKey, data)
}
- err = (*w.sdl).Set(pairs)
+ err = w.sdl.Set(pairs)
if err != nil {
return common.NewInternalError(err)
/*
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)
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)
}
/*
-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) {
import (
"e2mgr/mocks"
+ "encoding/json"
"errors"
"fmt"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
"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}
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 {
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)
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
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
}
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
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
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
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)
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)
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)
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)
}
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)
}
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{}
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)
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
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
"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")
// 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)
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
}
}
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 {
// 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)
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
}
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 (
}
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()
}
+++ /dev/null
-//
-// 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
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
--- /dev/null
+newrt|start
+rte|1|127.0.0.1:3801
+newrt|end
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,
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)
}
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"
)
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)
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)
}
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,
}
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)
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
+}
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)
}
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)
}
"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"
)
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,
}
}
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
})
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
})
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
})
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
})
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
})
}
}
-
func isRnibConnectionError(err error) bool {
internalErr, ok := err.(*common.InternalError)
if !ok {
"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"
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
// 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)
+}
const (
MaxMsgSize int = 4096
- Port int = 5555
+ Port int = 3801
Flags int = 0
MessageType int = 1001
RanPort uint16 = 879
--- /dev/null
+//
+// 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}
+}
+
+
info:
title: E2 Manager Service
description: E2 Manager Service APIs
- version: 2.0.5
+ version: 3.0.3
servers:
- url: 'http://{apiRoot}/v1'
variables:
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:
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
=============
-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
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
--- /dev/null
+##############################################################################
+#
+# 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
--- /dev/null
+---
+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"
--- /dev/null
+//
+// 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")
+}
--- /dev/null
+//
+// 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() })
+}
--- /dev/null
+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
+)
--- /dev/null
+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=
--- /dev/null
+//
+// 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)
+}
--- /dev/null
+//
+// 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)
+}
--- /dev/null
+//
+// 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),
+ )
+ })
+}
--- /dev/null
+//
+// 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"`
+}
--- /dev/null
+//
+// 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"`
+}
--- /dev/null
+//
+// 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"`
+}
--- /dev/null
+//
+// 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"`
+}
--- /dev/null
+//
+// 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 {
+}
--- /dev/null
+//
+// 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 {
+}
--- /dev/null
+//
+// 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"`
+}
--- /dev/null
+//
+// 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"`
+}
--- /dev/null
+//
+// 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 {
+}
--- /dev/null
+//
+// 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"`
+}
--- /dev/null
+//
+// 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,
+ },
+}
--- /dev/null
+//
+// 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))
+}
--- /dev/null
+http:
+ port: 12020
+++ /dev/null
-[
- {“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" }
-]
+++ /dev/null
-//
-// 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
+++ /dev/null
-newrt|start
-rte|1001|10.0.2.15:38000
-rte|2002|10.0.2.15:3801
-newrt|end
# 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
--- /dev/null
+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)
+ }
+ }
+ }
+}
--- /dev/null
+//
+// 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"
+)
"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())
"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))
}
}
}
--- /dev/null
+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
+)
--- /dev/null
+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=
--- /dev/null
+//
+// 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)
+}
+
--- /dev/null
+//
+// 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")
+}
--- /dev/null
+//
+// 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
+}
--- /dev/null
+//
+// 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)
+}
--- /dev/null
+//
+// 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)
+}
--- /dev/null
+[
+ {
+ "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"
+ }
+]
+
--- /dev/null
+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
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 {
}
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)
}
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)
}
return convertToMBuf(currCMBuf)
}
-
func (ctx *Context) IsReady() bool {
return int(C.rmr_ready(ctx.RmrCtx)) != 0
}
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 {
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")
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
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)
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
}
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
+}
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
}
}
-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()
}
-
-
-
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 {
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
}
* 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
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() {
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()
}
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()
}
func init() {
- counter = uint64(time.Now().Second())
+ counter = uint64(time.Now().Unix() - 1572000000)
}