mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-13 12:40:28 +00:00
Compare commits
50 Commits
develop-ha
...
ldpc_decod
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f709560814 | ||
|
|
ec99b5179d | ||
|
|
d30c7c30bb | ||
|
|
0a5b46c4c8 | ||
|
|
580ea58119 | ||
|
|
0d4bceabad | ||
|
|
eea9f4874e | ||
|
|
c86bc8ce5c | ||
|
|
c115f01155 | ||
|
|
58ccdb2993 | ||
|
|
3fd8e59814 | ||
|
|
007f001b81 | ||
|
|
4e3da82743 | ||
|
|
f31cde65e3 | ||
|
|
f054fa20f3 | ||
|
|
b332265971 | ||
|
|
211ebf4ac4 | ||
|
|
153498a471 | ||
|
|
5e3f72ccc7 | ||
|
|
b61ea4bea3 | ||
|
|
6f996be21a | ||
|
|
d7187155f8 | ||
|
|
3375775a32 | ||
|
|
1d860c0f00 | ||
|
|
662f6634bf | ||
|
|
45a9bb8bd9 | ||
|
|
16967ddb2e | ||
|
|
cc3d03f738 | ||
|
|
d509dba9f0 | ||
|
|
db034d4f48 | ||
|
|
fd4597b8de | ||
|
|
20b10593db | ||
|
|
6a59f7e7f7 | ||
|
|
8b3993c75b | ||
|
|
9e0e7a8e14 | ||
|
|
bf54022242 | ||
|
|
139bc7d8ea | ||
|
|
76918b076a | ||
|
|
f9a19017a6 | ||
|
|
4e133fff30 | ||
|
|
495f5f563c | ||
|
|
4bfabcb1d5 | ||
|
|
d0f55118a7 | ||
|
|
e8e88f5459 | ||
|
|
19afd37b93 | ||
|
|
ce879f1f92 | ||
|
|
03e5bdd8ae | ||
|
|
e9def5ce04 | ||
|
|
052d0001e3 | ||
|
|
9ea6af0fc2 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -25,4 +25,3 @@ tags
|
||||
nfapi_nr_interface_scf
|
||||
*.log
|
||||
*.out
|
||||
CMakeUserPresets.json
|
||||
|
||||
129
CMakeLists.txt
129
CMakeLists.txt
@@ -23,7 +23,6 @@
|
||||
|
||||
cmake_minimum_required (VERSION 3.16)
|
||||
project (OpenAirInterface LANGUAGES C CXX)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
#########################################################
|
||||
# Base directories, compatible with legacy OAI building #
|
||||
@@ -31,10 +30,6 @@ set(CMAKE_CXX_STANDARD 17)
|
||||
set (OPENAIR_DIR ${CMAKE_SOURCE_DIR})
|
||||
|
||||
include("cmake_targets/macros.cmake")
|
||||
if(NOT DEFINED ENV{CPM_SOURCE_CACHE})
|
||||
set(CPM_SOURCE_CACHE ~/.cache/cpm/ CACHE FILEPATH "Directory to download CPM dependencies")
|
||||
endif()
|
||||
include("cmake_targets/CPM.cmake")
|
||||
|
||||
##############################
|
||||
### CCache: reduce compilation time
|
||||
@@ -89,6 +84,7 @@ set (OPENAIR2_DIR ${OPENAIR_DIR}/openair2)
|
||||
set (OPENAIR3_DIR ${OPENAIR_DIR}/openair3)
|
||||
set (OPENAIR3_DIR ${OPENAIR_DIR}/openair3)
|
||||
set (OPENAIR_CMAKE ${OPENAIR_DIR}/cmake_targets)
|
||||
set (OPENAIR_BIN_DIR ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY})
|
||||
|
||||
project (OpenAirInterface)
|
||||
|
||||
@@ -258,6 +254,12 @@ if(GIT_FOUND)
|
||||
)
|
||||
endif()
|
||||
|
||||
# Below is a hard-coded info
|
||||
set (FIRMWARE_VERSION "No svn information")
|
||||
add_definitions("-DFIRMWARE_VERSION=\"${FIRMWARE_VERSION}\"")
|
||||
add_definitions("-DPACKAGE_VERSION=\"Branch: ${GIT_BRANCH} Abrev. Hash: ${GIT_COMMIT_HASH} Date: ${GIT_COMMIT_DATE}\"")
|
||||
add_definitions("-DPACKAGE_BUGREPORT=\"openair4g-devel@lists.eurecom.fr\"")
|
||||
|
||||
# Debug related options
|
||||
#########################################
|
||||
add_boolean_option(DEBUG_ASN1 False "Enable ASN1 debug logs" OFF)
|
||||
@@ -293,8 +295,6 @@ set_property(CACHE KPM_VERSION PROPERTY STRINGS "KPM_V2_03" "KPM_V3_00")
|
||||
message(STATUS "Selected KPM Version: ${KPM_VERSION}")
|
||||
|
||||
|
||||
add_boolean_option(ENABLE_IMSCOPE OFF "Enable phy scope based on imgui" OFF)
|
||||
|
||||
##################################################
|
||||
# ASN.1 grammar C code generation & dependencies #
|
||||
##################################################
|
||||
@@ -435,18 +435,20 @@ add_library(f1ap
|
||||
${F1AP_DIR}/f1ap_cu_rrc_message_transfer.c
|
||||
${F1AP_DIR}/f1ap_cu_task.c
|
||||
${F1AP_DIR}/f1ap_cu_ue_context_management.c
|
||||
${F1AP_DIR}/f1ap_cu_warning_message_transmission.c
|
||||
${F1AP_DIR}/f1ap_du_interface_management.c
|
||||
${F1AP_DIR}/f1ap_du_paging.c
|
||||
${F1AP_DIR}/f1ap_du_rrc_message_transfer.c
|
||||
${F1AP_DIR}/f1ap_du_system_information.c
|
||||
${F1AP_DIR}/f1ap_du_task.c
|
||||
${F1AP_DIR}/f1ap_du_ue_context_management.c
|
||||
${F1AP_DIR}/f1ap_du_warning_message_transmission.c
|
||||
${F1AP_DIR}/f1ap_encoder.c
|
||||
${F1AP_DIR}/f1ap_handlers.c
|
||||
${F1AP_DIR}/f1ap_itti_messaging.c)
|
||||
target_include_directories(f1ap PUBLIC F1AP_DIR)
|
||||
target_link_libraries(f1ap PUBLIC asn1_f1ap L2_NR)
|
||||
target_link_libraries(f1ap PRIVATE ngap nr_rrc HASHTABLE f1ap_lib)
|
||||
target_include_directories(f1ap PRIVATE ${F1AP_DIR}/lib)
|
||||
target_link_libraries(f1ap PRIVATE ngap nr_rrc HASHTABLE)
|
||||
|
||||
# LPP
|
||||
##############
|
||||
@@ -496,10 +498,30 @@ if (ENABLE_LDPC_T2)
|
||||
add_library(ldpc_t2 MODULE ${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c)
|
||||
set_target_properties(ldpc_t2 PROPERTIES COMPILE_FLAGS "-DALLOW_EXPERIMENTAL_API")
|
||||
target_link_libraries(ldpc_t2 ${LIBDPDK_T2_LDFLAGS} ${PMD_T2})
|
||||
set(PHY_LDPC_SLOT_T2_SRC
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_coding_t2.c
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim8segmulti.c
|
||||
)
|
||||
add_library(ldpc_slot_t2 MODULE ${PHY_LDPC_SLOT_T2_SRC})
|
||||
set_target_properties(ldpc_slot_t2 PROPERTIES COMPILE_FLAGS "-DALLOW_EXPERIMENTAL_API")
|
||||
target_link_libraries(ldpc_slot_t2 PRIVATE ldpc_gen_HEADERS ${LIBDPDK_T2_LDFLAGS} ${PMD_T2})
|
||||
endif()
|
||||
|
||||
##########################################################
|
||||
|
||||
# LDPC offload library - XDMA
|
||||
##########################################################
|
||||
add_boolean_option(ENABLE_LDPC_XDMA OFF "Build support for LDPC Offload to XDMA library" OFF)
|
||||
if (ENABLE_LDPC_XDMA)
|
||||
set(PHY_NRLDPC_CODING_XDMA_SRC
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload_xdma.c
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_coding_interface_xdma.c
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_coding_interface_demo_encoder.c
|
||||
)
|
||||
add_library(ldpc_xdma MODULE ${PHY_NRLDPC_CODING_XDMA_SRC})
|
||||
endif()
|
||||
|
||||
include_directories ("${OPENAIR_DIR}/radio/COMMON")
|
||||
|
||||
##############################################################
|
||||
@@ -542,8 +564,16 @@ add_boolean_option(NAS_UE True "NAS UE INSTANCE (<> NAS_MME)"
|
||||
add_boolean_option(RRC_DEFAULT_RAB_IS_AM True "set the LTE RLC mode to AM for the default bearer, otherwise it is UM." ON)
|
||||
|
||||
# add the binary tree to the search path for include files
|
||||
# We will find common/oai_version.h after generation in target directory
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
#######################################################
|
||||
# We will find ConfigOAI.h after generation in target directory
|
||||
include_directories("${OPENAIR_BIN_DIR}")
|
||||
# add directories to find all include files
|
||||
# the internal rule is to use generic names such as defs.h
|
||||
# but to make it uniq name as adding the relative path in the include directtive
|
||||
# example: #include "RRC/LTE/rrc_defs.h"
|
||||
#find_path (include_dirs_all *.h ${OPENAIR_DIR})
|
||||
#find_path (include_dirs_all *.h PATHS /usr/include NO_CMAKE_PATH)
|
||||
#include_directories("${include_dirs_all}")
|
||||
|
||||
# Legacy exact order
|
||||
|
||||
@@ -838,10 +868,19 @@ add_library(ldpc_cl MODULE ${PHY_LDPC_CL_SRC} )
|
||||
target_link_libraries(ldpc_cl OpenCL)
|
||||
add_dependencies(ldpc_cl nrLDPC_decoder_kernels_CL)
|
||||
|
||||
set(PHY_NRLDPC_CODING_DEMO_SRC
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_coding_interface_demo_decoder.c
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_coding_interface_demo_encoder.c
|
||||
)
|
||||
|
||||
set(PHY_NR_CODINGIF
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_load.c
|
||||
)
|
||||
|
||||
set(PHY_NRLDPC_CODINGIF
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_coding_interface_load.c
|
||||
)
|
||||
|
||||
##############################################
|
||||
# Base CUDA setting
|
||||
##############################################
|
||||
@@ -862,6 +901,7 @@ add_library(coding MODULE ${PHY_TURBOSRC} )
|
||||
|
||||
add_library(dfts MODULE ${OPENAIR1_DIR}/PHY/TOOLS/oai_dfts.c ${OPENAIR1_DIR}/PHY/TOOLS/oai_dfts_neon.c)
|
||||
|
||||
add_library(ldpc_slot_demo MODULE ${PHY_NRLDPC_CODING_DEMO_SRC})
|
||||
|
||||
set(PHY_SRC_COMMON
|
||||
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dci_tools_common.c
|
||||
@@ -1001,7 +1041,7 @@ set(PHY_SRC_UE
|
||||
|
||||
set(PHY_NR_SRC_COMMON
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_prach_common.c
|
||||
${OPENAIR1_DIR}/PHY/nr_phy_common/src/nr_phy_common_csirs.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_csi_rs.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_scrambling.c
|
||||
${OPENAIR1_DIR}/PHY/NR_REFSIG/scrambling_luts.c
|
||||
${OPENAIR1_DIR}/PHY/NR_REFSIG/refsig.c
|
||||
@@ -1021,7 +1061,9 @@ set(PHY_SRC_UE
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dlsch.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dlsch_tools.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dlsch_coding.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dlsch_coding_slot.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch_decoding_slot.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_tbs_tools.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_sch_dmrs.c
|
||||
@@ -1033,12 +1075,12 @@ set(PHY_SRC_UE
|
||||
${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_gen_mod_table.c
|
||||
${OPENAIR1_DIR}/PHY/NR_REFSIG/dmrs_nr.c
|
||||
${OPENAIR1_DIR}/PHY/NR_REFSIG/ptrs_nr.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_csi_rs.c
|
||||
${OPENAIR1_DIR}/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c
|
||||
${OPENAIR1_DIR}/PHY/NR_ESTIMATION/nr_freq_equalization.c
|
||||
${OPENAIR1_DIR}/PHY/NR_ESTIMATION/nr_measurements_gNB.c
|
||||
${OPENAIR1_DIR}/PHY/TOOLS/file_output.c
|
||||
${OPENAIR1_DIR}/PHY/TOOLS/cadd_vv.c
|
||||
#${OPENAIR1_DIR}/PHY/TOOLS/lte_dfts.c
|
||||
${OPENAIR1_DIR}/PHY/TOOLS/log2_approx.c
|
||||
${OPENAIR1_DIR}/PHY/TOOLS/cmult_sv.c
|
||||
${OPENAIR1_DIR}/PHY/TOOLS/cmult_vv.c
|
||||
@@ -1051,6 +1093,7 @@ set(PHY_SRC_UE
|
||||
${PHY_POLARSRC}
|
||||
${PHY_SMALLBLOCKSRC}
|
||||
${PHY_NR_CODINGIF}
|
||||
${PHY_NRLDPC_CODINGIF}
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/pucch_rx.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/srs_rx.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_uci_tools_common.c
|
||||
@@ -1070,7 +1113,10 @@ set(PHY_SRC_UE
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_psbch_tx.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_ulsch_coding_slot.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding_slot.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_tbs_tools.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_prach_common.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_sch_dmrs.c
|
||||
@@ -1093,6 +1139,7 @@ set(PHY_SRC_UE
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_ESTIMATION/nr_adjust_gain.c
|
||||
${OPENAIR1_DIR}/PHY/TOOLS/file_output.c
|
||||
${OPENAIR1_DIR}/PHY/TOOLS/cadd_vv.c
|
||||
# ${OPENAIR1_DIR}/PHY/TOOLS/lte_dfts.c
|
||||
${OPENAIR1_DIR}/PHY/TOOLS/log2_approx.c
|
||||
${OPENAIR1_DIR}/PHY/TOOLS/cmult_sv.c
|
||||
${OPENAIR1_DIR}/PHY/TOOLS/cmult_vv.c
|
||||
@@ -1103,9 +1150,11 @@ set(PHY_SRC_UE
|
||||
${OPENAIR1_DIR}/PHY/TOOLS/lut.c
|
||||
${OPENAIR1_DIR}/PHY/TOOLS/simde_operations.c
|
||||
${OPENAIR1_DIR}/PHY/INIT/nr_init_ue.c
|
||||
# ${OPENAIR1_DIR}/SIMULATION/NR_UE_PHY/unit_tests/src/pucch_uci_test.c
|
||||
${PHY_POLARSRC}
|
||||
${PHY_SMALLBLOCKSRC}
|
||||
${PHY_NR_CODINGIF}
|
||||
${PHY_NRLDPC_CODINGIF}
|
||||
)
|
||||
|
||||
|
||||
@@ -1202,7 +1251,6 @@ set(NR_PDCP_SRC
|
||||
${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_sdu.c
|
||||
${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_timer_thread.c
|
||||
${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_security_nea2.c
|
||||
${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_security_nea1.c
|
||||
${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_integrity_nia2.c
|
||||
${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_integrity_nia1.c
|
||||
${OPENAIR2_DIR}/LAYER2/nr_pdcp/asn1_utils.c
|
||||
@@ -1260,6 +1308,7 @@ set(L2_NR_SRC
|
||||
${NR_PDCP_SRC}
|
||||
${NR_SDAP_SRC}
|
||||
${NR_RRC_DIR}/rrc_gNB.c
|
||||
${NR_RRC_DIR}/nr_rrc_common.c
|
||||
${NR_RRC_DIR}/mac_rrc_dl_direct.c
|
||||
${NR_RRC_DIR}/mac_rrc_dl_f1ap.c
|
||||
${NR_RRC_DIR}/nr_rrc_config.c
|
||||
@@ -1271,7 +1320,6 @@ set(L2_NR_SRC
|
||||
${NR_RRC_DIR}/rrc_gNB_radio_bearers.c
|
||||
${NR_RRC_DIR}/rrc_gNB_cuup.c
|
||||
${NR_RRC_DIR}/rrc_gNB_du.c
|
||||
${NR_RRC_DIR}/rrc_gNB_mobility.c
|
||||
)
|
||||
|
||||
set(L2_SRC_UE
|
||||
@@ -1434,8 +1482,6 @@ add_library(L2_NR
|
||||
${GNB_APP_SRC}
|
||||
)
|
||||
target_link_libraries(L2_NR PRIVATE ds alg)
|
||||
target_link_libraries(L2_NR PRIVATE f1ap_lib)
|
||||
target_include_directories(L2_NR PRIVATE ${F1AP_DIR}/lib)
|
||||
|
||||
add_library(e1_if
|
||||
${NR_RRC_DIR}/cucp_cuup_direct.c
|
||||
@@ -1782,7 +1828,7 @@ add_library(LIB_NAS_SIMUE
|
||||
${NAS_SRC}UE/nas_parser.c
|
||||
${NAS_SRC}UE/nas_proc.c
|
||||
${NAS_SRC}UE/nas_user.c
|
||||
${NAS_SRC}NR_UE/nr_nas_msg.c
|
||||
${NAS_SRC}NR_UE/nr_nas_msg_sim.c
|
||||
${libnas_api_OBJS}
|
||||
${libnas_ue_api_OBJS}
|
||||
${libnas_emm_msg_OBJS}
|
||||
@@ -1845,6 +1891,8 @@ add_library(NB_IoT MODULE ${NBIOT_SOURCES} )
|
||||
|
||||
add_library(LIB_5GNAS_GNB
|
||||
${NAS_SRC}/COMMON/nr_common.c
|
||||
${NAS_SRC}/gNB/network_process_nas.c
|
||||
${NAS_SRC}/NR_UE/ue_process_nas.c
|
||||
${OPENAIR3_DIR}//UICC/usim_interface.c
|
||||
)
|
||||
|
||||
@@ -2037,10 +2085,14 @@ if(E2_AGENT)
|
||||
endif()
|
||||
|
||||
|
||||
add_dependencies(nr-softmodem ldpc_orig ldpc_optim ldpc_optim8seg ldpc)
|
||||
add_dependencies(nr-softmodem ldpc_orig ldpc_optim ldpc_optim8seg ldpc ldpc_slot_demo)
|
||||
|
||||
if (ENABLE_LDPC_T2)
|
||||
add_dependencies(nr-softmodem ldpc_t2)
|
||||
add_dependencies(nr-softmodem ldpc_t2 ldpc_slot_t2)
|
||||
endif()
|
||||
|
||||
if (ENABLE_LDPC_XDMA)
|
||||
add_dependencies(nr-softmodem ldpc_xdma)
|
||||
endif()
|
||||
|
||||
# force the generation of ASN.1 so that we don't need to wait during the build
|
||||
@@ -2094,7 +2146,7 @@ target_link_libraries(nr-uesoftmodem PRIVATE pthread m CONFIG_LIB rt nr_ue_phy_m
|
||||
target_link_libraries(nr-uesoftmodem PRIVATE ${T_LIB})
|
||||
target_link_libraries(nr-uesoftmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
|
||||
|
||||
add_dependencies( nr-uesoftmodem ldpc_orig ldpc_optim ldpc_optim8seg ldpc )
|
||||
add_dependencies( nr-uesoftmodem ldpc_orig ldpc_optim ldpc_optim8seg ldpc ldpc_slot_demo)
|
||||
if (ENABLE_LDPC_CUDA)
|
||||
add_dependencies(nr-uesoftmodem ldpc_cuda)
|
||||
add_dependencies(nr-softmodem ldpc_cuda)
|
||||
@@ -2255,8 +2307,12 @@ add_executable(nr_ulsim
|
||||
)
|
||||
|
||||
if (ENABLE_LDPC_T2)
|
||||
add_dependencies(nr_ulsim ldpc_t2)
|
||||
add_dependencies(nr_ulsim ldpc_t2 ldpc_slot_t2)
|
||||
endif()
|
||||
if (ENABLE_LDPC_XDMA)
|
||||
add_dependencies(nr_ulsim ldpc_xdma)
|
||||
endif()
|
||||
add_dependencies(nr_ulsim ldpc_slot_demo)
|
||||
|
||||
target_link_libraries(nr_ulsim PRIVATE
|
||||
-Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECURITY ngap -lz -Wl,--end-group
|
||||
@@ -2323,7 +2379,7 @@ if (${T_TRACER})
|
||||
PHY_COMMON PHY PHY_UE PHY_NR PHY_NR_COMMON PHY_NR_UE PHY_RU PHY_MEX
|
||||
L2 L2_LTE L2_NR L2_LTE_NR L2_UE NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON MAC_UE_NR ngap
|
||||
CN_UTILS GTPV1U SCTP_CLIENT MME_APP LIB_NAS_UE NB_IoT SIMU OPENAIR0_LIB
|
||||
ldpc_orig ldpc_optim ldpc_optim8seg ldpc_t2 ldpc_cl ldpc_cuda ldpc dfts config_internals nr_common)
|
||||
ldpc_orig ldpc_optim ldpc_optim8seg ldpc_t2 ldpc_cl ldpc_cuda ldpc ldpc_slot_demo ldpc_slot_t2 ldpc_xdma dfts config_internals nr_common)
|
||||
if (TARGET ${i})
|
||||
add_dependencies(${i} generate_T)
|
||||
endif()
|
||||
@@ -2343,24 +2399,17 @@ if(ENABLE_TESTS)
|
||||
find_package(GTest)
|
||||
if (NOT GTest_FOUND)
|
||||
message(STATUS "GTest package not found, will download googletest automatically. To prevent that install google test on your system (libgtest-dev)")
|
||||
CPMAddPackage(
|
||||
NAME googletest
|
||||
GITHUB_REPOSITORY google/googletest
|
||||
GIT_TAG release-1.12.1
|
||||
VERSION 1.12.1
|
||||
OPTIONS "INSTALL_GTEST OFF" "gtest_force_shared_crt" "BUILD_GMOCK OFF"
|
||||
)
|
||||
endif()
|
||||
|
||||
find_package(benchmark)
|
||||
if (NOT benchmark_FOUND)
|
||||
message(STATUS "benchmark package not found, will download benchmark automatically. To prevent that install google benchmark on your system (libbenchmark-dev)")
|
||||
CPMAddPackage(
|
||||
NAME benchmark
|
||||
GITHUB_REPOSITORY google/benchmark
|
||||
VERSION 1.9.0
|
||||
OPTIONS "BENCHMARK_ENABLE_TESTING OFF"
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
googletest
|
||||
GIT_REPOSITORY https://github.com/google/googletest.git
|
||||
GIT_TAG 58d77fa8070e8cec2dc1ed015d66b454c8d78850 # 1.12.1
|
||||
)
|
||||
set(BUILD_GMOCK OFF)
|
||||
set(INSTALL_GTEST OFF)
|
||||
FetchContent_MakeAvailable(googletest)
|
||||
add_library(GTest::gtest ALIAS gtest)
|
||||
add_library(GTest::gtest_main ALIAS gtest_main)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
{
|
||||
"version": 3,
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "default",
|
||||
"displayName": "Default Config",
|
||||
"description": "Default build using Ninja generator",
|
||||
"generator": "Ninja",
|
||||
"binaryDir": "${sourceDir}/cmake_targets/ran_build/build",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "RelWithDebInfo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tests",
|
||||
"displayName": "Default unit test config",
|
||||
"inherits": "default",
|
||||
"binaryDir": "${sourceDir}/cmake_targets/ran_build/build_test",
|
||||
"cacheVariables": {
|
||||
"ENABLE_TESTS": "ON",
|
||||
"SANITIZE_ADDRESS": "ON",
|
||||
"CMAKE_BUILD_TYPE": "RelWithDebInfo"
|
||||
}
|
||||
}
|
||||
],
|
||||
"buildPresets": [
|
||||
{
|
||||
"name": "5gdefault",
|
||||
"configurePreset": "default",
|
||||
"targets": [
|
||||
"nr-uesoftmodem",
|
||||
"nr-softmodem",
|
||||
"rfsimulator",
|
||||
"dfts",
|
||||
"ldpc",
|
||||
"params_libconfig",
|
||||
"params_yaml"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "default",
|
||||
"inherits": "5gdefault"
|
||||
},
|
||||
{
|
||||
"name": "4gdefault",
|
||||
"configurePreset": "default",
|
||||
"targets": [
|
||||
"lte-softmodem",
|
||||
"lte-uesoftmodem",
|
||||
"dfts",
|
||||
"coding",
|
||||
"rfsimulator",
|
||||
"params_libconfig"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "tests",
|
||||
"configurePreset": "tests",
|
||||
"targets": [
|
||||
"tests"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -7,8 +7,9 @@
|
||||
<a href="https://releases.ubuntu.com/20.04/"><img src="https://img.shields.io/badge/OS-Ubuntu20-Green" alt="Supported OS Ubuntu 20"></a>
|
||||
<a href="https://releases.ubuntu.com/22.04/"><img src="https://img.shields.io/badge/OS-Ubuntu22-Green" alt="Supported OS Ubuntu 22"></a>
|
||||
<a href="https://releases.ubuntu.com/24.04/"><img src="https://img.shields.io/badge/OS-Ubuntu24-Green" alt="Supported OS Ubuntu 24"></a>
|
||||
<a href="https://www.redhat.com/en/technologies/linux-platforms/enterprise-linux"><img src="https://img.shields.io/badge/OS-RHEL8-Green" alt="Supported OS RHEL8"></a>
|
||||
<a href="https://www.redhat.com/en/technologies/linux-platforms/enterprise-linux"><img src="https://img.shields.io/badge/OS-RHEL9-Green" alt="Supported OS RELH9"></a>
|
||||
<a href="https://getfedora.org/en/workstation/"><img src="https://img.shields.io/badge/OS-Fedore41-Green" alt="Supported OS Fedora 41"></a>
|
||||
<a href="https://getfedora.org/en/workstation/"><img src="https://img.shields.io/badge/OS-Fedore40-Green" alt="Supported OS Fedora 40"></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
@@ -42,7 +43,6 @@ Please see [NOTICE](NOTICE.md) file for third party software that is included in
|
||||
|
||||
* [General overview of documentation](./doc/README.md)
|
||||
* [The implemented features](./doc/FEATURE_SET.md)
|
||||
* [System Requirements for Using OAI Stack](./doc/system_requirements.md)
|
||||
* [How to build](./doc/BUILD.md)
|
||||
* [How to run the modems](./doc/RUNMODEM.md)
|
||||
|
||||
@@ -75,8 +75,7 @@ openairinterface5g
|
||||
├── openair3 : Layer 3 (3GPP LTE Rel-10 S1AP/GTP, NR Rel-15 NGAP/GTP)
|
||||
├── openshift : OpenShift helm charts for some deployment options of OAI
|
||||
├── radio : Drivers for various radios such as USRP, AW2S, RFsim, 7.2 FHI, ...
|
||||
├── targets : Some configuration files; only historical relevance, and might be deleted in the future
|
||||
└── tools : Tools for use by the developers/ci machines: code analysis and formatting
|
||||
└── targets : Some configuration files; only historical relevance, and might be deleted in the future
|
||||
```
|
||||
|
||||
# How to get support from the OAI Community #
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
apiVersion: v1
|
||||
name: oai-nr-pbchsim-scs
|
||||
description: A Helm subchart for nr-pbchsim network function ("Other SCS" tests)
|
||||
|
||||
# A chart can be either an 'application' or a 'library' chart.
|
||||
#
|
||||
# Application charts are a collection of templates that can be packaged into versioned archives
|
||||
# to be deployed.
|
||||
#
|
||||
# Library charts provide useful utilities or functions for the chart developer. They're included as
|
||||
# a dependency of application charts to inject those utilities and functions into the rendering
|
||||
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
|
||||
type: application
|
||||
|
||||
icon: http://www.openairinterface.org/wp-content/uploads/2015/06/cropped-oai_final_logo.png
|
||||
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
version: 0.1.1
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application.
|
||||
appVersion: v1
|
||||
|
||||
keywords:
|
||||
- Physical Simulator
|
||||
- nr-pbchsim
|
||||
- RAN
|
||||
- 5G
|
||||
|
||||
sources:
|
||||
- https://gitlab.eurecom.fr/oai/openairinterface5g
|
||||
|
||||
maintainers:
|
||||
- name: OPENAIRINTERFACE
|
||||
email: contact@openairinterface.org
|
||||
@@ -1,63 +0,0 @@
|
||||
{{/* vim: set filetype=mustache: */}}
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "oai-nr-pbchsim-scs.name" -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Create a default fully qualified app name.
|
||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||
If release name contains chart name it will be used as a full name.
|
||||
*/}}
|
||||
{{- define "oai-nr-pbchsim-scs.fullname" -}}
|
||||
{{- if .Values.fullnameOverride -}}
|
||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
|
||||
{{- else -}}
|
||||
{{- $name := default .Chart.Name .Values.nameOverride -}}
|
||||
{{- if contains $name .Release.Name -}}
|
||||
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
|
||||
{{- else -}}
|
||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Create chart name and version as used by the chart label.
|
||||
*/}}
|
||||
{{- define "oai-nr-pbchsim-scs.chart" -}}
|
||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Common labels
|
||||
*/}}
|
||||
{{- define "oai-nr-pbchsim-scs.labels" -}}
|
||||
helm.sh/chart: {{ include "oai-nr-pbchsim-scs.chart" . }}
|
||||
{{ include "oai-nr-pbchsim-scs.selectorLabels" . }}
|
||||
{{- if .Chart.AppVersion }}
|
||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||
{{- end }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Selector labels
|
||||
*/}}
|
||||
{{- define "oai-nr-pbchsim-scs.selectorLabels" -}}
|
||||
app.kubernetes.io/name: {{ include "oai-nr-pbchsim-scs.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Create the name of the service account to use
|
||||
*/}}
|
||||
{{- define "oai-nr-pbchsim-scs.serviceAccountName" -}}
|
||||
{{- if .Values.serviceAccount.create -}}
|
||||
{{ default (include "oai-nr-pbchsim-scs.fullname" .) .Values.serviceAccount.name }}
|
||||
{{- else -}}
|
||||
{{ default "default" .Values.serviceAccount.name }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
@@ -1,42 +0,0 @@
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: {{ .Chart.Name }}
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: physim
|
||||
spec:
|
||||
securityContext:
|
||||
{{- toYaml .Values.podSecurityContext | nindent 8 }}
|
||||
{{- if .Values.imagePullSecrets }}
|
||||
imagePullSecrets:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: physim
|
||||
image: "{{ .Values.global.image.repository }}:{{ .Values.global.image.version }}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.securityContext | nindent 12 }}
|
||||
env:
|
||||
- name: OPENAIR_DIR
|
||||
value: /opt/oai-physim
|
||||
command: ["/bin/sh", "-c"]
|
||||
args:
|
||||
- >
|
||||
cmake_targets/autotests/run_exec_autotests.bash -g "nr_pbchsim.otherSCS" -d bin/ &&
|
||||
echo "FINISHED" && sleep infinity
|
||||
dnsPolicy: ClusterFirst
|
||||
restartPolicy: Never
|
||||
schedulerName: default-scheduler
|
||||
serviceAccountName: {{ .Values.global.serviceAccountName }}
|
||||
terminationGracePeriodSeconds: 30
|
||||
{{- if .Values.global.nodeSelector}}
|
||||
nodeSelector:
|
||||
{{- toYaml .Values.global.nodeSelector | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- if .Values.global.nodeName.nrpbchsim273rb}}
|
||||
nodeName: {{ .Values.global.nodeName.nrpbchsim273rb }}
|
||||
{{- end }}
|
||||
@@ -1,48 +0,0 @@
|
||||
# Default values for oai-nr-pbchsim-scs
|
||||
# This is a YAML-formatted file.
|
||||
# Declare variables to be passed into your templates.
|
||||
|
||||
replicaCount: 1
|
||||
|
||||
image:
|
||||
# pullPolicy: IfNotPresent or Never or Always
|
||||
pullPolicy: Always
|
||||
|
||||
imagePullSecrets: []
|
||||
|
||||
nameOverride: ""
|
||||
fullnameOverride: ""
|
||||
|
||||
serviceAccount:
|
||||
# Specifies whether a service account should be created
|
||||
create: true
|
||||
# Annotations to add to the service account
|
||||
annotations: {}
|
||||
# The name of the service account to use.
|
||||
# If not set and create is true, a name is generated using the fullname template
|
||||
name: "oai-nr-pbchsim-scs"
|
||||
|
||||
podSecurityContext:
|
||||
runAsUser: 0
|
||||
runAsGroup: 0
|
||||
|
||||
securityContext:
|
||||
privileged: false
|
||||
|
||||
resources: {}
|
||||
# We usually recommend not to specify default resources and to leave this as a conscious
|
||||
# choice for the user. This also increases chances charts run on environments with little
|
||||
# resources, such as Minikube. If you do want to specify resources, uncomment the following
|
||||
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
|
||||
# limits:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
# requests:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
|
||||
nodeSelector: {}
|
||||
|
||||
tolerations: []
|
||||
|
||||
affinity: {}
|
||||
@@ -27,7 +27,6 @@ global:
|
||||
nrpbschsim106rb: dedale
|
||||
nrpbchsim217rb: dedale
|
||||
nrpbchsim273rb: dedale
|
||||
nrpbchsimscs: dedale
|
||||
nrpsbchsim: dedale
|
||||
nrprachsim: dedale
|
||||
nrpucchsim: dedale
|
||||
|
||||
@@ -200,8 +200,6 @@ pipeline {
|
||||
if (fileExists(xmlFile)) {
|
||||
mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " "
|
||||
echo "Test XML file : ${xmlFile}"
|
||||
} else {
|
||||
echo "Test XML file ${xmlFile}: no such file"
|
||||
}
|
||||
}
|
||||
withCredentials([
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
#!/bin/groovy
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698
|
||||
*
|
||||
* 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.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
def node = "porcepix"
|
||||
def resource = "CI-NEU-CI"
|
||||
|
||||
pipeline {
|
||||
agent {
|
||||
label node
|
||||
}
|
||||
options {
|
||||
timestamps()
|
||||
ansiColor('xterm')
|
||||
timeout(time: 3, unit: 'HOURS')
|
||||
}
|
||||
stages {
|
||||
stage ("Trigger NEU CI") {
|
||||
steps {
|
||||
lock (resource) {
|
||||
script {
|
||||
withCredentials([
|
||||
[$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.ColosseumCredentials}", usernameVariable: 'col_username', passwordVariable: 'col_password'],
|
||||
]) {
|
||||
// use eNB target branch variable if eNB repository is empty
|
||||
def git_Branch = ""
|
||||
if (params.eNB_Branch.isEmpty()) {
|
||||
echo 'eNB_Branch parameter is empty, using eNB_TargetBranch instead'
|
||||
git_Branch = params.eNB_TargetBranch
|
||||
} else {
|
||||
git_Branch = params.eNB_Branch
|
||||
}
|
||||
|
||||
// use default 10011 rf scenario if not specified
|
||||
if (params.Colosseum_Rf_Scenario.isEmpty()) {
|
||||
echo 'Colosseum_Rf_Scenario parameter is empty, defaulting to 10011'
|
||||
rf_scenario = "10011"
|
||||
} else {
|
||||
rf_scenario = params.Colosseum_Rf_Scenario
|
||||
}
|
||||
|
||||
sh "echo Testing reachability of Colosseum endpoint"
|
||||
sh "ping -c 3 10.100.1.253"
|
||||
|
||||
sh "./ci-scripts/colosseum_scripts/launch-job.sh ${col_username} ${col_password} ${currentBuild.number} ${params.eNB_Repository} ${git_Branch} ${rf_scenario} ${env.JOB_URL}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage ("Wait for job to finish") {
|
||||
steps {
|
||||
lock (resource) {
|
||||
script {
|
||||
withCredentials([
|
||||
[$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.ColosseumCredentials}", usernameVariable: 'col_username', passwordVariable: 'col_password'],
|
||||
]) {
|
||||
timeout (time: 2, unit: 'HOURS') {
|
||||
sh "./ci-scripts/colosseum_scripts/wait-job-end.sh ${col_username} ${col_password}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage ("Get test results") {
|
||||
steps {
|
||||
lock (resource) {
|
||||
script {
|
||||
withCredentials([
|
||||
[$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.ColosseumCredentials}", usernameVariable: 'col_username', passwordVariable: 'col_password'],
|
||||
]) {
|
||||
sh "./ci-scripts/colosseum_scripts/get-test-results.sh ${col_username} ${col_password}"
|
||||
}
|
||||
|
||||
if(fileExists("results.tar.xz")) {
|
||||
archiveArtifacts "results.tar.xz"
|
||||
|
||||
sh "mkdir -p results"
|
||||
sh "tar -xf results.tar.xz -C results --strip-components=1"
|
||||
|
||||
if(fileExists("results/test_summary.html")) {
|
||||
archiveArtifacts "results/test_summary.html"
|
||||
}
|
||||
|
||||
// check if test passed
|
||||
sh "./ci-scripts/colosseum_scripts/check-results.sh results/test_summary.html"
|
||||
|
||||
sh "rm -Rf ./results"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage ("Set job status") {
|
||||
steps {
|
||||
lock (resource) {
|
||||
script {
|
||||
echo 'Set job status'
|
||||
sh "./ci-scripts/colosseum_scripts/set-job-status.sh"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -193,8 +193,6 @@ pipeline {
|
||||
if (fileExists(xmlFile)) {
|
||||
mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " "
|
||||
echo "Test XML file : ${xmlFile}"
|
||||
} else {
|
||||
echo "Test XML file ${xmlFile}: no such file"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,8 +186,6 @@ pipeline {
|
||||
if (fileExists(xmlFile)) {
|
||||
mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " "
|
||||
echo "Test XML file : ${xmlFile}"
|
||||
} else {
|
||||
echo "Test XML file ${xmlFile}: no such file"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,8 +39,10 @@ if (params.LockResources != null && params.LockResources.trim().length() > 0)
|
||||
|
||||
// Terminate Status
|
||||
def termENB = 0
|
||||
def termStatusArray = new Boolean[termENB + 1]
|
||||
def termOAIUE = 1
|
||||
def termStatusArray = new Boolean[termOAIUE + 1]
|
||||
termStatusArray[termENB] = false
|
||||
termStatusArray[termOAIUE] = false
|
||||
|
||||
// Global Parameters. Normally they should be populated when the master job
|
||||
// triggers the slave job with parameters
|
||||
@@ -192,8 +194,6 @@ pipeline {
|
||||
if (fileExists(xmlFile)) {
|
||||
mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " "
|
||||
echo "Test XML file : ${xmlFile}"
|
||||
} else {
|
||||
echo "Test XML file ${xmlFile}: no such file"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -241,6 +241,23 @@ pipeline {
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Terminate OAI-UE') {
|
||||
steps {
|
||||
echo '\u2705 \u001B[32mTerminate OAI-UE\u001B[0m'
|
||||
withCredentials([
|
||||
[$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.UE_Credentials}", usernameVariable: 'UE_Username', passwordVariable: 'UE_Password']
|
||||
]) {
|
||||
sh "python3 ci-scripts/main.py --mode=TerminateOAIUE --UEIPAddress=${params.UE_IPAddress} --UEUserName=${UE_Username} --UEPassword=${UE_Password}"
|
||||
}
|
||||
}
|
||||
post {
|
||||
success {
|
||||
script {
|
||||
termStatusArray[termOAIUE] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Log Collection') {
|
||||
@@ -456,6 +473,13 @@ pipeline {
|
||||
sh "python3 ci-scripts/main.py --mode=TerminateeNB --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password}"
|
||||
}
|
||||
}
|
||||
if (!termStatusArray[termOAIUE]) {
|
||||
withCredentials([
|
||||
[$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.UE_Credentials}", usernameVariable: 'UE_Username', passwordVariable: 'UE_Password']
|
||||
]) {
|
||||
sh "python3 ci-scripts/main.py --mode=TerminateOAIUE --UEIPAddress=${params.UE_IPAddress} --UEUserName=${UE_Username} --UEPassword=${UE_Password}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,8 +189,6 @@ pipeline {
|
||||
if (fileExists(xmlFile)) {
|
||||
mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " "
|
||||
echo "Test XML file : ${xmlFile}"
|
||||
} else {
|
||||
echo "Test XML file ${xmlFile}: no such file"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,8 +200,6 @@ pipeline {
|
||||
if (fileExists(xmlFile)) {
|
||||
mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " "
|
||||
echo "Test XML file : ${xmlFile}"
|
||||
} else {
|
||||
echo "Test XML file ${xmlFile}: no such file"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,8 +181,6 @@ pipeline {
|
||||
if (fileExists(xmlFile)) {
|
||||
mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " "
|
||||
echo "Test XML file : ${xmlFile}"
|
||||
} else {
|
||||
echo "Test XML file ${xmlFile}: no such file"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
266
ci-scripts/Jenkinsfile-tmp-ue
Normal file
266
ci-scripts/Jenkinsfile-tmp-ue
Normal file
@@ -0,0 +1,266 @@
|
||||
#!/bin/groovy
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698
|
||||
*
|
||||
* 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.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
// Template Jenkins Declarative Pipeline script to run Test w/ RF HW
|
||||
|
||||
// Location of the python executor node shall be in the same subnet as the others servers
|
||||
def pythonExecutor = params.pythonExecutor
|
||||
|
||||
// Location of the test XML file to be run
|
||||
def testXMLFile = params.pythonTestXmlFile
|
||||
def mainPythonAllXmlFiles = ""
|
||||
def buildStageStatus = true
|
||||
|
||||
// Name of the test stage
|
||||
def testStageName = params.pipelineTestStageName
|
||||
|
||||
def lockResources = []
|
||||
if (params.LockResources != null && params.LockResources.trim().length() > 0)
|
||||
params.LockResources.trim().split(",").each{lockResources += [resource: it.trim()]}
|
||||
|
||||
// Terminate Status
|
||||
def termUE = 0
|
||||
def termENB = 1
|
||||
def termSPGW = 2
|
||||
def termMME = 3
|
||||
def termHSS = 4
|
||||
def termStatusArray = new Boolean[termHSS + 1]
|
||||
termStatusArray[termUE] = false
|
||||
termStatusArray[termENB] = false
|
||||
termStatusArray[termSPGW] = false
|
||||
termStatusArray[termMME] = false
|
||||
termStatusArray[termHSS] = false
|
||||
|
||||
// Global Parameters. Normally they should be populated when the master job
|
||||
// triggers the slave job with parameters
|
||||
def eNB_Repository
|
||||
def eNB_Branch
|
||||
def eNB_CommitID
|
||||
def eNB_AllowMergeRequestProcess = false
|
||||
def eNB_TargetBranch
|
||||
|
||||
pipeline {
|
||||
agent {
|
||||
label pythonExecutor
|
||||
}
|
||||
options {
|
||||
ansiColor('xterm')
|
||||
lock(extra: lockResources)
|
||||
}
|
||||
stages {
|
||||
stage ("Verify Parameters") {
|
||||
steps {
|
||||
script {
|
||||
echo '\u2705 \u001B[32mVerify Parameters\u001B[0m'
|
||||
def allParametersPresent = true
|
||||
|
||||
// It is already to late to check it
|
||||
if (params.pythonExecutor != null) {
|
||||
echo "eNB CI executor node : ${pythonExecutor}"
|
||||
}
|
||||
// If not present picking a default Stage Name
|
||||
if (params.pipelineTestStageName == null) {
|
||||
// picking default
|
||||
testStageName = 'Template Test Stage'
|
||||
}
|
||||
|
||||
if (params.LockResources == null) {
|
||||
echo "no LockResources given"
|
||||
allParametersPresent = false
|
||||
}
|
||||
if (params.UE_IPAddress == null) {
|
||||
allParametersPresent = false
|
||||
}
|
||||
if (params.UE_SourceCodePath == null) {
|
||||
allParametersPresent = false
|
||||
}
|
||||
if (params.UE_Credentials == null) {
|
||||
allParametersPresent = false
|
||||
}
|
||||
// the following 4 parameters should be pushed by the master trigger
|
||||
// if not present, take the job GIT variables (used for developing)
|
||||
if (params.eNB_Repository == null) {
|
||||
eNB_Repository = env.GIT_URL
|
||||
} else {
|
||||
eNB_Repository = params.eNB_Repository
|
||||
}
|
||||
echo "eNB_Repository : ${eNB_Repository}"
|
||||
if (params.eNB_Branch == null) {
|
||||
eNB_Branch = env.GIT_BRANCH
|
||||
} else {
|
||||
eNB_Branch = params.eNB_Branch
|
||||
}
|
||||
echo "eNB_Branch : ${eNB_Branch}"
|
||||
if (params.eNB_CommitID == null) {
|
||||
eNB_CommitID = env.GIT_COMMIT
|
||||
} else {
|
||||
eNB_CommitID = params.eNB_CommitID
|
||||
}
|
||||
echo "eNB_CommitID : ${eNB_CommitID}"
|
||||
if (params.eNB_mergeRequest != null) {
|
||||
eNB_AllowMergeRequestProcess = params.eNB_mergeRequest
|
||||
if (eNB_AllowMergeRequestProcess) {
|
||||
if (params.eNB_TargetBranch != null) {
|
||||
eNB_TargetBranch = params.eNB_TargetBranch
|
||||
} else {
|
||||
eNB_TargetBranch = 'develop'
|
||||
}
|
||||
echo "eNB_TargetBranch : ${eNB_TargetBranch}"
|
||||
}
|
||||
}
|
||||
/*
|
||||
if (params.EPC_IPAddress == null) {
|
||||
allParametersPresent = false
|
||||
}
|
||||
if (params.EPC_Type == null) {
|
||||
allParametersPresent = false
|
||||
}
|
||||
if (params.EPC_SourceCodePath == null) {
|
||||
allParametersPresent = false
|
||||
}
|
||||
if (params.EPC_Credentials == null) {
|
||||
allParametersPresent = false
|
||||
}
|
||||
*/
|
||||
if (allParametersPresent) {
|
||||
echo "All parameters are present"
|
||||
if (eNB_AllowMergeRequestProcess) {
|
||||
sh "git fetch"
|
||||
sh "./ci-scripts/doGitLabMerge.sh --src-branch ${eNB_Branch} --src-commit ${eNB_CommitID} --target-branch ${eNB_TargetBranch} --target-commit latest"
|
||||
} else {
|
||||
sh "git fetch"
|
||||
sh "git checkout -f ${eNB_CommitID}"
|
||||
}
|
||||
} else {
|
||||
echo "Some parameters are missing"
|
||||
sh "./ci-scripts/fail.sh"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage ("Build and Test") {
|
||||
steps {
|
||||
script {
|
||||
dir ('ci-scripts') {
|
||||
echo "\u2705 \u001B[32m${testStageName}\u001B[0m"
|
||||
// If not present picking a default XML file
|
||||
if (params.pythonTestXmlFile == null) {
|
||||
// picking default
|
||||
testXMLFile = 'xml_files/ue_band20_build.xml'
|
||||
echo "Test XML file(default): ${testXMLFile}"
|
||||
mainPythonAllXmlFiles += "--XMLTestFile=" + testXMLFile + " "
|
||||
} else {
|
||||
String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
|
||||
for (xmlFile in myXmlTestSuite) {
|
||||
if (fileExists(xmlFile)) {
|
||||
mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " "
|
||||
echo "Test XML file : ${xmlFile}"
|
||||
}
|
||||
}
|
||||
}
|
||||
withCredentials([
|
||||
[$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.UE_Credentials}", usernameVariable: 'UE_Username', passwordVariable: 'UE_Password'],
|
||||
]) {
|
||||
sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} ${mainPythonAllXmlFiles}"
|
||||
String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
|
||||
for (xmlFile in myXmlTestSuite) {
|
||||
if (fileExists(xmlFile)) {
|
||||
try {
|
||||
timeout (time: 60, unit: 'MINUTES') {
|
||||
sh "python3 main.py --mode=TestUE --UEIPAddress=${params.UE_IPAddress} --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --UEUserName=${UE_Username} --UEPassword=${UE_Password} --UESourceCodePath=${params.UE_SourceCodePath} --XMLTestFile=${xmlFile}"
|
||||
}
|
||||
} catch (Exception e) {
|
||||
currentBuild.result = 'FAILURE'
|
||||
buildStageStatus = false
|
||||
}
|
||||
}
|
||||
}
|
||||
sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus} --UEIPAddress=${params.UE_IPAddress} --UEUserName=${UE_Username} --UEPassword=${UE_Password}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Log Collection') {
|
||||
parallel {
|
||||
stage('Log Collection (OAI UE - Build)') {
|
||||
steps {
|
||||
echo '\u2705 \u001B[32mLog Collection (OAI UE - Build)\u001B[0m'
|
||||
withCredentials([
|
||||
[$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.UE_Credentials}", usernameVariable: 'UE_Username', passwordVariable: 'UE_Password']
|
||||
]) {
|
||||
sh "python3 ci-scripts/main.py --mode=LogCollectBuild --UEIPAddress=${params.UE_IPAddress} --UEUserName=${UE_Username} --UEPassword=${UE_Password} --UESourceCodePath=${params.UE_SourceCodePath}"
|
||||
|
||||
echo '\u2705 \u001B[32mLog Transfer (UE - Build)\u001B[0m'
|
||||
sh "sshpass -p \'${UE_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${UE_Username}@${params.UE_IPAddress}:${UE_SourceCodePath}/cmake_targets/build.log.zip ./build.log.${env.BUILD_ID}.zip || true"
|
||||
}
|
||||
script {
|
||||
if(fileExists("build.log.${env.BUILD_ID}.zip")) {
|
||||
archiveArtifacts "build.log.${env.BUILD_ID}.zip"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Log Collection (OAI UE - Run)') {
|
||||
steps {
|
||||
echo '\u2705 \u001B[32mLog Collection (OAI UE - Run)\u001B[0m'
|
||||
withCredentials([
|
||||
[$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.UE_Credentials}", usernameVariable: 'UE_Username', passwordVariable: 'UE_Password']
|
||||
]) {
|
||||
sh "python3 ci-scripts/main.py --mode=LogCollectOAIUE --UEIPAddress=${params.UE_IPAddress} --UEUserName=${UE_Username} --UEPassword=${UE_Password} --UESourceCodePath=${params.UE_SourceCodePath}"
|
||||
|
||||
echo '\u2705 \u001B[32mLog Transfer (UE - Run)\u001B[0m'
|
||||
sh "sshpass -p \'${UE_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${UE_Username}@${params.UE_IPAddress}:${UE_SourceCodePath}/cmake_targets/ue.log.zip ./ue.log.${env.BUILD_ID}.zip || true"
|
||||
}
|
||||
script {
|
||||
if(fileExists("ue.log.${env.BUILD_ID}.zip")) {
|
||||
archiveArtifacts "ue.log.${env.BUILD_ID}.zip"
|
||||
}
|
||||
if(fileExists("ci-scripts/test_results.html")) {
|
||||
sh "mv ci-scripts/test_results.html test_results-${JOB_NAME}.html"
|
||||
sh "sed -i -e 's#TEMPLATE_JOB_NAME#${JOB_NAME}#' -e 's@build #TEMPLATE_BUILD_ID@build #${BUILD_ID}@' -e 's#Build-ID: TEMPLATE_BUILD_ID#Build-ID: <a href=\"${BUILD_URL}\">${BUILD_ID}</a>#' -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' test_results-${JOB_NAME}.html"
|
||||
archiveArtifacts "test_results-${JOB_NAME}.html"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
post {
|
||||
always {
|
||||
script {
|
||||
if (params.pipelineZipsConsoleLog != null) {
|
||||
if (params.pipelineZipsConsoleLog) {
|
||||
echo "Archiving Jenkins console log"
|
||||
sh "wget --no-check-certificate --no-proxy ${env.JENKINS_URL}/job/${env.JOB_NAME}/${env.BUILD_ID}/consoleText -O consoleText.log || true"
|
||||
sh "zip -m consoleText.log.${env.BUILD_ID}.zip consoleText.log || true"
|
||||
if(fileExists("consoleText.log.${env.BUILD_ID}.zip")) {
|
||||
archiveArtifacts "consoleText.log.${env.BUILD_ID}.zip"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
160
ci-scripts/Jenkinsfile-trig-nsa
Normal file
160
ci-scripts/Jenkinsfile-trig-nsa
Normal file
@@ -0,0 +1,160 @@
|
||||
#!/bin/groovy
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698
|
||||
*
|
||||
* 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.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
// necessary for reading JSON
|
||||
import groovy.json.JsonSlurper
|
||||
|
||||
// Template Jenkins Declarative Pipeline script to run Test w/ RF HW
|
||||
|
||||
// Location of the python executor node shall be in the same subnet as the others servers
|
||||
def pythonExecutor = params.pythonExecutor
|
||||
|
||||
def TARGET_BRANCH = "develop"
|
||||
def ALLOW_MERGE = true
|
||||
def GitPostArgs = ''
|
||||
def jobStatus
|
||||
|
||||
pipeline {
|
||||
agent {
|
||||
label pythonExecutor
|
||||
}
|
||||
stages {
|
||||
stage ("Launcher") {
|
||||
steps {
|
||||
script {
|
||||
// retrieve MR that are opened nd with tag NSA
|
||||
MR_LIST = sh returnStdout: true, script: 'curl --silent "https://gitlab.eurecom.fr/api/v4/projects/oai%2Fopenairinterface5g/merge_requests?state=opened&per_page=100&labels=NSA" | jq -cj "[.[].iid]"'
|
||||
echo "List of selected MRs: ${MR_LIST.trim()}"
|
||||
def MR_ARRAY = new JsonSlurper().parseText(MR_LIST.trim())
|
||||
// for every selected MR, retrieve the branch name and the latest commit
|
||||
for (MR in MR_ARRAY) {
|
||||
SRC_BRANCH=sh returnStdout: true, script: """curl --silent "https://gitlab.eurecom.fr/api/v4/projects/oai%2Fopenairinterface5g/merge_requests/${MR}" | jq ".source_branch" || true """
|
||||
SRC_BRANCH=SRC_BRANCH.trim()
|
||||
COMMIT_ID=sh returnStdout: true, script: """curl --silent "https://gitlab.eurecom.fr/api/v4/projects/oai%2Fopenairinterface5g/merge_requests/${MR}" | jq ".sha" || true """
|
||||
COMMIT_ID=COMMIT_ID.trim()
|
||||
echo "Testing NSA on : ${MR} ${SRC_BRANCH} ${COMMIT_ID}"
|
||||
commit = COMMIT_ID.replace("\"","")
|
||||
GitPostArgs = MR + ' ' + commit + ' '
|
||||
echo GitPostArgs
|
||||
|
||||
//calling LTE 2x2
|
||||
jobName = "RAN-LTE-2x2-Module-OAIEPC"
|
||||
jobStatus = build job: jobName, wait : true, propagate : false, parameters: [
|
||||
string(name: 'eNB_MR', value: String.valueOf(MR)),
|
||||
string(name: 'eNB_Branch', value: String.valueOf(SRC_BRANCH)),
|
||||
string(name: 'eNB_CommitID', value: String.valueOf(COMMIT_ID)),
|
||||
string(name: 'eNB_TargetBranch', value: String.valueOf(TARGET_BRANCH)),
|
||||
booleanParam(name: 'eNB_mergeRequest', value: Boolean.valueOf(ALLOW_MERGE))
|
||||
]
|
||||
jobResult = jobStatus.getResult()
|
||||
build_url = jobStatus.getAbsoluteUrl()
|
||||
build_id = jobStatus.getNumber().toString()
|
||||
GitPostArgs += jobName + ' ' + build_url + ' ' + build_id + ' ' + jobResult + ' '
|
||||
echo GitPostArgs
|
||||
|
||||
//calling NSA B200
|
||||
jobName = "RAN-NSA-B200-Module-LTEBOX"
|
||||
jobStatus = build job: jobName, wait : true, propagate : false, parameters: [
|
||||
string(name: 'eNB_MR', value: String.valueOf(MR)),
|
||||
string(name: 'eNB_Branch', value: String.valueOf(SRC_BRANCH)),
|
||||
string(name: 'eNB_CommitID', value: String.valueOf(COMMIT_ID)),
|
||||
string(name: 'eNB_TargetBranch', value: String.valueOf(TARGET_BRANCH)),
|
||||
booleanParam(name: 'eNB_mergeRequest', value: Boolean.valueOf(ALLOW_MERGE))
|
||||
]
|
||||
jobResult = jobStatus.getResult()
|
||||
build_url = jobStatus.getAbsoluteUrl()
|
||||
build_id = jobStatus.getNumber().toString()
|
||||
GitPostArgs += jobName + ' ' + build_url + ' ' + build_id + ' ' + jobResult + ' '
|
||||
echo GitPostArgs
|
||||
|
||||
//calling NSA 2x2
|
||||
jobName = "RAN-NSA-2x2-Module-OAIEPC"
|
||||
jobStatus = build job: jobName, wait : true, propagate : false, parameters: [
|
||||
string(name: 'eNB_MR', value: String.valueOf(MR)),
|
||||
string(name: 'eNB_Branch', value: String.valueOf(SRC_BRANCH)),
|
||||
string(name: 'eNB_CommitID', value: String.valueOf(COMMIT_ID)),
|
||||
string(name: 'eNB_TargetBranch', value: String.valueOf(TARGET_BRANCH)),
|
||||
booleanParam(name: 'eNB_mergeRequest', value: Boolean.valueOf(ALLOW_MERGE))
|
||||
]
|
||||
jobResult = jobStatus.getResult()
|
||||
build_url = jobStatus.getAbsoluteUrl()
|
||||
build_id = jobStatus.getNumber().toString()
|
||||
GitPostArgs += jobName + ' ' + build_url + ' ' + build_id + ' ' + jobResult + ' '
|
||||
echo GitPostArgs
|
||||
|
||||
//calling SA
|
||||
jobName = "RAN-SA-Module-CN5G"
|
||||
jobStatus = build job: jobName, wait : true, propagate : false, parameters: [
|
||||
string(name: 'eNB_MR', value: String.valueOf(MR)),
|
||||
string(name: 'eNB_Branch', value: String.valueOf(SRC_BRANCH)),
|
||||
string(name: 'eNB_CommitID', value: String.valueOf(COMMIT_ID)),
|
||||
string(name: 'eNB_TargetBranch', value: String.valueOf(TARGET_BRANCH)),
|
||||
booleanParam(name: 'eNB_mergeRequest', value: Boolean.valueOf(ALLOW_MERGE))
|
||||
]
|
||||
jobResult = jobStatus.getResult()
|
||||
build_url = jobStatus.getAbsoluteUrl()
|
||||
build_id = jobStatus.getNumber().toString()
|
||||
GitPostArgs += jobName + ' ' + build_url + ' ' + build_id + ' ' + jobResult + ' '
|
||||
echo GitPostArgs
|
||||
|
||||
//calling SA-AmariS
|
||||
jobName = "RAN-SA-AmariS-CN5G"
|
||||
jobStatus = build job: jobName, wait : true, propagate : false, parameters: [
|
||||
string(name: 'eNB_MR', value: String.valueOf(MR)),
|
||||
string(name: 'eNB_Branch', value: String.valueOf(SRC_BRANCH)),
|
||||
string(name: 'eNB_CommitID', value: String.valueOf(COMMIT_ID)),
|
||||
string(name: 'eNB_TargetBranch', value: String.valueOf(TARGET_BRANCH)),
|
||||
booleanParam(name: 'eNB_mergeRequest', value: Boolean.valueOf(ALLOW_MERGE))
|
||||
]
|
||||
jobResult = jobStatus.getResult()
|
||||
build_url = jobStatus.getAbsoluteUrl()
|
||||
build_id = jobStatus.getNumber().toString()
|
||||
GitPostArgs += jobName + ' ' + build_url + ' ' + build_id + ' ' + jobResult + ' '
|
||||
echo GitPostArgs
|
||||
|
||||
//calling OAIUE N310-X300
|
||||
jobName = "RAN-SA-OAIUE-N310-X300-CN5G"
|
||||
jobStatus = build job: jobName, wait : true, propagate : false, parameters: [
|
||||
string(name: 'eNB_MR', value: String.valueOf(MR)),
|
||||
string(name: 'eNB_Branch', value: String.valueOf(SRC_BRANCH)),
|
||||
string(name: 'eNB_CommitID', value: String.valueOf(COMMIT_ID)),
|
||||
string(name: 'eNB_TargetBranch', value: String.valueOf(TARGET_BRANCH)),
|
||||
booleanParam(name: 'eNB_mergeRequest', value: Boolean.valueOf(ALLOW_MERGE))
|
||||
]
|
||||
jobResult = jobStatus.getResult()
|
||||
build_url = jobStatus.getAbsoluteUrl()
|
||||
build_id = jobStatus.getNumber().toString()
|
||||
GitPostArgs += jobName + ' ' + build_url + ' ' + build_id + ' ' + jobResult + ' '
|
||||
echo GitPostArgs
|
||||
|
||||
//git report the test results in 1 block, at the end of the test sequence of one MR
|
||||
dir ('ci-scripts/ran_dashboard') {
|
||||
sh "python3 Hdashboard.py gitpost ${GitPostArgs}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,284 +0,0 @@
|
||||
/* UE simulator configuration file version 2021-06-17
|
||||
* LTE / 5G Non StandAlone
|
||||
* Copyright (C) 2019-2021 Amarisoft
|
||||
*/
|
||||
{
|
||||
#define N_ANTENNA_DL 1
|
||||
#define N_ANTENNA_UL 1
|
||||
#define DL_ARFCN 631296
|
||||
#define TDD 1
|
||||
|
||||
log_options: "all.level=warn,all.max_size=0,nas.level=debug,nas.max_size=1,rrc.level=debug,rrc.max_size=1",
|
||||
log_filename: "/tmp/ue.log",
|
||||
|
||||
/* Enable remote API and Web interface */
|
||||
com_addr: "0.0.0.0:9002",
|
||||
|
||||
include "rf_driver_20/1chan.cfg",
|
||||
|
||||
/* If true, allow the simulation of several UEs at the same time and
|
||||
allow dynamic UE creation from remote API */
|
||||
|
||||
cell_groups: [{
|
||||
group_type: "nr",
|
||||
multi_ue: true,
|
||||
ldpc_max_its:8,
|
||||
cells: [{
|
||||
rf_port: 0,
|
||||
bandwidth: 20,
|
||||
band: 78,
|
||||
dl_nr_arfcn: DL_ARFCN,
|
||||
ssb_nr_arfcn: DL_ARFCN,
|
||||
subcarrier_spacing: 30,
|
||||
n_antenna_dl: N_ANTENNA_DL,
|
||||
n_antenna_ul: N_ANTENNA_UL,
|
||||
rx_to_tx_latency:2,
|
||||
global_timing_advance:-1,
|
||||
}],
|
||||
}],
|
||||
|
||||
/* UE capabilities */
|
||||
/* USIM data */
|
||||
ue_list: [
|
||||
{
|
||||
"ue_id" : 1,
|
||||
"imsi": "001020000000001",
|
||||
"K": "fec86ba6eb707ed08905757b1bb44b8f",
|
||||
"sim_algo":"milenage",
|
||||
"op": "1006020f0a478bf6b699f15c062e42b3",
|
||||
|
||||
as_release: 15,
|
||||
ue_category: "nr",
|
||||
apn:"oai",
|
||||
attach_pdn_type:"ipv4",
|
||||
default_nssai: [ { sst: 1, }, ],
|
||||
default_pdu_session_snssai: { sst: 1, },
|
||||
tun_setup_script: "ue-ifup",
|
||||
},
|
||||
{
|
||||
"ue_id" : 2,
|
||||
"imsi": "001020000000002",
|
||||
"K": "fec86ba6eb707ed08905757b1bb44b8f",
|
||||
"sim_algo":"milenage",
|
||||
"op": "1006020f0a478bf6b699f15c062e42b3",
|
||||
|
||||
as_release: 15,
|
||||
ue_category: "nr",
|
||||
apn:"oai",
|
||||
attach_pdn_type:"ipv4",
|
||||
default_nssai: [ { sst: 1, }, ],
|
||||
default_pdu_session_snssai: { sst: 1, },
|
||||
tun_setup_script: "ue-ifup",
|
||||
},
|
||||
{
|
||||
"ue_id" : 3,
|
||||
"imsi": "001020000000003",
|
||||
"K": "fec86ba6eb707ed08905757b1bb44b8f",
|
||||
"sim_algo":"milenage",
|
||||
"op": "1006020f0a478bf6b699f15c062e42b3",
|
||||
|
||||
as_release: 15,
|
||||
ue_category: "nr",
|
||||
apn:"oai",
|
||||
attach_pdn_type:"ipv4",
|
||||
default_nssai: [ { sst: 1, }, ],
|
||||
default_pdu_session_snssai: { sst: 1, },
|
||||
tun_setup_script: "ue-ifup",
|
||||
},
|
||||
{
|
||||
"ue_id" : 4,
|
||||
"imsi": "001020000000004",
|
||||
"K": "fec86ba6eb707ed08905757b1bb44b8f",
|
||||
"sim_algo":"milenage",
|
||||
"op": "1006020f0a478bf6b699f15c062e42b3",
|
||||
|
||||
as_release: 15,
|
||||
ue_category: "nr",
|
||||
apn:"oai",
|
||||
attach_pdn_type:"ipv4",
|
||||
default_nssai: [ { sst: 1, }, ],
|
||||
default_pdu_session_snssai: { sst: 1, },
|
||||
tun_setup_script: "ue-ifup",
|
||||
},
|
||||
{
|
||||
"ue_id" : 5,
|
||||
"imsi": "001020000000005",
|
||||
"K": "fec86ba6eb707ed08905757b1bb44b8f",
|
||||
"sim_algo":"milenage",
|
||||
"op": "1006020f0a478bf6b699f15c062e42b3",
|
||||
|
||||
as_release: 15,
|
||||
ue_category: "nr",
|
||||
apn:"oai",
|
||||
attach_pdn_type:"ipv4",
|
||||
default_nssai: [ { sst: 1, }, ],
|
||||
default_pdu_session_snssai: { sst: 1, },
|
||||
tun_setup_script: "ue-ifup",
|
||||
},
|
||||
{
|
||||
"ue_id" : 6,
|
||||
"imsi": "001020000000006",
|
||||
"K": "fec86ba6eb707ed08905757b1bb44b8f",
|
||||
"sim_algo":"milenage",
|
||||
"op": "1006020f0a478bf6b699f15c062e42b3",
|
||||
|
||||
as_release: 15,
|
||||
ue_category: "nr",
|
||||
apn:"oai",
|
||||
attach_pdn_type:"ipv4",
|
||||
default_nssai: [ { sst: 1, }, ],
|
||||
default_pdu_session_snssai: { sst: 1, },
|
||||
tun_setup_script: "ue-ifup",
|
||||
},
|
||||
{
|
||||
"ue_id" : 7,
|
||||
"imsi": "001020000000007",
|
||||
"K": "fec86ba6eb707ed08905757b1bb44b8f",
|
||||
"sim_algo":"milenage",
|
||||
"op": "1006020f0a478bf6b699f15c062e42b3",
|
||||
|
||||
as_release: 15,
|
||||
ue_category: "nr",
|
||||
apn:"oai",
|
||||
attach_pdn_type:"ipv4",
|
||||
default_nssai: [ { sst: 1, }, ],
|
||||
default_pdu_session_snssai: { sst: 1, },
|
||||
tun_setup_script: "ue-ifup",
|
||||
},
|
||||
{
|
||||
"ue_id" : 8,
|
||||
"imsi": "001020000000008",
|
||||
"K": "fec86ba6eb707ed08905757b1bb44b8f",
|
||||
"sim_algo":"milenage",
|
||||
"op": "1006020f0a478bf6b699f15c062e42b3",
|
||||
|
||||
as_release: 15,
|
||||
ue_category: "nr",
|
||||
apn:"oai",
|
||||
attach_pdn_type:"ipv4",
|
||||
default_nssai: [ { sst: 1, }, ],
|
||||
default_pdu_session_snssai: { sst: 1, },
|
||||
tun_setup_script: "ue-ifup",
|
||||
},
|
||||
{
|
||||
"ue_id" : 9,
|
||||
"imsi": "001020000000009",
|
||||
"K": "fec86ba6eb707ed08905757b1bb44b8f",
|
||||
"sim_algo":"milenage",
|
||||
"op": "1006020f0a478bf6b699f15c062e42b3",
|
||||
|
||||
as_release: 15,
|
||||
ue_category: "nr",
|
||||
apn:"oai",
|
||||
attach_pdn_type:"ipv4",
|
||||
default_nssai: [ { sst: 1, }, ],
|
||||
default_pdu_session_snssai: { sst: 1, },
|
||||
tun_setup_script: "ue-ifup",
|
||||
},
|
||||
{
|
||||
"ue_id" : 10,
|
||||
"imsi": "001020000000010",
|
||||
"K": "fec86ba6eb707ed08905757b1bb44b8f",
|
||||
"sim_algo":"milenage",
|
||||
"op": "1006020f0a478bf6b699f15c062e42b3",
|
||||
|
||||
as_release: 15,
|
||||
ue_category: "nr",
|
||||
apn:"oai",
|
||||
attach_pdn_type:"ipv4",
|
||||
default_nssai: [ { sst: 1, }, ],
|
||||
default_pdu_session_snssai: { sst: 1, },
|
||||
tun_setup_script: "ue-ifup",
|
||||
},
|
||||
{
|
||||
"ue_id" : 11,
|
||||
"imsi": "001020000000011",
|
||||
"K": "fec86ba6eb707ed08905757b1bb44b8f",
|
||||
"sim_algo":"milenage",
|
||||
"op": "1006020f0a478bf6b699f15c062e42b3",
|
||||
|
||||
as_release: 15,
|
||||
ue_category: "nr",
|
||||
apn:"oai",
|
||||
attach_pdn_type:"ipv4",
|
||||
default_nssai: [ { sst: 1, }, ],
|
||||
default_pdu_session_snssai: { sst: 1, },
|
||||
tun_setup_script: "ue-ifup",
|
||||
},
|
||||
{
|
||||
"ue_id" : 12,
|
||||
"imsi": "001020000000012",
|
||||
"K": "fec86ba6eb707ed08905757b1bb44b8f",
|
||||
"sim_algo":"milenage",
|
||||
"op": "1006020f0a478bf6b699f15c062e42b3",
|
||||
|
||||
as_release: 15,
|
||||
ue_category: "nr",
|
||||
apn:"oai",
|
||||
attach_pdn_type:"ipv4",
|
||||
default_nssai: [ { sst: 1, }, ],
|
||||
default_pdu_session_snssai: { sst: 1, },
|
||||
tun_setup_script: "ue-ifup",
|
||||
},
|
||||
{
|
||||
"ue_id" : 13,
|
||||
"imsi": "001020000000013",
|
||||
"K": "fec86ba6eb707ed08905757b1bb44b8f",
|
||||
"sim_algo":"milenage",
|
||||
"op": "1006020f0a478bf6b699f15c062e42b3",
|
||||
|
||||
as_release: 15,
|
||||
ue_category: "nr",
|
||||
apn:"oai",
|
||||
attach_pdn_type:"ipv4",
|
||||
default_nssai: [ { sst: 1, }, ],
|
||||
default_pdu_session_snssai: { sst: 1, },
|
||||
tun_setup_script: "ue-ifup",
|
||||
},
|
||||
{
|
||||
"ue_id" : 14,
|
||||
"imsi": "001020000000014",
|
||||
"K": "fec86ba6eb707ed08905757b1bb44b8f",
|
||||
"sim_algo":"milenage",
|
||||
"op": "1006020f0a478bf6b699f15c062e42b3",
|
||||
|
||||
as_release: 15,
|
||||
ue_category: "nr",
|
||||
apn:"oai",
|
||||
attach_pdn_type:"ipv4",
|
||||
default_nssai: [ { sst: 1, }, ],
|
||||
default_pdu_session_snssai: { sst: 1, },
|
||||
tun_setup_script: "ue-ifup",
|
||||
},
|
||||
{
|
||||
"ue_id" : 15,
|
||||
"imsi": "001020000000015",
|
||||
"K": "fec86ba6eb707ed08905757b1bb44b8f",
|
||||
"sim_algo":"milenage",
|
||||
"op": "1006020f0a478bf6b699f15c062e42b3",
|
||||
|
||||
as_release: 15,
|
||||
ue_category: "nr",
|
||||
apn:"oai",
|
||||
attach_pdn_type:"ipv4",
|
||||
default_nssai: [ { sst: 1, }, ],
|
||||
default_pdu_session_snssai: { sst: 1, },
|
||||
tun_setup_script: "ue-ifup",
|
||||
},
|
||||
{
|
||||
"ue_id" : 16,
|
||||
"imsi": "001020000000016",
|
||||
"K": "fec86ba6eb707ed08905757b1bb44b8f",
|
||||
"sim_algo":"milenage",
|
||||
"op": "1006020f0a478bf6b699f15c062e42b3",
|
||||
|
||||
as_release: 15,
|
||||
ue_category: "nr",
|
||||
apn:"oai",
|
||||
attach_pdn_type:"ipv4",
|
||||
default_nssai: [ { sst: 1, }, ],
|
||||
default_pdu_session_snssai: { sst: 1, },
|
||||
tun_setup_script: "ue-ifup",
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -5,7 +5,6 @@
|
||||
{
|
||||
#define N_ANTENNA_DL 2
|
||||
#define N_ANTENNA_UL 2
|
||||
#define DL_ARFCN 631296
|
||||
#define TDD 1
|
||||
|
||||
log_options: "all.level=warn,all.max_size=0,nas.level=debug,nas.max_size=1,rrc.level=debug,rrc.max_size=1",
|
||||
@@ -26,8 +25,8 @@ allow dynamic UE creation from remote API */
|
||||
rf_port: 0,
|
||||
bandwidth: 20,
|
||||
band: 78,
|
||||
dl_nr_arfcn: DL_ARFCN,
|
||||
ssb_nr_arfcn: DL_ARFCN,
|
||||
dl_nr_arfcn:630048,
|
||||
ssb_nr_arfcn:630048,
|
||||
subcarrier_spacing: 30,
|
||||
n_antenna_dl: N_ANTENNA_DL,
|
||||
n_antenna_ul: N_ANTENNA_UL,
|
||||
79
ci-scripts/build_fr1_from_yaml.py
Executable file
79
ci-scripts/build_fr1_from_yaml.py
Executable file
@@ -0,0 +1,79 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Tue Jul 7 23:04:51 2020
|
||||
|
||||
@author: hardy
|
||||
"""
|
||||
|
||||
|
||||
|
||||
import yaml
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
f_yaml=sys.argv[1]
|
||||
f_sh=sys.argv[2]
|
||||
#filename='py_params_template.yaml'
|
||||
with open(f_yaml,'r') as file:
|
||||
# The FullLoader parameter handles the conversion from YAML
|
||||
# scalar values to Python the dictionary format
|
||||
print('Loading '+f_yaml)
|
||||
params = yaml.load(file,Loader=yaml.FullLoader)
|
||||
|
||||
|
||||
with open(f_sh,'w') as f:
|
||||
f.write('#!/bin/sh\n')
|
||||
for i in range (0, len(params['steps'])):
|
||||
step=params['steps'][i].split(',')
|
||||
mode=step[0]
|
||||
f_xml=step[1]
|
||||
line='python3 main.py ' + \
|
||||
'--mode='+ mode + ' ' + \
|
||||
'--ranRepository=' + params['ranRepository'] + ' ' + \
|
||||
'--ranBranch=' + params['ranBranch'] + ' ' + \
|
||||
'--ranCommitID=' + params['ranCommitID'] + ' ' + \
|
||||
'--ranAllowMerge=' + params['ranAllowMerge'] + ' ' + \
|
||||
'--ranTargetBranch=' + params['ranTargetBranch'] + ' ' + \
|
||||
\
|
||||
'--UEIPAddress=' + params['UE']['UEIPAddress'] + ' ' + \
|
||||
'--UEUserName=' + params['UE']['UEUserName'] + ' ' + \
|
||||
'--UEPassword=' + params['UE']['UEPassword'] + ' ' + \
|
||||
'--UESourceCodePath=' + params['UE']['UESourceCodePath'] + ' ' + \
|
||||
\
|
||||
'--EPCIPAddress=' + params['EPC']['EPCIPAddress'] + ' ' + \
|
||||
'--EPCUserName=' + params['EPC']['EPCUserName'] + ' ' + \
|
||||
'--EPCPassword=' + params['EPC']['EPCPassword'] + ' ' + \
|
||||
'--EPCSourceCodePath=' + params['EPC']['EPCSourceCodePath'] + ' ' + \
|
||||
'--EPCType=' + params['EPC']['EPCType'] + ' ' + \
|
||||
\
|
||||
'--eNBIPAddress=' + params['RAN'][0]['eNBIPAddress'] + ' ' + \
|
||||
'--eNBUserName=' + params['RAN'][0]['eNBUserName'] + ' ' + \
|
||||
'--eNBPassword=' + params['RAN'][0]['eNBPassword'] + ' ' + \
|
||||
'--eNBSourceCodePath=' + params['RAN'][0]['eNBSourceCodePath'] + ' ' + \
|
||||
\
|
||||
'--eNB1IPAddress=' + params['RAN'][1]['eNB1IPAddress'] + ' ' + \
|
||||
'--eNB1UserName=' + params['RAN'][1]['eNB1UserName'] + ' ' + \
|
||||
'--eNB1Password=' + params['RAN'][1]['eNB1Password'] + ' ' + \
|
||||
'--eNB1SourceCodePath=' + params['RAN'][1]['eNB1SourceCodePath'] + ' '
|
||||
if mode!="InitiateHtml":
|
||||
line+='--XMLTestFile=' + f_xml
|
||||
#if mode is InitiateHTML we have a special processing to mention all xml files from the list
|
||||
#loop starting at 1 to avoid the xml file mentioned with InitiateHtml in yaml file (file is none)
|
||||
else:
|
||||
for i in range (1, len(params['steps'])):
|
||||
step=params['steps'][i].split(',')
|
||||
f_xml=step[1]
|
||||
line+='--XMLTestFile=' + f_xml+' '
|
||||
line+='\n'
|
||||
print(line)
|
||||
f.write(line)
|
||||
subprocess.call(['chmod','777',f_sh])
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
|
||||
40
ci-scripts/build_fr1_template.yaml
Executable file
40
ci-scripts/build_fr1_template.yaml
Executable file
@@ -0,0 +1,40 @@
|
||||
|
||||
ranRepository : https://gitlab.eurecom.fr/oai/openairinterface5g.git
|
||||
ranBranch : integration_2021_wk13_a
|
||||
ranCommitID : 104aa7eed5d6702c1b9da663414079ef698da206
|
||||
ranAllowMerge : 'yes'
|
||||
ranTargetBranch : develop
|
||||
|
||||
steps:
|
||||
- InitiateHtml,none
|
||||
- TesteNB,xml_files/fr1_multi_node_build.xml
|
||||
- TesteNB,xml_files/fr1_epc_start.xml
|
||||
- TesteNB,xml_files/fr1_nsa_base_next.xml #ue toggle, nodes initialize, ue toggle, ping, nodes terminate
|
||||
- TesteNB,xml_files/fr1_epc_closure.xml
|
||||
|
||||
RAN:
|
||||
- eNBIPAddress : 192.168.18.199 #eNB on Minimassive
|
||||
eNBUserName : oaicicd
|
||||
eNBPassword : HzB*nkryaITdVd08TKlT#2Z5a!7M#~qn
|
||||
eNBSourceCodePath : /tmp/CI-FR1-eNB
|
||||
- eNB1IPAddress : 192.168.18.198 #gNB on Mozart
|
||||
eNB1UserName : oaicicd
|
||||
eNB1Password : 7zkDOFgh@w3HvRBMPTMh@BAx
|
||||
eNB1SourceCodePath : /tmp/CI-FR1-gNB
|
||||
|
||||
|
||||
EPC: #on Nikaia
|
||||
EPCIPAddress : 192.168.18.99
|
||||
EPCUserName : nikaia
|
||||
EPCPassword : linux
|
||||
EPCSourceCodePath : /tmp/CI-FR1-EPC
|
||||
EPCType : ltebox
|
||||
|
||||
|
||||
UE:
|
||||
UEIPAddress : none
|
||||
UEUserName : none
|
||||
UEPassword : none
|
||||
UESourceCodePath : none
|
||||
|
||||
|
||||
@@ -106,11 +106,11 @@ echo "Merged Commit is : $MERGE_COMMMIT"
|
||||
echo "Target Init is : $TARGET_INIT_COMMIT"
|
||||
|
||||
# Retrieve the list of modified files since the latest develop commit
|
||||
MODIFIED_FILES=`git log $TARGET_INIT_COMMIT..$MERGE_COMMMIT --oneline --name-status | grep -E "^M|^A" | sed -e "s@^M\t*@@" -e "s@^A\t*@@" | sort | uniq`
|
||||
MODIFIED_FILES=`git log $TARGET_INIT_COMMIT..$MERGE_COMMMIT --oneline --name-status | egrep "^M|^A" | sed -e "s@^M\t*@@" -e "s@^A\t*@@" | sort | uniq`
|
||||
NB_WARNINGS_FILES=0
|
||||
|
||||
# Retrieve list of warnings
|
||||
LIST_WARNING_FILES=`grep -E "error:|warning:" archives/*/*.txt | grep -E -v "jobserver unavailable|Clock skew detected." | sed -e "s#^.*/home/ubuntu/tmp/##" -e "s#^.*/tmp/CI-eNB/##" -e "s#common/utils/.*/itti#common/utils/itti#" | awk -F ":" '{print $1}' | sort | uniq`
|
||||
LIST_WARNING_FILES=`egrep "error:|warning:" archives/*/*.txt | egrep -v "jobserver unavailable|Clock skew detected." | sed -e "s#^.*/home/ubuntu/tmp/##" -e "s#^.*/tmp/CI-eNB/##" -e "s#common/utils/.*/itti#common/utils/itti#" | awk -F ":" '{print $1}' | sort | uniq`
|
||||
|
||||
echo ""
|
||||
echo "List of files that have been modified by the Merge Request AND"
|
||||
|
||||
@@ -64,18 +64,18 @@ then
|
||||
awk '/#[ \t]*ifndef/ { gsub("^.*ifndef *",""); if (names[$1]!="") print "files with same {define ", FILENAME, names[$1]; names[$1]=FILENAME } /#[ \t]*define/ { gsub("^.*define *",""); if(names[$1]!=FILENAME) print "error in declaration", FILENAME, $1, names[$1]; nextfile }' `find openair* common targets executables -name *.h |grep -v LFDS` > header-files-w-incorrect-define.txt
|
||||
|
||||
# Testing if explicit GNU GPL license banner
|
||||
grep -E -irl --exclude-dir=.git --include=*.cpp --include=*.c --include=*.h "General Public License" . | grep -E -v "openair3/NAS/COMMON/milenage.h" > files-w-gnu-gpl-license-banner.txt
|
||||
egrep -irl --exclude-dir=.git --include=*.cpp --include=*.c --include=*.h "General Public License" . | egrep -v "openair3/NAS/COMMON/milenage.h" > files-w-gnu-gpl-license-banner.txt
|
||||
|
||||
# Looking at exotic/suspect banner
|
||||
LIST_OF_FILES_W_BANNER=`grep -E -irl --exclude-dir=.git --include=*.cpp --include=*.c --include=*.h "Copyright|copyleft" .`
|
||||
LIST_OF_FILES_W_BANNER=`egrep -irl --exclude-dir=.git --include=*.cpp --include=*.c --include=*.h "Copyright|copyleft" .`
|
||||
if [ -f ./files-w-suspect-banner.txt ]; then rm -f ./files-w-suspect-banner.txt; fi
|
||||
for FILE in $LIST_OF_FILES_W_BANNER
|
||||
do
|
||||
IS_NFAPI=`echo $FILE | grep -E -c "nfapi/open-nFAPI|nfapi/oai_integration/vendor_ext" || true`
|
||||
IS_OAI_LICENCE_PRESENT=`grep -E -c "OAI Public License" $FILE || true`
|
||||
IS_BSD_LICENCE_PRESENT=`grep -E -c "the terms of the BSD Licence|License-Identifier: BSD-2-Clause" $FILE || true`
|
||||
IS_MIT_LICENCE_PRESENT=`grep -E -c "MIT License" $FILE || true`
|
||||
IS_EXCEPTION=`echo $FILE | grep -E -c "common/utils/collection/tree.h|common/utils/collection/queue.h|openair2/UTIL/OPT/packet-rohc.h|openair3/NAS/COMMON/milenage.h|openair1/PHY/CODING/crc.h|openair1/PHY/CODING/crcext.h|openair1/PHY/CODING/types.h|openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c|openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_offload.h" || true`
|
||||
IS_NFAPI=`echo $FILE | egrep -c "nfapi/open-nFAPI|nfapi/oai_integration/vendor_ext" || true`
|
||||
IS_OAI_LICENCE_PRESENT=`egrep -c "OAI Public License" $FILE || true`
|
||||
IS_BSD_LICENCE_PRESENT=`egrep -c "the terms of the BSD Licence|License-Identifier: BSD-2-Clause" $FILE || true`
|
||||
IS_MIT_LICENCE_PRESENT=`egrep -c "MIT License" $FILE || true`
|
||||
IS_EXCEPTION=`echo $FILE | egrep -c "common/utils/collection/tree.h|common/utils/collection/queue.h|openair2/UTIL/OPT/packet-rohc.h|openair3/NAS/COMMON/milenage.h|openair1/PHY/CODING/crc.h|openair1/PHY/CODING/crcext.h|openair1/PHY/CODING/types.h|openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c|openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_offload.h" || true`
|
||||
if [ $IS_OAI_LICENCE_PRESENT -eq 0 ] && [ $IS_BSD_LICENCE_PRESENT -eq 0 ] && [ $IS_MIT_LICENCE_PRESENT -eq 0 ]
|
||||
then
|
||||
if [ $IS_NFAPI -eq 0 ] && [ $IS_EXCEPTION -eq 0 ]
|
||||
@@ -147,7 +147,7 @@ echo " ----------------------------------------------------------"
|
||||
echo ""
|
||||
|
||||
# Retrieve the list of modified files since the latest develop commit
|
||||
MODIFIED_FILES=`git log $TARGET_INIT_COMMIT..$MERGE_COMMMIT --oneline --name-status | grep -E "^M|^A" | sed -e "s@^M\t*@@" -e "s@^A\t*@@" | sort | uniq`
|
||||
MODIFIED_FILES=`git log $TARGET_INIT_COMMIT..$MERGE_COMMMIT --oneline --name-status | egrep "^M|^A" | sed -e "s@^M\t*@@" -e "s@^A\t*@@" | sort | uniq`
|
||||
NB_TO_FORMAT=0
|
||||
if [ -f header-files-w-incorrect-define.txt ]
|
||||
then
|
||||
@@ -173,20 +173,20 @@ do
|
||||
if [ $EXT = "c" ] || [ $EXT = "h" ] || [ $EXT = "cpp" ] || [ $EXT = "hpp" ]
|
||||
then
|
||||
# Testing if explicit GNU GPL license banner
|
||||
GNU_EXCEPTION=`echo $FULLFILE | grep -E -c "openair3/NAS/COMMON/milenage.h" || true`
|
||||
GNU_EXCEPTION=`echo $FULLFILE | egrep -c "openair3/NAS/COMMON/milenage.h" || true`
|
||||
if [ $GNU_EXCEPTION -eq 0 ]
|
||||
then
|
||||
grep -E -il "General Public License" $FULLFILE >> files-w-gnu-gpl-license-banner.txt
|
||||
egrep -il "General Public License" $FULLFILE >> files-w-gnu-gpl-license-banner.txt
|
||||
fi
|
||||
# Looking at exotic/suspect banner
|
||||
IS_BANNER=`grep -E -i -c "Copyright|copyleft" $FULLFILE || true`
|
||||
IS_BANNER=`egrep -i -c "Copyright|copyleft" $FULLFILE || true`
|
||||
if [ $IS_BANNER -ne 0 ]
|
||||
then
|
||||
IS_NFAPI=`echo $FULLFILE | grep -E -c "nfapi/open-nFAPI|nfapi/oai_integration/vendor_ext" || true`
|
||||
IS_OAI_LICENCE_PRESENT=`grep -E -c "OAI Public License" $FULLFILE || true`
|
||||
IS_BSD_LICENCE_PRESENT=`grep -E -c "the terms of the BSD Licence|License-Identifier: BSD-2-Clause" $FULLFILE || true`
|
||||
IS_MIT_LICENCE_PRESENT=`grep -E -c "MIT License" $FULLFILE || true`
|
||||
IS_EXCEPTION=`echo $FULLFILE | grep -E -c "common/utils/collection/tree.h|common/utils/collection/queue.h|openair2/UTIL/OPT/packet-rohc.h|openair3/NAS/COMMON/milenage.h|openair1/PHY/CODING/crc.h|openair1/PHY/CODING/crcext.h|openair1/PHY/CODING/types.h|openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c|openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_offload.h" || true`
|
||||
IS_NFAPI=`echo $FULLFILE | egrep -c "nfapi/open-nFAPI|nfapi/oai_integration/vendor_ext" || true`
|
||||
IS_OAI_LICENCE_PRESENT=`egrep -c "OAI Public License" $FULLFILE || true`
|
||||
IS_BSD_LICENCE_PRESENT=`egrep -c "the terms of the BSD Licence|License-Identifier: BSD-2-Clause" $FULLFILE || true`
|
||||
IS_MIT_LICENCE_PRESENT=`egrep -c "MIT License" $FULLFILE || true`
|
||||
IS_EXCEPTION=`echo $FULLFILE | egrep -c "common/utils/collection/tree.h|common/utils/collection/queue.h|openair2/UTIL/OPT/packet-rohc.h|openair3/NAS/COMMON/milenage.h|openair1/PHY/CODING/crc.h|openair1/PHY/CODING/crcext.h|openair1/PHY/CODING/types.h|openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c|openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_offload.h" || true`
|
||||
if [ $IS_OAI_LICENCE_PRESENT -eq 0 ] && [ $IS_BSD_LICENCE_PRESENT -eq 0 ] && [ $IS_MIT_LICENCE_PRESENT -eq 0 ]
|
||||
then
|
||||
if [ $IS_NFAPI -eq 0 ] && [ $IS_EXCEPTION -eq 0 ]
|
||||
|
||||
@@ -26,13 +26,16 @@ up2-fhi72:
|
||||
IF: wwan0
|
||||
MTU: 1500
|
||||
|
||||
up2-aerial:
|
||||
Host: up2
|
||||
AttachScript: sudo /opt/mbim-aerial/start_quectel_mbim.sh
|
||||
DetachScript: sudo /opt/mbim-aerial/stop_quectel_mbim.sh
|
||||
sphex_quectel:
|
||||
Host: sphex
|
||||
InitScript: sudo stdbuf -oL /home/oaicicd/quectel-CM/quectel-CM -4 -s oai.ipv4 &> /tmp/quecel-cm.log &
|
||||
TermScript: sudo -S killall --signal SIGKILL quectel-CM
|
||||
AttachScript: sudo python3 ci_ctl_qtel.py /dev/ttyUSB3 wup
|
||||
DetachScript: sudo python3 ci_ctl_qtel.py /dev/ttyUSB3 detach
|
||||
NetworkScript: ip a show dev wwan0
|
||||
IF: wwan0
|
||||
MTU: 1500
|
||||
LogStore: /media/ci_qlogs
|
||||
|
||||
adb_ue_1:
|
||||
Host: nano
|
||||
@@ -111,11 +114,7 @@ ltebox-nepes:
|
||||
|
||||
amarisoft_ue:
|
||||
Host: amariue
|
||||
InitScript: /root/lteue-linux-2023-10-27/ue/lteue /root/oaicicd/ran_sa_aw2s_asue/aw2s-multi-00102-20.cfg &
|
||||
TermScript: /root/2023-10-27/libs/ws.js -t 10 127.0.0.1:9002 '{"message":"quit"}' || killall -KILL lteue-avx2
|
||||
amarisoft_ue_2x2:
|
||||
Host: amariue
|
||||
InitScript: /root/lteue-linux-2023-10-27/ue/lteue /root/oaicicd/ran_sa_aw2s_asue_2x2/aw2s-multi-00102-2x2-v2.cfg &
|
||||
InitScript: /root/lteue-linux-2023-10-27/ue/lteue /root/oaicicd/ran_sa_aw2s_asue_2x2/aw2s-multi-00102-2x2.cfg &
|
||||
TermScript: /root/2023-10-27/libs/ws.js -t 10 127.0.0.1:9002 '{"message":"quit"}' || killall -KILL lteue-avx2
|
||||
amarisoft_ue_fhi72:
|
||||
Host: amariue
|
||||
@@ -250,13 +249,13 @@ lte_oai_ue_carabe:
|
||||
MTU: 1500
|
||||
|
||||
rfsim5g_gnb_nos1:
|
||||
Host: "%%current_host%%"
|
||||
Host: localhost
|
||||
NetworkScript: docker exec rfsim5g-oai-gnb ip a show dev oaitun_enb1
|
||||
CmdPrefix: docker exec rfsim5g-oai-gnb
|
||||
IF: oaitun_enb1
|
||||
|
||||
rfsim5g_ue:
|
||||
Host: "%%current_host%%"
|
||||
Host: localhost
|
||||
NetworkScript: docker exec rfsim5g-oai-nr-ue ip a show dev oaitun_ue1
|
||||
CmdPrefix: docker exec rfsim5g-oai-nr-ue
|
||||
IF: oaitun_ue1
|
||||
@@ -265,7 +264,7 @@ rfsim5g_ue:
|
||||
MTU: 1500
|
||||
|
||||
rfsim5g_ue2:
|
||||
Host: "%%current_host%%"
|
||||
Host: localhost
|
||||
NetworkScript: docker exec rfsim5g-oai-nr-ue2 ip a show dev oaitun_ue1
|
||||
CmdPrefix: docker exec rfsim5g-oai-nr-ue2
|
||||
IF: oaitun_ue1
|
||||
@@ -274,7 +273,7 @@ rfsim5g_ue2:
|
||||
MTU: 1500
|
||||
|
||||
rfsim5g_ue3:
|
||||
Host: "%%current_host%%"
|
||||
Host: localhost
|
||||
NetworkScript: docker exec rfsim5g-oai-nr-ue3 ip a show dev oaitun_ue1
|
||||
CmdPrefix: docker exec rfsim5g-oai-nr-ue3
|
||||
IF: oaitun_ue1
|
||||
@@ -283,7 +282,7 @@ rfsim5g_ue3:
|
||||
MTU: 1500
|
||||
|
||||
rfsim5g_ue4:
|
||||
Host: "%%current_host%%"
|
||||
Host: localhost
|
||||
NetworkScript: docker exec rfsim5g-oai-nr-ue4 ip a show dev oaitun_ue1
|
||||
CmdPrefix: docker exec rfsim5g-oai-nr-ue4
|
||||
IF: oaitun_ue1
|
||||
@@ -292,7 +291,7 @@ rfsim5g_ue4:
|
||||
MTU: 1500
|
||||
|
||||
rfsim5g_ue5:
|
||||
Host: "%%current_host%%"
|
||||
Host: localhost
|
||||
NetworkScript: docker exec rfsim5g-oai-nr-ue5 ip a show dev oaitun_ue1
|
||||
CmdPrefix: docker exec rfsim5g-oai-nr-ue5
|
||||
IF: oaitun_ue1
|
||||
@@ -301,7 +300,7 @@ rfsim5g_ue5:
|
||||
MTU: 1500
|
||||
|
||||
rfsim5g_ue6:
|
||||
Host: "%%current_host%%"
|
||||
Host: localhost
|
||||
NetworkScript: docker exec rfsim5g-oai-nr-ue6 ip a show dev oaitun_ue1
|
||||
CmdPrefix: docker exec rfsim5g-oai-nr-ue6
|
||||
IF: oaitun_ue1
|
||||
@@ -310,7 +309,7 @@ rfsim5g_ue6:
|
||||
MTU: 1500
|
||||
|
||||
rfsim5g_ue7:
|
||||
Host: "%%current_host%%"
|
||||
Host: localhost
|
||||
NetworkScript: docker exec rfsim5g-oai-nr-ue7 ip a show dev oaitun_ue1
|
||||
CmdPrefix: docker exec rfsim5g-oai-nr-ue7
|
||||
IF: oaitun_ue1
|
||||
@@ -319,7 +318,7 @@ rfsim5g_ue7:
|
||||
MTU: 1500
|
||||
|
||||
rfsim5g_ue8:
|
||||
Host: "%%current_host%%"
|
||||
Host: localhost
|
||||
NetworkScript: docker exec rfsim5g-oai-nr-ue8 ip a show dev oaitun_ue1
|
||||
CmdPrefix: docker exec rfsim5g-oai-nr-ue8
|
||||
IF: oaitun_ue1
|
||||
@@ -328,7 +327,7 @@ rfsim5g_ue8:
|
||||
MTU: 1500
|
||||
|
||||
rfsim5g_ue9:
|
||||
Host: "%%current_host%%"
|
||||
Host: localhost
|
||||
NetworkScript: docker exec rfsim5g-oai-nr-ue9 ip a show dev oaitun_ue1
|
||||
CmdPrefix: docker exec rfsim5g-oai-nr-ue9
|
||||
IF: oaitun_ue1
|
||||
@@ -337,7 +336,7 @@ rfsim5g_ue9:
|
||||
MTU: 1500
|
||||
|
||||
rfsim5g_ue10:
|
||||
Host: "%%current_host%%"
|
||||
Host: localhost
|
||||
NetworkScript: docker exec rfsim5g-oai-nr-ue10 ip a show dev oaitun_ue1
|
||||
CmdPrefix: docker exec rfsim5g-oai-nr-ue10
|
||||
IF: oaitun_ue1
|
||||
@@ -346,12 +345,12 @@ rfsim5g_ue10:
|
||||
MTU: 1500
|
||||
|
||||
rfsim5g_ext_dn:
|
||||
Host: "%%current_host%%"
|
||||
Host: localhost
|
||||
NetworkScript: docker exec rfsim5g-oai-ext-dn ip a show dev eth0
|
||||
CmdPrefix: docker exec rfsim5g-oai-ext-dn
|
||||
|
||||
rfsim4g_ue:
|
||||
Host: "%%current_host%%"
|
||||
Host: localhost
|
||||
NetworkScript: docker exec rfsim4g-oai-lte-ue0 ip a show dev oaitun_ue1
|
||||
CmdPrefix: docker exec rfsim4g-oai-lte-ue0
|
||||
IF: oaitun_ue1
|
||||
@@ -360,30 +359,30 @@ rfsim4g_ue:
|
||||
MTU: 1500
|
||||
|
||||
rfsim4g_ext_dn:
|
||||
Host: "%%current_host%%"
|
||||
Host: localhost
|
||||
NetworkScript: docker exec rfsim4g-trf-gen ip a show dev eth0
|
||||
CmdPrefix: docker exec rfsim4g-trf-gen
|
||||
|
||||
rfsim4g_enb_nos1:
|
||||
Host: "%%current_host%%"
|
||||
Host: localhost
|
||||
NetworkScript: docker exec rfsim4g-oai-enb ip a show dev oaitun_enb1
|
||||
CmdPrefix: docker exec rfsim4g-oai-enb
|
||||
IF: oaitun_enb1
|
||||
|
||||
rfsim4g_enb_fembms:
|
||||
Host: "%%current_host%%"
|
||||
Host: localhost
|
||||
NetworkScript: docker exec rfsim4g-oai-enb ip a show dev oaitun_enm1
|
||||
CmdPrefix: docker exec rfsim4g-oai-enb
|
||||
IF: oaitun_enm1
|
||||
|
||||
rfsim4g_ue_fembms:
|
||||
Host: "%%current_host%%"
|
||||
Host: localhost
|
||||
NetworkScript: docker exec rfsim4g-oai-lte-ue0 ip a show dev oaitun_uem1
|
||||
CmdPrefix: docker exec rfsim4g-oai-lte-ue0
|
||||
IF: oaitun_uem1
|
||||
|
||||
l2sim5g_ue:
|
||||
Host: "%%current_host%%"
|
||||
Host: localhost
|
||||
AttachScript: docker start l2sim-oai-nr-ue0
|
||||
DetachScript: docker stop l2sim-oai-nr-ue0
|
||||
NetworkScript: docker exec l2sim-oai-nr-ue0 ip a show dev oaitun_ue1
|
||||
@@ -392,12 +391,12 @@ l2sim5g_ue:
|
||||
MTU: 1500
|
||||
|
||||
l2sim5g_ext_dn:
|
||||
Host: "%%current_host%%"
|
||||
Host: localhost
|
||||
NetworkScript: docker exec l2sim-oai-ext-dn ip a show dev eth0
|
||||
CmdPrefix: docker exec l2sim-oai-ext-dn
|
||||
|
||||
l2sim4g_ue:
|
||||
Host: "%%current_host%%"
|
||||
Host: localhost
|
||||
AttachScript: docker start l2sim4g-oai-lte-ue1
|
||||
DetachScript: docker stop l2sim4g-oai-lte-ue1
|
||||
NetworkScript: docker exec l2sim4g-oai-lte-ue1 ip a show dev oaitun_ue1
|
||||
@@ -406,10 +405,6 @@ l2sim4g_ue:
|
||||
MTU: 1500
|
||||
|
||||
l2sim4g_ext_dn:
|
||||
Host: "%%current_host%%"
|
||||
Host: localhost
|
||||
NetworkScript: docker exec l2sim4g-trf-gen ip a show dev eth0
|
||||
CmdPrefix: docker exec l2sim4g-trf-gen
|
||||
|
||||
test:
|
||||
Host: localhost
|
||||
NetworkScript: echo "inet 127.0.0.1 mtu 1500"
|
||||
|
||||
@@ -41,7 +41,7 @@ import cls_cmd
|
||||
IMAGE_REGISTRY_SERVICE_NAME = "image-registry.openshift-image-registry.svc"
|
||||
NAMESPACE = "oaicicd-ran"
|
||||
OCUrl = "https://api.oai.cs.eurecom.fr:6443"
|
||||
OCRegistry = "default-route-openshift-image-registry.apps.oai.cs.eurecom.fr"
|
||||
OCRegistry = "default-route-openshift-image-registry.apps.oai.cs.eurecom.fr/"
|
||||
CI_OC_RAN_NAMESPACE = "oaicicd-ran"
|
||||
CN_IMAGES = ["mysql", "oai-nrf", "oai-amf", "oai-smf", "oai-upf", "oai-ausf", "oai-udm", "oai-udr", "oai-traffic-server"]
|
||||
CN_CONTAINERS = ["", "-c nrf", "-c amf", "-c smf", "-c upf", "-c ausf", "-c udm", "-c udr", ""]
|
||||
@@ -50,9 +50,9 @@ CN_CONTAINERS = ["", "-c nrf", "-c amf", "-c smf", "-c upf", "-c ausf", "-c udm"
|
||||
def OC_login(cmd, ocUserName, ocPassword, ocProjectName):
|
||||
if ocUserName == '' or ocPassword == '' or ocProjectName == '':
|
||||
HELP.GenericHelp(CONST.Version)
|
||||
raise ValueError('Insufficient Parameter: no OC Credentials')
|
||||
if OCRegistry.startswith("http") or OCRegistry.endswith("/"):
|
||||
raise ValueError(f'ocRegistry {OCRegistry} should not start with http:// or https:// and not end on a slash /')
|
||||
sys.exit('Insufficient Parameter: no OC Credentials')
|
||||
if OCRegistry.startswith("http") and not self.OCRegistry.endswith("/"):
|
||||
sys.exit(f'ocRegistry {OCRegistry} should not start with http:// or https:// and end on a slash /')
|
||||
ret = cmd.run(f'oc login -u {ocUserName} -p {ocPassword} --server {OCUrl}')
|
||||
if ret.returncode != 0:
|
||||
logging.error('\u001B[1m OC Cluster Login Failed\u001B[0m')
|
||||
@@ -118,8 +118,8 @@ class Cluster:
|
||||
self.OCUserName = ""
|
||||
self.OCPassword = ""
|
||||
self.OCProjectName = ""
|
||||
self.OCUrl = OCUrl
|
||||
self.OCRegistry = OCRegistry
|
||||
self.OCUrl = "https://api.oai.cs.eurecom.fr:6443"
|
||||
self.OCRegistry = "default-route-openshift-image-registry.apps.oai.cs.eurecom.fr/"
|
||||
self.ranRepository = ""
|
||||
self.ranBranch = ""
|
||||
self.ranCommitID = ""
|
||||
@@ -244,11 +244,10 @@ class Cluster:
|
||||
if self.testSvrId == None: self.testSvrId = self.eNBIPAddress
|
||||
if self.imageToPull == '':
|
||||
HELP.GenericHelp(CONST.Version)
|
||||
raise ValueError('Insufficient Parameter')
|
||||
sys.exit('Insufficient Parameter')
|
||||
logging.debug(f'Pull OC image {self.imageToPull} to server {self.testSvrId}')
|
||||
self.testCase_id = HTML.testCase_id
|
||||
cmd = cls_cmd.getConnection(self.testSvrId)
|
||||
logging.info(cmd.run('docker --version'))
|
||||
succeeded = OC_login(cmd, self.OCUserName, self.OCPassword, CI_OC_RAN_NAMESPACE)
|
||||
if not succeeded:
|
||||
logging.error('\u001B[1m OC Cluster Login Failed\u001B[0m')
|
||||
@@ -262,9 +261,8 @@ class Cluster:
|
||||
HTML.CreateHtmlTestRow('N/A', 'KO', CONST.OC_LOGIN_FAIL)
|
||||
return False
|
||||
for image in self.imageToPull:
|
||||
imagePrefix = f'{self.OCRegistry}/{CI_OC_RAN_NAMESPACE}'
|
||||
tag = cls_containerize.CreateTag(self.ranCommitID, self.ranBranch, self.ranAllowMerge)
|
||||
imageTag = f"{image}:{tag}"
|
||||
imagePrefix = f'{self.OCRegistry}{CI_OC_RAN_NAMESPACE}'
|
||||
imageTag = cls_containerize.ImageTagToUse(image, self.ranCommitID, self.ranBranch, self.ranAllowMerge)
|
||||
ret = cmd.run(f'docker pull {imagePrefix}/{imageTag}')
|
||||
if ret.returncode != 0:
|
||||
logging.error(f'Could not pull {image} from local registry : {self.OCRegistry}')
|
||||
@@ -282,19 +280,19 @@ class Cluster:
|
||||
def BuildClusterImage(self, HTML):
|
||||
if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '':
|
||||
HELP.GenericHelp(CONST.Version)
|
||||
raise ValueError(f'Insufficient Parameter: ranRepository {self.ranRepository} ranBranch {ranBranch} ranCommitID {self.ranCommitID}')
|
||||
sys.exit(f'Insufficient Parameter: ranRepository {self.ranRepository} ranBranch {ranBranch} ranCommitID {self.ranCommitID}')
|
||||
lIpAddr = self.eNBIPAddress
|
||||
lSourcePath = self.eNBSourceCodePath
|
||||
if lIpAddr == '' or lSourcePath == '':
|
||||
raise ValueError('Insufficient Parameter: eNBSourceCodePath missing')
|
||||
sys.exit('Insufficient Parameter: eNBSourceCodePath missing')
|
||||
ocUserName = self.OCUserName
|
||||
ocPassword = self.OCPassword
|
||||
ocProjectName = self.OCProjectName
|
||||
if ocUserName == '' or ocPassword == '' or ocProjectName == '':
|
||||
HELP.GenericHelp(CONST.Version)
|
||||
raise ValueError('Insufficient Parameter: no OC Credentials')
|
||||
if self.OCRegistry.startswith("http") or self.OCRegistry.endswith("/"):
|
||||
raise ValueError(f'ocRegistry {self.OCRegistry} should not start with http:// or https:// and not end on a slash /')
|
||||
sys.exit('Insufficient Parameter: no OC Credentials')
|
||||
if self.OCRegistry.startswith("http") and not self.OCRegistry.endswith("/"):
|
||||
sys.exit(f'ocRegistry {self.OCRegistry} should not start with http:// or https:// and end on a slash /')
|
||||
|
||||
logging.debug(f'Building on cluster triggered from server: {lIpAddr}')
|
||||
self.cmd = cls_cmd.RemoteCmd(lIpAddr)
|
||||
@@ -302,7 +300,10 @@ class Cluster:
|
||||
self.testCase_id = HTML.testCase_id
|
||||
|
||||
# Workaround for some servers, we need to erase completely the workspace
|
||||
self.cmd.cd(lSourcePath)
|
||||
if self.forcedWorkspaceCleanup:
|
||||
self.cmd.run(f'rm -Rf {lSourcePath}')
|
||||
cls_containerize.CreateWorkspace(self.cmd, lSourcePath, self.ranRepository, self.ranCommitID, self.ranTargetBranch, self.ranAllowMerge)
|
||||
|
||||
# to reduce the amount of data send to OpenShift, we
|
||||
# manually delete all generated files in the workspace
|
||||
self.cmd.run(f'rm -rf {lSourcePath}/cmake_targets/ran_build');
|
||||
|
||||
@@ -31,26 +31,18 @@ import subprocess as sp
|
||||
import os
|
||||
import paramiko
|
||||
import uuid
|
||||
import sys
|
||||
import time
|
||||
|
||||
SSHTIMEOUT=7
|
||||
|
||||
def is_local(host):
|
||||
return host is None or host.lower() in ["", "none", "localhost"]
|
||||
|
||||
# helper that returns either LocalCmd or RemoteCmd based on passed host name
|
||||
def getConnection(host, d=None):
|
||||
if is_local(host):
|
||||
if host is None or host.lower() in ["", "none", "localhost"]:
|
||||
return LocalCmd(d=d)
|
||||
else:
|
||||
return RemoteCmd(host, d=d)
|
||||
|
||||
def runScript(host, path, timeout, parameters=None, redirect=None, silent=False):
|
||||
if is_local(host):
|
||||
return LocalCmd.exec_script(path, timeout, parameters, redirect, silent)
|
||||
else:
|
||||
return RemoteCmd.exec_script(host, path, timeout, parameters, redirect, silent)
|
||||
|
||||
# provides a partial interface for the legacy SSHconnection class (getBefore(), command())
|
||||
class Cmd(metaclass=abc.ABCMeta):
|
||||
def cd(self, d, silent=False):
|
||||
@@ -66,10 +58,6 @@ class Cmd(metaclass=abc.ABCMeta):
|
||||
if not silent:
|
||||
logging.debug(f'cd {self.cwd}')
|
||||
|
||||
@abc.abstractmethod
|
||||
def exec_script(path, timeout, parameters=None, redirect=None, silent=False):
|
||||
return
|
||||
|
||||
@abc.abstractmethod
|
||||
def run(self, line, timeout=300, silent=False):
|
||||
return
|
||||
@@ -111,33 +99,17 @@ class LocalCmd(Cmd):
|
||||
logging.debug(f'Working dir is {self.cwd}')
|
||||
self.cp = sp.CompletedProcess(args='', returncode=0, stdout='')
|
||||
|
||||
def exec_script(path, timeout, parameters=None, redirect=None, silent=False):
|
||||
if redirect and not redirect.startswith("/"):
|
||||
raise ValueError(f"redirect must be absolute, but is {redirect}")
|
||||
c = f"{path} {parameters}" if parameters else path
|
||||
if not redirect:
|
||||
ret = sp.run(c, shell=True, timeout=timeout, stdout=sp.PIPE, stderr=sp.STDOUT)
|
||||
ret.stdout = ret.stdout.decode('utf-8').strip()
|
||||
else:
|
||||
with open(redirect, "w") as f:
|
||||
ret = sp.run(c, shell=True, timeout=timeout, stdout=f, stderr=f)
|
||||
ret.args += f" &> {redirect}"
|
||||
ret.stdout = ""
|
||||
if not silent:
|
||||
logging.info(f"local> {ret.args}")
|
||||
return ret
|
||||
|
||||
def run(self, line, timeout=300, silent=False, reportNonZero=True):
|
||||
if not silent:
|
||||
logging.info(f"local> {line}")
|
||||
logging.info(line)
|
||||
try:
|
||||
if line.strip().endswith('&'):
|
||||
# if we wait for stdout, subprocess does not return before the end of the command
|
||||
# however, we don't want to wait for commands with &, so just return fake command
|
||||
ret = sp.run(line, shell=True, cwd=self.cwd, timeout=5, executable='/bin/bash')
|
||||
ret = sp.run(line, shell=True, cwd=self.cwd, timeout=5)
|
||||
time.sleep(0.1)
|
||||
else:
|
||||
ret = sp.run(line, shell=True, cwd=self.cwd, stdout=sp.PIPE, stderr=sp.STDOUT, timeout=timeout, executable='/bin/bash')
|
||||
ret = sp.run(line, shell=True, cwd=self.cwd, stdout=sp.PIPE, stderr=sp.STDOUT, timeout=timeout)
|
||||
except Exception as e:
|
||||
ret = sp.CompletedProcess(args=line, returncode=255, stdout=f'Exception: {str(e)}'.encode('utf-8'))
|
||||
if ret.stdout is None:
|
||||
@@ -156,9 +128,7 @@ class LocalCmd(Cmd):
|
||||
|
||||
def copyin(self, src, tgt, recursive=False):
|
||||
if src[0] != '/' or tgt[0] != '/':
|
||||
raise Exception(f'support only absolute file paths (src {src} tgt {tgt})!')
|
||||
if src == tgt:
|
||||
return # nothing to copy, file is already where it should go
|
||||
raise Exception('support only absolute file paths!')
|
||||
opt = '-r' if recursive else ''
|
||||
return self.run(f'cp {opt} {src} {tgt}').returncode == 0
|
||||
|
||||
@@ -196,8 +166,9 @@ class RemoteCmd(Cmd):
|
||||
|
||||
def __init__(self, hostname, d=None):
|
||||
cIdx = 0
|
||||
self.hostname = hostname
|
||||
self.client = RemoteCmd._ssh_init()
|
||||
logging.getLogger('paramiko').setLevel(logging.ERROR) # prevent spamming through Paramiko
|
||||
self.client = paramiko.SSHClient()
|
||||
self.client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
cfg = RemoteCmd._lookup_ssh_config(hostname)
|
||||
self.cwd = d
|
||||
self.cp = sp.CompletedProcess(args='', returncode=0, stdout='')
|
||||
@@ -210,12 +181,6 @@ class RemoteCmd(Cmd):
|
||||
cIdx +=1
|
||||
raise Exception ("Error: max retries, did not connect to host")
|
||||
|
||||
def _ssh_init():
|
||||
logging.getLogger('paramiko').setLevel(logging.ERROR) # prevent spamming through Paramiko
|
||||
client = paramiko.SSHClient()
|
||||
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
return client
|
||||
|
||||
def _lookup_ssh_config(hostname):
|
||||
ssh_config = paramiko.SSHConfig()
|
||||
user_config_file = os.path.expanduser("~/.ssh/config")
|
||||
@@ -236,33 +201,9 @@ class RemoteCmd(Cmd):
|
||||
cfg['sock'] = paramiko.ProxyCommand(ucfg['proxycommand'])
|
||||
return cfg
|
||||
|
||||
def exec_script(host, path, timeout, parameters=None, redirect=None, silent=False):
|
||||
if redirect and not redirect.startswith("/"):
|
||||
raise ValueError(f"redirect must be absolute, but is {redirect}")
|
||||
p = parameters if parameters else ""
|
||||
r = f"> {redirect}" if redirect else ""
|
||||
if not silent:
|
||||
logging.info(f"local> ssh {host} bash -s {p} < {path} {r} # {path} from localhost")
|
||||
client = RemoteCmd._ssh_init()
|
||||
cfg = RemoteCmd._lookup_ssh_config(host)
|
||||
client.connect(**cfg)
|
||||
bash_opt = 'BASH_XTRACEFD=1' # write bash set -x output to stdout, see bash(1)
|
||||
stdin, stdout, stderr = client.exec_command(f"{bash_opt} bash -s {p} {r}", timeout=timeout)
|
||||
# open() the file f at path, read() it and write() it into the stdin of the bash -s cmd
|
||||
with open(path) as f:
|
||||
stdin.write(f.read())
|
||||
stdin.close()
|
||||
cmd = path
|
||||
if parameters: cmd += f" {parameters}"
|
||||
if redirect: cmd += f" &> {redirect}"
|
||||
ret = sp.CompletedProcess(args=cmd, returncode=stdout.channel.recv_exit_status(), stdout=stdout.read(size=None) + stderr.read(size=None))
|
||||
ret.stdout = ret.stdout.decode('utf-8').strip()
|
||||
client.close()
|
||||
return ret
|
||||
|
||||
def run(self, line, timeout=300, silent=False, reportNonZero=True):
|
||||
if not silent:
|
||||
logging.info(f"ssh[{self.hostname}]> {line}")
|
||||
logging.info(line)
|
||||
if self.cwd:
|
||||
line = f"cd {self.cwd} && {line}"
|
||||
try:
|
||||
@@ -292,7 +233,7 @@ class RemoteCmd(Cmd):
|
||||
# if recursive is True, tgt must be a directory (and src is file or directory)
|
||||
# if recursive is False, tgt and src must be a file name
|
||||
def copyout(self, src, tgt, recursive=False):
|
||||
logging.debug(f"copyout: local:{src} -> {self.hostname}:{tgt}")
|
||||
logging.debug(f"copyout: local:{src} -> remote:{tgt}")
|
||||
if recursive:
|
||||
tmpfile = f"{uuid.uuid4()}.tar"
|
||||
abstmpfile = f"/tmp/{tmpfile}"
|
||||
@@ -310,7 +251,7 @@ class RemoteCmd(Cmd):
|
||||
# if recursive is True, tgt must be a directory (and src is file or directory)
|
||||
# if recursive is False, tgt and src must be a file name
|
||||
def copyin(self, src, tgt, recursive=False):
|
||||
logging.debug(f"copyin: {self.hostname}:{src} -> local:{tgt}")
|
||||
logging.debug(f"copyin: remote:{src} -> local:{tgt}")
|
||||
if recursive:
|
||||
tmpfile = f"{uuid.uuid4()}.tar"
|
||||
abstmpfile = f"/tmp/{tmpfile}"
|
||||
|
||||
@@ -36,12 +36,18 @@ import re # reg
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import time
|
||||
import pyshark
|
||||
import threading
|
||||
import cls_cmd
|
||||
from multiprocessing import Process, Lock, SimpleQueue
|
||||
from zipfile import ZipFile
|
||||
|
||||
#-----------------------------------------------------------
|
||||
# OAI Testing modules
|
||||
#-----------------------------------------------------------
|
||||
import cls_cluster as OC
|
||||
import cls_cmd
|
||||
import sshconnection as SSH
|
||||
import helpreadme as HELP
|
||||
@@ -52,25 +58,43 @@ import cls_oaicitest
|
||||
# Helper functions used here and in other classes
|
||||
# (e.g., cls_cluster.py)
|
||||
#-----------------------------------------------------------
|
||||
IMAGES = ['oai-enb', 'oai-lte-ru', 'oai-lte-ue', 'oai-gnb', 'oai-nr-cuup', 'oai-gnb-aw2s', 'oai-nr-ue', 'oai-enb-asan', 'oai-gnb-asan', 'oai-lte-ue-asan', 'oai-nr-ue-asan', 'oai-nr-cuup-asan', 'oai-gnb-aerial', 'oai-gnb-fhi72']
|
||||
IMAGES = ['oai-enb', 'oai-lte-ru', 'oai-lte-ue', 'oai-gnb', 'oai-nr-cuup', 'oai-gnb-aw2s', 'oai-nr-ue', 'oai-gnb-asan', 'oai-nr-ue-asan', 'oai-nr-cuup-asan', 'oai-gnb-aerial', 'oai-gnb-fhi72']
|
||||
|
||||
def CreateWorkspace(host, sourcePath, ranRepository, ranCommitID, ranTargetBranch, ranAllowMerge):
|
||||
def CreateWorkspace(sshSession, sourcePath, ranRepository, ranCommitID, ranTargetBranch, ranAllowMerge):
|
||||
if ranCommitID == '':
|
||||
logging.error('need ranCommitID in CreateWorkspace()')
|
||||
raise ValueError('Insufficient Parameter in CreateWorkspace(): need ranCommitID')
|
||||
sys.exit('Insufficient Parameter in CreateWorkspace()')
|
||||
|
||||
script = "scripts/create_workspace.sh"
|
||||
options = f"{sourcePath} {ranRepository} {ranCommitID}"
|
||||
sshSession.command(f'rm -rf {sourcePath}', '\$', 10)
|
||||
sshSession.command('mkdir -p ' + sourcePath, '\$', 5)
|
||||
sshSession.command('cd ' + sourcePath, '\$', 5)
|
||||
# Recent version of git (>2.20?) should handle missing .git extension # without problems
|
||||
if ranTargetBranch == 'null':
|
||||
ranTargetBranch = 'develop'
|
||||
baseBranch = re.sub('origin/', '', ranTargetBranch)
|
||||
sshSession.command(f'git clone --filter=blob:none -n -b {baseBranch} {ranRepository} .', '\$', 60)
|
||||
if sshSession.getBefore().count('error') > 0 or sshSession.getBefore().count('error') > 0:
|
||||
sys.exit('error during clone')
|
||||
sshSession.command('git config user.email "jenkins@openairinterface.org"', '\$', 5)
|
||||
sshSession.command('git config user.name "OAI Jenkins"', '\$', 5)
|
||||
|
||||
sshSession.command('mkdir -p cmake_targets/log', '\$', 5)
|
||||
# if the commit ID is provided use it to point to it
|
||||
sshSession.command(f'git checkout -f {ranCommitID}', '\$', 30)
|
||||
if sshSession.getBefore().count(f'HEAD is now at {ranCommitID[:6]}') != 1:
|
||||
sshSession.command('git log --oneline | head -n5', '\$', 5)
|
||||
logging.warning(f'problems during checkout, is at: {sshSession.getBefore()}')
|
||||
else:
|
||||
logging.debug('successful checkout')
|
||||
# if the branch is not develop, then it is a merge request and we need to do
|
||||
# the potential merge. Note that merge conflicts should already been checked earlier
|
||||
if ranAllowMerge:
|
||||
if ranTargetBranch == '':
|
||||
ranTargetBranch = 'develop'
|
||||
options += f" {ranTargetBranch}"
|
||||
logging.info(f'execute "{script}" with options "{options}" on node {host}')
|
||||
ret = cls_cmd.runScript(host, script, 90, options)
|
||||
logging.debug(f'"{script}" finished with code {ret.returncode}, output:\n{ret.stdout}')
|
||||
return ret.returncode == 0
|
||||
logging.debug(f'Merging with the target branch: {ranTargetBranch}')
|
||||
sshSession.command(f'git merge --ff origin/{ranTargetBranch} -m "Temporary merge for CI"', '\$', 30)
|
||||
|
||||
def CreateTag(ranCommitID, ranBranch, ranAllowMerge):
|
||||
def ImageTagToUse(imageName, ranCommitID, ranBranch, ranAllowMerge):
|
||||
shortCommit = ranCommitID[0:8]
|
||||
if ranAllowMerge:
|
||||
# Allowing contributor to have a name/branchName format
|
||||
@@ -78,7 +102,8 @@ def CreateTag(ranCommitID, ranBranch, ranAllowMerge):
|
||||
tagToUse = f'{branchName}-{shortCommit}'
|
||||
else:
|
||||
tagToUse = f'develop-{shortCommit}'
|
||||
return tagToUse
|
||||
fullTag = f'{imageName}:{tagToUse}'
|
||||
return fullTag
|
||||
|
||||
def CopyLogsToExecutor(cmd, sourcePath, log_name):
|
||||
cmd.cd(f'{sourcePath}/cmake_targets')
|
||||
@@ -144,156 +169,27 @@ def AnalyzeBuildLogs(buildRoot, images, globalStatus):
|
||||
collectInfo[image] = files
|
||||
return collectInfo
|
||||
|
||||
def GetCredentials(instance):
|
||||
server_id = instance.eNB_serverId[instance.eNB_instance]
|
||||
if server_id == '0':
|
||||
return (instance.eNBIPAddress, instance.eNBUserName, instance.eNBPassword, instance.eNBSourceCodePath)
|
||||
elif server_id == '1':
|
||||
return (instance.eNB1IPAddress, instance.eNB1UserName, instance.eNB1Password, instance.eNB1SourceCodePath)
|
||||
elif server_id == '2':
|
||||
return (instance.eNB2IPAddress, instance.eNB2UserName, instance.eNB2Password, instance.eNB2SourceCodePath)
|
||||
else:
|
||||
raise Exception ("Only supports maximum of 3 servers")
|
||||
# pyshark livecapture launches 2 processes:
|
||||
# * One using dumpcap -i lIfs -w - (ie redirecting the packets to STDOUT)
|
||||
# * One using tshark -i - -w loFile (ie capturing from STDIN from previous process)
|
||||
# but in fact the packets are read by the following loop before being in fact
|
||||
# really written to loFile.
|
||||
# So it is mandatory to keep the loop
|
||||
def LaunchPySharkCapture(lIfs, lFilter, loFile):
|
||||
capture = pyshark.LiveCapture(interface=lIfs, bpf_filter=lFilter, output_file=loFile, debug=False)
|
||||
for packet in capture.sniff_continuously():
|
||||
pass
|
||||
|
||||
def GetContainerName(ssh, svcName, file):
|
||||
ret = ssh.run(f"docker compose -f {file} config --format json {svcName} | jq -r '.services.\"{svcName}\".container_name'", silent=True)
|
||||
return ret.stdout
|
||||
|
||||
def GetImageName(ssh, svcName, file):
|
||||
ret = ssh.run(f"docker compose -f {file} config --format json {svcName} | jq -r '.services.\"{svcName}\".image'", silent=True)
|
||||
if ret.returncode != 0:
|
||||
return f"cannot retrieve image info for {containerName}: {ret.stdout}"
|
||||
else:
|
||||
return ret.stdout.strip()
|
||||
|
||||
def GetContainerHealth(ssh, containerName):
|
||||
if containerName is None:
|
||||
return False
|
||||
if 'db_init' in containerName or 'db-init' in containerName: # exits with 0, there cannot be healthy
|
||||
return True
|
||||
time.sleep(5)
|
||||
for _ in range(3):
|
||||
result = ssh.run(f'docker inspect --format="{{{{.State.Health.Status}}}}" {containerName}', silent=True)
|
||||
if result.stdout == 'healthy':
|
||||
return True
|
||||
time.sleep(10)
|
||||
def StopPySharkCapture(testcase):
|
||||
with cls_cmd.LocalCmd() as myCmd:
|
||||
cmd = 'killall tshark'
|
||||
myCmd.run(cmd, reportNonZero=False)
|
||||
cmd = 'killall dumpcap'
|
||||
myCmd.run(cmd, reportNonZero=False)
|
||||
time.sleep(5)
|
||||
cmd = f'mv /tmp/capture_{testcase}.pcap ../cmake_targets/log/{testcase}/.'
|
||||
myCmd.run(cmd, timeout=100, reportNonZero=False)
|
||||
return False
|
||||
|
||||
def ExistEnvFilePrint(ssh, wd, prompt='env vars in existing'):
|
||||
ret = ssh.run(f'cat {wd}/.env', silent=True)
|
||||
if ret.returncode != 0:
|
||||
return False
|
||||
env_vars = ret.stdout.strip().splitlines()
|
||||
logging.info(f'{prompt} {wd}/.env: {env_vars}')
|
||||
return True
|
||||
|
||||
def WriteEnvFile(ssh, services, wd, tag):
|
||||
ret = ssh.run(f'cat {wd}/.env', silent=True)
|
||||
registry = "oai-ci" # pull_images() gives us this registry path
|
||||
envs = {"REGISTRY":registry, "TAG": tag}
|
||||
if ret.returncode == 0: # it exists, we have to update
|
||||
# transforms env file to dictionary
|
||||
old_envs = {}
|
||||
for l in ret.stdout.strip().splitlines():
|
||||
var, val = l.split('=', 1)
|
||||
old_envs[var] = val.strip('"')
|
||||
# will retain the old environment variables
|
||||
envs = {**envs, **old_envs}
|
||||
for svc in services.split():
|
||||
# In some scenarios we have the choice of either pulling normal images
|
||||
# or -asan images. We need to detect which kind we did pull.
|
||||
fullImageName = GetImageName(ssh, svc, f"{wd}/docker-compose.y*ml")
|
||||
image = fullImageName.split("/")[-1].split(":")[0]
|
||||
checkimg = f"{registry}/{image}-asan:{tag}"
|
||||
ret = ssh.run(f'docker image inspect {checkimg}', reportNonZero=False)
|
||||
if ret.returncode == 0:
|
||||
logging.info(f"detected pulled image {checkimg}")
|
||||
if "oai-enb" in image: envs["ENB_IMG"] = "oai-enb-asan"
|
||||
elif "oai-gnb" in image: envs["GNB_IMG"] = "oai-gnb-asan"
|
||||
elif "oai-lte-ue" in image: envs["LTEUE_IMG"] = "oai-lte-ue-asan"
|
||||
elif "oai-nr-ue" in image: envs["NRUE_IMG"] = "oai-nr-ue-asan"
|
||||
elif "oai-nr-cuup" in image: envs["NRCUUP_IMG"] = "oai-nr-cuup-asan"
|
||||
else: logging.warning("undetected image format {image}, cannot use asan")
|
||||
env_string = "\n".join([f"{var}=\"{val}\"" for var,val in envs.items()])
|
||||
ssh.run(f'echo -e \'{env_string}\' > {wd}/.env', silent=True)
|
||||
ExistEnvFilePrint(ssh, wd, prompt='New env vars in file')
|
||||
|
||||
def GetServices(ssh, requested, file):
|
||||
if requested == [] or requested is None or requested == "":
|
||||
logging.warning('No service name given: starting all services in docker-compose.yml!')
|
||||
ret = ssh.run(f'docker compose -f {file} config --services')
|
||||
if ret.returncode != 0:
|
||||
return ""
|
||||
else:
|
||||
return ' '.join(ret.stdout.splitlines())
|
||||
else:
|
||||
return requested
|
||||
|
||||
def CopyinContainerLog(ssh, lSourcePath, yaml, containerName, filename):
|
||||
remote_filename = f"{lSourcePath}/cmake_targets/log/{filename}"
|
||||
ssh.run(f'docker logs {containerName} &> {remote_filename}')
|
||||
local_dir = f"{os.getcwd()}/../cmake_targets/log/{yaml}"
|
||||
os.system(f'mkdir -p {local_dir}')
|
||||
local_filename = f"{local_dir}/{filename}"
|
||||
return ssh.copyin(remote_filename, local_filename)
|
||||
|
||||
def GetRunningServices(ssh, file):
|
||||
ret = ssh.run(f'docker compose -f {file} config --services')
|
||||
if ret.returncode != 0:
|
||||
return None
|
||||
allServices = ret.stdout.splitlines()
|
||||
running_services = []
|
||||
for s in allServices:
|
||||
# outputs the hash if the container is running
|
||||
ret = ssh.run(f'docker compose -f {file} ps --all --quiet -- {s}')
|
||||
if ret.returncode != 0:
|
||||
logging.info(f"service {s}: {ret.stdout}")
|
||||
elif ret.stdout == "":
|
||||
logging.warning(f"could not retrieve information for service {s}")
|
||||
else:
|
||||
c = ret.stdout
|
||||
logging.debug(f'running service {s} with container id {c}')
|
||||
running_services.append((s, c))
|
||||
logging.info(f'stopping services: {running_services}')
|
||||
return running_services
|
||||
|
||||
def CheckLogs(self, yaml, service_name, HTML, RAN):
|
||||
logPath = f'{os.getcwd()}/../cmake_targets/log/{yaml}'
|
||||
filename = f'{logPath}/{service_name}-{HTML.testCase_id}.log'
|
||||
success = True
|
||||
if (any(sub in service_name for sub in ['oai_ue','oai-nr-ue','lte_ue'])):
|
||||
logging.debug(f'\u001B[1m Analyzing UE logfile {filename} \u001B[0m')
|
||||
logStatus = cls_oaicitest.OaiCiTest().AnalyzeLogFile_UE(filename, HTML, RAN)
|
||||
opt = f"UE log analysis for service {service_name}"
|
||||
# usage of htmlUEFailureMsg/htmleNBFailureMsg is because Analyze log files
|
||||
# abuse HTML to store their reports, and we here want to put custom options,
|
||||
# which is not possible with CreateHtmlTestRow
|
||||
# solution: use HTML templates, where we don't need different HTML write funcs
|
||||
if (logStatus < 0):
|
||||
HTML.CreateHtmlTestRowQueue(opt, 'KO', [HTML.htmlUEFailureMsg])
|
||||
success = False
|
||||
else:
|
||||
HTML.CreateHtmlTestRowQueue(opt, 'OK', [HTML.htmlUEFailureMsg])
|
||||
HTML.htmlUEFailureMsg = ""
|
||||
elif service_name == 'nv-cubb':
|
||||
msg = 'Undeploy PNF/Nvidia CUBB'
|
||||
HTML.CreateHtmlTestRow(msg, 'OK', CONST.ALL_PROCESSES_OK)
|
||||
elif (any(sub in service_name for sub in ['enb','rru','rcc','cu','du','gnb'])):
|
||||
logging.debug(f'\u001B[1m Analyzing XnB logfile {filename}\u001B[0m')
|
||||
logStatus = RAN.AnalyzeLogFile_eNB(filename, HTML, self.ran_checkers)
|
||||
opt = f"xNB log analysis for service {service_name}"
|
||||
if (logStatus < 0):
|
||||
HTML.CreateHtmlTestRowQueue(opt, 'KO', [HTML.htmleNBFailureMsg])
|
||||
success = False
|
||||
else:
|
||||
HTML.CreateHtmlTestRowQueue(opt, 'OK', [HTML.htmleNBFailureMsg])
|
||||
HTML.htmleNBFailureMsg = ""
|
||||
else:
|
||||
logging.info(f'Skipping to analyze log for service name {service_name}')
|
||||
HTML.CreateHtmlTestRowQueue(f"service {service_name}", 'OK', ["no analysis function"])
|
||||
logging.debug(f"log check: service {service_name} passed analysis {success}")
|
||||
return success
|
||||
|
||||
#-----------------------------------------------------------
|
||||
# Class Declaration
|
||||
#-----------------------------------------------------------
|
||||
@@ -323,9 +219,11 @@ class Containerize():
|
||||
self.proxyCommit = None
|
||||
self.eNB_instance = 0
|
||||
self.eNB_serverId = ['', '', '']
|
||||
self.deployKind = [True, True, True]
|
||||
self.yamlPath = ['', '', '']
|
||||
self.services = ['', '', '']
|
||||
self.deploymentTag = ''
|
||||
self.nb_healthy = [0, 0, 0]
|
||||
self.exitStatus = 0
|
||||
self.eNB_logFile = ['', '', '']
|
||||
|
||||
self.testCase_id = ''
|
||||
@@ -337,6 +235,7 @@ class Containerize():
|
||||
|
||||
self.deployedContainers = []
|
||||
self.tsharkStarted = False
|
||||
self.displayedNewTags = False
|
||||
self.pingContName = ''
|
||||
self.pingOptions = ''
|
||||
self.pingLossThreshold = ''
|
||||
@@ -417,9 +316,7 @@ class Containerize():
|
||||
imageNames.append(('oai-gnb-aerial', 'gNB.aerial', 'oai-gnb-aerial', ''))
|
||||
# Building again the 5G images with Address Sanitizer
|
||||
imageNames.append(('ran-build', 'build', 'ran-build-asan', '--build-arg "BUILD_OPTION=--sanitize"'))
|
||||
imageNames.append(('oai-enb', 'eNB', 'oai-enb-asan', '--build-arg "BUILD_OPTION=--sanitize"'))
|
||||
imageNames.append(('oai-gnb', 'gNB', 'oai-gnb-asan', '--build-arg "BUILD_OPTION=--sanitize"'))
|
||||
imageNames.append(('oai-lte-ue', 'lteUE', 'oai-lte-ue-asan', '--build-arg "BUILD_OPTION=--sanitize"'))
|
||||
imageNames.append(('oai-nr-ue', 'nrUE', 'oai-nr-ue-asan', '--build-arg "BUILD_OPTION=--sanitize"'))
|
||||
imageNames.append(('oai-nr-cuup', 'nr-cuup', 'oai-nr-cuup-asan', '--build-arg "BUILD_OPTION=--sanitize"'))
|
||||
imageNames.append(('ran-build-fhi72', 'build.fhi72', 'ran-build-fhi72', ''))
|
||||
@@ -428,11 +325,19 @@ class Containerize():
|
||||
if result is not None:
|
||||
self.dockerfileprefix = '.ubuntu22.cross-arm64'
|
||||
|
||||
# Workaround for some servers, we need to erase completely the workspace
|
||||
if self.forcedWorkspaceCleanup:
|
||||
cmd.run(f'sudo -S rm -Rf {lSourcePath}')
|
||||
|
||||
self.testCase_id = HTML.testCase_id
|
||||
cmd.cd(lSourcePath)
|
||||
|
||||
CreateWorkspace(cmd, lSourcePath, self.ranRepository, self.ranCommitID, self.ranTargetBranch, self.ranAllowMerge)
|
||||
|
||||
# if asterix, copy the entitlement and subscription manager configurations
|
||||
if self.host == 'Red Hat':
|
||||
cmd.run('mkdir -p ./etc-pki-entitlement')
|
||||
cmd.run('mkdir -p ./etc-pki-entitlement ./rhsm-conf ./rhsm-ca')
|
||||
cmd.run('cp /etc/rhsm/rhsm.conf ./rhsm-conf/')
|
||||
cmd.run('cp /etc/rhsm/ca/redhat-uep.pem ./rhsm-ca/')
|
||||
cmd.run('cp /etc/pki/entitlement/*.pem ./etc-pki-entitlement/')
|
||||
|
||||
baseImage = 'ran-base'
|
||||
@@ -627,7 +532,7 @@ class Containerize():
|
||||
self.ranRepository = 'https://github.com/EpiSci/oai-lte-5g-multi-ue-proxy.git'
|
||||
self.ranAllowMerge = False
|
||||
self.ranTargetBranch = 'master'
|
||||
mySSH.command('cd ' +lSourcePath, '\$', 3)
|
||||
CreateWorkspace(mySSH, lSourcePath, self.ranRepository, self.ranCommitID, self.ranTargetBranch, self.ranAllowMerge)
|
||||
# to prevent accidentally overwriting data that might be used later
|
||||
self.ranCommitID = oldRanCommidID
|
||||
self.ranRepository = oldRanRepository
|
||||
@@ -646,6 +551,8 @@ class Containerize():
|
||||
buildProxy = mySSH.getBefore().count('o such image') != 0
|
||||
if buildProxy:
|
||||
mySSH.command(self.cli + ' build ' + self.cliBuildOptions + ' --target oai-lte-multi-ue-proxy --tag proxy:' + tag + ' --file docker/Dockerfile.ubuntu18.04 . > cmake_targets/log/proxy-build.log 2>&1', '\$', 180)
|
||||
# Note: at this point, OAI images are flattened, but we cannot do this
|
||||
# here, as the flatten script is not in the proxy repo
|
||||
mySSH.command(self.cli + ' image inspect --format=\'Size = {{.Size}} bytes\' proxy:' + tag, '\$', 5)
|
||||
mySSH.command(self.cli + ' image prune --force || true','\$', 15)
|
||||
if mySSH.getBefore().count('o such image') != 0:
|
||||
@@ -787,7 +694,7 @@ class Containerize():
|
||||
HTML.CreateHtmlTestRowQueue("Build unit tests", 'OK', [dockerfile])
|
||||
|
||||
# it worked, build and execute tests, and close connection
|
||||
ret = cmd.run(f'docker run -a STDOUT --workdir /oai-ran/build/ --env LD_LIBRARY_PATH=/oai-ran/build/ --rm ran-unittests:{baseTag} ctest --output-on-failure --no-label-summary -j$(nproc)')
|
||||
ret = cmd.run(f'docker run -a STDOUT --rm ran-unittests:{baseTag} ctest --output-on-failure --no-label-summary -j$(nproc)')
|
||||
cmd.run(f'docker rmi ran-unittests:{baseTag}')
|
||||
build_log_name = f'build_log_{self.testCase_id}'
|
||||
CopyLogsToExecutor(cmd, lSourcePath, build_log_name)
|
||||
@@ -837,25 +744,19 @@ class Containerize():
|
||||
if self.ranAllowMerge:
|
||||
orgTag = 'ci-temp'
|
||||
for image in IMAGES:
|
||||
tagToUse = CreateTag(self.ranCommitID, self.ranBranch, self.ranAllowMerge)
|
||||
imageTag = f"{image}:{tagToUse}"
|
||||
mySSH.command(f'docker image tag {image}:{orgTag} {imagePrefix}/{imageTag}', '\$', 5)
|
||||
tagToUse = ImageTagToUse(image, self.ranCommitID, self.ranBranch, self.ranAllowMerge)
|
||||
mySSH.command(f'docker image tag {image}:{orgTag} {imagePrefix}/{tagToUse}', '\$', 5)
|
||||
if re.search('Error response from daemon: No such image:', mySSH.getBefore()) is not None:
|
||||
continue
|
||||
mySSH.command(f'docker push {imagePrefix}/{imageTag}', '\$', 120)
|
||||
mySSH.command(f'docker push {imagePrefix}/{tagToUse}', '\$', 120)
|
||||
if re.search(': digest:', mySSH.getBefore()) is None:
|
||||
logging.debug(mySSH.getBefore())
|
||||
msg = f'Could not push {image} to local registry : {imageTag}'
|
||||
msg = f'Could not push {image} to local registry : {tagToUse}'
|
||||
logging.error(msg)
|
||||
mySSH.close()
|
||||
HTML.CreateHtmlTestRow(msg, 'KO', CONST.ALL_PROCESSES_OK)
|
||||
return False
|
||||
# Creating a develop tag on the local private registry
|
||||
if not self.ranAllowMerge:
|
||||
mySSH.command(f'docker image tag {image}:{orgTag} {imagePrefix}/{image}:develop', '\$', 5)
|
||||
mySSH.command(f'docker push {imagePrefix}/{image}:develop', '\$', 120)
|
||||
mySSH.command(f'docker rmi {imagePrefix}/{image}:develop', '\$', 120)
|
||||
mySSH.command(f'docker rmi {imagePrefix}/{imageTag} {image}:{orgTag}', '\$', 30)
|
||||
mySSH.command(f'docker rmi {imagePrefix}/{tagToUse} {image}:{orgTag}', '\$', 30)
|
||||
|
||||
mySSH.command(f'docker logout {imagePrefix}', '\$', 5)
|
||||
if re.search('Removing login credentials', mySSH.getBefore()) is None:
|
||||
@@ -900,22 +801,19 @@ class Containerize():
|
||||
myCmd.close()
|
||||
HTML.CreateHtmlTestRow(msg, 'KO', CONST.ALL_PROCESSES_OK)
|
||||
return False
|
||||
pulled_images = []
|
||||
for image in self.imageToPull:
|
||||
tagToUse = CreateTag(self.ranCommitID, self.ranBranch, self.ranAllowMerge)
|
||||
imageTag = f"{image}:{tagToUse}"
|
||||
cmd = f'docker pull {imagePrefix}/{imageTag}'
|
||||
tagToUse = ImageTagToUse(image, self.ranCommitID, self.ranBranch, self.ranAllowMerge)
|
||||
cmd = f'docker pull {imagePrefix}/{tagToUse}'
|
||||
response = myCmd.run(cmd, timeout=120)
|
||||
if response.returncode != 0:
|
||||
logging.debug(response)
|
||||
msg = f'Could not pull {image} from local registry : {imageTag}'
|
||||
msg = f'Could not pull {image} from local registry : {tagToUse}'
|
||||
logging.error(msg)
|
||||
myCmd.close()
|
||||
HTML.CreateHtmlTestRow('msg', 'KO', CONST.ALL_PROCESSES_OK)
|
||||
return False
|
||||
myCmd.run(f'docker tag {imagePrefix}/{imageTag} oai-ci/{imageTag}')
|
||||
myCmd.run(f'docker rmi {imagePrefix}/{imageTag}')
|
||||
pulled_images += [f"oai-ci/{imageTag}"]
|
||||
myCmd.run(f'docker tag {imagePrefix}/{tagToUse} oai-ci/{tagToUse}')
|
||||
myCmd.run(f'docker rmi {imagePrefix}/{tagToUse}')
|
||||
response = myCmd.run(f'docker logout {imagePrefix}')
|
||||
if response.returncode != 0:
|
||||
msg = 'Could not log off from local registry'
|
||||
@@ -924,8 +822,7 @@ class Containerize():
|
||||
HTML.CreateHtmlTestRow(msg, 'KO', CONST.ALL_PROCESSES_OK)
|
||||
return False
|
||||
myCmd.close()
|
||||
msg = "Pulled Images:\n" + '\n'.join(pulled_images)
|
||||
HTML.CreateHtmlTestRowQueue('N/A', 'OK', [msg])
|
||||
HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK)
|
||||
return True
|
||||
|
||||
def Clean_Test_Server_Images(self, HTML):
|
||||
@@ -957,8 +854,7 @@ class Containerize():
|
||||
myCmd = cls_cmd.LocalCmd()
|
||||
|
||||
for image in IMAGES:
|
||||
tag = CreateTag(self.ranCommitID, self.ranBranch, self.ranAllowMerge)
|
||||
imageTag = f"{image}:{tag}"
|
||||
imageTag = ImageTagToUse(image, self.ranCommitID, self.ranBranch, self.ranAllowMerge)
|
||||
cmd = f'docker rmi oai-ci/{imageTag}'
|
||||
myCmd.run(cmd, reportNonZero=False)
|
||||
|
||||
@@ -966,7 +862,7 @@ class Containerize():
|
||||
HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK)
|
||||
return True
|
||||
|
||||
def Create_Workspace(self,HTML):
|
||||
def DeployObject(self, HTML, EPC):
|
||||
if self.eNB_serverId[self.eNB_instance] == '0':
|
||||
lIpAddr = self.eNBIPAddress
|
||||
lUserName = self.eNBUserName
|
||||
@@ -985,96 +881,501 @@ class Containerize():
|
||||
if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '':
|
||||
HELP.GenericHelp(CONST.Version)
|
||||
sys.exit('Insufficient Parameter')
|
||||
|
||||
success = CreateWorkspace(lIpAddr, lSourcePath, self.ranRepository, self.ranCommitID, self.ranTargetBranch, self.ranAllowMerge)
|
||||
if success:
|
||||
HTML.CreateHtmlTestRowQueue('N/A', 'OK', [f"created workspace {lSourcePath}"])
|
||||
else:
|
||||
HTML.CreateHtmlTestRowQueue('N/A', 'KO', ["cannot create workspace"])
|
||||
return success
|
||||
|
||||
def DeployObject(self, HTML):
|
||||
lIpAddr, lUserName, lPassWord, lSourcePath = GetCredentials(self)
|
||||
if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '':
|
||||
HELP.GenericHelp(CONST.Version)
|
||||
sys.exit('Insufficient Parameter')
|
||||
logging.debug('\u001B[1m Deploying OAI Object on server: ' + lIpAddr + '\u001B[0m')
|
||||
yaml = self.yamlPath[self.eNB_instance].strip('/')
|
||||
wd = f'{lSourcePath}/{yaml}'
|
||||
self.deployKind[self.eNB_instance] = True
|
||||
|
||||
with cls_cmd.getConnection(lIpAddr) as ssh:
|
||||
services = GetServices(ssh, self.services[self.eNB_instance], f"{wd}/docker-compose.y*ml")
|
||||
if services == [] or services == ' ' or services == None:
|
||||
msg = "Cannot determine services to start"
|
||||
logging.error(msg)
|
||||
HTML.CreateHtmlTestRowQueue('N/A', 'KO', [msg])
|
||||
return False
|
||||
mySSH = SSH.SSHConnection()
|
||||
mySSH.open(lIpAddr, lUserName, lPassWord)
|
||||
|
||||
ExistEnvFilePrint(ssh, wd)
|
||||
WriteEnvFile(ssh, services, wd, self.deploymentTag)
|
||||
CreateWorkspace(mySSH, lSourcePath, self.ranRepository, self.ranCommitID, self.ranTargetBranch, self.ranAllowMerge)
|
||||
|
||||
logging.info(f"will start services {services}")
|
||||
status = ssh.run(f'docker compose -f {wd}/docker-compose.y*ml up -d -- {services}')
|
||||
if status.returncode != 0:
|
||||
msg = f"cannot deploy services {services}: {status.stdout}"
|
||||
logging.error(msg)
|
||||
HTML.CreateHtmlTestRowQueue('N/A', 'KO', [msg])
|
||||
return False
|
||||
mySSH.command('cd ' + lSourcePath + '/' + self.yamlPath[self.eNB_instance], '\$', 5)
|
||||
mySSH.command('cp docker-compose.y*ml ci-docker-compose.yml', '\$', 5)
|
||||
for image in IMAGES:
|
||||
imageTag = ImageTagToUse(image, self.ranCommitID, self.ranBranch, self.ranAllowMerge)
|
||||
mySSH.command(f'sed -i -e "s#image: {image}:latest#image: oai-ci/{imageTag}#" ci-docker-compose.yml', '\$', 2)
|
||||
|
||||
imagesInfo = []
|
||||
fstatus = True
|
||||
for svc in services.split():
|
||||
containerName = GetContainerName(ssh, svc, f"{wd}/docker-compose.y*ml")
|
||||
healthy = GetContainerHealth(ssh, containerName)
|
||||
if not healthy:
|
||||
tgtlogfile = f'{svc}-{HTML.testCase_id}.log'
|
||||
logging.warning(f"Deployment Failed: Trying to copy container logs to {tgtlogfile}")
|
||||
yaml_dir = yaml.split('/')[-1]
|
||||
CopyinContainerLog(ssh, lSourcePath, yaml_dir, containerName, tgtlogfile)
|
||||
imagesInfo += [f"Failed to deploy: service {svc}"]
|
||||
fstatus = False
|
||||
# Currently support only one
|
||||
svcName = self.services[self.eNB_instance]
|
||||
if svcName == '':
|
||||
logging.warning('no service name given: starting all services in ci-docker-compose.yml!')
|
||||
|
||||
mySSH.command(f'docker compose --file ci-docker-compose.yml up -d -- {svcName}', '\$', 30)
|
||||
|
||||
# Checking Status
|
||||
mySSH.command(f'docker compose --file ci-docker-compose.yml config {svcName}', '\$', 5)
|
||||
result = re.search('container_name: (?P<container_name>[a-zA-Z0-9\-\_]+)', mySSH.getBefore())
|
||||
unhealthyNb = 0
|
||||
healthyNb = 0
|
||||
startingNb = 0
|
||||
containerName = ''
|
||||
usedImage = ''
|
||||
imageInfo = ''
|
||||
if result is not None:
|
||||
containerName = result.group('container_name')
|
||||
time.sleep(5)
|
||||
cnt = 0
|
||||
while (cnt < 3):
|
||||
mySSH.command('docker inspect --format="{{.State.Health.Status}}" ' + containerName, '\$', 5)
|
||||
unhealthyNb = mySSH.getBefore().count('unhealthy')
|
||||
healthyNb = mySSH.getBefore().count('healthy') - unhealthyNb
|
||||
startingNb = mySSH.getBefore().count('starting')
|
||||
if healthyNb == 1:
|
||||
cnt = 10
|
||||
else:
|
||||
image = GetImageName(ssh, svc, f"{wd}/docker-compose.y*ml")
|
||||
logging.info(f"service {svc} healthy, container {containerName}, image {image}")
|
||||
imagesInfo += [f"service {svc} healthy, image {image}"]
|
||||
if fstatus:
|
||||
HTML.CreateHtmlTestRowQueue('N/A', 'OK', ['\n'.join(imagesInfo)])
|
||||
time.sleep(10)
|
||||
cnt += 1
|
||||
|
||||
mySSH.command('docker inspect --format="ImageUsed: {{.Config.Image}}" ' + containerName, '\$', 5)
|
||||
for stdoutLine in mySSH.getBefore().split('\n'):
|
||||
if stdoutLine.count('ImageUsed: oai-ci'):
|
||||
usedImage = stdoutLine.replace('ImageUsed: oai-ci', 'oai-ci').strip()
|
||||
logging.debug('Used image is ' + usedImage)
|
||||
if usedImage != '':
|
||||
mySSH.command('docker image inspect --format "* Size = {{.Size}} bytes\n* Creation = {{.Created}}\n* Id = {{.Id}}" ' + usedImage, '\$', 5, silent=True)
|
||||
for stdoutLine in mySSH.getBefore().split('\n'):
|
||||
if re.search('Size = [0-9]', stdoutLine) is not None:
|
||||
imageInfo += stdoutLine.strip() + '\n'
|
||||
if re.search('Creation = [0-9]', stdoutLine) is not None:
|
||||
imageInfo += stdoutLine.strip() + '\n'
|
||||
if re.search('Id = sha256', stdoutLine) is not None:
|
||||
imageInfo += stdoutLine.strip() + '\n'
|
||||
logging.debug(' -- ' + str(healthyNb) + ' healthy container(s)')
|
||||
logging.debug(' -- ' + str(unhealthyNb) + ' unhealthy container(s)')
|
||||
logging.debug(' -- ' + str(startingNb) + ' still starting container(s)')
|
||||
|
||||
self.testCase_id = HTML.testCase_id
|
||||
self.eNB_logFile[self.eNB_instance] = 'enb_' + self.testCase_id + '.log'
|
||||
|
||||
status = False
|
||||
if healthyNb == 1:
|
||||
cnt = 0
|
||||
while (cnt < 20):
|
||||
mySSH.command('docker logs ' + containerName + ' | egrep --text --color=never -i "wait|sync|Starting|ready"', '\$', 30)
|
||||
result = re.search('got sync|Starting E1AP at CU UP|Starting F1AP at CU|Got sync|Waiting for RUs to be configured|cuPHYController initialized|Received CONFIG.response, gNB is ready', mySSH.getBefore())
|
||||
if result is None:
|
||||
time.sleep(6)
|
||||
cnt += 1
|
||||
else:
|
||||
cnt = 100
|
||||
status = True
|
||||
logging.info('\u001B[1m Deploying OAI object Pass\u001B[0m')
|
||||
else:
|
||||
HTML.CreateHtmlTestRowQueue('N/A', 'KO', ['\n'.join(imagesInfo)])
|
||||
return fstatus
|
||||
# containers are unhealthy, so we won't start. However, logs are stored at the end
|
||||
# in UndeployObject so we here store the logs of the unhealthy container to report it
|
||||
logfilename = f'{lSourcePath}/cmake_targets/log/{self.eNB_logFile[self.eNB_instance]}'
|
||||
mySSH.command(f'docker logs {containerName} > {logfilename}', '\$', 30)
|
||||
mySSH.copyin(lIpAddr, lUserName, lPassWord, logfilename, '.')
|
||||
mySSH.close()
|
||||
|
||||
message = ''
|
||||
if usedImage != '':
|
||||
message += f'Used Image = {usedImage} :\n'
|
||||
message += imageInfo
|
||||
else:
|
||||
message += 'Could not retrieve used image info!\n'
|
||||
if status:
|
||||
message += '\nHealthy deployment!\n'
|
||||
else:
|
||||
message += '\nUnhealthy deployment! -- Check logs for reason!\n'
|
||||
if status:
|
||||
HTML.CreateHtmlTestRowQueue('N/A', 'OK', [message])
|
||||
else:
|
||||
self.exitStatus = 1
|
||||
HTML.CreateHtmlTestRowQueue('N/A', 'KO', [message])
|
||||
|
||||
|
||||
def UndeployObject(self, HTML, RAN):
|
||||
lIpAddr, lUserName, lPassWord, lSourcePath = GetCredentials(self)
|
||||
if self.eNB_serverId[self.eNB_instance] == '0':
|
||||
lIpAddr = self.eNBIPAddress
|
||||
lUserName = self.eNBUserName
|
||||
lPassWord = self.eNBPassword
|
||||
lSourcePath = self.eNBSourceCodePath
|
||||
elif self.eNB_serverId[self.eNB_instance] == '1':
|
||||
lIpAddr = self.eNB1IPAddress
|
||||
lUserName = self.eNB1UserName
|
||||
lPassWord = self.eNB1Password
|
||||
lSourcePath = self.eNB1SourceCodePath
|
||||
elif self.eNB_serverId[self.eNB_instance] == '2':
|
||||
lIpAddr = self.eNB2IPAddress
|
||||
lUserName = self.eNB2UserName
|
||||
lPassWord = self.eNB2Password
|
||||
lSourcePath = self.eNB2SourceCodePath
|
||||
if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '':
|
||||
HELP.GenericHelp(CONST.Version)
|
||||
sys.exit('Insufficient Parameter')
|
||||
logging.debug(f'\u001B[1m Undeploying OAI Object from server: {lIpAddr}\u001B[0m')
|
||||
yaml = self.yamlPath[self.eNB_instance].strip('/')
|
||||
wd = f'{lSourcePath}/{yaml}'
|
||||
yaml_dir = yaml.split('/')[-1]
|
||||
with cls_cmd.getConnection(lIpAddr) as ssh:
|
||||
ExistEnvFilePrint(ssh, wd)
|
||||
services = GetRunningServices(ssh, f"{wd}/docker-compose.y*ml")
|
||||
copyin_res = None
|
||||
if services is not None:
|
||||
all_serv = " ".join([s for s, _ in services])
|
||||
ssh.run(f'docker compose -f {wd}/docker-compose.y*ml stop -- {all_serv}')
|
||||
copyin_res = all(CopyinContainerLog(ssh, lSourcePath, yaml_dir, c, f'{s}-{HTML.testCase_id}.log') for s, c in services)
|
||||
else:
|
||||
logging.warning('could not identify services to stop => no log file')
|
||||
ssh.run(f'docker compose -f {wd}/docker-compose.y*ml down -v')
|
||||
ssh.run(f'rm {wd}/.env')
|
||||
mySSH = cls_cmd.getConnection(lIpAddr)
|
||||
yamlDir = f'{lSourcePath}/{self.yamlPath[self.eNB_instance]}'
|
||||
mySSH.run(f'cd {yamlDir}')
|
||||
svcName = self.services[self.eNB_instance]
|
||||
forceDown = False
|
||||
if svcName != '':
|
||||
logging.warning(f'service name given, but will stop all services in ci-docker-compose.yml!')
|
||||
svcName = ''
|
||||
|
||||
ret = mySSH.run(f'docker compose -f {yamlDir}/ci-docker-compose.yml config --services')
|
||||
if ret.returncode != 0:
|
||||
HTML.CreateHtmlTestRow(RAN.runtime_stats, 'KO', "cannot enumerate running services")
|
||||
self.exitStatus = 1
|
||||
return
|
||||
# first line has command, last line has next command prompt
|
||||
allServices = ret.stdout.splitlines()
|
||||
services = []
|
||||
for s in allServices:
|
||||
# outputs the hash if the container is running
|
||||
ret = mySSH.run(f'docker compose -f {yamlDir}/ci-docker-compose.yml ps --all --quiet -- {s}')
|
||||
c = ret.stdout
|
||||
logging.debug(f'running service {s} with container id {c}')
|
||||
if ret.stdout != "" and ret.returncode == 0: # something is running for that service
|
||||
services.append((s, c))
|
||||
logging.info(f'stopping services {[s for s, _ in services]}')
|
||||
|
||||
mySSH.run(f'docker compose -f {yamlDir}/ci-docker-compose.yml stop -t3')
|
||||
copyin_res = True
|
||||
for service_name, container_id in services:
|
||||
# head -n -1 suppresses the final "X exited with status code Y"
|
||||
filename = f'{service_name}-{HTML.testCase_id}.log'
|
||||
mySSH.run(f'docker logs {container_id} &> {lSourcePath}/cmake_targets/log/{filename}')
|
||||
copyin_res = mySSH.copyin(f'{lSourcePath}/cmake_targets/log/{filename}', f'{filename}') and copyin_res
|
||||
|
||||
mySSH.run(f'docker compose -f {yamlDir}/ci-docker-compose.yml down -v')
|
||||
|
||||
# Analyzing log file!
|
||||
if not copyin_res:
|
||||
HTML.CreateHtmlTestRowQueue('N/A', 'KO', ['Could not copy logfile(s)'])
|
||||
return False
|
||||
HTML.htmleNBFailureMsg='Could not copy logfile(s) to analyze it!'
|
||||
HTML.CreateHtmlTestRow('N/A', 'KO', CONST.ENB_PROCESS_NOLOGFILE_TO_ANALYZE)
|
||||
self.exitStatus = 1
|
||||
# use function for UE log analysis, when oai-nr-ue container is used
|
||||
elif any(service_name == 'oai-nr-ue' or service_name == 'lte_ue0' for service_name, _ in services):
|
||||
self.exitStatus == 0
|
||||
logging.debug(f'Analyzing UE logfile {filename}')
|
||||
logStatus = cls_oaicitest.OaiCiTest().AnalyzeLogFile_UE(f'{filename}', HTML, RAN)
|
||||
if (logStatus < 0):
|
||||
HTML.CreateHtmlTestRow('UE log Analysis', 'KO', logStatus)
|
||||
self.exitStatus = 1
|
||||
else:
|
||||
HTML.CreateHtmlTestRow('UE log Analysis', 'OK', CONST.ALL_PROCESSES_OK)
|
||||
else:
|
||||
log_results = [CheckLogs(self, yaml_dir, s, HTML, RAN) for s, _ in services]
|
||||
success = all(log_results)
|
||||
if success:
|
||||
for service_name, _ in services:
|
||||
if service_name == 'nv-cubb':
|
||||
msg = 'Undeploy PNF/Nvidia CUBB'
|
||||
HTML.CreateHtmlTestRow(msg, 'OK', CONST.ALL_PROCESSES_OK)
|
||||
else:
|
||||
filename = f'{service_name}-{HTML.testCase_id}.log'
|
||||
logging.debug(f'\u001B[1m Analyzing logfile {filename}\u001B[0m')
|
||||
logStatus = RAN.AnalyzeLogFile_eNB(filename, HTML, self.ran_checkers)
|
||||
if (logStatus < 0):
|
||||
HTML.CreateHtmlTestRow(RAN.runtime_stats, 'KO', logStatus)
|
||||
self.exitStatus = 1
|
||||
else:
|
||||
HTML.CreateHtmlTestRow(RAN.runtime_stats, 'OK', CONST.ALL_PROCESSES_OK)
|
||||
# all the xNB run logs shall be on the server 0 for logCollecting
|
||||
if self.eNB_serverId[self.eNB_instance] != '0':
|
||||
mySSH.copyout(f'./*.log', f'{lSourcePath}/cmake_targets/', recursive=True)
|
||||
if self.exitStatus == 0:
|
||||
logging.info('\u001B[1m Undeploying OAI Object Pass\u001B[0m')
|
||||
else:
|
||||
logging.error('\u001B[1m Undeploying OAI Object Failed\u001B[0m')
|
||||
return success
|
||||
mySSH.close()
|
||||
|
||||
def DeployGenObject(self, HTML, RAN, UE):
|
||||
self.exitStatus = 0
|
||||
logging.debug('\u001B[1m Checking Services to deploy\u001B[0m')
|
||||
# Implicitly we are running locally
|
||||
myCmd = cls_cmd.LocalCmd(d = self.yamlPath[0])
|
||||
self.deployKind[0] = False
|
||||
cmd = 'docker-compose config --services'
|
||||
listServices = myCmd.run(cmd)
|
||||
if listServices.returncode != 0:
|
||||
myCmd.close()
|
||||
self.exitStatus = 1
|
||||
HTML.CreateHtmlTestRow('SVC not Found', 'KO', CONST.ALL_PROCESSES_OK)
|
||||
return
|
||||
for reqSvc in self.services[0].split(' '):
|
||||
res = re.search(reqSvc, listServices.stdout)
|
||||
if res is None:
|
||||
logging.error(reqSvc + ' not found in specified docker-compose')
|
||||
self.exitStatus = 1
|
||||
if (self.exitStatus == 1):
|
||||
myCmd.close()
|
||||
HTML.CreateHtmlTestRow('SVC not Found', 'KO', CONST.ALL_PROCESSES_OK)
|
||||
return
|
||||
cmd = 'cp docker-compose.y*ml docker-compose-ci.yml'
|
||||
myCmd.run(cmd, silent=self.displayedNewTags)
|
||||
imageNames = ['oai-enb', 'oai-gnb', 'oai-lte-ue', 'oai-nr-ue', 'oai-lte-ru', 'oai-nr-cuup']
|
||||
for image in imageNames:
|
||||
tagToUse = ImageTagToUse(image, self.ranCommitID, self.ranBranch, self.ranAllowMerge)
|
||||
# In the scenario, for 5G images, we have the choice of either pulling normal images
|
||||
# or -asan images. We need to detect which kind we did pull.
|
||||
if image == 'oai-gnb' or image == 'oai-nr-ue' or image == 'oai-nr-cuup':
|
||||
ret = myCmd.run(f'docker image inspect oai-ci/{tagToUse}', reportNonZero=False, silent=self.displayedNewTags)
|
||||
if ret.returncode != 0:
|
||||
tagToUse = tagToUse.replace('oai-gnb', 'oai-gnb-asan')
|
||||
tagToUse = tagToUse.replace('oai-nr-ue', 'oai-nr-ue-asan')
|
||||
tagToUse = tagToUse.replace('oai-nr-cuup', 'oai-nr-cuup-asan')
|
||||
if not self.displayedNewTags:
|
||||
logging.debug(f'\u001B[1m Using sanitized version of {image} with {tagToUse}\u001B[0m')
|
||||
cmd = f'sed -i -e "s@oaisoftwarealliance/{image}:develop@oai-ci/{tagToUse}@" docker-compose-ci.yml'
|
||||
myCmd.run(cmd, silent=self.displayedNewTags)
|
||||
self.displayedNewTags = True
|
||||
|
||||
cmd = f'docker-compose -f docker-compose-ci.yml up -d {self.services[0]}'
|
||||
deployStatus = myCmd.run(cmd, timeout=100)
|
||||
if deployStatus.returncode != 0:
|
||||
myCmd.close()
|
||||
self.exitStatus = 1
|
||||
logging.error('Could not deploy')
|
||||
HTML.CreateHtmlTestRow('Could not deploy', 'KO', CONST.ALL_PROCESSES_OK)
|
||||
return
|
||||
|
||||
logging.debug('\u001B[1m Checking if all deployed healthy\u001B[0m')
|
||||
cmd = 'docker-compose -f docker-compose-ci.yml ps -a'
|
||||
count = 0
|
||||
healthy = 0
|
||||
restarting = 0
|
||||
newContainers = []
|
||||
while (count < 10):
|
||||
count += 1
|
||||
containerStatus = []
|
||||
deployStatus = myCmd.run(cmd, 30, silent=True)
|
||||
healthy = 0
|
||||
restarting = 0
|
||||
for state in deployStatus.stdout.split('\n'):
|
||||
state = state.strip()
|
||||
res = re.search('Name|NAME|----------', state)
|
||||
if res is not None:
|
||||
continue
|
||||
if len(state) == 0:
|
||||
continue
|
||||
res = re.search('^(?P<container_name>[a-zA-Z0-9\-\_]+) ', state)
|
||||
if res is not None:
|
||||
cName = res.group('container_name')
|
||||
found = False
|
||||
for alreadyDeployed in self.deployedContainers:
|
||||
if cName == alreadyDeployed:
|
||||
found = True
|
||||
if not found:
|
||||
newContainers.append(cName)
|
||||
self.deployedContainers.append(cName)
|
||||
if re.search('\(healthy\)', state) is not None:
|
||||
healthy += 1
|
||||
if re.search('rfsim4g-db-init.*Exit 0', state) is not None or re.search('rfsim4g-db-init.*Exited \(0\)', state) is not None:
|
||||
myCmd.run('docker rm -f rfsim4g-db-init', timeout=30, silent=True, reportNonZero=False)
|
||||
if re.search('l2sim4g-db-init.*Exit 0', state) is not None or re.search('l2sim4g-db-init.*Exited \(0\)', state) is not None:
|
||||
myCmd.run('docker rm -f l2sim4g-db-init', timeout=30, silent=True, reportNonZero=False)
|
||||
if re.search('Restarting', state) is None:
|
||||
containerStatus.append(state)
|
||||
else:
|
||||
restarting += 1
|
||||
if healthy == self.nb_healthy[0] and restarting == 0:
|
||||
count = 100
|
||||
else:
|
||||
time.sleep(10)
|
||||
|
||||
html_cell = ''
|
||||
for newCont in newContainers:
|
||||
if newCont == 'rfsim4g-db-init':
|
||||
continue
|
||||
cmd = 'docker inspect -f "{{.Config.Image}}" ' + newCont
|
||||
imageInspect = myCmd.run(cmd, timeout=30, silent=True)
|
||||
imageName = str(imageInspect.stdout).strip()
|
||||
cmd = 'docker image inspect --format \'{{.RepoTags}}\t{{.Size}} bytes\t{{index (split .Created ".") 0}}\n{{.Id}}\' ' + imageName
|
||||
imageInspect = myCmd.run(cmd, 30, silent=True)
|
||||
html_cell += imageInspect.stdout + '\n'
|
||||
myCmd.close()
|
||||
|
||||
for cState in containerStatus:
|
||||
html_cell += cState + '\n'
|
||||
if count == 100 and healthy == self.nb_healthy[0]:
|
||||
if self.tsharkStarted == False:
|
||||
logging.debug('Starting tshark on public network')
|
||||
self.CaptureOnDockerNetworks()
|
||||
HTML.CreateHtmlTestRowQueue('n/a', 'OK', [html_cell])
|
||||
for cState in containerStatus:
|
||||
logging.debug(cState)
|
||||
logging.info('\u001B[1m Deploying OAI Object(s) PASS\u001B[0m')
|
||||
else:
|
||||
HTML.CreateHtmlTestRowQueue('Could not deploy in time', 'KO', [html_cell])
|
||||
for cState in containerStatus:
|
||||
logging.debug(cState)
|
||||
logging.error('\u001B[1m Deploying OAI Object(s) FAILED\u001B[0m')
|
||||
HTML.testCase_id = 'AUTO-UNDEPLOY'
|
||||
UE.testCase_id = 'AUTO-UNDEPLOY'
|
||||
HTML.desc = 'Automatic Undeployment'
|
||||
UE.desc = 'Automatic Undeployment'
|
||||
UE.ShowTestID()
|
||||
self.UndeployGenObject(HTML, RAN, UE)
|
||||
self.exitStatus = 1
|
||||
|
||||
def CaptureOnDockerNetworks(self):
|
||||
myCmd = cls_cmd.LocalCmd(d = self.yamlPath[0])
|
||||
cmd = 'docker-compose -f docker-compose-ci.yml config | grep com.docker.network.bridge.name | sed -e "s@^.*name: @@"'
|
||||
networkNames = myCmd.run(cmd, silent=True)
|
||||
myCmd.close()
|
||||
# Allow only: control plane RAN (SCTP), HTTP of control in CN (port 80), PFCP traffic (port 8805), MySQL (port 3306)
|
||||
capture_filter = 'sctp or port 80 or port 8805 or icmp or port 3306'
|
||||
interfaces = []
|
||||
iInterfaces = ''
|
||||
for name in networkNames.stdout.split('\n'):
|
||||
if re.search('rfsim', name) is not None or re.search('l2sim', name) is not None:
|
||||
interfaces.append(name)
|
||||
iInterfaces += f'-i {name} '
|
||||
ymlPath = self.yamlPath[0].split('/')
|
||||
output_file = f'/tmp/capture_{ymlPath[1]}.pcap'
|
||||
self.tsharkStarted = True
|
||||
# On old systems (ubuntu 18), pyshark live-capture is buggy.
|
||||
# Going back to old method
|
||||
if sys.version_info < (3, 7):
|
||||
cmd = f'nohup tshark -f "{capture_filter}" {iInterfaces} -w {output_file} > /tmp/tshark.log 2>&1 &'
|
||||
myCmd = cls_cmd.LocalCmd()
|
||||
myCmd.run(cmd, timeout=5, reportNonZero=False)
|
||||
myCmd.close()
|
||||
return
|
||||
x = threading.Thread(target = LaunchPySharkCapture, args = (interfaces,capture_filter,output_file,))
|
||||
x.daemon = True
|
||||
x.start()
|
||||
|
||||
def UndeployGenObject(self, HTML, RAN, UE):
|
||||
self.exitStatus = 0
|
||||
# Implicitly we are running locally
|
||||
ymlPath = self.yamlPath[0].split('/')
|
||||
logPath = '../cmake_targets/log/' + ymlPath[1]
|
||||
myCmd = cls_cmd.LocalCmd(d = self.yamlPath[0])
|
||||
cmd = 'cp docker-compose.y*ml docker-compose-ci.yml'
|
||||
myCmd.run(cmd)
|
||||
|
||||
# check which containers are running for log recovery later
|
||||
cmd = 'docker-compose -f docker-compose-ci.yml ps --all'
|
||||
deployStatusLogs = myCmd.run(cmd, timeout=30)
|
||||
|
||||
# Stop the containers to shut down objects
|
||||
logging.debug('\u001B[1m Stopping containers \u001B[0m')
|
||||
cmd = 'docker-compose -f docker-compose-ci.yml stop -t3'
|
||||
deployStatus = myCmd.run(cmd, timeout=100)
|
||||
if deployStatus.returncode != 0:
|
||||
myCmd.close()
|
||||
self.exitStatus = 1
|
||||
logging.error('Could not stop containers')
|
||||
HTML.CreateHtmlTestRow('Could not stop', 'KO', CONST.ALL_PROCESSES_OK)
|
||||
logging.error('\u001B[1m Undeploying OAI Object(s) FAILED\u001B[0m')
|
||||
return
|
||||
|
||||
anyLogs = False
|
||||
logging.debug('Working dir is now . (ie ci-scripts)')
|
||||
myCmd2 = cls_cmd.LocalCmd()
|
||||
myCmd2.run(f'mkdir -p {logPath}')
|
||||
myCmd2.cd(logPath)
|
||||
for state in deployStatusLogs.stdout.split('\n'):
|
||||
res = re.search('Name|NAME|----------', state)
|
||||
if res is not None:
|
||||
continue
|
||||
if len(state) == 0:
|
||||
continue
|
||||
res = re.search('^(?P<container_name>[a-zA-Z0-9\-\_]+) ', state)
|
||||
if res is not None:
|
||||
anyLogs = True
|
||||
cName = res.group('container_name')
|
||||
cmd = f'docker logs {cName} > {cName}.log 2>&1'
|
||||
myCmd2.run(cmd, timeout=30, reportNonZero=False)
|
||||
if re.search('magma-mme', cName) is not None:
|
||||
cmd = f'docker cp -L {cName}:/var/log/mme.log {cName}-full.log'
|
||||
myCmd2.run(cmd, timeout=30, reportNonZero=False)
|
||||
fullStatus = True
|
||||
if anyLogs:
|
||||
# Analyzing log file(s)!
|
||||
listOfPossibleRanContainers = ['enb*', 'gnb*', 'cu*', 'du*']
|
||||
for container in listOfPossibleRanContainers:
|
||||
filenames = './*-oai-' + container + '.log'
|
||||
cmd = f'ls {filenames}'
|
||||
lsStatus = myCmd2.run(cmd, silent=True, reportNonZero=False)
|
||||
if lsStatus.returncode != 0:
|
||||
continue
|
||||
filenames = str(lsStatus.stdout).strip()
|
||||
|
||||
for filename in filenames.split('\n'):
|
||||
logging.debug('\u001B[1m Analyzing xNB logfile ' + filename + ' \u001B[0m')
|
||||
logStatus = RAN.AnalyzeLogFile_eNB(f'{logPath}/{filename}', HTML, self.ran_checkers)
|
||||
if (logStatus < 0):
|
||||
fullStatus = False
|
||||
self.exitStatus = 1
|
||||
HTML.CreateHtmlTestRow(RAN.runtime_stats, 'KO', logStatus)
|
||||
else:
|
||||
HTML.CreateHtmlTestRow(RAN.runtime_stats, 'OK', CONST.ALL_PROCESSES_OK)
|
||||
|
||||
listOfPossibleUeContainers = ['lte-ue*', 'nr-ue*']
|
||||
for container in listOfPossibleUeContainers:
|
||||
filenames = './*-oai-' + container + '.log'
|
||||
cmd = f'ls {filenames}'
|
||||
lsStatus = myCmd2.run(cmd, silent=True, reportNonZero=False)
|
||||
if lsStatus.returncode != 0:
|
||||
continue
|
||||
filenames = str(lsStatus.stdout).strip()
|
||||
|
||||
for filename in filenames.split('\n'):
|
||||
logging.debug('\u001B[1m Analyzing UE logfile ' + filename + ' \u001B[0m')
|
||||
logStatus = UE.AnalyzeLogFile_UE(f'{logPath}/{filename}', HTML, RAN)
|
||||
if (logStatus < 0):
|
||||
fullStatus = False
|
||||
self.exitStatus = 1
|
||||
HTML.CreateHtmlTestRow('UE log Analysis', 'KO', logStatus)
|
||||
else:
|
||||
HTML.CreateHtmlTestRow('UE log Analysis', 'OK', CONST.ALL_PROCESSES_OK)
|
||||
myCmd2.close()
|
||||
if self.tsharkStarted:
|
||||
self.tsharkStarted = StopPySharkCapture(ymlPath[1])
|
||||
logging.debug('\u001B[1m Undeploying \u001B[0m')
|
||||
logging.debug(f'Working dir is back {self.yamlPath[0]}')
|
||||
cmd = 'docker-compose -f docker-compose-ci.yml down -v'
|
||||
deployStatus = myCmd.run(cmd, timeout=100)
|
||||
if deployStatus.returncode != 0:
|
||||
myCmd.close()
|
||||
self.exitStatus = 1
|
||||
logging.error('Could not undeploy')
|
||||
HTML.CreateHtmlTestRow('Could not undeploy', 'KO', CONST.ALL_PROCESSES_OK)
|
||||
logging.error('\u001B[1m Undeploying OAI Object(s) FAILED\u001B[0m')
|
||||
return
|
||||
|
||||
self.deployedContainers = []
|
||||
myCmd.close()
|
||||
|
||||
if fullStatus:
|
||||
HTML.CreateHtmlTestRow('n/a', 'OK', CONST.ALL_PROCESSES_OK)
|
||||
logging.info('\u001B[1m Undeploying OAI Object(s) PASS\u001B[0m')
|
||||
else:
|
||||
HTML.CreateHtmlTestRow('n/a', 'KO', CONST.ALL_PROCESSES_OK)
|
||||
logging.error('\u001B[1m Undeploying OAI Object(s) FAIL\u001B[0m')
|
||||
|
||||
def StatsFromGenObject(self, HTML):
|
||||
self.exitStatus = 0
|
||||
ymlPath = self.yamlPath[0].split('/')
|
||||
logPath = '../cmake_targets/log/' + ymlPath[1]
|
||||
|
||||
# if the containers are running, recover the logs!
|
||||
myCmd = cls_cmd.LocalCmd(d = self.yamlPath[0])
|
||||
cmd = 'docker-compose -f docker-compose-ci.yml ps --all'
|
||||
deployStatus = myCmd.run(cmd, timeout=30)
|
||||
cmd = 'docker stats --no-stream --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}" '
|
||||
anyLogs = False
|
||||
for state in deployStatus.stdout.split('\n'):
|
||||
res = re.search('Name|NAME|----------', state)
|
||||
if res is not None:
|
||||
continue
|
||||
if len(state) == 0:
|
||||
continue
|
||||
res = re.search('^(?P<container_name>[a-zA-Z0-9\-\_]+) ', state)
|
||||
if res is not None:
|
||||
anyLogs = True
|
||||
cmd += res.group('container_name') + ' '
|
||||
message = ''
|
||||
if anyLogs:
|
||||
stats = myCmd.run(cmd, timeout=30)
|
||||
for statLine in stats.stdout.split('\n'):
|
||||
logging.debug(statLine)
|
||||
message += statLine + '\n'
|
||||
myCmd.close()
|
||||
|
||||
HTML.CreateHtmlTestRowQueue(self.pingOptions, 'OK', [message])
|
||||
|
||||
def CheckAndAddRoute(self, svrName, ipAddr, userName, password):
|
||||
logging.debug('Checking IP routing on ' + svrName)
|
||||
|
||||
94
ci-scripts/cls_log_mgt.py
Normal file
94
ci-scripts/cls_log_mgt.py
Normal file
@@ -0,0 +1,94 @@
|
||||
# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
# * contributor license agreements. See the NOTICE file distributed with
|
||||
# * this work for additional information regarding copyright ownership.
|
||||
# * The OpenAirInterface Software Alliance licenses this file to You under
|
||||
# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698
|
||||
# *
|
||||
# * 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.
|
||||
# *-------------------------------------------------------------------------------
|
||||
# * For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
# * contact@openairinterface.org
|
||||
# */
|
||||
#---------------------------------------------------------------------
|
||||
#
|
||||
# Required Python Version
|
||||
# Python 3.x
|
||||
#
|
||||
#---------------------------------------------------------------------
|
||||
|
||||
#USAGE:
|
||||
# log=Log_Mgt(Username,IPAddress,Password,Path)
|
||||
# log.LogRotation()
|
||||
|
||||
|
||||
|
||||
import logging
|
||||
import re
|
||||
import subprocess
|
||||
import sshconnection
|
||||
|
||||
class Log_Mgt:
|
||||
|
||||
def __init__(self,Username, IPAddress,Password,Path):
|
||||
self.Username=Username
|
||||
self.IPAddress=IPAddress
|
||||
self.Password=Password
|
||||
self.path=Path
|
||||
|
||||
#-----------------$
|
||||
#PRIVATE# Methods$
|
||||
#-----------------$
|
||||
|
||||
|
||||
def __CheckUsedSpace(self):
|
||||
HOST=self.Username+'@'+self.IPAddress
|
||||
COMMAND="df "+ self.path
|
||||
ssh = subprocess.Popen(["ssh", "%s" % HOST, COMMAND],shell=False,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
|
||||
result = ssh.stdout.readlines()
|
||||
s=result[1].decode('utf-8').rstrip()#result[1] is the second line with the results we are looking for
|
||||
used=s.split()[4] #get 4th field ex: 70%
|
||||
m = re.match('^(\d+)\%',used)
|
||||
if m is not None:
|
||||
return int(m.group(1))
|
||||
|
||||
def __RemoveOldest(self, days):
|
||||
mySSH = sshconnection.SSHConnection()
|
||||
mySSH.open(self.IPAddress, self.Username, self.Password)
|
||||
COMMAND='echo ' + self.Password + ' | sudo -S find ' + self.path + ' -type f -mtime +' + str(days) + ' -delete'
|
||||
mySSH.command(COMMAND,'\$',20)
|
||||
mySSH.close()
|
||||
|
||||
|
||||
|
||||
#-----------------$
|
||||
#PUBLIC Methods$
|
||||
#-----------------$
|
||||
|
||||
|
||||
def LogRotation(self):
|
||||
doLoop = True
|
||||
nbDays = 14
|
||||
while doLoop and nbDays > 1:
|
||||
used_space = self.__CheckUsedSpace() #avail space in target folder
|
||||
if used_space > 80 :
|
||||
logging.debug('\u001B[1;37;41m Used Disk (' + str(used_space) + '%) > 80%, on ' + self.Username+'@'+self.IPAddress + '\u001B[0m')
|
||||
logging.debug('\u001B[1;37;41m Removing Artifacts older than ' + str(nbDays) + ' days \u001B[0m')
|
||||
self.__RemoveOldest(nbDays)
|
||||
nbDays -= 1
|
||||
else:
|
||||
logging.debug('Used Disk (' + str(used_space) + '%) < 80%, on ' + self.Username+'@'+self.IPAddress +', no cleaning required')
|
||||
doLoop = False
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -25,28 +25,30 @@
|
||||
#---------------------------------------------------------------------
|
||||
|
||||
#to use isfile
|
||||
import os
|
||||
import sys
|
||||
import logging
|
||||
#time.sleep
|
||||
import time
|
||||
import re
|
||||
import subprocess
|
||||
from datetime import datetime
|
||||
import yaml
|
||||
|
||||
#for log rotation mgt
|
||||
import cls_log_mgt
|
||||
import cls_cmd
|
||||
|
||||
class Module_UE:
|
||||
|
||||
def __init__(self, module_name, node=None, filename="ci_infra.yaml"):
|
||||
def __init__(self, module_name, filename="ci_infra.yaml"):
|
||||
with open(filename, 'r') as f:
|
||||
all_ues = yaml.load(f, Loader=yaml.FullLoader)
|
||||
m = all_ues.get(module_name)
|
||||
if m is None:
|
||||
raise Exception(f'no such module name "{module_name}" in "{filename}"')
|
||||
self.module_name = module_name
|
||||
self.host = m['Host'] if m['Host'] != "%%current_host%%" else None
|
||||
if node is None and self.host is None:
|
||||
raise Exception(f'node not provided when needed')
|
||||
elif node is not None and self.host is None:
|
||||
self.host = node
|
||||
self.host = m['Host']
|
||||
self.cmd_dict = {
|
||||
"attach": m.get('AttachScript'),
|
||||
"detach": m.get('DetachScript'),
|
||||
@@ -204,9 +206,35 @@ class Module_UE:
|
||||
|
||||
def _enableTrace(self):
|
||||
raise Exception("not implemented")
|
||||
mySSH = sshconnection.SSHConnection()
|
||||
mySSH.open(self.HostIPAddress, self.HostUsername, self.HostPassword)
|
||||
#delete old artifacts
|
||||
mySSH.command('echo ' + ' ' + ' | sudo -S rm -rf ci_qlog','\$',5)
|
||||
#start Trace, artifact is created in home dir
|
||||
mySSH.command('echo $USER; nohup sudo -E QLog/QLog -s ci_qlog -f NR5G.cfg > /dev/null 2>&1 &','\$', 5)
|
||||
mySSH.close()
|
||||
|
||||
def _disableTrace(self):
|
||||
raise Exception("not implemented")
|
||||
mySSH = sshconnection.SSHConnection()
|
||||
mySSH.open(self.HostIPAddress, self.HostUsername, self.HostPassword)
|
||||
mySSH.command('echo ' + ' ' + ' | sudo -S killall --signal=SIGINT *QLog*', '\$',5)
|
||||
mySSH.close()
|
||||
|
||||
|
||||
def _logCollect(self):
|
||||
raise Exception("not implemented")
|
||||
mySSH = sshconnection.SSHConnection()
|
||||
mySSH.open(self.HostIPAddress, self.HostUsername, self.HostPassword)
|
||||
#archive qlog to USB stick in /media/usb-drive/ci_qlogs with datetime suffix
|
||||
now=datetime.now()
|
||||
now_string = now.strftime("%Y%m%d-%H%M")
|
||||
source='ci_qlog'
|
||||
destination= self.LogStore + '/ci_qlog_'+now_string+'.zip'
|
||||
#qlog artifact is zipped into the target folder
|
||||
mySSH.command('echo $USER; echo ' + ' ' + ' | nohup sudo -S zip -r '+destination+' '+source+' > /dev/null 2>&1 &','\$', 10)
|
||||
mySSH.close()
|
||||
#post action : log cleaning to make sure enough space is reserved for the next run
|
||||
Log_Mgt=cls_log_mgt.Log_Mgt(self.HostUsername,self.HostIPAddress, self.HostPassword, self.LogStore)
|
||||
return destination
|
||||
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
#/*
|
||||
# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
# * contributor license agreements. See the NOTICE file distributed with
|
||||
# * this work for additional information regarding copyright ownership.
|
||||
# * The OpenAirInterface Software Alliance licenses this file to You under
|
||||
# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698
|
||||
# *
|
||||
# * 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.
|
||||
# *-------------------------------------------------------------------------------
|
||||
# * For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
# * contact@openairinterface.org
|
||||
# */
|
||||
#---------------------------------------------------------------------
|
||||
|
||||
import logging
|
||||
import re
|
||||
|
||||
import cls_cmd
|
||||
import cls_oai_html
|
||||
import constants as CONST
|
||||
|
||||
class Native():
|
||||
|
||||
def Build(test_case, HTML, host, directory, options):
|
||||
logging.debug(f'Building on server: {host}')
|
||||
HTML.testCase_id = test_case
|
||||
|
||||
with cls_cmd.getConnection(host) as ssh:
|
||||
base = f"{directory}/cmake_targets"
|
||||
ret = ssh.run(f"{base}/build_oai {options} > {base}/log/build_oai.log", timeout=900)
|
||||
success = ret.returncode == 0
|
||||
logs = ssh.run(f"cat {base}/log/build_oai.log", silent=True)
|
||||
logging.debug(f"build finished with code {ret.returncode}, output:\n{logs.stdout}")
|
||||
|
||||
# create log directory, and copy build logs
|
||||
target = f"{base}/build_log_{test_case}/"
|
||||
ssh.run(f"mkdir -p {target}")
|
||||
ssh.run(f"mv {base}/log/* {target}")
|
||||
|
||||
# check if build artifacts are there
|
||||
# NOTE: build_oai should fail with exit code if it could not build, but it does not
|
||||
build_dir = f"{base}/ran_build/build"
|
||||
build_gnb = re.search('--gNB', options) is not None
|
||||
if build_gnb:
|
||||
success = success and ssh.run(f"ls {build_dir}/nr-softmodem").returncode == 0
|
||||
build_enb = re.search('--eNB', options) is not None
|
||||
if build_enb:
|
||||
success = success and ssh.run(f"ls {build_dir}/lte-softmodem").returncode == 0
|
||||
|
||||
if success:
|
||||
logging.info('\u001B[1m Building OAI Pass\u001B[0m')
|
||||
HTML.CreateHtmlTestRow(options, 'OK', CONST.ALL_PROCESSES_OK)
|
||||
else:
|
||||
logging.error('\u001B[1m Building OAI Failed\u001B[0m')
|
||||
HTML.CreateHtmlTestRow(options, 'KO', CONST.ALL_PROCESSES_OK)
|
||||
return success
|
||||
@@ -31,12 +31,14 @@
|
||||
#-----------------------------------------------------------
|
||||
# Import
|
||||
#-----------------------------------------------------------
|
||||
import sys # arg
|
||||
import re # reg
|
||||
import fileinput
|
||||
import logging
|
||||
import os
|
||||
import time
|
||||
import subprocess
|
||||
from multiprocessing import Process, Lock, SimpleQueue
|
||||
|
||||
import constants as CONST
|
||||
|
||||
@@ -63,6 +65,10 @@ class HTMLManagement():
|
||||
self.htmlTabIcons = []
|
||||
self.testXMLfiles = []
|
||||
|
||||
self.testUnstable = False
|
||||
self.testMinStableId = '999999'
|
||||
self.testStabilityPointReached = False
|
||||
|
||||
self.htmleNBFailureMsg = ''
|
||||
self.htmlUEFailureMsg = ''
|
||||
|
||||
@@ -213,13 +219,20 @@ class HTMLManagement():
|
||||
|
||||
def CreateHtmlTabFooter(self, passStatus):
|
||||
if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)):
|
||||
testOkEvenIfUnstable = False
|
||||
if self.testUnstable and not passStatus:
|
||||
if self.testStabilityPointReached or self.testMinStableId == '999999':
|
||||
testOkEvenIfUnstable = True
|
||||
self.htmlFile = open('test_results.html', 'a')
|
||||
self.htmlFile.write(' <tr>\n')
|
||||
self.htmlFile.write(' <th bgcolor = "#33CCFF" colspan="3">Final Tab Status</th>\n')
|
||||
if passStatus:
|
||||
self.htmlFile.write(' <th bgcolor = "green" colspan="3"><font color="white">PASS <span class="glyphicon glyphicon-ok"></span> </font></th>\n')
|
||||
else:
|
||||
self.htmlFile.write(' <th bgcolor = "red" colspan="3"><font color="white">FAIL <span class="glyphicon glyphicon-remove"></span> </font></th>\n')
|
||||
if testOkEvenIfUnstable:
|
||||
self.htmlFile.write(' <th bgcolor = "orange" colspan="3"><font color="white">KNOWN UNSTABLE SCENARIO <span class="glyphicon glyphicon-exclamation-sign"></span> </font></th>\n')
|
||||
else:
|
||||
self.htmlFile.write(' <th bgcolor = "red" colspan="3"><font color="white">FAIL <span class="glyphicon glyphicon-remove"></span> </font></th>\n')
|
||||
self.htmlFile.write(' </tr>\n')
|
||||
self.htmlFile.write(' </table>\n')
|
||||
self.htmlFile.write(' </div>\n')
|
||||
@@ -229,7 +242,10 @@ class HTMLManagement():
|
||||
cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__//' test_results.html"
|
||||
subprocess.run(cmd, shell=True)
|
||||
else:
|
||||
cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__/<span class=\"glyphicon glyphicon-remove\"><\/span>/' test_results.html"
|
||||
if testOkEvenIfUnstable:
|
||||
cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__/<span class=\"glyphicon glyphicon-exclamation-sign\"><\/span>/' test_results.html"
|
||||
else:
|
||||
cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__/<span class=\"glyphicon glyphicon-remove\"><\/span>/' test_results.html"
|
||||
subprocess.run(cmd, shell=True)
|
||||
self.htmlFooterCreated = False
|
||||
|
||||
@@ -263,6 +279,14 @@ class HTMLManagement():
|
||||
self.htmlFile.write('</html>\n')
|
||||
self.htmlFile.close()
|
||||
|
||||
def CreateHtmlRetrySeparator(self, cntnumfails):
|
||||
if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)):
|
||||
self.htmlFile = open('test_results.html', 'a')
|
||||
self.htmlFile.write(' <tr bgcolor = "#F0F0F0" >\n')
|
||||
self.htmlFile.write(' <td colspan="6"><b> ---- Try Run #' + str(cntnumfails) + ' ---- </b></td>\n')
|
||||
self.htmlFile.write(' </tr>\n')
|
||||
self.htmlFile.close()
|
||||
|
||||
def CreateHtmlTestRow(self, options, status, processesStatus, machine='eNB'):
|
||||
if (self.htmlFooterCreated or (not self.htmlHeaderCreated)):
|
||||
return
|
||||
@@ -444,8 +468,6 @@ class HTMLManagement():
|
||||
self.htmlFile.write(f' <td bgcolor = "lightgreen" >{status}</td>\n')
|
||||
elif (str(status) == 'KO'):
|
||||
self.htmlFile.write(f' <td bgcolor = "lightcoral" >{status}</td>\n')
|
||||
elif str(status) == 'SKIP':
|
||||
self.htmlFile.write(f' <td bgcolor = "lightgray" >{status}</td>\n')
|
||||
else:
|
||||
addOrangeBK = True
|
||||
self.htmlFile.write(f' <td bgcolor = "orange" >{status}</td>\n')
|
||||
|
||||
@@ -34,20 +34,32 @@
|
||||
#-----------------------------------------------------------
|
||||
import sys # arg
|
||||
import re # reg
|
||||
import pexpect # pexpect
|
||||
import time # sleep
|
||||
import os
|
||||
import subprocess
|
||||
import xml.etree.ElementTree as ET
|
||||
import logging
|
||||
import datetime
|
||||
import signal
|
||||
import statistics as stat
|
||||
from multiprocessing import SimpleQueue, Lock
|
||||
import concurrent.futures
|
||||
import json
|
||||
|
||||
#import our libs
|
||||
import helpreadme as HELP
|
||||
import constants as CONST
|
||||
import cls_cluster as OC
|
||||
import sshconnection
|
||||
|
||||
import cls_module
|
||||
import cls_cmd
|
||||
|
||||
logging.getLogger("matplotlib").setLevel(logging.WARNING)
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
|
||||
#-----------------------------------------------------------
|
||||
# Helper functions used here and in other classes
|
||||
#-----------------------------------------------------------
|
||||
@@ -138,8 +150,8 @@ def Iperf_analyzeV3UDP(filename, iperf_bitrate_threshold, iperf_packetloss_thres
|
||||
receiver_bitrate = None
|
||||
with open(filename, 'r') as server_file:
|
||||
for line in server_file.readlines():
|
||||
res_sender = re.search(r'(?P<bitrate>[0-9\.]+)\s+(?P<unit>[KMG]?bits\/sec)\s+(?P<jitter>[0-9\.]+\s+ms)\s+(?P<lostPack>-?\d+)/(?P<sentPack>-?\d+) \((?P<lost>[0-9\.]+).*?\s+(sender)', line)
|
||||
res_receiver = re.search(r'(?P<bitrate>[0-9\.]+)\s+(?P<unit>[KMG]?bits\/sec)\s+(?P<jitter>[0-9\.]+\s+ms)\s+(?P<lostPack>-?\d+)/(?P<receivedPack>-?\d+)\s+\((?P<lost>[0-9\.]+)%\).*?(receiver)', line)
|
||||
res_sender = re.search(r'(?P<bitrate>[0-9\.]+)\s+(?P<unit>[KMG]bits\/sec)\s+(?P<jitter>[0-9\.]+\s+ms)\s+(?P<lostPack>\d+)/(?P<sentPack>\d+) \((?P<lost>[0-9\.]+).*?\s+(sender)', line)
|
||||
res_receiver = re.search(r'(?P<bitrate>[0-9\.]+)\s+(?P<unit>[KMG]bits\/sec)\s+(?P<jitter>[0-9\.]+\s+ms)\s+(?P<lostPack>\d+)/(?P<receivedPack>\d+) \((?P<lost>[0-9\.]+).*?\s+(receiver)', line)
|
||||
if res_sender is not None:
|
||||
sender_bitrate = res_sender.group('bitrate')
|
||||
sender_unit = res_sender.group('unit')
|
||||
@@ -214,43 +226,6 @@ def Iperf_analyzeV2UDP(server_filename, iperf_bitrate_threshold, iperf_packetlos
|
||||
pal_msg += f' (too high! >{self.iperf_packetloss_threshold}%)'
|
||||
return (result, f'{req_msg}\n{bir_msg}\n{brl_msg}\n{jit_msg}\n{pal_msg}')
|
||||
|
||||
def Custom_Command(HTML, node, command, command_fail):
|
||||
logging.info(f"Executing custom command on {node}")
|
||||
cmd = cls_cmd.getConnection(node)
|
||||
ret = cmd.run(command)
|
||||
cmd.close()
|
||||
logging.debug(f"Custom_Command: {command} on node: {node} - {'OK, command succeeded' if ret.returncode == 0 else f'Error, return code: {ret.returncode}'}")
|
||||
status = 'OK'
|
||||
message = []
|
||||
if ret.returncode != 0 and not command_fail:
|
||||
message = [ret.stdout]
|
||||
logging.warning(f'Custom_Command output: {message}')
|
||||
status = 'Warning'
|
||||
if ret.returncode != 0 and command_fail:
|
||||
message = [ret.stdout]
|
||||
logging.error(f'Custom_Command failed: output: {message}')
|
||||
status = 'KO'
|
||||
HTML.CreateHtmlTestRowQueue(command, status, message)
|
||||
return status == 'OK' or status == 'Warning'
|
||||
|
||||
def Custom_Script(HTML, node, script, command_fail):
|
||||
logging.info(f"Executing custom script on {node}")
|
||||
ret = cls_cmd.runScript(node, script, 90)
|
||||
logging.debug(f"Custom_Script: {script} on node: {node} - return code {ret.returncode}, output:\n{ret.stdout}")
|
||||
status = 'OK'
|
||||
message = [ret.stdout]
|
||||
if ret.returncode != 0 and not command_fail:
|
||||
status = 'Warning'
|
||||
if ret.returncode != 0 and command_fail:
|
||||
status = 'KO'
|
||||
HTML.CreateHtmlTestRowQueue(script, status, message)
|
||||
return status == 'OK' or status == 'Warning'
|
||||
|
||||
def IdleSleep(HTML, idle_sleep_time):
|
||||
time.sleep(idle_sleep_time)
|
||||
HTML.CreateHtmlTestRow(f"{idle_sleep_time} sec", 'OK', CONST.ALL_PROCESSES_OK)
|
||||
return True
|
||||
|
||||
#-----------------------------------------------------------
|
||||
# OaiCiTest Class Definition
|
||||
#-----------------------------------------------------------
|
||||
@@ -263,8 +238,12 @@ class OaiCiTest():
|
||||
self.ranAllowMerge = False
|
||||
self.ranTargetBranch = ''
|
||||
|
||||
self.FailReportCnt = 0
|
||||
self.testCase_id = ''
|
||||
self.testXMLfiles = []
|
||||
self.testUnstable = False
|
||||
self.testMinStableId = '999999'
|
||||
self.testStabilityPointReached = False
|
||||
self.desc = ''
|
||||
self.ping_args = ''
|
||||
self.ping_packetloss_threshold = ''
|
||||
@@ -275,96 +254,415 @@ class OaiCiTest():
|
||||
self.iperf_profile = ''
|
||||
self.iperf_options = ''
|
||||
self.iperf_tcp_rate_target = ''
|
||||
self.nbMaxUEtoAttach = -1
|
||||
self.UEDevices = []
|
||||
self.UEDevicesStatus = []
|
||||
self.UEDevicesRemoteServer = []
|
||||
self.UEDevicesRemoteUser = []
|
||||
self.UEDevicesOffCmd = []
|
||||
self.UEDevicesOnCmd = []
|
||||
self.UEDevicesRebootCmd = []
|
||||
self.idle_sleep_time = 0
|
||||
self.x2_ho_options = 'network'
|
||||
self.x2NbENBs = 0
|
||||
self.x2ENBBsIds = []
|
||||
self.x2ENBConnectedUEs = []
|
||||
self.repeatCounts = []
|
||||
self.finalStatus = False
|
||||
self.UEIPAddress = ''
|
||||
self.UEUserName = ''
|
||||
self.UEPassword = ''
|
||||
self.UE_instance = 0
|
||||
self.UESourceCodePath = ''
|
||||
self.UELogFile = ''
|
||||
self.Build_OAI_UE_args = ''
|
||||
self.Initialize_OAI_UE_args = ''
|
||||
self.clean_repository = True
|
||||
self.air_interface=''
|
||||
self.ue_ids = []
|
||||
self.nodes = []
|
||||
self.svr_node = None
|
||||
self.svr_id = None
|
||||
self.cmd_prefix = '' # prefix before {lte,nr}-uesoftmodem
|
||||
|
||||
|
||||
def BuildOAIUE(self,HTML):
|
||||
if self.UEIPAddress == '' or self.ranRepository == '' or self.ranBranch == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '':
|
||||
HELP.GenericHelp(CONST.Version)
|
||||
sys.exit('Insufficient Parameter')
|
||||
SSH = sshconnection.SSHConnection()
|
||||
SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword)
|
||||
result = re.search('--nrUE', self.Build_OAI_UE_args)
|
||||
if result is not None:
|
||||
self.air_interface='nr-uesoftmodem'
|
||||
ue_prefix = 'NR '
|
||||
else:
|
||||
self.air_interface='lte-uesoftmodem'
|
||||
ue_prefix = ''
|
||||
result = re.search('([a-zA-Z0-9\:\-\.\/])+\.git', self.ranRepository)
|
||||
if result is not None:
|
||||
full_ran_repo_name = self.ranRepository.replace('git/', 'git')
|
||||
else:
|
||||
full_ran_repo_name = self.ranRepository + '.git'
|
||||
SSH.command(f'mkdir -p {self.UESourceCodePath}', '\$', 5)
|
||||
SSH.command(f'cd {self.UESourceCodePath}', '\$', 5)
|
||||
SSH.command(f'if [ ! -e .git ]; then stdbuf -o0 git clone {full_ran_repo_name} .; else stdbuf -o0 git fetch --prune; fi', '\$', 600)
|
||||
# here add a check if git clone or git fetch went smoothly
|
||||
SSH.command('git config user.email "jenkins@openairinterface.org"', '\$', 5)
|
||||
SSH.command('git config user.name "OAI Jenkins"', '\$', 5)
|
||||
if self.clean_repository:
|
||||
SSH.command('ls *.txt', '\$', 5)
|
||||
result = re.search('LAST_BUILD_INFO', SSH.getBefore())
|
||||
if result is not None:
|
||||
mismatch = False
|
||||
SSH.command('grep --colour=never SRC_COMMIT LAST_BUILD_INFO.txt', '\$', 2)
|
||||
result = re.search(self.ranCommitID, SSH.getBefore())
|
||||
if result is None:
|
||||
mismatch = True
|
||||
SSH.command('grep --colour=never MERGED_W_TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2)
|
||||
if self.ranAllowMerge:
|
||||
result = re.search('YES', SSH.getBefore())
|
||||
if result is None:
|
||||
mismatch = True
|
||||
SSH.command('grep --colour=never TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2)
|
||||
if self.ranTargetBranch == '':
|
||||
result = re.search('develop', SSH.getBefore())
|
||||
else:
|
||||
result = re.search(self.ranTargetBranch, SSH.getBefore())
|
||||
if result is None:
|
||||
mismatch = True
|
||||
else:
|
||||
result = re.search('NO', SSH.getBefore())
|
||||
if result is None:
|
||||
mismatch = True
|
||||
if not mismatch:
|
||||
SSH.close()
|
||||
HTML.CreateHtmlTestRow(self.Build_OAI_UE_args, 'OK', CONST.ALL_PROCESSES_OK)
|
||||
return
|
||||
|
||||
SSH.command(f'echo {self.UEPassword} | sudo -S git clean -x -d -ff', '\$', 30)
|
||||
|
||||
# if the commit ID is provided use it to point to it
|
||||
if self.ranCommitID != '':
|
||||
SSH.command(f'git checkout -f {self.ranCommitID}', '\$', 30)
|
||||
# if the branch is not develop, then it is a merge request and we need to do
|
||||
# the potential merge. Note that merge conflicts should already been checked earlier
|
||||
if self.ranAllowMerge:
|
||||
if self.ranTargetBranch == '':
|
||||
if (self.ranBranch != 'develop') and (self.ranBranch != 'origin/develop'):
|
||||
SSH.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 30)
|
||||
else:
|
||||
logging.debug(f'Merging with the target branch: {self.ranTargetBranch}')
|
||||
SSH.command(f'git merge --ff origin/{self.ranTargetBranch} -m "Temporary merge for CI"', '\$', 30)
|
||||
SSH.command('source oaienv', '\$', 5)
|
||||
SSH.command('cd cmake_targets', '\$', 5)
|
||||
SSH.command('mkdir -p log', '\$', 5)
|
||||
SSH.command('chmod 777 log', '\$', 5)
|
||||
# no need to remove in log (git clean did the trick)
|
||||
SSH.command(f'stdbuf -o0 ./build_oai {self.Build_OAI_UE_args} 2>&1 | stdbuf -o0 tee compile_oai_ue.log', 'Bypassing the Tests|build have failed', 1200)
|
||||
SSH.command('ls ran_build/build', '\$', 3)
|
||||
SSH.command('ls ran_build/build', '\$', 3)
|
||||
buildStatus = True
|
||||
result = re.search(self.air_interface, SSH.getBefore())
|
||||
if result is None:
|
||||
buildStatus = False
|
||||
SSH.command(f'mkdir -p build_log_{self.testCase_id}', '\$', 5)
|
||||
SSH.command(f'mv log/* build_log_{self.testCase_id}', '\$', 5)
|
||||
SSH.command(f'mv compile_oai_ue.log build_log_{self.testCase_id}', '\$', 5)
|
||||
if buildStatus:
|
||||
# Generating a BUILD INFO file
|
||||
SSH.command(f'echo "SRC_BRANCH: {self.ranBranch}" > ../LAST_BUILD_INFO.txt', '\$', 2)
|
||||
SSH.command(f'echo "SRC_COMMIT: {self.ranCommitID}" >> ../LAST_BUILD_INFO.txt', '\$', 2)
|
||||
if self.ranAllowMerge:
|
||||
SSH.command('echo "MERGED_W_TGT_BRANCH: YES" >> ../LAST_BUILD_INFO.txt', '\$', 2)
|
||||
if self.ranTargetBranch == '':
|
||||
SSH.command('echo "TGT_BRANCH: develop" >> ../LAST_BUILD_INFO.txt', '\$', 2)
|
||||
else:
|
||||
SSH.command(f'echo "TGT_BRANCH: {self.ranTargetBranch}" >> ../LAST_BUILD_INFO.txt', '\$', 2)
|
||||
else:
|
||||
SSH.command('echo "MERGED_W_TGT_BRANCH: NO" >> ../LAST_BUILD_INFO.txt', '\$', 2)
|
||||
SSH.close()
|
||||
HTML.CreateHtmlTestRow(self.Build_OAI_UE_args, 'OK', CONST.ALL_PROCESSES_OK, 'OAI UE')
|
||||
else:
|
||||
SSH.close()
|
||||
logging.error('\u001B[1m Building OAI UE Failed\u001B[0m')
|
||||
HTML.CreateHtmlTestRow(self.Build_OAI_UE_args, 'KO', CONST.ALL_PROCESSES_OK, 'OAI UE')
|
||||
HTML.CreateHtmlTabFooter(False)
|
||||
self.ConditionalExit()
|
||||
|
||||
|
||||
def InitializeUE(self, HTML):
|
||||
ues = [cls_module.Module_UE(n.strip()) for n in self.ue_ids]
|
||||
messages = []
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor:
|
||||
with concurrent.futures.ThreadPoolExecutor() as executor:
|
||||
futures = [executor.submit(ue.initialize) for ue in ues]
|
||||
for f, ue in zip(futures, ues):
|
||||
uename = f'UE {ue.getName()}'
|
||||
messages.append(f'{uename}: initialized' if f.result() else f'{uename}: ERROR during Initialization')
|
||||
[f.result() for f in futures]
|
||||
HTML.CreateHtmlTestRowQueue('N/A', 'OK', messages)
|
||||
return True
|
||||
|
||||
def AttachUE(self, HTML):
|
||||
ues = [cls_module.Module_UE(ue_id, server_name) for ue_id, server_name in zip(self.ue_ids, self.nodes)]
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor:
|
||||
def InitializeOAIUE(self,HTML,RAN,EPC,CONTAINERS):
|
||||
if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '':
|
||||
HELP.GenericHelp(CONST.Version)
|
||||
sys.exit('Insufficient Parameter')
|
||||
|
||||
|
||||
if self.air_interface == 'lte-uesoftmodem':
|
||||
result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args))
|
||||
if result is None:
|
||||
check_eNB = True
|
||||
check_OAI_UE = False
|
||||
UE_prefix = ''
|
||||
else:
|
||||
UE_prefix = 'NR '
|
||||
SSH = sshconnection.SSHConnection()
|
||||
SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword)
|
||||
SSH.command(f'cd {self.UESourceCodePath}', '\$', 5)
|
||||
# Initialize_OAI_UE_args usually start with -C and followed by the location in repository
|
||||
SSH.command('source oaienv', '\$', 5)
|
||||
SSH.command('cd cmake_targets/ran_build/build', '\$', 5)
|
||||
if self.air_interface == 'lte-uesoftmodem':
|
||||
result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args))
|
||||
# We may have to regenerate the .u* files
|
||||
if result is None:
|
||||
SSH.command('ls /tmp/*.sed', '\$', 5)
|
||||
result = re.search('adapt_usim_parameters', SSH.getBefore())
|
||||
if result is not None:
|
||||
SSH.command('sed -f /tmp/adapt_usim_parameters.sed ../../../openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf > ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf', '\$', 5)
|
||||
else:
|
||||
SSH.command('sed -e "s#93#92#" -e "s#8baf473f2f8fd09487cccbd7097c6862#fec86ba6eb707ed08905757b1bb44b8f#" -e "s#e734f8734007d6c5ce7a0508809e7e9c#C42449363BBAD02B66D16BC975D77CC1#" ../../../openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf > ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf', '\$', 5)
|
||||
SSH.command(f'echo {self.UEPassword} | sudo -S rm -Rf .u*', '\$', 5)
|
||||
SSH.command(f'echo {self.UEPassword} | sudo -S ../../nas_sim_tools/build/conf2uedata -c ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf -o .', '\$', 5)
|
||||
else:
|
||||
SSH.command(f'if [ -e rbconfig.raw ]; then echo {self.UEPassword} | sudo -S rm rbconfig.raw; fi', '\$', 5)
|
||||
SSH.command(f'if [ -e reconfig.raw ]; then echo {self.UEPassword} | sudo -S rm reconfig.raw; fi', '\$', 5)
|
||||
# Copy the RAW files from gNB running directory (maybe on another machine)
|
||||
copyin_res = SSH.copyin(RAN.eNBIPAddress, RAN.eNBUserName, RAN.eNBPassword, RAN.eNBSourceCodePath + '/cmake_targets/rbconfig.raw', '.')
|
||||
if (copyin_res == 0):
|
||||
SSH.copyout(self.UEIPAddress, self.UEUserName, self.UEPassword, './rbconfig.raw', self.UESourceCodePath + '/cmake_targets/ran_build/build')
|
||||
copyin_res = SSH.copyin(RAN.eNBIPAddress, RAN.eNBUserName, RAN.eNBPassword, RAN.eNBSourceCodePath + '/cmake_targets/reconfig.raw', '.')
|
||||
if (copyin_res == 0):
|
||||
SSH.copyout(self.UEIPAddress, self.UEUserName, self.UEPassword, './reconfig.raw', self.UESourceCodePath + '/cmake_targets/ran_build/build')
|
||||
SSH.command(f'echo "ulimit -c unlimited && {self.cmd_prefix} ./{self.air_interface} {self.Initialize_OAI_UE_args}" > ./my-lte-uesoftmodem-run{self.UE_instance}.sh', '\$', 5)
|
||||
SSH.command(f'chmod 775 ./my-lte-uesoftmodem-run {self.UE_instance}.sh', '\$', 5)
|
||||
SSH.command(f'echo {self.UEPassword} | sudo -S rm -Rf {self.UESourceCodePath}/cmake_targets/ue_{self.testCase_id}.log', '\$', 5)
|
||||
self.UELogFile = f'ue_{self.testCase_id}.log'
|
||||
|
||||
# We are now looping several times to hope we really sync w/ an eNB
|
||||
doOutterLoop = True
|
||||
outterLoopCounter = 5
|
||||
gotSyncStatus = True
|
||||
fullSyncStatus = True
|
||||
while (doOutterLoop):
|
||||
SSH.command(f'cd {self.UESourceCodePath}/cmake_targets/ran_build/build', '\$', 5)
|
||||
SSH.command(f'echo {self.UEPassword} | sudo -S rm -Rf {self.UESourceCodePath}/cmake_targets/ue_{self.testCase_id}.log', '\$', 5)
|
||||
SSH.command(f'echo $USER; nohup sudo -E stdbuf -o0 ./my-lte-uesoftmodem-run {self.UE_instance}.sh > {self.UESourceCodePath}/cmake_targets/ue_{self.testCase_id}.log 2>&1 &', self.UEUserName, 5)
|
||||
time.sleep(6)
|
||||
SSH.command('cd ../..', '\$', 5)
|
||||
doLoop = True
|
||||
loopCounter = 10
|
||||
gotSyncStatus = True
|
||||
# the 'got sync' message is for the UE threads synchronization
|
||||
while (doLoop):
|
||||
loopCounter = loopCounter - 1
|
||||
if (loopCounter == 0):
|
||||
# Here should never occur
|
||||
logging.error('"got sync" message never showed!')
|
||||
gotSyncStatus = False
|
||||
doLoop = False
|
||||
continue
|
||||
SSH.command(f'stdbuf -o0 cat ue_{self.testCase_id}.log | egrep --text --color=never -i "wait|sync"', '\$', 4)
|
||||
if self.air_interface == 'nr-uesoftmodem':
|
||||
result = re.search('Starting sync detection', SSH.getBefore())
|
||||
else:
|
||||
result = re.search('got sync', SSH.getBefore())
|
||||
if result is None:
|
||||
time.sleep(10)
|
||||
else:
|
||||
doLoop = False
|
||||
logging.debug('Found "got sync" message!')
|
||||
if gotSyncStatus == False:
|
||||
# we certainly need to stop the lte-uesoftmodem process if it is still running!
|
||||
SSH.command('ps -aux | grep --text --color=never softmodem | grep -v grep', '\$', 4)
|
||||
result = re.search('-uesoftmodem', SSH.getBefore())
|
||||
if result is not None:
|
||||
SSH.command(f'echo {self.UEPassword} | sudo -S killall --signal=SIGINT -r *-uesoftmodem', '\$', 4)
|
||||
time.sleep(3)
|
||||
outterLoopCounter = outterLoopCounter - 1
|
||||
if (outterLoopCounter == 0):
|
||||
doOutterLoop = False
|
||||
continue
|
||||
# We are now checking if sync w/ eNB DOES NOT OCCUR
|
||||
# Usually during the cell synchronization stage, the UE returns with No cell synchronization message
|
||||
# That is the case for LTE
|
||||
# In NR case, it's a positive message that will show if synchronization occurs
|
||||
doLoop = True
|
||||
if self.air_interface == 'nr-uesoftmodem':
|
||||
loopCounter = 10
|
||||
else:
|
||||
# We are now checking if sync w/ eNB DOES NOT OCCUR
|
||||
# Usually during the cell synchronization stage, the UE returns with No cell synchronization message
|
||||
loopCounter = 10
|
||||
while (doLoop):
|
||||
loopCounter = loopCounter - 1
|
||||
if (loopCounter == 0):
|
||||
if self.air_interface == 'nr-uesoftmodem':
|
||||
# Here we do have great chances that UE did NOT cell-sync w/ gNB
|
||||
doLoop = False
|
||||
fullSyncStatus = False
|
||||
logging.debug('Never seen the NR-Sync message (Measured Carrier Frequency) --> try again')
|
||||
time.sleep(6)
|
||||
# Stopping the NR-UE
|
||||
SSH.command('ps -aux | grep --text --color=never softmodem | grep -v grep', '\$', 4)
|
||||
result = re.search('nr-uesoftmodem', SSH.getBefore())
|
||||
if result is not None:
|
||||
SSH.command(f'echo {self.UEPassword} | sudo -S killall --signal=SIGINT nr-uesoftmodem', '\$', 4)
|
||||
time.sleep(6)
|
||||
else:
|
||||
# Here we do have a great chance that the UE did cell-sync w/ eNB
|
||||
doLoop = False
|
||||
doOutterLoop = False
|
||||
fullSyncStatus = True
|
||||
continue
|
||||
SSH.command(f'stdbuf -o0 cat ue_{self.testCase_id}.log | egrep --text --color=never -i "wait|sync|Frequency"', '\$', 4)
|
||||
if self.air_interface == 'nr-uesoftmodem':
|
||||
# Positive messaging -->
|
||||
result = re.search('Measured Carrier Frequency', SSH.getBefore())
|
||||
if result is not None:
|
||||
doLoop = False
|
||||
doOutterLoop = False
|
||||
fullSyncStatus = True
|
||||
else:
|
||||
time.sleep(6)
|
||||
else:
|
||||
# Negative messaging -->
|
||||
result = re.search('No cell synchronization found', SSH.getBefore())
|
||||
if result is None:
|
||||
time.sleep(6)
|
||||
else:
|
||||
doLoop = False
|
||||
fullSyncStatus = False
|
||||
logging.debug('Found: "No cell synchronization" message! --> try again')
|
||||
time.sleep(6)
|
||||
SSH.command('ps -aux | grep --text --color=never softmodem | grep -v grep', '\$', 4)
|
||||
result = re.search('lte-uesoftmodem', SSH.getBefore())
|
||||
if result is not None:
|
||||
SSH.command(f'echo {self.UEPassword} | sudo -S killall --signal=SIGINT lte-uesoftmodem', '\$', 4)
|
||||
outterLoopCounter = outterLoopCounter - 1
|
||||
if (outterLoopCounter == 0):
|
||||
doOutterLoop = False
|
||||
|
||||
if fullSyncStatus and gotSyncStatus:
|
||||
doInterfaceCheck = False
|
||||
if self.air_interface == 'lte-uesoftmodem':
|
||||
result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args))
|
||||
if result is None:
|
||||
doInterfaceCheck = True
|
||||
# For the moment, only in explicit noS1 without kernel module (ie w/ tunnel interface)
|
||||
if self.air_interface == 'nr-uesoftmodem':
|
||||
result = re.search('--noS1', str(self.Initialize_OAI_UE_args))
|
||||
if result is not None:
|
||||
doInterfaceCheck = True
|
||||
if doInterfaceCheck:
|
||||
SSH.command('ifconfig oaitun_ue1', '\$', 4)
|
||||
SSH.command('ifconfig oaitun_ue1', '\$', 4)
|
||||
# ifconfig output is different between ubuntu 16 and ubuntu 18
|
||||
result = re.search('inet addr:[0-9]|inet [0-9]', SSH.getBefore())
|
||||
if result is not None:
|
||||
logging.debug('\u001B[1m oaitun_ue1 interface is mounted and configured\u001B[0m')
|
||||
tunnelInterfaceStatus = True
|
||||
else:
|
||||
logging.debug(SSH.getBefore())
|
||||
logging.error('\u001B[1m oaitun_ue1 interface is either NOT mounted or NOT configured\u001B[0m')
|
||||
tunnelInterfaceStatus = False
|
||||
if RAN.eNBmbmsEnables[0]:
|
||||
SSH.command('ifconfig oaitun_uem1', '\$', 4)
|
||||
result = re.search('inet addr', SSH.getBefore())
|
||||
if result is not None:
|
||||
logging.debug('\u001B[1m oaitun_uem1 interface is mounted and configured\u001B[0m')
|
||||
tunnelInterfaceStatus = tunnelInterfaceStatus and True
|
||||
else:
|
||||
logging.error('\u001B[1m oaitun_uem1 interface is either NOT mounted or NOT configured\u001B[0m')
|
||||
tunnelInterfaceStatus = False
|
||||
else:
|
||||
tunnelInterfaceStatus = True
|
||||
else:
|
||||
tunnelInterfaceStatus = True
|
||||
|
||||
SSH.close()
|
||||
if fullSyncStatus and gotSyncStatus and tunnelInterfaceStatus:
|
||||
HTML.CreateHtmlTestRow(self.air_interface + ' ' + self.Initialize_OAI_UE_args, 'OK', CONST.ALL_PROCESSES_OK, 'OAI UE')
|
||||
logging.debug('\u001B[1m Initialize OAI UE Completed\u001B[0m')
|
||||
else:
|
||||
if self.air_interface == 'lte-uesoftmodem':
|
||||
if RAN.eNBmbmsEnables[0]:
|
||||
HTML.htmlUEFailureMsg='oaitun_ue1/oaitun_uem1 interfaces are either NOT mounted or NOT configured'
|
||||
else:
|
||||
HTML.htmlUEFailureMsg='oaitun_ue1 interface is either NOT mounted or NOT configured'
|
||||
HTML.CreateHtmlTestRow(self.air_interface + ' ' + self.Initialize_OAI_UE_args, 'KO', CONST.OAI_UE_PROCESS_NO_TUNNEL_INTERFACE, 'OAI UE')
|
||||
else:
|
||||
HTML.htmlUEFailureMsg='nr-uesoftmodem did NOT synced'
|
||||
HTML.CreateHtmlTestRow(self.air_interface + ' ' + self.Initialize_OAI_UE_args, 'KO', CONST.OAI_UE_PROCESS_COULD_NOT_SYNC, 'OAI UE')
|
||||
logging.error('\033[91mInitialize OAI UE Failed! \033[0m')
|
||||
self.AutoTerminateUEandeNB(HTML,RAN,EPC,CONTAINERS)
|
||||
|
||||
def AttachUE(self, HTML, RAN, EPC, CONTAINERS):
|
||||
ues = [cls_module.Module_UE(n.strip()) for n in self.ue_ids]
|
||||
with concurrent.futures.ThreadPoolExecutor() as executor:
|
||||
futures = [executor.submit(ue.attach) for ue in ues]
|
||||
attached = [f.result() for f in futures]
|
||||
futures = [executor.submit(ue.checkMTU) for ue in ues]
|
||||
mtus = [f.result() for f in futures]
|
||||
messages = [f"UE {ue.getName()}: {ue.getIP()}" for ue in ues]
|
||||
success = all(attached) and all(mtus)
|
||||
if success:
|
||||
if all(attached) and all(mtus):
|
||||
HTML.CreateHtmlTestRowQueue('N/A', 'OK', messages)
|
||||
else:
|
||||
logging.error(f'error attaching or wrong MTU: attached {attached}, mtus {mtus}')
|
||||
HTML.CreateHtmlTestRowQueue('N/A', 'KO', ["Could not retrieve UE IP address(es) or MTU(s) wrong!"])
|
||||
return success
|
||||
self.AutoTerminateUEandeNB(HTML, RAN, EPC, CONTAINERS)
|
||||
|
||||
def DetachUE(self, HTML):
|
||||
ues = [cls_module.Module_UE(ue_id, server_name) for ue_id, server_name in zip(self.ue_ids, self.nodes)]
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor:
|
||||
ues = [cls_module.Module_UE(n.strip()) for n in self.ue_ids]
|
||||
with concurrent.futures.ThreadPoolExecutor() as executor:
|
||||
futures = [executor.submit(ue.detach) for ue in ues]
|
||||
[f.result() for f in futures]
|
||||
messages = [f"UE {ue.getName()}: detached" for ue in ues]
|
||||
HTML.CreateHtmlTestRowQueue('NA', 'OK', messages)
|
||||
return True
|
||||
|
||||
def DataDisableUE(self, HTML):
|
||||
ues = [cls_module.Module_UE(n.strip()) for n in self.ue_ids]
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor:
|
||||
with concurrent.futures.ThreadPoolExecutor() as executor:
|
||||
futures = [executor.submit(ue.dataDisable) for ue in ues]
|
||||
status = [f.result() for f in futures]
|
||||
success = all(status)
|
||||
if success:
|
||||
if all(status):
|
||||
messages = [f"UE {ue.getName()}: data disabled" for ue in ues]
|
||||
HTML.CreateHtmlTestRowQueue('NA', 'OK', messages)
|
||||
else:
|
||||
logging.error(f'error enabling data: {status}')
|
||||
HTML.CreateHtmlTestRowQueue('N/A', 'KO', ["Could not disable UE data!"])
|
||||
return success
|
||||
|
||||
def DataEnableUE(self, HTML):
|
||||
ues = [cls_module.Module_UE(n.strip()) for n in self.ue_ids]
|
||||
logging.debug(f'disabling data for UEs {ues}')
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor:
|
||||
with concurrent.futures.ThreadPoolExecutor() as executor:
|
||||
futures = [executor.submit(ue.dataEnable) for ue in ues]
|
||||
status = [f.result() for f in futures]
|
||||
success = all(status)
|
||||
if success:
|
||||
if all(status):
|
||||
messages = [f"UE {ue.getName()}: data enabled" for ue in ues]
|
||||
HTML.CreateHtmlTestRowQueue('NA', 'OK', messages)
|
||||
else:
|
||||
logging.error(f'error enabling data: {status}')
|
||||
HTML.CreateHtmlTestRowQueue('N/A', 'KO', ["Could not enable UE data!"])
|
||||
return success
|
||||
|
||||
def CheckStatusUE(self,HTML):
|
||||
ues = [cls_module.Module_UE(n.strip()) for n in self.ue_ids]
|
||||
logging.debug(f'checking status of UEs {ues}')
|
||||
messages = []
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor:
|
||||
with concurrent.futures.ThreadPoolExecutor() as executor:
|
||||
futures = [executor.submit(ue.check) for ue in ues]
|
||||
messages = [f.result() for f in futures]
|
||||
HTML.CreateHtmlTestRowQueue('NA', 'OK', messages)
|
||||
return True
|
||||
|
||||
def Ping_common(self, EPC, ue, logPath):
|
||||
def Ping_common(self, EPC, ue, RAN, printLock):
|
||||
# Launch ping on the EPC side (true for ltebox and old open-air-cn)
|
||||
ping_status = 0
|
||||
ueIP = ue.getIP()
|
||||
@@ -372,7 +670,7 @@ class OaiCiTest():
|
||||
return (False, f"UE {ue.getName()} has no IP address")
|
||||
ping_log_file = f'ping_{self.testCase_id}_{ue.getName()}.log'
|
||||
ping_time = re.findall("-c *(\d+)",str(self.ping_args))
|
||||
local_ping_log_file = f'{logPath}/{ping_log_file}'
|
||||
local_ping_log_file = f'{os.getcwd()}/{ping_log_file}'
|
||||
# if has pattern %cn_ip%, replace with core IP address, else we assume the IP is present
|
||||
if re.search('%cn_ip%', self.ping_args):
|
||||
#target address is different depending on EPC type
|
||||
@@ -392,6 +690,7 @@ class OaiCiTest():
|
||||
ue_header = f'UE {ue.getName()} ({ueIP})'
|
||||
if response.returncode != 0:
|
||||
message = ue_header + ': ping crashed: TIMEOUT?'
|
||||
logging.error('\u001B[1;37;41m ' + message + ' \u001B[0m')
|
||||
return (False, message)
|
||||
|
||||
#copy the ping log file to have it locally for analysis (ping stats)
|
||||
@@ -403,11 +702,13 @@ class OaiCiTest():
|
||||
result = re.search(', (?P<packetloss>[0-9\.]+)% packet loss, time [0-9\.]+ms', ping_output)
|
||||
if result is None:
|
||||
message = ue_header + ': Packet Loss Not Found!'
|
||||
logging.error(f'\u001B[1;37;41m {message} \u001B[0m')
|
||||
return (False, message)
|
||||
packetloss = result.group('packetloss')
|
||||
result = re.search('rtt min\/avg\/max\/mdev = (?P<rtt_min>[0-9\.]+)\/(?P<rtt_avg>[0-9\.]+)\/(?P<rtt_max>[0-9\.]+)\/[0-9\.]+ ms', ping_output)
|
||||
if result is None:
|
||||
message = ue_header + ': Ping RTT_Min RTT_Avg RTT_Max Not Found!'
|
||||
logging.error(f'\u001B[1;37;41m {message} \u001B[0m')
|
||||
return (False, message)
|
||||
rtt_min = result.group('rtt_min')
|
||||
rtt_avg = result.group('rtt_avg')
|
||||
@@ -418,60 +719,60 @@ class OaiCiTest():
|
||||
avg_msg = f'RTT(Avg) : {rtt_avg} ms'
|
||||
max_msg = f'RTT(Max) : {rtt_max} ms'
|
||||
|
||||
# adding a lock for cleaner display in command line
|
||||
printLock.acquire()
|
||||
logging.info(f'\u001B[1;37;44m ping result for {ue_header} \u001B[0m')
|
||||
logging.info(f'\u001B[1;34m {pal_msg} \u001B[0m')
|
||||
logging.info(f'\u001B[1;34m {min_msg} \u001B[0m')
|
||||
logging.info(f'\u001B[1;34m {avg_msg} \u001B[0m')
|
||||
logging.info(f'\u001B[1;34m {max_msg} \u001B[0m')
|
||||
|
||||
message = f'{ue_header}\n{pal_msg}\n{min_msg}\n{avg_msg}\n{max_msg}'
|
||||
|
||||
#checking packet loss compliance
|
||||
if float(packetloss) > float(self.ping_packetloss_threshold):
|
||||
message += '\nPacket Loss too high'
|
||||
logging.error(f'\u001B[1;37;41m Packet Loss too high; Target: {self.ping_packetloss_threshold}%\u001B[0m')
|
||||
printLock.release()
|
||||
return (False, message)
|
||||
elif float(packetloss) > 0:
|
||||
message += '\nPacket Loss is not 0%'
|
||||
logging.info('\u001B[1;30;43m Packet Loss is not 0% \u001B[0m')
|
||||
|
||||
if self.ping_rttavg_threshold != '':
|
||||
if float(rtt_avg) > float(self.ping_rttavg_threshold):
|
||||
ping_rttavg_error_msg = f'RTT(Avg) too high: {rtt_avg} ms; Target: {self.ping_rttavg_threshold} ms'
|
||||
message += f'\n {ping_rttavg_error_msg}'
|
||||
logging.error('\u001B[1;37;41m'+ ping_rttavg_error_msg +' \u001B[0m')
|
||||
printLock.release()
|
||||
return (False, message)
|
||||
printLock.release()
|
||||
|
||||
return (True, message)
|
||||
|
||||
def Ping(self, HTML, EPC, CONTAINERS):
|
||||
def Ping(self,HTML,RAN,EPC,CONTAINERS):
|
||||
if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.SourceCodePath == '':
|
||||
HELP.GenericHelp(CONST.Version)
|
||||
sys.exit('Insufficient Parameter')
|
||||
|
||||
if self.ue_ids == []:
|
||||
raise Exception("no module names in self.ue_ids provided")
|
||||
# Creating destination log folder if needed on the python executor workspace
|
||||
with cls_cmd.getConnection('localhost') as local:
|
||||
ymlPath = CONTAINERS.yamlPath[0].split('/')
|
||||
logPath = f'{os.getcwd()}/../cmake_targets/log/{ymlPath[-1]}'
|
||||
local.run(f'mkdir -p {logPath}', silent=True)
|
||||
ues = [cls_module.Module_UE(ue_id, server_name) for ue_id, server_name in zip(self.ue_ids, self.nodes)]
|
||||
|
||||
ues = [cls_module.Module_UE(n.strip()) for n in self.ue_ids]
|
||||
logging.debug(ues)
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor:
|
||||
futures = [executor.submit(self.Ping_common, EPC, ue, logPath) for ue in ues]
|
||||
pingLock = Lock()
|
||||
with concurrent.futures.ThreadPoolExecutor() as executor:
|
||||
futures = [executor.submit(self.Ping_common, EPC, ue, RAN, pingLock) for ue in ues]
|
||||
results = [f.result() for f in futures]
|
||||
# each result in results is a tuple, first member goes to successes, second to messages
|
||||
successes, messages = map(list, zip(*results))
|
||||
|
||||
success = len(successes) == len(ues) and all(successes)
|
||||
logger = logging.info if success else logging.error
|
||||
hcolor = "\u001B[1;37;44m" if success else "\u001B[1;37;41m"
|
||||
lcolor = "\u001B[1;34m" if success else "\u001B[1;31m"
|
||||
for m in messages:
|
||||
lines = m.split('\n')
|
||||
logger(f'{hcolor} ping result for {lines[0]} \u001B[0m')
|
||||
for l in lines[1:]:
|
||||
logger(f'{lcolor} {l}\u001B[0m')
|
||||
|
||||
if success:
|
||||
if len(successes) == len(ues) and all(successes):
|
||||
HTML.CreateHtmlTestRowQueue(self.ping_args, 'OK', messages)
|
||||
else:
|
||||
HTML.CreateHtmlTestRowQueue(self.ping_args, 'KO', messages)
|
||||
return success
|
||||
self.AutoTerminateUEandeNB(HTML,RAN,EPC,CONTAINERS)
|
||||
|
||||
def Iperf_Module(self, EPC, ue, svr, idx, ue_num, logPath):
|
||||
def Iperf_Module(self, EPC, ue, svr, RAN, idx, ue_num, CONTAINERS):
|
||||
ueIP = ue.getIP()
|
||||
if not ueIP:
|
||||
return (False, f"UE {ue.getName()} has no IP address")
|
||||
@@ -486,38 +787,56 @@ class OaiCiTest():
|
||||
udpIperf = re.search('-u', iperf_opt) is not None
|
||||
bidirIperf = re.search('--bidir', iperf_opt) is not None
|
||||
client_filename = f'iperf_client_{self.testCase_id}_{ue.getName()}.log'
|
||||
ymlPath = CONTAINERS.yamlPath[0].split('/')
|
||||
logPath = f'../cmake_targets/log/{ymlPath[1]}'
|
||||
if udpIperf:
|
||||
target_bitrate, iperf_opt = Iperf_ComputeModifiedBW(idx, ue_num, self.iperf_profile, self.iperf_args)
|
||||
# note: for UDP testing we don't want to use json report - reports 0 Mbps received bitrate
|
||||
jsonReport = ""
|
||||
# note: enable server report collection on the UE side, no need to store and collect server report separately on the server side
|
||||
serverReport = "--get-server-output"
|
||||
logging.info(f'iperf options modified from "{self.iperf_args}" to "{iperf_opt}" for {ue.getName()}')
|
||||
iperf_time = Iperf_ComputeTime(self.iperf_args)
|
||||
# hack: the ADB UEs don't have iperf in $PATH, so we need to hardcode for the moment
|
||||
iperf_ue = '/data/local/tmp/iperf3' if re.search('adb', ue.getName()) else 'iperf3'
|
||||
ue_header = f'UE {ue.getName()} ({ueIP})'
|
||||
# create log directory on executor node
|
||||
with cls_cmd.getConnection('localhost') as local:
|
||||
local.run(f'mkdir -p {logPath}')
|
||||
with cls_cmd.getConnection(ue.getHost()) as cmd_ue, cls_cmd.getConnection(EPC.IPAddress) as cmd_svr:
|
||||
port = 5002 + idx
|
||||
# note: some core setups start an iperf3 server automatically, indicated in ci_infra by runIperf3Server: False`
|
||||
t = iperf_time * 2.5
|
||||
cmd_ue.run(f'rm /tmp/{client_filename}', reportNonZero=False, silent=True)
|
||||
cmd_ue.run(f'rm /tmp/{client_filename}', reportNonZero=False)
|
||||
if runIperf3Server:
|
||||
cmd_svr.run(f'{svr.getCmdPrefix()} nohup timeout -vk3 {t} iperf3 -s -B {svrIP} -p {port} -1 {jsonReport} &', timeout=t)
|
||||
cmd_ue.run(f'{ue.getCmdPrefix()} timeout -vk3 {t} {iperf_ue} -B {ueIP} -c {svrIP} -p {port} {iperf_opt} {jsonReport} {serverReport} -O 5 >> /tmp/{client_filename}', timeout=t)
|
||||
localPath = f'{os.getcwd()}'
|
||||
# note: copy iperf3 log to the directory for log collection, used by pipelines running on executor machine
|
||||
cmd_ue.copyin(f'/tmp/{client_filename}', f'{localPath}/{logPath}/{client_filename}')
|
||||
# note: copy iperf3 log to the current directory for log analysis and log collection
|
||||
dest_filename = f'{logPath}/{client_filename}'
|
||||
cmd_ue.copyin(f'/tmp/{client_filename}', dest_filename)
|
||||
cmd_ue.run(f'rm /tmp/{client_filename}', reportNonZero=False, silent=True)
|
||||
cmd_ue.copyin(f'/tmp/{client_filename}', f'{localPath}/{client_filename}')
|
||||
cmd_ue.run(f'rm /tmp/{client_filename}', reportNonZero=False)
|
||||
if udpIperf:
|
||||
status, msg = Iperf_analyzeV3UDP(dest_filename, self.iperf_bitrate_threshold, self.iperf_packetloss_threshold, target_bitrate)
|
||||
status, msg = Iperf_analyzeV3UDP(client_filename, self.iperf_bitrate_threshold, self.iperf_packetloss_threshold, target_bitrate)
|
||||
elif bidirIperf:
|
||||
status, msg = Iperf_analyzeV3BIDIRJson(dest_filename)
|
||||
status, msg = Iperf_analyzeV3BIDIRJson(client_filename)
|
||||
else:
|
||||
status, msg = Iperf_analyzeV3TCPJson(dest_filename, self.iperf_tcp_rate_target)
|
||||
status, msg = Iperf_analyzeV3TCPJson(client_filename, self.iperf_tcp_rate_target)
|
||||
|
||||
logging.info(f'\u001B[1;37;45m iperf result for {ue_header}\u001B[0m')
|
||||
for l in msg.split('\n'):
|
||||
logging.info(f'\u001B[1;35m {l} \u001B[0m')
|
||||
return (status, f'{ue_header}\n{msg}')
|
||||
|
||||
def Iperf(self,HTML,EPC,CONTAINERS):
|
||||
def IperfNoS1(self,HTML,RAN,EPC,CONTAINERS):
|
||||
raise 'IperfNoS1 not implemented'
|
||||
|
||||
def Iperf(self,HTML,RAN,EPC,CONTAINERS):
|
||||
result = re.search('noS1', str(RAN.Initialize_eNB_args))
|
||||
if result is not None:
|
||||
self.IperfNoS1(HTML,RAN,EPC,CONTAINERS)
|
||||
return
|
||||
if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.SourceCodePath == '':
|
||||
HELP.GenericHelp(CONST.Version)
|
||||
sys.exit('Insufficient Parameter')
|
||||
@@ -526,41 +845,26 @@ class OaiCiTest():
|
||||
|
||||
if self.ue_ids == [] or self.svr_id == None:
|
||||
raise Exception("no module names in self.ue_ids or/and self.svr_id provided")
|
||||
# create log directory on executor node
|
||||
with cls_cmd.getConnection('localhost') as local:
|
||||
ymlPath = CONTAINERS.yamlPath[0].split('/')
|
||||
logPath = f'{os.getcwd()}/../cmake_targets/log/{ymlPath[-1]}'
|
||||
local.run(f'mkdir -p {logPath}', silent=True)
|
||||
ues = [cls_module.Module_UE(ue_id, server_name) for ue_id, server_name in zip(self.ue_ids, self.nodes)]
|
||||
svr = cls_module.Module_UE(self.svr_id,self.svr_node)
|
||||
|
||||
ues = [cls_module.Module_UE(n.strip()) for n in self.ue_ids]
|
||||
svr = cls_module.Module_UE(self.svr_id)
|
||||
logging.debug(ues)
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor:
|
||||
futures = [executor.submit(self.Iperf_Module, EPC, ue, svr, i, len(ues), logPath) for i, ue in enumerate(ues)]
|
||||
with concurrent.futures.ThreadPoolExecutor() as executor:
|
||||
futures = [executor.submit(self.Iperf_Module, EPC, ue, svr, RAN, i, len(ues), CONTAINERS) for i, ue in enumerate(ues)]
|
||||
results = [f.result() for f in futures]
|
||||
# each result in results is a tuple, first member goes to successes, second to messages
|
||||
successes, messages = map(list, zip(*results))
|
||||
|
||||
success = len(successes) == len(ues) and all(successes)
|
||||
logger = logging.info if success else logging.error
|
||||
hcolor = "\u001B[1;37;45m" if success else "\u001B[1;37;41m"
|
||||
lcolor = "\u001B[1;35m" if success else "\u001B[1;31m"
|
||||
for m in messages:
|
||||
lines = m.split('\n')
|
||||
logger(f'{hcolor} iperf result for {lines[0]} \u001B[0m')
|
||||
for l in lines[1:]:
|
||||
logger(f'{lcolor} {l}\u001B[0m')
|
||||
|
||||
if success:
|
||||
if len(successes) == len(ues) and all(successes):
|
||||
HTML.CreateHtmlTestRowQueue(self.iperf_args, 'OK', messages)
|
||||
else:
|
||||
HTML.CreateHtmlTestRowQueue(self.iperf_args, 'KO', messages)
|
||||
return success
|
||||
self.AutoTerminateUEandeNB(HTML,RAN,EPC,CONTAINERS)
|
||||
|
||||
def Iperf2_Unidir(self,HTML,EPC,CONTAINERS):
|
||||
def Iperf2_Unidir(self,HTML,RAN,EPC,CONTAINERS):
|
||||
if self.ue_ids == [] or self.svr_id == None or len(self.ue_ids) != 1:
|
||||
raise Exception("no module names in self.ue_ids or/and self.svr_id provided, multi UE scenario not supported")
|
||||
ue = cls_module.Module_UE(self.ue_ids[0].strip(),self.nodes[0].strip())
|
||||
svr = cls_module.Module_UE(self.svr_id,self.svr_node)
|
||||
ue = cls_module.Module_UE(self.ue_ids[0].strip())
|
||||
svr = cls_module.Module_UE(self.svr_id)
|
||||
ueIP = ue.getIP()
|
||||
if not ueIP:
|
||||
return (False, f"UE {ue.getName()} has no IP address")
|
||||
@@ -569,7 +873,7 @@ class OaiCiTest():
|
||||
return (False, f"Iperf server {ue.getName()} has no IP address")
|
||||
server_filename = f'iperf_server_{self.testCase_id}_{ue.getName()}.log'
|
||||
ymlPath = CONTAINERS.yamlPath[0].split('/')
|
||||
logPath = f'{os.getcwd()}/../cmake_targets/log/{ymlPath[-1]}'
|
||||
logPath = f'../cmake_targets/log/{ymlPath[-1]}'
|
||||
iperf_time = Iperf_ComputeTime(self.iperf_args)
|
||||
target_bitrate, iperf_opt = Iperf_ComputeModifiedBW(0, 1, self.iperf_profile, self.iperf_args)
|
||||
t = iperf_time*2.5
|
||||
@@ -594,12 +898,12 @@ class OaiCiTest():
|
||||
HTML.CreateHtmlTestRowQueue(self.iperf_args, 'OK', [f'{ue_header}\n{msg}'])
|
||||
else:
|
||||
HTML.CreateHtmlTestRowQueue(self.iperf_args, 'KO', [f'{ue_header}\n{msg}'])
|
||||
return success
|
||||
self.AutoTerminateUEandeNB(HTML,RAN,EPC,CONTAINERS)
|
||||
|
||||
def AnalyzeLogFile_UE(self, UElogFile,HTML,RAN):
|
||||
if (not os.path.isfile(f'{UElogFile}')):
|
||||
if (not os.path.isfile(f'./{UElogFile}')):
|
||||
return -1
|
||||
ue_log_file = open(f'{UElogFile}', 'r')
|
||||
ue_log_file = open(f'./{UElogFile}', 'r')
|
||||
exitSignalReceived = False
|
||||
foundAssertion = False
|
||||
msgAssertion = ''
|
||||
@@ -628,11 +932,8 @@ class OaiCiTest():
|
||||
global_status = CONST.ALL_PROCESSES_OK
|
||||
for line in ue_log_file.readlines():
|
||||
result = re.search('nr_synchro_time|Starting NR UE soft modem', str(line))
|
||||
sidelink = re.search('sl-mode', str(line))
|
||||
if result is not None:
|
||||
nrUEFlag = True
|
||||
if sidelink is not None:
|
||||
nrUEFlag = False
|
||||
if nrUEFlag:
|
||||
result = re.search('decode mib', str(line))
|
||||
if result is not None:
|
||||
@@ -869,13 +1170,185 @@ class OaiCiTest():
|
||||
|
||||
def TerminateUE(self, HTML):
|
||||
ues = [cls_module.Module_UE(n.strip()) for n in self.ue_ids]
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor:
|
||||
with concurrent.futures.ThreadPoolExecutor() as executor:
|
||||
futures = [executor.submit(ue.terminate) for ue in ues]
|
||||
archives = [f.result() for f in futures]
|
||||
archive_info = [f'Log at: {a}' if a else 'No log available' for a in archives]
|
||||
messages = [f"UE {ue.getName()}: {log}" for (ue, log) in zip(ues, archive_info)]
|
||||
HTML.CreateHtmlTestRowQueue(f'N/A', 'OK', messages)
|
||||
return True
|
||||
|
||||
def TerminateOAIUE(self,HTML,RAN,EPC,CONTAINERS):
|
||||
SSH = sshconnection.SSHConnection()
|
||||
SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword)
|
||||
SSH.command(f'cd {self.UESourceCodePath}/cmake_targets', '\$', 5)
|
||||
SSH.command('ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5)
|
||||
result = re.search('-uesoftmodem', SSH.getBefore())
|
||||
if result is not None:
|
||||
SSH.command(f'echo {self.UEPassword} | sudo -S killall --signal SIGINT -r .*-uesoftmodem || true', '\$', 5)
|
||||
time.sleep(10)
|
||||
SSH.command('ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5)
|
||||
result = re.search('-uesoftmodem', SSH.getBefore())
|
||||
if result is not None:
|
||||
SSH.command(f'echo {self.UEPassword} | sudo -S killall --signal SIGKILL -r .*-uesoftmodem || true', '\$', 5)
|
||||
time.sleep(5)
|
||||
SSH.command(f'rm -f my-lte-uesoftmodem-run {self.UE_instance}.sh', '\$', 5)
|
||||
SSH.close()
|
||||
result = re.search('ue_', str(self.UELogFile))
|
||||
if result is not None:
|
||||
copyin_res = SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword,f'{self.UESourceCodePath}/cmake_targets/{self.UELogFile}', '.')
|
||||
if (copyin_res == -1):
|
||||
logging.debug('\u001B[1;37;41m Could not copy UE logfile to analyze it! \u001B[0m')
|
||||
HTML.htmlUEFailureMsg='Could not copy UE logfile to analyze it!'
|
||||
HTML.CreateHtmlTestRow('N/A', 'KO', CONST.OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE, 'UE')
|
||||
self.UELogFile = ''
|
||||
return
|
||||
logging.debug('\u001B[1m Analyzing UE logfile \u001B[0m')
|
||||
logStatus = self.AnalyzeLogFile_UE(self.UELogFile,HTML,RAN)
|
||||
result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args))
|
||||
if result is not None:
|
||||
ueAction = 'Sniffing'
|
||||
else:
|
||||
ueAction = 'Connection'
|
||||
if (logStatus < 0):
|
||||
logging.debug(f'\u001B[1m {ueAction} Failed \u001B[0m')
|
||||
HTML.htmlUEFailureMsg='<b>' + ueAction + ' Failed</b>\n' + HTML.htmlUEFailureMsg
|
||||
HTML.CreateHtmlTestRow('N/A', 'KO', logStatus, 'UE')
|
||||
if self.air_interface == 'lte-uesoftmodem':
|
||||
# In case of sniffing on commercial eNBs we have random results
|
||||
# Not an error then
|
||||
if (logStatus != CONST.OAI_UE_PROCESS_COULD_NOT_SYNC) or (ueAction != 'Sniffing'):
|
||||
self.Initialize_OAI_UE_args = ''
|
||||
self.AutoTerminateUEandeNB(HTML,RAN,EPC,CONTAINERS)
|
||||
else:
|
||||
if (logStatus == CONST.OAI_UE_PROCESS_COULD_NOT_SYNC):
|
||||
self.Initialize_OAI_UE_args = ''
|
||||
self.AutoTerminateUEandeNB(HTML,RAN,EPC,CONTAINERS)
|
||||
else:
|
||||
logging.debug(f'\u001B[1m {ueAction} Completed \u001B[0m')
|
||||
HTML.htmlUEFailureMsg='<b>' + ueAction + ' Completed</b>\n' + HTML.htmlUEFailureMsg
|
||||
HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK)
|
||||
self.UELogFile = ''
|
||||
else:
|
||||
HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK)
|
||||
|
||||
def AutoTerminateUEandeNB(self,HTML,RAN,EPC,CONTAINERS):
|
||||
# TODO: terminate UE?
|
||||
if (self.Initialize_OAI_UE_args != ''):
|
||||
self.testCase_id = 'AUTO-KILL-OAI-UE'
|
||||
HTML.testCase_id = self.testCase_id
|
||||
self.desc = 'Automatic Termination of OAI-UE'
|
||||
HTML.desc = self.desc
|
||||
self.ShowTestID()
|
||||
self.TerminateOAIUE(HTML,RAN,EPC,CONTAINERS)
|
||||
if (RAN.Initialize_eNB_args != ''):
|
||||
self.testCase_id = 'AUTO-KILL-RAN'
|
||||
HTML.testCase_id = self.testCase_id
|
||||
self.desc = 'Automatic Termination of all RAN nodes'
|
||||
HTML.desc = self.desc
|
||||
self.ShowTestID()
|
||||
#terminate all RAN nodes eNB/gNB/OCP
|
||||
for instance in range(0, len(RAN.air_interface)):
|
||||
if RAN.air_interface[instance]!='':
|
||||
logging.debug(f'Auto Termination of Instance {instance} : {RAN.air_interface[instance]}')
|
||||
RAN.eNB_instance=instance
|
||||
RAN.TerminateeNB(HTML,EPC)
|
||||
if CONTAINERS.yamlPath[0] != '':
|
||||
self.testCase_id = 'AUTO-KILL-CONTAINERS'
|
||||
HTML.testCase_id = self.testCase_id
|
||||
self.desc = 'Automatic Termination of all RAN containers'
|
||||
HTML.desc = self.desc
|
||||
self.ShowTestID()
|
||||
for instance in range(0, len(CONTAINERS.yamlPath)):
|
||||
if CONTAINERS.yamlPath[instance]!='':
|
||||
CONTAINERS.eNB_instance=instance
|
||||
if CONTAINERS.deployKind[instance]:
|
||||
CONTAINERS.UndeployObject(HTML,RAN)
|
||||
else:
|
||||
CONTAINERS.UndeployGenObject(HTML,RAN, self)
|
||||
RAN.prematureExit=True
|
||||
|
||||
#this function is called only if eNB/gNB fails to start
|
||||
#RH to be re-factored
|
||||
def AutoTerminateeNB(self,HTML,RAN,EPC,CONTAINERS):
|
||||
if (RAN.Initialize_eNB_args != ''):
|
||||
self.testCase_id = 'AUTO-KILL-RAN'
|
||||
HTML.testCase_id = self.testCase_id
|
||||
self.desc = 'Automatic Termination of all RAN nodes'
|
||||
HTML.desc = self.desc
|
||||
self.ShowTestID()
|
||||
#terminate all RAN nodes eNB/gNB/OCP
|
||||
for instance in range(0, len(RAN.air_interface)):
|
||||
if RAN.air_interface[instance]!='':
|
||||
logging.debug(f'Auto Termination of Instance {instance} : {RAN.air_interface[instance]}')
|
||||
RAN.eNB_instance=instance
|
||||
RAN.TerminateeNB(HTML,EPC)
|
||||
if CONTAINERS.yamlPath[0] != '':
|
||||
self.testCase_id = 'AUTO-KILL-CONTAINERS'
|
||||
HTML.testCase_id = self.testCase_id
|
||||
self.desc = 'Automatic Termination of all RAN containers'
|
||||
HTML.desc = self.desc
|
||||
self.ShowTestID()
|
||||
for instance in range(0, len(CONTAINERS.yamlPath)):
|
||||
if CONTAINERS.yamlPath[instance]!='':
|
||||
CONTAINERS.eNB_instance=instance
|
||||
if CONTAINERS.deployKind[instance]:
|
||||
CONTAINERS.UndeployObject(HTML,RAN)
|
||||
else:
|
||||
CONTAINERS.UndeployGenObject(HTML,RAN,self)
|
||||
RAN.prematureExit=True
|
||||
|
||||
def IdleSleep(self,HTML):
|
||||
time.sleep(self.idle_sleep_time)
|
||||
HTML.CreateHtmlTestRow(str(self.idle_sleep_time) + ' sec', 'OK', CONST.ALL_PROCESSES_OK)
|
||||
|
||||
def X2_Status(self, idx, fileName, EPC):
|
||||
cmd = "curl --silent http://" + EPC.IPAddress + ":9999/stats | jq '.' > " + fileName
|
||||
message = cmd + '\n'
|
||||
logging.debug(cmd)
|
||||
subprocess.run(cmd, shell=True)
|
||||
if idx == 0:
|
||||
cmd = "jq '.mac_stats | length' " + fileName
|
||||
strNbEnbs = subprocess.check_output(cmd, shell=True, universal_newlines=True)
|
||||
self.x2NbENBs = int(strNbEnbs.strip())
|
||||
cnt = 0
|
||||
while cnt < self.x2NbENBs:
|
||||
cmd = "jq '.mac_stats[" + str(cnt) + "].bs_id' " + fileName
|
||||
bs_id = subprocess.check_output(cmd, shell=True, universal_newlines=True)
|
||||
self.x2ENBBsIds[idx].append(bs_id.strip())
|
||||
cmd = "jq '.mac_stats[" + str(cnt) + "].ue_mac_stats | length' " + fileName
|
||||
stNbUEs = subprocess.check_output(cmd, shell=True, universal_newlines=True)
|
||||
nbUEs = int(stNbUEs.strip())
|
||||
ueIdx = 0
|
||||
self.x2ENBConnectedUEs[idx].append([])
|
||||
while ueIdx < nbUEs:
|
||||
cmd = "jq '.mac_stats[" + str(cnt) + "].ue_mac_stats[" + str(ueIdx) + "].rnti' " + fileName
|
||||
rnti = subprocess.check_output(cmd, shell=True, universal_newlines=True)
|
||||
self.x2ENBConnectedUEs[idx][cnt].append(rnti.strip())
|
||||
ueIdx += 1
|
||||
cnt += 1
|
||||
|
||||
cnt = 0
|
||||
while cnt < self.x2NbENBs:
|
||||
msg = " -- eNB: " + str(self.x2ENBBsIds[idx][cnt]) + " is connected to " + str(len(self.x2ENBConnectedUEs[idx][cnt])) + " UE(s)"
|
||||
logging.debug(msg)
|
||||
message += msg + '\n'
|
||||
ueIdx = 0
|
||||
while ueIdx < len(self.x2ENBConnectedUEs[idx][cnt]):
|
||||
msg = " -- UE rnti: " + str(self.x2ENBConnectedUEs[idx][cnt][ueIdx])
|
||||
logging.debug(msg)
|
||||
message += msg + '\n'
|
||||
ueIdx += 1
|
||||
cnt += 1
|
||||
return message
|
||||
|
||||
def Perform_X2_Handover(self,HTML,RAN,EPC):
|
||||
html_queue = SimpleQueue()
|
||||
fullMessage = '<pre style="background-color:white">'
|
||||
msg = f'Doing X2 Handover w/ option {self.x2_ho_options}'
|
||||
logging.debug(msg)
|
||||
fullMessage += msg + '\n'
|
||||
if self.x2_ho_options == 'network':
|
||||
HTML.CreateHtmlTestRow('Cannot perform requested X2 Handover', 'KO', CONST.ALL_PROCESSES_OK)
|
||||
|
||||
def LogCollectBuild(self,RAN):
|
||||
# Some pipelines are using "none" IP / Credentials
|
||||
@@ -945,6 +1418,12 @@ class OaiCiTest():
|
||||
SSH.command(f'echo {self.UEPassword} | sudo -S rm ue*.log core* ue_*record.raw ue_*.pcap ue_*txt', '\$', 5)
|
||||
SSH.close()
|
||||
|
||||
def ConditionalExit(self):
|
||||
if self.testUnstable:
|
||||
if self.testStabilityPointReached or self.testMinStableId == '999999':
|
||||
sys.exit(0)
|
||||
sys.exit(1)
|
||||
|
||||
def ShowTestID(self):
|
||||
logging.info(f'\u001B[1m----------------------------------------\u001B[0m')
|
||||
logging.info(f'\u001B[1m Test ID: {self.testCase_id} \u001B[0m')
|
||||
|
||||
@@ -34,6 +34,7 @@ import sshconnection
|
||||
#to update the HTML object
|
||||
import cls_oai_html
|
||||
import cls_cmd
|
||||
from multiprocessing import SimpleQueue
|
||||
#for log folder maintenance
|
||||
import os
|
||||
import re
|
||||
@@ -51,6 +52,7 @@ class PhySim:
|
||||
self.ranCommitID= ""
|
||||
self.ranAllowMerge= ""
|
||||
self.ranTargetBranch= ""
|
||||
self.exitStatus=0
|
||||
self.forced_workspace_cleanup=False
|
||||
#private attributes
|
||||
self.__workSpacePath=''
|
||||
@@ -82,7 +84,7 @@ class PhySim:
|
||||
os.system('mv '+self.__runLogFile+' '+ self.__runLogPath+'/.')
|
||||
|
||||
HTML.CreateHtmlTestRowQueue(self.runargs, 'OK', [info])
|
||||
return True
|
||||
return HTML
|
||||
|
||||
def __CheckResults_LDPCt2Test(self,HTML,CONST,testcase_id):
|
||||
thrs_KO = int(self.timethrs)
|
||||
@@ -109,19 +111,20 @@ class PhySim:
|
||||
if res_enc is None and res_dec is None:
|
||||
logging.error(f'no statistics: res_enc {res_enc} res_dec {res_dec}')
|
||||
HTML.CreateHtmlTestRowQueue(self.runargs, 'KO', ['no statistics'])
|
||||
self.exitStatus = 1
|
||||
os.system(f'mv {self.__runLogFile} {self.__runLogPath}/.')
|
||||
return False
|
||||
return HTML
|
||||
|
||||
#once parsed move the local logfile to its folder
|
||||
os.system(f'mv {self.__runLogFile} {self.__runLogPath}/.')
|
||||
success = float(time) < thrs_KO
|
||||
if success:
|
||||
if float(time) < thrs_KO:
|
||||
HTML.CreateHtmlTestRowQueue(self.runargs, 'OK', [info])
|
||||
else:
|
||||
error_msg = f'Processing time exceeds a limit of {thrs_KO} us'
|
||||
logging.error(error_msg)
|
||||
HTML.CreateHtmlTestRowQueue(self.runargs, 'KO', [info + '\n' + error_msg])
|
||||
return success
|
||||
self.exitStatus = 1
|
||||
return HTML
|
||||
|
||||
def __CheckResults_NRulsimTest(self, HTML, CONST, testcase_id):
|
||||
#retrieve run log file and store it locally
|
||||
@@ -132,7 +135,8 @@ class PhySim:
|
||||
error_msg = f'could not recover test result file {filename}'
|
||||
logging.error(error_msg)
|
||||
HTML.CreateHtmlTestRowQueue("could not recover results", 'KO', [error_msg])
|
||||
return False
|
||||
self.exitStatus = 1
|
||||
return HTML
|
||||
|
||||
PUSCH_OK = False
|
||||
with open(self.__runLogFile) as f:
|
||||
@@ -148,7 +152,8 @@ class PhySim:
|
||||
error_msg = 'error: no "PUSCH test OK"'
|
||||
logging.error(error_msg)
|
||||
HTML.CreateHtmlTestRowQueue(self.runargs, 'KO', 1, [error_msg])
|
||||
return PUSCH_OK
|
||||
self.exitStatus = 1
|
||||
return HTML
|
||||
|
||||
def __CheckBuild_PhySim(self, HTML, CONST):
|
||||
self.__workSpacePath=self.eNBSourceCodePath+'/cmake_targets/'
|
||||
@@ -163,11 +168,14 @@ class PhySim:
|
||||
with open(self.__buildLogFile) as f:
|
||||
if 'BUILD SHOULD BE SUCCESSFUL' in f.read():
|
||||
HTML.CreateHtmlTestRow(self.buildargs, 'OK', CONST.ALL_PROCESSES_OK, 'PhySim')
|
||||
return True
|
||||
self.exitStatus=0
|
||||
return HTML
|
||||
logging.error('\u001B[1m Building Physical Simulators Failed\u001B[0m')
|
||||
HTML.CreateHtmlTestRow(self.buildargs, 'KO', CONST.ALL_PROCESSES_OK, 'LDPC')
|
||||
HTML.CreateHtmlTabFooter(False)
|
||||
return False
|
||||
#exitStatus=1 will do a sys.exit in main
|
||||
self.exitStatus = 1
|
||||
return HTML
|
||||
|
||||
|
||||
#-----------------$
|
||||
@@ -218,7 +226,10 @@ class PhySim:
|
||||
mySSH.command(f'./build_oai {self.buildargs} 2>&1 | tee {self.__buildLogFile}', '\$', 1500)
|
||||
|
||||
mySSH.close()
|
||||
return __CheckBuild_PhySim(htmlObj,constObj)
|
||||
#check build status and update HTML object
|
||||
lHTML = cls_oai_html.HTMLManagement()
|
||||
lHTML=self.__CheckBuild_PhySim(htmlObj,constObj)
|
||||
return lHTML
|
||||
|
||||
|
||||
def Run_CUDATest(self,htmlObj,constObj,testcase_id):
|
||||
@@ -234,7 +245,10 @@ class PhySim:
|
||||
#run and redirect the results to a log file
|
||||
mySSH.command(self.__workSpacePath+'ran_build/build/ldpctest ' + self.runargs + ' >> '+self.__runLogFile, '\$', 30)
|
||||
mySSH.close()
|
||||
return self.__CheckResults_LDPCcudaTest(htmlObj,constObj,testcase_id)
|
||||
#return updated HTML to main
|
||||
lHTML = cls_oai_html.HTMLManagement()
|
||||
lHTML=self.__CheckResults_LDPCcudaTest(htmlObj,constObj,testcase_id)
|
||||
return lHTML
|
||||
|
||||
def Run_T2Test(self,htmlObj,constObj,testcase_id):
|
||||
self.__workSpacePath = f'{self.eNBSourceCodePath}/cmake_targets/'
|
||||
@@ -248,7 +262,10 @@ class PhySim:
|
||||
#run and redirect the results to a log file
|
||||
mySSH.run(f'sudo {self.__workSpacePath}ran_build/build/{self.runsim} {self.runargs} > {self.__workSpacePath}{self.__runLogFile} 2>&1')
|
||||
mySSH.close()
|
||||
return self.__CheckResults_LDPCt2Test(htmlObj,constObj,testcase_id)
|
||||
#return updated HTML to main
|
||||
lHTML = cls_oai_html.HTMLManagement()
|
||||
lHTML=self.__CheckResults_LDPCt2Test(htmlObj,constObj,testcase_id)
|
||||
return lHTML
|
||||
|
||||
def Run_NRulsimTest(self, htmlObj, constObj, testcase_id):
|
||||
self.__workSpacePath=self.eNBSourceCodePath+'/cmake_targets/'
|
||||
@@ -259,4 +276,6 @@ class PhySim:
|
||||
mySSH.command(f'cd {self.__workSpacePath}', '\$', 5)
|
||||
mySSH.command(f'sudo {self.__workSpacePath}ran_build/build/nr_ulsim {self.runargs} > {self.__runLogFile} 2>&1', '\$', 30)
|
||||
mySSH.close()
|
||||
return self.__CheckResults_NRulsimTest(htmlObj, constObj, testcase_id)
|
||||
#return updated HTML to main
|
||||
lHTML = self.__CheckResults_NRulsimTest(htmlObj, constObj, testcase_id)
|
||||
return lHTML
|
||||
|
||||
@@ -65,7 +65,7 @@ class PhySim:
|
||||
#PUBLIC Methods$
|
||||
#-----------------$
|
||||
|
||||
def Deploy_PhySim(self, HTML):
|
||||
def Deploy_PhySim(self, HTML, RAN):
|
||||
if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '':
|
||||
HELP.GenericHelp(CONST.Version)
|
||||
sys.exit('Insufficient Parameter')
|
||||
@@ -123,7 +123,8 @@ class PhySim:
|
||||
logging.error('\u001B[1m OC Cluster Login Failed\u001B[0m')
|
||||
mySSH.close()
|
||||
HTML.CreateHtmlTestRow('N/A', 'KO', CONST.OC_LOGIN_FAIL)
|
||||
return False
|
||||
RAN.prematureExit = True
|
||||
return
|
||||
else:
|
||||
logging.debug('\u001B[1m Login to OC Cluster Successfully\u001B[0m')
|
||||
mySSH.command(f'oc project {ocProjectName}', '\$', 30)
|
||||
@@ -132,7 +133,8 @@ class PhySim:
|
||||
mySSH.command('oc logout', '\$', 30)
|
||||
mySSH.close()
|
||||
HTML.CreateHtmlTestRow('N/A', 'KO', CONST.OC_PROJECT_FAIL)
|
||||
return False
|
||||
RAN.prematureExit = True
|
||||
return
|
||||
else:
|
||||
logging.debug(f'\u001B[1m Now using project {ocProjectName}\u001B[0m')
|
||||
|
||||
@@ -152,7 +154,8 @@ class PhySim:
|
||||
mySSH.command('oc logout', '\$', 30)
|
||||
mySSH.close()
|
||||
self.AnalyzeLogFile_phySim()
|
||||
return False
|
||||
RAN.prematureExit = True
|
||||
return
|
||||
else:
|
||||
logging.debug('\u001B[1m Deployed PhySim Successfully using helm chart\u001B[0m')
|
||||
isRunning = False
|
||||
@@ -163,7 +166,7 @@ class PhySim:
|
||||
mySSH.command('oc get pods -o wide -l app=physim | tee -a cmake_targets/log/physim_pods_summary.txt', '\$', 30, resync=True)
|
||||
running_count = mySSH.getBefore().count('Running')
|
||||
completed_count = mySSH.getBefore().count('Completed')
|
||||
if (running_count + completed_count) == 23:
|
||||
if (running_count + completed_count) == 22:
|
||||
logging.debug('\u001B[1m Running the physim test Scenarios\u001B[0m')
|
||||
isRunning = True
|
||||
podNames = re.findall('oai-[\S\d\w]+', mySSH.getBefore())
|
||||
@@ -183,7 +186,8 @@ class PhySim:
|
||||
mySSH.command('oc logout', '\$', 30)
|
||||
HTML.CreateHtmlTestRow('N/A', 'KO', CONST.OC_PHYSIM_DEPLOY_FAIL)
|
||||
HTML.CreateHtmlTestRowPhySimTestResult(self.testSummary,self.testResult)
|
||||
return False
|
||||
RAN.prematureExit = True
|
||||
return
|
||||
# Waiting to complete the running test
|
||||
count = 0
|
||||
isFinished = False
|
||||
@@ -210,7 +214,7 @@ class PhySim:
|
||||
mySSH.command('for pod in $(oc get pods | tail -n +2 | awk \'{print $1}\'); do oc describe pod $pod >> cmake_targets/log/physim_pods_summary.txt; done', '\$', 10)
|
||||
mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/log/physim_test.txt', '.')
|
||||
try:
|
||||
listLogFiles = subprocess.check_output('grep -E --colour=never "Execution Log file|Linux oai-" physim_test.txt', shell=True, universal_newlines=True)
|
||||
listLogFiles = subprocess.check_output('egrep --colour=never "Execution Log file|Linux oai-" physim_test.txt', shell=True, universal_newlines=True)
|
||||
for line in listLogFiles.split('\n'):
|
||||
res1 = re.search('Linux (?P<pod>oai-[a-zA-Z0-9\-]+) ', str(line))
|
||||
res2 = re.search('Execution Log file = (?P<name>[a-zA-Z0-9\-\/\.\_\+]+)', str(line))
|
||||
@@ -244,13 +248,13 @@ class PhySim:
|
||||
HTML.CreateHtmlTestRowPhySimTestResult(self.testSummary,self.testResult)
|
||||
logging.info('\u001B[1m Physical Simulator Pass\u001B[0m')
|
||||
else:
|
||||
RAN.prematureExit = True
|
||||
if isFinished:
|
||||
HTML.CreateHtmlTestRow('N/A', 'KO', CONST.ALL_PROCESSES_OK)
|
||||
else:
|
||||
HTML.CreateHtmlTestRow('Some test(s) timed-out!', 'KO', CONST.ALL_PROCESSES_OK)
|
||||
HTML.CreateHtmlTestRowPhySimTestResult(self.testSummary,self.testResult)
|
||||
logging.error('\u001B[1m Physical Simulator Fail\u001B[0m')
|
||||
return self.testStatus
|
||||
|
||||
def AnalyzeLogFile_phySim(self):
|
||||
mySSH = SSH.SSHConnection()
|
||||
|
||||
@@ -36,6 +36,8 @@ import re # reg
|
||||
import logging
|
||||
import os
|
||||
from pathlib import Path
|
||||
import time
|
||||
from multiprocessing import Process, Lock, SimpleQueue
|
||||
|
||||
#-----------------------------------------------------------
|
||||
# OAI Testing modules
|
||||
@@ -43,6 +45,7 @@ from pathlib import Path
|
||||
import helpreadme as HELP
|
||||
import constants as CONST
|
||||
import cls_cmd
|
||||
from cls_containerize import CreateWorkspace
|
||||
|
||||
#-----------------------------------------------------------
|
||||
# Class Declaration
|
||||
@@ -102,7 +105,8 @@ class StaticCodeAnalysis():
|
||||
else:
|
||||
full_ran_repo_name = self.ranRepository + '.git'
|
||||
|
||||
cmd.cd(lSourcePath)
|
||||
CreateWorkspace(cmd, lSourcePath, full_ran_repo_name, self.ranCommitID, self.ranTargetBranch, self.ranAllowMerge)
|
||||
|
||||
logDir = f'{lSourcePath}/cmake_targets/build_log_{self.testCase_id}'
|
||||
cmd.run(f'mkdir -p {logDir}')
|
||||
cmd.run('docker image rm oai-cppcheck:bionic oai-cppcheck:focal')
|
||||
@@ -211,12 +215,12 @@ class StaticCodeAnalysis():
|
||||
HTML.CreateHtmlTestRowCppCheckResults(CCR)
|
||||
logging.info('\u001B[1m Static Code Analysis Pass\u001B[0m')
|
||||
|
||||
return True
|
||||
return 0
|
||||
|
||||
def LicenceAndFormattingCheck(self, HTML):
|
||||
# Workspace is no longer recreated from scratch.
|
||||
# It implies that this method shall be called last within a build pipeline
|
||||
# where workspace is already created
|
||||
if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '':
|
||||
HELP.GenericHelp(CONST.Version)
|
||||
sys.exit('Insufficient Parameter')
|
||||
lIpAddr = self.eNBIPAddress
|
||||
lUserName = self.eNBUserName
|
||||
lPassWord = self.eNBPassword
|
||||
@@ -228,7 +232,14 @@ class StaticCodeAnalysis():
|
||||
logging.debug('Building on server: ' + lIpAddr)
|
||||
cmd = cls_cmd.getConnection(lIpAddr)
|
||||
self.testCase_id = HTML.testCase_id
|
||||
# on RedHat/CentOS .git extension is mandatory
|
||||
result = re.search('([a-zA-Z0-9\:\-\.\/])+\.git', self.ranRepository)
|
||||
if result is not None:
|
||||
full_ran_repo_name = self.ranRepository.replace('git/', 'git')
|
||||
else:
|
||||
full_ran_repo_name = self.ranRepository + '.git'
|
||||
|
||||
CreateWorkspace(cmd, lSourcePath, full_ran_repo_name, self.ranCommitID, self.ranTargetBranch, self.ranAllowMerge)
|
||||
check_options = ''
|
||||
if self.ranAllowMerge:
|
||||
check_options = f'--build-arg MERGE_REQUEST=true --build-arg SRC_BRANCH={self.ranBranch}'
|
||||
@@ -241,7 +252,7 @@ class StaticCodeAnalysis():
|
||||
logDir = f'{lSourcePath}/cmake_targets/build_log_{self.testCase_id}'
|
||||
cmd.run(f'mkdir -p {logDir}')
|
||||
cmd.run('docker image rm oai-formatting-check:latest')
|
||||
cmd.run(f'docker build --target oai-formatting-check --tag oai-formatting-check:latest {check_options} --file {lSourcePath}/ci-scripts/docker/Dockerfile.formatting.bionic {lSourcePath} > {logDir}/oai-formatting-check.txt 2>&1')
|
||||
cmd.run(f'docker build --target oai-formatting-check --tag oai-formatting-check:latest {check_options} --file {lSourcePath}/ci-scripts/docker/Dockerfile.formatting.bionic . > {logDir}/oai-formatting-check.txt 2>&1')
|
||||
|
||||
cmd.run('docker image rm oai-formatting-check:latest')
|
||||
cmd.run('docker image prune --force')
|
||||
@@ -353,4 +364,4 @@ class StaticCodeAnalysis():
|
||||
HTML.htmleNBFailureMsg = 'Could not access oai-formatting-check.txt file'
|
||||
HTML.CreateHtmlTestRow('N/A', 'KO', CONST.ENB_PROCESS_NOLOGFILE_TO_ANALYZE)
|
||||
|
||||
return finalStatus == 0
|
||||
return finalStatus
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
# Colosseum Automated Testing
|
||||
|
||||
These scripts are used by a Jenkins [job](../Jenkinsfile-colosseum) to trigger automated testing of OpenAirInterface (OAI) gNB and softUE on the [Colosseum](https://www.northeastern.edu/colosseum/) Open RAN digital twin.
|
||||
Once a test is triggered, a new OAI LXC container at the specified OAI version will be built on Colosseum (if not already present), and gNB and softUE will perform TCP uplink and downlink connectivity test via the iPerf [tool](https://iperf.fr/).
|
||||
The OAI branch to build and test can be specified through the `eNB_Branch` parameter passed through Jenkins (`eNB_TargetBranch`, which defaults to the `develop` branch, is used if `eNB_Branch` is not specified).
|
||||
The Colosseum network scenario to test is specified through the `Colosseum_Rf_Scenario` Jenkins parameter, which defaults to a base Colosseum scenario without artificially added channel effects (e.g., only hardware impariments of software-defined radios, cables, and channel emulator).
|
||||
|
||||
Once the test ends, results are analyzed through the OAI automated test report generation tool available [here](https://github.com/ztouchnetworks/openairinterface-automated-test-reports), which builds a test report from the iPerf and OAI logs, and marks the test as successful or unsuccessful.
|
||||
Results from successful tests are saved in history files and used to compare more recent tests.
|
||||
A test is considered successful if the downlink throughput achieved during the test is greather than or equal to the average of the test history, which spans successful test executed since May 2024.
|
||||
This is used to identify possible regressions of OAI runs executed on the Colosseum testbed.
|
||||
@@ -1,33 +0,0 @@
|
||||
#!/bin/bash
|
||||
#/*
|
||||
# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
# * contributor license agreements. See the NOTICE file distributed with
|
||||
# * this work for additional information regarding copyright ownership.
|
||||
# * The OpenAirInterface Software Alliance licenses this file to You under
|
||||
# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698
|
||||
# *
|
||||
# * 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.
|
||||
# *-------------------------------------------------------------------------------
|
||||
# * For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
# * contact@openairinterface.org
|
||||
# */
|
||||
|
||||
set -x
|
||||
|
||||
RESULT_FILE=$1
|
||||
|
||||
grep -A 1 "Final Status" ${RESULT_FILE} | grep "PASS"
|
||||
|
||||
if [ "$?" = 0 ]; then
|
||||
echo '{"status": "successful"}' > results.json
|
||||
else
|
||||
echo '{"status": "failed"}' > results.json
|
||||
fi
|
||||
@@ -1,38 +0,0 @@
|
||||
#!/bin/bash
|
||||
#/*
|
||||
# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
# * contributor license agreements. See the NOTICE file distributed with
|
||||
# * this work for additional information regarding copyright ownership.
|
||||
# * The OpenAirInterface Software Alliance licenses this file to You under
|
||||
# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698
|
||||
# *
|
||||
# * 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.
|
||||
# *-------------------------------------------------------------------------------
|
||||
# * For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
# * contact@openairinterface.org
|
||||
# */
|
||||
|
||||
set -eu
|
||||
|
||||
AWX_API_URL=https://10.100.1.253
|
||||
AWX_JOB_EVENT_QUERY=job_events/?search=results_url
|
||||
|
||||
COL_USER=$1
|
||||
COL_PASS=$2
|
||||
|
||||
AWX_API_JOB_PATH=$(jq -r '.url' launch.json)
|
||||
|
||||
# get result url and download test results
|
||||
curl -s -f -k -u ${COL_USER}:${COL_PASS} -X GET ${AWX_API_URL}${AWX_API_JOB_PATH}${AWX_JOB_EVENT_QUERY} > result.json
|
||||
|
||||
set -x
|
||||
RESULT=$(jq -r '.results[0].event_data.res.ansible_facts.results_url' result.json)
|
||||
wget -q -O - ${RESULT} > results.tar.xz
|
||||
@@ -1,53 +0,0 @@
|
||||
#!/bin/bash
|
||||
#/*
|
||||
# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
# * contributor license agreements. See the NOTICE file distributed with
|
||||
# * this work for additional information regarding copyright ownership.
|
||||
# * The OpenAirInterface Software Alliance licenses this file to You under
|
||||
# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698
|
||||
# *
|
||||
# * 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.
|
||||
# *-------------------------------------------------------------------------------
|
||||
# * For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
# * contact@openairinterface.org
|
||||
# */
|
||||
|
||||
set -eu
|
||||
|
||||
AWX_API_URL=https://10.100.1.253
|
||||
AWX_JOB_ID=16
|
||||
AWX_API_LAUNCH_PATH=/api/v2/job_templates/${AWX_JOB_ID}/launch/
|
||||
|
||||
COL_USER=$1
|
||||
COL_PASS=$2
|
||||
JENKINS_JOB_ID=$3
|
||||
GIT_REPOSITORY=$4
|
||||
GIT_BRANCH=$5
|
||||
COLOSSEUM_RF_SCENARIO=$6
|
||||
JENKINS_JOB_URL=$7
|
||||
|
||||
# assemble data to send
|
||||
CURL_DATA=$(cat <<-END | jq -c .
|
||||
{
|
||||
"extra_vars":
|
||||
{
|
||||
"oai_repo": "${GIT_REPOSITORY}",
|
||||
"oai_branch": "${GIT_BRANCH}",
|
||||
"colosseum_rf_scenario": "${COLOSSEUM_RF_SCENARIO}",
|
||||
"jenkins_job_id": "${JENKINS_JOB_ID}",
|
||||
"jenkins_job_url": "${JENKINS_JOB_URL}"
|
||||
}
|
||||
}
|
||||
END
|
||||
)
|
||||
|
||||
# launch job
|
||||
curl -s -f -k -u ${COL_USER}:${COL_PASS} -X POST -H "Content-Type: application/json" -d ${CURL_DATA} ${AWX_API_URL}${AWX_API_LAUNCH_PATH} > launch.json
|
||||
@@ -1,28 +0,0 @@
|
||||
#!/bin/bash
|
||||
#/*
|
||||
# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
# * contributor license agreements. See the NOTICE file distributed with
|
||||
# * this work for additional information regarding copyright ownership.
|
||||
# * The OpenAirInterface Software Alliance licenses this file to You under
|
||||
# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698
|
||||
# *
|
||||
# * 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.
|
||||
# *-------------------------------------------------------------------------------
|
||||
# * For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
# * contact@openairinterface.org
|
||||
# */
|
||||
|
||||
set -eu
|
||||
|
||||
# sets final exit code and thus jenkins pass or fail
|
||||
STATUS=$(jq -r '.status' results.json)
|
||||
echo "job status: ${STATUS}"
|
||||
[ "${STATUS}" = "successful" ]
|
||||
@@ -1,47 +0,0 @@
|
||||
#!/bin/bash
|
||||
#/*
|
||||
# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
# * contributor license agreements. See the NOTICE file distributed with
|
||||
# * this work for additional information regarding copyright ownership.
|
||||
# * The OpenAirInterface Software Alliance licenses this file to You under
|
||||
# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698
|
||||
# *
|
||||
# * 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.
|
||||
# *-------------------------------------------------------------------------------
|
||||
# * For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
# * contact@openairinterface.org
|
||||
# */
|
||||
|
||||
set -xeu
|
||||
|
||||
AWX_API_URL=https://10.100.1.253
|
||||
AWX_MAX_API_CHECKS=120
|
||||
|
||||
COL_USER=$1
|
||||
COL_PASS=$2
|
||||
|
||||
AWX_API_JOB_PATH=$(jq -r '.url' launch.json)
|
||||
|
||||
# wait for job to complete
|
||||
for ((try = 1; try <= ${AWX_MAX_API_CHECKS}; try++)); do
|
||||
set +x
|
||||
curl -s -f -k -u ${COL_USER}:${COL_PASS} -X GET ${AWX_API_URL}${AWX_API_JOB_PATH} > status.json
|
||||
set -x
|
||||
|
||||
FINISHED=$(jq -r '.finished' status.json)
|
||||
[ "${FINISHED}" = "null" ] || break
|
||||
|
||||
sleep 60
|
||||
done
|
||||
|
||||
[ $try != $AWX_MAX_API_CHECKS ] || echo "WARNING: stopped retrying after $AWX_MAX_API_CHECKS times; timed out?"
|
||||
|
||||
echo "AWX job completed $FINISHED"
|
||||
@@ -228,7 +228,7 @@ RUs = (
|
||||
nb_tx = 1
|
||||
nb_rx = 1
|
||||
att_tx = 0
|
||||
att_rx = 6;
|
||||
att_rx = 0;
|
||||
eNB_instances = [0];
|
||||
}
|
||||
);
|
||||
|
||||
@@ -191,7 +191,7 @@ RUs = (
|
||||
nb_tx = 1
|
||||
nb_rx = 1
|
||||
att_tx = 6
|
||||
att_rx = 12;
|
||||
att_rx = 6;
|
||||
bands = [38];
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 125;
|
||||
|
||||
@@ -191,7 +191,7 @@ RUs = (
|
||||
nb_tx = 1
|
||||
nb_rx = 1
|
||||
att_tx = 6
|
||||
att_rx = 12;
|
||||
att_rx = 6;
|
||||
bands = [38];
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 125;
|
||||
|
||||
@@ -224,7 +224,7 @@ RUs =
|
||||
nb_tx = 1
|
||||
nb_rx = 1
|
||||
att_tx = 3
|
||||
att_rx = 6;
|
||||
att_rx = 0;
|
||||
bands = [7];
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 115;
|
||||
|
||||
@@ -224,7 +224,7 @@ RUs =
|
||||
nb_tx = 1
|
||||
nb_rx = 1
|
||||
att_tx = 3
|
||||
att_rx = 6;
|
||||
att_rx = 0;
|
||||
bands = [7];
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 115;
|
||||
|
||||
@@ -224,7 +224,7 @@ RUs =
|
||||
nb_tx = 1
|
||||
nb_rx = 1
|
||||
att_tx = 3
|
||||
att_rx = 6;
|
||||
att_rx = 0;
|
||||
bands = [7];
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 115;
|
||||
|
||||
@@ -224,7 +224,7 @@ RUs =
|
||||
nb_tx = 1
|
||||
nb_rx = 1
|
||||
att_tx = 3
|
||||
att_rx = 6;
|
||||
att_rx = 0;
|
||||
bands = [7];
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 115;
|
||||
|
||||
@@ -224,7 +224,7 @@ RUs =
|
||||
nb_tx = 1
|
||||
nb_rx = 1
|
||||
att_tx = 3
|
||||
att_rx = 6;
|
||||
att_rx = 0;
|
||||
bands = [7];
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 115;
|
||||
|
||||
@@ -224,7 +224,7 @@ RUs =
|
||||
nb_tx = 1
|
||||
nb_rx = 1
|
||||
att_tx = 3
|
||||
att_rx = 6;
|
||||
att_rx = 0;
|
||||
bands = [7];
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 115;
|
||||
|
||||
@@ -116,7 +116,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
@@ -198,6 +200,8 @@ RUs = (
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 114;
|
||||
eNB_instances = [0];
|
||||
#beamforming 1x4 matrix:
|
||||
bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000];
|
||||
clock_src = "internal";
|
||||
}
|
||||
);
|
||||
|
||||
@@ -118,9 +118,10 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -70;
|
||||
# TimingAdvanceOffset_n25600
|
||||
n_TimingAdvanceOffset = 1;
|
||||
|
||||
n_TimingAdvanceOffset = 0;
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
@@ -195,6 +196,8 @@ RUs = (
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 108;
|
||||
eNB_instances = [0];
|
||||
#beamforming 1x4 matrix:
|
||||
bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000];
|
||||
clock_src = "internal";
|
||||
}
|
||||
);
|
||||
|
||||
@@ -116,7 +116,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
@@ -198,6 +200,8 @@ RUs = (
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 114;
|
||||
eNB_instances = [0];
|
||||
#beamforming 1x4 matrix:
|
||||
bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000];
|
||||
clock_src = "internal";
|
||||
}
|
||||
);
|
||||
|
||||
@@ -22,9 +22,8 @@ gNBs =
|
||||
|
||||
////////// Physical parameters:
|
||||
|
||||
min_rxtxtime = 2;
|
||||
do_CSIRS = 1;
|
||||
do_SRS = 1;
|
||||
min_rxtxtime = 6;
|
||||
|
||||
|
||||
servingCellConfigCommon = (
|
||||
{
|
||||
@@ -118,7 +117,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
@@ -184,7 +185,7 @@ L1s = (
|
||||
num_cc = 1;
|
||||
tr_n_preference = "local_mac";
|
||||
prach_dtx_threshold = 200;
|
||||
pucch0_dtx_threshold = 30;
|
||||
pucch0_dtx_threshold = 100;
|
||||
ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0
|
||||
}
|
||||
);
|
||||
@@ -194,12 +195,14 @@ RUs = (
|
||||
local_rf = "yes"
|
||||
nb_tx = 1
|
||||
nb_rx = 1
|
||||
att_tx = 10;
|
||||
att_rx = 10;
|
||||
att_tx = 0
|
||||
att_rx = 0;
|
||||
bands = [78];
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 114;
|
||||
eNB_instances = [0];
|
||||
#beamforming 1x4 matrix:
|
||||
bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000];
|
||||
clock_src = "internal";
|
||||
}
|
||||
);
|
||||
|
||||
@@ -30,7 +30,6 @@ gNBs =
|
||||
////////// Physical parameters:
|
||||
|
||||
pdsch_AntennaPorts_XP = 2;
|
||||
pdsch_AntennaPorts_N1 = 2;
|
||||
pusch_AntennaPorts = 2;
|
||||
do_CSIRS = 1;
|
||||
do_SRS = 0;
|
||||
@@ -144,7 +143,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
@@ -167,10 +168,10 @@ gNBs =
|
||||
# pattern1
|
||||
# dl_UL_TransmissionPeriodicity
|
||||
# 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
|
||||
dl_UL_TransmissionPeriodicity = 6; #5;
|
||||
nrofDownlinkSlots = 6; #3;
|
||||
nrofDownlinkSymbols = 10; #6;
|
||||
nrofUplinkSlots = 3; #1;
|
||||
dl_UL_TransmissionPeriodicity = 5; #6;
|
||||
nrofDownlinkSlots = 3; #7;
|
||||
nrofDownlinkSymbols = 6;
|
||||
nrofUplinkSlots = 1; #2;
|
||||
nrofUplinkSymbols = 0;
|
||||
|
||||
ssPBCH_BlockPower = -25;
|
||||
|
||||
@@ -117,7 +117,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
@@ -187,6 +189,15 @@ RUs = (
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 75;
|
||||
eNB_instances = [0];
|
||||
##beamforming 1x2 matrix: 1 layer x 2 antennas
|
||||
bf_weights = [0x00007fff, 0x0000];
|
||||
##beamforming 1x4 matrix: 1 layer x 4 antennas
|
||||
#bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000];
|
||||
## beamforming 2x2 matrix:
|
||||
# bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff];
|
||||
## beamforming 4x4 matrix:
|
||||
#bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff];
|
||||
|
||||
sdr_addrs = "addr=192.168.10.2,mgmt_addr=192.168.10.2,second_addr=192.168.20.2";
|
||||
clock_src = "external";
|
||||
# if_freq = 3700000000L;
|
||||
|
||||
@@ -115,7 +115,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
@@ -198,6 +200,15 @@ RUs = (
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 50;
|
||||
eNB_instances = [0];
|
||||
## beamforming 1x2 matrix: 1 layer x 2 antennas
|
||||
bf_weights = [0x00007fff, 0x0000];
|
||||
## beamforming 1x4 matrix: 1 layer x 4 antennas
|
||||
#bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000];
|
||||
## beamforming 2x2 matrix:
|
||||
#bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff];
|
||||
## beamforming 4x4 matrix:
|
||||
#bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff];
|
||||
|
||||
sdr_addrs = "addr=192.168.10.2,second_addr=192.168.20.2";
|
||||
}
|
||||
);
|
||||
|
||||
@@ -115,7 +115,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
@@ -198,6 +200,15 @@ RUs = (
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 50;
|
||||
eNB_instances = [0];
|
||||
## beamforming 1x2 matrix: 1 layer x 2 antennas
|
||||
bf_weights = [0x00007fff, 0x0000];
|
||||
## beamforming 1x4 matrix: 1 layer x 4 antennas
|
||||
#bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000];
|
||||
## beamforming 2x2 matrix:
|
||||
#bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff];
|
||||
## beamforming 4x4 matrix:
|
||||
#bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff];
|
||||
|
||||
sdr_addrs = "addr=192.168.10.2,second_addr=192.168.20.2";
|
||||
}
|
||||
);
|
||||
|
||||
@@ -115,7 +115,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
@@ -191,6 +193,7 @@ RUs = ({
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 50;
|
||||
eNB_instances = [0];
|
||||
bf_weights = [0x00007fff, 0x0000];
|
||||
sdr_addrs = "addr=192.168.10.2,second_addr=192.168.20.2";
|
||||
});
|
||||
|
||||
|
||||
@@ -117,7 +117,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
@@ -193,6 +195,7 @@ RUs = ({
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 50;
|
||||
eNB_instances = [0];
|
||||
bf_weights = [0x00007fff, 0x0000];
|
||||
sdr_addrs = "addr=192.168.10.2,second_addr=192.168.20.2";
|
||||
});
|
||||
|
||||
|
||||
@@ -111,7 +111,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1; #0x80;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
|
||||
@@ -116,7 +116,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1; #0x80;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
@@ -211,6 +213,7 @@ RUs = (
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 75;
|
||||
eNB_instances = [0];
|
||||
bf_weights = [0x00007fff, 0x00007fff];
|
||||
#clock_src = "external";
|
||||
sf_extension = 0
|
||||
sdr_addrs = "mgmt_addr=172.21.19.14,addr=192.168.10.2,second_addr=192.168.20.2,clock_source=internal,time_source=internal"
|
||||
|
||||
@@ -23,8 +23,7 @@ gNBs =
|
||||
|
||||
sib1_tda = 15;
|
||||
min_rxtxtime = 6;
|
||||
beam_weights = [0]; // single SSB -> one analog beam
|
||||
|
||||
|
||||
servingCellConfigCommon = (
|
||||
{
|
||||
#spCellConfigCommon
|
||||
@@ -117,7 +116,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 3;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
@@ -178,9 +179,6 @@ MACRLCs = ({
|
||||
tr_n_preference = "local_RRC";
|
||||
pusch_TargetSNRx10 = 200;
|
||||
pucch_TargetSNRx10 = 200;
|
||||
set_analog_beamforming = 1;
|
||||
beam_duration = 1;
|
||||
beams_per_period = 1;
|
||||
});
|
||||
|
||||
L1s = (
|
||||
|
||||
@@ -113,7 +113,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
@@ -203,6 +205,8 @@ RUs = (
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 75;
|
||||
eNB_instances = [0];
|
||||
#beamforming 1x4 matrix:
|
||||
bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000];
|
||||
clock_src = "internal";
|
||||
}
|
||||
);
|
||||
|
||||
@@ -114,7 +114,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
@@ -203,6 +205,14 @@ RUs = (
|
||||
max_rxgain = 114;
|
||||
sf_extension = 0;
|
||||
eNB_instances = [0];
|
||||
##beamforming 1x2 matrix: 1 layer x 2 antennas
|
||||
bf_weights = [0x00007fff, 0x0000];
|
||||
##beamforming 1x4 matrix: 1 layer x 4 antennas
|
||||
#bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000];
|
||||
## beamforming 2x2 matrix:
|
||||
# bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff];
|
||||
## beamforming 4x4 matrix:
|
||||
#bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff];
|
||||
sdr_addrs = "type=x300";
|
||||
clock_src = "internal";
|
||||
# if_freq = 3700000000L;
|
||||
|
||||
@@ -120,7 +120,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -70;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
@@ -210,8 +212,10 @@ RUs = (
|
||||
att_rx = 0;
|
||||
bands = [77];
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 75;
|
||||
max_rxgain = 72;
|
||||
eNB_instances = [0];
|
||||
##beamforming 1x2 matrix: 1 layer x 2 antennas
|
||||
bf_weights = [0x00007fff, 0x0000];
|
||||
#clock_src = "internal";
|
||||
sdr_addrs = "addr=192.168.80.53, clock_source=internal,time_source=internal"
|
||||
|
||||
@@ -222,17 +226,17 @@ security = {
|
||||
# preferred ciphering algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
# valid values: nea0, nea1, nea2, nea3
|
||||
ciphering_algorithms = ( "nea1", "nea0" );
|
||||
ciphering_algorithms = ( "nea0" );
|
||||
|
||||
# preferred integrity algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
# valid values: nia0, nia1, nia2, nia3
|
||||
integrity_algorithms = ( "nia1", "nia0" );
|
||||
integrity_algorithms = ( "nia2", "nia0" );
|
||||
|
||||
# setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter
|
||||
# what 'ciphering_algorithms' configures; same thing for 'drb_integrity'
|
||||
drb_ciphering = "yes";
|
||||
drb_integrity = "yes";
|
||||
drb_integrity = "no";
|
||||
};
|
||||
|
||||
log_config :
|
||||
|
||||
@@ -123,7 +123,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 0;
|
||||
p0_nominal = -96;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 0x1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
@@ -152,7 +154,7 @@ gNBs =
|
||||
nrofUplinkSlots = 1;
|
||||
nrofUplinkSymbols = 4;
|
||||
|
||||
ssPBCH_BlockPower = -10;
|
||||
ssPBCH_BlockPower = 0;
|
||||
}
|
||||
|
||||
);
|
||||
@@ -220,6 +222,8 @@ RUs = (
|
||||
eNB_instances = [0];
|
||||
ru_thread_core = 5;
|
||||
sl_ahead = 5;
|
||||
##beamforming 1x2 matrix: 1 layer x 2 antennas
|
||||
bf_weights = [0x00007fff, 0x0000,0x00007fff, 0x0000];
|
||||
clock_src = "internal";
|
||||
tr_preference = "raw_if4p5"; # important: activate FHI7.2
|
||||
do_precoding = 0; # needs to match O-RU configuration
|
||||
|
||||
@@ -23,6 +23,7 @@ gNBs = (
|
||||
pusch_AntennaPorts = 2;
|
||||
do_CSIRS = 1;
|
||||
do_SRS = 1;
|
||||
ul_prbblacklist = "135,136,137,138"
|
||||
|
||||
servingCellConfigCommon = (
|
||||
{
|
||||
@@ -126,6 +127,10 @@ gNBs = (
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
subcarrierSpacing = 1;
|
||||
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
# ssb_periodicityServingCell
|
||||
# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1
|
||||
@@ -176,8 +181,8 @@ MACRLCs = (
|
||||
num_cc = 1;
|
||||
tr_s_preference = "local_L1";
|
||||
tr_n_preference = "local_RRC";
|
||||
pusch_TargetSNRx10 = 270;
|
||||
pucch_TargetSNRx10 = 270;
|
||||
pusch_TargetSNRx10 = 200;
|
||||
pucch_TargetSNRx10 = 200;
|
||||
pusch_FailureThres = 1000;
|
||||
ulsch_max_frame_inactivity = 0;
|
||||
ul_max_mcs = 25;
|
||||
@@ -199,12 +204,14 @@ RUs = (
|
||||
local_rf = "yes"
|
||||
nb_tx = 2;
|
||||
nb_rx = 2;
|
||||
att_tx = 15;
|
||||
att_tx = 12;
|
||||
att_rx = 0;
|
||||
bands = [77];
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 71;
|
||||
max_rxgain = 72;
|
||||
eNB_instances = [0];
|
||||
##beamforming 1x2 matrix: 1 layer x 2 antennas
|
||||
bf_weights = [0x00007fff, 0x0000];
|
||||
#clock_src = "internal";
|
||||
sdr_addrs = "addr=192.168.80.53,clock_source=internal,time_source=internal"
|
||||
}
|
||||
|
||||
@@ -111,7 +111,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
|
||||
@@ -124,7 +124,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -70;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
@@ -211,6 +213,8 @@ RUs = (
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 65;
|
||||
eNB_instances = [0];
|
||||
##beamforming 1x2 matrix: 1 layer x 2 antennas
|
||||
bf_weights = [0x00007fff, 0x0000];
|
||||
sf_extension = 0
|
||||
sdr_addrs = "addr=192.168.80.52,clock_source=internal,time_source=internal"
|
||||
}
|
||||
|
||||
@@ -32,20 +32,20 @@ gNBs =
|
||||
# downlinkConfigCommon
|
||||
#frequencyInfoDL
|
||||
# this is 3300.60 MHz + 53*12*30e-3 MHz = 3319.68
|
||||
absoluteFrequencySSB = 630048;
|
||||
absoluteFrequencySSB = 621312;
|
||||
dl_frequencyBand = 78;
|
||||
# this is 3300.60 MHz
|
||||
dl_absoluteFrequencyPointA = 626772;
|
||||
dl_absoluteFrequencyPointA = 620040;
|
||||
#scs-SpecificCarrierList
|
||||
dl_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
dl_subcarrierSpacing = 1;
|
||||
dl_carrierBandwidth = 273;
|
||||
dl_carrierBandwidth = 106;
|
||||
#initialDownlinkBWP
|
||||
#genericParameters
|
||||
# this is RBstart=27,L=48 (275*(L-1))+RBstart
|
||||
initialDLBWPlocationAndBandwidth = 1099; # 6366 12925 12956 28875 12952
|
||||
initialDLBWPlocationAndBandwidth = 28875; # 6366 12925 12956 28875 12952
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialDLBWPsubcarrierSpacing = 1;
|
||||
@@ -61,11 +61,11 @@ gNBs =
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
ul_subcarrierSpacing = 1;
|
||||
ul_carrierBandwidth = 273;
|
||||
ul_carrierBandwidth = 106;
|
||||
pMax = 20;
|
||||
#initialUplinkBWP
|
||||
#genericParameters
|
||||
initialULBWPlocationAndBandwidth = 1099;
|
||||
initialULBWPlocationAndBandwidth = 28875;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialULBWPsubcarrierSpacing = 1;
|
||||
@@ -115,7 +115,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -70;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
@@ -138,10 +140,10 @@ gNBs =
|
||||
# pattern1
|
||||
# dl_UL_TransmissionPeriodicity
|
||||
# 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
|
||||
dl_UL_TransmissionPeriodicity = 5;
|
||||
nrofDownlinkSlots = 3;
|
||||
dl_UL_TransmissionPeriodicity = 6;
|
||||
nrofDownlinkSlots = 7;
|
||||
nrofDownlinkSymbols = 6;
|
||||
nrofUplinkSlots = 1;
|
||||
nrofUplinkSlots = 2;
|
||||
nrofUplinkSymbols = 4;
|
||||
|
||||
ssPBCH_BlockPower = -25;
|
||||
@@ -177,6 +179,9 @@ MACRLCs = (
|
||||
num_cc = 1;
|
||||
tr_s_preference = "local_L1";
|
||||
tr_n_preference = "local_RRC";
|
||||
#pusch_TargetSNRx10 = 150;
|
||||
#pucch_TargetSNRx10 = 200;
|
||||
dl_max_mcs = 16; # there are retransmissions if more
|
||||
}
|
||||
);
|
||||
|
||||
@@ -185,6 +190,7 @@ L1s = (
|
||||
num_cc = 1;
|
||||
tr_n_preference = "local_mac";
|
||||
prach_dtx_threshold = 120;
|
||||
#pucch0_dtx_threshold = 120;
|
||||
}
|
||||
);
|
||||
|
||||
@@ -199,6 +205,8 @@ RUs = (
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 75;
|
||||
eNB_instances = [0];
|
||||
##beamforming 1x2 matrix: 1 layer x 2 antennas
|
||||
bf_weights = [0x00007fff, 0x0000];
|
||||
#clock_src = "internal";
|
||||
sdr_addrs = "mgmt_addr=192.168.10.2,addr=192.168.10.2,clock_source=internal,time_source=internal"
|
||||
}
|
||||
@@ -118,7 +118,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
@@ -205,6 +207,14 @@ RUs = (
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 75;
|
||||
eNB_instances = [0];
|
||||
##beamforming 1x2 matrix: 1 layer x 2 antennas
|
||||
bf_weights = [0x00007fff, 0x0000];
|
||||
##beamforming 1x4 matrix: 1 layer x 4 antennas
|
||||
#bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000];
|
||||
## beamforming 2x2 matrix:
|
||||
# bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff];
|
||||
## beamforming 4x4 matrix:
|
||||
#bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff];
|
||||
sf_extension = 0
|
||||
sdr_addrs = "serial=XXXXXXX"
|
||||
}
|
||||
|
||||
@@ -120,7 +120,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
@@ -266,6 +268,8 @@ RUs = ({
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 114;
|
||||
eNB_instances = [0];
|
||||
#beamforming 1x4 matrix:
|
||||
bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000];
|
||||
clock_src = "internal";
|
||||
});
|
||||
|
||||
|
||||
@@ -1,200 +0,0 @@
|
||||
Active_gNBs:
|
||||
- gnb-rfsim
|
||||
# Asn1_verbosity, choice in: none, info, annoying
|
||||
Asn1_verbosity: none
|
||||
gNBs:
|
||||
##### Identification parameters:
|
||||
- gNB_ID: 0xe00
|
||||
gNB_name: gnb-rfsim
|
||||
tracking_area_code: 1
|
||||
plmn_list:
|
||||
- mcc: 208
|
||||
mnc: 99
|
||||
mnc_length: 2
|
||||
snssaiList:
|
||||
- sst: 1
|
||||
sd: 0xffffff
|
||||
nr_cellid: 12345678
|
||||
##### Physical parameters:
|
||||
min_rxtxtime: 6
|
||||
servingCellConfigCommon:
|
||||
#spCellConfigCommon
|
||||
- physCellId: 0
|
||||
# downlinkConfigCommon
|
||||
#frequencyInfoDL
|
||||
# this is 3300.60 MHz + 53*12*30e-3 MHz = 3319.68
|
||||
absoluteFrequencySSB: 621312
|
||||
# this is 3300.60 MHz
|
||||
dl_absoluteFrequencyPointA: 620040
|
||||
#scs-SpecificCarrierList
|
||||
dl_offstToCarrier: 0
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
dl_subcarrierSpacing: 1
|
||||
dl_carrierBandwidth: 106
|
||||
#initialDownlinkBWP
|
||||
#genericParameters
|
||||
# this is RBstart=0,L=106 (275*(L-1))+RBstart
|
||||
initialDLBWPlocationAndBandwidth: 28875
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialDLBWPsubcarrierSpacing: 1
|
||||
#pdcch-ConfigCommon
|
||||
initialDLBWPcontrolResourceSetZero: 11
|
||||
initialDLBWPsearchSpaceZero: 0
|
||||
#uplinkConfigCommon
|
||||
#frequencyInfoUL
|
||||
ul_frequencyBand: 78
|
||||
#scs-SpecificCarrierList
|
||||
ul_offstToCarrier: 0
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
ul_subcarrierSpacing: 1
|
||||
ul_carrierBandwidth: 106
|
||||
pMax: 20
|
||||
#initialUplinkBWP
|
||||
#genericParameters
|
||||
initialULBWPlocationAndBandwidth: 28875
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialULBWPsubcarrierSpacing: 1
|
||||
#rach-ConfigCommon
|
||||
#rach-ConfigGeneric
|
||||
prach_ConfigurationIndex: 98
|
||||
#prach_msg1_FDM
|
||||
#0 = one, 1=two, 2=four, 3=eight
|
||||
prach_msg1_FDM: 0
|
||||
prach_msg1_FrequencyStart: 0
|
||||
zeroCorrelationZoneConfig: 12
|
||||
preambleReceivedTargetPower: -104
|
||||
#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
|
||||
preambleTransMax: 6
|
||||
#powerRampingStep
|
||||
# 0=dB0,1=dB2,2=dB4,3=dB6
|
||||
powerRampingStep: 1
|
||||
#ra_ReponseWindow
|
||||
#1,2,4,8,10,20,40,80
|
||||
ra_ResponseWindow: 5
|
||||
#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
|
||||
#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen
|
||||
ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR: 3
|
||||
#oneHalf (0..15) 4,8,12,16,...60,64
|
||||
ssb_perRACH_OccasionAndCB_PreamblesPerSSB: 15
|
||||
#ra_ContentionResolutionTimer
|
||||
#(0..7) 8,16,24,32,40,48,56,64
|
||||
ra_ContentionResolutionTimer: 7
|
||||
rsrp_ThresholdSSB: 19
|
||||
#prach-RootSequenceIndex_PR
|
||||
#1 = 839, 2 = 139
|
||||
prach_RootSequenceIndex_PR: 2
|
||||
prach_RootSequenceIndex: 1
|
||||
# SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
|
||||
msg1_SubcarrierSpacing: 1
|
||||
# restrictedSetConfig
|
||||
# 0=unrestricted, 1=restricted type A, 2=restricted type B
|
||||
restrictedSetConfig: 0
|
||||
msg3_DeltaPreamble: 1
|
||||
p0_NominalWithGrant: -90
|
||||
|
||||
# pucch-ConfigCommon setup :
|
||||
# pucchGroupHopping
|
||||
# 0 = neither, 1= group hopping, 2=sequence hopping
|
||||
pucchGroupHopping: 0
|
||||
hoppingId: 40
|
||||
p0_nominal: -90
|
||||
ssb_PositionsInBurst_Bitmap: 1
|
||||
# ssb_periodicityServingCell
|
||||
# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1
|
||||
ssb_periodicityServingCell: 2
|
||||
|
||||
# dmrs_TypeA_position
|
||||
# 0 = pos2, 1 = pos3
|
||||
dmrs_TypeA_Position: 0
|
||||
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
subcarrierSpacing: 1
|
||||
|
||||
#tdd-UL-DL-ConfigurationCommon
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
referenceSubcarrierSpacing: 1
|
||||
|
||||
# pattern1
|
||||
# dl_UL_TransmissionPeriodicity
|
||||
# 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
|
||||
dl_UL_TransmissionPeriodicity: 6
|
||||
nrofDownlinkSlots: 7
|
||||
nrofDownlinkSymbols: 6
|
||||
nrofUplinkSlots: 2
|
||||
nrofUplinkSymbols: 4
|
||||
ssPBCH_BlockPower: -25
|
||||
SCTP:
|
||||
SCTP_INSTREAMS: 2
|
||||
SCTP_OUTSTREAMS: 2
|
||||
|
||||
##### AMF parameters:
|
||||
amf_ip_address:
|
||||
- ipv4: 192.168.71.132
|
||||
|
||||
NETWORK_INTERFACES:
|
||||
GNB_IPV4_ADDRESS_FOR_NG_AMF: 192.168.71.140
|
||||
GNB_IPV4_ADDRESS_FOR_NGU: 192.168.71.140
|
||||
GNB_PORT_FOR_S1U: 2152 # Spec 2152
|
||||
|
||||
|
||||
MACRLCs:
|
||||
- num_cc: 1
|
||||
tr_s_preference: local_L1
|
||||
tr_n_preference: local_RRC
|
||||
pusch_TargetSNRx10: 200
|
||||
pucch_TargetSNRx10: 200
|
||||
|
||||
L1s:
|
||||
- num_cc: 1
|
||||
tr_n_preference: local_mac
|
||||
prach_dtx_threshold: 200
|
||||
# pucch0_dtx_threshold = 150;
|
||||
|
||||
RUs:
|
||||
- local_rf: yes
|
||||
nb_tx: 1
|
||||
nb_rx: 1
|
||||
att_tx: 0
|
||||
att_rx: 0
|
||||
bands: [78]
|
||||
max_pdschReferenceSignalPower: -27
|
||||
max_rxgain: 75
|
||||
eNB_instances: [0]
|
||||
sf_extension: 0
|
||||
sdr_addrs: serial=XXXXXXX
|
||||
|
||||
rfsimulator:
|
||||
serveraddr: server
|
||||
|
||||
security:
|
||||
# preferred ciphering algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
# valid values: nea0, nea1, nea2, nea3
|
||||
ciphering_algorithms: [nea0]
|
||||
|
||||
# preferred integrity algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
# valid values: nia0, nia1, nia2, nia3
|
||||
integrity_algorithms: [nia2, nia0]
|
||||
|
||||
# setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter
|
||||
# what 'ciphering_algorithms' configures; same thing for 'drb_integrity'
|
||||
drb_ciphering: yes
|
||||
drb_integrity: no
|
||||
|
||||
log_config:
|
||||
global_log_level: info
|
||||
hw_log_level: info
|
||||
phy_log_level: info
|
||||
mac_log_level: info
|
||||
rlc_log_level: info
|
||||
pdcp_log_level: info
|
||||
rrc_log_level: info
|
||||
ngap_log_level: debug
|
||||
f1ap_log_level: debug
|
||||
@@ -117,7 +117,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
@@ -204,6 +206,14 @@ RUs = (
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 68;
|
||||
eNB_instances = [0];
|
||||
##beamforming 1x2 matrix: 1 layer x 2 antennas
|
||||
bf_weights = [0x00007fff, 0x0000];
|
||||
##beamforming 1x4 matrix: 1 layer x 4 antennas
|
||||
#bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000];
|
||||
## beamforming 2x2 matrix:
|
||||
# bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff];
|
||||
## beamforming 4x4 matrix:
|
||||
#bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff];
|
||||
sf_extension = 0
|
||||
sdr_addrs = "mgmt_addr=172.21.19.14,addr=192.168.10.2,second_addr=192.168.20.2,clock_source=internal,time_source=internal"
|
||||
}
|
||||
|
||||
@@ -110,7 +110,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
@@ -175,6 +177,7 @@ MACRLCs = (
|
||||
pusch_TargetSNRx10 = 200;
|
||||
pucch_TargetSNRx10 = 200;
|
||||
ul_prbblack_SNR_threshold = 10;
|
||||
ul_max_mcs = 9;
|
||||
}
|
||||
);
|
||||
|
||||
@@ -183,7 +186,7 @@ L1s = (
|
||||
num_cc = 1;
|
||||
tr_n_preference = "local_mac";
|
||||
prach_dtx_threshold = 120;
|
||||
pucch0_dtx_threshold = 30;
|
||||
pucch0_dtx_threshold = 100;
|
||||
ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0
|
||||
}
|
||||
);
|
||||
@@ -193,12 +196,14 @@ RUs = (
|
||||
local_rf = "yes"
|
||||
nb_tx = 1
|
||||
nb_rx = 1
|
||||
att_tx = 10;
|
||||
att_rx = 10;
|
||||
att_tx = 14;
|
||||
att_rx = 14;
|
||||
bands = [78];
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 114;
|
||||
eNB_instances = [0];
|
||||
#beamforming 1x4 matrix:
|
||||
bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000];
|
||||
clock_src = "internal";
|
||||
}
|
||||
);
|
||||
|
||||
@@ -130,7 +130,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
@@ -217,6 +219,14 @@ RUs = (
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 68;
|
||||
eNB_instances = [0];
|
||||
##beamforming 1x2 matrix: 1 layer x 2 antennas
|
||||
bf_weights = [0x00007fff, 0x0000];
|
||||
##beamforming 1x4 matrix: 1 layer x 4 antennas
|
||||
#bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000];
|
||||
## beamforming 2x2 matrix:
|
||||
# bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff];
|
||||
## beamforming 4x4 matrix:
|
||||
#bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff];
|
||||
sf_extension = 0
|
||||
sdr_addrs = "mgmt_addr=172.21.19.14,addr=192.168.10.2,second_addr=192.168.20.2,clock_source=internal,time_source=internal"
|
||||
sl_ahead = 5;
|
||||
|
||||
@@ -131,7 +131,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
@@ -218,6 +220,14 @@ RUs = (
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 75;
|
||||
eNB_instances = [0];
|
||||
##beamforming 1x2 matrix: 1 layer x 2 antennas
|
||||
bf_weights = [0x00007fff, 0x0000];
|
||||
##beamforming 1x4 matrix: 1 layer x 4 antennas
|
||||
#bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000];
|
||||
## beamforming 2x2 matrix:
|
||||
# bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff];
|
||||
## beamforming 4x4 matrix:
|
||||
#bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff];
|
||||
sf_extension = 0
|
||||
sdr_addrs = "mgmt_addr=172.21.19.14,addr=192.168.10.2,second_addr=192.168.20.2,clock_source=internal,time_source=internal"
|
||||
}
|
||||
|
||||
@@ -112,7 +112,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
@@ -203,6 +205,8 @@ RUs = (
|
||||
max_rxgain = 114;
|
||||
sf_extension = 0;
|
||||
eNB_instances = [0];
|
||||
#beamforming 1x4 matrix:
|
||||
bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000];
|
||||
clock_src = "internal";
|
||||
}
|
||||
);
|
||||
|
||||
@@ -126,7 +126,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 0;
|
||||
p0_nominal = -96;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 0x1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
@@ -227,6 +229,8 @@ RUs = (
|
||||
eNB_instances = [0];
|
||||
ru_thread_core = 5;
|
||||
sl_ahead = 10;
|
||||
##beamforming 1x2 matrix: 1 layer x 2 antennas
|
||||
bf_weights = [0x00007fff, 0x0000,0x00007fff, 0x0000];
|
||||
tr_preference = "raw_if4p5"; # important: activate FHI7.2
|
||||
do_precoding = 0; # needs to match O-RU configuration
|
||||
}
|
||||
|
||||
@@ -21,10 +21,10 @@ gNBs =
|
||||
nr_cellid = 12345678L
|
||||
|
||||
////////// Physical parameters:
|
||||
pdsch_AntennaPorts_XP = 1;
|
||||
pusch_AntennaPorts = 1;
|
||||
pdsch_AntennaPorts_XP = 2;
|
||||
pusch_AntennaPorts = 2;
|
||||
do_CSIRS = 1;
|
||||
do_SRS = 0;
|
||||
do_SRS = 1;
|
||||
|
||||
servingCellConfigCommon = (
|
||||
{
|
||||
@@ -34,11 +34,11 @@ gNBs =
|
||||
|
||||
# downlinkConfigCommon
|
||||
#frequencyInfoDL
|
||||
# this is 3469.44 MHz => 301 REs from PointA 25 PRBs + 1 RE
|
||||
absoluteFrequencySSB = 631296;
|
||||
# this is 3410.4 MHz => 301 REs from PointA 25 PRBs + 1 RE
|
||||
absoluteFrequencySSB = 630048;
|
||||
dl_frequencyBand = 78;
|
||||
# this is 3469.44 - (51*12*30e-3/2) = 3460.26 MHz
|
||||
dl_absoluteFrequencyPointA = 630684;
|
||||
# this is 3410.4 - (51*12*30e-3/2) = 3401.22 MHz
|
||||
dl_absoluteFrequencyPointA = 629436;
|
||||
#scs-SpecificCarrierList
|
||||
dl_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
@@ -119,7 +119,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -96;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
@@ -207,8 +209,8 @@ RUs = (
|
||||
remote_portd = 52183;
|
||||
local_rf = "no"
|
||||
tr_preference = "udp_ecpri_if5"
|
||||
nb_tx = 1
|
||||
nb_rx = 1
|
||||
nb_tx = 2
|
||||
nb_rx = 2
|
||||
att_tx = 18
|
||||
att_rx = 0;
|
||||
num_tp_cores = 4;
|
||||
@@ -219,6 +221,14 @@ RUs = (
|
||||
eNB_instances = [0];
|
||||
bands = [78];
|
||||
sl_ahead = 5;
|
||||
##beamforming 1x2 matrix: 1 layer x 2 antennas
|
||||
bf_weights = [0x00007fff, 0x0000];
|
||||
##beamforming 1x4 matrix: 1 layer x 4 antennas
|
||||
#bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000];
|
||||
## beamforming 2x2 matrix:
|
||||
# bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff];
|
||||
## beamforming 4x4 matrix:
|
||||
#bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff];
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -110,7 +110,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
@@ -199,6 +201,8 @@ RUs = (
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 114;
|
||||
eNB_instances = [0];
|
||||
#beamforming 1x4 matrix:
|
||||
bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000];
|
||||
clock_src = "internal";
|
||||
}
|
||||
);
|
||||
|
||||
@@ -62,12 +62,12 @@ nr_measurement_configuration = {
|
||||
};
|
||||
|
||||
A3 = ({
|
||||
physCellId = -1; #Default
|
||||
cell_id = -1; #Default
|
||||
offset = 10;
|
||||
hysteresis = 0;
|
||||
timeToTrigger = 1
|
||||
}, {
|
||||
physCellId = 2;
|
||||
cell_id = 2;
|
||||
offset = 5;
|
||||
hysteresis = 1;
|
||||
timeToTrigger = 2
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
uicc0:
|
||||
imsi: 208990100001100
|
||||
key: fec86ba6eb707ed08905757b1bb44b8f
|
||||
opc: C42449363BBAD02B66D16BC975D77CC1
|
||||
dnn: oai
|
||||
nssai_sst: 1
|
||||
|
||||
#/* configuration for channel modelisation */
|
||||
#/* To be included in main config file when */
|
||||
#/* channel modelisation is used (rfsimulator with chanmod options enabled) */
|
||||
channelmod:
|
||||
max_chan: 10
|
||||
modellist: modellist_rfsimu_1
|
||||
modellist_rfsimu_1:
|
||||
- model_name: rfsimu_channel_enB0
|
||||
type: AWGN
|
||||
ploss_dB: 20
|
||||
noise_power_dB: -4
|
||||
forgetfact: 0
|
||||
offset: 0
|
||||
ds_tdl: 0
|
||||
- model_name: rfsimu_channel_ue0
|
||||
type: AWGN
|
||||
ploss_dB: 20
|
||||
nose_power_dB: -2
|
||||
forgetfact: 0
|
||||
offset: 0
|
||||
ds_tdl: 0
|
||||
@@ -118,7 +118,9 @@ gNBs =
|
||||
hoppingId = 40;
|
||||
#p0_nominal = -90;
|
||||
p0_nominal = -118;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1; #0x80;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
|
||||
@@ -116,7 +116,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1; #0x80;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
|
||||
@@ -114,7 +114,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
|
||||
@@ -115,7 +115,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
|
||||
@@ -130,8 +130,10 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1
|
||||
@@ -217,6 +219,15 @@ RUs = (
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 75;
|
||||
eNB_instances = [0];
|
||||
##beamforming 1x2 matrix: 1 layer x 2 antennas
|
||||
bf_weights = [0x00007fff, 0x0000];
|
||||
##beamforming 1x4 matrix: 1 layer x 4 antennas
|
||||
#bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000];
|
||||
## beamforming 2x2 matrix:
|
||||
# bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff];
|
||||
## beamforming 4x4 matrix:
|
||||
#bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff];
|
||||
|
||||
sdr_addrs = "mgmt_addr=172.21.19.14,addr=192.168.10.2,second_addr=192.168.20.2,clock_source=internal,time_source=internal"
|
||||
}
|
||||
);
|
||||
|
||||
@@ -127,7 +127,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
@@ -213,6 +215,15 @@ RUs = (
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 75;
|
||||
eNB_instances = [0];
|
||||
##beamforming 1x2 matrix: 1 layer x 2 antennas
|
||||
bf_weights = [0x00007fff, 0x0000];
|
||||
##beamforming 1x4 matrix: 1 layer x 4 antennas
|
||||
#bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000];
|
||||
## beamforming 2x2 matrix:
|
||||
# bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff];
|
||||
## beamforming 4x4 matrix:
|
||||
#bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff];
|
||||
|
||||
sdr_addrs = "mgmt_addr=172.21.19.14,addr=192.168.10.2,second_addr=192.168.20.2,clock_source=internal,time_source=internal"
|
||||
}
|
||||
);
|
||||
|
||||
@@ -135,7 +135,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
@@ -221,6 +223,14 @@ RUs = (
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 75;
|
||||
eNB_instances = [0];
|
||||
##beamforming 1x2 matrix: 1 layer x 2 antennas
|
||||
bf_weights = [0x00007fff, 0x0000];
|
||||
##beamforming 1x4 matrix: 1 layer x 4 antennas
|
||||
#bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000];
|
||||
## beamforming 2x2 matrix:
|
||||
# bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff];
|
||||
## beamforming 4x4 matrix:
|
||||
#bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff];
|
||||
sf_extension = 0
|
||||
sdr_addrs = "mgmt_addr=172.21.19.14,addr=192.168.10.2,second_addr=192.168.20.2,clock_source=internal,time_source=internal"
|
||||
}
|
||||
|
||||
@@ -110,7 +110,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1; #0x80;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
|
||||
@@ -115,7 +115,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1; #0x80;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
|
||||
@@ -113,7 +113,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
@@ -203,6 +205,8 @@ RUs = (
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 75;
|
||||
eNB_instances = [0];
|
||||
#beamforming 1x4 matrix:
|
||||
bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000];
|
||||
clock_src = "internal";
|
||||
}
|
||||
);
|
||||
|
||||
@@ -112,7 +112,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
@@ -201,6 +203,8 @@ RUs = (
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 114;
|
||||
eNB_instances = [0];
|
||||
#beamforming 1x4 matrix:
|
||||
bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000];
|
||||
clock_src = "internal";
|
||||
}
|
||||
);
|
||||
|
||||
@@ -111,7 +111,9 @@ gNBs =
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
|
||||
20
ci-scripts/cots_ue_ctl.yaml
Normal file
20
ci-scripts/cots_ue_ctl.yaml
Normal file
@@ -0,0 +1,20 @@
|
||||
9d690a12: #oppo
|
||||
- adb shell input keyevent KEYCODE_POWER
|
||||
- adb shell input swipe 300 700 300 0
|
||||
- adb shell am start -a android.settings.AIRPLANE_MODE_SETTINGS
|
||||
- adb shell input keyevent 20
|
||||
- adb shell input tap 968 324
|
||||
002: #s10
|
||||
- adb shell input keyevent KEYCODE_POWER
|
||||
- adb shell input swipe 200 900 200 300
|
||||
- adb shell am start -a android.settings.AIRPLANE_MODE_SETTINGS
|
||||
- adb shell input tap 968 324
|
||||
003: #s20
|
||||
- adb shell input keyevent KEYCODE_POWER
|
||||
- adb shell input swipe 200 900 200 300
|
||||
- adb shell am start -a android.settings.AIRPLANE_MODE_SETTINGS
|
||||
- adb shell input tap 968 324
|
||||
004: #xperia
|
||||
- tbd
|
||||
- tbd
|
||||
- tbd
|
||||
@@ -126,7 +126,7 @@ git config user.email "jenkins@openairinterface.org"
|
||||
git config user.name "OAI Jenkins"
|
||||
|
||||
git checkout -f $SOURCE_COMMIT_ID > checkout.txt 2>&1
|
||||
STATUS=`grep -E -c "fatal: reference is not a tree" checkout.txt`
|
||||
STATUS=`egrep -c "fatal: reference is not a tree" checkout.txt`
|
||||
rm -f checkout.txt
|
||||
if [ $STATUS -ne 0 ]
|
||||
then
|
||||
@@ -137,7 +137,7 @@ fi
|
||||
|
||||
git merge --ff $TARGET_COMMIT_ID -m "Temporary merge for CI"
|
||||
|
||||
STATUS=`git status | grep -E -c "You have unmerged paths.|fix conflicts"`
|
||||
STATUS=`git status | egrep -c "You have unmerged paths.|fix conflicts"`
|
||||
if [ $STATUS -ne 0 ]
|
||||
then
|
||||
echo "There are merge conflicts.. Cannot perform further build tasks"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user