Compare commits

...

90 Commits

Author SHA1 Message Date
Michael Dürre
d73b07475f pre-devcontainer-rebuild 2023-03-24 17:10:55 +00:00
Michael Dürre
d67c03a264 fix build script 2023-03-14 11:13:50 +00:00
Michael Dürre
c15e00f3e9 update integration solution for all VES messages 2023-03-14 11:13:31 +00:00
Michael Dürre
ccd46058c6 commiting all the changes so far; work in progress 2023-03-09 16:14:41 +00:00
Michael Dürre
7598c0cac7 add o1Config section to gnb.conf 2023-03-01 15:02:56 +00:00
Michael Dürre
c66eec2b7d [adrian] first commit to save status 2023-02-24 09:07:31 +00:00
Michael Dürre
a61e569cb2 add partially filled example for gnb 2023-02-14 07:24:12 +00:00
Michael Dürre
006aaaaa8d fix docker-compose for the gnb 2023-02-14 07:23:40 +00:00
Michael Dürre
9d8dad92b5 fix gnb docker build 2023-02-14 07:23:21 +00:00
Michael Dürre
bfab79924a add integration folder to test 2023-02-14 06:27:31 +00:00
Adrian Lita
3d26fc5146 added netconf dependencies and tried ubuntu22 with no success 2023-02-07 14:10:42 +01:00
Michael Dürre
7045fd089c add yang specs 2023-01-31 16:50:30 +00:00
Robert Schmidt
5d58645a85 Merge branch 'integration_2023_w03' into 'develop'
integration_2023_w03

See merge request oai/openairinterface5g!1919

!1880 Fix to schedule NR SRS K2 slots in advance
!1885 cleaning only
!1912 Correctly encode DNN length/APN name
!1913 bugfix: initialize all variables of the 'context' thing
!1914 bugfix: avoid a crash when oai_exit is set
!1915 remove patch in install_simde_from_source()
!1882 CI: Add more RFsim tests, cleanup
2023-01-21 11:04:36 +00:00
Robert Schmidt
d501025037 Merge remote-tracking branch 'origin/more-rfsim-tests' into integration_2023_w03 2023-01-20 17:45:05 +01:00
Robert Schmidt
5b2b0432c9 Merge remote-tracking branch 'origin/simde-patch-in-upstream' into integration_2023_w03 2023-01-20 12:29:15 +01:00
Robert Schmidt
1f21757d62 Merge remote-tracking branch 'origin/bugfix-better-exit-eth-udp' into integration_2023_w03 2023-01-20 12:29:09 +01:00
Robert Schmidt
206f8ae187 Merge remote-tracking branch 'origin/bugfix-fix-context' into integration_2023_w03 2023-01-20 12:29:04 +01:00
Robert Schmidt
60bf3a9869 Merge remote-tracking branch 'origin/fix-dnn-size' into integration_2023_w03 2023-01-20 12:28:59 +01:00
Robert Schmidt
d0bc613d64 Merge remote-tracking branch 'origin/cleaning-vars-h' into integration_2023_w03 2023-01-20 12:28:53 +01:00
laurent
b74ba0fb92 cleaning only 2023-01-19 14:52:39 +01:00
Cedric Roux
565b8482f9 remove patch in install_simde_from_source()
upstream took it
2023-01-18 13:01:37 +01:00
Cedric Roux
fc7bcceca9 fix a small bug and add a log for when recvfrom() fails
recvfrom() returns ssize_t, not size_t.
2023-01-18 10:23:37 +01:00
Cedric Roux
08e57ca313 bugfix: use correct size in malloc() 2023-01-17 15:03:44 +01:00
Cedric Roux
3674a6f0f2 bugfix: initialize all variables of the 'context' thing
There was a problem in rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND()
where we PROTOCOL_CTXT_SET_BY_INSTANCE() that does not initialize
eNB_index leading to a crash later on in pdcp. So let's initialize
everything.

Plus, while we're here, use do { } while(0) in the macros, just to avoid
problems like:

  if (condition)
    macro;

Without do { } while(0) only the first statement of the macro is done
in the if. (Not sure if the code has the problem somewhere, but doesn't
hurt to fix.)
2023-01-17 13:19:30 +01:00
Cedric Roux
924d88bbf9 bugfix: avoid a crash when oai_exit is set
There was a crash when we exit the nr softmodem with AW2S device.
The array rxbase[] was surely freed() by some other thread, so
let's not access it after detecting oai_exit != 0.

We also need to unblock a possible reader thread. The chosen way to
do may be not the best. To be checked.
2023-01-17 13:06:25 +01:00
Robert Schmidt
90a836a022 Correctly encode DNN length/APN name 2023-01-17 11:38:57 +01:00
francescomani
f9f6283cc3 schedule SRS K2 slots in advance 2023-01-14 17:51:27 +01:00
Robert Schmidt
214aa50595 Merge branch 'integration_2023_w02' into 'develop'
integration_2023_w02

See merge request oai/openairinterface5g!1906

!1796 Make SFN dependent on GPS time
!1874 Processing time optimization for SRS
!1881 Fix documentation of dot_product()
!1884 Prevent Msg3 to be scheduled in downlink slot when nrofUplinkSymbols = 0 and DDDSU
!1888 Adopting new BWP structure at UE (first MR)
!1890 Fix setup_time overflow in VNF processing thread
!1892 system.c cleaning check result of system call
!1893 fix buildhelper Soapy folder name, case not respected, reinstall was broken
!1894 doc(ci): adding constraint on the branch name
!1895 ASN_SEQUENCE_ADD return code was checked only in 0.5% of calls
!1900 bugfix CU/DU: use correct IP address for GTP-U
!1901 Adding NRPPA ASN1 definitions and library
!1903 bugfix in function channelmod_modify_cmd
!1867 CI: new Python classes for SSH & Local execution
restore LDPC docs
2023-01-14 08:39:57 +00:00
Robert Schmidt
7d3100dbe7 Force correct min_rxtxtime in OAI UE test 2023-01-13 13:42:13 +01:00
Robert Schmidt
18b9135c4f Fix warning in nFAPI 2023-01-12 18:05:16 +01:00
Robert Schmidt
75e542c6ad Restore LDPC decdoer documentation 2023-01-12 18:02:45 +01:00
Robert Schmidt
da099ca77a Merge remote-tracking branch 'origin/ci-new-ssh' into integration_2023_w02 2023-01-12 17:58:09 +01:00
Robert Schmidt
f36d7e8e96 Merge remote-tracking branch 'origin/bugfix_channelmod_modify_cmd' into integration_2023_w02 2023-01-12 17:57:23 +01:00
Robert Schmidt
1e812a4b7c Merge remote-tracking branch 'origin/nrppa_new' into integration_2023_w02 2023-01-12 17:57:14 +01:00
Robert Schmidt
2c3e4ef47f Merge remote-tracking branch 'origin/bugfix-cu-du-gtpu-correct-address' into integration_2023_w02 2023-01-12 17:57:06 +01:00
Robert Schmidt
47a4da8d5f Merge remote-tracking branch 'origin/fix-check-return-ASN_SEQUENCE_ADD' into integration_2023_w02 2023-01-12 17:56:56 +01:00
Robert Schmidt
3598180557 Merge remote-tracking branch 'origin/documentation-branch-name' into integration_2023_w02 2023-01-12 17:56:13 +01:00
Robert Schmidt
a040fbddf2 Merge remote-tracking branch 'origin/kharobcom_fixbuildhelper' into integration_2023_w02 2023-01-12 17:56:03 +01:00
Robert Schmidt
6620471822 Merge remote-tracking branch 'origin/kharobcom_cleansystemfile' into integration_2023_w02 2023-01-12 17:55:54 +01:00
Robert Schmidt
da70a37551 Merge remote-tracking branch 'origin/FAPI_fix_setup_time_from_overflowing' into integration_2023_w02 2023-01-12 17:55:42 +01:00
Robert Schmidt
ce1246e0dd Merge remote-tracking branch 'origin/NR_UE_BWP_reworking' into integration_2022_wk02 2023-01-12 17:49:22 +01:00
Robert Schmidt
3b4371e01c Merge remote-tracking branch 'origin/Hotfix_Msg3_scheduling' into integration_2022_wk02 2023-01-12 17:46:27 +01:00
Robert Schmidt
6886f0d3dd Merge remote-tracking branch 'origin/dot-prod-doc' into integration_2022_wk02 2023-01-12 17:46:19 +01:00
Robert Schmidt
451937d88b Merge remote-tracking branch 'origin/develop-SRS-in-ulsim' into integration_2022_wk02 2023-01-12 17:46:09 +01:00
Robert Schmidt
b780c9db80 Workaround: MCS>16 leads to retx in 2x2 2023-01-12 17:26:49 +01:00
Karim Harouat
096a32bf16 system.c : cleaning check result of system call 2023-01-12 14:28:38 +01:00
Rúben Soares da Silva
cdf7fb6f70 Fix setup_time overflow in vnf processing thread, preventing gNB from stopping message processing once setup_time overflowed 2023-01-12 10:17:03 +00:00
Robert Schmidt
3b9107228a cls_containerize: Add comment to help understand the magnitude of size 2023-01-11 15:15:08 +01:00
Robert Schmidt
57dbc79668 cls_physim1: Mention python version and separate Python/own modules 2023-01-11 15:15:08 +01:00
Robert Schmidt
074cf91bec cls_cluster: various fixes after review
- Mention python version and separate Python/own modules
- Use constants for registry and namespace name
- Provide OC url in oc login
- Do not perform oc logout in background
2023-01-11 15:15:06 +01:00
Robert Schmidt
941acb2e8d Tag cluster images with branch and commit ID 2023-01-11 15:15:06 +01:00
Robert Schmidt
7361c1689e Use new SSH class to execute image build 2023-01-11 15:15:06 +01:00
Robert Schmidt
de4a9e1d5a Use new SSH class to execute cluster build 2023-01-11 15:13:21 +01:00
Robert Schmidt
ce03b84898 Add new SSH/local cmd classes 2023-01-11 15:10:55 +01:00
Adeel Malik
affa5e3086 bugfix in function channelmod_modify_cmd 2023-01-11 11:12:19 +01:00
Florian Kaltenberger
89bddc76f0 addressing reviewer comments 2023-01-11 10:13:01 +01:00
Robert Schmidt
21ef822c45 Shorten IP address buffer to avoid strncpy() warning 2023-01-11 09:59:39 +01:00
laurent
9a789dbb8a ASN_SEQUENCE_ADD return code was checked only in 0.5% of calls, existing errors not detected by sanitize address 2023-01-11 09:59:39 +01:00
Florian Kaltenberger
24237b3e35 adapting ans1 handling of NRPPA to new framework 2023-01-10 11:26:27 +01:00
Florian Kaltenberger
1434175a84 adding Mohsen's NRPPA main program to CMakeLists.txt 2023-01-10 10:23:55 +01:00
ahadi
b7762141e8 added NRPPA .asm file and compiled the functions to CMakeFiles 2023-01-10 10:21:05 +01:00
Cedric Roux
551aee172a bugfix CU/DU: use correct IP address for GTP-U
Not only the teid is received from the DU but also the IP address. We
have to use it too.

Also, don't connect the UDP socket. The parameter remote_s_address in the
configuration file must not be used, at least not for gtp-u because the
IP address is received from the DU (plus for later, for multiple DUs, it
won't work at all).
2023-01-09 15:19:07 +01:00
Raphael Defosseux
719e36159d doc(ci): adding constraint on the branch name
Signed-off-by: Raphael Defosseux <raphael.defosseux@eurecom.fr>
2023-01-03 09:58:02 +01:00
francescomani
01030bbc4e L2 simulator fix 2022-12-30 10:32:58 +01:00
Karim Harouat
f277a27f57 fix buildhelper Saopy folder name, case not respected, reinstall was broken 2022-12-30 08:54:53 +01:00
francescomani
5300c57f3d common BWP structure and further improvements 2022-12-27 19:00:41 +01:00
francescomani
e55e880b71 cleaning up of dci functions 2022-12-27 18:32:30 +01:00
francescomani
1e6db77be7 first commit 2022-12-27 18:26:06 +01:00
Florian Kaltenberger
675ebb1f22 attempt to fix issues when starting with SFN > 0 2022-12-27 16:01:44 +01:00
Florian Kaltenberger
ad6c250595 adressing reviewer comment 2022-12-27 11:49:47 +01:00
Florian Kaltenberger
00c36d7b40 fixing "making SFN dependent on GPS time"
in fact it syncs the USRP time to GPS time when available and then derives the SFN from the USRP time.
2022-12-27 11:49:47 +01:00
Roberto Louro Magueta
a7db9280b8 Generate SRS sequence only when needed 2022-12-23 10:39:11 +00:00
Roberto Louro Magueta
c6bfb97988 Remove calloc of report_tlv, prg_list and prgs 2022-12-23 10:39:11 +00:00
Roberto Louro Magueta
f7a34d4274 Rename some variables 2022-12-23 10:39:11 +00:00
Roberto Louro Magueta
4c6a1c722b Change input of rrc_get_max_nr_csrs() from uint8_t to int 2022-12-23 10:39:11 +00:00
Roberto Louro Magueta
01ddccb101 Fix size of IQ channel_matrix of SRS 2022-12-23 10:39:11 +00:00
Roberto Louro Magueta
b95b95e7a7 Add SRS time stats in nr_ulsim 2022-12-23 10:39:11 +00:00
Roberto Louro Magueta
44dabd7377 Add SRS enable/disable as input command line in nr_ulsim 2022-12-23 10:39:10 +00:00
Roberto Louro Magueta
93770edc8a Add SRS in nr_ulsim 2022-12-23 10:39:10 +00:00
luis_pereira87
4a518335bb Prevent Msg3 to be scheduled in downlink slot when nrofUplinkSymbols = 0 and DDDSU 2022-12-22 18:17:10 +00:00
Robert Schmidt
9de7f5838b Correct naming: slash interferes with sed 2022-12-22 16:42:39 +01:00
Robert Schmidt
10e9474e67 Add forgotten file 2022-12-22 13:02:03 +01:00
Robert Schmidt
387ff92ab3 CI: Add 5G RFsim u0/25prb test 2022-12-22 12:58:01 +01:00
Robert Schmidt
69b6d7ed5b CI: docker-compose file for RFsim u0/25prb 2022-12-22 12:58:01 +01:00
Robert Schmidt
a74ced54a2 CI: Add 5G RFsim 2x2 test 2022-12-22 12:58:01 +01:00
Robert Schmidt
cc04996bd5 CI: docker-compose file for RFsim 2x2 test 2022-12-22 12:58:01 +01:00
Robert Schmidt
c4963ed16d CI: support cmd_prefix for OAI UE 2022-12-22 12:58:01 +01:00
Robert Schmidt
3e3dd82433 CI: Remove legacy bash scripts 2022-12-22 12:57:56 +01:00
Robert Schmidt
c54cf49f27 CI: stop containers more quickly
- avoid wasting time
- might prevent excess HARQ retx messing up the logs
2022-12-22 12:57:20 +01:00
laurent
ef65ad6cd5 fix doc only 2022-12-22 11:36:24 +01:00
388 changed files with 33284 additions and 11573 deletions

5
.gitignore vendored
View File

@@ -22,3 +22,8 @@ tags
nfapi_nr_interface_scf
*.log
*.out
**/*_3gpp*.yang
**/specification/available-yangs
**/integration/dcae/externalRepo
/dev

View File

@@ -525,7 +525,6 @@ target_link_libraries(f1ap PRIVATE ngap nr_rrc)
##############
# target asn1_lpp in openair3/LPP/MESSAGES/CMakeLists.txt used below
# Hardware dependant options
###################################
add_list1_option(NB_ANTENNAS_RX "4" "Number of antennas in reception" "1" "2" "4")
@@ -2430,6 +2429,13 @@ add_executable(nr-softmodem
${OPENAIR_DIR}/common/utils/lte/ue_power.c
${OPENAIR_DIR}/common/utils/lte/prach_utils.c
${OPENAIR_DIR}/common/utils/nr/nr_common.c
${OPENAIR_DIR}/common/utils/netconf/netconf_session.c
${OPENAIR_DIR}/common/utils/netconf/netconf.c
${OPENAIR_DIR}/common/utils/netconf/netconf_demos.c
${OPENAIR_DIR}/common/utils/netconf/o1config.c
${OPENAIR_DIR}/common/utils/netconf/utils.c
${OPENAIR_DIR}/common/utils/netconf/ves_demo_alarm.c
${OPENAIR_DIR}/common/utils/netconf/ves.c
${PHY_INTERFACE_DIR}/queue_t.c
${XFORMSINTERFACE_SOURCE}
${T_SOURCE}
@@ -2449,6 +2455,7 @@ target_link_libraries(nr-softmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPT
target_link_libraries(nr-softmodem PRIVATE ${LIB_LMS_LIBRARIES})
target_link_libraries(nr-softmodem PRIVATE ${T_LIB})
target_link_libraries(nr-softmodem PRIVATE asn1_nr_rrc asn1_lte_rrc)
target_link_libraries(nr-softmodem PRIVATE yang sysrepo curl)
add_dependencies( nr-softmodem ldpc_orig ldpc_optim ldpc_optim8seg ldpc)
@@ -2843,6 +2850,7 @@ if(OAI_NW_DRIVER_USE_NETLINK)
endif()
make_driver(ue_ip ${OPENAIR2_DIR}/NETWORK_DRIVER/UE_IP ${ue_ip_src})
#include (common/utils/netconf/netconf_CMakeLists.txt)
include (common/utils/telnetsrv/telnetsrv_CMakeLists.txt)
include(${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_tools/CMakeLists.txt)
include (${OPENAIR_DIR}/common/utils/websrv/websrv_CMakeLists.txt)

View File

@@ -12,6 +12,8 @@ We want to make contributing to this project as easy and transparent as possible
* This decision was made for the license reasons.
* The Continuous Integration will reject your merge request.
- All merge requests SHALL have `develop` branch as target branch.
- All merge requests SHALL have source branch names that SHALL not contain the `/` character.
* We are using a `docker` registry scheme and the image names are based on the source branch name.
## Coding Styles ##

80
build-gnb-docker.sh Executable file
View File

@@ -0,0 +1,80 @@
#!/bin/bash
OSBASE="ubuntu22"
TIMESTAMP=$(date -u +'%Y%m%dT%H%M%SZ')
TIMESTAMP_TAG="$OSBASE-$TIMESTAMP"
BUILD_RAN_BASE="false"
BUILD_RAN_BUILD="false"
BUILD_RAN_DEV="false"
BUILD_RAN_GNB="false"
until [ -z "$1" ]
do
case "$1" in
--all)
BUILD_RAN_BASE="true"
BUILD_RAN_BUILD="true"
BUILD_RAN_DEV="true"
BUILD_RAN_GNB="true"
shift
;;
--base)
BUILD_RAN_BASE="true"
shift
;;
--build)
BUILD_RAN_BUILD="true"
shift
;;
--dev)
BUILD_RAN_DEV="true"
shift
;;
--gnb)
BUILD_RAN_GNB="true"
shift
;;
--no-cache)
NO_CACHE="--no-cache"
shift
;;
*)
shift
;;
esac
done
if ! $BUILD_RAN_BUILD && ! $BUILD_RAN_GNB && ! $BUILD_RAN_DEV && ! $BUILD_RAN_GNB; then
BUILD_RAN_BUILD="true"
BUILD_RAN_GNB="true"
fi
if $BUILD_RAN_BASE; then
docker build $NO_CACHE --target ran-base --tag ran-base:$OSBASE-latest --file docker/Dockerfile.base.$OSBASE .
if [ ! $? -eq 0 ]; then
exit 1
fi
fi
if $BUILD_RAN_BUILD; then
docker build $NO_CACHE --target ran-build --build-arg BASETAG=$OSBASE-latest --tag ran-build:$OSBASE-latest --file docker/Dockerfile.build.$OSBASE .
if [ ! $? -eq 0 ]; then
exit 1
fi
fi
if $BUILD_RAN_DEV; then
docker build $NO_CACHE --target ran-dev --build-arg BASETAG=$OSBASE-latest --tag ran-dev:$OSBASE-latest --file docker/Dockerfile.dev.$OSBASE .
if [ ! $? -eq 0 ]; then
exit 1
fi
fi
if $BUILD_RAN_GNB; then
docker build $NO_CACHE --target oai-gnb --build-arg BASETAG=$OSBASE-latest --tag oai-gnb:$OSBASE-latest --tag oai-gnb:$TIMESTAMP_TAG --file docker/Dockerfile.gNB.ubuntu22 .
if [ ! $? -eq 0 ]; then
exit 1
fi
fi

View File

@@ -1,391 +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
*/
// Location of the executor node
def nodeExecutor = params.nodeExecutor
// VM Lockable resources
def vmResource = params.vmLockableResource
// Tags to shorten pipeline duration
def doMandatoryTests = false
def doFullTestsuite = false
pipeline {
agent {
label nodeExecutor
}
options {
disableConcurrentBuilds()
timestamps()
gitLabConnection('OAI GitLab')
ansiColor('xterm')
}
stages {
stage ("Verify Parameters") {
steps {
script {
JOB_TIMESTAMP = sh returnStdout: true, script: 'date --utc --rfc-3339=seconds | sed -e "s#+00:00##"'
JOB_TIMESTAMP = JOB_TIMESTAMP.trim()
echo '\u2705 \u001B[32mVerify Parameters\u001B[0m'
def allParametersPresent = true
if (env.TESTPLATFORM_OWNER) {
echo "Platform is ${env.TESTPLATFORM_OWNER}"
}
echo '\u2705 \u001B[32mVerify Labels\u001B[0m'
if ("MERGE".equals(env.gitlabActionType)) {
LABEL_CHECK = sh returnStdout: true, script: 'ci-scripts/checkGitLabMergeRequestLabels.sh --mr-id ' + env.gitlabMergeRequestIid
LABEL_CHECK = LABEL_CHECK.trim()
if (LABEL_CHECK == 'NONE') {
def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): Your merge request has none of the mandatory labels:\n\n"
message += " - BUILD-ONLY\n"
message += " - 4G-LTE\n"
message += " - 5G-NR\n"
message += " - CI\n\n"
message += "Not performing CI due to lack of labels"
addGitLabMRComment comment: message
error('Not performing CI due to lack of labels')
} else if (LABEL_CHECK == 'FULL' || LABEL_CHECK == 'SHORTEN-4G') {
doMandatoryTests = true
doFullTestsuite = true
} else if (LABEL_CHECK == 'SHORTEN-5G') {
doMandatoryTests = true
} else {
def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): We will perform only build stages on your Merge Request"
addGitLabMRComment comment: message
}
} else {
doMandatoryTests = true
doFullTestsuite = true
}
}
}
}
stage ("Verify Guidelines") {
steps {
echo "Git URL is ${GIT_URL}"
echo "GitLab Act is ${env.gitlabActionType}"
script {
if ("MERGE".equals(env.gitlabActionType)) {
// since a bit, in push events, gitlabUserEmail is not populated
gitCommitAuthorEmailAddr = env.gitlabUserEmail
echo "GitLab Usermail is ${gitCommitAuthorEmailAddr}"
// GitLab-Jenkins plugin integration is lacking to perform the merge by itself
// Doing it manually --> it may have merge conflicts
sh "./ci-scripts/doGitLabMerge.sh --src-branch ${env.gitlabSourceBranch} --src-commit ${env.gitlabMergeRequestLastCommit} --target-branch ${env.gitlabTargetBranch} --target-commit ${GIT_COMMIT}"
sh "zip -r -qq localZip.zip ."
// here was an astyle formatting check, with corresponding messages. The same could be done with clang-format
} else {
echo "Git Branch is ${GIT_BRANCH}"
echo "Git Commit is ${GIT_COMMIT}"
// since a bit, in push events, gitlabUserEmail is not populated
gitCommitAuthorEmailAddr = sh returnStdout: true, script: 'git log -n1 --pretty=format:%ae ${GIT_COMMIT}'
gitCommitAuthorEmailAddr = gitCommitAuthorEmailAddr.trim()
echo "GitLab Usermail is ${gitCommitAuthorEmailAddr}"
sh "git log -n1 --pretty=format:\"%s\" > .git/CI_COMMIT_MSG"
sh "zip -r -qq localZip.zip ."
}
}
}
post {
failure {
script {
def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): Merge Conflicts -- Cannot perform CI"
addGitLabMRComment comment: message
currentBuild.result = 'FAILURE'
}
}
}
}
stage ("Start VM -- gnb-usrp") {
steps {
lock (vmResource) {
timeout (time: 5, unit: 'MINUTES') {
sh "./ci-scripts/oai-ci-vm-tool build --workspace $WORKSPACE --variant gnb-usrp --job-name ${JOB_NAME} --build-id ${BUILD_ID} --daemon"
}
}
}
}
stage ("Start VM -- nr-ue-usrp") {
steps {
lock (vmResource) {
timeout (time: 5, unit: 'MINUTES') {
sh "./ci-scripts/oai-ci-vm-tool build --workspace $WORKSPACE --variant nr-ue-usrp --job-name ${JOB_NAME} --build-id ${BUILD_ID} --daemon"
}
}
}
}
stage ("Start VM -- enb-ethernet") {
steps {
lock (vmResource) {
timeout (time: 7, unit: 'MINUTES') {
sh "./ci-scripts/oai-ci-vm-tool build --workspace $WORKSPACE --variant enb-ethernet --job-name ${JOB_NAME} --build-id ${BUILD_ID} --daemon"
}
}
}
}
stage ("Start VM -- ue-ethernet") {
steps {
lock (vmResource) {
timeout (time: 7, unit: 'MINUTES') {
sh "./ci-scripts/oai-ci-vm-tool build --workspace $WORKSPACE --variant ue-ethernet --job-name ${JOB_NAME} --build-id ${BUILD_ID} --daemon"
}
}
}
}
stage ("Variant Builds") {
parallel {
stage ("Build 5G gNB-USRP") {
steps {
gitlabCommitStatus(name: "Build gNB-USRP") {
timeout (time: 45, unit: 'MINUTES') {
sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant gnb-usrp --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive"
}
}
}
}
stage ("Build 5G NR-UE-USRP") {
steps {
gitlabCommitStatus(name: "Build nr-UE-USRP") {
timeout (time: 45, unit: 'MINUTES') {
sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant nr-ue-usrp --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive"
}
}
}
}
stage ("Build eNB-ethernet") {
steps {
gitlabCommitStatus(name: "Build eNB-ethernet") {
timeout (time: 45, unit: 'MINUTES') {
sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant enb-ethernet --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive"
}
}
}
}
stage ("Build UE-ethernet") {
steps {
// This is typically the last one to finish.
lock (vmResource) {
gitlabCommitStatus(name: "Build UE-ethernet") {
timeout (time: 45, unit: 'MINUTES') {
sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant ue-ethernet --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive"
}
}
}
}
}
}
post {
failure {
script {
currentBuild.result = 'FAILURE'
}
}
always {
script {
dir ('archives') {
if (fileExists('red_hat')) {
sh "zip -r -qq vm_build_logs.zip enb_eth ue_eth gnb_usrp nr_ue_usrp red_hat"
} else {
sh "zip -r -qq vm_build_logs.zip enb_eth ue_eth gnb_usrp nr_ue_usrp"
}
}
if(fileExists('archives/vm_build_logs.zip')) {
archiveArtifacts artifacts: 'archives/vm_build_logs.zip'
}
if ("MERGE".equals(env.gitlabActionType)) {
sh "./ci-scripts/oai-ci-vm-tool report-build --workspace $WORKSPACE --git-url ${GIT_URL} --job-name ${JOB_NAME} --build-id ${BUILD_ID} --trigger merge-request --src-branch ${env.gitlabSourceBranch} --src-commit ${env.gitlabMergeRequestLastCommit} --target-branch ${env.gitlabTargetBranch} --target-commit ${GIT_COMMIT}"
// If the merge request has introduced compilation warnings, notifications in GitLab
sh "./ci-scripts/checkAddedWarnings.sh --src-branch ${env.gitlabSourceBranch} --target-branch ${env.gitlabTargetBranch}"
def res=readFile('./oai_warning_files.txt').trim();
if ("0".equals(res)) {
echo "No issues w/ warnings/errors in this merge request"
} else {
def fileList=readFile('./oai_warning_files_list.txt').trim();
def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): Some modified files in Merge Request MAY have INTRODUCED WARNINGS (" + fileList + ")"
addGitLabMRComment comment: message
}
} else {
sh "./ci-scripts/oai-ci-vm-tool report-build --workspace $WORKSPACE --git-url ${GIT_URL} --job-name ${JOB_NAME} --build-id ${BUILD_ID} --trigger push --branch ${GIT_BRANCH} --commit ${GIT_COMMIT}"
}
if(fileExists('build_results.html')) {
sh "sed -i -e 's#Build-ID: ${BUILD_ID}#Build-ID: <a href=\"${BUILD_URL}\">${BUILD_ID}</a>#' -e 's#TEMPLATE_BUILD_TIME#${JOB_TIMESTAMP}#' build_results.html"
archiveArtifacts artifacts: 'build_results.html'
}
}
}
}
}
stage ("Variant Tests") {
parallel {
stage ("VM-based tests") {
stages {
stage ("Test L1 simulator") {
when {
expression {doMandatoryTests}
}
steps {
lock (vmResource) {
script {
timeout (time: 30, unit: 'MINUTES') {
try {
gitlabCommitStatus(name: "Test L1-sim") {
sh "./ci-scripts/oai-ci-vm-tool test --workspace $WORKSPACE --variant l1-sim --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive"
}
} catch (Exception e) {
currentBuild.result = 'FAILURE'
}
}
}
}
}
}
stage ("Test RF simulator") {
when {
expression {doMandatoryTests}
}
steps {
lock (vmResource) {
script {
timeout (time: 40, unit: 'MINUTES') {
try {
gitlabCommitStatus(name: "Test RF-sim") {
sh "./ci-scripts/oai-ci-vm-tool test --workspace $WORKSPACE --variant rf-sim --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive"
}
} catch (Exception e) {
currentBuild.result = 'FAILURE'
}
}
}
}
}
}
stage ("Test 5G RF simulator") {
when {
expression {doMandatoryTests}
}
steps {
lock (vmResource) {
script {
timeout (time: 40, unit: 'MINUTES') {
try {
gitlabCommitStatus(name: "Test 5G RF-sim") {
sh "./ci-scripts/oai-ci-vm-tool test --workspace $WORKSPACE --variant rf5g-sim --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive"
}
} catch (Exception e) {
currentBuild.result = 'FAILURE'
}
}
}
}
}
}
stage ("Destroy all Virtual Machines") {
when {
expression {doMandatoryTests}
}
steps {
lock (vmResource) {
sh "./ci-scripts/oai-ci-vm-tool destroy --job-name ${JOB_NAME} --build-id ${BUILD_ID}"
}
}
}
}
}
}
post {
always {
script {
if (doMandatoryTests) {
dir ('archives') {
sh "if [ -d rf_sim/test ] || [ -d rf5g_sim/test ] || [ -d l2_sim/test ]; then zip -r -qq vm_tests_logs.zip */test ; fi"
}
if(fileExists('archives/vm_tests_logs.zip')) {
archiveArtifacts artifacts: 'archives/vm_tests_logs.zip'
if ("MERGE".equals(env.gitlabActionType)) {
sh "./ci-scripts/oai-ci-vm-tool report-test --workspace $WORKSPACE --git-url ${GIT_URL} --job-name ${JOB_NAME} --build-id ${BUILD_ID} --trigger merge-request --src-branch ${env.gitlabSourceBranch} --src-commit ${env.gitlabMergeRequestLastCommit} --target-branch ${env.gitlabTargetBranch} --target-commit ${GIT_COMMIT}"
} else {
sh "./ci-scripts/oai-ci-vm-tool report-test --workspace $WORKSPACE --git-url ${GIT_URL} --job-name ${JOB_NAME} --build-id ${BUILD_ID} --trigger push --branch ${GIT_BRANCH} --commit ${GIT_COMMIT}"
}
if(fileExists('test_simulator_results.html')) {
sh "sed -i -e 's#Build-ID: ${BUILD_ID}#Build-ID: <a href=\"${BUILD_URL}\">${BUILD_ID}</a>#' -e 's#TEMPLATE_BUILD_TIME#${JOB_TIMESTAMP}#' test_simulator_results.html"
archiveArtifacts artifacts: 'test_simulator_results.html'
}
}
}
}
}
}
}
}
post {
always {
script {
// Stage destroy may not be run if error in previous stage
sh "./ci-scripts/oai-ci-vm-tool destroy --job-name ${JOB_NAME} --build-id ${BUILD_ID}"
emailext attachmentsPattern: '*results*.html',
body: '''Hi,
Here are attached HTML report files for $PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS!
Regards,
OAI CI Team''',
replyTo: 'no-reply@openairinterface.org',
subject: '$PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS!',
to: gitCommitAuthorEmailAddr
if (fileExists('.git/CI_COMMIT_MSG')) {
sh "rm -f .git/CI_COMMIT_MSG"
}
}
}
success {
script {
def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): passed (" + BUILD_URL + ")"
if ("MERGE".equals(env.gitlabActionType)) {
echo "This is a MERGE event"
addGitLabMRComment comment: message
}
}
}
failure {
script {
def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): failed (" + BUILD_URL + ")"
if ("MERGE".equals(env.gitlabActionType)) {
echo "This is a MERGE event"
addGitLabMRComment comment: message
}
}
}
}
}

View File

@@ -1,7 +0,0 @@
#!/bin/bash
while true
do
echo "gNB will be started automatically..."
sleep 1
sudo .././cmake_targets/ran_build/build/nr-softmodem -E -O ../targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf
done

View File

@@ -1,236 +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
# */
function build_usage {
echo "OAI CI VM script"
echo " Original Author: Raphael Defosseux"
echo " Requirements:"
echo " -- uvtool uvtool-libvirt apt-cacher"
echo " -- $VM_OSREL image already synced"
echo " Default:"
echo " -- eNB with USRP"
echo ""
echo "Usage:"
echo "------"
echo " oai-ci-vm-tool build [OPTIONS]"
echo ""
command_options_usage
}
function build_on_vm {
if [ ! -f $JENKINS_WKSP/localZip.zip ]
then
echo "Missing localZip.zip file!"
STATUS=1
return
fi
if [[ ! -f /etc/apt/apt.conf.d/01proxy ]] && [[ "$OPTIONAL_APTCACHER" != "true" ]]
then
echo "Missing /etc/apt/apt.conf.d/01proxy file!"
echo "Is apt-cacher installed and configured?"
STATUS=1
return
fi
echo "############################################################"
echo "OAI CI VM script"
echo "############################################################"
echo "VM_NAME = $VM_NAME"
echo "VM_CMD_FILE = $VM_CMDS"
echo "JENKINS_WKSP = $JENKINS_WKSP"
echo "ARCHIVES_LOC = $ARCHIVES_LOC"
echo "BUILD_OPTIONS = $BUILD_OPTIONS"
if [[ "$VM_NAME" == *"-enb-usrp"* ]] || [[ "$VM_NAME" == *"-cppcheck"* ]] || [[ "$VM_NAME" == *"-phy-sim"* ]] || [[ "$VM_NAME" == *"-basic-sim"* ]] || [[ "$VM_NAME" == *"-flexran-rtc"* ]] || [[ "$VM_NAME" == *"-rf-sim"* ]] || [[ "$VM_NAME" == *"-ethernet"* ]] || [[ "$VM_NAME" == *"rf5g-sim"* ]] || [[ "$VM_NAME" == *"gnb-usrp"* ]] || [[ "$VM_NAME" == *"nr-ue-usrp"* ]]
then
echo "This VM type is no longer supported in the pipeline framework"
return
fi
IS_VM_ALIVE=`uvt-kvm list | grep -c $VM_NAME`
if [ $IS_VM_ALIVE -eq 0 ]
then
echo "VM_MEMORY = $VM_MEMORY MBytes"
echo "VM_CPU = $VM_CPU"
echo "VM_DISK = $VM_DISK GBytes"
echo "############################################################"
echo "Creating VM ($VM_NAME) on Ubuntu Cloud Image base"
echo "############################################################"
acquire_vm_create_lock
uvt-kvm create $VM_NAME release=$VM_OSREL --memory $VM_MEMORY --cpu $VM_CPU --disk $VM_DISK --unsafe-caching --template ci-scripts/template-host.xml
echo "Waiting for VM to be started"
uvt-kvm wait $VM_NAME --insecure
VM_IP_ADDR=`uvt-kvm ip $VM_NAME`
echo "$VM_NAME has for IP addr = $VM_IP_ADDR"
release_vm_create_lock
else
echo "Waiting for VM to be started"
uvt-kvm wait $VM_NAME --insecure
VM_IP_ADDR=`uvt-kvm ip $VM_NAME`
echo "$VM_NAME has for IP addr = $VM_IP_ADDR"
fi
echo "############################################################"
echo "Copying GIT repo into VM ($VM_NAME)"
echo "############################################################"
if [[ "$VM_NAME" == *"-flexran-rtc"* ]]
then
scp -o StrictHostKeyChecking=no $JENKINS_WKSP/flexran/flexran.zip ubuntu@$VM_IP_ADDR:/home/ubuntu/localZip.zip
else
scp -o StrictHostKeyChecking=no $JENKINS_WKSP/localZip.zip ubuntu@$VM_IP_ADDR:/home/ubuntu
fi
[ -f /etc/apt/apt.conf.d/01proxy ] && scp -o StrictHostKeyChecking=no /etc/apt/apt.conf.d/01proxy ubuntu@$VM_IP_ADDR:/home/ubuntu
echo "############################################################"
echo "Running install and build script on VM ($VM_NAME)"
echo "############################################################"
echo "[ -f 01proxy ] && sudo cp 01proxy /etc/apt/apt.conf.d/" > $VM_CMDS
echo "touch /home/ubuntu/.hushlogin" >> $VM_CMDS
echo "git config --global https.postBuffer 123289600" >> $VM_CMDS
if [[ "$VM_NAME" == *"-cppcheck"* ]]
then
if [ $DAEMON -eq 0 ]
then
echo "echo \"sudo apt-get --yes --quiet install zip cppcheck \"" >> $VM_CMDS
echo "sudo apt-get update > zip-install.txt 2>&1" >> $VM_CMDS
echo "sudo apt-get --yes install zip cppcheck >> zip-install.txt 2>&1" >> $VM_CMDS
else
echo "echo \"sudo apt-get --yes --quiet install zip daemon cppcheck \"" >> $VM_CMDS
echo "sudo apt-get update > zip-install.txt 2>&1" >> $VM_CMDS
echo "sudo apt-get --yes install zip daemon cppcheck >> zip-install.txt 2>&1" >> $VM_CMDS
fi
fi
if [[ "$VM_NAME" == *"-flexran-rtc"* ]]
then
if [ $DAEMON -eq 0 ]
then
echo "echo \"sudo apt-get --yes --quiet install zip curl jq \"" >> $VM_CMDS
echo "sudo apt-get update > zip-install.txt 2>&1" >> $VM_CMDS
echo "sudo apt-get --yes install zip curl jq >> zip-install.txt 2>&1" >> $VM_CMDS
else
echo "echo \"sudo apt-get --yes --quiet install zip daemon curl jq \"" >> $VM_CMDS
echo "sudo apt-get update > zip-install.txt 2>&1" >> $VM_CMDS
echo "sudo apt-get --yes install zip daemon curl jq >> zip-install.txt 2>&1" >> $VM_CMDS
fi
fi
if [[ "$VM_NAME" != *"-cppcheck"* ]] && [[ "$VM_NAME" != *"-flexran-rtc"* ]]
then
if [ $DAEMON -eq 0 ]
then
echo "echo \"sudo apt-get --yes --quiet install zip subversion libboost-dev \"" >> $VM_CMDS
echo "sudo apt-get update > zip-install.txt 2>&1" >> $VM_CMDS
if [[ "$VM_NAME" == *"-phy-sim"* ]]
then
echo "sudo apt-get --yes install zip subversion libboost-dev make gcc >> zip-install.txt 2>&1" >> $VM_CMDS
else
echo "sudo apt-get --yes install zip subversion libboost-dev >> zip-install.txt 2>&1" >> $VM_CMDS
fi
else
echo "echo \"sudo apt-get --yes --quiet install zip daemon subversion libboost-dev \"" >> $VM_CMDS
echo "sudo apt-get update > zip-install.txt 2>&1" >> $VM_CMDS
if [[ "$VM_NAME" == *"-phy-sim"* ]]
then
echo "sudo apt-get --yes install zip daemon subversion libboost-dev make gcc >> zip-install.txt 2>&1" >> $VM_CMDS
else
echo "sudo apt-get --yes install zip daemon subversion libboost-dev >> zip-install.txt 2>&1" >> $VM_CMDS
fi
fi
fi
echo "mkdir tmp" >> $VM_CMDS
echo "cd tmp" >> $VM_CMDS
echo "echo \"unzip -qq -DD ../localZip.zip\"" >> $VM_CMDS
echo "unzip -qq -DD ../localZip.zip" >> $VM_CMDS
# Trying to make some room on filesystem before building
echo "rm ../localZip.zip" >> $VM_CMDS
echo "export CI_ENV=True" >> $VM_CMDS
if [[ "$VM_NAME" == *"-cppcheck"* ]]
then
echo "mkdir cmake_targets/log" >> $VM_CMDS
echo "chmod 777 cmake_targets/log" >> $VM_CMDS
echo "cp /home/ubuntu/zip-install.txt cmake_targets/log" >> $VM_CMDS
echo "echo \"cppcheck $BUILD_OPTIONS . \"" >> $VM_CMDS
if [ $DAEMON -eq 0 ]
then
echo "cppcheck $BUILD_OPTIONS . 2> cmake_targets/log/cppcheck.xml 1> cmake_targets/log/cppcheck_build.txt" >> $VM_CMDS
else
echo "echo \"cppcheck $BUILD_OPTIONS .\" > ./my-vm-build.sh" >> $VM_CMDS
echo "chmod 775 ./my-vm-build.sh " >> $VM_CMDS
echo "sudo -E daemon --inherit --unsafe --name=build_daemon --chdir=/home/ubuntu/tmp -O /home/ubuntu/tmp/cmake_targets/log/cppcheck_build.txt -E /home/ubuntu/tmp/cmake_targets/log/cppcheck.xml ./my-vm-build.sh" >> $VM_CMDS
fi
fi
if [[ "$VM_NAME" == *"-flexran-rtc"* ]]
then
echo "mkdir -p cmake_targets/log" >> $VM_CMDS
echo "chmod 777 cmake_targets/log" >> $VM_CMDS
echo "cp /home/ubuntu/zip-install.txt cmake_targets/log" >> $VM_CMDS
# Patching the pistache build for Xenial (cmake too old for new commits)
echo "sed -i -e 's@cd pistache@cd pistache \&\& git checkout -f 9a65f40975fafca5bb5370ba6d0d00f42cbc4356@' ./tools/install_dependencies" >> $VM_CMDS
echo "echo \"./tools/install_dependencies \"" >> $VM_CMDS
echo "./tools/install_dependencies > cmake_targets/log/install-build.txt 2>&1" >> $VM_CMDS
echo "echo \"mkdir build\"" >> $VM_CMDS
echo "mkdir build" >> $VM_CMDS
echo "echo \"cd build\"" >> $VM_CMDS
echo "cd build" >> $VM_CMDS
echo "echo \"$BUILD_OPTIONS \"" >> $VM_CMDS
echo "$BUILD_OPTIONS > ../cmake_targets/log/rt_controller.txt 2>&1" >> $VM_CMDS
fi
if [[ "$VM_NAME" != *"-cppcheck"* ]] && [[ "$VM_NAME" != *"-flexran-rtc"* ]]
then
echo "echo \"source oaienv\"" >> $VM_CMDS
echo "source oaienv" >> $VM_CMDS
if [[ "$VM_NAME" == *"-phy-sim"* ]]
then
echo "cd common/utils/T" >> $VM_CMDS
echo "make" >> $VM_CMDS
echo "cd ../../.." >> $VM_CMDS
fi
echo "cd cmake_targets/" >> $VM_CMDS
echo "mkdir log" >> $VM_CMDS
echo "chmod 777 log" >> $VM_CMDS
echo "cp /home/ubuntu/zip-install.txt log" >> $VM_CMDS
if [ $DAEMON -eq 0 ]
then
echo "echo \"./build_oai -I $BUILD_OPTIONS \"" >> $VM_CMDS
echo "./build_oai -I $BUILD_OPTIONS > log/install-build.txt 2>&1" >> $VM_CMDS
else
if [[ "$VM_NAME" == *"-enb-ethernet"* ]]
then
echo "echo \"sleep 170 && ./build_oai -I $BUILD_OPTIONS\" > ./my-vm-build.sh" >> $VM_CMDS
elif [[ "$VM_NAME" == *"-ue-ethernet"* ]]
then
echo "echo \"sleep 60 && ./build_oai -I $BUILD_OPTIONS\" > ./my-vm-build.sh" >> $VM_CMDS
else
echo "echo \"./build_oai -I $BUILD_OPTIONS\" > ./my-vm-build.sh" >> $VM_CMDS
fi
echo "chmod 775 ./my-vm-build.sh " >> $VM_CMDS
echo "echo \"sudo -E daemon --inherit --unsafe --name=build_daemon --chdir=/home/ubuntu/tmp/cmake_targets -o /home/ubuntu/tmp/cmake_targets/log/install-build.txt ./my-vm-build.sh\"" >> $VM_CMDS
echo "sudo -E daemon --inherit --unsafe --name=build_daemon --chdir=/home/ubuntu/tmp/cmake_targets -o /home/ubuntu/tmp/cmake_targets/log/install-build.txt ./my-vm-build.sh" >> $VM_CMDS
fi
fi
ssh -T -o StrictHostKeyChecking=no ubuntu@$VM_IP_ADDR < $VM_CMDS
rm -f $VM_CMDS
}

View File

@@ -19,29 +19,27 @@
# * contact@openairinterface.org
# */
#---------------------------------------------------------------------
# Python for CI of OAI-eNB + COTS-UE
#
# Required Python Version
# Python 3.x
#
# Required Python Package
# pexpect
#---------------------------------------------------------------------
#-----------------------------------------------------------
# Import
#-----------------------------------------------------------
import logging
import sshconnection as SSH
import cls_oai_html
#import os
import re
import time
#import subprocess
import sys
import cls_oai_html
import constants as CONST
import helpreadme as HELP
import cls_containerize
import cls_cmd
IMAGE_REGISTRY_SERVICE_NAME = "image-registry.openshift-image-registry.svc"
NAMESPACE = "oaicicd-ran"
class Cluster:
def __init__(self):
@@ -58,86 +56,73 @@ class Cluster:
self.ranCommitID = ""
self.ranAllowMerge = False
self.ranTargetBranch = ""
self.cmd = None
def _recreate_entitlements(self, sshSession):
def _recreate_entitlements(self):
# recreating entitlements, don't care if deletion fails
sshSession.command('oc delete secret etc-pki-entitlement', '\$', 5)
if re.search(r"not found", sshSession.getBefore()):
logging.warning("no secrets etc-pki-entitlement found, recreating")
sshSession.command('ls /etc/pki/entitlement/???????????????????.pem | tail -1', '\$', 5, silent=True)
regres1 = re.search(r"/etc/pki/entitlement/[0-9]+.pem", sshSession.getBefore())
sshSession.command('ls /etc/pki/entitlement/???????????????????-key.pem | tail -1', '\$', 5, silent=True)
regres2 = re.search(r"/etc/pki/entitlement/[0-9]+-key.pem", sshSession.getBefore())
self.cmd.run('oc delete secret etc-pki-entitlement')
ret = self.cmd.run('ls /etc/pki/entitlement/???????????????????.pem | tail -1', silent=True)
regres1 = re.search(r"/etc/pki/entitlement/[0-9]+.pem", ret.stdout)
ret = self.cmd.run('ls /etc/pki/entitlement/???????????????????-key.pem | tail -1', silent=True)
regres2 = re.search(r"/etc/pki/entitlement/[0-9]+-key.pem", ret.stdout)
if regres1 is None or regres2 is None:
logging.error("could not find entitlements")
return False
file1 = regres1.group(0)
file2 = regres2.group(0)
sshSession.command(f'oc create secret generic etc-pki-entitlement --from-file {file1} --from-file {file2}', '\$', 5)
regres = re.search(r"secret/etc-pki-entitlement created", sshSession.getBefore())
if regres is None:
ret = self.cmd.run(f'oc create secret generic etc-pki-entitlement --from-file {file1} --from-file {file2}')
regres = re.search(r"secret/etc-pki-entitlement created", ret.stdout)
if ret.returncode != 0 or regres is None:
logging.error("could not create secret/etc-pki-entitlement")
return False
return True
def _recreate_bc(self, sshSession, name, newTag, filename):
self._retag_image_statement(sshSession, name, name, newTag, filename)
sshSession.command(f'oc delete -f {filename}', '\$', 5)
sshSession.command(f'oc create -f {filename}', '\$', 5)
before = sshSession.getBefore()
if re.search('buildconfig.build.openshift.io/[a-zA-Z\-0-9]+ created', before) is not None:
def _recreate_bc(self, name, newTag, filename):
self._retag_image_statement(name, name, newTag, filename)
self.cmd.run(f'oc delete -f {filename}')
ret = self.cmd.run(f'oc create -f {filename}')
if re.search('buildconfig.build.openshift.io/[a-zA-Z\-0-9]+ created', ret.stdout) is not None:
return True
logging.error('error while creating buildconfig: ' + sshSession.getBefore())
logging.error('error while creating buildconfig: ' + ret.stdout)
return False
def _recreate_is_tag(self, sshSession, name, newTag, filename):
sshSession.command(f'oc describe is {name}', '\$', 5)
if sshSession.getBefore().count('NotFound') > 0:
sshSession.command(f'oc create -f {filename}', '\$', 5)
before = sshSession.getBefore()
if re.search(f'imagestream.image.openshift.io/{name} created', before) is None:
logging.error('error while creating imagestream: ' + sshSession.getBefore())
def _recreate_is_tag(self, name, newTag, filename):
ret = self.cmd.run(f'oc describe is {name}')
if ret.returncode != 0:
ret = self.cmd.run(f'oc create -f {filename}')
if ret.returncode != 0:
logging.error(f'error while creating imagestream: {ret.stdout}')
return False
else:
logging.debug(f'-> imagestream {name} found')
image = f'{name}:{newTag}'
sshSession.command(f'oc delete istag {image}', '\$', 5) # we don't care if this fails, e.g., if it is missing
sshSession.command(f'oc create istag {image}', '\$', 5)
before = sshSession.getBefore()
if re.search(f'imagestreamtag.image.openshift.io/{image} created', before) is not None:
self.cmd.run(f'oc delete istag {image}', reportNonZero=False) # we don't care if this fails, e.g., if it is missing
ret = self.cmd.run(f'oc create istag {image}')
if ret.returncode == 0:
return True
logging.error('error while creating imagestreamtag: ' + sshSession.getBefore())
logging.error(f'error while creating imagestreamtag: {ret.stdout}')
return False
def _start_build(self, sshSession, name):
def _start_build(self, name):
# will return "immediately" but build runs in background
# if multiple builds are started at the same time, this can take some time, however
ret = sshSession.command(f'oc start-build {name} --from-file={self.eNBSourceCodePath}', '\$', 300)
before = sshSession.getBefore()
regres = re.search(r'build.build.openshift.io/(?P<jobname>[a-zA-Z0-9\-]+) started', str(before))
if ret != 0 or before.count('Uploading finished') != 1 or regres is None:
logging.error("error during oc start-build: " + sshSession.getBefore())
self._delete_pod(sshSession, name)
ret = self.cmd.run(f'oc start-build {name} --from-file={self.eNBSourceCodePath}')
regres = re.search(r'build.build.openshift.io/(?P<jobname>[a-zA-Z0-9\-]+) started', ret.stdout)
if ret.returncode != 0 or ret.stdout.count('Uploading finished') != 1 or regres is None:
logging.error(f"error during oc start-build: {ret.stdout}")
return None
return regres.group('jobname') + '-build'
def _delete_pod(self, sshSession, shortName):
sshSession.command(f"oc get pods | grep {shortName}", '\$', 5)
regres = re.search(rf'{shortName}-[0-9]+-build', sshSession.getBefore())
if regres is not None:
sshSession.command(f"oc delete pod {regres.group(0)}", '\$', 5)
else:
logging.warning(f"no pod found with name {shortName}")
def _wait_build_end(self, sshSession, jobs, timeout_sec, check_interval_sec = 5):
def _wait_build_end(self, jobs, timeout_sec, check_interval_sec = 5):
logging.debug(f"waiting for jobs {jobs} to finish building")
while timeout_sec > 0:
# check status
for j in jobs:
sshSession.command(f'oc get pods | grep {j}', '\$', 30, silent = True)
if sshSession.getBefore().count('Completed') > 0: jobs.remove(j)
if sshSession.getBefore().count('Error') > 0:
logging.error(f'error for job {j}: ' + sshSession.getBefore())
ret = self.cmd.run(f'oc get pods | grep {j}', silent = True)
if ret.stdout.count('Completed') > 0: jobs.remove(j)
if ret.stdout.count('Error') > 0:
logging.error(f'error for job {j}: {ret.stdout}')
return False
if jobs == []:
logging.debug('all jobs completed')
@@ -147,44 +132,43 @@ class Cluster:
logging.error(f"timeout while waiting for end of build of {jobs}")
return False
def _retag_image_statement(self, sshSession, oldImage, newImage, newTag, filename):
sshSession.command(f'sed -i -e "s#{oldImage}:latest#{newImage}:{newTag}#" {filename}', '\$', 5)
def _retag_image_statement(self, oldImage, newImage, newTag, filename):
self.cmd.run(f'sed -i -e "s#{oldImage}:latest#{newImage}:{newTag}#" {filename}')
def _get_image_size(self, sshSession, image, tag):
def _get_image_size(self, image, tag):
# get the SHA of the image we built using the image name and its tag
sshSession.command(f'oc describe is {image} | grep -A4 {tag}', '\$', 5)
result = re.search(f'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/(?P<imageSha>{image}@sha256:[a-f0-9]+)', sshSession.getBefore())
ret = self.cmd.run(f'oc describe is {image} | grep -A4 {tag}')
result = re.search(f'{IMAGE_REGISTRY_SERVICE_NAME}:5000/{NAMESPACE}/(?P<imageSha>{image}@sha256:[a-f0-9]+)', ret.stdout)
if result is None:
return -1
imageSha = result.group("imageSha")
# retrieve the size
sshSession.command(f'oc get -o json isimage {imageSha} | jq -Mc "{{dockerImageSize: .image.dockerImageMetadata.Size}}"', '\$', 5)
result = re.search('{"dockerImageSize":(?P<size>[0-9]+)}', str(sshSession.getBefore()))
ret = self.cmd.run(f'oc get -o json isimage {imageSha} | jq -Mc "{{dockerImageSize: .image.dockerImageMetadata.Size}}"')
result = re.search('{"dockerImageSize":(?P<size>[0-9]+)}', ret.stdout)
if result is None:
return -1
return int(result.group("size"))
def _deploy_pod(self, sshSession, filename, timeout = 30):
sshSession.command(f'oc create -f {filename}', '\$', 10)
result = re.search(f'pod/(?P<pod>[a-zA-Z0-9_\-]+) created', sshSession.getBefore())
def _deploy_pod(self, filename, timeout = 30):
ret = self.cmd.run(f'oc create -f {filename}')
result = re.search(f'pod/(?P<pod>[a-zA-Z0-9_\-]+) created', ret.stdout)
if result is None:
logging.error(f'could not deploy pod: {sshSession.getBefore()}')
logging.error(f'could not deploy pod: {ret.stdout}')
return None
pod = result.group("pod")
logging.debug(f'checking if pod {pod} is in Running state')
while timeout > 0:
sshSession.command(f'oc get pod {pod} -o json | jq -Mc .status.phase', '\$', 5, silent=True)
if re.search('"Running"', sshSession.getBefore()) is not None: return pod
ret = self.cmd.run(f'oc get pod {pod} -o json | jq -Mc .status.phase', silent=True)
if re.search('"Running"', ret.stdout) is not None: return pod
timeout -= 1
time.sleep(1)
logging.error(f'pod {pod} did not reach Running state')
self._undeploy_pod(sshSession, filename)
self._undeploy_pod(filename)
return None
def _undeploy_pod(self, sshSession, filename):
# to save time we start this in the background and trust that oc stops correctly
sshSession.command(f'oc delete -f {filename} &', '\$', 5)
def _undeploy_pod(self, filename):
self.cmd.run(f'oc delete -f {filename}')
def BuildClusterImage(self, HTML):
if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '':
@@ -194,8 +178,7 @@ class Cluster:
lIpAddr = self.eNBIPAddress
lSourcePath = self.eNBSourceCodePath
if lIpAddr == '' or lSourcePath == '':
HELP.GenericHelp(CONST.Version)
sys.exit('Insufficient Parameter: no SSH Credentials')
sys.exit('Insufficient Parameter: eNBSourceCodePath missing')
ocUserName = self.OCUserName
ocPassword = self.OCPassword
ocProjectName = self.OCProjectName
@@ -206,29 +189,27 @@ class Cluster:
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}')
mySSH = SSH.SSHConnection()
mySSH.open(lIpAddr, "oaicicd", "SHOULD NOT BE NECESSARY")
self.cmd = cls_cmd.RemoteCmd(lIpAddr)
self.testCase_id = HTML.testCase_id
# Workaround for some servers, we need to erase completely the workspace
if self.forcedWorkspaceCleanup:
mySSH.command(f'rm -Rf {lSourcePath}', '\$', 15)
cls_containerize.CreateWorkspace(mySSH, lSourcePath, self.ranRepository, self.ranCommitID, self.ranTargetBranch, self.ranAllowMerge)
self.cmd.run(f'rm -Rf {lSourcePath}')
cls_containerize.CreateWorkspace(self.cmd, lSourcePath, self.ranRepository, self.ranCommitID, self.ranTargetBranch, self.ranAllowMerge)
# we don't necessarily need a forced workspace cleanup, but in
# order to reduce the amount of data send to OpenShift, we
# to reduce the amount of data send to OpenShift, we
# manually delete all generated files in the workspace
mySSH.command(f'rm -rf {lSourcePath}/cmake_targets/ran_build', '\$', 30);
self.cmd.run(f'rm -rf {lSourcePath}/cmake_targets/ran_build');
baseTag = 'develop'
forceBaseImageBuild = False
imageTag = 'develop'
if self.ranAllowMerge: # merging MR branch into develop -> temporary image
imageTag = 'ci-temp'
imageTag = f'{self.ranBranch}-{self.ranCommitID[0:8]}'
if self.ranTargetBranch == 'develop':
mySSH.command(f'git diff HEAD..origin/develop -- cmake_targets/build_oai cmake_targets/tools/build_helper docker/Dockerfile.base.rhel8.2 | grep --colour=never -i INDEX', '\$', 5)
result = re.search('index', mySSH.getBefore())
ret = self.cmd.run(f'git diff HEAD..origin/develop -- cmake_targets/build_oai cmake_targets/tools/build_helper docker/Dockerfile.base.rhel8.2 | grep --colour=never -i INDEX')
result = re.search('index', ret.stdout)
if result is not None:
forceBaseImageBuild = True
baseTag = 'ci-temp'
@@ -236,122 +217,120 @@ class Cluster:
forceBaseImageBuild = True
# logging to OC Cluster and then switch to corresponding project
mySSH.command(f'oc login -u {ocUserName} -p {ocPassword} --server {self.OCUrl}', '\$', 31)
if mySSH.getBefore().count('Login successful.') == 0:
ret = self.cmd.run(f'oc login -u {ocUserName} -p {ocPassword} --server {self.OCUrl}')
if ret.returncode != 0:
logging.error('\u001B[1m OC Cluster Login Failed\u001B[0m')
mySSH.close()
HTML.CreateHtmlTestRow('N/A', 'KO', CONST.OC_LOGIN_FAIL)
return False
mySSH.command(f'oc project {ocProjectName}', '\$', 30)
if mySSH.getBefore().count(f'Already on project "{ocProjectName}"') == 0 and mySSH.getBefore().count(f'Now using project "{self.OCProjectName}"') == 0:
ret = self.cmd.run(f'oc project {ocProjectName}')
if ret.returncode != 0:
logging.error(f'\u001B[1mUnable to access OC project {ocProjectName}\u001B[0m')
mySSH.command('oc logout', '\$', 30)
mySSH.close()
self.cmd.run('oc logout')
HTML.CreateHtmlTestRow('N/A', 'KO', CONST.OC_PROJECT_FAIL)
return False
self._recreate_entitlements(mySSH)
self._recreate_entitlements()
status = True # flag to abandon compiling if any image fails
attemptedImages = []
if forceBaseImageBuild:
self._recreate_is_tag(mySSH, 'ran-base', baseTag, 'openshift/ran-base-is.yaml')
self._recreate_bc(mySSH, 'ran-base', baseTag, 'openshift/ran-base-bc.yaml')
ranbase_job = self._start_build(mySSH, 'ran-base')
self._recreate_is_tag('ran-base', baseTag, 'openshift/ran-base-is.yaml')
self._recreate_bc('ran-base', baseTag, 'openshift/ran-base-bc.yaml')
ranbase_job = self._start_build('ran-base')
attemptedImages += ['ran-base']
status = ranbase_job is not None and self._wait_build_end(mySSH, [ranbase_job], 600)
status = ranbase_job is not None and self._wait_build_end([ranbase_job], 600)
if not status: logging.error('failure during build of ran-base')
mySSH.command(f'oc logs {ranbase_job} &> cmake_targets/log/ran-base.log', '\$', 10)
self.cmd.run(f'oc logs {ranbase_job} &> cmake_targets/log/ran-base.log') # cannot use cmd.run because of redirect
# recover logs by mounting image
self._retag_image_statement(mySSH, 'ran-base', 'ran-base', baseTag, 'openshift/ran-base-log-retrieval.yaml')
pod = self._deploy_pod(mySSH, 'openshift/ran-base-log-retrieval.yaml')
self._retag_image_statement('ran-base', 'ran-base', baseTag, 'openshift/ran-base-log-retrieval.yaml')
pod = self._deploy_pod('openshift/ran-base-log-retrieval.yaml')
if pod is not None:
mySSH.command(f'mkdir -p cmake_targets/log/ran-base', '\$', 5)
mySSH.command(f'oc rsync {pod}:/oai-ran/cmake_targets/log/ cmake_targets/log/ran-base', '\$', 5)
self._undeploy_pod(mySSH, 'openshift/ran-base-log-retrieval.yaml')
self.cmd.run(f'mkdir -p cmake_targets/log/ran-base')
self.cmd.run(f'oc rsync {pod}:/oai-ran/cmake_targets/log/ cmake_targets/log/ran-base')
self._undeploy_pod('openshift/ran-base-log-retrieval.yaml')
else:
status = False
if status:
self._recreate_is_tag(mySSH, 'oai-physim', imageTag, 'openshift/oai-physim-is.yaml')
self._recreate_bc(mySSH, 'oai-physim', imageTag, 'openshift/oai-physim-bc.yaml')
self._retag_image_statement(mySSH, 'ran-base', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-base', baseTag, 'docker/Dockerfile.phySim.rhel8.2')
physim_job = self._start_build(mySSH, 'oai-physim')
self._recreate_is_tag('oai-physim', imageTag, 'openshift/oai-physim-is.yaml')
self._recreate_bc('oai-physim', imageTag, 'openshift/oai-physim-bc.yaml')
self._retag_image_statement('ran-base', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-base', baseTag, 'docker/Dockerfile.phySim.rhel8.2')
physim_job = self._start_build('oai-physim')
attemptedImages += ['oai-physim']
self._recreate_is_tag(mySSH, 'ran-build', imageTag, 'openshift/ran-build-is.yaml')
self._recreate_bc(mySSH, 'ran-build', imageTag, 'openshift/ran-build-bc.yaml')
self._retag_image_statement(mySSH, 'ran-base', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-base', baseTag, 'docker/Dockerfile.build.rhel8.2')
ranbuild_job = self._start_build(mySSH, 'ran-build')
self._recreate_is_tag('ran-build', imageTag, 'openshift/ran-build-is.yaml')
self._recreate_bc('ran-build', imageTag, 'openshift/ran-build-bc.yaml')
self._retag_image_statement('ran-base', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-base', baseTag, 'docker/Dockerfile.build.rhel8.2')
ranbuild_job = self._start_build('ran-build')
attemptedImages += ['ran-build']
wait = ranbuild_job is not None and physim_job is not None and self._wait_build_end(mySSH, [ranbuild_job, physim_job], 1200)
wait = ranbuild_job is not None and physim_job is not None and self._wait_build_end([ranbuild_job, physim_job], 1200)
if not wait: logging.error('error during build of ranbuild_job or physim_job')
status = status and wait
mySSH.command(f'oc logs {ranbuild_job} &> cmake_targets/log/ran-build.log', '\$', 10)
mySSH.command(f'oc logs {physim_job} &> cmake_targets/log/oai-physim.log', '\$', 10)
mySSH.command('oc get pods.metrics.k8s.io >> cmake_targets/log/build-metrics.log', '\$', 10)
self.cmd.run(f'oc logs {ranbuild_job} &> cmake_targets/log/ran-build.log')
self.cmd.run(f'oc logs {physim_job} &> cmake_targets/log/oai-physim.log')
self.cmd.run(f'oc get pods.metrics.k8s.io &>> cmake_targets/log/build-metrics.log', '\$', 10)
if status:
self._recreate_is_tag(mySSH, 'oai-enb', imageTag, 'openshift/oai-enb-is.yaml')
self._recreate_bc(mySSH, 'oai-enb', imageTag, 'openshift/oai-enb-bc.yaml')
self._retag_image_statement(mySSH, 'ran-base', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-base', baseTag, 'docker/Dockerfile.eNB.rhel8.2')
self._retag_image_statement(mySSH, 'ran-build', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-build', imageTag, 'docker/Dockerfile.eNB.rhel8.2')
enb_job = self._start_build(mySSH, 'oai-enb')
self._recreate_is_tag('oai-enb', imageTag, 'openshift/oai-enb-is.yaml')
self._recreate_bc('oai-enb', imageTag, 'openshift/oai-enb-bc.yaml')
self._retag_image_statement('ran-base', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-base', baseTag, 'docker/Dockerfile.eNB.rhel8.2')
self._retag_image_statement('ran-build', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-build', imageTag, 'docker/Dockerfile.eNB.rhel8.2')
enb_job = self._start_build('oai-enb')
attemptedImages += ['oai-enb']
self._recreate_is_tag(mySSH, 'oai-gnb', imageTag, 'openshift/oai-gnb-is.yaml')
self._recreate_bc(mySSH, 'oai-gnb', imageTag, 'openshift/oai-gnb-bc.yaml')
self._retag_image_statement(mySSH, 'ran-base', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-base', baseTag, 'docker/Dockerfile.gNB.rhel8.2')
self._retag_image_statement(mySSH, 'ran-build', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-build', imageTag, 'docker/Dockerfile.gNB.rhel8.2')
gnb_job = self._start_build(mySSH, 'oai-gnb')
self._recreate_is_tag('oai-gnb', imageTag, 'openshift/oai-gnb-is.yaml')
self._recreate_bc('oai-gnb', imageTag, 'openshift/oai-gnb-bc.yaml')
self._retag_image_statement('ran-base', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-base', baseTag, 'docker/Dockerfile.gNB.rhel8.2')
self._retag_image_statement('ran-build', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-build', imageTag, 'docker/Dockerfile.gNB.rhel8.2')
gnb_job = self._start_build('oai-gnb')
attemptedImages += ['oai-gnb']
self._recreate_is_tag(mySSH, 'oai-gnb-aw2s', imageTag, 'openshift/oai-gnb-aw2s-is.yaml')
self._recreate_bc(mySSH, 'oai-gnb-aw2s', imageTag, 'openshift/oai-gnb-aw2s-bc.yaml')
self._retag_image_statement(mySSH, 'ran-base', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-base', baseTag, 'docker/Dockerfile.gNB.aw2s.rhel8.2')
self._retag_image_statement(mySSH, 'ran-build', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-build', imageTag, 'docker/Dockerfile.gNB.aw2s.rhel8.2')
gnb_aw2s_job = self._start_build(mySSH, 'oai-gnb-aw2s')
self._recreate_is_tag('oai-gnb-aw2s', imageTag, 'openshift/oai-gnb-aw2s-is.yaml')
self._recreate_bc('oai-gnb-aw2s', imageTag, 'openshift/oai-gnb-aw2s-bc.yaml')
self._retag_image_statement('ran-base', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-base', baseTag, 'docker/Dockerfile.gNB.aw2s.rhel8.2')
self._retag_image_statement('ran-build', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-build', imageTag, 'docker/Dockerfile.gNB.aw2s.rhel8.2')
gnb_aw2s_job = self._start_build('oai-gnb-aw2s')
attemptedImages += ['oai-gnb-aw2s']
wait = enb_job is not None and gnb_job is not None and gnb_aw2s_job is not None and self._wait_build_end(mySSH, [enb_job, gnb_job, gnb_aw2s_job], 600)
wait = enb_job is not None and gnb_job is not None and gnb_aw2s_job is not None and self._wait_build_end([enb_job, gnb_job, gnb_aw2s_job], 600)
if not wait: logging.error('error during build of eNB/gNB')
status = status and wait
# recover logs
mySSH.command(f'oc logs {enb_job} &> cmake_targets/log/oai-enb.log', '\$', 10)
mySSH.command(f'oc logs {gnb_job} &> cmake_targets/log/oai-gnb.log', '\$', 10)
mySSH.command(f'oc logs {gnb_aw2s_job} &> cmake_targets/log/oai-gnb-aw2s.log', '\$', 10)
self.cmd.run(f'oc logs {enb_job} &> cmake_targets/log/oai-enb.log')
self.cmd.run(f'oc logs {gnb_job} &> cmake_targets/log/oai-gnb.log')
self.cmd.run(f'oc logs {gnb_aw2s_job} &> cmake_targets/log/oai-gnb-aw2s.log')
self._recreate_is_tag(mySSH, 'oai-lte-ue', imageTag, 'openshift/oai-lte-ue-is.yaml')
self._recreate_bc(mySSH, 'oai-lte-ue', imageTag, 'openshift/oai-lte-ue-bc.yaml')
self._retag_image_statement(mySSH, 'ran-base', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-base', baseTag, 'docker/Dockerfile.lteUE.rhel8.2')
self._retag_image_statement(mySSH, 'ran-build', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-build', imageTag, 'docker/Dockerfile.lteUE.rhel8.2')
lteue_job = self._start_build(mySSH, 'oai-lte-ue')
self._recreate_is_tag('oai-lte-ue', imageTag, 'openshift/oai-lte-ue-is.yaml')
self._recreate_bc('oai-lte-ue', imageTag, 'openshift/oai-lte-ue-bc.yaml')
self._retag_image_statement('ran-base', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-base', baseTag, 'docker/Dockerfile.lteUE.rhel8.2')
self._retag_image_statement('ran-build', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-build', imageTag, 'docker/Dockerfile.lteUE.rhel8.2')
lteue_job = self._start_build('oai-lte-ue')
attemptedImages += ['oai-lte-ue']
self._recreate_is_tag(mySSH, 'oai-nr-ue', imageTag, 'openshift/oai-nr-ue-is.yaml')
self._recreate_bc(mySSH, 'oai-nr-ue', imageTag, 'openshift/oai-nr-ue-bc.yaml')
self._retag_image_statement(mySSH, 'ran-base', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-base', baseTag, 'docker/Dockerfile.nrUE.rhel8.2')
self._retag_image_statement(mySSH, 'ran-build', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-build', imageTag, 'docker/Dockerfile.nrUE.rhel8.2')
nrue_job = self._start_build(mySSH, 'oai-nr-ue')
self._recreate_is_tag('oai-nr-ue', imageTag, 'openshift/oai-nr-ue-is.yaml')
self._recreate_bc('oai-nr-ue', imageTag, 'openshift/oai-nr-ue-bc.yaml')
self._retag_image_statement('ran-base', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-base', baseTag, 'docker/Dockerfile.nrUE.rhel8.2')
self._retag_image_statement('ran-build', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-build', imageTag, 'docker/Dockerfile.nrUE.rhel8.2')
nrue_job = self._start_build('oai-nr-ue')
attemptedImages += ['oai-nr-ue']
wait = lteue_job is not None and nrue_job is not None and self._wait_build_end(mySSH, [lteue_job, nrue_job], 600)
wait = lteue_job is not None and nrue_job is not None and self._wait_build_end([lteue_job, nrue_job], 600)
if not wait: logging.error('error during build of lteUE/nrUE')
status = status and wait
# recover logs
mySSH.command(f'oc logs {lteue_job} &> cmake_targets/log/oai-lte-ue.log', '\$', 10)
mySSH.command(f'oc logs {nrue_job} &> cmake_targets/log/oai-nr-ue.log', '\$', 10)
mySSH.command('oc get pods.metrics.k8s.io >> cmake_targets/log/build-metrics.log', '\$', 10)
self.cmd.run(f'oc logs {lteue_job} &> cmake_targets/log/oai-lte-ue.log')
self.cmd.run(f'oc logs {nrue_job} &> cmake_targets/log/oai-nr-ue.log')
self.cmd.run(f'oc get pods.metrics.k8s.io &>> cmake_targets/log/build-metrics.log', '\$', 10)
# split and analyze logs
imageSize = {}
for image in attemptedImages:
mySSH.command(f'mkdir -p cmake_targets/log/{image}', '\$', 5)
mySSH.command(f'python3 ci-scripts/docker_log_split.py --logfilename=cmake_targets/log/{image}.log', '\$', 5)
self.cmd.run(f'mkdir -p cmake_targets/log/{image}')
self.cmd.run(f'python3 ci-scripts/docker_log_split.py --logfilename=cmake_targets/log/{image}.log')
tag = imageTag if image != 'ran-base' else baseTag
size = self._get_image_size(mySSH, image, tag)
size = self._get_image_size(image, tag)
if size <= 0:
imageSize[image] = 'unknown -- BUILD FAILED'
status = False
@@ -361,17 +340,17 @@ class Cluster:
logging.info(f'\u001B[1m{image} size is {imageSize[image]}\u001B[0m')
grep_exp = "\|".join(attemptedImages)
mySSH.command(f'oc get images | grep -e \'{grep_exp}\' &> cmake_targets/log/image_registry.log', '\$', 10);
mySSH.command('for pod in $(oc get pods | tail -n +2 | awk \'{print $1}\'); do oc get pod $pod -o json >> cmake_targets/log/build_pod_summary.log; done', '\$', 60)
self.cmd.run(f'oc get images | grep -e \'{grep_exp}\' &> cmake_targets/log/image_registry.log');
self.cmd.run(f'for pod in $(oc get pods | tail -n +2 | awk \'{{print $1}}\'); do oc get pod $pod -o json &>> cmake_targets/log/build_pod_summary.log; done', '\$', 60)
build_log_name = f'build_log_{self.testCase_id}'
cls_containerize.CopyLogsToExecutor(mySSH, lSourcePath, build_log_name, lIpAddr, 'oaicicd', CONST.CI_NO_PASSWORD)
cls_containerize.CopyLogsToExecutor(self.cmd, lSourcePath, build_log_name)
mySSH.command('for pod in $(oc get pods | tail -n +2 | awk \'{print $1}\'); do oc delete pod ${pod}; done', '\$', 60)
self.cmd.run('for pod in $(oc get pods | tail -n +2 | awk \'{print $1}\'); do oc delete pod ${pod}; done')
# logout will return eventually, but we don't care when -> start in background
mySSH.command('oc logout &', '\$', 5)
mySSH.close()
self.cmd.run(f'oc logout')
self.cmd.close()
# Analyze the logs
collectInfo = cls_containerize.AnalyzeBuildLogs(build_log_name, attemptedImages, status)

217
ci-scripts/cls_cmd.py Normal file
View File

@@ -0,0 +1,217 @@
#/*
# * 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
#
#---------------------------------------------------------------------
import abc
import logging
import subprocess as sp
import os
import paramiko
import uuid
# provides a partial interface for the legacy SSHconnection class (getBefore(), command())
class Cmd(metaclass=abc.ABCMeta):
def cd(self, d, silent=False):
if d == None or d == '' or d == []:
self.cwd = None
elif d[0] == '/':
self.cwd = d
else:
if not self.cwd:
# no cwd set: get current working directory
self.cwd = self.run('pwd').stdout.strip()
self.cwd += f"/{d}"
if not silent:
logging.debug(f'cd {self.cwd}')
@abc.abstractmethod
def run(self, line, timeout=300, silent=False):
return
@abc.abstractmethod
def command(self, commandline, expectedline, timeout, silent=False, resync=False):
return
@abc.abstractmethod
def close(self):
return
@abc.abstractmethod
def getBefore(self):
return
@abc.abstractmethod
def copyin(self, scpIp, scpUser, scpPw, src, tgt):
return
@abc.abstractmethod
def copyout(self, scpIp, scpUser, scpPw, src, tgt):
return
class LocalCmd(Cmd):
def __init__(self, d = None):
self.cwd = d
self.cp = sp.CompletedProcess(args='', returncode=0, stdout='')
def run(self, line, timeout=300, silent=False, reportNonZero=True):
if type(line) is str:
line = [s for s in line.split(' ') if len(s) > 0]
if not silent:
logging.debug(' '.join(line))
try:
ret = sp.run(line, 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:
ret.stdout = b''
ret.stdout = ret.stdout.decode('utf-8').strip()
if reportNonZero and ret.returncode != 0:
cmd = ' '.join(ret.args)
logging.warning(f'command "{cmd}" returned non-zero returncode {ret.returncode}: output:\n{ret.stdout}')
self.cp = ret
return ret
def command(self, commandline, expectedline=None, timeout=300, silent=False, resync=False):
line = [s for s in commandline.split(' ') if len(s) > 0]
if line[0] == 'cd':
self.cd(line[1], silent)
else:
self.run(line, timeout, silent)
return 0
def close(self):
pass
def getBefore(self):
return self.cp.stdout
def copyin(self, scpIp, scpUser, scpPw, src, tgt):
logging.warning("LocalCmd emulating sshconnection.copyin() function")
self.run(f'cp -r {src} {tgt}')
def copyout(self, scpIp, scpUser, scpPw, src, tgt):
logging.warning("LocalCmd emulating sshconnection.copyout() function")
self.run(f'cp -r {src} {tgt}')
class RemoteCmd(Cmd):
def __init__(self, hostname, d=None):
logging.getLogger('paramiko').setLevel(logging.INFO) # prevent spamming through Paramiko
self.client = paramiko.SSHClient()
self.client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
cfg = RemoteCmd._lookup_ssh_config(hostname)
self.client.connect(**cfg)
self.cwd = d
self.cp = sp.CompletedProcess(args='', returncode=0, stdout='')
def _lookup_ssh_config(hostname):
ssh_config = paramiko.SSHConfig()
user_config_file = os.path.expanduser("~/.ssh/config")
if os.path.exists(user_config_file):
with open(user_config_file) as f:
ssh_config.parse(f)
else:
raise FileNotFoundError('class needs SSH config at ~/.ssh/config')
ucfg = ssh_config.lookup(hostname)
if 'identityfile' not in ucfg or 'user' not in ucfg:
raise KeyError(f'no identityfile or user in SSH config for host {hostname}')
cfg = {'hostname':hostname, 'username':ucfg['user'], 'key_filename':ucfg['identityfile']}
if 'hostname' in ucfg:
cfg['hostname'] = ucfg['hostname'] # override user-given hostname with what is in config
if 'port' in ucfg:
cfg['port'] = int(ucfg['port'])
if 'proxycommand' in ucfg:
cfg['sock'] = paramiko.ProxyCommand(ucfg['proxycommand'])
return cfg
def run(self, line, timeout=300, silent=False, reportNonZero=True):
if type(line) is list:
line = ' '.join(line)
if not silent:
logging.debug(line)
if self.cwd:
line = f"cd {self.cwd} && {line}"
args = line.split(' ')
try:
stdin, stdout, stderr = self.client.exec_command(line, timeout=timeout)
ret = sp.CompletedProcess(args=args, returncode=stdout.channel.recv_exit_status(), stdout=stdout.read(size=None) + stderr.read(size=None))
except Exception as e:
ret = sp.CompletedProcess(args=args, returncode=255, stdout=f'Exception: {str(e)}'.encode('utf-8'))
ret.stdout = ret.stdout.decode('utf-8').strip()
if reportNonZero and ret.returncode != 0:
cmd = ' '.join(ret.args)
logging.warning(f'command "{cmd}" returned non-zero returncode {ret.returncode}: output:\n{ret.stdout}')
self.cp = ret
return ret
def command(self, commandline, expectedline=None, timeout=300, silent=False, resync=False):
line = [s for s in commandline.split(' ') if len(s) > 0]
if line[0] == 'cd':
self.cd(line[1], silent)
else:
self.run(line, timeout, silent)
return 0
def close(self):
self.client.close()
def getBefore(self):
return self.cp.stdout
def copyout(self, src, tgt, recursive=False):
logging.warning("RemoteCmd emulating sshconnection.copyout() function, ignoring scpIp")
logging.debug(f"copyout: local:{src} -> remote:{tgt}")
if recursive:
tmpfile = f"{uuid.uuid4()}.tar"
abstmpfile = f"/tmp/{tmpfile}"
cmd = LocalCmd()
cmd.run(f"tar -cf {abstmpfile} {src}")
sftp = self.client.open_sftp()
sftp.put(abstmpfile, abstmpfile)
sftp.close()
cmd.run(f"rm {abstmpfile}")
self.run(f"mv {abstmpfile} {tgt}; cd {tgt} && tar -xf {tmpfile} && rm {tmpfile}")
else:
sftp = self.client.open_sftp()
sftp.put(src, tgt)
sftp.close()
def copyin(self, src, tgt, recursive=False):
logging.warning("RemoteCmd emulating sshconnection.copyout() function")
logging.debug(f"copyin: remote:{src} -> local:{tgt}")
if recursive:
tmpfile = f"{uuid.uuid4()}.tar"
abstmpfile = f"/tmp/{tmpfile}"
self.run(f"tar -cf {abstmpfile} {src}")
sftp = self.client.open_sftp()
sftp.get(abstmpfile, abstmpfile)
sftp.close()
self.run(f"rm {abstmpfile}")
cmd = LocalCmd()
cmd.run(f"mv {abstmpfile} {tgt}; cd {tgt} && tar -xf {tmpfile} && rm {tmpfile}")
else:
sftp = self.client.open_sftp()
sftp.get(src, tgt)
sftp.close()

View File

@@ -44,6 +44,7 @@ from zipfile import ZipFile
#-----------------------------------------------------------
# OAI Testing modules
#-----------------------------------------------------------
import cls_cmd
import sshconnection as SSH
import helpreadme as HELP
import constants as CONST
@@ -83,20 +84,20 @@ def CreateWorkspace(sshSession, sourcePath, ranRepository, ranCommitID, ranTarge
logging.debug(f'Merging with the target branch: {ranTargetBranch}')
sshSession.command(f'git merge --ff origin/{ranTargetBranch} -m "Temporary merge for CI"', '\$', 30)
def CopyLogsToExecutor(sshSession, sourcePath, log_name, scpIp, scpUser, scpPw):
sshSession.command(f'cd {sourcePath}/cmake_targets', '\$', 5)
sshSession.command(f'rm -f {log_name}.zip', '\$', 5)
sshSession.command(f'mkdir -p {log_name}', '\$', 5)
sshSession.command(f'mv log/* {log_name}', '\$', 5)
sshSession.command(f'zip -r -qq {log_name}.zip {log_name}', '\$', 5)
def CopyLogsToExecutor(cmd, sourcePath, log_name):
cmd.cd(f'{sourcePath}/cmake_targets')
cmd.run(f'rm -f {log_name}.zip')
cmd.run(f'mkdir -p {log_name}')
cmd.run(f'mv log/* {log_name}')
cmd.run(f'zip -r -qq {log_name}.zip {log_name}')
# copy zip to executor for analysis
if (os.path.isfile(f'./{log_name}.zip')):
os.remove(f'./{log_name}.zip')
if (os.path.isdir(f'./{log_name}')):
shutil.rmtree(f'./{log_name}')
sshSession.copyin(scpIp, scpUser, scpPw, f'{sourcePath}/cmake_targets/{log_name}.zip', '.')
sshSession.command(f'rm -f {log_name}.zip','\$', 5)
cmd.copyin(f'{sourcePath}/cmake_targets/{log_name}.zip', f'./{log_name}.zip')
cmd.run(f'rm -f {log_name}.zip')
ZipFile(f'{log_name}.zip').extractall('.')
def AnalyzeBuildLogs(buildRoot, images, globalStatus):
@@ -329,12 +330,11 @@ class Containerize():
HELP.GenericHelp(CONST.Version)
sys.exit('Insufficient Parameter')
logging.debug('Building on server: ' + lIpAddr)
mySSH = SSH.SSHConnection()
mySSH.open(lIpAddr, lUserName, lPassWord)
cmd = cls_cmd.RemoteCmd(lIpAddr)
# Checking the hostname to get adapted on cli and dockerfileprefixes
mySSH.command('hostnamectl', '\$', 5)
result = re.search('Ubuntu|Red Hat', mySSH.getBefore())
cmd.run('hostnamectl')
result = re.search('Ubuntu|Red Hat', cmd.getBefore())
self.host = result.group(0)
if self.host == 'Ubuntu':
self.cli = 'docker'
@@ -369,18 +369,18 @@ class Containerize():
# Workaround for some servers, we need to erase completely the workspace
if self.forcedWorkspaceCleanup:
mySSH.command('echo ' + lPassWord + ' | sudo -S rm -Rf ' + lSourcePath, '\$', 15)
cmd.run(f'sudo -S rm -Rf {lSourcePath}')
self.testCase_id = HTML.testCase_id
CreateWorkspace(mySSH, lSourcePath, self.ranRepository, self.ranCommitID, self.ranTargetBranch, self.ranAllowMerge)
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':
mySSH.command('mkdir -p ./etc-pki-entitlement ./rhsm-conf ./rhsm-ca', '\$', 5)
mySSH.command('sudo cp /etc/rhsm/rhsm.conf ./rhsm-conf/', '\$', 5)
mySSH.command('sudo cp /etc/rhsm/ca/redhat-uep.pem ./rhsm-ca/', '\$', 5)
mySSH.command('sudo cp /etc/pki/entitlement/*.pem ./etc-pki-entitlement/', '\$', 5)
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'
baseTag = 'develop'
@@ -389,8 +389,8 @@ class Containerize():
if (self.ranAllowMerge):
imageTag = 'ci-temp'
if self.ranTargetBranch == 'develop':
mySSH.command('git diff HEAD..origin/develop -- cmake_targets/build_oai cmake_targets/tools/build_helper docker/Dockerfile.base' + self.dockerfileprefix + ' | grep --colour=never -i INDEX', '\$', 5)
result = re.search('index', mySSH.getBefore())
cmd.run(f'git diff HEAD..origin/develop -- cmake_targets/build_oai cmake_targets/tools/build_helper docker/Dockerfile.base{self.dockerfileprefix} | grep --colour=never -i INDEX')
result = re.search('index', cmd.getBefore())
if result is not None:
forceBaseImageBuild = True
baseTag = 'ci-temp'
@@ -398,31 +398,31 @@ class Containerize():
forceBaseImageBuild = True
# Let's remove any previous run artifacts if still there
mySSH.command(self.cli + ' image prune --force', '\$', 30)
cmd.run(f"{self.cli} image prune --force")
if forceBaseImageBuild:
mySSH.command(self.cli + ' image rm ' + baseImage + ':' + baseTag + ' || true', '\$', 30)
cmd.run(f"{self.cli} image rm {baseImage}:{baseTag}")
for image,pattern in imageNames:
mySSH.command(self.cli + ' image rm ' + image + ':' + imageTag + ' || true', '\$', 30)
cmd.run(f"{self.cli} image rm {image}:{imageTag}")
# Build the base image only on Push Events (not on Merge Requests)
# On when the base image docker file is being modified.
if forceBaseImageBuild:
mySSH.command(self.cli + ' build ' + self.cliBuildOptions + ' --target ' + baseImage + ' --tag ' + baseImage + ':' + baseTag + ' --file docker/Dockerfile.base' + self.dockerfileprefix + ' . > cmake_targets/log/ran-base.log 2>&1', '\$', 1600)
cmd.run(f"{self.cli} build {self.cliBuildOptions} --target {baseImage} --tag {baseImage}:{baseTag} --file docker/Dockerfile.base{self.dockerfileprefix} . &> cmake_targets/log/ran-base.log", timeout=1600)
# First verify if the base image was properly created.
mySSH.command(self.cli + ' image inspect --format=\'Size = {{.Size}} bytes\' ' + baseImage + ':' + baseTag, '\$', 5)
ret = cmd.run(f"{self.cli} image inspect --format=\'Size = {{{{.Size}}}} bytes\' {baseImage}:{baseTag}")
allImagesSize = {}
if mySSH.getBefore().count('o such image') != 0:
if ret.returncode != 0:
logging.error('\u001B[1m Could not build properly ran-base\u001B[0m')
# Recover the name of the failed container?
mySSH.command(self.cli + ' ps --quiet --filter "status=exited" -n1 | xargs ' + self.cli + ' rm -f', '\$', 5)
mySSH.command(self.cli + ' image prune --force', '\$', 30)
mySSH.close()
cmd.run(f"{self.cli} ps --quiet --filter \"status=exited\" -n1 | xargs {self.cli} rm -f")
cmd.run(f"{self.cli} image prune --force")
cmd.close()
logging.error('\u001B[1m Building OAI Images Failed\u001B[0m')
HTML.CreateHtmlTestRow(self.imageKind, 'KO', CONST.ALL_PROCESSES_OK)
HTML.CreateHtmlTabFooter(False)
sys.exit(1)
else:
result = re.search('Size *= *(?P<size>[0-9\-]+) *bytes', mySSH.getBefore())
result = re.search('Size *= *(?P<size>[0-9\-]+) *bytes', cmd.getBefore())
if result is not None:
size = float(result.group("size")) / 1000000
imageSizeStr = f'{size:.1f}'
@@ -432,10 +432,10 @@ class Containerize():
logging.debug('ran-base size is unknown')
# Recover build logs, for the moment only possible when build is successful
mySSH.command(self.cli + ' create --name test ' + baseImage + ':' + baseTag, '\$', 5)
mySSH.command('mkdir -p cmake_targets/log/ran-base', '\$', 5)
mySSH.command(self.cli + ' cp test:/oai-ran/cmake_targets/log/. cmake_targets/log/ran-base', '\$', 5)
mySSH.command(self.cli + ' rm -f test', '\$', 5)
cmd.run(f"{self.cli} create --name test {baseImage}:{baseTag}")
cmd.run("mkdir -p cmake_targets/log/ran-base")
cmd.run(f"{self.cli} cp test:/oai-ran/cmake_targets/log/. cmake_targets/log/ran-base")
cmd.run(f"{self.cli} rm -f test")
# Build the target image(s)
status = True
@@ -444,26 +444,26 @@ class Containerize():
attemptedImages += [image]
# the archived Dockerfiles have "ran-base:latest" as base image
# we need to update them with proper tag
mySSH.command(f'sed -i -e "s#{baseImage}:latest#{baseImage}:{baseTag}#" docker/Dockerfile.{pattern}{self.dockerfileprefix}', '\$', 5)
cmd.run(f'sed -i -e "s#{baseImage}:latest#{baseImage}:{baseTag}#" docker/Dockerfile.{pattern}{self.dockerfileprefix}')
if image != 'ran-build':
mySSH.command(f'sed -i -e "s#ran-build:latest#ran-build:{imageTag}#" docker/Dockerfile.{pattern}{self.dockerfileprefix}', '\$', 5)
mySSH.command(f'{self.cli} build {self.cliBuildOptions} --target {image} --tag {image}:{imageTag} --file docker/Dockerfile.{pattern}{self.dockerfileprefix} . > cmake_targets/log/{image}.log 2>&1', '\$', 1200)
cmd.run(f'sed -i -e "s#ran-build:latest#ran-build:{imageTag}#" docker/Dockerfile.{pattern}{self.dockerfileprefix}')
cmd.run(f'{self.cli} build {self.cliBuildOptions} --target {image} --tag {image}:{imageTag} --file docker/Dockerfile.{pattern}{self.dockerfileprefix} . > cmake_targets/log/{image}.log 2>&1', timeout=1200)
# split the log
mySSH.command('mkdir -p cmake_targets/log/' + image, '\$', 5)
mySSH.command('python3 ci-scripts/docker_log_split.py --logfilename=cmake_targets/log/' + image + '.log', '\$', 5)
# checking the status of the build
mySSH.command(self.cli + ' image inspect --format=\'Size = {{.Size}} bytes\' ' + image + ':' + imageTag, '\$', 5)
if mySSH.getBefore().count('o such image') != 0:
cmd.run(f"mkdir -p cmake_targets/log/{image}")
cmd.run(f"python3 ci-scripts/docker_log_split.py --logfilename=cmake_targets/log/{image}.log")
# check the status of the build
ret = cmd.run(f"{self.cli} image inspect --format=\'Size = {{{{.Size}}}} bytes\' {image}:{imageTag}")
if ret.returncode != 0:
logging.error('\u001B[1m Could not build properly ' + image + '\u001B[0m')
status = False
# Here we should check if the last container corresponds to a failed command and destroy it
mySSH.command(self.cli + ' ps --quiet --filter "status=exited" -n1 | xargs ' + self.cli + ' rm -f', '\$', 5)
cmd.run(f"{self.cli} ps --quiet --filter \"status=exited\" -n1 | xargs {self.cli} rm -f")
allImagesSize[image] = 'N/A -- Build Failed'
break
else:
result = re.search('Size *= *(?P<size>[0-9\-]+) *bytes', mySSH.getBefore())
result = re.search('Size *= *(?P<size>[0-9\-]+) *bytes', cmd.getBefore())
if result is not None:
size = float(result.group("size")) / 1000000
size = float(result.group("size")) / 1000000 # convert to MB
imageSizeStr = f'{size:.1f}'
logging.debug(f'\u001B[1m {image} size is {imageSizeStr} Mbytes\u001B[0m')
allImagesSize[image] = f'{imageSizeStr} Mbytes'
@@ -471,18 +471,18 @@ class Containerize():
logging.debug(f'{image} size is unknown')
allImagesSize[image] = 'unknown'
# Now pruning dangling images in between target builds
mySSH.command(self.cli + ' image prune --force', '\$', 30)
cmd.run(f"{self.cli} image prune --force")
# Remove all intermediate build images and clean up
if self.ranAllowMerge and forceBaseImageBuild:
mySSH.command(f'{self.cli} image rm {baseImage}:{baseTag} || true', '\$', 30)
mySSH.command(f'{self.cli} image rm ran-build:{imageTag}','\$', 30)
mySSH.command(f'{self.cli} volume prune --force','\$', 15)
cmd.run(f"{self.cli} image rm {baseImage}:{baseTag}")
cmd.run(f"{self.cli} image rm ran-build:{imageTag}")
cmd.run(f"{self.cli} volume prune --force")
# create a zip with all logs
build_log_name = f'build_log_{self.testCase_id}'
CopyLogsToExecutor(mySSH, lSourcePath, build_log_name, lIpAddr, lUserName, lPassWord)
mySSH.close()
CopyLogsToExecutor(cmd, lSourcePath, build_log_name)
cmd.close()
# Analyze the logs
collectInfo = AnalyzeBuildLogs(build_log_name, attemptedImages, status)
@@ -1001,7 +1001,7 @@ class Containerize():
services.append(s)
logging.info(f'stopping services {services}')
mySSH.command(f'docker-compose -f ci-docker-compose.yml stop', '\$', 30)
mySSH.command(f'docker-compose -f ci-docker-compose.yml stop -t3', '\$', 30)
time.sleep(5) # give some time to running containers to stop
for svcName in services:
# head -n -1 suppresses the final "X exited with status code Y"
@@ -1203,7 +1203,7 @@ class Containerize():
# Stop the containers to shut down objects
logging.debug('\u001B[1m Stopping containers \u001B[0m')
cmd = 'cd ' + self.yamlPath[0] + ' && docker-compose -f docker-compose-ci.yml stop'
cmd = 'cd ' + self.yamlPath[0] + ' && docker-compose -f docker-compose-ci.yml stop -t3'
logging.info(cmd)
try:
deployStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=100)

View File

@@ -193,6 +193,7 @@ class OaiCiTest():
self.expectedNbOfConnectedUEs = 0
self.ue_id = '' #used for module identification
self.ue_trace ='' #used to enable QLog trace for Module UE, passed to Module UE object at InitializeUE()
self.cmd_prefix = '' # prefix before {lte,nr}-uesoftmodem
def BuildOAIUE(self,HTML):
@@ -489,7 +490,7 @@ class OaiCiTest():
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('echo "ulimit -c unlimited && ./'+ self.air_interface +' ' + self.Initialize_OAI_UE_args + '" > ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5)
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('chmod 775 ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5)
SSH.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log', '\$', 5)
self.UELogFile = 'ue_' + self.testCase_id + '.log'

View File

@@ -32,13 +32,14 @@
# Import
#-----------------------------------------------------------
import logging
import sshconnection as SSH
import cls_oai_html
import os
import re
import time
import subprocess
import sys
import sshconnection as SSH
import cls_oai_html
import constants as CONST
import helpreadme as HELP
@@ -105,7 +106,7 @@ class PhySim:
if self.ranCommitID != '':
mySSH.command('git checkout -f ' + self.ranCommitID, '\$', 30)
if self.ranAllowMerge:
imageTag = "ci-temp"
imageTag = f'{self.ranBranch}-{self.ranCommitID[0:8]}'
if self.ranTargetBranch == '':
if (self.ranBranch != 'develop') and (self.ranBranch != 'origin/develop'):
mySSH.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 30)

View File

@@ -0,0 +1,284 @@
Active_gNBs = ( "5G-GOA-gNB");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";
gNBs =
(
{
////////// Identification parameters:
gNB_ID = 0xe00;
gNB_name = "5G-GOA-gNB";
// Tracking area code, 0x0000 and 0xfffe are reserved values
tracking_area_code = 1;
plmn_list = ({ mcc = 208; mnc = 99; mnc_length = 2; snssaiList = ({ sst = 1 }) });
nr_cellid = 12345678L;
////////// Physical parameters:
sib1_tda = 5;
min_rxtxtime = 6;
pdcch_ConfigSIB1 = (
{
controlResourceSetZero = 2;
searchSpaceZero = 0;
}
);
servingCellConfigCommon = (
{
#spCellConfigCommon
physCellId = 0;
# downlinkConfigCommon
#frequencyInfoDL
# this is 2150 MHz + 14 PRBs@15kHz SCS (same as initial BWP), points to Subcarrier 0 of RB#10 of SSB block
absoluteFrequencySSB = 430504;
dl_frequencyBand = 66;
# this is 2150 MHz
dl_absoluteFrequencyPointA = 430000;
#scs-SpecificCarrierList
dl_offstToCarrier = 0;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
dl_subcarrierSpacing = 0;
dl_carrierBandwidth = 25;
#initialDownlinkBWP
#genericParameters
# this is RBstart=0,L=25 (275*(L-1))+RBstart
initialDLBWPlocationAndBandwidth = 6600;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
initialDLBWPsubcarrierSpacing = 0;
#pdcch-ConfigCommon
initialDLBWPcontrolResourceSetZero = 2;
initialDLBWPsearchSpaceZero = 0;
#uplinkConfigCommon
#frequencyInfoUL
ul_frequencyBand = 66;
# this is 1750 MHz
ul_absoluteFrequencyPointA = 350000;
#scs-SpecificCarrierList
ul_offstToCarrier = 0;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
ul_subcarrierSpacing = 0;
ul_carrierBandwidth = 25;
pMax = 20;
#initialUplinkBWP
#genericParameters
initialULBWPlocationAndBandwidth = 6600;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
initialULBWPsubcarrierSpacing = 0;
#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 = 13;
preambleReceivedTargetPower = -118;
#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 = 4;
#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 = 4;
#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 = 0;
# 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_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
ssb_periodicityServingCell = 2;
# dmrs_TypeA_position
# 0 = pos2, 1 = pos3
dmrs_TypeA_Position = 0;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
subcarrierSpacing = 0;
#tdd-UL-DL-ConfigurationCommon
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
referenceSubcarrierSpacing = 0;
# 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 definitions
SCTP :
{
# Number of streams to use in input/output
SCTP_INSTREAMS = 2;
SCTP_OUTSTREAMS = 2;
};
////////// AMF parameters:
amf_ip_address = ( { ipv4 = "192.168.71.132";
ipv6 = "192:168:30::17";
active = "yes";
preference = "ipv4";
}
);
NETWORK_INTERFACES :
{
GNB_INTERFACE_NAME_FOR_NG_AMF = "eno1";
GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.71.140/26";
GNB_INTERFACE_NAME_FOR_NGU = "eno1";
GNB_IPV4_ADDRESS_FOR_NGU = "192.168.71.140/26";
GNB_PORT_FOR_S1U = 2152; # Spec 2152
};
}
);
MACRLCs = (
{
num_cc = 1;
tr_s_preference = "local_L1";
tr_n_preference = "local_RRC";
pusch_TargetSNRx10 = 150;
pucch_TargetSNRx10 = 200;
ulsch_max_frame_inactivity = 0;
}
);
L1s = (
{
num_cc = 1;
tr_n_preference = "local_mac";
prach_dtx_threshold = 120;
pucch0_dtx_threshold = 150;
ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0
}
);
RUs = (
{
local_rf = "yes";
nb_tx = 1;
nb_rx = 1;
att_tx = 0;
att_rx = 0;
bands = [7];
max_pdschReferenceSignalPower = -27;
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;
# if_offset = 1000000;
}
);
THREAD_STRUCT = (
{
#three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
parallel_config = "PARALLEL_RU_L1_TRX_SPLIT";
#two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
worker_config = "WORKER_DISABLE";
}
);
rfsimulator :
{
serveraddr = "server";
serverport = "4043";
options = (); #("saviq"); or/and "chanmod"
modelname = "AWGN";
IQfile = "/tmp/rfsimulator.iqs";
};
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";
};

View File

@@ -0,0 +1,335 @@
Active_gNBs = ( "gNB-OAI");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";
gNBs =
(
{
////////// Identification parameters:
gNB_ID = 0xe00;
gNB_name = "gNB-OAI";
// Tracking area code, 0x0000 and 0xfffe are reserved values
tracking_area_code = 1;
plmn_list = ({ mcc = 208; mnc = 99; mnc_length = 2; snssaiList = ({ sst = 1 }) });
nr_cellid = 12345678L;
////////// Physical parameters:
pdsch_AntennaPorts_XP = 2;
pusch_AntennaPorts = 2;
do_CSIRS = 1;
do_SRS = 1;
min_rxtxtime = 5;
pdcch_ConfigSIB1 = (
{
controlResourceSetZero = 12;
searchSpaceZero = 0;
}
);
servingCellConfigCommon = (
{
#spCellConfigCommon
physCellId = 0;
# downlinkConfigCommon
#frequencyInfoDL
# this is 3300.60 MHz + 53*12*30e-3 MHz = 3319.68
absoluteFrequencySSB = 621312; # 641280
dl_frequencyBand = 78;
# this is 3300.60 MHz
dl_absoluteFrequencyPointA = 620040; # 640008
#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=27,L=48 (275*(L-1))+RBstart
initialDLBWPlocationAndBandwidth = 28875; # 6366 12925 12956 28875 12952
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
initialDLBWPsubcarrierSpacing = 1;
#pdcch-ConfigCommon
initialDLBWPcontrolResourceSetZero = 12;
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 = -96;
#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 = 4;
#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 = -70;
# 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
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;
}
);
# Dedicated Serving Cell Configuration
servingCellConfigDedicated = ({
# BWP-Downlink
# BWP 1 Configuration
dl_bwp-Id_1 = 1;
dl_bwp1_locationAndBandwidth = 28875; // RBstart=0, L=106 (40 MHz BW)
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
dl_bwp1_subcarrierSpacing = 1;
# BWP 2 Configuration
dl_bwp-Id_2 = 2;
dl_bwp2_locationAndBandwidth = 13750; // RBstart=0, L=51 (20 MHz BW)
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
dl_bwp2_subcarrierSpacing = 1;
# BWP 3 Configuration
dl_bwp-Id_3 = 3;
dl_bwp3_locationAndBandwidth = 6325; // RBstart=0, L=24 (10 MHz BW)
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
dl_bwp3_subcarrierSpacing = 1;
firstActiveDownlinkBWP-Id = 1; #BWP-Id
defaultDownlinkBWP-Id = 1; #BWP-Id
# bwp-InactivityTimer ENUMERATED {ms2, ms3, ms4, ms5, ms6, ms8, ms10, ms20, ms30,
# ms40,ms50, ms60, ms80,ms100, ms200,ms300, ms500,
# ms750, ms1280, ms1920, ms2560, spare10, spare9, spare8,
# spare7, spare6, spare5, spare4, spare3, spare2, spare1 }
# UplinkConfig
# BWP-Uplink
# BWP 1 Configuration
ul_bwp-Id_1 = 1;
ul_bwp1_locationAndBandwidth = 28875; // RBstart=0, L=106 (40 MHz BW)
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
ul_bwp1_subcarrierSpacing = 1;
# BWP 2 Configuration
ul_bwp-Id_2 = 2;
ul_bwp2_locationAndBandwidth = 13750; // RBstart=0, L=51 (20 MHz BW)
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
ul_bwp2_subcarrierSpacing = 1;
# BWP 3 Configuration
ul_bwp-Id_3 = 3;
ul_bwp3_locationAndBandwidth = 6325; // RBstart=0, L=24 (10 MHz BW)
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
ul_bwp3_subcarrierSpacing = 1;
firstActiveUplinkBWP-Id = 1; #BWP-Id
}
);
# ------- SCTP definitions
SCTP :
{
# Number of streams to use in input/output
SCTP_INSTREAMS = 2;
SCTP_OUTSTREAMS = 2;
};
////////// AMF parameters:
amf_ip_address = ( { ipv4 = "192.168.71.132";
ipv6 = "192:168:30::17";
active = "yes";
preference = "ipv4";
}
);
NETWORK_INTERFACES :
{
GNB_INTERFACE_NAME_FOR_NG_AMF = "demo-oai";
GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.71.140/24";
GNB_INTERFACE_NAME_FOR_NGU = "demo-oai";
GNB_IPV4_ADDRESS_FOR_NGU = "192.168.71.140/24";
GNB_PORT_FOR_S1U = 2152; # Spec 2152
};
}
);
MACRLCs = (
{
num_cc = 1;
tr_s_preference = "local_L1";
tr_n_preference = "local_RRC";
#pusch_TargetSNRx10 = 150;
#pucch_TargetSNRx10 = 200;
ulsch_max_frame_inactivity = 0;
dl_max_mcs = 16; # there are retransmissions if more
}
);
L1s = (
{
num_cc = 1;
tr_n_preference = "local_mac";
prach_dtx_threshold = 120;
#pucch0_dtx_threshold = 120;
}
);
RUs = (
{
local_rf = "yes"
nb_tx = 2
nb_rx = 2
att_tx = 0
att_rx = 0;
bands = [78];
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"
}
);
THREAD_STRUCT = (
{
#three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
parallel_config = "PARALLEL_SINGLE_THREAD";
#two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
worker_config = "WORKER_ENABLE";
}
);
rfsimulator :
{
serveraddr = "server";
serverport = "4043";
options = (); #("saviq"); or/and "chanmod"
modelname = "AWGN";
IQfile = "/tmp/rfsimulator.iqs";
};
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";
};

View File

@@ -1,107 +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
# */
function create_usage {
echo "OAI CI VM script"
echo " Original Author: Raphael Defosseux"
echo " Requirements:"
echo " -- uvtool uvtool-libvirt apt-cacher"
echo " -- $VM_OSREL image already synced"
echo " Default:"
echo " -- eNB with USRP"
echo ""
echo "Usage:"
echo "------"
echo " oai-ci-vm-tool create [OPTIONS]"
echo ""
echo "Mandatory Options:"
echo "--------"
echo " --job-name #### OR -jn ####"
echo " Specify the name of the Jenkins job."
echo ""
echo " --build-id #### OR -id ####"
echo " Specify the build ID of the Jenkins job."
echo ""
variant_usage
echo " Specify the variant to build."
echo ""
echo " --help OR -h"
echo " Print this help message."
echo ""
}
function acquire_vm_create_lock {
local FlockFile="/tmp/vmclone.lck"
local unlocked="0"
touch ${FlockFile} 2>/dev/null
if [[ $? -ne 0 ]]
then
echo "Cannot access lock file ${FlockFile}"
exit 2
fi
while [ $unlocked -eq 0 ]
do
exec 5>${FlockFile}
flock -nx 5
if [[ $? -ne 0 ]]
then
echo "Another instance of VM creation is running"
sleep 10
else
unlocked="1"
fi
done
chmod 666 ${FlockFile} 2>/dev/null
}
function release_vm_create_lock {
local FlockFile="/tmp/vmclone.lck"
rm -Rf ${FlockFile}
}
function create_vm {
echo "############################################################"
echo "OAI CI VM script"
echo "############################################################"
echo "VM_NAME = $VM_NAME"
echo "VM_MEMORY = $VM_MEMORY MBytes"
echo "VM_CPU = $VM_CPU"
echo "VM_DISK = $VM_DISK GBytes"
if [[ "$VM_NAME" == *"-enb-usrp"* ]] || [[ "$VM_NAME" == *"-cppcheck"* ]] || [[ "$VM_NAME" == *"-phy-sim"* ]] || [[ "$VM_NAME" == *"-rf-sim"* ]] || [[ "$VM_NAME" == *"-ethernet"* ]] || [[ "$VM_NAME" == *"rf5g-sim"* ]]
then
echo "This VM type is no longer supported in the pipeline framework"
return
fi
echo "############################################################"
echo "Creating VM ($VM_NAME) on Ubuntu Cloud Image base"
echo "############################################################"
acquire_vm_create_lock
uvt-kvm create $VM_NAME release=$VM_OSREL --memory $VM_MEMORY --cpu $VM_CPU --disk $VM_DISK --unsafe-caching --template ci-scripts/template-host.xml
echo "Waiting for VM to be started"
uvt-kvm wait $VM_NAME --insecure
VM_IP_ADDR=`uvt-kvm ip $VM_NAME`
echo "$VM_NAME has for IP addr = $VM_IP_ADDR"
release_vm_create_lock
}

View File

@@ -1,31 +0,0 @@
<table style="border-collapse: collapse; border: none;">
<tr style="border-collapse: collapse; border: none;">
<td style="border-collapse: collapse; border: none;">
<a href="http://www.openairinterface.org/">
<img src="../../doc/images/oai_final_logo.png" alt="" border=3 height=50 width=150>
</img>
</a>
</td>
<td style="border-collapse: collapse; border: none; vertical-align: center;">
<b><font size = "5">OAI CI Dev documentation</font></b>
</td>
</tr>
</table>
VM-based RF-Less Environment:
* [How to setup your test env](./vm_based_simulator_env.md)
* [How to deal with OAI source files](./vm_based_simulator_sources.md)
* [The main script](./vm_based_simulator_main_scripts.md)
* [How to create one or several VM instances](./vm_based_simulator_create.md)
* [How to build an OAI variant](./vm_based_simulator_build.md)
* [How the build is checked](./vm_based_simulator_check_build.md)
* [How to test an OAI variant](./vm_based_simulator_test.md)
* [How to destroy all VM instances](./vm_based_simulator_destroy.md)
Currently missing documentation:
* How to generate a build report
* How to generate a test report
---

View File

@@ -1,261 +0,0 @@
<table style="border-collapse: collapse; border: none;">
<tr style="border-collapse: collapse; border: none;">
<td style="border-collapse: collapse; border: none;">
<a href="http://www.openairinterface.org/">
<img src="../../doc/images/oai_final_logo.png" alt="" border=3 height=50 width=150>
</img>
</a>
</td>
<td style="border-collapse: collapse; border: none; vertical-align: center;">
<b><font size = "5">OAI CI Virtual-Machine-based Test Environment: build an OAI variant</font></b>
</td>
</tr>
</table>
**Table of Contents**
[[_TOC_]]
# 1. Introduction #
```bash
$ cd /tmp/CI-raphael
$ ls *.zip
localZip.zip
$ ./ci-scripts/oai-ci-vm-tool build --help
OAI CI VM script
Original Author: Raphael Defosseux
Requirements:
-- uvtool uvtool-libvirt apt-cacher
-- xenial image already synced
Default:
-- eNB with USRP
Usage:
------
oai-ci-vm-tool build [OPTIONS]
Mandatory Options:
--------
--job-name #### OR -jn ####
Specify the name of the Jenkins job.
--build-id #### OR -id ####
Specify the build ID of the Jenkins job.
--workspace #### OR -ws ####
Specify the workspace.
Options:
--------
# OpenAirInterface Build Variants
--variant enb-usrp OR -v1 ( build and test )
--variant phy-sim OR -v3 ( build and test )
--variant cppcheck OR -v4 ( build and test )
--variant gnb-usrp OR -v5 ( build and test )
--variant nr-ue-usrp OR -v6 ( build and test )
--variant enb-ethernet OR -v7 ( build and test )
--variant ue-ethernet OR -v8 ( build and test )
# non-OSA Build Variants
--variant flexran-rtc OR -v10 ( build and test non-OSA )
# OpenAirInterface Test Variants
--variant l1-sim OR -v20 ( test )
--variant rf-sim OR -v21 ( test )
--variant l2-sim OR -v22 ( test )
Specify the variant to build.
--keep-vm-alive OR -k
Keep the VM alive after the build.
--daemon OR -D
Run as daemon
--help OR -h
Print this help message.
```
# 2. Detailed Description #
Source file concerned: `ci-scripts/buildOnVM.sh`
## 2.1. build_on_vm function ##
* First check if the ZIP file is available and if the apt-cacher proxy configuration file is present. If not, it will stop.
* Check if the VM instance is alive. If not, create it.
* Once the VM is alive, retrieve the IP address with VM_IP_ADDR=`uvt-kvm ip $VM_NAME`
* We copy the ZIP file to the VM : `scp localZip.zip ubuntu@$VM_IP_ADDR:/home/ubuntu`
* apt-cacher proxy file: `scp etc/apt/apt.conf.d/01proxy ubuntu@$VM_IP_ADDR:/home/ubuntu`
Then we open a SSH session on the VM : `ssh ubuntu@$VM_IP_ADDR`
* We copy the apt-cacher proxy file to its destination space: `sudo cp 01proxy /etc/apt/apt.conf.d/`
* We create an hush login file to eliminate the ssh opening session messages.
* We unzip the ZIP file into `/home/ubuntu/tmp/` folder
* and we work from there.
# 3. Typical Usage #
## 3.1. Build in the foreground, check the results and destroy the VM at the end ##
```bash
$ cd /tmp/CI-raphael
$ ls *.zip
localZip.zip
$ ./ci-scripts/oai-ci-vm-tool build --workspace /tmp/CI-raphael --job-name RAN-CI-develop --build-id 47 --variant enb-usrp
############################################################
OAI CI VM script
############################################################
VM_NAME = RAN-CI-develop-b47-enb-usrp
VM_CMD_FILE = RAN-CI-develop-b47-enb-usrp_cmds.txt
JENKINS_WKSP = /var/jenkins/workspace/RAN-CI-develop
ARCHIVES_LOC = /var/jenkins/workspace/RAN-CI-develop/archives/enb_usrp
BUILD_OPTIONS = --eNB -w USRP --mu
VM_MEMORY = 2048 MBytes
VM_CPU = 4
############################################################
Creating VM (RAN-CI-develop-b47-enb-usrp) on Ubuntu Cloud Image base
############################################################
Waiting for VM to be started
Warning: Permanently added '192.168.122.2' (ECDSA) to the list of known hosts.
RAN-CI-develop-b47-enb-usrp has for IP addr = 192.168.122.2
############################################################
Copying GIT repo into VM (RAN-CI-develop-b47-enb-usrp)
############################################################
Warning: Permanently added '192.168.122.2' (ECDSA) to the list of known hosts.
############################################################
Running install and build script on VM (RAN-CI-develop-b47-enb-usrp)
############################################################
Welcome to Ubuntu 16.04.6 LTS (GNU/Linux 4.4.0-145-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
Get cloud support with Ubuntu Advantage Cloud Guest:
http://www.ubuntu.com/business/services/cloud
0 packages can be updated.
0 updates are security updates.
New release '18.04.2 LTS' available.
Run 'do-release-upgrade' to upgrade to it.
sudo apt-get --yes --quiet install zip subversion libboost-dev
unzip -qq -DD ../localZip.zip
cd /home/ubuntu/tmp
source oaienv
cd cmake_targets
./build_oai -I --eNB -w USRP --mu
# Here wait for a few minutes 8 to 12 minutes #
############################################################
Creating a tmp folder to store results and artifacts
############################################################
############################################################
Destroying VM
############################################################
# Host 192.168.122.2 found: line 19
/home/eurecom/.ssh/known_hosts updated.
Original contents retained as /home/eurecom/.ssh/known_hosts.old
############################################################
Checking build status
############################################################
STATUS seems OK
```
If you are adding the `-k` or `--keep-vm-alive` option, the VM instance will not be destroyed and you explore what happenned.
## 3.2. Build in the background ##
This is how it is done in the CI master job pipeline.
```bash
$ cd /tmp/CI-raphael
$ ls *.zip
localZip.zip
$ ./ci-scripts/oai-ci-vm-tool build --workspace /tmp/CI-raphael --job-name RAN-CI-develop --build-id 47 --variant phy-sim --daemon
12:44:24 ############################################################
12:44:24 OAI CI VM script
12:44:24 ############################################################
12:44:24 VM_NAME = RAN-CI-develop-b47-phy-sim
12:44:24 VM_CMD_FILE = RAN-CI-develop-b47-phy-sim_cmds.txt
12:44:24 JENKINS_WKSP = /var/jenkins/workspace/RAN-CI-develop
12:44:24 ARCHIVES_LOC = /var/jenkins/workspace/RAN-CI-develop/archives/phy_sim
12:44:24 BUILD_OPTIONS = --phy_simulators
12:44:24 VM_MEMORY = 2048 MBytes
12:44:24 VM_CPU = 4
12:44:24 ############################################################
12:44:24 Creating VM (RAN-CI-develop-b47-phy-sim) on Ubuntu Cloud Image base
12:44:24 ############################################################
12:44:27 Waiting for VM to be started
12:46:34 Warning: Permanently added '192.168.122.220' (ECDSA) to the list of known hosts.
12:46:34 RAN-CI-develop-b47-phy-sim has for IP addr = 192.168.122.220
12:46:34 ############################################################
12:46:34 Copying GIT repo into VM (RAN-CI-develop-b47-phy-sim)
12:46:34 ############################################################
12:46:34 Warning: Permanently added '192.168.122.220' (ECDSA) to the list of known hosts.
12:46:34 ############################################################
12:46:34 Running install and build script on VM (RAN-CI-develop-b47-phy-sim)
12:46:34 ############################################################
12:46:34 Welcome to Ubuntu 16.04.6 LTS (GNU/Linux 4.4.0-145-generic x86_64)
12:46:34
12:46:34 * Documentation: https://help.ubuntu.com
12:46:34 * Management: https://landscape.canonical.com
12:46:34 * Support: https://ubuntu.com/advantage
12:46:34
12:46:34 Get cloud support with Ubuntu Advantage Cloud Guest:
12:46:34 http://www.ubuntu.com/business/services/cloud
12:46:34
12:46:34 0 packages can be updated.
12:46:34 0 updates are security updates.
12:46:34
12:46:34 New release '18.04.2 LTS' available.
12:46:34 Run 'do-release-upgrade' to upgrade to it.
12:46:34
12:46:34
12:46:34 sudo apt-get --yes --quiet install zip daemon subversion libboost-dev
12:46:46 unzip -qq -DD ../localZip.zip
12:46:48 source oaienv
12:46:48 sudo -E daemon --inherit --unsafe --name=build_daemon --chdir=/home/ubuntu/tmp/cmake_targets -o /home/ubuntu/tmp/cmake_targets/log/install-build.txt ./my-vm-build.sh
12:46:48 STATUS seems OK
```
So here is 2.5 minutes, a VM was created, source files copied and the build process is started in the background.
```bash
$ cd /tmp/raphael
$ ./ci-scripts/oai-ci-vm-tool wait --workspace /var/jenkins/workspace/RAN-CI-develop --variant phy-sim --job-name RAN-CI-develop --build-id 47 --keep-vm-alive
12:49:14 ############################################################
12:49:14 OAI CI VM script
12:49:14 ############################################################
12:49:14 VM_NAME = RAN-CI-develop-b47-phy-sim
12:49:14 VM_CMD_FILE = RAN-CI-develop-b47-phy-sim_cmds.txt
12:49:14 JENKINS_WKSP = /var/jenkins/workspace/RAN-CI-develop
12:49:14 ARCHIVES_LOC = /var/jenkins/workspace/RAN-CI-develop/archives/phy_sim
12:49:14 BUILD_OPTIONS = --phy_simulators
12:49:15 Waiting for VM to be started
12:49:15 Warning: Permanently added '192.168.122.220' (ECDSA) to the list of known hosts.
12:49:16 RAN-CI-develop-b47-phy-sim has for IP addr = 192.168.122.220
12:49:16 ############################################################
12:49:16 Waiting build process to end on VM (RAN-CI-develop-b47-phy-sim)
12:49:16 ############################################################
12:49:16 ps -aux | grep build
12:54:23 ############################################################
12:54:23 Creating a tmp folder to store results and artifacts
12:54:23 ############################################################
12:54:23 ############################################################
12:54:23 Checking build status
12:54:23 ############################################################
12:54:23 STATUS seems OK
```
Here the `--keep-vm-alive` option is used to keep the VM alive and performs some testing.
---
Next step: [how the build is checked](./vm_based_simulator_check_build.md)
You can also go back to the [CI dev main page](./ci_dev_home.md)

View File

@@ -1,44 +0,0 @@
<table style="border-collapse: collapse; border: none;">
<tr style="border-collapse: collapse; border: none;">
<td style="border-collapse: collapse; border: none;">
<a href="http://www.openairinterface.org/">
<img src="../../doc/images/oai_final_logo.png" alt="" border=3 height=50 width=150>
</img>
</a>
</td>
<td style="border-collapse: collapse; border: none; vertical-align: center;">
<b><font size = "5">OAI CI Virtual-Machine-based Test Environment: checking the build result</font></b>
</td>
</tr>
</table>
**Table of Contents**
[[_TOC_]]
# 1. Introduction #
Function is called:
- when building in foreground
- when waiting for the background build process is finished
# 2. Detailed Description #
Source file concerned: `ci-scripts/waitBuildOnVM.sh`
## 2.1. check_on_vm_build function ##
* Retrieve the build log files from the VM instance `ubuntu@$VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/*.txt`
* and copy them locally in the workspace at $ARCHIVES_LOC
* List all log files that match the pattern. Each should have
* the `Built target` pattern (the library/executable SHALL link)
* Evaluate the remaining space on VM disk
* The number of patterned log files SHALL match $NB_PATTERN_FILES defined in `ci-scripts/oai-ci-vm-tool` script for the variant
---
Next step: [how to test a function](./vm_based_simulator_test.md)
You can also go back to the [CI dev main page](./ci_dev_home.md)

View File

@@ -1,110 +0,0 @@
<table style="border-collapse: collapse; border: none;">
<tr style="border-collapse: collapse; border: none;">
<td style="border-collapse: collapse; border: none;">
<a href="http://www.openairinterface.org/">
<img src="../../doc/images/oai_final_logo.png" alt="" border=3 height=50 width=150>
</img>
</a>
</td>
<td style="border-collapse: collapse; border: none; vertical-align: center;">
<b><font size = "5">OAI CI Virtual-Machine-based Test Environment: create a VM instance</font></b>
</td>
</tr>
</table>
**Table of Contents**
[[_TOC_]]
# 1. Introduction #
```bash
$ cd /tmp/CI-raphael
$ ./ci-scripts/oai-ci-vm-tool create --help
OAI CI VM script
Original Author: Raphael Defosseux
Requirements:
-- uvtool uvtool-libvirt apt-cacher
-- xenial image already synced
Default:
-- eNB with USRP
Usage:
------
oai-ci-vm-tool create [OPTIONS]
Mandatory Options:
--------
--job-name #### OR -jn ####
Specify the name of the Jenkins job.
--build-id #### OR -id ####
Specify the build ID of the Jenkins job.
# OpenAirInterface Build Variants
--variant enb-usrp OR -v1 ( build and test )
--variant phy-sim OR -v3 ( build and test )
--variant cppcheck OR -v4 ( build and test )
--variant gnb-usrp OR -v5 ( build and test )
--variant nr-ue-usrp OR -v6 ( build and test )
--variant enb-ethernet OR -v7 ( build and test )
--variant ue-ethernet OR -v8 ( build and test )
# non-OSA Build Variants
--variant flexran-rtc OR -v10 ( build and test non-OSA )
# OpenAirInterface Test Variants
--variant l1-sim OR -v20 ( test )
--variant rf-sim OR -v21 ( test )
--variant l2-sim OR -v22 ( test )
Specify the variant to build.
--help OR -h
Print this help message.
```
# 2. Detailed Description #
Source file concerned: `ci-scripts/createVM.sh`
## 2.1. create_vm function ##
This is the function that is being called from the main oai-vm-tool script.
The main purpose is to start a VM instance:
```bash
uvt-kvm create $VM_NAME release=xenial --memory $VM_MEMORY --cpu $VM_CPU --disk $VM_DISK --unsafe-caching --template ci-scripts/template-host.xml
```
Variables are set in the main script based on the options.
`--unsafe-caching` option is used because our VM instances are throw-away's.
`--template ci-scripts/template-host.xml` is used to duplicate the CPU properties to the VM instance. **VERY IMPORTANT to build OAI**
## 2.2. Lock / Unlock functions ##
There are `acquire_vm_create_lock` and `release_vm_create_lock` functions.
Creating Virtual Machines instances in parallel **creates a lot of stress** on the host server HW. If you launch creations in parallel (Jenkins pipeline could do it) or you are several people working on the same host server, this mechanism atomizes the creation process and wait until the previous VM creation is finished.
# 3. Typical Usage #
```bash
$ cd /tmp/CI-raphael
$ ./ci-scripts/oai-ci-vm-tool create --job-name raphael --build-id 1 --variant phy-sim
# or a more **unique approach**
$ ./ci-scripts/oai-ci-vm-tool create -jn toto -id 1 -v2
```
The Jenkins pipeline uses the master job name as `job-name` option and the job-build ID.
Try to be unique if you are several developers working on the same host server.
Finally, typically I never use the `create` command. I use directly the build command that checks if VM is created and if not, will create it. See next step.
---
Next step: [how to build an OAI variant](./vm_based_simulator_build.md)
You can also go back to the [CI dev main page](./ci_dev_home.md)

View File

@@ -1,69 +0,0 @@
<table style="border-collapse: collapse; border: none;">
<tr style="border-collapse: collapse; border: none;">
<td style="border-collapse: collapse; border: none;">
<a href="http://www.openairinterface.org/">
<img src="../../doc/images/oai_final_logo.png" alt="" border=3 height=50 width=150>
</img>
</a>
</td>
<td style="border-collapse: collapse; border: none; vertical-align: center;">
<b><font size = "5">OAI CI Virtual-Machine-based Test Environment: Properly Destroy all VM instances</font></b>
</td>
</tr>
</table>
**Table of Contents**
[[_TOC_]]
# 1. Introduction #
```bash
$ cd /tmp/CI-raphael
$ ./ci-scripts/oai-ci-vm-tool destroy --help
OAI CI VM script
Original Author: Raphael Defosseux
Requirements:
-- uvtool uvtool-libvirt apt-cacher
Usage:
------
oai-ci-vm-tool destroy [OPTIONS]
Mandatory Options:
--------
--job-name #### OR -jn ####
Specify the name of the Jenkins job.
--build-id #### OR -id ####
Specify the build ID of the Jenkins job.
Options:
--------
--help OR -h
Print this help message.
```
# 2. Detailed Description #
Source file concerned: `ci-scripts/destroyAllRunningVM.sh`
## 2.1. destroy_vm function ##
This is the function that is being called from the main oai-vm-tool script.
The main purpose is to destroy all VM instances whose name matches a pattern.
It also cleans up the `.ssh/known_hosts` file.
# 3. Typical Usage #
```bash
$ cd /tmp/CI-raphael
$ ./ci-scripts/oai-ci-vm-tool destroy --job-name raphael --build-id 1
```
---
You can go back to the [CI dev main page](./ci_dev_home.md)

View File

@@ -1,119 +0,0 @@
<table style="border-collapse: collapse; border: none;">
<tr style="border-collapse: collapse; border: none;">
<td style="border-collapse: collapse; border: none;">
<a href="http://www.openairinterface.org/">
<img src="../../doc/images/oai_final_logo.png" alt="" border=3 height=50 width=150>
</img>
</a>
</td>
<td style="border-collapse: collapse; border: none; vertical-align: center;">
<b><font size = "5">OAI CI Virtual-Machine-based Simulator Test Environment</font></b>
</td>
</tr>
</table>
**Table of Contents**
[[_TOC_]]
# 1. Introduction #
This document explains how the master pipeline works and how any developer could contribute to add testing.
It is an extension to the wiki [page](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/ci/enb-master-job).
The purpose of this master pipeline is to:
* Validate that a Merge Request is mergeable
* Validate that a Merge Request is following coding guidelines
* Validate that a Merge Request is not breaking any typical build variant
* Validate that a Merge Request is not breaking any legacy simulator-based test
We will mainly focused on the 2 last items.
Last point, this documentation is valid for all CI-supported branches:
* `master`
* `develop`
But the feature set may not be aligned. **The principles still apply.**
# 2. Prerequisites #
Some details are available on this wiki [section](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/ci/enb-ci-architecture#22-pipeline-executor).
Currently we have a host server (`bellatrix`) with the current parameters:
* 40 x Intel(R) Xeon(R) CPU E5-2640 v4 @ 2.40GHz
* 64 Gbytes RAM
* Ubuntu 16.04.3 LTS (xenial)
For you to replicate this environment, you need a strong server:
* At least 16 cores
* Ubuntu 16 (xenial) or higher (such as bionic, not tested)
Also we are using a Virtual Machine (VM for the rest of document) based strategy for the moment.
So you need to install 2 tools:
* uvt-kvm
* apt-cacher
We are planning to also add:
* A Red Hat Linux Entreprise 7.6 host environment
* A Container-based strategy (such as Docket and Kubernetes)
## 2.1. uvtool installation ##
```bash
$ sudo apt-get install uvtool
# if you don't have already, create an ssh key
$ ssh-keygen -b 2048
# retrieve an image
$ sudo uvt-simplestreams-libvirt sync arch=amd64 release=xenial
# we might soon switch to an Ubuntu 18.04 version
$ sudo uvt-simplestreams-libvirt sync arch=amd64 release=bionic
$ uvt-simplestreams-libvirt query
release=bionic arch=amd64 label=release (20190402)
release=xenial arch=amd64 label=release (20190406)
```
On our server, I don't update (sync) that often (every 2-4 months).
For more details:
* uvtool syntax is [here](http://manpages.ubuntu.com/manpages/trusty/man1/uvt-kvm.1.html)
* more readable tutorial is [here](https://help.ubuntu.com/lts/serverguide/cloud-images-and-uvtool.html)
## 2.2. apt-cacher-server installation ##
I recommend to follow to the letter this [tutorial](https://help.ubuntu.com/community/Apt-Cacher-Server).
The reason: we are creating/using/destroying a lot of VM instances and we are always installing the same packages.
This service allows to cache on the host and, doing so, **decreases the pressure on your internet bandwith usage**.
It also optimizes time at build stage.
```bash
$ sudo apt-get install apt-cacher apache2
$ sudo vi /etc/default/apt-cache
$ sudo service apache2 restart
# Server configuration
$ sudo vi /etc/apt-cacher/apt-cacher.conf
--> allowed_hosts = *
--> fix the installer_files_regexp
$ sudo vi /etc/apt/apt.conf.d/01proxy
--> add `Acquire::http::Proxy "http://<IP address or hostname of the apt-cacher server>:3142";`
$ sudo service apt-cacher restart
```
This last file (/etc/apt/apt.conf.d/01proxy) is very important since it is tested in any CI script.
---
We can now switch to the next step: [how to deal with oai sources](./vm_based_simulator_sources.md)
You can also go back to the [CI dev main page](./ci_dev_home.md)

View File

@@ -1,188 +0,0 @@
<table style="border-collapse: collapse; border: none;">
<tr style="border-collapse: collapse; border: none;">
<td style="border-collapse: collapse; border: none;">
<a href="http://www.openairinterface.org/">
<img src="../../doc/images/oai_final_logo.png" alt="" border=3 height=50 width=150>
</img>
</a>
</td>
<td style="border-collapse: collapse; border: none; vertical-align: center;">
<b><font size = "5">OAI CI Virtual-Machine-based Test Environment: the Main Script</font></b>
</td>
</tr>
</table>
**Table of Contents**
[[_TOC_]]
# 1. Introduction #
The file name is `./ci-scripts/oai-ci-vm-tool` from the workspace root.
```bash
$ cd /tmp/CI-raphael
$ ./ci-scripts/oai-ci-vm-tool --help
OAI CI VM script
Original Author: Raphael Defosseux
Requirements:
-- uvtool uvtool-libvirt apt-cacher
-- xenial image already synced
Usage:
------
oai-ci-vm-tool (-h|--help) {create,destroy,build,wait,test,report-build,report-test} ...
```
This is a **BASH** script.
# 2. Sub BASH scripts #
The main script is including a bunch of sub BASH scripts.
* ci-scripts/createVM.sh
* ci-scripts/buildOnVM.sh
* ci-scripts/waitBuildOnVM.sh
* ci-scripts/destroyAllRunningVM.sh
* ci-scripts/runTestOnVM.sh
* ci-scripts/reportBuildLocally.sh
* ci-scripts/reportTestLocally.sh
**NOTE: ci-scripts/runTestOnVM.sh is getting big and will certainly be split to facilitate maintenance. Start functions will be also factorized.**
# 3. Main script features #
The main purpose of the main script is decipher the options and launch the requested function.
It is also **testing if uvtool and apt-cacher are installed.**
It finally provides parameters to the requested functions. Parameter definition is centralized there.
For example:
for VM instance creation:
* the instance name: VM_NAME
* the RAM and number of CPUs: VM_MEMORY, VM_CPU
for OAI variant build:
* build options: BUILD_OPTIONS
* build log file to parse: LOG_PATTERN
* the number of log files to parse: NB_PATTERN_FILES
You can get the list of variant specific variables specifying the variant argument when asking for help:
``` bash
./ci-scripts/oai-ci-vm-tool help variant
--variant flexran-rtc OR -v10 ( build and test non-OSA )
VM_NAME=ci-flexran-rtc ARCHIVES_LOC=flexran
VM_MEMORY=2048 VM_CPU=4
NB_PATTERN_FILES=1 BUILD_OPTIONS="cmake . && make -j2"
LOG_PATTERN=.txt
--variant enb-usrp OR -v1 ( build and test )
VM_NAME=ci-enb-usrp ARCHIVES_LOC=enb_usrp
VM_MEMORY=2048 VM_CPU=4
NB_PATTERN_FILES=9 BUILD_OPTIONS="--eNB -w USRP --mu"
LOG_PATTERN=.txt
--variant l1-sim OR -v20 ( test )
VM_NAME=ci-l1-sim ARCHIVES_LOC=l1_sim
VM_MEMORY=2048 VM_CPU=4
NB_PATTERN_FILES=9 BUILD_OPTIONS=""
LOG_PATTERN=.txt
--variant rf-sim OR -v21 ( test )
VM_NAME=ci-rf-sim ARCHIVES_LOC=rf_sim
VM_MEMORY=2048 VM_CPU=4
NB_PATTERN_FILES=9 BUILD_OPTIONS=""
LOG_PATTERN=.txt
--variant l2-sim OR -v22 ( test )
VM_NAME=ci-l2-sim ARCHIVES_LOC=l2_sim
VM_MEMORY=2048 VM_CPU=4
NB_PATTERN_FILES=9 BUILD_OPTIONS=""
LOG_PATTERN=.txt
--variant phy-sim OR -v3 ( build and test )
VM_NAME=ci-phy-sim ARCHIVES_LOC=phy_sim
VM_MEMORY=2048 VM_CPU=4
NB_PATTERN_FILES=3 BUILD_OPTIONS="--phy_simulators"
LOG_PATTERN=.txt
--variant cppcheck OR -v4 ( build and test )
VM_NAME=ci-cppcheck ARCHIVES_LOC=cppcheck
VM_MEMORY=4096 VM_CPU=4
NB_PATTERN_FILES=1 BUILD_OPTIONS="--enable=warning --force --xml --xml-version=2 --suppressions-list=ci-scripts/cppcheck_suppressions.list -I common/utils -j4"
LOG_PATTERN=cppcheck.xml
--variant enb-ethernet OR -v7 ( build and test )
VM_NAME=ci-enb-ethernet ARCHIVES_LOC=enb_eth
VM_MEMORY=4096 VM_CPU=4
NB_PATTERN_FILES=8 BUILD_OPTIONS="--eNB"
LOG_PATTERN=.txt
--variant ue-ethernet OR -v8 ( build and test )
VM_NAME=ci-ue-ethernet ARCHIVES_LOC=ue_eth
VM_MEMORY=4096 VM_CPU=4
NB_PATTERN_FILES=12 BUILD_OPTIONS="--UE"
LOG_PATTERN=.txt
```
To define a new variant you just need to define a function which name conforms to `function variant__v<n>__<variant_name>` where n and variant_name will respectively define the short and long options for your variant. The function only needs to define the variant dependent variables. For many variables, default values are set in the `check_set_variant` function. When a variant doesn't define the BUILD_OPTIONS variable it cannot be used for the `build` `wait` and `create` commands.
The main scripts also allows the definition of non variant-dependant variable via the `--setvar_<variable name> <variable value>` options.
You can get the list of these variables by using `help setvar`:
```BASH
./ci-scripts/oai-ci-vm-tool help setvar
--setvar_<varname> <value> where varname is one of:
VM_OSREL : OS release to use in virtual machines
RUN_EXPERIMENTAL : Enforce execution of variants with EXPERIMENTAL variable set to "true"
```
To add a new non-variant dependant variable you need:
* Add an item to the `AUTHORIZED_VAR` array
* In the `setvar_usage`function, add your help string in the HELP_VAR["<your variable name>"] variable.
* Write the bash code for your variable.
Example of non variant dependent usage:
``` bash
./ci-scripts/oai-ci-vm-tool test -v21 -ws /usr/local/oai/enhance_CI_extEPC/openairinterface5g -id 1 -jn testci
Currently testci-b1-rf-sim Testing is not implemented / enabled
Comment out these lines in ./ci-scripts/oai-ci-vm-tool if you want to run it
or use option --setvar_RUN_EXPERIMENTAL=true to test it
./ci-scripts/oai-ci-vm-tool test -v21 -ws /usr/local/oai/enhance_CI_extEPC/openairinterface5g -id 1 -jn testci --setvar_RUN_EXPERIMENTAL true
Setting RUN_EXPERIMENTAL to true...
############################################################
OAI CI VM script
############################################################
ENB_VM_NAME = testci-b1-enb-ethernet
ENB_VM_CMD_FILE = testci-b1-enb-ethernet_cmds.txt
UE_VM_NAME = testci-b1-ue-ethernet
UE_VM_CMD_FILE = testci-b1-ue-ethernet_cmds.txt
JENKINS_WKSP = /usr/local/oai/enhance_CI_extEPC/openairinterface5g
ARCHIVES_LOC = /usr/local/oai/enhance_CI_extEPC/openairinterface5g/archives/rf_sim/test
############################################################
Waiting for ENB VM to be started
...........................
```
In the same way, you can set the variable `VM_OSREL` to run the test in virtual machines of the specified OS release:
``` bash
./ci-scripts/oai-ci-vm-tool test -v21 -ws /usr/local/oai/enhance_CI_extEPC/openairinterface5g -id 1 -jn testci --setvar_VM_OSREL bionic
```
---
Next step: [how to create one or several VM instances](./vm_based_simulator_create.md)
You can also go back to the [CI dev main page](./ci_dev_home.md)

View File

@@ -1,83 +0,0 @@
<table style="border-collapse: collapse; border: none;">
<tr style="border-collapse: collapse; border: none;">
<td style="border-collapse: collapse; border: none;">
<a href="http://www.openairinterface.org/">
<img src="../../doc/images/oai_final_logo.png" alt="" border=3 height=50 width=150>
</img>
</a>
</td>
<td style="border-collapse: collapse; border: none; vertical-align: center;">
<b><font size = "5">OAI CI Virtual-Machine-based Simulator OAI source management</font></b>
</td>
</tr>
</table>
**Table of Contents**
[[_TOC_]]
# 1. Introduction #
The idea of this section is to optimize/uniform source management for several VM instances.
If we were cloning the same repository in each VM we are creating, we would put so much pressure on the central GitLab repository.
The solution:
* clone/fetch on a given clean workspace and tar/zip only the source files without any artifacts.
* we then copy the tar/zip file to each VM instance
* and within each VM instance, unzip
# 2. Centralized Workspace #
You can create a brand new workspace by cloning:
```bash
$ mkdir /tmp/CI-raphael
$ cd /tmp/CI-raphael
$ git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git .
$ git checkout develop
```
You can also use your current cloned workspace and any `develop`-based branch.
```bash
$ cd /home/raphael/openairinterface5g
$ git fetch
$ git checkout develop-improved-documentation
# CAUTION: the following command will remove any file that has not already been added to GIT
$ sudo git clean -x -d -ff
$ git status
On branch develop-improved-documentation
Your branch is up-to-date with 'origin/develop-improved-documentation'.
nothing to commit, working directory clean
```
You can also have modified files.
**The main point is to have NO ARTIFACTS from a previous build in your workspace.**
Last point, the workspace folder name is not necesseraly `openairinterface5g`. But all the following commands will be run for the root of the workspace.
For clarity, I will always use `/tmp/CI-raphael` as $WORKSPACE.
# 3. Create the ZIP file #
```bash
# go to root of workspace
$ cd /tmp/CI-raphael
$ zip -r -qq localZip.zip .
```
The **Jenkins Pipeline** performs automatically these operations.
In addition, in case of a merge request, it tries to merge with the target branch and might create a dummy local commit.
See [section](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/ci/enb-master-job#32-verify-guidelines-stage)
---
Next step: [the main scripts](./vm_based_simulator_main_scripts.md)
You can also go back to the [CI dev main page](./ci_dev_home.md)

View File

@@ -1,197 +0,0 @@
<table style="border-collapse: collapse; border: none;">
<tr style="border-collapse: collapse; border: none;">
<td style="border-collapse: collapse; border: none;">
<a href="http://www.openairinterface.org/">
<img src="../../doc/images/oai_final_logo.png" alt="" border=3 height=50 width=150>
</img>
</a>
</td>
<td style="border-collapse: collapse; border: none; vertical-align: center;">
<b><font size = "5">OAI CI Virtual-Machine-based Test Environment: Testing an OAI variant</font></b>
</td>
</tr>
</table>
**Table of Contents**
[[_TOC_]]
# 1. Introduction #
Currently 1 build variant can be directly tested:
* Physical Simulators
In addition, 2 build variants are used:
* OAI eNB with ETHERNET transport
* OAI UE with ETHERNET transport
for the following scenarios:
* L1 simulator w/ a channel simulator (NOT IMPLEMENTED)
* RF simulator : (IMPLEMENTED but not working as of 2019.w15)
* L2 nFAPI simulator
Tests are run sequentially in the Jenkins pipeline because:
* We want to mutualize the VM creation for an EPC
* We have seen performance issues when running in parallel.
```bash
./ci-scripts/oai-ci-vm-tool test --help
OAI CI VM script
Original Author: Raphael Defosseux
Requirements:
-- uvtool uvtool-libvirt apt-cacher
-- xenial image already synced
Default:
-- eNB with USRP
Usage:
------
oai-ci-vm-tool test [OPTIONS]
Options:
--------
--job-name #### OR -jn ####
Specify the name of the Jenkins job.
--build-id #### OR -id ####
Specify the build ID of the Jenkins job.
--workspace #### OR -ws ####
Specify the workspace.
# OpenAirInterface Build Variants
--variant enb-usrp OR -v1 ( build and test )
--variant phy-sim OR -v3 ( build and test )
--variant cppcheck OR -v4 ( build and test )
--variant gnb-usrp OR -v5 ( build and test )
--variant nr-ue-usrp OR -v6 ( build and test )
--variant enb-ethernet OR -v7 ( build and test )
--variant ue-ethernet OR -v8 ( build and test )
# non-OSA Build Variants
--variant flexran-rtc OR -v10 ( build and test non-OSA )
# OpenAirInterface Test Variants
--variant l1-sim OR -v20 ( test )
--variant rf-sim OR -v21 ( test )
--variant l2-sim OR -v22 ( test )
Specify the variant to build.
--keep-vm-alive OR -k
Keep the VM alive after the build.
--help OR -h
Print this help message.
```
# 2. Detailed Description #
Source file concerned: `ci-scripts/run_test_on_vm.sh`
**TBD when file is re-structured.**
# 3. Typical Usage #
## 3.1. Testing the physical simulators ##
```bash
$ ./ci-scripts/oai-ci-vm-tool test --workspace /var/jenkins/workspace/RAN-CI-develop --variant phy-sim --job-name RAN-CI-develop --build-id 47
12:54:29 ############################################################
12:54:29 OAI CI VM script
12:54:29 ############################################################
12:54:29 VM_NAME = RAN-CI-develop-b47-phy-sim
12:54:29 VM_CMD_FILE = RAN-CI-develop-b47-phy-sim_cmds.txt
12:54:29 JENKINS_WKSP = /var/jenkins/workspace/RAN-CI-develop
12:54:29 ARCHIVES_LOC = /var/jenkins/workspace/RAN-CI-develop/archives/phy_sim/test
12:54:29 ############################################################
12:54:29 Waiting for VM to be started
12:54:29 ############################################################
12:54:29 Warning: Permanently added '192.168.122.220' (ECDSA) to the list of known hosts.
12:54:30 RAN-CI-develop-b47-phy-sim has for IP addr = 192.168.122.220
...
13:04:48 Test Results are written to /home/ubuntu/tmp/cmake_targets/autotests/log/results_autotests.xml
13:05:00 ############################################################
13:05:00 Creating a tmp folder to store results and artifacts
13:05:00 ############################################################
13:05:00 /var/jenkins/workspace/RAN-CI-develop/archives/phy_sim/test /var/jenkins/workspace/RAN-CI-develop
13:05:04 /var/jenkins/workspace/RAN-CI-develop
13:05:04 ############################################################
13:05:04 Destroying VM
13:05:04 ############################################################
13:05:06 # Host 192.168.122.220 found: line 21
13:05:06 /home/eurecom/.ssh/known_hosts updated.
13:05:06 Original contents retained as /home/eurecom/.ssh/known_hosts.old
13:05:06 ############################################################
13:05:06 Checking run status
13:05:06 ############################################################
13:05:06 NB_FOUND_FILES = 1
13:05:06 NB_RUNS = 20
13:05:06 NB_FAILURES = 0
13:05:06 STATUS seems OK
```
Note that the VM instance is destroyed. You do that when you are sure your test is passing.
## 3.2. Test the RF simulator ##
```bash
./ci-scripts/oai-ci-vm-tool test --workspace /var/jenkins/workspace/RAN-CI-develop --variant rf-sim --job-name RAN-CI-develop --build-id 48 --keep-vm-alive
15:24:45 Currently RF-Simulator Testing is not implemented / enabled
15:24:45 Comment out these lines in ./ci-scripts/oai-ci-vm-tool if you want to run it
15:24:45 STATUS seems OK
```
## 3.3. Testing the L2-nFAPI simulator
```bash
./ci-scripts/oai-ci-vm-tool test --workspace /var/jenkins/workspace/RAN-CI-develop --variant l2-sim --job-name RAN-CI-develop --build-id 48
15:24:47 ############################################################
15:24:47 OAI CI VM script
15:24:47 ############################################################
15:24:47 ENB_VM_NAME = RAN-CI-develop-b48-enb-ethernet
15:24:47 ENB_VM_CMD_FILE = RAN-CI-develop-b48-enb-ethernet_cmds.txt
15:24:47 UE_VM_NAME = RAN-CI-develop-b48-ue-ethernet
15:24:47 UE_VM_CMD_FILE = RAN-CI-develop-b48-ue-ethernet_cmds.txt
15:24:47 JENKINS_WKSP = /var/jenkins/workspace/RAN-CI-develop
15:24:47 ARCHIVES_LOC = /var/jenkins/workspace/RAN-CI-develop/archives/l2_sim/test
15:24:47 ############################################################
15:24:47 Waiting for ENB VM to be started
15:24:47 ############################################################
15:24:47 Warning: Permanently added '192.168.122.110' (ECDSA) to the list of known hosts.
15:24:48 RAN-CI-develop-b48-enb-ethernet has for IP addr = 192.168.122.110
15:24:48 ############################################################
15:24:48 Waiting for UE VM to be started
15:24:48 ############################################################
15:24:49 Warning: Permanently added '192.168.122.90' (ECDSA) to the list of known hosts.
15:24:50 RAN-CI-develop-b48-ue-ethernet has for IP addr = 192.168.122.90
15:24:50 ############################################################
15:24:50 Test EPC on VM (RAN-CI-develop-b48-epc) will be using ltebox
15:24:50 ############################################################
15:24:50 EPC_VM_CMD_FILE = RAN-CI-develop-b48-epc_cmds.txt
15:24:50 Waiting for VM to be started
15:24:50 Warning: Permanently added '192.168.122.156' (ECDSA) to the list of known hosts.
15:24:51 RAN-CI-develop-b48-epc has for IP addr = 192.168.122.156
...
15:42:44 ############################################################
15:42:44 Destroying VMs
15:42:44 ############################################################
15:42:46 # Host 192.168.122.110 found: line 18
15:42:46 /home/eurecom/.ssh/known_hosts updated.
15:42:46 Original contents retained as /home/eurecom/.ssh/known_hosts.old
15:42:47 # Host 192.168.122.90 found: line 18
15:42:47 /home/eurecom/.ssh/known_hosts updated.
15:42:47 Original contents retained as /home/eurecom/.ssh/known_hosts.old
15:42:47 ############################################################
15:42:47 Checking run status
15:42:47 ############################################################
15:42:47 STATUS failed?
```
---
Final step: [how to properly destroy all VM instances](./vm_based_simulator_destroy.md)
You can also go back to the [CI dev main page](./ci_dev_home.md)

View File

@@ -287,6 +287,8 @@ def GetParametersFromXML(action):
#CiTestObj.air_interface = 'ocp-enb'
logging.error('OCP UE -- NOT SUPPORTED')
CiTestObj.cmd_prefix = test.findtext('cmd_prefix') or ""
elif action == 'Terminate_OAI_UE':
UE_instance=test.findtext('UE_instance')
if (UE_instance is None):

View File

@@ -1,889 +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
# */
function top_usage {
echo "OAI CI VM script"
echo " Original Author: Raphael Defosseux"
echo " Requirements:"
echo " -- uvtool uvtool-libvirt apt-cacher"
echo " -- $VM_OSREL image already synced"
echo ""
echo "Usage:"
echo "------"
echo " oai-ci-vm-tool (-h|--help) { `for i in "${COMMANDS_NAME[@]}"; do echo -n $i,;done` ..." }
echo ""
}
function variant_usage {
for (( i=0 ; i<${#VARIANTS_LONG[@]} ; i++ ))
do
unset BUILD_OPTIONS
unset VARIANT_INFO
check_set_variant "${VARIANTS_SHORT[$i]}"
printf " --variant %-15s OR -%-3s" "${VARIANTS_LONG[$i]}" "${VARIANTS_SHORT[$i]}"
if [ "$BUILD_OPTIONS" = "" ]
then
echo -n " ( test "
else
echo -n " ( build and test "
fi
echo "$VARIANT_INFO )"
if [ "$1" = "full" ]
then
printf " VM_NAME=%-15s ARCHIVES_LOC=%-15s\n" "$VM_NAME" "$ARCHIVES_LOC"
printf " VM_MEMORY=%-15s VM_CPU=%-15s VM_DISK=%-15s\n" "$VM_MEMORY" "$VM_CPU" "$VM_DISK"
printf " NB_PATTERN_FILES=%-15s BUILD_OPTIONS=%-15s\n" "$NB_PATTERN_FILES" "\"$BUILD_OPTIONS\""
printf " LOG_PATTERN=%-15s EXPERIMENTAL=%-15s\n\n\n" "$LOG_PATTERN" "$EXPERIMENTAL"
fi
done
}
function command_options_usage {
local -A HELP_MSG
HELP_MSG["jn"]=" Specify the name of the Jenkins job."
HELP_MSG["id"]=" Specify the build ID of the Jenkins job."
HELP_MSG["ws"]=" Specify the workspace"
HELP_MSG["var"]=" Specify the variant to build."
HELP_MSG["k"]=" Keep the VM alive after the build."
HELP_MSG["D"]=" Run as daemon"
HELP_MSG["gu"]=" Specify the URL of the GIT Repository."
HELP_MSG["pu"]=" trigger a push action from the Jenkins job to the specified url, \"--trigger pu\" can also be used"
HELP_MSG["mr"]=" trigger a merge request action from the Jenkins job, \"--trigger mr\" can also be used"
HELP_MSG["sb"]=" Specify the source branch of the merge request."
HELP_MSG["sc"]=" Specify the source commit ID (SHA-1) of the merge request."
HELP_MSG["tb"]=" Specify the target branch of the merge request (usually develop)."
HELP_MSG["tc"]=" Specify the target commit ID (SHA-1) of the merge request."
HELP_MSG["br"]=" Specify the branch of the push event."
HELP_MSG["co"]=" Specify the commit ID (SHA-1) of the push event."
HELP_MSG["epc"]=" (two arguments) Specify the ip addresses of an external EPC, on respectively the core network and the UEs network"
HELP_MSG["sim"]=" Specify the path to the sim file, used to emulate the oai UE sim card "
for (( m=0 ; m<2 ; m++ ))
do
if [[ $m -eq 0 || ( $m > 0 && ${MANDATORY_OPTMASK[$m]} > 0 ) ]]
then
echo "Mandatory Options ($((m+1))):"
echo "---------------------"
for (( i=0 ; i<${#SHORT_OPTIONS[@]} ; i++ ))
do
if [ $(( MANDATORY_OPTMASK[$m] & $(( 2**$i )) )) -ne 0 ]
then
if [ "${LONG_OPTIONS[$i]}" != "" ]
then
local ARGPATTERN
if [[ !("${HELP_MSG[${SHORT_OPTIONS[$i]}]}" =~ "Specify") ]]
then
ARGPATTERN=""
elif [[ "${HELP_MSG[${SHORT_OPTIONS[$i]}]}" =~ "(two arguments)" ]]
then
ARGPATTERN="#### ####"
else
ARGPATTERN="####"
fi
printf " %s %s OR " "--${LONG_OPTIONS[$i]}" "$ARGPATTERN"
fi
printf "%s %s \n" "-${SHORT_OPTIONS[$i]}" "$ARGPATTERN"
printf " %s\n\n" "${HELP_MSG[${SHORT_OPTIONS[$i]}]}"
fi
done
fi
done
echo "Options:"
echo "--------"
for (( i=0 ; i<${#SHORT_OPTIONS[@]} ; i++ ))
do
if [ $(( ALLOWED_OPTMASK & $(( 2**$i )) )) -ne 0 ]
then
if [ "${LONG_OPTIONS[$i]}" != "" ]
then
printf " %s #### OR " "--${LONG_OPTIONS[$i]}"
fi
printf "%s #### \n" "-${SHORT_OPTIONS[$i]}"
printf " %s\n\n" "${HELP_MSG[${SHORT_OPTIONS[$i]}]}"
fi
done
for (( i=0 ; i<${#SHORT_OPTIONS[@]} ; i++ ))
do
if [ $(( ALLOWED_OPTMASK & $(( 2**$i )) )) -ne 0 ]
then
if [ "$(type -t ${LONG_OPTIONS[$i]}_usage)" = 'function' ]
then
${LONG_OPTIONS[$i]}_usage
fi
fi
done
echo " --help OR -h"
echo " Print this help message."
echo ""
}
# function to set specific behavior depending on the TESTPLATFORM_OWNER variable
# which may be set by a jenkins server for exemple
function platform_set {
if [ "$TESTPLATFORM_OWNER" != "" ]
then
echo "Running on $TESTPLATFORM_OWNER platform"
if [ -x "/usr/local/bin/oai_${TESTPLATFORM_OWNER}_setenv.sh" ]
then
. /usr/local/bin/oai_${TESTPLATFORM_OWNER}_setenv.sh
fi
fi
}
function setvar_usage {
declare -A HELP_VAR
HELP_VAR["VM_OSREL"]="OS release to use in virtual machines"
HELP_VAR["RUN_EXPERIMENTAL"]="Enforce execution of variants with EXPERIMENTAL variable set to \"true\""
HELP_VAR["OPTIONAL_APTCACHER"]="build and Run tests will fail if apt-cacher not installed and this variable not set to \"true\""
HELP_VAR["TESTPLATFORM_OWNER"]="Allow pipeline customization via execution of an externel scripts residing on the jenkins server"
echo "--setvar_<varname> <value> where varname is one of:"
for i in ${AUTHORIZED_VAR[@]}; do printf "%20s : %s\n" "$i" "${HELP_VAR[$i]}" ;done
}
# functions variant__v<n>__<variant name> are used to define build or test variants
# The only thing to do to define a new variant is to add a function which name
# match this template. Note that "_" character in function <varriant name> part
# will be replaced by "-" character in build_variant_arrays function, this is
# for compatibility reasons
function variant__v1__enb_usrp {
NB_PATTERN_FILES=7
BUILD_OPTIONS="--eNB -w USRP --mu"
VM_MEMORY=3072
}
function variant__v2__basic_sim {
NB_PATTERN_FILES=11
BUILD_OPTIONS="--eNB --UE --noavx512"
VM_MEMORY=8192
RUN_OPTIONS="complex"
}
function variant__v3__phy_sim {
NB_PATTERN_FILES=11
BUILD_OPTIONS="--phy_simulators"
VM_MEMORY=8192
VM_DISK=20
RUN_OPTIONS="./run_exec_autotests.bash -g \"01510* 015111 015112\" -q -np -b"
}
function variant__v4__cppcheck {
VM_MEMORY=4096
LOG_PATTERN=cppcheck.xml
NB_PATTERN_FILES=1
BUILD_OPTIONS="--enable=warning --force --xml --xml-version=2 -i openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c --suppressions-list=ci-scripts/cppcheck_suppressions.list -I common/utils -I openair3/NAS/COMMON/UTIL -j4"
}
function variant__v5__gnb_usrp {
VM_MEMORY=10240
VM_CPU=8
NB_PATTERN_FILES=6
BUILD_OPTIONS="--gNB -w USRP --noavx512"
}
function variant__v6__nr_ue_usrp {
VM_MEMORY=4096
VM_CPU=4
NB_PATTERN_FILES=6
BUILD_OPTIONS="--nrUE -w USRP --noavx512"
}
function variant__v7__enb_ethernet {
VM_MEMORY=4096
ARCHIVES_LOC=enb_eth
NB_PATTERN_FILES=6
BUILD_OPTIONS="--eNB -w USRP --noavx512"
}
function variant__v8__ue_ethernet {
VM_MEMORY=4096
ARCHIVES_LOC=ue_eth
NB_PATTERN_FILES=10
BUILD_OPTIONS="--UE -w USRP --noavx512"
}
function variant__v10__flexran_rtc {
ARCHIVES_LOC=flexran
NB_PATTERN_FILES=1
BUILD_OPTIONS="cmake .. && make -j2"
VARIANT_INFO="non-OSA"
}
function variant__v20__l1_sim {
ARCHIVES_LOC=l1_sim
RUN_OPTIONS="complex"
EXPERIMENTAL="true"
}
function variant__v21__rf_sim {
ARCHIVES_LOC=rf_sim
RUN_OPTIONS="complex"
}
function variant__v22__l2_sim {
RUN_OPTIONS="complex"
}
function variant__v23__rf5g_sim {
ARCHIVES_LOC=rf5g_sim
RUN_OPTIONS="complex"
}
# Following function lists all variant__v<n>__<variant name> functions
# and set the VARIANTS_SHORT and VARIANTS_LONG arrays from
# the function names
function build_variant_arrays {
VARIANTS=`declare -F`
VARIANTS=${VARIANTS//"declare -f "}
for i in $VARIANTS
do
if [ `expr match "$i" 'variant__v'` -eq 10 ]
then
IDX1=`expr match "$i" 'variant__v[0-9]\+__'`
VARIANTS_SHORT+=(${i:9:$((IDX1-11))})
LONGNAME=${i:$IDX1}
VARIANTS_LONG+=(${LONGNAME//"_"/"-"})
fi
done
}
# check that the passed argument is a valid variant, set
# default values for variant related variables and then execute
# the corresponding variant__v<n>__<variant name> function
function check_set_variant {
for (( i=0 ; i<${#VARIANTS_SHORT[@]} ; i++ ))
do
if [ "$1" = "${VARIANTS_SHORT[$i]}" ] || [ "$1" = "${VARIANTS_LONG[$i]}" ]
then
VM_NAME=ci-${VARIANTS_LONG[$i]}
LOG_PATTERN=.txt
ARCHIVES_LOC=${VARIANTS_LONG[$i]//"-"/"_"}
VM_MEMORY=2048
VM_CPU=4
VM_DISK=10
EXPERIMENTAL=""
NBARGS=$[$NBARGS+$VARIANT_OPTID]
variant__${VARIANTS_SHORT[$i]}__${VARIANTS_LONG[$i]//"-"/"_"}
return 0
fi
done
echo "$1" is not a valid variant
variant_usage
exit 1
}
function check_command_options {
GIVEN_OPTIONS=$1
declare -a MANDATORY_OPTIONS=("${!2}")
if [ ${MANDATORY_OPTIONS[1]} -eq 0 ]
then
MANDATORY_OPTIONS[1]=${MANDATORY_OPTIONS[0]}
fi
OPTIONAL_OPTIONS=$3
if [ $(($GIVEN_OPTIONS & ${MANDATORY_OPTIONS[0]} )) -ne ${MANDATORY_OPTIONS[0]} ] && [ $(($GIVEN_OPTIONS & ${MANDATORY_OPTIONS[1]} )) -ne ${MANDATORY_OPTIONS[1]} ]
then
echo "Syntax Error: missing option(s) for $4 command"
${4//-/_}_usage
exit 1
fi
if [ $(( $(($GIVEN_OPTIONS ^ ${MANDATORY_OPTIONS[0]})) | $OPTIONAL_OPTIONS )) -ne $(( $OPTIONAL_OPTIONS )) ] && [ $(( $(($GIVEN_OPTIONS ^ ${MANDATORY_OPTIONS[1]})) | $OPTIONAL_OPTIONS )) -ne $(( $OPTIONAL_OPTIONS )) ]
then
echo "Syntax Error: unknown option(s) for $4 command"
${4//-/_}_usage
exit 1
fi
}
function check_ipv4addr {
local ipaddr=$1
local stat=1
if [[ $ipaddr =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3} ]]
then
OIFS=$IFS
IFS='.'
ipaddr=($ipaddr)
IFS=$OIFS
[[ ${ipaddr[0]} -le 255 && ${ipaddr[1]} -le 255 \
&& ${ipaddr[2]} -le 255 && ${ipaddr[3]} -le 255 ]]
stat=$?
fi
if [ $stat -ne 0 ]
then
echo $ipaddr " is not a valid ip V4 address"
exit 1
fi
}
function check_setvar {
for i in ${AUTHORIZED_VAR[@]}
do
if [ "$1" = "$i" ]
then
echo "Setting $1 to $2..."
export "$1"="$2"
return 0
fi
done
echo " $1 is not a variable you can set"
setvar_usage
exit 1
}
platform_set
MY_DIR=$(dirname $(readlink -f $0))
. $MY_DIR/createVM.sh
. $MY_DIR/buildOnVM.sh
. $MY_DIR/waitBuildOnVM.sh
. $MY_DIR/destroyAllRunningVM.sh
. $MY_DIR/runTestOnVM.sh
. $MY_DIR/reportBuildLocally.sh
. $MY_DIR/reportTestLocally.sh
if [ $# -lt 1 ]
then
echo "Syntax Error: too few arguments"
echo ""
top_usage
exit 1
fi
VM_TEMPLATE=ci-
# look for ASN1 release in cmake directives
# It will be the release used when building
ASN1VEROPT=( `grep "set (RRC_ASN1_VERSION" CMakeLists.txt` )
ASN1VER=${ASN1VEROPT[2]//\"}
ASN1VER=${ASN1VER//)}
unset ASN1VEROPT
# variable to identify and store the command (build, create ...)
# command index in the COMMAND and COMMANDS_NAME arrays
HELP_CMD=0
CREATE_CMD=1
BUILD_CMD=2
WAIT_CMD=3
DESTROY_CMD=4
TEST_CMD=5
REPORT_BUILD_CMD=6
REPORT_TEST_CMD=7
COMMANDS_NAME=(help create build wait destroy test report-build report-test)
#COMMAND will be used to save the command entered as argument
declare -A COMMAND
for i in "${COMMANDS_NAME[@]}"
do
COMMAND[$i]=0
done
# build the variant arrays
declare -a VARIANTS_SHORT
declare -a VARIANTS_LONG
build_variant_arrays
#variables to process options, for each option we define a variable to store
# its value and a bit mask, used to check allowed options depending on
# the command
# The two following arrays must be consistent: a given index must point to the long and short options
# of a given command
SHORT_OPTIONS=( "jn" "id" "ws" "k" "D" "gu" "pu" "mr" "var" "notused" "sb" "sc" "tb" "tc" "br" "co" "epc" "sim")
LONG_OPTIONS=( "job-name" "build-id" "workspace" "keep-vm-alive" "daemon" "git-url" "push" "merge-request"
"variant" "notused" "src-branch" "src-commit" "target-branch" "target-commit" "branch" "commit"
"external-epc" "sim-file")
JOB_NAME=XX
JOB_NAME_OPTINDEX=0
JOB_NAME_OPTID=1
BUILD_ID=XX
BUILD_ID_OPTINDEX=1
BUILD_ID_OPTID=2
JENKINS_WKSP_OPTINDEX=2
JENKINS_WKSP_OPTID=4
KEEP_VM_ALIVE_OPTINDEX=3
KEEP_VM_ALIVE_OPTID=8
KEEP_VM_ALIVE=0
DAEMON_OPTINDEX=4
DAEMON_OPTID=$((2**4))
DAEMON=0
GITURL_OPTINDEX=5
GITURL_OPTID=$((2**5))
PU_OPTINDEX=6
PU_OPTID=$((2**6))
PU_TRIG=0
MR_OPTINDEX=7
MR_OPTID=$((2**7))
MR_TRIG=0
VARIANT_OPTINDEX=8
VARIANT_OPTID=$((2**8))
SB_OPTINDEX=10
SB_OPTID=$((2**10))
SC_OPTINDEX=11
SC_OPTID=$((2**11))
TB_OPTINDEX=12
TB_OPTID=$((2**12))
TC_OPTINDEX=13
TC_OPTID=$((2**13))
BR_OPTINDEX=14
BR_OPTID=$((2**14))
CO_OPTINDEX=15
CO_OPTID=$((2**15))
EPC_IPADDR_OPTINDEX=16
EPC_IPADDR_OPTID=$((2**16))
EPC_IPADDR=""
SIM_OPTINDEX=17
SIM_OPTID=$((2**17))
SIMFILE=""
RUN_OPTIONS="none"
# list of variables that can be set via the --setvar option
AUTHORIZED_VAR=("VM_OSREL RUN_EXPERIMENTAL OPTIONAL_APTCACHER TESTPLATFORM_OWNER")
#variables to set which OS VM should use
#if [ -f "/etc/os-release" ]
#then
# source /etc/os-release
# VM_OS="$NAME"
# VM_OSREL="$VERSION_CODENAME"
# VM_ARCHI=`uname -m`
#else
VM_OS="ubuntu"
VM_OSREL="xenial"
VM_ARCHI="x86_64"
#fi
# variant option, ie the test variant which will be run triggers the
# variables listed below, used to configure the VM and to define what this
# VM will do. The variant can be specified by the --variant option or by a
# -V<xx> option.
VM_NAME=""
VM_MEMORY=0
VM_DISK=0
VM_CPU=0
ARCHIVES_LOC=""
LOG_PATTERN=""
NB_PATTERN_FILES=0
BUILD_OPTIONS=""
RUN_OPTIONS=""
# NARGS is used to check that only valid options are used for the given command
# It is a bit mask, each bit set to 1 specifies the corresponding option
# has been entered on the command line. MANDATORY_OPTMASK and ALLOWED_OPTMASK define
# respectively the mandatory and optional parameters of the entered command
NBARGS=0
MANDATORY_OPTMASK=(0 0) # some command have two sets of mandatory options
ALLOWED_OPTMASK=0
while [[ $# -gt 0 ]]
do
key="$1"
if [ "$(type -t $funcname)" != 'function' ]; then
funcname=do_it_normal
fi
case $key in
--debug)
set -v
set -x
shift
;;
-h|--help|help)
COMMAND["help"]=1
# following word might specify the topic for the help request
# but help can also be used without argument, so don't shift
if [ "$2" != "" ] && [ "$(type -t ${2//-/_}_usage)" = 'function' ]
then
HELPCMD="${2//-/_}_usage full"
fi
shift
;;
create)
COMMAND[$key]=1
# For create, mandatory options: jn, id. Optional: variant
MANDATORY_OPTMASK[0]=$(($JOB_NAME_OPTID + $BUILD_ID_OPTID ))
ALLOWED_OPTMASK=$(($VARIANT_OPTID))
# It is implied to keep the VM when creating it
KEEP_VM_ALIVE=1
shift
;;
build)
COMMAND[$key]=1
# For build, mandatory options: jn, id, ws. Optional: variant, k, D
MANDATORY_OPTMASK[0]=$(($JOB_NAME_OPTID + $BUILD_ID_OPTID + $JENKINS_WKSP_OPTID))
ALLOWED_OPTMASK=$(($KEEP_VM_ALIVE_OPTID + $DAEMON_OPTID + $VARIANT_OPTID))
shift
;;
wait)
# For test, mandatory options: jn, id, ws. Optional: variant, k
COMMAND[$key]=1
MANDATORY_OPTMASK[0]=$(($JOB_NAME_OPTID + $BUILD_ID_OPTID + $JENKINS_WKSP_OPTID))
ALLOWED_OPTMASK=$(($KEEP_VM_ALIVE_OPTID + $VARIANT_OPTID))
shift
;;
test)
COMMAND[$key]=1
# For test, mandatory options: jn, id, ws. Optional: variant, k, epc
MANDATORY_OPTMASK[0]=$(($JOB_NAME_OPTID + $BUILD_ID_OPTID + $JENKINS_WKSP_OPTID))
ALLOWED_OPTMASK=$(($KEEP_VM_ALIVE_OPTID + $VARIANT_OPTID + $EPC_IPADDR_OPTID + $SIM_OPTID))
shift
;;
destroy)
COMMAND[$key]=1
# For destroy, mandatory options: jn, id.
MANDATORY_OPTMASK[0]=$(($JOB_NAME_OPTID + $BUILD_ID_OPTID))
shift
;;
report-build)
COMMAND[$key]=1
# For report-build, mandatory options: jn, id, ws, gu, pu, br,co.
# or: jn, id, ws, gu, mr, sb, sc, tb, tc.
MANDATORY_OPTMASK[0]=$(($JOB_NAME_OPTID + $BUILD_ID_OPTID + $JENKINS_WKSP_OPTID + $GITURL_OPTID + $PU_OPTID + $BR_OPTID + $CO_OPTID))
MANDATORY_OPTMASK[1]=$(($JOB_NAME_OPTID + $BUILD_ID_OPTID + $JENKINS_WKSP_OPTID + $GITURL_OPTID + $MR_OPTID + $SB_OPTID + $SC_OPTID))
MANDATORY_OPTMASK[1]=$(( ${MANDATORY_OPTMASK[1]} + $TB_OPTID + $TC_OPTID))
shift
;;
report-test)
COMMAND[$key]=1
# For report-test, mandatory options: jn, id, ws, gu, pu, br,co.
# or: jn, id, ws, gu, mr, sb, sc, tb, tc.
MANDATORY_OPTMASK[0]=$(($JOB_NAME_OPTID + $BUILD_ID_OPTID + $JENKINS_WKSP_OPTID))
MANDATORY_OPTMASK[0]=$((${MANDATORY_OPTMASK[0]} + $GITURL_OPTID + $PU_OPTID + $BR_OPTID + $CO_OPTID))
MANDATORY_OPTMASK[1]=$(($JOB_NAME_OPTID + $BUILD_ID_OPTID + $JENKINS_WKSP_OPTID))
MANDATORY_OPTMASK[1]=$((${MANDATORY_OPTMASK[1]} + GITURL_OPTID + $MR_OPTID + $SB_OPTID + $SC_OPTID))
MANDATORY_OPTMASK[1]=$((${MANDATORY_OPTMASK[1]} + $TB_OPTID + $TC_OPTID))
shift
;;
-jn|--job-name)
JOB_NAME="$2"
NBARGS=$[$NBARGS+$JOB_NAME_OPTID]
shift
shift
;;
-id|--build-id)
BUILD_ID="$2"
NBARGS=$[$NBARGS+$BUILD_ID_OPTID]
shift
shift
;;
-ws|--workspace)
JENKINS_WKSP="$2"
NBARGS=$[$NBARGS+$JENKINS_WKSP_OPTID]
shift
shift
;;
-k|--keep-vm-alive)
KEEP_VM_ALIVE=1
NBARGS=$[$NBARGS+$KEEP_VM_ALIVE_OPTID]
shift
;;
-D|--daemon)
DAEMON=1
NBARGS=$[$NBARGS+$DAEMON_OPTID]
shift
;;
-gu|--git-url)
GIT_URL="$2"
NBARGS=$[$NBARGS+$GITURL_OPTID]
shift
shift
;;
--trigger)
TRIG="$2"
case $TRIG in
merge-request)
MR_TRIG=1
NBARGS=$[$NBARGS+$MR_OPTID]
;;
push)
PU_TRIG=1
NBARGS=$[$NBARGS+$PU_OPTID]
;;
*)
echo ""
echo "Syntax Error: Invalid Trigger option -> $TRIG"
echo ""
trigger_usage
exit
;;
esac
shift
shift
;;
-mr|--merge-request)
MR_TRIG=1
NBARGS=$[$NBARGS+$MR_OPTID]
shift
;;
-pu|--push)
PU_TRIG=1
NBARGS=$[$NBARGS+$PU_OPTID]
shift
;;
-sb|--src-branch)
SOURCE_BRANCH="$2"
NBARGS=$[$NBARGS+$SB_OPTID]
shift
shift
;;
-sc|--src-commit)
SOURCE_COMMIT_ID="$2"
NBARGS=$[$NBARGS+$SC_OPTID]
shift
shift
;;
-tb|--target-branch)
TARGET_BRANCH="$2"
NBARGS=$[$NBARGS+$TB_OPTID]
shift
shift
;;
-tc|--target-commit)
TARGET_COMMIT_ID="$2"
NBARGS=$[$NBARGS+$TC_OPTID]
shift
shift
;;
-br|--branch)
SOURCE_BRANCH="$2"
NBARGS=$[$NBARGS+$BR_OPTID]
shift
shift
;;
-co|--commit)
SOURCE_COMMIT_ID="$2"
NBARGS=$[$NBARGS+$CO_OPTID]
shift
shift
;;
-epc|--external-epc)
check_ipv4addr "$2"
check_ipv4addr "$3"
EPC_IPADDR="$2"
EPC_TUN_IPADDR="$3"
NBARGS=$[$NBARGS+$EPC_IPADDR_OPTID]
shift
shift
shift
;;
-sim|--sim-file)
SIMFILE="$2"
NBARGS=$[$NBARGS+$SIM_OPTID]
shift
shift
;;
--setvar_*)
check_setvar "${key:9}" "$2"
shift
shift
;;
-v[0-9] | -v[0-9][0-9])
check_set_variant ${key//"-"}
shift
;;
-var|--variant)
variant="$2"
check_set_variant ${2}
shift
shift
;;
*)
echo "Syntax Error: unknown option: $key"
echo ""
top_usage
exit 1
esac
done
i=0
for (( COUNT=1 ; COUNT<${#COMMAND[@]} ; COUNT++ ))
do
if [ ${COMMAND[${COMMANDS_NAME[$COUNT]}]} -eq 1 ]
then
COMMAND_KEY[$i]=${COMMANDS_NAME[$COUNT]}
(( i++ ))
fi
done
if [ ${COMMAND["help"]} -eq 1 ]
then
if [ ${#COMMAND_KEY[@]} -ne 1 ] && [ "$HELPCMD" == "" ]
then
top_usage
elif [ "$HELPCMD" != "" ]
then
$HELPCMD
else
${COMMAND_KEY[0]//-/_}_usage
fi
exit 0
else
if [ ${#COMMAND_KEY[@]} -gt 1 ]
then
echo "Syntax Error, too many commands: ${COMMAND_KEY[@]}"
top_usage
exit 1
fi
if [ -z "${COMMAND_KEY[0]}" ]
then
echo "Syntax Error: no command, specify one of: ${COMMANDS_NAME[@]}"
top_usage
exit 1
fi
check_command_options $NBARGS MANDATORY_OPTMASK[@] $ALLOWED_OPTMASK ${COMMAND_KEY[0]}
fi
if [ ${COMMAND[${COMMANDS_NAME[$REPORT_BUILD_CMD]}]} -ne 1 ] && [ ${COMMAND[${COMMANDS_NAME[$REPORT_TEST_CMD]}]} -ne 1 ]
then
# Checking uvt-kvm is installed
UVT_KVM_PATH=`which uvt-kvm | grep -c uvt-kvm`
if [ $UVT_KVM_PATH -eq 0 ]
then
echo "Error: uvt-kvm is not installed"
top_usage
exit 1
fi
fi
if [ "$JOB_NAME" == "XX" ] || [ "$BUILD_ID" == "XX" ]
then
VM_TEMPLATE=ci-
else
VM_TEMPLATE=${JOB_NAME}-b${BUILD_ID}-
fi
# set default variant
if [ "$VM_NAME" = "" ]
then
check_set_variant "v1"
fi
VM_NAME=`echo $VM_NAME | sed -e "s#ci-#$VM_TEMPLATE#"`
VM_CMDS=${VM_NAME}_cmds.txt
ARCHIVES_LOC=${JENKINS_WKSP}/archives/${ARCHIVES_LOC}
STATUS=0
if [ ${COMMAND[${COMMANDS_NAME[$CREATE_CMD]}]} -eq 1 ]
then
if [[ "$BUILD_OPTIONS" = "" ]]
then
echo "$VM_NAME is not a build variant"
exit 0
else
create_vm
fi
fi
if [ ${COMMAND[${COMMANDS_NAME[$BUILD_CMD]}]} -eq 1 ]
then
if [[ "$BUILD_OPTIONS" = "" ]]
then
echo " $VM_NAME is not a build variant"
exit 0
else
build_on_vm
fi
if [ $DAEMON -eq 0 ] && [ $STATUS -eq 0 ]
then
check_on_vm_build
fi
fi
if [ ${COMMAND[${COMMANDS_NAME[$WAIT_CMD]}]} -eq 1 ]
then
if [[ "$BUILD_OPTIONS" = "" ]]
then
echo "$VM_NAME is not a build variant"
exit 0
else
wait_on_vm_build
fi
if [ $STATUS -eq 0 ]
then
check_on_vm_build
fi
fi
if [ ${COMMAND[${COMMANDS_NAME[$TEST_CMD]}]} -eq 1 ]
then
# variant with EXPERIMENTAL variable set to true won't run and will be
# considered OK, except if --setvar_RUN_EXPERIMENTAL option has been set to true
if [ "$EXPERIMENTAL" = "true" ] && [ "$RUN_EXPERIMENTAL" != "true" ]
then
echo "Currently $VM_NAME Testing is not implemented / enabled"
echo "remove EXPERIMENTAL variable definition from this variant"
echo " or use option --setvar_RUN_EXPERIMENTAL=true to enforce testing it"
echo "STATUS seems OK"
exit $STATUS
fi
ARCHIVES_LOC=${ARCHIVES_LOC}/test
run_test_on_vm
fi
if [ ${COMMAND[${COMMANDS_NAME[$DESTROY_CMD]}]} -eq 1 ]
then
destroy_vm
fi
if [ ${COMMAND[${COMMANDS_NAME[$REPORT_BUILD_CMD]}]} -eq 1 ]
then
report_build
fi
if [ ${COMMAND[${COMMANDS_NAME[$REPORT_TEST_CMD]}]} -eq 1 ]
then
report_test
fi
# Did command pass or fail?
if [ $STATUS -eq 0 ]
then
echo "STATUS seems OK"
else
echo "STATUS failed?"
fi
exit $STATUS

View File

@@ -1,613 +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
# */
function report_build_usage {
echo "OAI CI VM script"
echo " Original Author: Raphael Defosseux"
echo ""
echo "Usage:"
echo "------"
echo " oai-ci-vm-tool report-build [OPTIONS]"
echo ""
command_options_usage
}
function trigger_usage {
echo "OAI CI VM script"
echo " Original Author: Raphael Defosseux"
echo ""
echo " --trigger merge-request OR -mr"
echo " --trigger push OR -pu"
echo " Specify trigger action of the Jenkins job. Either a merge-request event or a push event."
echo ""
}
function details_table {
echo " <h4>$1</h4>" >> $3
echo " <table border = \"1\">" >> $3
echo " <tr bgcolor = \"#33CCFF\" >" >> $3
echo " <th>File</th>" >> $3
echo " <th>Line Number</th>" >> $3
echo " <th>Status</th>" >> $3
echo " <th>Message</th>" >> $3
echo " </tr>" >> $3
LIST_MESSAGES=`egrep "error:|warning:" $2 | egrep -v "jobserver unavailable|Clock skew detected.|disabling jobserver mode"`
COMPLETE_MESSAGE="start"
for MESSAGE in $LIST_MESSAGES
do
if [[ $MESSAGE == *"/home/ubuntu/tmp"* ]] || [[ $MESSAGE == *"/tmp/CI-eNB"* ]]
then
FILENAME=`echo $MESSAGE | sed -e "s#^/home/ubuntu/tmp/##" -e "s#^.*/tmp/CI-eNB/##" | awk -F ":" '{print $1}'`
LINENB=`echo $MESSAGE | awk -F ":" '{print $2}'`
if [ "$COMPLETE_MESSAGE" != "start" ]
then
COMPLETE_MESSAGE=`echo $COMPLETE_MESSAGE | sed -e "s##'#g" -e "s##'#g"`
echo " <td>$COMPLETE_MESSAGE</td>" >> $3
echo " </tr>" >> $3
fi
echo " <tr>" >> $3
echo " <td>$FILENAME</td>" >> $3
echo " <td>$LINENB</td>" >> $3
else
if [[ $MESSAGE == *"warning:"* ]] || [[ $MESSAGE == *"error:"* ]]
then
MSGTYPE=`echo $MESSAGE | sed -e "s#:##g"`
echo " <td>$MSGTYPE</td>" >> $3
COMPLETE_MESSAGE=""
else
COMPLETE_MESSAGE=$COMPLETE_MESSAGE" "$MESSAGE
fi
fi
done
if [ "$COMPLETE_MESSAGE" != "start" ]
then
COMPLETE_MESSAGE=`echo $COMPLETE_MESSAGE | sed -e "s##'#g" -e "s##'#g"`
echo " <td>$COMPLETE_MESSAGE</td>" >> $3
echo " </tr>" >> $3
fi
echo " </table>" >> $3
}
function summary_table_header {
echo " <h3>$1</h3>" >> ./build_results.html
if [ -f $2/build_final_status.log ]
then
if [ `grep -c COMMAND $2/build_final_status.log` -eq 1 ]
then
COMMAND=`grep COMMAND $2/build_final_status.log | sed -e "s#COMMAND: ##"`
else
COMMAND="Unknown"
fi
if [ `grep -c BUILD_OK $2/build_final_status.log` -eq 1 ]
then
echo " <div class=\"alert alert-success\">" >> ./build_results.html
echo " <span class=\"glyphicon glyphicon-expand\"></span> $COMMAND <span class=\"glyphicon glyphicon-arrow-right\"></span> " >> ./build_results.html
echo " <strong>BUILD was SUCCESSFUL <span class=\"glyphicon glyphicon-ok-circle\"></span></strong>" >> ./build_results.html
echo " </div>" >> ./build_results.html
else
echo " <div class=\"alert alert-danger\">" >> ./build_results.html
echo " <span class=\"glyphicon glyphicon-expand\"></span> $COMMAND <span class=\"glyphicon glyphicon-arrow-right\"></span> " >> ./build_results.html
echo " <strong>BUILD was a FAILURE! <span class=\"glyphicon glyphicon-ban-circle\"></span></strong>" >> ./build_results.html
echo " </div>" >> ./build_results.html
fi
else
echo " <div class=\"alert alert-danger\">" >> ./build_results.html
echo " <strong>COULD NOT DETERMINE BUILD FINAL STATUS! <span class=\"glyphicon glyphicon-ban-circle\"></span></strong>" >> ./build_results.html
echo " </div>" >> ./build_results.html
fi
echo " <table border = \"1\">" >> ./build_results.html
echo " <tr bgcolor = \"#33CCFF\" >" >> ./build_results.html
echo " <th>Element</th>" >> ./build_results.html
echo " <th>Status</th>" >> ./build_results.html
echo " <th>Nb Errors</th>" >> ./build_results.html
echo " <th>Nb Warnings</th>" >> ./build_results.html
echo " </tr>" >> ./build_results.html
}
function summary_table_row {
echo " <tr>" >> ./build_results.html
echo " <td bgcolor = \"lightcyan\" >$1</th>" >> ./build_results.html
if [ -f $2 ]
then
BUILD_STATUS=`egrep -c "$3" $2`
if [ $BUILD_STATUS -eq 1 ]
then
echo " <td bgcolor = \"green\" >OK</th>" >> ./build_results.html
else
echo " <td bgcolor = \"red\" >KO</th>" >> ./build_results.html
fi
NB_ERRORS=`egrep -c "error:" $2`
if [ $NB_ERRORS -eq 0 ]
then
echo " <td bgcolor = \"green\" >$NB_ERRORS</th>" >> ./build_results.html
else
echo " <td bgcolor = \"red\" >$NB_ERRORS</th>" >> ./build_results.html
fi
NB_WARNINGS=`egrep "warning:" $2 | egrep -v "jobserver unavailable|Clock skew detected.|disabling jobserver mode" | egrep -c "warning:"`
if [ $NB_WARNINGS -eq 0 ]
then
echo " <td bgcolor = \"green\" >$NB_WARNINGS</th>" >> ./build_results.html
else
if [ $NB_WARNINGS -gt 20 ]
then
echo " <td bgcolor = \"red\" >$NB_WARNINGS</th>" >> ./build_results.html
else
echo " <td bgcolor = \"orange\" >$NB_WARNINGS</th>" >> ./build_results.html
fi
fi
if [ $NB_ERRORS -ne 0 ] || [ $NB_WARNINGS -ne 0 ]
then
details_table "$1" $2 $4
fi
else
echo " <td bgcolor = \"lightgray\" >Unknown</th>" >> ./build_results.html
echo " <td bgcolor = \"lightgray\" >--</th>" >> ./build_results.html
echo " <td bgcolor = \"lightgray\" >--</th>" >> ./build_results.html
fi
echo " </tr>" >> ./build_results.html
}
function summary_table_footer {
echo " </table>" >> ./build_results.html
}
function sca_summary_table_header {
echo " <h3>$2</h3>" >> ./build_results.html
NB_ERRORS=`egrep -c "severity=\"error\"" $1`
NB_WARNINGS=`egrep -c "severity=\"warning\"" $1`
ADDED_ERRORS="0"
ADDED_WARNINGS="0"
FINAL_LOG=`echo $1 | sed -e "s#cppcheck\.xml#build_final_status.log#"`
if [ `grep -c COMMAND $FINAL_LOG` -eq 1 ]
then
COMMAND=`grep COMMAND $FINAL_LOG | sed -e "s#COMMAND: ##"`
else
COMMAND="Unknown"
fi
if [ $MR_TRIG -eq 1 ]
then
if [ -d ../../cppcheck_archives ]
then
if [ -d ../../cppcheck_archives/$JOB_NAME ]
then
ADDED_ERRORS=`diff $1 ../../cppcheck_archives/$JOB_NAME/cppcheck.xml | egrep --color=never "^<" | egrep -c "severity=\"error"`
ADDED_WARNINGS=`diff $1 ../../cppcheck_archives/$JOB_NAME/cppcheck.xml | egrep --color=never "^<" | egrep -c "severity=\"warning"`
fi
fi
local TOTAL_NUMBER=$[$ADDED_ERRORS+$ADDED_WARNINGS]
if [ -f $JENKINS_WKSP/oai_cppcheck_added_errors.txt ]; then rm -f $JENKINS_WKSP/oai_cppcheck_added_errors.txt; fi
echo "$TOTAL_NUMBER" > $JENKINS_WKSP/oai_cppcheck_added_errors.txt
fi
if [ $NB_ERRORS -eq 0 ] && [ $NB_WARNINGS -eq 0 ]
then
echo " <div class=\"alert alert-success\">" >> ./build_results.html
echo " <span class=\"glyphicon glyphicon-expand\"></span> $COMMAND <br><br>" >> ./build_results.html
echo " <strong>CPPCHECK found NO error and NO warning <span class=\"glyphicon glyphicon-ok-circle\"></span></strong>" >> ./build_results.html
echo " </div>" >> ./build_results.html
else
if [ $NB_ERRORS -eq 0 ]
then
echo " <div class=\"alert alert-warning\">" >> ./build_results.html
echo " <span class=\"glyphicon glyphicon-expand\"></span> $COMMAND <br><br>" >> ./build_results.html
if [ $PU_TRIG -eq 1 ]
then
echo " <strong>CPPCHECK found NO error and $NB_WARNINGS warnings <span class=\"glyphicon glyphicon-warning-sign\"></span></strong>" >> ./build_results.html
fi
if [ $MR_TRIG -eq 1 ]
then
if [ $ADDED_WARNINGS -eq 0 ]
then
echo " <strong>CPPCHECK found NO error and $NB_WARNINGS warnings <span class=\"glyphicon glyphicon-warning-sign\"></span></strong>" >> ./build_results.html
else
echo " <strong>CPPCHECK found NO error and $NB_WARNINGS warnings <span class=\"glyphicon glyphicon-warning-sign\"></span></strong>" >> ./build_results.html
fi
fi
echo " </div>" >> ./build_results.html
else
echo " <div class=\"alert alert-danger\">" >> ./build_results.html
echo " <span class=\"glyphicon glyphicon-expand\"></span> $COMMAND <br><br>" >> ./build_results.html
if [ $PU_TRIG -eq 1 ]
then
echo " <strong>CPPCHECK found $NB_ERRORS errors and $NB_WARNINGS warnings <span class=\"glyphicon glyphicon-ban-circle\"></span></strong>" >> ./build_results.html
fi
if [ $MR_TRIG -eq 1 ]
then
if [ $ADDED_ERRORS -eq 0 ] && [ $ADDED_WARNINGS -eq 0 ]
then
echo " <strong>CPPCHECK found $NB_ERRORS errors and $NB_WARNINGS warnings <span class=\"glyphicon glyphicon-ban-circle\"></span></strong>" >> ./build_results.html
else
echo " <strong>CPPCHECK found $NB_ERRORS errors and $NB_WARNINGS warnings <span class=\"glyphicon glyphicon-ban-circle\"></span>" >> ./build_results.html
echo " <br>" >> ./build_results.html
echo " <br>" >> ./build_results.html
echo " <span class=\"glyphicon glyphicon-alert\"></span> This Merge Request may have introduced up to $ADDED_ERRORS errors and $ADDED_WARNINGS warnings. <span class=\"glyphicon glyphicon-alert\"></span></strong>" >> ./build_results.html
fi
fi
echo " </div>" >> ./build_results.html
fi
fi
if [ $PU_TRIG -eq 1 ]
then
if [ -d ../../cppcheck_archives ]
then
if [ -d ../../cppcheck_archives/$JOB_NAME ]
then
cp $1 ../../cppcheck_archives/$JOB_NAME
fi
fi
fi
echo " <button data-toggle=\"collapse\" data-target=\"#oai-cppcheck-details\">More details on CPPCHECK results</button>" >> ./build_results.html
echo " <div id=\"oai-cppcheck-details\" class=\"collapse\">" >> ./build_results.html
echo " <br>" >> ./build_results.html
echo " <table border = \"1\">" >> ./build_results.html
echo " <tr bgcolor = \"#33CCFF\" >" >> ./build_results.html
echo " <th>Error / Warning Type</th>" >> ./build_results.html
echo " <th>Nb Errors</th>" >> ./build_results.html
echo " <th>Nb Warnings</th>" >> ./build_results.html
echo " </tr>" >> ./build_results.html
echo "0" > ccp_error_cnt.txt
}
function sca_summary_table_row {
echo " <tr>" >> ./build_results.html
echo " <td bgcolor = \"lightcyan\" >$2</td>" >> ./build_results.html
if [ -f $1 ]
then
NB_ERRORS=`egrep "severity=\"error\"" $1 | egrep -c "id=\"$3\""`
echo " <td>$NB_ERRORS</td>" >> ./build_results.html
echo " <td>N/A</td>" >> ./build_results.html
if [ -f ccp_error_cnt.txt ]
then
TOTAL_ERRORS=`cat ccp_error_cnt.txt`
TOTAL_ERRORS=$((TOTAL_ERRORS + NB_ERRORS))
echo $TOTAL_ERRORS > ccp_error_cnt.txt
fi
else
echo " <td>Unknown</td>" >> ./build_results.html
echo " <td>Unknown</td>" >> ./build_results.html
fi
echo " </tr>" >> ./build_results.html
}
function sca_summary_table_footer {
if [ -f $1 ]
then
NB_ERRORS=`egrep -c "severity=\"error\"" $1`
NB_WARNINGS=`egrep -c "severity=\"warning\"" $1`
if [ -f ccp_error_cnt.txt ]
then
echo " <tr>" >> ./build_results.html
echo " <td bgcolor = \"lightcyan\" >Others</td>" >> ./build_results.html
TOTAL_ERRORS=`cat ccp_error_cnt.txt`
TOTAL_ERRORS=$((NB_ERRORS - TOTAL_ERRORS))
echo " <td>$TOTAL_ERRORS</td>" >> ./build_results.html
echo " <td>$NB_WARNINGS</td>" >> ./build_results.html
echo " </tr>" >> ./build_results.html
rm -f ccp_error_cnt.txt
fi
echo " <tr bgcolor = \"#33CCFF\" >" >> ./build_results.html
echo " <th>Total</th>" >> ./build_results.html
echo " <th>$NB_ERRORS</th>" >> ./build_results.html
echo " <th>$NB_WARNINGS</th>" >> ./build_results.html
else
echo " <tr bgcolor = \"#33CCFF\" >" >> ./build_results.html
echo " <th>Total</th>" >> ./build_results.html
echo " <th>Unknown</th>" >> ./build_results.html
echo " <th>Unknown</th>" >> ./build_results.html
if [ -f ccp_error_cnt.txt ]
then
rm -f ccp_error_cnt.txt
fi
fi
echo " </tr>" >> ./build_results.html
echo " </table>" >> ./build_results.html
echo " <p>Full details in zipped artifact (cppcheck/cppcheck.xml) </p>" >> ./build_results.html
echo " <p style=\"margin-left: 30px\">Graphical Interface tool : <strong><code>cppcheck-gui -l cppcheck/cppcheck.xml</code></strong></p>" >> ./build_results.html
if [ $MR_TRIG -eq 1 ]
then
if [ $ADDED_ERRORS -ne 0 ] || [ $ADDED_WARNINGS -ne 0 ]
then
echo " <table border = \"1\">" >> ./build_results.html
echo " <tr bgcolor = \"#33CCFF\" >" >> ./build_results.html
echo " <th>Potential File(s) impacted by added errors/warnings</th>" >> ./build_results.html
echo " <th>Line Number</th>" >> ./build_results.html
echo " <th>Severity</th>" >> ./build_results.html
echo " <th>Message</th>" >> ./build_results.html
echo " </tr>" >> ./build_results.html
SEVERITY="none"
POTENTIAL_FILES=`diff $1 ../../cppcheck_archives/$JOB_NAME/cppcheck.xml | egrep --color=never "^<" | egrep "location file|severity" | sed -e "s# #@#g"`
for POT_FILE in $POTENTIAL_FILES
do
if [ `echo $POT_FILE | grep -c location` -eq 1 ]
then
FILENAME=`echo $POT_FILE | sed -e "s#^.*file=\"##" -e "s#\"@line.*/>##"`
LINE=`echo $POT_FILE | sed -e "s#^.*line=\"##" -e "s#\"/>##"`
if [[ $SEVERITY != *"none" ]]
then
echo " <tr>" >> ./build_results.html
echo " <td>$FILENAME</td>" >> ./build_results.html
echo " <td>$LINE</td>" >> ./build_results.html
echo " <td>$SEVERITY</td>" >> ./build_results.html
echo " <td>$MESSAGE</td>" >> ./build_results.html
echo " </tr>" >> ./build_results.html
fi
else
SEVERITY=`echo $POT_FILE | sed -e "s#^.*severity=\"##" -e "s#\"@msg=.*##"`
MESSAGE=`echo $POT_FILE | sed -e "s#^.*msg=\"##" -e "s#\"@verbose=.*##" -e "s#@# #g"`
fi
done
echo " </table>" >> ./build_results.html
fi
fi
echo " </div>" >> ./build_results.html
}
function report_build {
echo "############################################################"
echo "OAI CI VM script"
echo "############################################################"
echo "JENKINS_WKSP = $JENKINS_WKSP"
echo "GIT_URL = $GIT_URL"
cd ${JENKINS_WKSP}
echo "<!DOCTYPE html>" > ./build_results.html
echo "<html class=\"no-js\" lang=\"en-US\">" >> ./build_results.html
echo "<head>" >> ./build_results.html
echo " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">" >> ./build_results.html
echo " <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css\">" >> ./build_results.html
echo " <script src=\"https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js\"></script>" >> ./build_results.html
echo " <script src=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js\"></script>" >> ./build_results.html
echo " <title>Build Results for $JOB_NAME job build #$BUILD_ID</title>" >> ./build_results.html
echo " <base href = \"http://www.openairinterface.org/\" />" >> ./build_results.html
echo "</head>" >> ./build_results.html
echo "<body><div class=\"container\">" >> ./build_results.html
echo " <br>" >> ./build_results.html
echo " <table style=\"border-collapse: collapse; border: none;\">" >> ./build_results.html
echo " <tr style=\"border-collapse: collapse; border: none;\">" >> ./build_results.html
echo " <td style=\"border-collapse: collapse; border: none;\">" >> ./build_results.html
echo " <a href=\"http://www.openairinterface.org/\">" >> ./build_results.html
echo " <img src=\"/wp-content/uploads/2016/03/cropped-oai_final_logo2.png\" alt=\"\" border=\"none\" height=50 width=150>" >> ./build_results.html
echo " </img>" >> ./build_results.html
echo " </a>" >> ./build_results.html
echo " </td>" >> ./build_results.html
echo " <td style=\"border-collapse: collapse; border: none; vertical-align: center;\">" >> ./build_results.html
echo " <b><font size = \"6\">Job Summary -- Job: $JOB_NAME -- Build-ID: $BUILD_ID</font></b>" >> ./build_results.html
echo " </td>" >> ./build_results.html
echo " </tr>" >> ./build_results.html
echo " </table>" >> ./build_results.html
echo " <br>" >> ./build_results.html
echo " <table border = \"1\">" >> ./build_results.html
echo " <tr>" >> ./build_results.html
echo " <td bgcolor = \"lightcyan\" > <span class=\"glyphicon glyphicon-time\"></span> Build Start Time (UTC)</td>" >> ./build_results.html
echo " <td>TEMPLATE_BUILD_TIME</td>" >> ./build_results.html
echo " </tr>" >> ./build_results.html
echo " <tr>" >> ./build_results.html
echo " <td bgcolor = \"lightcyan\" > <span class=\"glyphicon glyphicon-cloud-upload\"></span> GIT Repository</td>" >> ./build_results.html
echo " <td><a href=\"$GIT_URL\">$GIT_URL</a></td>" >> ./build_results.html
echo " </tr>" >> ./build_results.html
echo " <tr>" >> ./build_results.html
echo " <td bgcolor = \"lightcyan\" > <span class=\"glyphicon glyphicon-wrench\"></span> Job Trigger</td>" >> ./build_results.html
if [ $PU_TRIG -eq 1 ]; then echo " <td>Push Event</td>" >> ./build_results.html; fi
if [ $MR_TRIG -eq 1 ]; then echo " <td>Merge-Request</td>" >> ./build_results.html; fi
echo " </tr>" >> ./build_results.html
if [ $PU_TRIG -eq 1 ]
then
echo " <tr>" >> ./build_results.html
echo " <td bgcolor = \"lightcyan\" > <span class=\"glyphicon glyphicon-tree-deciduous\"></span> Branch</td>" >> ./build_results.html
echo " <td>$SOURCE_BRANCH</td>" >> ./build_results.html
echo " </tr>" >> ./build_results.html
echo " <tr>" >> ./build_results.html
echo " <td bgcolor = \"lightcyan\" > <span class=\"glyphicon glyphicon-tag\"></span> Commit ID</td>" >> ./build_results.html
echo " <td>$SOURCE_COMMIT_ID</td>" >> ./build_results.html
echo " </tr>" >> ./build_results.html
if [ -e .git/CI_COMMIT_MSG ]
then
echo " <tr>" >> ./build_results.html
echo " <td bgcolor = \"lightcyan\" > <span class=\"glyphicon glyphicon-comment\"></span> Commit Message</td>" >> ./build_results.html
MSG=`cat .git/CI_COMMIT_MSG`
echo " <td>$MSG</td>" >> ./build_results.html
echo " </tr>" >> ./build_results.html
fi
fi
if [ $MR_TRIG -eq 1 ]
then
echo " <tr>" >> ./build_results.html
echo " <td bgcolor = \"lightcyan\" > <span class=\"glyphicon glyphicon-log-out\"></span> Source Branch</td>" >> ./build_results.html
echo " <td>$SOURCE_BRANCH</td>" >> ./build_results.html
echo " </tr>" >> ./build_results.html
echo " <tr>" >> ./build_results.html
echo " <td bgcolor = \"lightcyan\" > <span class=\"glyphicon glyphicon-tag\"></span> Source Commit ID</td>" >> ./build_results.html
echo " <td>$SOURCE_COMMIT_ID</td>" >> ./build_results.html
echo " </tr>" >> ./build_results.html
if [ -e .git/CI_COMMIT_MSG ]
then
echo " <tr>" >> ./build_results.html
echo " <td bgcolor = \"lightcyan\" > <span class=\"glyphicon glyphicon-comment\"></span> Source Commit Message</td>" >> ./build_results.html
MSG=`cat .git/CI_COMMIT_MSG`
echo " <td>$MSG</td>" >> ./build_results.html
echo " </tr>" >> ./build_results.html
fi
echo " <tr>" >> ./build_results.html
echo " <td bgcolor = \"lightcyan\" > <span class=\"glyphicon glyphicon-log-in\"></span> Target Branch</td>" >> ./build_results.html
echo " <td>$TARGET_BRANCH</td>" >> ./build_results.html
echo " </tr>" >> ./build_results.html
echo " <tr>" >> ./build_results.html
echo " <td bgcolor = \"lightcyan\" > <span class=\"glyphicon glyphicon-tag\"></span> Target Commit ID</td>" >> ./build_results.html
echo " <td>$TARGET_COMMIT_ID</td>" >> ./build_results.html
echo " </tr>" >> ./build_results.html
fi
echo " </table>" >> ./build_results.html
echo " <h2>Build Summary</h2>" >> ./build_results.html
echo " <h3>OAI Coding / Formatting Guidelines Check</h3>" >> ./build_results.html
if [ -f ./header-files-w-incorrect-define.txt ]
then
NB_FILES_IN_ERROR=`wc -l ./header-files-w-incorrect-define.txt | sed -e "s@ .*@@"`
if [ $NB_FILES_IN_ERROR -eq 0 ]
then
echo " <div class=\"alert alert-success\">" >> ./build_results.html
if [ $MR_TRIG -eq 1 ]; then echo " <strong>No Issue for CIRCULAR DEPENDENCY PROTECTION in modified files</strong>" >> ./build_results.html; fi
if [ $PU_TRIG -eq 1 ]; then echo " <strong>No Issue for CIRCULAR DEPENDENCY PROTECTION in the whole repository</strong>" >> ./build_results.html; fi
echo " </div>" >> ./build_results.html
else
echo " <div class=\"alert alert-warning\">" >> ./build_results.html
if [ $MR_TRIG -eq 1 ]; then echo " <strong>${NB_FILES_IN_ERROR} modified files MAY NOT HAVE CIRCULAR DEPENDENCY PROTECTION</strong>" >> ./build_results.html; fi
if [ $PU_TRIG -eq 1 ]; then echo " <strong>${NB_FILES_IN_ERROR} files in repository MAY NOT HAVE CIRCULAR DEPENDENCY PROTECTION in the whole repository</strong>" >> ./build_results.html; fi
echo " </div>" >> ./build_results.html
echo " <button data-toggle=\"collapse\" data-target=\"#oai-circular-details\">More details on circular dependency protection check</button>" >> ./build_results.html
echo " <div id=\"oai-circular-details\" class=\"collapse\">" >> ./build_results.html
echo " <table border = 1>" >> ./build_results.html
echo " <tr>" >> ./build_results.html
echo " <th bgcolor = \"lightcyan\" >Potential Issue</th>" >> ./build_results.html
echo " <th bgcolor = \"lightcyan\" >Impacted File</th>" >> ./build_results.html
echo " <th bgcolor = \"lightcyan\" >Incorrect Macro</th>" >> ./build_results.html
echo " </tr>" >> ./build_results.html
awk '{if($0 ~/error in/){print " <tr><td>error in declaration</td><td>"$4"</td><td>"$5"</td></tr>"};if($0 ~/files with same/){print " <tr><td>files with same #define</td><td>"$5"</td><td>"$6"</td></tr>"}}' ./header-files-w-incorrect-define.txt >> ./build_results.html
echo " </table>" >> ./build_results.html
echo " </div>" >> ./build_results.html
echo " <br>" >> ./build_results.html
fi
fi
if [ -f ./files-w-gnu-gpl-license-banner.txt ]
then
NB_FILES_IN_ERROR=`wc -l ./files-w-gnu-gpl-license-banner.txt | sed -e "s@ .*@@"`
if [ $NB_FILES_IN_ERROR -ne 0 ]
then
echo " <div class=\"alert alert-danger\">" >> ./build_results.html
if [ $MR_TRIG -eq 1 ]; then echo " <strong>${NB_FILES_IN_ERROR} modified files HAVE a GNU GPL license banner</strong>" >> ./build_results.html; fi
if [ $PU_TRIG -eq 1 ]; then echo " <strong>${NB_FILES_IN_ERROR} files in repository HAVE a GNU GPL license banner</strong>" >> ./build_results.html; fi
echo " </div>" >> ./build_results.html
echo " <button data-toggle=\"collapse\" data-target=\"#oai-license-gpl\">More details on GNU GPL license banner issue</button>" >> ./build_results.html
echo " <div id=\"oai-license-gpl\" class=\"collapse\">" >> ./build_results.html
echo " <table border = 1>" >> ./build_results.html
echo " <tr>" >> ./build_results.html
echo " <th bgcolor = \"lightcyan\" >Filename</th>" >> ./build_results.html
echo " </tr>" >> ./build_results.html
awk '{print " <tr><td>"$1"</td></tr>"}' ./files-w-gnu-gpl-license-banner.txt >> ./build_results.html
echo " </table>" >> ./build_results.html
echo " </div>" >> ./build_results.html
echo " <br>" >> ./build_results.html
fi
fi
if [ -f ./files-w-suspect-banner.txt ]
then
NB_FILES_IN_ERROR=`wc -l ./files-w-suspect-banner.txt | sed -e "s@ .*@@"`
if [ $NB_FILES_IN_ERROR -ne 0 ]
then
echo " <div class=\"alert alert-warning\">" >> ./build_results.html
if [ $MR_TRIG -eq 1 ]; then echo " <strong>${NB_FILES_IN_ERROR} modified files HAVE a suspect license banner</strong>" >> ./build_results.html; fi
if [ $PU_TRIG -eq 1 ]; then echo " <strong>${NB_FILES_IN_ERROR} files in repository HAVE a suspect license banner</strong>" >> ./build_results.html; fi
echo " </div>" >> ./build_results.html
echo " <button data-toggle=\"collapse\" data-target=\"#oai-license-suspect\">More details on suspect banner files</button>" >> ./build_results.html
echo " <div id=\"oai-license-suspect\" class=\"collapse\">" >> ./build_results.html
echo " <table border = 1>" >> ./build_results.html
echo " <tr>" >> ./build_results.html
echo " <th bgcolor = \"lightcyan\" >Filename</th>" >> ./build_results.html
echo " </tr>" >> ./build_results.html
awk '{print " <tr><td>"$1"</td></tr>"}' ././files-w-suspect-banner.txt >> ./build_results.html
echo " </table>" >> ./build_results.html
echo " </div>" >> ./build_results.html
echo " <br>" >> ./build_results.html
fi
fi
echo " <h2>Ubuntu 16.04 LTS -- Summary</h2>" >> ./build_results.html
if [ -f archives/gnb_usrp/nr-softmodem.txt ]
then
summary_table_header "OAI Build: 5G NR gNB -- USRP option" ./archives/gnb_usrp
summary_table_row "5G NR SoftModem" ./archives/gnb_usrp/nr-softmodem.txt "Built target nr-softmodem" ./gnb_usrp_row1.html
summary_table_row "Coding" ./archives/gnb_usrp/coding.txt "Built target coding" ./gnb_usrp_row2.html
summary_table_row "OAI USRP device if" ./archives/gnb_usrp/oai_usrpdevif.txt "Built target oai_usrpdevif" ./gnb_usrp_row3.html
summary_table_row "OAI ETHERNET transport" ./archives/gnb_usrp/oai_eth_transpro.txt "Built target oai_eth_transpro" ./gnb_usrp_row4.html
summary_table_row "Parameters Lib Config" ./archives/gnb_usrp/params_libconfig.txt "Built target params_libconfig" ./gnb_usrp_row6.html
summary_table_footer
fi
if [ -f archives/nr_ue_usrp/nr-uesoftmodem.txt ]
then
summary_table_header "OAI Build: 5G NR UE -- USRP option" ./archives/nr_ue_usrp
summary_table_row "5G NR UE SoftModem" ./archives/nr_ue_usrp/nr-uesoftmodem.txt "Built target nr-uesoftmodem" ./nr_ue_usrp_row1.html
summary_table_row "Coding" ./archives/nr_ue_usrp/coding.txt "Built target coding" ./nr_ue_usrp_row2.html
summary_table_row "OAI USRP device if" ./archives/nr_ue_usrp/oai_usrpdevif.txt "Built target oai_usrpdevif" ./nr_ue_usrp_row3.html
summary_table_row "OAI ETHERNET transport" ./archives/nr_ue_usrp/oai_eth_transpro.txt "Built target oai_eth_transpro" ./nr_ue_usrp_row4.html
summary_table_row "Parameters Lib Config" ./archives/nr_ue_usrp/params_libconfig.txt "Built target params_libconfig" ./nr_ue_usrp_row6.html
summary_table_footer
fi
if [ -e ./archives/red_hat ]
then
echo " <h2>Red Hat Enterprise Linux Server release 7.6) -- Summary</h2>" >> ./build_results.html
summary_table_header "OAI Build: 4G LTE eNB -- USRP option (RHEL)" ./archives/red_hat
summary_table_row "LTE SoftModem" ./archives/red_hat/lte-softmodem.txt "Built target lte-softmodem" ./enb_usrp_rh_row1.html
summary_table_row "Coding" ./archives/red_hat/coding.txt "Built target coding" ./enb_usrp_rh_row2.html
summary_table_row "OAI USRP device if" ./archives/red_hat/oai_usrpdevif.txt "Built target oai_usrpdevif" ./enb_usrp_rh_row3.html
summary_table_row "Parameters Lib Config" ./archives/red_hat/params_libconfig.txt "Built target params_libconfig" ./enb_usrp_rh_row4.html
summary_table_footer
fi
echo " <h3>Details</h3>" >> ./build_results.html
echo " <button data-toggle=\"collapse\" data-target=\"#oai-compilation-details\">Details for Compilation Errors and Warnings </button>" >> ./build_results.html
echo " <div id=\"oai-compilation-details\" class=\"collapse\">" >> ./build_results.html
if [ -f ./enb_eth_row1.html ] || [ -f ./enb_eth_row2.html ] || [ -f ./enb_eth_row3.html ] || [ -f ./enb_eth_row4.html ] || [ -f ./enb_eth_row5.html ] || [ -f ./enb_eth_row6.html ] || [ -f ./enb_eth_row7.html ]
then
for DETAILS_TABLE in `ls ./enb_eth_row*.html`
do
cat $DETAILS_TABLE >> ./build_results.html
done
fi
if [ -f ./ue_eth_row1.html ] || [ -f ./ue_eth_row2.html ] || [ -f ./ue_eth_row3.html ] || [ -f ./ue_eth_row4.html ] || [ -f ./ue_eth_row5.html ] || [ -f ./ue_eth_row6.html ] || [ -f ./ue_eth_row7.html ] || [ -f ./ue_eth_row8.html ] || [ -f ./ue_eth_row9.html ] || [ -f ./ue_eth_row9a.html ] || [ -f ./ue_eth_row9b.html ]
then
for DETAILS_TABLE in `ls ./ue_eth_row*.html`
do
cat $DETAILS_TABLE >> ./build_results.html
done
fi
if [ -f ./gnb_usrp_row1.html ] || [ -f ./gnb_usrp_row2.html ] || [ -f ./gnb_usrp_row3.html ] || [ -f ./gnb_usrp_row4.html ]
then
for DETAILS_TABLE in `ls ./gnb_usrp_row*.html`
do
cat $DETAILS_TABLE >> ./build_results.html
done
fi
if [ -f ./nr_ue_usrp_row1.html ] || [ -f ./nr_ue_usrp_row2.html ] || [ -f ./nr_ue_usrp_row3.html ] || [ -f ./nr_ue_usrp_row4.html ]
then
for DETAILS_TABLE in `ls ./nr_ue_usrp_row*.html`
do
cat $DETAILS_TABLE >> ./build_results.html
done
fi
rm -f ./*_row*.html
echo " </div>" >> ./build_results.html
echo " <p></p>" >> ./build_results.html
echo " <div class=\"well well-lg\">End of Build Report -- Copyright <span class=\"glyphicon glyphicon-copyright-mark\"></span> 2018 <a href=\"http://www.openairinterface.org/\">OpenAirInterface</a>. All Rights Reserved.</div>" >> ./build_results.html
echo "</div></body>" >> ./build_results.html
echo "</html>" >> ./build_results.html
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,205 +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
# */
function wait_usage {
echo "OAI CI VM script"
echo " Original Author: Raphael Defosseux"
echo " Requirements:"
echo " -- uvtool uvtool-libvirt apt-cacher"
echo " -- $VM_OSREL image already synced"
echo " Default:"
echo " -- eNB with USRP"
echo ""
echo "Usage:"
echo "------"
echo " oai-ci-vm-tool wait [OPTIONS]"
echo ""
command_options_usage
}
function wait_on_vm_build {
echo "############################################################"
echo "OAI CI VM script"
echo "############################################################"
echo "VM_NAME = $VM_NAME"
echo "VM_CMD_FILE = $VM_CMDS"
echo "JENKINS_WKSP = $JENKINS_WKSP"
echo "ARCHIVES_LOC = $ARCHIVES_LOC"
echo "BUILD_OPTIONS = $BUILD_OPTIONS"
if [[ "$VM_NAME" == *"-enb-usrp"* ]] || [[ "$VM_NAME" == *"-cppcheck"* ]] || [[ "$VM_NAME" == *"-phy-sim"* ]] || [[ "$VM_NAME" == *"-basic-sim"* ]] || [[ "$VM_NAME" == *"-flexran-rtc"* ]] || [[ "$VM_NAME" == *"-rf-sim"* ]] || [[ "$VM_NAME" == *"-ethernet"* ]] || [[ "$VM_NAME" == *"rf5g-sim"* ]] || [[ "$VM_NAME" == *"gnb-usrp"* ]] || [[ "$VM_NAME" == *"nr-ue-usrp"* ]]
then
echo "This VM type is no longer supported in the pipeline framework"
return
fi
IS_VM_ALIVE=`uvt-kvm list | grep -c $VM_NAME`
if [ $IS_VM_ALIVE -eq 0 ]
then
echo "############################################################"
echo "You should have created the VM before doing anything"
echo "############################################################"
STATUS=1
return
fi
echo "Waiting for VM to be started"
uvt-kvm wait $VM_NAME --insecure
VM_IP_ADDR=`uvt-kvm ip $VM_NAME`
echo "$VM_NAME has for IP addr = $VM_IP_ADDR"
echo "############################################################"
echo "Waiting build process to end on VM ($VM_NAME)"
echo "############################################################"
# Since the last VM was cppcheck and is removed
# we are going too fast in wait and the build_oai is not yet started
sleep 120
if [[ "$VM_NAME" == *"-cppcheck"* ]]
then
echo "echo \"ps -aux | grep cppcheck \"" >> $VM_CMDS
echo "while [ \$(ps -aux | grep --color=never cppcheck | grep -v grep | wc -l) -gt 0 ]; do sleep 3; done" >> $VM_CMDS
else
echo "echo \"ps -aux | grep build \"" >> $VM_CMDS
echo "while [ \$(ps -aux | grep --color=never build_oai | grep -v grep | wc -l) -gt 0 ]; do sleep 3; done" >> $VM_CMDS
fi
echo "echo \"df -h\"" >> $VM_CMDS
echo "df -h" >> $VM_CMDS
ssh -T -o StrictHostKeyChecking=no ubuntu@$VM_IP_ADDR < $VM_CMDS
rm -f $VM_CMDS
}
function check_on_vm_build {
if [[ "$VM_NAME" == *"-enb-usrp"* ]] || [[ "$VM_NAME" == *"-cppcheck"* ]] || [[ "$VM_NAME" == *"-phy-sim"* ]] || [[ "$VM_NAME" == *"-basic-sim"* ]] || [[ "$VM_NAME" == *"-flexran-rtc"* ]] || [[ "$VM_NAME" == *"-rf-sim"* ]] || [[ "$VM_NAME" == *"-ethernet"* ]] || [[ "$VM_NAME" == *"rf5g-sim"* ]] || [[ "$VM_NAME" == *"gnb-usrp"* ]] || [[ "$VM_NAME" == *"nr-ue-usrp"* ]]
then
echo "This VM type is no longer supported in the pipeline framework"
return
fi
echo "############################################################"
echo "Creating a tmp folder to store results and artifacts"
echo "############################################################"
if [ ! -d $JENKINS_WKSP/archives ]
then
mkdir $JENKINS_WKSP/archives
fi
if [ ! -d $ARCHIVES_LOC ]
then
mkdir $ARCHIVES_LOC
fi
scp -o StrictHostKeyChecking=no ubuntu@$VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/*.txt $ARCHIVES_LOC
if [[ "$VM_NAME" == *"-cppcheck"* ]]
then
scp -o StrictHostKeyChecking=no ubuntu@$VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/*.xml $ARCHIVES_LOC
fi
if [ $KEEP_VM_ALIVE -eq 0 ]
then
if [[ "$VM_NAME" == *"-enb-ethernet"* ]] || [[ "$VM_NAME" == *"-ue-ethernet"* ]]
then
echo "Hack to not destroy in current pipeline"
else
echo "############################################################"
echo "Destroying VM"
echo "############################################################"
uvt-kvm destroy $VM_NAME
ssh-keygen -R $VM_IP_ADDR
fi
fi
rm -f $VM_CMDS
echo "############################################################"
echo "Checking build status"
echo "############################################################"
if [[ "$VM_NAME" == *"-cppcheck"* ]]
then
LOG_FILES=`ls $ARCHIVES_LOC/*.txt $ARCHIVES_LOC/*.xml`
else
LOG_FILES=`ls $ARCHIVES_LOC/*.txt`
fi
echo "LOG_FILES=$LOG_FILES"
echo "expecting NB_PATTERN_FILES=$NB_PATTERN_FILES"
STATUS=0
NB_FOUND_FILES=0
for FULLFILE in $LOG_FILES
do
if [[ $FULLFILE == *"$LOG_PATTERN"* ]]
then
filename=$(basename -- "$FULLFILE")
if [ "$LOG_PATTERN" == ".txt" ]
then
PASS_PATTERN=`echo $filename | sed -e "s#$LOG_PATTERN##"`
fi
if [ "$LOG_PATTERN" == "cppcheck.xml" ]
then
PASS_PATTERN="results version"
LOCAL_STAT=`egrep -c "$PASS_PATTERN" $FULLFILE`
else
LOCAL_STAT=`egrep -c "Built target $PASS_PATTERN" $FULLFILE`
fi
if [ $LOCAL_STAT -eq 0 ]; then
echo "WARNING: file $filename does not contain pass pattern"
else
NB_FOUND_FILES=$((NB_FOUND_FILES + 1))
fi
fi
done
if [ $NB_PATTERN_FILES -ne $NB_FOUND_FILES ]
then
echo "Expecting $NB_PATTERN_FILES log files and found $NB_FOUND_FILES"
STATUS=-1
fi
# If we were building the FlexRan Controller, flag-touch for basic-simulator to continue
#if [[ "$VM_NAME" == *"-flexran-rtc"* ]]
#then
# if [[ $STATUS -eq 0 ]]
# then
# touch $JENKINS_WKSP/flexran/flexran_build_complete.txt
# fi
#fi
if [[ "$VM_NAME" == *"-cppcheck"* ]]
then
echo "COMMAND: cppcheck $BUILD_OPTIONS . 2> cppcheck.xml" > $ARCHIVES_LOC/build_final_status.log
elif [[ "$VM_NAME" == *"-flexran-rtc"* ]]
then
echo "COMMAND: $BUILD_OPTIONS" > $ARCHIVES_LOC/build_final_status.log
else
echo "COMMAND: build_oai -I $BUILD_OPTIONS" > $ARCHIVES_LOC/build_final_status.log
fi
if [[ $STATUS -eq 0 ]]
then
echo "BUILD_OK" >> $ARCHIVES_LOC/build_final_status.log
else
echo "BUILD_KO" >> $ARCHIVES_LOC/build_final_status.log
fi
}

View File

@@ -0,0 +1,124 @@
<!--
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
-->
<testCaseList>
<htmlTabRef>rfsim-5gnr-tdd-2x2</htmlTabRef>
<htmlTabName>Monolithic SA TDD 2x2 gNB</htmlTabName>
<htmlTabIcon>wrench</htmlTabIcon>
<repeatCount>1</repeatCount>
<TestCaseRequestedList>
111111
100001
000000
000001
000002
000003
020001
020002
030001
030002
100001
</TestCaseRequestedList>
<TestCaseExclusionList></TestCaseExclusionList>
<testCase id="111111">
<class>Pull_Local_Registry</class>
<desc>Pull Images from Local Registry</desc>
<test_svr_id>0</test_svr_id>
<images_to_pull>oai-gnb oai-nr-ue</images_to_pull>
</testCase>
<testCase id="000000">
<class>DeployGenObject</class>
<desc>Deploy MySql Database</desc>
<yaml_path>yaml_files/5g_rfsimulator_2x2</yaml_path>
<services>mysql</services>
<nb_healthy>1</nb_healthy>
</testCase>
<testCase id="000001">
<class>DeployGenObject</class>
<desc>Deploy OAI 5G CoreNetwork</desc>
<yaml_path>yaml_files/5g_rfsimulator_2x2</yaml_path>
<services>oai-nrf oai-amf oai-smf oai-spgwu oai-ext-dn</services>
<nb_healthy>6</nb_healthy>
</testCase>
<testCase id="000002">
<class>DeployGenObject</class>
<desc>Deploy OAI 5G gNB RF sim SA</desc>
<yaml_path>yaml_files/5g_rfsimulator_2x2</yaml_path>
<services>oai-gnb</services>
<nb_healthy>7</nb_healthy>
</testCase>
<testCase id="000003">
<class>DeployGenObject</class>
<desc>Deploy OAI 5G NR-UE RF sim SA</desc>
<yaml_path>yaml_files/5g_rfsimulator_2x2</yaml_path>
<services>oai-nr-ue</services>
<nb_healthy>8</nb_healthy>
</testCase>
<testCase id="020001">
<class>PingFromContainer</class>
<desc>Ping ext-dn from NR-UE</desc>
<container_name>rfsim5g-oai-nr-ue</container_name>
<options>-I oaitun_ue1 -c 20 192.168.72.135</options>
<loss_threshold>5</loss_threshold>
</testCase>
<testCase id="020002">
<class>PingFromContainer</class>
<desc>Ping NR-UE from ext-dn</desc>
<container_name>rfsim5g-oai-ext-dn</container_name>
<options>-c 20 12.1.1.2</options>
<loss_threshold>5</loss_threshold>
</testCase>
<testCase id="030001">
<class>IperfFromContainer</class>
<desc>Iperf UDP Downlink</desc>
<server_container_name>rfsim5g-oai-nr-ue</server_container_name>
<client_container_name>rfsim5g-oai-ext-dn</client_container_name>
<server_options>-B 12.1.1.2 -u -i 1 -s</server_options>
<client_options>-c 12.1.1.2 -u -i 1 -t 10 -b 3M</client_options>
</testCase>
<testCase id="030002">
<class>IperfFromContainer</class>
<desc>Iperf UDP Uplink</desc>
<server_container_name>rfsim5g-oai-ext-dn</server_container_name>
<client_container_name>rfsim5g-oai-nr-ue</client_container_name>
<server_options>-u -i 1 -s</server_options>
<client_options>-B 12.1.1.2 -c 192.168.72.135 -u -i 1 -t 10 -b 1M</client_options>
</testCase>
<testCase id="100001">
<class>UndeployGenObject</class>
<desc>Undeploy all OAI 5G stack</desc>
<yaml_path>yaml_files/5g_rfsimulator_2x2</yaml_path>
<d_retx_th>1,0,0,0</d_retx_th>
<u_retx_th>1,0,0,0</u_retx_th>
</testCase>
</testCaseList>

View File

@@ -0,0 +1,45 @@
<!--
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
-->
<testCaseList>
<htmlTabRef>rfsim-5gnr-2x2-down</htmlTabRef>
<htmlTabName>CleanUp SA Monolithic TDD 2x2 gNB</htmlTabName>
<htmlTabIcon>trash</htmlTabIcon>
<TestCaseRequestedList>
100002
222222
</TestCaseRequestedList>
<TestCaseExclusionList></TestCaseExclusionList>
<testCase id="100002">
<class>UndeployGenObject</class>
<desc>Undeploy all OAI 5G stack</desc>
<yaml_path>yaml_files/5g_rfsimulator_2x2</yaml_path>
</testCase>
<testCase id="222222">
<class>Clean_Test_Server_Images</class>
<desc>Clean Test Images on Test Server</desc>
<test_svr_id>0</test_svr_id>
</testCase>
</testCaseList>

View File

@@ -0,0 +1,124 @@
<!--
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
-->
<testCaseList>
<htmlTabRef>rfsim-5gnr-tdd-u0-25prb</htmlTabRef>
<htmlTabName>Monolithic SA TDD u0 25PRB gNB</htmlTabName>
<htmlTabIcon>wrench</htmlTabIcon>
<repeatCount>1</repeatCount>
<TestCaseRequestedList>
111111
100001
000000
000001
000002
000003
020001
020002
030001
030002
100001
</TestCaseRequestedList>
<TestCaseExclusionList></TestCaseExclusionList>
<testCase id="111111">
<class>Pull_Local_Registry</class>
<desc>Pull Images from Local Registry</desc>
<test_svr_id>0</test_svr_id>
<images_to_pull>oai-gnb oai-nr-ue</images_to_pull>
</testCase>
<testCase id="000000">
<class>DeployGenObject</class>
<desc>Deploy MySql Database</desc>
<yaml_path>yaml_files/5g_rfsimulator_u0_25prb</yaml_path>
<services>mysql</services>
<nb_healthy>1</nb_healthy>
</testCase>
<testCase id="000001">
<class>DeployGenObject</class>
<desc>Deploy OAI 5G CoreNetwork</desc>
<yaml_path>yaml_files/5g_rfsimulator_u0_25prb</yaml_path>
<services>oai-nrf oai-amf oai-smf oai-spgwu oai-ext-dn</services>
<nb_healthy>6</nb_healthy>
</testCase>
<testCase id="000002">
<class>DeployGenObject</class>
<desc>Deploy OAI 5G gNB RF sim SA</desc>
<yaml_path>yaml_files/5g_rfsimulator_u0_25prb</yaml_path>
<services>oai-gnb</services>
<nb_healthy>7</nb_healthy>
</testCase>
<testCase id="000003">
<class>DeployGenObject</class>
<desc>Deploy OAI 5G NR-UE RF sim SA</desc>
<yaml_path>yaml_files/5g_rfsimulator_u0_25prb</yaml_path>
<services>oai-nr-ue</services>
<nb_healthy>8</nb_healthy>
</testCase>
<testCase id="020001">
<class>PingFromContainer</class>
<desc>Ping ext-dn from NR-UE</desc>
<container_name>rfsim5g-oai-nr-ue</container_name>
<options>-I oaitun_ue1 -c 20 192.168.72.135</options>
<loss_threshold>5</loss_threshold>
</testCase>
<testCase id="020002">
<class>PingFromContainer</class>
<desc>Ping NR-UE from ext-dn</desc>
<container_name>rfsim5g-oai-ext-dn</container_name>
<options>-c 20 12.1.1.2</options>
<loss_threshold>5</loss_threshold>
</testCase>
<testCase id="030001">
<class>IperfFromContainer</class>
<desc>Iperf UDP Downlink</desc>
<server_container_name>rfsim5g-oai-nr-ue</server_container_name>
<client_container_name>rfsim5g-oai-ext-dn</client_container_name>
<server_options>-B 12.1.1.2 -u -i 1 -s</server_options>
<client_options>-c 12.1.1.2 -u -i 1 -t 10 -b 3M</client_options>
</testCase>
<testCase id="030002">
<class>IperfFromContainer</class>
<desc>Iperf UDP Uplink</desc>
<server_container_name>rfsim5g-oai-ext-dn</server_container_name>
<client_container_name>rfsim5g-oai-nr-ue</client_container_name>
<server_options>-u -i 1 -s</server_options>
<client_options>-B 12.1.1.2 -c 192.168.72.135 -u -i 1 -t 10 -b 1M</client_options>
</testCase>
<testCase id="100001">
<class>UndeployGenObject</class>
<desc>Undeploy all OAI 5G stack</desc>
<yaml_path>yaml_files/5g_rfsimulator_u0_25prb</yaml_path>
<d_retx_th>1,0,0,0</d_retx_th>
<u_retx_th>1,0,0,0</u_retx_th>
</testCase>
</testCaseList>

View File

@@ -0,0 +1,45 @@
<!--
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
-->
<testCaseList>
<htmlTabRef>rfsim-5gnr-u0-25prb-down</htmlTabRef>
<htmlTabName>CleanUp SA Monolithic TDD u0 25PRB gNB</htmlTabName>
<htmlTabIcon>trash</htmlTabIcon>
<TestCaseRequestedList>
100002
222222
</TestCaseRequestedList>
<TestCaseExclusionList></TestCaseExclusionList>
<testCase id="100002">
<class>UndeployGenObject</class>
<desc>Undeploy all OAI 5G stack</desc>
<yaml_path>yaml_files/5g_rfsimulator_u0_25prb</yaml_path>
</testCase>
<testCase id="222222">
<class>Clean_Test_Server_Images</class>
<desc>Clean Test Images on Test Server</desc>
<test_svr_id>0</test_svr_id>
</testCase>
</testCaseList>

View File

@@ -54,13 +54,14 @@
<testCase id="040000">
<class>Initialize_eNB</class>
<desc>Initialize gNB</desc>
<Initialize_eNB_args>-O ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.conf --sa --usrp-tx-thread-config 1 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --gNBs.[0].min_rxtxtime 5 --log_config.global_log_options level,nocolor,time</Initialize_eNB_args>
<Initialize_eNB_args>-O ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.conf --gNBs.[0].min_rxtxtime 5 --sa --usrp-tx-thread-config 1 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --gNBs.[0].min_rxtxtime 5 --log_config.global_log_options level,nocolor,time</Initialize_eNB_args>
<eNB_instance>0</eNB_instance>
<eNB_serverId>0</eNB_serverId>
<air_interface>nr</air_interface>
<eNB_Trace>yes</eNB_Trace>
<eNB_Stats>yes</eNB_Stats>
<USRP_IPAddress>172.21.19.14</USRP_IPAddress>
<cmd_prefix>numactl --cpunodebind=netdev:ens2f0np0 --membind=netdev:ens2f0np0</cmd_prefix>
</testCase>
<testCase id="000001">

View File

@@ -0,0 +1,301 @@
version: '3.8'
services:
oai-nrf:
container_name: "rfsim5g-oai-nrf"
image: oai-nrf:august-dev
environment:
- NRF_INTERFACE_NAME_FOR_SBI=eth0
- NRF_INTERFACE_PORT_FOR_SBI=80
- NRF_INTERFACE_HTTP2_PORT_FOR_SBI=9090
- NRF_API_VERSION=v1
- INSTANCE=0
- PID_DIRECTORY=/var/run
networks:
public_net:
ipv4_address: 192.168.71.130
volumes:
- ../5g_rfsimulator/nrf-healthcheck.sh:/openair-nrf/bin/nrf-healthcheck.sh
healthcheck:
test: /bin/bash -c "/openair-nrf/bin/nrf-healthcheck.sh"
interval: 10s
timeout: 5s
retries: 5
mysql:
container_name: "rfsim5g-mysql"
image: mysql:5.7
volumes:
- ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql
- ../5g_rfsimulator/mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh
environment:
- TZ=Europe/Paris
- MYSQL_DATABASE=oai_db
- MYSQL_USER=test
- MYSQL_PASSWORD=test
- MYSQL_ROOT_PASSWORD=linux
healthcheck:
test: /bin/bash -c "/tmp/mysql-healthcheck.sh"
interval: 10s
timeout: 5s
retries: 5
networks:
public_net:
ipv4_address: 192.168.71.131
oai-amf:
container_name: "rfsim5g-oai-amf"
image: oai-amf:august-dev
environment:
- TZ=Europe/paris
- INSTANCE=0
- PID_DIRECTORY=/var/run
- MCC=208
- MNC=99
- REGION_ID=128
- AMF_SET_ID=1
- SERVED_GUAMI_MCC_0=208
- SERVED_GUAMI_MNC_0=99
- SERVED_GUAMI_REGION_ID_0=128
- SERVED_GUAMI_AMF_SET_ID_0=1
- SERVED_GUAMI_MCC_1=460
- SERVED_GUAMI_MNC_1=11
- SERVED_GUAMI_REGION_ID_1=10
- SERVED_GUAMI_AMF_SET_ID_1=1
- PLMN_SUPPORT_MCC=208
- PLMN_SUPPORT_MNC=99
- PLMN_SUPPORT_TAC=0x0001
- SST_0=1
- SD_0=0xffffff
- SST_1=1
- SD_1=1
- AMF_INTERFACE_NAME_FOR_NGAP=eth0
- AMF_INTERFACE_NAME_FOR_N11=eth0
- SMF_INSTANCE_ID_0=1
- SMF_FQDN_0=oai-smf
- SMF_IPV4_ADDR_0=0.0.0.0
- SMF_HTTP_VERSION_0=v1
- SELECTED_0=true
- SMF_INSTANCE_ID_1=2
- SMF_FQDN_1=oai-smf
- SMF_IPV4_ADDR_1=0.0.0.0
- SMF_HTTP_VERSION_1=v1
- SELECTED_1=false
- MYSQL_SERVER=192.168.71.131
- MYSQL_USER=root
- MYSQL_PASS=linux
- MYSQL_DB=oai_db
- OPERATOR_KEY=c42449363bbad02b66d16bc975d77cc1
- NRF_IPV4_ADDRESS=192.168.71.130
- NRF_PORT=80
- NF_REGISTRATION=yes
- SMF_SELECTION=yes
- USE_FQDN_DNS=yes
- NRF_API_VERSION=v1
- NRF_FQDN=oai-nrf
- EXTERNAL_AUSF=no
- AUSF_IPV4_ADDRESS=0.0.0.0
- AUSF_PORT=80
- AUSF_API_VERSION=v1
- AUSF_FQDN=localhost
depends_on:
- oai-nrf
- mysql
volumes:
- ../5g_rfsimulator/amf-healthcheck.sh:/openair-amf/bin/amf-healthcheck.sh
healthcheck:
test: /bin/bash -c "/openair-amf/bin/amf-healthcheck.sh"
interval: 10s
timeout: 15s
retries: 5
networks:
public_net:
ipv4_address: 192.168.71.132
oai-smf:
container_name: "rfsim5g-oai-smf"
image: oai-smf:august-dev
environment:
- TZ=Europe/Paris
- INSTANCE=0
- PID_DIRECTORY=/var/run
- SMF_INTERFACE_NAME_FOR_N4=eth0
- SMF_INTERFACE_NAME_FOR_SBI=eth0
- SMF_INTERFACE_PORT_FOR_SBI=80
- SMF_INTERFACE_HTTP2_PORT_FOR_SBI=9090
- SMF_API_VERSION=v1
- DEFAULT_DNS_IPV4_ADDRESS=172.21.3.100
- DEFAULT_DNS_SEC_IPV4_ADDRESS=4.4.4.4
- AMF_IPV4_ADDRESS=0.0.0.0
- AMF_PORT=80
- AMF_API_VERSION=v1
- AMF_FQDN=oai-amf
- UDM_IPV4_ADDRESS=127.0.0.1
- UDM_PORT=80
- UDM_API_VERSION=v1
- UDM_FQDN=localhost
- UPF_IPV4_ADDRESS=192.168.71.134
- UPF_FQDN_0=oai-spgwu
- NRF_IPV4_ADDRESS=192.168.71.130
- NRF_PORT=80
- NRF_API_VERSION=v1
- NRF_FQDN=oai-nrf
- REGISTER_NRF=yes
- DISCOVER_UPF=yes
- USE_FQDN_DNS=yes
- DNN_NI0=oai
- TYPE0=IPv4
- DNN_RANGE0=12.1.1.2 - 12.1.1.127
- NSSAI_SST0=1
- NSSAI_SD0=0xFFFFFF
- SESSION_AMBR_UL0=200Mbps
- SESSION_AMBR_DL0=400Mbps
- DNN_NI2=oai.ipv4
depends_on:
- oai-nrf
- oai-amf
volumes:
- ../5g_rfsimulator/smf-healthcheck.sh:/openair-smf/bin/smf-healthcheck.sh
healthcheck:
test: /bin/bash -c "/openair-smf/bin/smf-healthcheck.sh"
interval: 10s
timeout: 5s
retries: 5
networks:
public_net:
ipv4_address: 192.168.71.133
oai-spgwu:
container_name: "rfsim5g-oai-spgwu"
image: oai-spgwu-tiny:august-dev
environment:
- TZ=Europe/Paris
- PID_DIRECTORY=/var/run
- SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP=eth0
- SGW_INTERFACE_NAME_FOR_SX=eth0
- PGW_INTERFACE_NAME_FOR_SGI=eth0
- NETWORK_UE_NAT_OPTION=yes
- NETWORK_UE_IP=12.1.1.0/24
- SPGWC0_IP_ADDRESS=192.168.71.133
- BYPASS_UL_PFCP_RULES=no
- MCC=208
- MNC=99
- MNC03=099
- TAC=1
- GTP_EXTENSION_HEADER_PRESENT=yes
- GW_ID=1
- REALM=openairinterface.org
- ENABLE_5G_FEATURES=yes
- REGISTER_NRF=yes
- USE_FQDN_NRF=yes
- UPF_FQDN_5G=oai-spgwu
- NRF_IPV4_ADDRESS=192.168.71.130
- NRF_PORT=80
- NRF_API_VERSION=v1
- NRF_FQDN=oai-nrf
- NSSAI_SST_0=1
- NSSAI_SD_0=0xffffff
- DNN_0=oai
depends_on:
- oai-nrf
- oai-smf
cap_add:
- NET_ADMIN
- SYS_ADMIN
cap_drop:
- ALL
privileged: true
volumes:
- ../5g_rfsimulator/spgwu-healthcheck.sh:/openair-spgwu-tiny/bin/spgwu-healthcheck.sh
healthcheck:
test: /bin/bash -c "/openair-spgwu-tiny/bin/spgwu-healthcheck.sh"
interval: 10s
timeout: 5s
retries: 5
networks:
public_net:
ipv4_address: 192.168.71.134
traffic_net:
ipv4_address: 192.168.72.134
oai-ext-dn:
image: ubuntu:bionic
privileged: true
container_name: rfsim5g-oai-ext-dn
entrypoint: /bin/bash -c \
"apt update; apt install -y procps iptables iproute2 iperf iputils-ping;"\
"iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\
"ip route add 12.1.1.0/24 via 192.168.72.134 dev eth0; sleep infinity"
depends_on:
- oai-spgwu
networks:
traffic_net:
ipv4_address: 192.168.72.135
healthcheck:
test: /bin/bash -c "ping -c 2 192.168.72.134"
interval: 10s
timeout: 5s
retries: 5
oai-gnb:
image: oai-gnb:develop
privileged: true
container_name: rfsim5g-oai-gnb
environment:
RFSIMULATOR: server
USE_VOLUMED_CONF: 'yes'
USE_ADDITIONAL_OPTIONS: --sa --rfsim --log_config.global_log_options level,nocolor,time
depends_on:
- oai-ext-dn
networks:
public_net:
ipv4_address: 192.168.71.140
volumes:
- ../../conf_files/gnb.sa.band78.106prb.rfsim.2x2.conf:/opt/oai-gnb/etc/mounted.conf
healthcheck:
test: /bin/bash -c "pgrep nr-softmodem"
interval: 10s
timeout: 5s
retries: 5
oai-nr-ue:
image: oai-nr-ue:develop
privileged: true
container_name: rfsim5g-oai-nr-ue
environment:
RFSIMULATOR: 192.168.71.140
FULL_IMSI: '208990100001100'
FULL_KEY: 'fec86ba6eb707ed08905757b1bb44b8f'
OPC: 'C42449363BBAD02B66D16BC975D77CC1'
DNN: oai
NSSAI_SST: 1
USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 106 --numerology 1 --band 78 -C 3319680000 --nokrnmod --ue-nb-ant-tx 2 --ue-nb-ant-rx 2 --uecap_file /opt/oai-nr-ue/etc/uecap.xml --log_config.global_log_options level,nocolor,time
depends_on:
- oai-gnb
networks:
public_net:
ipv4_address: 192.168.71.150
volumes:
- ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/uecap_ports2.xml:/opt/oai-nr-ue/etc/uecap.xml
healthcheck:
test: /bin/bash -c "pgrep nr-uesoftmodem"
interval: 10s
timeout: 5s
retries: 5
networks:
public_net:
driver: bridge
name: rfsim5g-oai-public-net
ipam:
config:
- subnet: 192.168.71.128/26
driver_opts:
com.docker.network.bridge.name: "rfsim5g-public"
traffic_net:
driver: bridge
name: rfsim5g-oai-traffic-net
ipam:
config:
- subnet: 192.168.72.128/26
driver_opts:
com.docker.network.bridge.name: "rfsim5g-traffic"

View File

@@ -0,0 +1,299 @@
version: '3.8'
services:
oai-nrf:
container_name: "rfsim5g-oai-nrf"
image: oai-nrf:august-dev
environment:
- NRF_INTERFACE_NAME_FOR_SBI=eth0
- NRF_INTERFACE_PORT_FOR_SBI=80
- NRF_INTERFACE_HTTP2_PORT_FOR_SBI=9090
- NRF_API_VERSION=v1
- INSTANCE=0
- PID_DIRECTORY=/var/run
networks:
public_net:
ipv4_address: 192.168.71.130
volumes:
- ../5g_rfsimulator/nrf-healthcheck.sh:/openair-nrf/bin/nrf-healthcheck.sh
healthcheck:
test: /bin/bash -c "/openair-nrf/bin/nrf-healthcheck.sh"
interval: 10s
timeout: 5s
retries: 5
mysql:
container_name: "rfsim5g-mysql"
image: mysql:5.7
volumes:
- ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql
- ../5g_rfsimulator/mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh
environment:
- TZ=Europe/Paris
- MYSQL_DATABASE=oai_db
- MYSQL_USER=test
- MYSQL_PASSWORD=test
- MYSQL_ROOT_PASSWORD=linux
healthcheck:
test: /bin/bash -c "/tmp/mysql-healthcheck.sh"
interval: 10s
timeout: 5s
retries: 5
networks:
public_net:
ipv4_address: 192.168.71.131
oai-amf:
container_name: "rfsim5g-oai-amf"
image: oai-amf:august-dev
environment:
- TZ=Europe/paris
- INSTANCE=0
- PID_DIRECTORY=/var/run
- MCC=208
- MNC=99
- REGION_ID=128
- AMF_SET_ID=1
- SERVED_GUAMI_MCC_0=208
- SERVED_GUAMI_MNC_0=99
- SERVED_GUAMI_REGION_ID_0=128
- SERVED_GUAMI_AMF_SET_ID_0=1
- SERVED_GUAMI_MCC_1=460
- SERVED_GUAMI_MNC_1=11
- SERVED_GUAMI_REGION_ID_1=10
- SERVED_GUAMI_AMF_SET_ID_1=1
- PLMN_SUPPORT_MCC=208
- PLMN_SUPPORT_MNC=99
- PLMN_SUPPORT_TAC=0x0001
- SST_0=1
- SD_0=0xffffff
- SST_1=1
- SD_1=1
- AMF_INTERFACE_NAME_FOR_NGAP=eth0
- AMF_INTERFACE_NAME_FOR_N11=eth0
- SMF_INSTANCE_ID_0=1
- SMF_FQDN_0=oai-smf
- SMF_IPV4_ADDR_0=0.0.0.0
- SMF_HTTP_VERSION_0=v1
- SELECTED_0=true
- SMF_INSTANCE_ID_1=2
- SMF_FQDN_1=oai-smf
- SMF_IPV4_ADDR_1=0.0.0.0
- SMF_HTTP_VERSION_1=v1
- SELECTED_1=false
- MYSQL_SERVER=192.168.71.131
- MYSQL_USER=root
- MYSQL_PASS=linux
- MYSQL_DB=oai_db
- OPERATOR_KEY=c42449363bbad02b66d16bc975d77cc1
- NRF_IPV4_ADDRESS=192.168.71.130
- NRF_PORT=80
- NF_REGISTRATION=yes
- SMF_SELECTION=yes
- USE_FQDN_DNS=yes
- NRF_API_VERSION=v1
- NRF_FQDN=oai-nrf
- EXTERNAL_AUSF=no
- AUSF_IPV4_ADDRESS=0.0.0.0
- AUSF_PORT=80
- AUSF_API_VERSION=v1
- AUSF_FQDN=localhost
depends_on:
- oai-nrf
- mysql
volumes:
- ../5g_rfsimulator/amf-healthcheck.sh:/openair-amf/bin/amf-healthcheck.sh
healthcheck:
test: /bin/bash -c "/openair-amf/bin/amf-healthcheck.sh"
interval: 10s
timeout: 15s
retries: 5
networks:
public_net:
ipv4_address: 192.168.71.132
oai-smf:
container_name: "rfsim5g-oai-smf"
image: oai-smf:august-dev
environment:
- TZ=Europe/Paris
- INSTANCE=0
- PID_DIRECTORY=/var/run
- SMF_INTERFACE_NAME_FOR_N4=eth0
- SMF_INTERFACE_NAME_FOR_SBI=eth0
- SMF_INTERFACE_PORT_FOR_SBI=80
- SMF_INTERFACE_HTTP2_PORT_FOR_SBI=9090
- SMF_API_VERSION=v1
- DEFAULT_DNS_IPV4_ADDRESS=172.21.3.100
- DEFAULT_DNS_SEC_IPV4_ADDRESS=4.4.4.4
- AMF_IPV4_ADDRESS=0.0.0.0
- AMF_PORT=80
- AMF_API_VERSION=v1
- AMF_FQDN=oai-amf
- UDM_IPV4_ADDRESS=127.0.0.1
- UDM_PORT=80
- UDM_API_VERSION=v1
- UDM_FQDN=localhost
- UPF_IPV4_ADDRESS=192.168.71.134
- UPF_FQDN_0=oai-spgwu
- NRF_IPV4_ADDRESS=192.168.71.130
- NRF_PORT=80
- NRF_API_VERSION=v1
- NRF_FQDN=oai-nrf
- REGISTER_NRF=yes
- DISCOVER_UPF=yes
- USE_FQDN_DNS=yes
- DNN_NI0=oai
- TYPE0=IPv4
- DNN_RANGE0=12.1.1.2 - 12.1.1.127
- NSSAI_SST0=1
- NSSAI_SD0=0xFFFFFF
- SESSION_AMBR_UL0=200Mbps
- SESSION_AMBR_DL0=400Mbps
- DNN_NI2=oai.ipv4
depends_on:
- oai-nrf
- oai-amf
volumes:
- ../5g_rfsimulator/smf-healthcheck.sh:/openair-smf/bin/smf-healthcheck.sh
healthcheck:
test: /bin/bash -c "/openair-smf/bin/smf-healthcheck.sh"
interval: 10s
timeout: 5s
retries: 5
networks:
public_net:
ipv4_address: 192.168.71.133
oai-spgwu:
container_name: "rfsim5g-oai-spgwu"
image: oai-spgwu-tiny:august-dev
environment:
- TZ=Europe/Paris
- PID_DIRECTORY=/var/run
- SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP=eth0
- SGW_INTERFACE_NAME_FOR_SX=eth0
- PGW_INTERFACE_NAME_FOR_SGI=eth0
- NETWORK_UE_NAT_OPTION=yes
- NETWORK_UE_IP=12.1.1.0/24
- SPGWC0_IP_ADDRESS=192.168.71.133
- BYPASS_UL_PFCP_RULES=no
- MCC=208
- MNC=99
- MNC03=099
- TAC=1
- GTP_EXTENSION_HEADER_PRESENT=yes
- GW_ID=1
- REALM=openairinterface.org
- ENABLE_5G_FEATURES=yes
- REGISTER_NRF=yes
- USE_FQDN_NRF=yes
- UPF_FQDN_5G=oai-spgwu
- NRF_IPV4_ADDRESS=192.168.71.130
- NRF_PORT=80
- NRF_API_VERSION=v1
- NRF_FQDN=oai-nrf
- NSSAI_SST_0=1
- NSSAI_SD_0=0xffffff
- DNN_0=oai
depends_on:
- oai-nrf
- oai-smf
cap_add:
- NET_ADMIN
- SYS_ADMIN
cap_drop:
- ALL
privileged: true
volumes:
- ../5g_rfsimulator/spgwu-healthcheck.sh:/openair-spgwu-tiny/bin/spgwu-healthcheck.sh
healthcheck:
test: /bin/bash -c "/openair-spgwu-tiny/bin/spgwu-healthcheck.sh"
interval: 10s
timeout: 5s
retries: 5
networks:
public_net:
ipv4_address: 192.168.71.134
traffic_net:
ipv4_address: 192.168.72.134
oai-ext-dn:
image: ubuntu:bionic
privileged: true
container_name: rfsim5g-oai-ext-dn
entrypoint: /bin/bash -c \
"apt update; apt install -y procps iptables iproute2 iperf iputils-ping;"\
"iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\
"ip route add 12.1.1.0/24 via 192.168.72.134 dev eth0; sleep infinity"
depends_on:
- oai-spgwu
networks:
traffic_net:
ipv4_address: 192.168.72.135
healthcheck:
test: /bin/bash -c "ping -c 2 192.168.72.134"
interval: 10s
timeout: 5s
retries: 5
oai-gnb:
image: oai-gnb:develop
privileged: true
container_name: rfsim5g-oai-gnb
environment:
RFSIMULATOR: server
USE_VOLUMED_CONF: 'yes'
USE_ADDITIONAL_OPTIONS: --sa --rfsim --log_config.global_log_options level,nocolor,time
depends_on:
- oai-ext-dn
networks:
public_net:
ipv4_address: 192.168.71.140
volumes:
- ../../conf_files/gnb.sa.band66.u0.25prb.rfsim.conf:/opt/oai-gnb/etc/mounted.conf
healthcheck:
test: /bin/bash -c "pgrep nr-softmodem"
interval: 10s
timeout: 5s
retries: 5
oai-nr-ue:
image: oai-nr-ue:develop
privileged: true
container_name: rfsim5g-oai-nr-ue
environment:
RFSIMULATOR: 192.168.71.140
FULL_IMSI: '208990100001100'
FULL_KEY: 'fec86ba6eb707ed08905757b1bb44b8f'
OPC: 'C42449363BBAD02B66D16BC975D77CC1'
DNN: oai
NSSAI_SST: 1
USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 25 --numerology 0 --band 66 -C 2152250000 --CO -400000000 --ssb 48 --nokrnmod --nokrnmod --log_config.global_log_options level,nocolor,time
depends_on:
- oai-gnb
networks:
public_net:
ipv4_address: 192.168.71.150
healthcheck:
test: /bin/bash -c "pgrep nr-uesoftmodem"
interval: 10s
timeout: 5s
retries: 5
networks:
public_net:
driver: bridge
name: rfsim5g-oai-public-net
ipam:
config:
- subnet: 192.168.71.128/26
driver_opts:
com.docker.network.bridge.name: "rfsim5g-public"
traffic_net:
driver: bridge
name: rfsim5g-oai-traffic-net
ipam:
config:
- subnet: 192.168.72.128/26
driver_opts:
com.docker.network.bridge.name: "rfsim5g-traffic"

View File

@@ -461,7 +461,7 @@ install_soapy_from_source(){
(
cd /tmp
echo "Downloading SoapySDR"
rm -rf /tmp/soapysdr
rm -rf /tmp/SoapySDR
git clone -b soapy-sdr-0.7.0 --single-branch https://github.com/pothosware/SoapySDR.git
cd SoapySDR
#git checkout tags/release_003_010_001_001
@@ -474,7 +474,7 @@ install_soapy_from_source(){
$SUDO ldconfig
cd /tmp
echo "Downloading SoapyRemote"
rm -rf /tmp/soapyremote
rm -rf /tmp/SoapyRemote
git clone -b soapy-remote-0.5.0 --single-branch https://github.com/pothosware/SoapyRemote.git
cd SoapyRemote
#git checkout tags/release_003_010_001_001
@@ -838,21 +838,6 @@ install_simde_from_source(){
cd /tmp/simde
# brute force copy into /usr/include
$SUDO \cp -rv ../simde /usr/include
$SUDO patch /usr/include/simde/x86/avx.h << FIN
--- /usr/include/simde/x86/avx.h.old 2022-10-03 19:17:39.828223432 +0200
+++ /usr/include/simde/x86/avx.h 2022-10-05 16:19:55.086019445 +0200
@@ -3643,6 +3643,9 @@
simde__m256i simde_mm256_insertf128_si256(simde__m256i a, simde__m128i b, int im
return simde__m256i_from_private(a_);
}
+#if defined(SIMDE_X86_AVX_NATIVE)
+ #define simde_mm256_insertf128_si256(a, b, imm8) _mm256_insertf128_si256(a, b, imm8)
+#endif
#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES)
#undef _mm256_insertf128_si256
#define _mm256_insertf128_si256(a, b, imm8) simde_mm256_insertf128_si256(a, b, imm8)
FIN
}
#################################################

155
common/platform_constants.h Normal file
View File

@@ -0,0 +1,155 @@
/*
* 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
*/
/*
platform_constants.h
-------------------
AUTHOR : Lionel GAUTHIER and Navid Nikaein
COMPANY : EURECOM
EMAIL : Lionel.Gauthier@eurecom.fr
***************************************************************************/
#ifndef __PLATFORM_CONSTANTS_H__
#define __PLATFORM_CONSTANTS_H__
#include "LTE_asn_constant.h"
#include "NR_asn_constant.h"
#define NR_MAXDRB 14
#ifdef JUMBO_FRAME
#define NL_MAX_PAYLOAD 18000 /* this should cover the max mtu size*/
#else
#define NL_MAX_PAYLOAD 9000 /* this should cover the max mtu size*/
#endif
#ifdef LARGE_SCALE
#define NB_MODULES_MAX 128
#define NB_NODE_MAX 128
#else
#define NB_MODULES_MAX 32
#define NB_NODE_MAX 32
#endif
#ifdef JUMBO_FRAME
#define MAX_IP_PACKET_SIZE 10000 // 9000
#else
#if defined(OAI_NW_DRIVER_TYPE_ETHERNET)
/* SR: When using ethernet network driver the packet size is 1512 :
* 1500 bytes IP packet + 14 bytes ethernet header
*/
#define MAX_IP_PACKET_SIZE 1514
#else
#define MAX_IP_PACKET_SIZE 1500 // 3000
#endif
#endif
// overwrite the previous deinitions
#define MAX_MODULES NB_MODULES_MAX
#define MAX_NR_RRC_UE_CONTEXTS 64
#ifndef UE_EXPANSION
#ifdef LARGE_SCALE
#define MAX_MOBILES_PER_ENB 128
#define MAX_MOBILES_PER_ENB_NB_IoT 128
#define MAX_MOBILES_PER_GNB 128
#define MAX_eNB 2
#define MAX_gNB 2
#else
#define MAX_MOBILES_PER_ENB 40
#define MAX_MOBILES_PER_ENB_NB_IoT 40
#define MAX_MOBILES_PER_GNB 16
#define MAX_eNB 2
#define MAX_gNB 2
#endif
#else
#define MAX_MOBILES_PER_ENB 256
#define MAX_MOBILES_PER_ENB_NB_IoT 256
#define MAX_MOBILES_PER_GNB 256
#define MAX_eNB 2
#define MAX_gNB 2
#endif
#define NUMBER_OF_NR_UCI_STATS_MAX 16
#define MAX_MANAGED_ENB_PER_MOBILE 2
#define MAX_MANAGED_GNB_PER_MOBILE 2
/// NB-IOT
#define NB_RB_MAX_NB_IOT (LTE_maxDRB_NB_r13 + 3) // MP: NB_IoT --> 2(DRB)+3(SRBs - 2 is not used) = 5
#define DEFAULT_RAB_ID 1
#define NB_RB_MAX (LTE_maxDRB + 3) /* was 11, now 14, maxDRB comes from asn1_constants.h, + 3 because of 3 SRB, one invisible id 0, then id 1 and 2 */
#define NR_NB_RB_MAX (NR_maxDRB + 3)
#define NGAP_MAX_PDU_SESSION (256) /* As defined in TS 38.413 9.2.1.1 Range Bound for PDU Sessions. */
#define NGAP_MAX_DRBS_PER_UE (32) /* As defined in TS 38.413 9.2.1.1 - maxnoofDRBs */
#define NB_RB_MBMS_MAX (LTE_maxSessionPerPMCH * LTE_maxServiceCount)
#define NB_RAB_MAX LTE_maxDRB /* was 8, now 11 */
#define RAB_SHIFT1 9
#define RAB_SHIFT2 3
//#define RAB_OFFSET 0x0007
#define RAB_OFFSET 0x000F
#define RAB_OFFSET1 0x7E00
#define RAB_OFFSET2 0x01F8
#define DIR_OFFSET 0x8000
#define DIR_SHIFT 15
#define CH_OFFSET 0x0004
#define CH_SHIFT 2
// RLC Entity
#define RLC_TX_MAXSIZE 10000000
#define RLC_RX_MAXSIZE 10000000
// RLC_AM_SEND_MRW
#define SEND_MRW_OFF 15
#define SEND_MRW_ON 240
// RLC_SEGMENTATION_INDICATION
#define SEGMENTATION_NOT_ALLOWED 0
#define SEGMENTATION_ALLOWED 1
// RLC_DELIVERY_OF_ERRONEOUS_SDU
#define DELIVERY_OF_ERRONEOUS_SDU_NO 0
#define DELIVERY_OF_ERRONEOUS_SDU_YES 1
#define DELIVERY_OF_ERRONEOUS_SDU_NO_DETECT 2
// CBA constant
#define NUM_MAX_CBA_GROUP 4
#ifndef __cplusplus
#ifndef NULL
#define NULL 0
#endif
#ifndef null
#define null 0
#endif
#endif
#define UNUSED_PARAM_MBMS_SESSION_ID 0
#define UNUSED_PARAM_MBMS_SERVICE_ID 0
#define printk printf
#define UNUSED_VARIABLE(vARIABLE) (void)(vARIABLE)
#endif /* __PLATFORM_CONSTANTS_H__ */

View File

@@ -34,7 +34,7 @@
#define __RAN_CONTEXT_H__
#include <pthread.h>
#include "COMMON/platform_constants.h"
#include "common/platform_constants.h"
#include "PHY/defs_eNB.h"
#include "PHY/types.h"
#include "PHY/impl_defs_top.h"
@@ -110,4 +110,6 @@ typedef struct {
} RAN_CONTEXT_t;
extern RAN_CONTEXT_t RC;
#define NB_eNB_INST RC.nb_inst
#endif

View File

@@ -0,0 +1,139 @@
# Netconf Server for O1 interface
## Specification
For this part please look into the [specification](../../../../specification/README.md) folder.
## Configuration
Example
```
o1Config :
{
nfNodeId = "gnb-test01";
netconfUsername = "netconf";
netconfPassword = "netconf!";
netconfPort = 58300;
netconfHost = "192.168.5.207";
vesUrl = "https://dcae-ves-collector:8443/eventListener/v7";
vesBasicAuthUsername = "sample1";
vesBasicAuthPassword = "sample1";
vesNfVendorName = "OpenAirInterface";
vesNfNamingCode = "OGNB";
vesOamIpv6 = "";
vesFtpServerPort = 21;
vesFtpServerListenAddress = "0.0.0.0";
vesFtpServerUrl = "ftp://netconfr:netconf@gnodeb01-test:21";
demoAlarmingInterval = 30;
};
```
Properties:
| property | type | mandatory | description |
| -------- | ---- | --------- | ----------- |
| nfNodeId | string |true | network function node-id to get mounted via netconf |
| netconfUsername | string | true | username to access netconf server(at the moment hardcoded)|
| netconfPassword | string | true | password to access netconf server(at the moment hardcoded)|
| netconfPort | uint_16 | true | port to listen on for netconf server(at the moment hardcoded to 830).|
| netconfHost | string | true | |
| vesUrl| string | false | url to send VES messages to. If not set, complete VES functionality is disabled |
| vesBasicAuthUsername| string | if vesUrl | basic auth username for the VES collector |
| vesBasicAuthPassword | string | if vesUrl | basic auth password for the VES collector |
| vesNfVendorName | string | if vesUrl | vendor name to be sent in the VES messages |
| vesNfNamingCode | string | if vesUrl | nfNamingCode to be sent in the VES messages |
| vesOamIpv6 | string | false | |
| vesFtpServerPort | uint_16 | false ||
| vesFtpServerListenAddress| string | false | |
| vesFtpServerUrl | string | false | |
| demoAlarmingInterval | unit_16| false | interval in seconds to send and clear a demo alarm sent via VES |
The VES functionality can be disabled by just not setting the ```vesUrl```. With this all of the ```vesXXX``` properties are obsolete.
## Software Architecture
```
|----------------------------------------------------------------------------------------------|
| OAI container | Netopeer2 server | | FTPes-server | |
| |--------------------| |------------------| |
| | | |
| | | |
| |--------------------| | |
| | sysrepo | | |
| | (datastore) | | |
| |--------------------| | |
| gnb.conf | | |
| | | | |
| ------------------------------------------------------------------------------------------ |
| | nr-softmodem | | | |
| | | | | |
| | read-oper- edit-config- | |
| | callbacks callbacks | |
| | ves-client | |
| | | |
| | | |
| | | |
| | | |
| | | |
|----------------------------------------------------------------------------------------------|
```
## Minimal Deployment Architecture
This picture is only showing the directly connected components to the OAI gNodeB. This is NOT a complete deployment since there a some more components needed to make everything work together.
```
smo-network-----|------------------------------------------------------------------------
| | |
|-------------------| |--------------------| |-----------------|
| SDNC | | VES-Collector | | FileCollector |
| | | | | |
|-------------------| |--------------------| |-----------------|
| | |
oam-network-----|-------------------------|----------------------|-------------------
| | |
|--------------------------------------------------------------------|
| | NETCONF-Server | | VES-Client | | FTPes-Server | |
| |----------------| |------------| |--------------| |
| |
| OAI gNodeB |
| |
|--------------------------------------------------------------------|
```
## Integration Deployment And Usage
for this documentation please check the [integration](../../../../integration/README.md) folder.
### PNF Registration
By starting up the gNodeB should automatically sends a pnfRegistration message to the VES-Collector. This message will be received by the SDNC and creates then a NETCONF connection between the itself and the device.
### PNF Alarming
If the ```demoAlarmingInterval``` is set, every n seconds there will be a alarm notification sent via VES to raise and clear the demoAlarm.
### PNF Performance Data
To transmit performance data to the ONAP system there is a ```file-ready``` event sent to the VES-Collector which contains the information of the file to transmit. The will be collected by the File-Collector via FTPes or SFTP.
For demo purpose we have now created a trigger inside which is sending such a file ready event. To do this you have to do the following steps.
* Open the ConfigApp with the gNodeB
```
http://localhost:8080/odlux/index.html#/configuration/{node-id}/_3gpp-common-managed-element:ManagedElement[OAI%20gNodeB]
```
* _3gpp-common-managed-element > Attributes
* click edit on the top right corner
* set the userLabel property to ```pmData``` and click save to trigger the ```file-ready``` event once.
* afterwards you have to reset it to ```disabled``` and back if you want to trigger it again
* up to now the file and its data is hardcoded. But it shows that the workflow is working

View File

@@ -0,0 +1,41 @@
#pragma once
// constants to set
#define MANAGED_ELEMENT_ID "OAI gNodeB"
#define MANAGED_ELEMENT_GNBDUFUNCTION_ID "OAI-DU"
#define MANAGED_ELEMENT_GNBCUCPFUNCTION_ID "OAI-CUCP"
#define MANAGED_ELEMENT_GNBCUUPFUNCTION_ID "OAI-CUUP"
#define MANAGED_ELEMENT_GNBDUFUNCTION_BWDUPLINK_NAME "Uplink"
#define MANAGED_ELEMENT_GNBDUFUNCTION_BWDDOWNLINK_NAME "Downlink"
// generated xpaths out of the constants
#define XPATH_MANAGED_ELEMENT_BASE1 "/_3gpp-common-managed-element:ManagedElement[id='" MANAGED_ELEMENT_ID
#define XPATH_MANAGED_ELEMENT_BASE XPATH_MANAGED_ELEMENT_BASE1 "']"
#define XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BASE1 XPATH_MANAGED_ELEMENT_BASE "/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='"
#define XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BASE2 XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BASE1 MANAGED_ELEMENT_GNBDUFUNCTION_ID
#define XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BASE XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BASE2 "']"
#define XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPDOWNLINK_BASE1 XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BASE "/_3gpp-nr-nrm-bwp:BWP[id='"
#define XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPDOWNLINK_BASE2 XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPDOWNLINK_BASE1 MANAGED_ELEMENT_GNBDUFUNCTION_BWDDOWNLINK_NAME
#define XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPDOWNLINK_BASE XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPDOWNLINK_BASE2 "']"
#define XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPDOWNLINK_ATTRIBUTES_BASE XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPDOWNLINK_BASE "/attributes"
#define XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPDOWNLINK_ATTRIBUTES_BWPCONTEXT XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPDOWNLINK_ATTRIBUTES_BASE "/bwpContext"
#define XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPDOWNLINK_ATTRIBUTES_ISINITIALBWP XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPDOWNLINK_ATTRIBUTES_BASE "/isInitialBwp"
#define XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPDOWNLINK_ATTRIBUTES_SUBCARRIERSPACING XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPDOWNLINK_ATTRIBUTES_BASE "/subCarrierSpacing"
#define XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPDOWNLINK_ATTRIBUTES_CYCLICPREFIX XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPDOWNLINK_ATTRIBUTES_BASE "/cyclicPrefix"
#define XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPDOWNLINK_ATTRIBUTES_STARTRB XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPDOWNLINK_ATTRIBUTES_BASE "/startRB"
#define XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPDOWNLINK_ATTRIBUTES_NUMBEROFRBS XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPDOWNLINK_ATTRIBUTES_BASE "/numberOfRBs"
#define XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPUPLINK_BASE1 XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BASE "/_3gpp-nr-nrm-bwp:BWP[id='"
#define XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPUPLINK_BASE2 XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPUPLINK_BASE1 MANAGED_ELEMENT_GNBDUFUNCTION_BWDUPLINK_NAME
#define XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPUPLINK_BASE XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPUPLINK_BASE2 "']"
#define XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPUPLINK_ATTRIBUTES_BASE XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPUPLINK_BASE "/attributes"
#define XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPUPLINK_ATTRIBUTES_BWPCONTEXT XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPUPLINK_ATTRIBUTES_BASE "/bwpContext"
#define XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPUPLINK_ATTRIBUTES_ISINITIALBWP XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPUPLINK_ATTRIBUTES_BASE "/isInitialBwp"
#define XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPUPLINK_ATTRIBUTES_SUBCARRIERSPACING XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPUPLINK_ATTRIBUTES_BASE "/subCarrierSpacing"
#define XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPUPLINK_ATTRIBUTES_CYCLICPREFIX XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPUPLINK_ATTRIBUTES_BASE "/cyclicPrefix"
#define XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPUPLINK_ATTRIBUTES_STARTRB XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPUPLINK_ATTRIBUTES_BASE "/startRB"
#define XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPUPLINK_ATTRIBUTES_NUMBEROFRBS XPATH_MANAGED_ELEMENT_GNBDUFUNCTION_BWPUPLINK_ATTRIBUTES_BASE "/numberOfRBs"

View File

@@ -0,0 +1,114 @@
#include "netconf.h"
#include "o1config.h"
#include "netconf_session.h"
#include "netconf_log.h"
#include "utils.h"
#include "ves.h"
#include "ves_demo_alarm.h"
int netconf_init(void) {
int rc = 0;
//get configuration
o1_config_t config = {0};
rc = o1_config_read(&config);
if(rc != 0) {
netconf_log_error("o1_config_read() failed");
goto failed;
}
o1_config_print(&config);
//init netconf
sr_log_stderr(SR_LL_WRN);
rc = netconf_session_init();
if(rc != 0) {
netconf_log_error("netconf_session_init() failed");
goto failed;
}
//init ves
if (o1_config_is_ves_enabled(&config)) {
ves_header_t data = {
hostname: get_hostname(),
nf_naming_code: config.ves_nf_naming_code,
nf_vendor_name: config.ves_nf_vendor_name,
pnf_id: config.netconf_node_id
};
ves_config_t ves_config = {
url: config.ves_url,
username: config.ves_basicauth_username,
password: config.ves_basicauth_password
};
rc = ves_init(&ves_config, &data);
free(data.hostname);
if(rc != 0) {
netconf_log_error("ves_init() failed");
goto failed;
}
ves_registration_data_t pnf_reg_data= {
pnf_username: config.netconf_username,
pnf_password: config.netconf_password,
pnf_ip_v4_address: config.netconf_host,
pnf_ip_v6_address: config.ves_oam_ipv6,
pnf_port: config.netconf_port,
mac_address: "12:34:56:78:90:AB", //TODO get it programatically
vendor: config.ves_nf_vendor_name,
model: "testModel",
type: "gNB",
is_tls: false
};
rc = ves_pnf_registration_execute(&pnf_reg_data);
if(rc != 0) {
netconf_log_error("ves_pnf_registration_execute() failed");
goto failed;
}
if(o1_config_is_demoalarming_enabled(&config)){
ves_demo_alarm_start(&config);
}
}
rc = netconf_disable_nacm(netconf_session_running);
if(rc != 0) {
netconf_log("netconf_disable_nacm() failed\n");
}
printf("netconf_demo_populate()...\n");
rc = netconf_demo_populate();
if(rc != 0) {
netconf_log_error("netconf_demo_subscribe_edit_change() failed");
}
printf("netconf_demo_subscribe_edit_change()...\n");
rc = netconf_demo_subscribe_edit_change();
if(rc != 0) {
netconf_log_error("netconf_demo_subscribe_edit_change() failed");
}
printf("netconf_demo_subscribe_operational()...\n");
rc = netconf_demo_subscribe_operational();
if(rc != 0) {
netconf_log_error("netconf_demo_subscribe_operational() failed");
}
o1_config_free(&config);
return 0;
failed:
ves_free();
o1_config_free(&config);
return 1;
}
int netconf_free(void) {
ves_free();
netconf_session_free();
return 0;
}

View File

@@ -0,0 +1,11 @@
#pragma once
#include <sysrepo.h>
int netconf_init(void);
int netconf_free(void);
int netconf_disable_nacm(sr_session_ctx_t *session);
int netconf_demo_populate(void);
int netconf_demo_subscribe_edit_change();
int netconf_demo_subscribe_operational();

View File

@@ -0,0 +1,38 @@
set(NETCONFROOT ${OPENAIR_DIR}/common/utils/netconf )
set(NETCONFROOTSRV_SOURCE
${NETCONFROOT}/netconf.c
${NETCONFROOT}/netconf_demos.c
${NETCONFROOT}/netconf_session.c
${NETCONFROOT}/o1config.c
${NETCONFROOT}/utils.c
${NETCONFROOT}/ves.c
)
add_library(netconfsrv MODULE ${NETCONFSRV_SOURCE} )
target_link_libraries(netconfsrv PRIVATE yang sysrepo )
foreach(NETCONFLIB enb gnb 4Gue 5Gue)
set(NETCONFLIB_SRCS "")
foreach(NETCONFLIB_ASRC measurements phycmd)
set(NETCONFLIB_SRC ${OPENAIR_DIR}/common/utils/netconfsrv/netconfsrv_${NETCONFLIB}_${NETCONFLIB_ASRC}.c)
if (EXISTS ${NETCONFLIB_SRC})
set( NETCONFLIB_SRCS "${NETCONFLIB_SRC};${NETCONFLIB_SRCS}")
endif()
endforeach()
if(NOT "${NETCONFLIB_SRCS}" STREQUAL "")
message("Add ${NETCONFLIB} specific telnet functions in libnetconfsrv_${NETCONFLIB}.so")
add_library(netconfsrv_${NETCONFLIB} MODULE ${NETCONFLIB_SRCS} )
add_dependencies(netconfsrv netconfsrv_${NETCONFLIB})
target_link_libraries(netconfsrv_${NETCONFLIB} PRIVATE asn1_nr_rrc asn1_lte_rrc)
install(TARGETS netconfsrv_${NETCONFLIB} DESTINATION bin)
else()
message("No specific netconf functions for ${NETCONFLIB}")
endif()
endforeach()
install(TARGETS netconfsrv DESTINATION bin)
if (EXISTS "${OPENAIR_CMAKE}/ran_build/build" AND IS_DIRECTORY "${OPENAIR_CMAKE}/ran_build/build")
install(TARGETS netconfsrv DESTINATION ${OPENAIR_CMAKE}/ran_build/build)
endif (EXISTS "${OPENAIR_CMAKE}/ran_build/build" AND IS_DIRECTORY "${OPENAIR_CMAKE}/ran_build/build")

View File

@@ -0,0 +1,353 @@
#include "netconf.h"
#include "netconf_log.h"
#include "netconf_session.h"
#include "ves.h"
#include <sysrepo.h>
#include <libyang/libyang.h>
#include <stdint.h>
static int test_edit_callback(sr_session_ctx_t *session, uint32_t sub_id, const char *module_name, const char *xpath, sr_event_t event, uint32_t request_id, void *private_data);
static int test_oper_callback(sr_session_ctx_t *session, uint32_t sub_id, const char *module_name, const char *path, const char *request_xpath, uint32_t request_id, struct lyd_node **parent, void *private_data);
int netconf_disable_nacm(sr_session_ctx_t *session) {
#define IETF_NETCONF_ACM_ENABLE_NACM_SCHEMA_XPATH "/ietf-netconf-acm:nacm/enable-nacm"
#define IETF_NETCONF_ACM_GROUPS_SCHEMA_XPATH "/ietf-netconf-acm:nacm/groups"
#define IETF_NETCONF_ACM_RULE_LIST_SCHEMA_XPATH "/ietf-netconf-acm:nacm/rule-list"
int rc = 0;
rc = sr_set_item_str(session, IETF_NETCONF_ACM_ENABLE_NACM_SCHEMA_XPATH, "true", 0, 0);
if(rc != SR_ERR_OK) {
netconf_log_error("sr_set_item_str() failed");
goto failed;
}
rc = sr_set_item_str(session, IETF_NETCONF_ACM_GROUPS_SCHEMA_XPATH"/group[name='sudo']/user-name", "netconf", 0, 0);
if(rc != SR_ERR_OK) {
netconf_log_error("sr_set_item_str() failed");
goto failed;
}
rc = sr_set_item_str(session, IETF_NETCONF_ACM_RULE_LIST_SCHEMA_XPATH"[name='sudo-rules']/group", "sudo", 0, 0);
if(rc != SR_ERR_OK) {
netconf_log_error("sr_set_item_str() failed");
goto failed;
}
rc = sr_set_item_str(session, IETF_NETCONF_ACM_RULE_LIST_SCHEMA_XPATH"[name='sudo-rules']/rule[name='allow-all-sudo']/module-name", "*", 0, 0);
if(rc != SR_ERR_OK) {
netconf_log_error("sr_set_item_str() failed");
goto failed;
}
rc = sr_set_item_str(session, IETF_NETCONF_ACM_RULE_LIST_SCHEMA_XPATH"[name='sudo-rules']/rule[name='allow-all-sudo']/path", "/", 0, 0);
if(rc != SR_ERR_OK) {
netconf_log_error("sr_set_item_str() failed");
goto failed;
}
rc = sr_set_item_str(session, IETF_NETCONF_ACM_RULE_LIST_SCHEMA_XPATH"[name='sudo-rules']/rule[name='allow-all-sudo']/access-operations", "*", 0, 0);
if(rc != SR_ERR_OK) {
netconf_log_error("sr_set_item_str() failed");
goto failed;
}
rc = sr_set_item_str(session, IETF_NETCONF_ACM_RULE_LIST_SCHEMA_XPATH"[name='sudo-rules']/rule[name='allow-all-sudo']/action", "permit", 0, 0);
if(rc != SR_ERR_OK) {
netconf_log_error("sr_set_item_str() failed");
goto failed;
}
rc = sr_set_item_str(session, IETF_NETCONF_ACM_RULE_LIST_SCHEMA_XPATH"[name='sudo-rules']/rule[name='allow-all-sudo']/comment", "Corresponds all the rules under the sudo group as defined in O-RAN.WG4.MP.0-v05.00", 0, 0);
if(rc != SR_ERR_OK) {
netconf_log_error("sr_set_item_str() failed");
goto failed;
}
rc = sr_apply_changes(session, 0);
if(rc != SR_ERR_OK) {
netconf_log_error("sr_apply_changes() failed");
goto failed;
}
return 0;
failed:
sr_discard_changes(session);
return 1;
}
int netconf_demo_populate(void) {
int rc = 0;
const char *list_running[] = {
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']",
0,
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='OAI-DU']",
0,
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='OAI-DU']/attributes/vnfParametersList[vnfInstanceId='SDNR_NODE_ID']",
0,
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='OAI-DU']/_3gpp-nr-nrm-bwp:BWP[id='Downlink']",
0,
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='OAI-DU']/_3gpp-nr-nrm-bwp:BWP[id='Downlink']/attributes/bwpContext",
"DL",
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='OAI-DU']/_3gpp-nr-nrm-bwp:BWP[id='Downlink']/attributes/isInitialBwp",
"INITIAL",
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='OAI-DU']/_3gpp-nr-nrm-bwp:BWP[id='Downlink']/attributes/subCarrierSpacing",
"60",
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='OAI-DU']/_3gpp-nr-nrm-bwp:BWP[id='Downlink']/attributes/cyclicPrefix",
"NORMAL",
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='OAI-DU']/_3gpp-nr-nrm-bwp:BWP[id='Downlink']/attributes/startRB",
"0",
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='OAI-DU']/_3gpp-nr-nrm-bwp:BWP[id='Downlink']/attributes/numberOfRBs",
"2",
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='OAI-DU']/_3gpp-nr-nrm-bwp:BWP[id='Downlink']/ThresholdMonitor[id='Threshold']",
0,
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='OAI-DU']/_3gpp-nr-nrm-bwp:BWP[id='Downlink']/ThresholdMonitor[id='Threshold']/attributes/administrativeState",
"UNLOCKED",
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='OAI-DU']/_3gpp-nr-nrm-bwp:BWP[id='Uplink']",
0,
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='OAI-DU']/_3gpp-nr-nrm-bwp:BWP[id='Uplink']/attributes/bwpContext",
"UL",
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='OAI-DU']/_3gpp-nr-nrm-bwp:BWP[id='Uplink']/attributes/isInitialBwp",
"INITIAL",
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='OAI-DU']/_3gpp-nr-nrm-bwp:BWP[id='Uplink']/attributes/subCarrierSpacing",
"15",
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='OAI-DU']/_3gpp-nr-nrm-bwp:BWP[id='Uplink']/attributes/cyclicPrefix",
"EXTENDED",
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='OAI-DU']/_3gpp-nr-nrm-bwp:BWP[id='Uplink']/attributes/startRB",
"0",
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='OAI-DU']/_3gpp-nr-nrm-bwp:BWP[id='Uplink']/attributes/numberOfRBs",
"2",
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='OAI-DU']/_3gpp-nr-nrm-bwp:BWP[id='Uplink']/ThresholdMonitor[id='Threshold']",
0,
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='OAI-DU']/_3gpp-nr-nrm-bwp:BWP[id='Uplink']/ThresholdMonitor[id='Threshold']/attributes/administrativeState",
"UNLOCKED",
//alarms
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/AlarmList[id='CUUP-alarms']",
0,
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/AlarmList[id='CUUP-alarms']/attributes/administrativeState",
"UNLOCKED",
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/AlarmList[id='CUUP-alarms']/attributes/alarmRecords[alarmId='alarm-id-01']",
0,
//mandatory nodes
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/attributes/priorityLabel",
"5",
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='OAI-DU']/attributes/priorityLabel",
"6",
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='OAI-DU']/attributes/gNBId",
"7",
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='OAI-DU']/attributes/gNBIdLength",
"23",
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='OAI-DU']/attributes/gNBDUId",
"8",
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='OAI-DU']/attributes/vnfParametersList[vnfInstanceId='SDNR_NODE_ID']/autoScalable",
"true",
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='OAI-DU']/_3gpp-nr-nrm-bwp:BWP[id='Downlink']/attributes/priorityLabel",
"9",
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='OAI-DU']/_3gpp-nr-nrm-bwp:BWP[id='Uplink']/attributes/priorityLabel",
"10",
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='OAI-DU']/_3gpp-nr-nrm-bwp:BWP[id='Downlink']/ThresholdMonitor[id='Threshold']/attributes/thresholdInfoList[idx='0']/thresholdLevel",
"12",
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='OAI-DU']/_3gpp-nr-nrm-bwp:BWP[id='Uplink']/ThresholdMonitor[id='Threshold']/attributes/thresholdInfoList[idx='0']/thresholdLevel",
"13",
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='OAI-DU']/_3gpp-nr-nrm-bwp:BWP[id='Downlink']/ThresholdMonitor[id='Threshold']/attributes/thresholdInfoList[idx='0']/thresholdDirection",
"UP",
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='OAI-DU']/_3gpp-nr-nrm-bwp:BWP[id='Uplink']/ThresholdMonitor[id='Threshold']/attributes/thresholdInfoList[idx='0']/thresholdDirection",
"UP",
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='OAI-DU']/_3gpp-nr-nrm-bwp:BWP[id='Downlink']/ThresholdMonitor[id='Threshold']/attributes/thresholdInfoList[idx='0']/thresholdValue",
"14",
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='OAI-DU']/_3gpp-nr-nrm-bwp:BWP[id='Uplink']/ThresholdMonitor[id='Threshold']/attributes/thresholdInfoList[idx='0']/thresholdValue",
"15",
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='OAI-DU']/_3gpp-nr-nrm-bwp:BWP[id='Downlink']/ThresholdMonitor[id='Threshold']/attributes/monitorGranularityPeriod",
"16",
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='OAI-DU']/_3gpp-nr-nrm-bwp:BWP[id='Uplink']/ThresholdMonitor[id='Threshold']/attributes/monitorGranularityPeriod",
"17",
0
};
const char *list_operational[] = {
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction[id='OAI-DU']/attributes/rimRSReportConf[reportInterval='1000']/reportIndicator",
"DISABLED",
//alarms
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/AlarmList[id='CUUP-alarms']/attributes/operationalState",
"ENABLED",
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/AlarmList[id='CUUP-alarms']/attributes/numOfAlarmRecords",
"1",
"/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/AlarmList[id='CUUP-alarms']/attributes/lastModification",
"2023-02-07T08:44:26.0Z",
0
};
const char **l = list_running;
while(*l) {
const char *xpath = *l;
const char *value = *(l + 1);
netconf_log("[config] populating %s with %s.. ", xpath, value);
rc = sr_set_item_str(netconf_session_running, xpath, value, 0, 0);
if(rc != SR_ERR_OK) {
netconf_log_error("error on line %d", __LINE__);
}
l += 2;
}
rc = sr_apply_changes(netconf_session_running, 0);
if(rc != SR_ERR_OK) {
netconf_log_error("error on sr_apply_changes line %d", __LINE__);
}
l = list_operational;
while(*l) {
const char *xpath = *l;
const char *value = *(l + 1);
netconf_log("[oper] populating %s with %s.. ", xpath, value);
rc = sr_set_item_str(netconf_session_operational, xpath, value, 0, 0);
if(rc != SR_ERR_OK) {
netconf_log_error("error on line %d", __LINE__);
}
l += 2;
}
rc = sr_apply_changes(netconf_session_operational, 0);
if(rc != SR_ERR_OK) {
netconf_log_error("error on sr_apply_changes line %d", __LINE__);
}
return 0;
}
int netconf_demo_subscribe_edit_change() {
const char *xpath = "/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/attributes/userLabel";
int rc = sr_module_change_subscribe(netconf_session_running, "_3gpp-common-managed-element", xpath, test_edit_callback, NULL, 0, 0, &netconf_session_subscription);
if (rc != SR_ERR_OK) {
netconf_log_error("sr_module_change_subscribe() failed");
goto failed;
}
return 0;
failed:
return 1;
}
int netconf_demo_subscribe_operational() {
static uint32_t counter = 1;
const char *xpath = "/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/attributes";
int rc = sr_oper_get_subscribe(netconf_session_operational, "_3gpp-common-managed-element", xpath, test_oper_callback, &counter, SR_SUBSCR_DEFAULT, &netconf_session_subscription);
if(rc != SR_ERR_OK) {
netconf_log_error("sr_oper_get_subscribe() failed");
goto failed;
}
return 0;
failed:
return 1;
}
int test_edit_callback(sr_session_ctx_t *session, uint32_t sub_id, const char *module_name, const char *xpath, sr_event_t event, uint32_t request_id, void *private_data) {
sr_change_iter_t *it = NULL;
int rc = SR_ERR_OK;
char path[512];
sr_change_oper_t oper;
sr_val_t *old_value = NULL;
sr_val_t *new_value = NULL;
(void)sub_id;
(void)request_id;
(void)private_data;
if(event == SR_EV_CHANGE) {
if (xpath) {
sprintf(path, "%s//.", xpath);
}
else {
sprintf(path, "/%s:*//.", module_name);
}
rc = sr_get_changes_iter(session, path, &it);
if (rc != SR_ERR_OK) {
netconf_log_error("sr_get_changes_iter() failed");
goto failed;
}
while ((rc = sr_get_change_next(session, it, &oper, &old_value, &new_value)) == SR_ERR_OK) {
if((oper == SR_OP_CREATED) || (oper == SR_OP_MODIFIED)) {
if(strcmp("/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/attributes/userLabel", new_value->xpath) == 0) {
if(strcmp(new_value->data.string_val, "enabled") == 0) {
printf("enabled\n");
}
else if(strcmp(new_value->data.string_val, "disabled") == 0) {
printf("disabled\n");
}
else if(strstr(new_value->data.string_val, "pmData") == new_value->data.string_val) {
ves_file_ready_t pm_data = {
.expires_on = "2099-12-31T235959.0Z",
.filesize = 1234,
.filelocation = "/ftp/test.gz"
};
int rc = ves_pnf_pmdata_fileready_execute(&pm_data);
if(rc != 0) {
netconf_log_error("ves_pnf_pmdata_fileready_execute() failed");
}
}
else {
return SR_ERR_VALIDATION_FAILED;
}
}
}
sr_free_val(old_value);
sr_free_val(new_value);
}
sr_free_change_iter(it);
}
return SR_ERR_OK;
failed:
return SR_ERR_INTERNAL;
}
static int test_oper_callback(sr_session_ctx_t *session, uint32_t sub_id, const char *module_name, const char *path, const char *request_xpath, uint32_t request_id, struct lyd_node **parent, void *private_data) {
uint32_t *counter = private_data;
(void)session;
(void)sub_id;
(void)module_name;
(void)path;
(void)request_xpath;
(void)request_id;
const char *xpath = "/_3gpp-common-managed-element:ManagedElement[id='OAI gNodeB']/attributes/SupportedPerfMetricGroup/granularityPeriods";
char value[10];
sprintf(value, "%d", *counter);
struct lyd_node *node;
LY_ERR rc = lyd_new_path(*parent, 0, xpath, value, 0, &node);
if(rc != LY_SUCCESS) {
netconf_log_error("lyd_new_path() failed");
goto failed;
}
(*counter)++;
return SR_ERR_OK;
failed:
return SR_ERR_INTERNAL;
}

View File

@@ -0,0 +1,9 @@
#pragma once
#include <stdio.h>
// #define netconf_log_error(format, args...) fprintf(stderr, format, ## args);
#define netconf_log_error(format, ...) { fprintf(stderr, "\033[1;31m[err/:%5d]\033[0m ", __LINE__); fprintf(stderr, format, ##__VA_ARGS__); fprintf(stderr, "\n"); }
// #define netconf_log(format, args...) fprintf(stderr, format, ## args);
#define netconf_log(format, ...) { fprintf(stdout, "\033[1m[log/:%5d]\033[0m ", __LINE__); fprintf(stdout, format, ##__VA_ARGS__); fprintf(stdout, "\n"); }

View File

@@ -0,0 +1,62 @@
#include "netconf_session.h"
#include "netconf_log.h"
sr_conn_ctx_t *netconf_session_connection = 0;
sr_session_ctx_t *netconf_session_running = 0;
sr_session_ctx_t *netconf_session_operational = 0;
const struct ly_ctx *netconf_session_context = 0;
sr_subscription_ctx_t *netconf_session_subscription = 0;
int netconf_session_init(void) {
int rc = SR_ERR_OK;
/* connect to sysrepo */
rc = sr_connect(0, &netconf_session_connection);
if(SR_ERR_OK != rc) {
netconf_log_error("sr_connect failed");
goto netconf_session_init_cleanup;
}
/* start session */
rc = sr_session_start(netconf_session_connection, SR_DS_OPERATIONAL, &netconf_session_operational);
if (rc != SR_ERR_OK) {
netconf_log_error("sr_session_start operational failed");
goto netconf_session_init_cleanup;
}
rc = sr_session_start(netconf_session_connection, SR_DS_RUNNING, &netconf_session_running);
if (rc != SR_ERR_OK) {
netconf_log_error("sr_session_start running failed");
goto netconf_session_init_cleanup;
}
/* get context */
netconf_session_context = sr_acquire_context(netconf_session_connection);
if(netconf_session_context == 0) {
netconf_log_error("sr_acquire_context failed");
goto netconf_session_init_cleanup;
}
return 0;
netconf_session_init_cleanup:
return 1;
}
void netconf_session_free(void) {
if(netconf_session_subscription) {
sr_unsubscribe(netconf_session_subscription);
}
sr_release_context(netconf_session_connection);
sr_session_stop(netconf_session_operational);
sr_session_stop(netconf_session_running);
sr_disconnect(netconf_session_connection);
netconf_session_connection = 0;
netconf_session_running = 0;
netconf_session_operational = 0;
netconf_session_context = 0;
}

View File

@@ -0,0 +1,13 @@
#pragma once
#include <libyang/libyang.h>
#include <sysrepo.h>
extern sr_conn_ctx_t *netconf_session_connection;
extern sr_session_ctx_t *netconf_session_running;
extern sr_session_ctx_t *netconf_session_operational;
extern const struct ly_ctx *netconf_session_context;
extern sr_subscription_ctx_t *netconf_session_subscription;
int netconf_session_init(void);
void netconf_session_free(void);

View File

@@ -0,0 +1,111 @@
#include "o1config.h"
#include "netconf_log.h"
#include <common/utils/assertions.h>
#include <common/utils/LOG/log.h>
#define simOpt PARAMFLAG_NOFREE|PARAMFLAG_CMDLINE_NOPREFIXENABLED
#define simOptMandatory PARAMFLAG_NOFREE|PARAMFLAG_CMDLINE_NOPREFIXENABLED|PARAMFLAG_MANDATORY
static int o1_validate_config(o1_config_t* config);
int o1_config_read(o1_config_t* config) {
memset(config, 0, sizeof(o1_config_t));
paramdef_t o1config_params[] = {
{"nfNodeId", "nodeId for oam for ves mount package\n", simOpt, strptr:&config->netconf_node_id, defstrval:"gnb-test01", TYPE_STRING, 0 },
{"netconfUsername", "username for netconf interface\n", simOpt, strptr:&config->netconf_username, defstrval:"netconf", TYPE_STRING, 0 },
{"netconfPassword", "password for netconf interface\n", simOpt, strptr:&config->netconf_password, defstrval:"netconf!", TYPE_STRING, 0 },
{"netconfPort", "port on host device for netconf interface\n", simOpt, u16ptr:&(config->netconf_port), defuintval:830, TYPE_UINT16, 0 },
{"netconfHost", "ip address on host device for netconf interface\n", simOpt, strptr:&config->netconf_host, defstrval:"0.0.0.0", TYPE_STRING, 0 },
{"vesUrl", "ves endpoint url to send notifications to\n", simOpt, strptr:&config->ves_url, defstrval:"", TYPE_STRING, 0 },
{"vesBasicAuthUsername", "ves endpoint username to authorize\n", simOpt, strptr:&config->ves_basicauth_username, defstrval:"", TYPE_STRING, 0 },
{"vesBasicAuthPassword", "ves endpoint password to authorize\n", simOpt, strptr:&config->ves_basicauth_password, defstrval:"", TYPE_STRING, 0 },
{"vesNfVendorName", "vendor name information for ves packages\n", simOpt, strptr:&config->ves_nf_vendor_name, defstrval:"OAI", TYPE_STRING, 0 },
{"vesNfNamingCode", "naming code information for ves packages\n", simOpt, strptr:&config->ves_nf_naming_code, defstrval:"gNodeB", TYPE_STRING, 0 },
{"vesOamIpv6", "oam ipv6 information for ves mount package\n", simOpt, strptr:&config->ves_oam_ipv6, defstrval:"", TYPE_STRING, 0 },
{"vesFtpServerPort", "ftp server port to serve pm data\n", simOpt, u16ptr:&(config->ves_ftp_server_port), defuintval:21, TYPE_UINT16, 0 },
{"vesFtpServerListenAddress", "ftp listen address to serve pm data\n", simOpt, strptr:&config->ves_ftp_listen_addr, defstrval:"0.0.0.0", TYPE_STRING, 0 },
{"demoAlarmingInterval", "ves alarming interval in seconds for demoing alarms\n",simOpt, u16ptr:&(config->demo_alarming_interval), defuintval:0, TYPE_UINT16, 0 }
};
#if defined(USE_TEST_CONFIG)
(void)o1config_params; //unused
config->netconf_node_id = strdup("gnb-test01");
config->netconf_username = strdup("netconf");
config->netconf_password = strdup("netconf!");
config->netconf_port = 830;
config->netconf_host = strdup("192.168.2.3");
config->ves_url = strdup("https://192.168.5.207:8443/eventListener/v7");
config->ves_basicauth_username = strdup("sample1");
config->ves_basicauth_password = strdup("sample1");
config->ves_nf_vendor_name = strdup("OpenAirInterface");
config->ves_nf_naming_code = strdup("OGNB");
config->ves_oam_ipv6 = strdup("");
config->ves_ftp_server_port = 21;
config->ves_ftp_listen_addr = strdup("0.0.0.0");
config->demo_alarming_interval = 30;
#else
int ret = config_get(o1config_params, sizeof(o1config_params) / sizeof(paramdef_t), "o1Config");
AssertFatal(ret >= 0, "configuration load couldn't be performed");
#endif
return o1_validate_config(config);
}
void o1_config_free(o1_config_t* config) {
free(config->netconf_node_id);
free(config->netconf_username);
free(config->netconf_password);
free(config->netconf_host);
free(config->ves_url);
free(config->ves_basicauth_username);
free(config->ves_basicauth_password);
free(config->ves_nf_vendor_name);
free(config->ves_nf_naming_code);
free(config->ves_oam_ipv6);
free(config->ves_ftp_listen_addr);
}
void o1_config_print(o1_config_t *config) {
netconf_log("Printing config:");
netconf_log("netconf_node_id: %s", config->netconf_node_id);
netconf_log("netconf_username: %s", config->netconf_username);
netconf_log("netconf_password: %s", config->netconf_password);
netconf_log("netconf_port = %d", config->netconf_port);
netconf_log("netconf_host: %s", config->netconf_host);
netconf_log("ves_url: %s", config-> ves_url);
netconf_log("ves_username: %s", config-> ves_basicauth_username);
netconf_log("ves_password: %s", config-> ves_basicauth_password);
netconf_log("ves_nf_vendor_name: %s", config->ves_nf_vendor_name);
netconf_log("ves_nf_naming_code: %s", config->ves_nf_naming_code);
netconf_log("ves_oam_ipv6: %s", config->ves_oam_ipv6);
netconf_log("ves_ftp_server_port = %d", config->ves_ftp_server_port);
netconf_log("ves_ftp_listen_addr: %s", config->ves_ftp_listen_addr);
netconf_log("demo_alarming_interval: %d", config->demo_alarming_interval);
netconf_log("=======");
}
bool o1_config_is_ves_enabled(o1_config_t *config){
return ((config->ves_url) && (strlen(config->ves_url) > 0));
}
bool o1_config_is_demoalarming_enabled(o1_config_t *config) {
return (config->demo_alarming_interval > 0);
}
static int o1_validate_config(o1_config_t* config) {
if (config == NULL) {
return 1;
}
// TODO
if (o1_config_is_ves_enabled(config)) {
//verify vesNfNamingCode (has to be exactly 4 characters long)
}
else {
}
return 0;
}

View File

@@ -0,0 +1,29 @@
#pragma once
#include <common/config/config_userapi.h>
#include "common_lib.h"
typedef struct {
char *netconf_node_id;
char *netconf_username;
char *netconf_password;
uint16_t netconf_port;
char *netconf_host;
char *ves_url;
char *ves_basicauth_username;
char *ves_basicauth_password;
char *ves_nf_vendor_name;
char *ves_nf_naming_code;
char *ves_oam_ipv6;
uint16_t ves_ftp_server_port;
char *ves_ftp_listen_addr;
uint16_t demo_alarming_interval; //send demo alarms every n seconds
} o1_config_t;
int o1_config_read(o1_config_t* config);
void o1_config_free(o1_config_t* config);
void o1_config_print(o1_config_t *config);
bool o1_config_is_ves_enabled(o1_config_t *config);
bool o1_config_is_demoalarming_enabled(o1_config_t *config);

View File

@@ -0,0 +1,75 @@
#pragma once
#include <stdint.h>
#define MAND
#define RO
#define RW
#define KEY
typedef struct oai_alarmRecords_thresholdInfo {
RO MAND char *measurementType;
RO MAND char *direction;
RO char *thresholdLevel;
RO char *thresholdValue;
RO char *hysteresis;
} oai_alarmRecords_thresholdInfo_t;
typedef struct oai_alarmRecords {
RW KEY char *alarmId;
RO MAND char *objectInstance;
RO MAND char *notificationId; //int32_t
RO char *alarmRaisedTime; //yang:date-and-time
RO char *alarmChangedTime; //yang:date-and-time
RO char *alarmClearedTime; //yang:date-and-time
RO char *alarmType; //eventType
RO char *probableCause;
RO char *specificProblem;
RW char *perceivedSeverity; //severity-level
RO char *backedUpStatus;
RO char *backUpObject;
RO char *trendIndication;
RO oai_alarmRecords_thresholdInfo_t *thresholdInfo;
RO char *stateChangeDefinition;
RO char *monitoredAttributes;
RO char *proposedRepairActions;
RO char *additionalText;
// RO char *additionalInformation; <anydata>
RO char *rootCauseIndicator;
RO char *ackTime; //yang:date-and-time
RW char *ackUserId;
RW char *ackSystemId;
RW char *ackState;
RW char *clearUserId;
RW char *clearSystemId;
RO char *serviceUser;
RO char *serviceProvider;
RO char *securityAlarmDetector;
} oai_alarmRecords_t;
typedef struct oai_BWP_ThresholdMonitor {
RW KEY char *id;
RW struct attributes {
RW MAND char *bwpContext;
RW MAND char *isInitialBwp;
RW MAND char *subCarrierSpacing;
RW MAND char *cyclicPrefix;
RW MAND char *startRB;
RW MAND char *numberOfRBs;
};
} oai_BWP_ThresholdMonitor_t;
typedef struct oai_BWP {
RW KEY char *id;
RW struct attributes {
RW MAND char *bwpContext;
RW MAND char *isInitialBwp;
RW MAND char *subCarrierSpacing;
RW MAND char *cyclicPrefix;
RW MAND char *startRB;
RW MAND char *numberOfRBs;
};
RW oai_BWP_ThresholdMonitor_t *ThresholdMonitor;
} oai_BWP_t;

View File

@@ -0,0 +1,118 @@
#define _GNU_SOURCE
#include "utils.h"
#include <time.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "netconf_log.h"
long int get_microseconds_since_epoch(void) {
time_t t = time(0);
struct timeval tv;
long int useconds;
gettimeofday(&tv, 0);
useconds = t*1000000 + tv.tv_usec; //add the microseconds to the seconds
return useconds;
}
char *get_netconf_timestamp(void) {
time_t rawtime = time(0);
char *nctime = 0;
if (rawtime == -1) {
netconf_log_error("time() failed");
return 0;
}
else {
struct tm *ptm = gmtime(&rawtime);
if (ptm == 0) {
netconf_log_error("gmtime failed");
}
else {
asprintf(&nctime, "%04d-%02d-%02dT%02d:%02d:%02d.0Z", ptm->tm_year + 1900, ptm->tm_mon + 1,
ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
}
}
return nctime;
}
char *str_replace(const char *orig, const char *rep, const char *with) {
char *result; // the return string
const char *ins; // the next insert point
char *tmp; // varies
int len_rep; // length of rep (the string to remove)
int len_with; // length of with (the string to replace rep with)
int len_front; // distance between rep and end of last rep
int count; // number of replacements
// sanity checks and initialization
if(!orig || !rep) {
return 0;
}
len_rep = strlen(rep);
if(len_rep == 0) {
return 0; // empty rep causes infinite loop during count
}
if (!with) {
with = "";
}
len_with = strlen(with);
// count the number of replacements needed
ins = orig;
for(count = 0; (tmp = strstr(ins, rep)); ++count) {
ins = tmp + len_rep;
}
tmp = result = malloc(strlen(orig) + (len_with - len_rep) * count + 1);
if(!result) {
return 0;
}
// first time through the loop, all the variable are set correctly
// from here on,
// tmp points to the end of the result string
// ins points to the next occurrence of rep in orig
// orig points to the remainder of orig after "end of rep"
while(count--) {
ins = strstr(orig, rep);
len_front = ins - orig;
tmp = strncpy(tmp, orig, len_front) + len_front;
tmp = strcpy(tmp, with) + len_with;
orig += len_front + len_rep; // move to next "end of rep"
}
strcpy(tmp, orig);
return result;
}
char *str_replace_inplace(char *s, const char *rep, const char *with) {
char *ret = str_replace(s, rep, with);
free(s);
if(ret == 0) {
return 0;
}
return ret;
}
char *get_hostname(void) {
char hostname[1024];
hostname[1023] = '\0';
gethostname(hostname, 1023);
return strdup(hostname);
}
unsigned long int get_file_size(const char *filename) {
struct stat st;
stat(filename, &st);
return st.st_size;
}

View File

@@ -0,0 +1,8 @@
#pragma once
long int get_microseconds_since_epoch(void);
char *get_netconf_timestamp(void);
char *str_replace(const char *orig, const char *rep, const char *with);
char *str_replace_inplace(char *s, const char *rep, const char *with);
char *get_hostname(void);
unsigned long int get_file_size(const char *filename);

822
common/utils/netconf/ves.c Normal file
View File

@@ -0,0 +1,822 @@
#define _GNU_SOURCE
#include "ves.h"
#include "utils.h"
#include "netconf_log.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <curl/curl.h>
#define VES_COMMON_HEADER_TEMPLATE "\"commonEventHeader\": {\
\"domain\": \"@domain@\",\
\"eventId\": \"@domain@_@eventType@\",\
\"eventName\": \"@domain@_@eventType@\",\
\"eventType\": \"@eventType@\",\
\"sequence\": @seqId@,\
\"priority\": \"@priority@\",\
\"reportingEntityId\": \"\",\
\"reportingEntityName\": \"@controllerName@\",\
\"sourceId\": \"\",\
\"sourceName\": \"@pnfId@\",\
\"startEpochMicrosec\": @timestamp@,\
\"lastEpochMicrosec\": @timestamp@,\
\"nfNamingCode\": \"@nfNamingCode@\",\
\"nfVendorName\": \"@nfVendorName@\",\
\"timeZoneOffset\": \"+00:00\",\
\"version\": \"4.1\",\
\"vesEventListenerVersion\": \"7.2.1\",\
\"stndDefinedNamespace\": \"@stndDefinedNamespace@\",\
\"nfcNamingCode\": \"NFC\"\
}"
#define VES_PNF_REGISTRATION_TEMPLATE "\"pnfRegistrationFields\": {\
\"pnfRegistrationFieldsVersion\": \"2.1\",\
\"lastServiceDate\": \"2021-03-26\",\
\"macAddress\": \"@macAddress@\",\
\"manufactureDate\": \"2021-01-16\",\
\"modelNumber\": \"@model@\",\
\"oamV4IpAddress\": \"@oamIp@\",\
@ipv6FullDefine@\
\"serialNumber\": \"@vendor@-@type@-@oamIp@-@model@\",\
\"softwareVersion\": \"2.3.5\",\
\"unitFamily\": \"@vendor@-@type@\",\
\"unitType\": \"@type@\",\
\"vendorName\": \"@vendor@\",\
\"additionalFields\": {\
\"oamPort\": \"@port@\",\
\"protocol\": \"SSH\",\
\"username\": \"@username@\",\
\"password\": \"@password@\",\
\"reconnectOnChangedSchema\": \"false\",\
\"sleep-factor\": \"1.5\",\
\"tcpOnly\": \"false\",\
\"connectionTimeout\": \"20000\",\
\"maxConnectionAttempts\": \"100\",\
\"betweenAttemptsTimeout\": \"2000\",\
\"keepaliveDelay\": \"120\"\
}\
}"
#define VES_PNF_ALARMING_TEMPLATE_RAISE "\"stndDefinedFields\": {\
\"schemaReference\": \"https://forge.3gpp.org/rep/sa5/MnS/raw/Rel-18/OpenAPI/TS28532_FaultMnS.yaml#components/schemas/NotifyNewAlarm\",\
\"data\": {\
\"href\": \"href1\",\
\"notificationId\": @seqId@,\
\"notificationType\": \"notifyNewAlarm\",\
\"eventTime\": \"@eventTime@\",\
\"systemDN\": \"xyz\",\
\"alarmId\": \"@alarm@\",\
\"alarmType\": \"COMMUNICATIONS_ALARM\",\
\"probableCause\": \"@alarm@\",\
\"specificProblem\": \"@alarm@\",\
\"perceivedSeverity\": \"@severity@\",\
\"backedUpStatus\": true,\
\"backUpObject\": \"xyz\",\
\"trendIndication\": \"MORE_SEVERE\",\
\"thresholdInfo\": {\
\"observedMeasurement\": \"new\",\
\"observedValue\": 123.1\
},\
\"correlatedNotifications\": [],\
\"stateChangeDefinition\": [{ \"operational-state\": \"DISABLED\" }],\
\"monitoredAttributes\": {\
\"interface\": \"@interface@\"\
},\
\"proposedRepairActions\": \"Call the police!\",\
\"additionalText\": \"O-RAN Software Community OAM\",\
\"additionalInformation\": {\
\"eventTime\": \"@eventTime@\",\
\"equipType\": \"@type@\",\
\"vendor\": \"@vendor@\",\
\"model\": \"@model@\"\
},\
\"rootCauseIndicator\": false\
},\
\"stndDefinedFieldsVersion\": \"1.0\"\
}"
#define VES_PNF_ALARMING_TEMPLATE_CLEAR "\"stndDefinedFields\": {\
\"schemaReference\": \"https://forge.3gpp.org/rep/sa5/MnS/raw/Rel-18/OpenAPI/TS28532_FaultMnS.yaml#components/schemas/NotifyClearedAlarm\",\
\"data\": {\
\"href\": \"href1\",\
\"notificationId\": @seqId@,\
\"notificationType\": \"notifyNewAlarm\",\
\"eventTime\": \"@eventTime@\",\
\"systemDN\": \"xyz\",\
\"alarmId\": \"@alarm@\",\
\"alarmType\": \"COMMUNICATIONS_ALARM\",\
\"probableCause\": \"@alarm@\",\
\"perceivedSeverity\": \"@severity@\",\
\"clearUserId\": \"@vendor@\",\
\"clearSystemId\": \"@vendor@\"\
},\
\"stndDefinedFieldsVersion\": \"1.0\"\
}"
#define VES_FILE_READY_TEMPLATE "\"stndDefinedFields\": {\
\"schemaReference\": \"https://forge.3gpp.org/rep/sa5/MnS/raw/Rel-18/OpenAPI/TS28532_FileDataReportingMnS.yaml#components/schemas/NotifyFileReady\",\
\"data\": {\
\"href\": \"href1\",\
\"notificationId\": 0,\
\"notificationType\": \"notifyFileReady\",\
\"eventTime\": \"@eventTime@\",\
\"systemDN\": \"xyz\",\
\"fileInfoList\": [{\
\"fileLocation\": \"@fileLocation@\",\
\"fileSize\": @fileSize@,\
\"fileReadyTime\": \"@eventTime@\",\
\"fileExpirationTime\": \"@expTime@\",\
\"fileCompression\": \"no\",\
\"fileFormat\": \"xml\",\
\"fileDataType\": \"Performance\"\
}],\
\"additionalText\": \"Have fun!\"\
},\
\"stndDefinedFieldsVersion\": \"1.0\"\
}"
/*
#define VES_FILE_READY_TEMPLATE "\"notificationFields\": {\
\"changeIdentifier\": \"PM_MEAS_FILES\",\
\"changeType\": \"FileReady\",\
\"notificationFieldsVersion\": \"2.0\",\
\"arrayOfNamedHashMap\": [\
{\
\"name\": \"@filename@\",\
\"hashMap\": {\
\"location\": \"@fileLocation@\",\
\"compression\": \"gzip\",\
\"fileFormatType\": \"org.3GPP.32.435#measCollec\",\
\"fileFormatVersion\": \"V5\"\
}\
}\
]\
}"
*/
struct memory {
char *response;
size_t size;
};
static int ves_execute(char *priority, char *domain, char *event_type, char *stnd_defined_namespace, char* main_content);
static int ves_http_request(const char *url, const char *username, const char* password, const char *method, const char *send_data, int *response_code, char **recv_data);
static size_t curl_write_cb(void *data, size_t size, size_t nmemb, void *userp);
static int vsftp_daemon_init(void);
static int vsftp_daemon_deinit(void);
static int sftp_daemon_init(void);
static int sftp_daemon_deinit(void);
static ves_config_t ves_config = {0};
static int ves_seq_id = 0;
static char *ves_common_header = 0;
/**
* initialize ves component
* save config internally
* prepare ves common header as far as possible
*/
int ves_init(ves_config_t *config, ves_header_t *ves) {
if(ves_common_header) {
netconf_log_error("ves_init() already called");
goto failed;
}
ves_common_header = strdup(VES_COMMON_HEADER_TEMPLATE);
if(ves_common_header == 0) {
netconf_log_error("strdup() error");
goto failed;
}
ves_config.url = strdup(config->url);
ves_config.username = strdup(config->username);
ves_config.password = strdup(config->password);
if(!ves_config.url || !ves_config.username || !ves_config.password) {
netconf_log_error("strdup() error");
goto failed;
}
ves_common_header = str_replace_inplace(ves_common_header, "@controllerName@", ves->hostname);
if(ves_common_header == 0) {
netconf_log_error("str_replace_inplace() failed");
goto failed;
}
ves_common_header = str_replace_inplace(ves_common_header, "@pnfId@", ves->pnf_id);
if(ves_common_header == 0) {
netconf_log_error("str_replace_inplace() failed");
goto failed;
}
ves_common_header = str_replace_inplace(ves_common_header, "@nfNamingCode@", ves->nf_naming_code);
if(ves_common_header == 0) {
netconf_log_error("str_replace_inplace() failed");
goto failed;
}
ves_common_header = str_replace_inplace(ves_common_header, "@nfVendorName@", ves->nf_vendor_name);
if(ves_common_header == 0) {
netconf_log_error("str_replace_inplace() failed");
goto failed;
}
int rc = vsftp_daemon_init();
if(rc != 0) {
netconf_log_error("vsftp_daemon_init() failed");
goto failed;
}
// rc = sftp_daemon_init();
// if(rc != 0) {
// netconf_log_error("sftp_daemon_init() failed");
// goto failed;
// }
return 0;
failed:
ves_free();
return 1;
}
void ves_free() {
vsftp_daemon_deinit();
// sftp_daemon_deinit();
free(ves_common_header);
free(ves_config.url);
free(ves_config.username);
free(ves_config.password);
ves_seq_id = 0;
ves_common_header = 0;
memset(&ves_config, 0, sizeof(ves_config_t));
}
/**
* send ves pnfRegistration
*
*/
int ves_pnf_registration_execute(ves_registration_data_t *ves) {
char *content = strdup(VES_PNF_REGISTRATION_TEMPLATE);
if(content == 0) {
netconf_log_error("strdup() failed");
goto failed;
}
char *port = 0;
asprintf(&port, "%d",ves->pnf_port);
if(port == 0) {
netconf_log_error("asprintf() failed");
goto failed;
}
// fill template
content = str_replace_inplace(content, "@macAddress@", ves->mac_address);
if(content == 0) {
netconf_log_error("str_replace_inplace() failed");
goto failed;
}
content = str_replace_inplace(content, "@model@", ves->model);
if(content == 0) {
netconf_log_error("str_replace_inplace() failed");
goto failed;
}
content = str_replace_inplace(content, "@oamIp@", ves->pnf_ip_v4_address);
if(content == 0) {
netconf_log_error("str_replace_inplace() failed");
goto failed;
}
char *ipv6 = strdup("");
if(ipv6 == 0) {
netconf_log_error("strdup() failed");
goto failed;
}
if(ves->pnf_ip_v6_address && strlen(ves->pnf_ip_v6_address)) {
free(ipv6);
asprintf(&ipv6, "\"oamV6IpAddress\": \"%s\"", ves->pnf_ip_v6_address);
if(ipv6 == 0) {
netconf_log_error("asprintf() failed");
goto failed;
}
}
content = str_replace_inplace(content, "@ipv6FullDefine@", ipv6);
free(ipv6);
if(content == 0) {
netconf_log_error("str_replace_inplace() failed");
goto failed;
}
content = str_replace_inplace(content, "@vendor@", ves->vendor);
if(content == 0) {
netconf_log_error("str_replace_inplace() failed");
goto failed;
}
content = str_replace_inplace(content, "@type@", ves->type);
if(content == 0) {
netconf_log_error("str_replace_inplace() failed");
goto failed;
}
content = str_replace_inplace(content, "@port@", port);
if(content == 0) {
netconf_log_error("str_replace_inplace() failed");
goto failed;
}
content = str_replace_inplace(content, "@username@", ves->pnf_username);
if(content == 0) {
netconf_log_error("str_replace_inplace() failed");
goto failed;
}
content = str_replace_inplace(content, "@password@", ves->pnf_password);
if(content == 0) {
netconf_log_error("str_replace_inplace() failed");
goto failed;
}
int rc = ves_execute(PRIORITY_PNFREGISTRATION, DOMAIN_PNFREGISTRAION, EVENTTYPE_PNFREGISTRATION,
STNDDEF_NAMESPACE_NONE, content);
if(rc != 0) {
netconf_log_error("ves_execute() failed");
goto failed;
}
free(port);
free(content);
return 0;
failed:
free(port);
free(content);
return 1;
}
/**
* send ves pnf file ready event
*
*/
int ves_pnf_pmdata_fileready_execute(ves_file_ready_t* ves_data) {
char *content = strdup(VES_FILE_READY_TEMPLATE);
if(content == 0) {
netconf_log_error("strdup() failed");
goto failed;
}
char *filesize = 0;
asprintf(&filesize, "%lu", ves_data->filesize);
if(filesize == 0) {
netconf_log_error("asprintf() failed");
goto failed;
}
// fill template
content = str_replace_inplace(content, "@expTime@", ves_data->expires_on);
if(content == 0) {
netconf_log_error("str_replace_inplace failed");
goto failed;
}
content = str_replace_inplace(content, "@fileLocation@", ves_data->filelocation);
if(content == 0) {
netconf_log_error("str_replace_inplace failed");
goto failed;
}
content = str_replace_inplace(content, "@fileSize@", filesize);
if(content == 0) {
netconf_log_error("str_replace_inplace failed");
goto failed;
}
int rc = ves_execute(PRIORITY_PMDATA, DOMAIN_PMDATA, EVENTTYPE_PNFALARMING,
STNDDEF_NAMESPACE_NONE, content);
if(rc != 0) {
netconf_log_error("ves_execute() failed");
goto failed;
}
free(filesize);
free(content);
return 0;
failed:
free(filesize);
free(content);
return 1;
}
/**
* send ves pnf alarm
*
*/
int ves_pnf_alarm_execute(ves_alarm_t* ves_alarm) {
char *content;
char *timestamp = 0;
char *seq_id = 0;
if (strcmp(VES_ALARM_ALARMTYPE_NONALARM, ves_alarm->alarm_type) == 0) {
content = strdup(VES_PNF_ALARMING_TEMPLATE_CLEAR);
}
else {
content = strdup(VES_PNF_ALARMING_TEMPLATE_RAISE);
}
if(content == 0) {
netconf_log_error("strdup() failed");
goto failed;
}
// asprintf(&timestamp, "%lu", get_microseconds_since_epoch());
// if(timestamp == 0) {
// netconf_log_error("asprintf() failed");
// goto failed;
// }
timestamp = get_netconf_timestamp();
asprintf(&seq_id, "%d", ves_seq_id);
if(seq_id == 0) {
netconf_log_error("asprintf() failed");
goto failed;
}
content = str_replace_inplace(content, "@eventTime@", timestamp);
if(content == 0) {
netconf_log_error("str_replace_inplace failed");
goto failed;
}
content = str_replace_inplace(content, "@seqId@", seq_id);
if(content == 0) {
netconf_log_error("str_replace_inplace() failed");
goto failed;
}
content = str_replace_inplace(content, "@notificationId@", "");
if(content == 0) {
netconf_log_error("str_replace_inplace failed");
goto failed;
}
content = str_replace_inplace(content, "@alarm@", ves_alarm->alarm_name);
if(content == 0) {
netconf_log_error("str_replace_inplace failed");
goto failed;
}
content = str_replace_inplace(content, "@severity@", ves_alarm->severity);
if(content == 0) {
netconf_log_error("str_replace_inplace failed");
goto failed;
}
content = str_replace_inplace(content, "@type@", ves_alarm->alarm_type);
if(content == 0) {
netconf_log_error("str_replace_inplace failed");
goto failed;
}
content = str_replace_inplace(content, "@vendor@", ves_alarm->vendor);
if(content == 0) {
netconf_log_error("str_replace_inplace failed");
goto failed;
}
content = str_replace_inplace(content, "@model@", "");
if(content == 0) {
netconf_log_error("str_replace_inplace failed");
goto failed;
}
int rc = ves_execute(PRIORITY_PNFALARMING, DOMAIN_STNDDEFINED, EVENTTYPE_PNFALARMING,
STNDDEF_NAMESPACE_FAULT, content);
if(rc != 0) {
netconf_log_error("ves_execute() failed");
goto failed;
}
free(content);
return 0;
failed:
free(content);
return 1;
}
static int ves_execute(char *priority, char *domain, char *event_type, char *stnd_defined_namespace, char* main_content) {
char *timestamp = 0;
char *seq_id = 0;
char *post_data = 0;
char *header = 0;
asprintf(&timestamp, "%lu", get_microseconds_since_epoch());
if(timestamp == 0) {
netconf_log_error("asprintf() failed");
goto failed;
}
asprintf(&seq_id, "%d", ves_seq_id);
if(seq_id == 0) {
netconf_log_error("asprintf() failed");
goto failed;
}
//fill header
header = strdup(ves_common_header);
if(header == 0) {
netconf_log_error("strdup() failed");
goto failed;
}
header = str_replace_inplace(header, "@seqId@", seq_id);
if(header == 0) {
netconf_log_error("str_replace_inplace() failed");
goto failed;
}
header = str_replace_inplace(header, "@timestamp@", timestamp);
if(header == 0) {
netconf_log_error("str_replace_inplace() failed");
goto failed;
}
header = str_replace_inplace(header, "@priority@", priority);
if(header == 0) {
netconf_log_error("str_replace_inplace() failed");
goto failed;
}
header = str_replace_inplace(header, "@domain@", domain);
if(header == 0) {
netconf_log_error("str_replace_inplace() failed");
goto failed;
}
header = str_replace_inplace(header, "@eventType@", event_type);
if(header == 0) {
netconf_log_error("str_replace_inplace() failed");
goto failed;
}
header = str_replace_inplace(header, "@stndDefinedNamespace@", stnd_defined_namespace);
if(header == 0) {
netconf_log_error("str_replace_inplace() failed");
goto failed;
}
//append body
asprintf(&post_data,"{\"event\":{%s,%s}}", header, main_content);
if(post_data == 0) {
netconf_log_error("asprintf() failed");
goto failed;
}
//send request
int response_code;
char *response = 0;
int rc = ves_http_request(ves_config.url, ves_config.username, ves_config.password, "POST", post_data, &response_code, &response);
if(rc != 0) {
netconf_log_error("ves_http_request() failed");
goto failed;
}
netconf_log("response_code = %d", response_code);
if(response) {
netconf_log("response = %s", response);
}
free(response);
if(response_code > 399) {
netconf_log_error("failure http response code: %d", response_code);
goto failed;
}
ves_seq_id++;
free(timestamp);
free(seq_id);
free(post_data);
free(header);
return 0;
failed:
free(timestamp);
free(seq_id);
free(post_data);
free(header);
return 1;
}
static int ves_http_request(const char *url, const char *username, const char* password, const char *method, const char *send_data, int *response_code, char **recv_data) {
const char *send_data_good = send_data;
if(send_data_good == 0) {
send_data_good = "";
}
CURL *curl = curl_easy_init();
if(curl == 0) {
netconf_log_error("curl_easy_init() error");
goto failed;
}
// set curl options
struct curl_slist *header = 0;
header = curl_slist_append(header, "Content-Type: application/json");
if(!header) {
netconf_log_error("curl_slist_append() failed");
goto failed;
}
header = curl_slist_append(header, "Accept: application/json");
if(!header) {
netconf_log_error("curl_slist_append() failed");
goto failed;
}
header = curl_slist_append(header, "X-MinorVersion: 1");
if(!header) {
netconf_log_error("curl_slist_append() failed");
goto failed;
}
CURLcode res = CURLE_OK;
res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header);
if(res != CURLE_OK) {
netconf_log_error("curl_easy_setopt() error");
goto failed;
}
res = curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 1L); //seconds timeout for a connection
if(res != CURLE_OK) {
netconf_log_error("curl_easy_setopt() error");
goto failed;
}
res = curl_easy_setopt(curl, CURLOPT_TIMEOUT, 1L); //seconds timeout for an operation
if(res != CURLE_OK) {
netconf_log_error("curl_easy_setopt() error");
goto failed;
}
res = curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 1L);
if(res != CURLE_OK) {
netconf_log_error("curl_easy_setopt() error");
goto failed;
}
res = curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L);
if(res != CURLE_OK) {
netconf_log_error("curl_easy_setopt() error");
goto failed;
}
// disable SSL verifications
res = curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
if(res != CURLE_OK) {
netconf_log_error("curl_easy_setopt() error");
goto failed;
}
res = curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
if(res != CURLE_OK) {
netconf_log_error("curl_easy_setopt() error");
goto failed;
}
res = curl_easy_setopt(curl, CURLOPT_PROXY_SSL_VERIFYPEER, 0L);
if(res != CURLE_OK) {
netconf_log_error("curl_easy_setopt() error");
goto failed;
}
res = curl_easy_setopt(curl, CURLOPT_PROXY_SSL_VERIFYHOST, 0L);
if(res != CURLE_OK) {
netconf_log_error("curl_easy_setopt() error");
goto failed;
}
res = curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, method);
if(res != CURLE_OK) {
netconf_log_error("curl_easy_setopt() error");
goto failed;
}
res = curl_easy_setopt(curl, CURLOPT_POSTFIELDS, send_data_good);
if(res != CURLE_OK) {
netconf_log_error("curl_easy_setopt() error");
goto failed;
}
res = curl_easy_setopt(curl, CURLOPT_URL, url);
if(res != CURLE_OK) {
netconf_log_error("curl_easy_setopt() error");
goto failed;
}
char *credentials = 0;
if((username) && (password)) {
asprintf(&credentials, "%s:%s", username, password);
if(credentials == 0) {
netconf_log_error("asprintf() failed");
goto failed;
}
res = curl_easy_setopt(curl, CURLOPT_USERPWD, credentials);
if(res != CURLE_OK) {
netconf_log_error("curl_easy_setopt() error");
goto failed;
}
}
struct memory response_data = {0};
if(recv_data) {
res = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_cb);
if(res != CURLE_OK) {
netconf_log_error("curl_easy_setopt() error");
goto failed;
}
res = curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response_data);
if(res != CURLE_OK) {
netconf_log_error("curl_easy_setopt() error");
goto failed;
}
}
netconf_log("%s-ing cURL to url=\"%s\" with body=\"%s\"... ", method, url, send_data_good);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
netconf_log_error("curl_easy_perform() failed");
goto failed;
}
if(response_code) {
long http_rc;
res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_rc);
if(res != CURLE_OK) {
netconf_log_error("curl_easy_getinfo() failed");
goto failed;
}
*response_code = http_rc;
}
if(recv_data) {
*recv_data = response_data.response;
}
free(credentials);
curl_slist_free_all(header);
curl_easy_cleanup(curl);
return 0;
failed:
free(credentials);
curl_slist_free_all(header);
curl_easy_cleanup(curl);
return 1;
}
static size_t curl_write_cb(void *data, size_t size, size_t nmemb, void *userp) {
size_t realsize = size * nmemb;
struct memory *mem = (struct memory *)userp;
char *ptr = realloc(mem->response, mem->size + realsize + 1);
if(ptr == NULL) {
//TODO log_error("realloc failed\n");
return 0; /* out of memory! */
}
mem->response = ptr;
memcpy(&(mem->response[mem->size]), data, realsize);
mem->size += realsize;
mem->response[mem->size] = 0;
return realsize;
}
static int vsftp_daemon_init(void) {
return system("/usr/sbin/vsftpd &");
}
static int vsftp_daemon_deinit(void) {
return system("killall -9 vsftpd");
}
static int sftp_daemon_init(void) {
return system("/usr/sbin/sshd -D &");
}
static int sftp_daemon_deinit(void) {
return system("killall -9 sshd");
}

View File

@@ -0,0 +1,77 @@
#pragma once
#include <stdbool.h>
// common data
typedef struct ves_header {
char *hostname;
char *nf_naming_code;
char *nf_vendor_name;
char *pnf_id;
} ves_header_t;
// ves endpoint configuration
typedef struct ves_config {
char *url; // endpoint url e.g. https://10.20.30.40/enventlistener/v7
char *username; // basic auth username
char *password; // basic auth password
} ves_config_t;
//pnfRegistration data
typedef struct ves_registration_data {
char *pnf_username;
char *pnf_password;
char *pnf_ip_v4_address;
char *pnf_ip_v6_address;
int pnf_port;
char *mac_address;
char *vendor;
char *model;
char *type;
bool is_tls;
} ves_registration_data_t;
//
typedef struct ves_file_ready {
char *filename;
char *filelocation;
unsigned long int filesize;
char *expires_on;
} ves_file_ready_t;
//
typedef struct ves_alarm {
char *alarm_name;
char *severity;
char *alarm_type; //TODO: maybe we should think about enum
char *vendor;
char *model;
} ves_alarm_t;
#define DOMAIN_PNFREGISTRAION "pnfRegistration"
#define DOMAIN_PNFALARMING "fault"
#define DOMAIN_HEARTBEAT "heartbeat"
#define DOMAIN_PMDATA "measurement"
#define DOMAIN_STNDDEFINED "stndDefined"
#define EVENTTYPE_PNFREGISTRATION "EventType5G"
#define EVENTTYPE_PNFALARMING "O_RAN_COMPONENT_Alarms"
#define EVENTTYPE_PMDATA "Notification-gnb_Nokia-FileReady"
#define PRIORITY_PNFREGISTRATION "Low"
#define PRIORITY_PNFALARMING "Low"
#define PRIORITY_PMDATA "Low"
#define STNDDEF_NAMESPACE_FAULT "3GPP-FaultSupervision"
#define STNDDEF_NAMESPACE_NONE ""
#define VES_ALARM_SEVERITY_CLEARED "CLEARED"
#define VES_ALARM_ALARMTYPE_ALARM "ALARM"
#define VES_ALARM_ALARMTYPE_NONALARM "NON-ALARM"
int ves_init(ves_config_t *config, ves_header_t *header);
void ves_free();
int ves_pnf_registration_execute(ves_registration_data_t *data);
int ves_pnf_pmdata_fileready_execute(ves_file_ready_t* ves_data);
int ves_pnf_alarm_execute(ves_alarm_t* ves_alarm);

View File

@@ -0,0 +1,76 @@
#include "ves_demo_alarm.h"
#include "netconf_log.h"
#include "o1config.h"
#include "ves.h"
#include <pthread.h>
typedef struct ves_demo_alarm_params {
int interval;
} ves_demo_alarm_params_t;
static pthread_t ves_demo_alarm_thread;
static void *ves_demo_alarm_routine(void *arg);
int ves_demo_alarm_start(o1_config_t *config) {
ves_demo_alarm_params_t *params = (ves_demo_alarm_params_t *)malloc(sizeof(ves_demo_alarm_params_t));
if(params == 0) {
netconf_log_error("malloc failed");
goto failed;
}
params->interval = config->demo_alarming_interval;
int rc = pthread_create(&ves_demo_alarm_thread, 0, ves_demo_alarm_routine, params);
if(rc != 0) {
netconf_log_error("pthread_create() failed");
goto failed;
}
return 0;
failed:
free(params);
return 1;
}
static void *ves_demo_alarm_routine(void *arg) {
ves_demo_alarm_params_t *params = (ves_demo_alarm_params_t *)arg;
int alarm_type = 0;
while(1) {
sleep(params->interval);
alarm_type++;
if(alarm_type >= 2) {
alarm_type = 0;
}
ves_alarm_t alarm = {
.alarm_name = "demoAlarm",
.vendor = "highstreet",
.model = "oai"
};
if(alarm_type) {
netconf_log("set alarm");
alarm.severity = "MAJOR";
alarm.alarm_type = VES_ALARM_ALARMTYPE_ALARM;
}
else {
netconf_log("clear alarm");
alarm.severity = VES_ALARM_SEVERITY_CLEARED;
alarm.alarm_type = VES_ALARM_ALARMTYPE_NONALARM;
}
netconf_log("alarm");
int rc = ves_pnf_alarm_execute(&alarm);
if(rc != 0) {
netconf_log_error("ves_pnf_alarm_execute() failed");
}
}
free(arg);
return 0;
}

View File

@@ -0,0 +1,5 @@
#pragma once
#include "o1config.h"
int ves_demo_alarm_start(o1_config_t *config);

View File

@@ -37,7 +37,9 @@
#include "assertions.h"
#include "PHY/defs_common.h"
#define MAX_BWP_SIZE 275
#define MAX_BWP_SIZE 275
#define NR_MAX_NUM_BWP 4
#define NR_MAX_HARQ_PROCESSES 16
typedef struct nr_bandentry_s {
int16_t band;
@@ -82,7 +84,7 @@ int get_dmrs_port(int nl, uint16_t dmrs_ports);
uint16_t SL_to_bitmap(int startSymbolIndex, int nrOfSymbols);
int get_nb_periods_per_frame(uint8_t tdd_period);
int get_supported_band_index(int scs, int band, int n_rbs);
long rrc_get_max_nr_csrs(uint8_t max_rbs, long b_SRS);
long rrc_get_max_nr_csrs(const int max_rbs, long b_SRS);
void get_samplerate_and_bw(int mu,
int n_rb,
int8_t threequarter_fs,

View File

@@ -71,12 +71,11 @@ static inline uint16_t BIT_STRING_to_uint16(BIT_STRING_t *asn) {
*/
static inline uint32_t BIT_STRING_to_uint32(BIT_STRING_t *asn) {
uint32_t result = 0;
int index;
int shift;
size_t index;
DevCheck ((asn->size > 0) && (asn->size <= 4), asn->size, 0, 0);
shift = ((asn->size - 1) * 8) - asn->bits_unused;
int shift = ((asn->size - 1) * 8) - asn->bits_unused;
for (index = 0; index < (asn->size - 1); index++) {
result |= asn->buf[index] << shift;
shift -= 8;
@@ -94,7 +93,7 @@ static inline uint32_t BIT_STRING_to_uint32(BIT_STRING_t *asn) {
*/
static inline uint64_t BIT_STRING_to_uint64(BIT_STRING_t *asn) {
uint64_t result = 0;
int index;
size_t index;
int shift;
DevCheck ((asn->size > 0) && (asn->size <= 8), asn->size, 0, 0);
@@ -110,4 +109,13 @@ static inline uint64_t BIT_STRING_to_uint64(BIT_STRING_t *asn) {
return result;
}
#define asn1cSeqAdd(VaR, PtR) if (ASN_SEQUENCE_ADD(VaR,PtR)!=0) AssertFatal(false, "ASN.1 encoding error " #VaR "\n")
#define asn1cCallocOne(VaR, VaLue) \
VaR = calloc(1,sizeof(*VaR)); *VaR=VaLue
#define asn1cCalloc(VaR, lOcPtr) \
typeof(VaR) lOcPtr = VaR = calloc(1,sizeof(*VaR))
#define asn1cSequenceAdd(VaR, TyPe, lOcPtr) \
TyPe *lOcPtr= calloc(1,sizeof(TyPe)); \
asn1cSeqAdd(&VaR,lOcPtr)
#endif

View File

@@ -366,9 +366,14 @@ void set_latency_target(void) {
LOG_E(HW,"Can't set /dev/cpu_dma_latency to %u us\n", latency_target_value);
// Set CPU frequency to it's maximum
if ( 0 != system("for d in /sys/devices/system/cpu/cpu[0-9]*; do cat $d/cpufreq/cpuinfo_max_freq > $d/cpufreq/scaling_min_freq; done"))
LOG_E(HW,"Can't set cpu frequency\n");
int system_ret = system("for d in /sys/devices/system/cpu/cpu[0-9]*; do cat $d/cpufreq/cpuinfo_max_freq > $d/cpufreq/scaling_min_freq; done");
if (system_ret == -1) {
LOG_E(HW, "Can't set cpu frequency: [%d] %s\n", errno, strerror(errno));
return;
}
if (!((WIFEXITED(system_ret)) && (WEXITSTATUS(system_ret) == 0))) {
LOG_E(HW, "Can't set cpu frequency\n");
}
mlockall(MCL_CURRENT | MCL_FUTURE);
}

View File

@@ -165,8 +165,7 @@ void measurcmd_display_rlcstats(telnet_printfunc_t prnt) {
statsptr[i].vptr = rlcstats + i;
}
for (int UE_id=UE_info->list.head; UE_id>=0; UE_id=UE_info->list.next[UE_id]) {
#define NB_eNB_INST 1
for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) {
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt,eNB_id, ENB_FLAG_YES,UE_info->eNB_UE_stats[0][UE_id].crnti,
eNB->frame,eNB->subframe,eNB_id);
measurcmd_display_one_rlcstat(prnt, UE_id, statsptr, num_rlcmeasure, rlcstats, "DCCH", &ctxt, SRB_FLAG_YES, DCCH);

View File

@@ -888,6 +888,7 @@ INPUT = \
@CMAKE_CURRENT_SOURCE_DIR@/../common/config/libconfig/config_libconfig.c \
@CMAKE_CURRENT_SOURCE_DIR@/../common/config/libconfig/config_libconfig_private.h \
@CMAKE_CURRENT_SOURCE_DIR@/../common/config/config_userapi.c \
@CMAKE_CURRENT_SOURCE_DIR@/../common/oai_asn1.h \
@CMAKE_CURRENT_SOURCE_DIR@/../common/utils/time_meas.h \
@CMAKE_CURRENT_SOURCE_DIR@/../common/utils/backtrace.c \
@CMAKE_CURRENT_SOURCE_DIR@/../common/utils/time_stat.h \
@@ -930,7 +931,7 @@ INPUT = \
@CMAKE_CURRENT_SOURCE_DIR@/../common/utils/load_module_shlib.c \
@CMAKE_CURRENT_SOURCE_DIR@/../common/utils/backtrace.h \
@CMAKE_CURRENT_SOURCE_DIR@/../common/utils/assertions.h \
@CMAKE_CURRENT_SOURCE_DIR@/../common/utils/asn1_conversions.h \
@CMAKE_CURRENT_SOURCE_DIR@/../common/utils/oai_asn1.h \
@CMAKE_CURRENT_SOURCE_DIR@/../common/utils/threadPool/thread-pool.h \
@CMAKE_CURRENT_SOURCE_DIR@/../common/utils/threadPool/thread-pool.c \
@CMAKE_CURRENT_SOURCE_DIR@/../common/utils/T/T.c \
@@ -1248,7 +1249,7 @@ INPUT = \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/rlc_v2/rlc_entity_am.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/rlc_v2/rlc_sdu.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/rlc_v2/rlc_entity.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/rlc_v2/asn1_utils.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/rlc_v2/rlc_asn1_utils.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/rlc_v2/rlc_ue_manager.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/rlc_v2/rlc_oai_api.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/rlc_v2/rlc_sdu.h \
@@ -1356,7 +1357,7 @@ INPUT = \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia1.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/nr_pdcp/asn1_utils.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/nr_pdcp/nr_pdcp_asn1_utils.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia1.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/nr_pdcp/nr_pdcp.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/nr_pdcp/asn1_utils.c \
@@ -1390,7 +1391,7 @@ INPUT = \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/nr_rlc/nr_rlc_entity.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/nr_rlc/nr_rlc_pdu.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/nr_rlc/nr_rlc_sdu.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/nr_rlc/asn1_utils.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/nr_rlc/nr_rlc_asn1_utils.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/nr_rlc/nr_rlc_pdu.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/nr_rlc/nr_rlc_entity_am.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/nr_rlc/asn1_utils.c \
@@ -2109,7 +2110,6 @@ INPUT = \
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/SCHED/nfapi_lte_dummy.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/SCHED/sched_eNB.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/SCHED/phy_procedures_lte_common.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/SCHED/sched_common_vars.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/SCHED/phy_procedures_lte_eNb.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/SCHED/sched_common_extern.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/SCHED/nfapi_nr_dummy.c \
@@ -2437,7 +2437,6 @@ INPUT = \
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/MODULATION/nr_modulation.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/MODULATION/slot_fep.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/MODULATION/ul_7_5_kHz.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/MODULATION/modulation_vars.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/MODULATION/slot_fep_ul.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/phy_extern.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/defs_UE.h \

View File

@@ -42,6 +42,12 @@ RUN apt-get update && \
psmisc \
git \
xxd \
# libyang dependencies
libpcre2-dev \
# libssh dependencies
zlib1g-dev libssl-dev \
# netconf base dependencies
unzip openssl openssh-client \
# python3-pip for conf template generation
python3-pip && \
pip3 install --ignore-installed pyyaml

View File

@@ -0,0 +1,76 @@
#/*
# * 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
# */
#---------------------------------------------------------------------
#
# Dockerfile for the Open-Air-Interface BUILD service
# Valid for Ubuntu 18.04
#
#---------------------------------------------------------------------
FROM ubuntu:22.04 AS ran-base
ARG NEEDED_GIT_PROXY
ENV DEBIAN_FRONTEND=noninteractive
ENV TZ=Europe/Paris
ENV BUILD_UHD_FROM_SOURCE=True
ENV UHD_VERSION=4.3.0.0
RUN \
apt-get clean && \
cd /var/lib/apt && \
mv lists lists.old && \
mkdir -p lists/partial && \
apt-get clean
#install developers pkg/repo
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \
DEBIAN_FRONTEND=noninteractive apt-get install --yes \
#gcc needed for build_oai
build-essential \
psmisc \
git \
xxd \
# libyang dependencies
libpcre2-dev \
# libssh dependencies
zlib1g-dev libssl-dev \
# netconf base dependencies
unzip openssl openssh-client \
# python3-pip for conf template generation
python3-pip && \
pip3 install --ignore-installed pyyaml
# In some network environments, GIT proxy is required
RUN /bin/bash -c "if [[ -v NEEDED_GIT_PROXY ]]; then git config --global http.proxy $NEEDED_GIT_PROXY; fi"
#create the WORKDIR
WORKDIR /oai-ran
COPY . .
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y libulfius-dev
#run build_oai -I to get the builder image
RUN /bin/sh oaienv && \
cd cmake_targets && \
mkdir -p log && \
./build_oai -I -w USRP

View File

@@ -27,12 +27,24 @@
FROM ran-base:latest as ran-build
# run dependencies install for netconf
RUN ./docker/scripts/netconf_dep_install.sh
RUN rm -Rf /oai-ran
WORKDIR /oai-ran
COPY . .
# get and install required YANG libraries
RUN \
cd /oai-ran/specification && \
./get-yangs.sh && \
./install-yangs.sh
WORKDIR /oai-ran
# build all targets so final targets can be created afterwards
RUN /bin/sh oaienv && \
cd cmake_targets && \
mkdir -p log && \
./build_oai --eNB --gNB --RU --UE --nrUE --ninja --build-lib all -w USRP --verbose-ci --noavx512 -c
# ./build_oai --eNB --gNB --RU --UE --nrUE --ninja --build-lib all -w USRP --verbose-ci --noavx512 -c
./build_oai --gNB -w USRP --build-lib telnetsrv --verbose-ci --noavx512 -c

View File

@@ -1,4 +1,3 @@
#!/bin/bash
#/*
# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
# * contributor license agreements. See the NOTICE file distributed with
@@ -19,33 +18,33 @@
# * For more information about the OpenAirInterface (OAI) Software Alliance:
# * contact@openairinterface.org
# */
#---------------------------------------------------------------------
#
# Dockerfile for the Open-Air-Interface BUILD service
# Valid for Ubuntu 18.04
#
#---------------------------------------------------------------------
ARG BASETAG="latest"
FROM ran-base:${BASETAG} as ran-build
function destroy_usage {
echo "OAI CI VM script"
echo " Original Author: Raphael Defosseux"
echo " Requirements:"
echo " -- uvtool uvtool-libvirt apt-cacher"
echo ""
echo "Usage:"
echo "------"
echo " oai-ci-vm-tool destroy [OPTIONS]"
echo ""
command_options_usage
}
# run dependencies install for netconf
RUN ./docker/scripts/netconf_dep_install.sh
function destroy_vm {
echo "############################################################"
echo "OAI CI VM script"
echo "############################################################"
echo "VM_TEMPLATE = $VM_TEMPLATE"
RUN rm -Rf /oai-ran
WORKDIR /oai-ran
COPY . .
LIST_CI_VM=`uvt-kvm list | grep $VM_TEMPLATE`
# get and install required YANG libraries
RUN \
cd /oai-ran/specification && \
./get-yangs.sh && \
./install-yangs.sh
for CI_VM in $LIST_CI_VM
do
VM_IP_ADDR=`uvt-kvm ip $CI_VM`
echo "VM to destroy: $CI_VM -- IP $VM_IP_ADDR"
uvt-kvm destroy $CI_VM
ssh-keygen -R $VM_IP_ADDR
done
}
WORKDIR /oai-ran
# build all targets so final targets can be created afterwards
RUN /bin/sh oaienv && \
cd cmake_targets && \
mkdir -p log && \
# ./build_oai --eNB --gNB --RU --UE --nrUE --ninja --build-lib all -w USRP --verbose-ci --noavx512 -c
./build_oai --gNB -w USRP --build-lib telnetsrv --verbose-ci --noavx512 -c

View File

@@ -0,0 +1,75 @@
#/*
# * 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
# */
#---------------------------------------------------------------------
#
# Dockerfile for the Open-Air-Interface BUILD service
# Valid for Ubuntu 18.04
#
#---------------------------------------------------------------------
FROM ran-base:latest as ran-dev
# run dependencies install for netconf
RUN ./docker/scripts/netconf_dep_install.sh
RUN rm -Rf /oai-ran
WORKDIR /oai-ran
COPY . .
# get and install required YANG libraries
RUN \
cd /oai-ran/specification && \
./get-yangs.sh && \
./install-yangs.sh
WORKDIR /oai-ran
# build all targets so final targets can be created afterwards
RUN /bin/sh oaienv && \
cd cmake_targets && \
mkdir -p log
# ./build_oai --eNB --gNB --RU --UE --nrUE --ninja --build-lib all -w USRP --verbose-ci --noavx512 -c
# ./build_oai --gNB -w USRP --build-lib telnetsrv --verbose-ci --noavx512 -c
# Add netconf user and configure access
RUN \
adduser netconf && \
echo "netconf:netconf!" | chpasswd && \
mkdir -p /home/netconf/.ssh
# # Initialize netopeer2
RUN \
/usr/local/share/netopeer2/merge_hostkey.sh && \
/usr/local/share/netopeer2/merge_config.sh
COPY docker/scripts/gnb_entrypoint.sh /opt/oai-gnb/bin/entrypoint.sh
WORKDIR /opt/oai-gnb
#EXPOSE 2152/udp # S1U, GTP/UDP
#EXPOSE 22100/tcp # ?
#EXPOSE 36412/udp # S1C, SCTP/UDP
#EXPOSE 36422/udp # X2C, SCTP/UDP
#EXPOSE 50000/udp # IF5 / ORI (control)
#EXPOSE 50001/udp # IF5 / ECPRI (data)
# ENTRYPOINT ["/opt/oai-gnb/bin/entrypoint.sh"]
# CMD ["/opt/oai-gnb/bin/nr-softmodem", "-O", "/opt/oai-gnb/etc/gnb.conf"]
WORKDIR /oai-ran/cmake_targets
CMD ["/bin/sh", "-c", "sleep infinity"]

View File

@@ -0,0 +1,109 @@
#/*
# * 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
# */
#---------------------------------------------------------------------
#
# Dockerfile for the Open-Air-Interface BUILD service
# Valid for Ubuntu 18.04
#
#---------------------------------------------------------------------
ARG BASETAG="latest"
FROM ran-build:${BASETAG} AS gnb-build
FROM ran-base:${BASETAG} as ran-dev
RUN apt-get update && \
apt-get install --yes \
openssh-client \
vsftpd
# run dependencies install for netconf
RUN ./docker/scripts/netconf_dep_install.sh
RUN rm -Rf /oai-ran
WORKDIR /oai-ran
COPY . .
# get and install required YANG libraries
RUN \
cd /oai-ran/specification && \
./get-yangs.sh && \
./install-yangs.sh
WORKDIR /oai-ran
# build all targets so final targets can be created afterwards
RUN /bin/sh oaienv && \
cd cmake_targets && \
mkdir -p log
# ./build_oai --eNB --gNB --RU --UE --nrUE --ninja --build-lib all -w USRP --verbose-ci --noavx512 -c
# ./build_oai --gNB -w USRP --build-lib telnetsrv --build-lib --verbose-ci --noavx512 -c
COPY --from=gnb-build \
/oai-ran/cmake_targets/ran_build/build/liboai_eth_transpro.so \
/oai-ran/cmake_targets/ran_build/build/librfsimulator.so \
/oai-ran/cmake_targets/ran_build/build/liboai_usrpdevif.so \
/oai-ran/cmake_targets/ran_build/build/libcoding.so \
/oai-ran/cmake_targets/ran_build/build/libparams_libconfig.so \
/oai-ran/cmake_targets/ran_build/build/libdfts.so \
/oai-ran/cmake_targets/ran_build/build/libldpc.so \
/oai-ran/cmake_targets/ran_build/build/libldpc_optim.so \
/oai-ran/cmake_targets/ran_build/build/libldpc_optim8seg.so \
/oai-ran/cmake_targets/ran_build/build/libldpc_orig.so \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv.so \
/usr/local/lib/
# Add netconf user and configure access
RUN \
adduser netconf && \
echo "netconf:netconf!" | chpasswd && \
mkdir -p /home/netconf/.ssh
### FTP and SFTP configuration
RUN \
mkdir /ftp && \
chown -R netconf:netconf /ftp && \
mkdir /var/run/vsftpd && \
mkdir /var/run/vsftpd/empty && \
mkdir /run/sshd && \
echo "Match User netconf\n ChrootDirectory /\n X11Forwarding no\n AllowTcpForwarding no\n ForceCommand internal-sftp -d /ftp" >> /etc/ssh/sshd_config
COPY docker/config/vsftpd.conf /etc/vsftpd.conf
COPY docker/config/vsftpd.userlist /etc/vsftpd.userlist
# # Initialize netopeer2
RUN \
/usr/local/share/netopeer2/merge_hostkey.sh && \
/usr/local/share/netopeer2/merge_config.sh
COPY docker/scripts/gnb_entrypoint.sh /opt/oai-gnb/bin/entrypoint.sh
WORKDIR /opt/oai-gnb
#EXPOSE 2152/udp # S1U, GTP/UDP
#EXPOSE 22100/tcp # ?
#EXPOSE 36412/udp # S1C, SCTP/UDP
#EXPOSE 36422/udp # X2C, SCTP/UDP
#EXPOSE 50000/udp # IF5 / ORI (control)
#EXPOSE 50001/udp # IF5 / ECPRI (data)
# ENTRYPOINT ["/opt/oai-gnb/bin/entrypoint.sh"]
# CMD ["/opt/oai-gnb/bin/nr-softmodem", "-O", "/opt/oai-gnb/etc/gnb.conf"]
WORKDIR /oai-ran/cmake_targets
CMD ["/bin/sh", "-c", "sleep infinity"]

View File

@@ -58,7 +58,10 @@ RUN apt-get update && \
python3 \
python3-six \
python3-requests \
libusb-1.0-0 && \
libusb-1.0-0 \
# libyang/sysrepo/netopeer2
libpcre2-8-0 \
openssh-client && \
rm -rf /var/lib/apt/lists/*
WORKDIR /opt/oai-gnb/bin
@@ -102,6 +105,43 @@ RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai
WORKDIR /opt/oai-gnb/etc
COPY --from=gnb-build /oai-ran/docker/etc .
# Copy relevant netopeer/sysrepo files for gNB
COPY --from=gnb-build \
/usr/local/bin/yanglint \
/usr/local/bin/yangre \
/usr/local/bin/sysrepo-plugind \
/usr/local/bin/sysrepocfg \
/usr/local/bin/sysrepoctl \
/usr/local/bin/netopeer2-cli \
/usr/local/bin/
COPY --from=gnb-build /usr/local/sbin/netopeer2-server /usr/local/sbin/netopeer2-server
COPY --from=gnb-build \
/usr/local/lib/libnetconf2.so \
/usr/local/lib/libssh.so \
/usr/local/lib/libsysrepo.so \
/usr/local/lib/libyang.so \
/usr/local/lib/sysrepo-plugind/ \
/usr/local/lib/
RUN ldconfig
COPY --from=gnb-build /usr/local/share/yang /usr/local/share/yang
COPY --from=gnb-build /usr/local/share/netopeer2 /usr/local/share/netopeer2
COPY --from=gnb-build /etc/sysrepo /etc/sysrepo
# Add netconf user and configure access
RUN \
adduser netconf && \
echo "netconf:netconf!" | chpasswd && \
mkdir -p /home/netconf/.ssh
# # Initialize netopeer2
RUN \
/usr/local/share/netopeer2/merge_hostkey.sh && \
/usr/local/share/netopeer2/merge_config.sh
COPY docker/scripts/gnb_entrypoint.sh /opt/oai-gnb/bin/entrypoint.sh
WORKDIR /opt/oai-gnb
#EXPOSE 2152/udp # S1U, GTP/UDP
#EXPOSE 22100/tcp # ?

View File

@@ -0,0 +1,173 @@
#/*
# * 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
# */
#---------------------------------------------------------------------
#
# Dockerfile for the Open-Air-Interface BUILD service
# Valid for Ubuntu18.04
#
#---------------------------------------------------------------------
ARG BASETAG="latest"
FROM ran-base:${BASETAG} as gnb-base
FROM ran-build:${BASETAG} AS gnb-build
RUN python3 ./docker/scripts/generateTemplate.py ./docker/scripts/gnb_parameters.yaml && \
cp /oai-ran/docker/scripts/gnb_entrypoint.sh /oai-ran/docker/scripts/entrypoint.sh
#start from scratch for target executable
FROM ubuntu:22.04 as oai-gnb
ENV DEBIAN_FRONTEND=noninteractive
ENV TZ=Europe
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \
DEBIAN_FRONTEND=noninteractive apt-get install --yes \
software-properties-common \
procps \
libsctp1 \
tzdata \
libnettle8 \
libblas3 \
libatlas3-base \
libconfig9 \
openssl \
net-tools \
iperf \
iproute2 \
iputils-ping \
gdb \
python3 \
python3-six \
python3-requests \
libusb-1.0-0 \
# libyang/sysrepo/netopeer2
psmisc \
libpcre2-8-0 \
openssh-client \
vsftpd && \
rm -rf /var/lib/apt/lists/*
WORKDIR /opt/oai-gnb/bin
COPY --from=gnb-build \
/oai-ran/cmake_targets/ran_build/build/nr-softmodem \
/oai-ran/docker/scripts/entrypoint.sh \
./
COPY --from=gnb-build \
/oai-ran/cmake_targets/ran_build/build/liboai_eth_transpro.so \
/oai-ran/cmake_targets/ran_build/build/librfsimulator.so \
/oai-ran/cmake_targets/ran_build/build/liboai_usrpdevif.so \
/oai-ran/cmake_targets/ran_build/build/libcoding.so \
/oai-ran/cmake_targets/ran_build/build/libparams_libconfig.so \
/oai-ran/cmake_targets/ran_build/build/libdfts.so \
/oai-ran/cmake_targets/ran_build/build/libldpc.so \
/oai-ran/cmake_targets/ran_build/build/libldpc_optim.so \
/oai-ran/cmake_targets/ran_build/build/libldpc_optim8seg.so \
/oai-ran/cmake_targets/ran_build/build/libldpc_orig.so \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv.so \
/usr/local/lib/
# Now we are copying from builder-image the UHD files.
COPY --from=gnb-base /usr/local/bin/uhd_find_devices /usr/local/bin
COPY --from=gnb-base /usr/local/lib/libuhd.so.4.3.0 /usr/local/lib
COPY --from=gnb-base /usr/local/lib/uhd/utils/uhd_images_downloader.py /opt/oai-gnb/bin
COPY --from=gnb-base \
/usr/lib/x86_64-linux-gnu/libboost_date_time.so.1.74.0 \
/usr/lib/x86_64-linux-gnu/libboost_filesystem.so.1.74.0 \
/usr/lib/x86_64-linux-gnu/libboost_regex.so.1.74.0 \
/usr/lib/x86_64-linux-gnu/libboost_serialization.so.1.74.0 \
/usr/lib/x86_64-linux-gnu/libboost_thread.so.1.74.0 \
/usr/lib/x86_64-linux-gnu/libboost_system.so.1.74.0 \
/usr/lib/x86_64-linux-gnu/libboost_chrono.so.1.74.0 \
/usr/lib/x86_64-linux-gnu/libboost_program_options.so.1.74.0 \
/usr/lib/x86_64-linux-gnu/
RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai_device.so" && \
ldconfig
# Copy the relevant configuration files for gNB
WORKDIR /opt/oai-gnb/etc
COPY --from=gnb-build /oai-ran/docker/etc .
# Copy relevant netopeer/sysrepo files for gNB
COPY --from=gnb-build \
/usr/local/bin/yanglint \
/usr/local/bin/yangre \
/usr/local/bin/sysrepo-plugind \
/usr/local/bin/sysrepocfg \
/usr/local/bin/sysrepoctl \
/usr/local/bin/netopeer2-cli \
/usr/local/bin/
COPY --from=gnb-build /usr/local/sbin/netopeer2-server /usr/local/sbin/netopeer2-server
COPY --from=gnb-build \
/usr/local/lib/libcurl.so \
/usr/local/lib/libnetconf2.so \
/usr/local/lib/libssh.so \
/usr/local/lib/libsysrepo.so \
/usr/local/lib/libyang.so \
/usr/local/lib/sysrepo-plugind/ \
/usr/local/lib/
RUN ldconfig
COPY --from=gnb-build /usr/local/share/yang /usr/local/share/yang
COPY --from=gnb-build /usr/local/share/netopeer2 /usr/local/share/netopeer2
COPY --from=gnb-build /etc/sysrepo /etc/sysrepo
# Add netconf user and configure access
RUN \
adduser netconf && \
echo "netconf:netconf!" | chpasswd && \
mkdir -p /home/netconf/.ssh
### FTP and SFTP configuration
RUN \
mkdir /ftp && \
chown -R netconf:netconf /ftp && \
mkdir /var/run/vsftpd && \
mkdir /var/run/vsftpd/empty && \
mkdir /run/sshd && \
echo "Match User netconf\n ChrootDirectory /\n X11Forwarding no\n AllowTcpForwarding no\n ForceCommand internal-sftp -d /ftp" >> /etc/ssh/sshd_config
COPY docker/config/vsftpd.conf /etc/vsftpd.conf
COPY docker/config/vsftpd.userlist /etc/vsftpd.userlist
# # Initialize netopeer2
RUN \
/usr/local/share/netopeer2/merge_hostkey.sh && \
/usr/local/share/netopeer2/merge_config.sh
COPY docker/scripts/gnb_entrypoint.sh /opt/oai-gnb/bin/entrypoint.sh
WORKDIR /opt/oai-gnb
#EXPOSE 2152/udp # S1U, GTP/UDP
#EXPOSE 22100/tcp # ?
#EXPOSE 36412/udp # S1C, SCTP/UDP
#EXPOSE 36422/udp # X2C, SCTP/UDP
#EXPOSE 50000/udp # IF5 / ORI (control)
#EXPOSE 50001/udp # IF5 / ECPRI (data)
ENTRYPOINT ["/opt/oai-gnb/bin/entrypoint.sh"]
CMD ["/opt/oai-gnb/bin/nr-softmodem", "-O", "/opt/oai-gnb/etc/gnb.conf"]

View File

@@ -116,6 +116,7 @@ For example, the eNB:
```bash
docker build --target oai-enb --tag oai-enb:latest --file docker/Dockerfile.eNB.ubuntu18 .
docker build --target oai-gnb --tag oai-gnb:latest --file docker/Dockerfile.gNB.ubuntu22 .
```
After a while:

36
docker/config/vsftpd.conf Normal file
View File

@@ -0,0 +1,36 @@
listen=NO
listen_ipv6=YES
anonymous_enable=NO
local_enable=YES
write_enable=YES
local_umask=022
dirmessage_enable=YES
use_localtime=YES
xferlog_enable=YES
connect_from_port_20=YES
chroot_local_user=YES
secure_chroot_dir=/var/run/vsftpd/empty
pam_service_name=vsftpd
pasv_enable=Yes
pasv_min_port=10000
pasv_max_port=11000
user_sub_token=$USER
local_root=/ftp
userlist_enable=YES
userlist_file=/etc/vsftpd.userlist
userlist_deny=NO
pasv_promiscuous=YES
allow_writeable_chroot=YES
# rsa_cert_file=/home/netconf/.ssh/melacon.server.crt
# rsa_private_key_file=/home/netconf/.ssh/melacon.server.key
# ssl_enable=YES
# allow_anon_ssl=NO
# force_local_data_ssl=YES
# force_local_logins_ssl=YES
# ssl_tlsv1=YES
# ssl_sslv2=NO
# ssl_sslv3=NO
# require_ssl_reuse=NO
# ssl_ciphers=HIGH

View File

@@ -0,0 +1 @@
netconf

View File

@@ -21,6 +21,7 @@ if [[ -v USE_VOLUMED_CONF ]]; then cp $PREFIX/etc/mounted.conf $PREFIX/etc/gnb.c
# Defualt Parameters
GNB_ID=${GNB_ID:-e00}
NSSAI_SD=${NSSAI_SD:-ffffff}
ENABLE_NETCONF=${ENABLE_NETCONF:-"false"}
# AMF_IP_ADDRESS can be amf ip address of amf fqdn
if [[ -v AMF_IP_ADDRESS ]] && [[ "${AMF_IP_ADDRESS}" =~ [a-zA-Z] ]] && [[ -z `getent hosts $AMF_IP_ADDRESS | awk '{print $1}'` ]]; then echo "not able to resolve AMF FQDN" && exit 1 ; fi
[[ -v AMF_IP_ADDRESS ]] && [[ "${AMF_IP_ADDRESS}" =~ [a-zA-Z] ]] && AMF_IP_ADDRESS=$(getent hosts $AMF_IP_ADDRESS | awk '{print $1}')
@@ -72,7 +73,19 @@ elif [[ -v USE_N3XX ]]; then
fi
# enable printing of stack traces on assert
export gdbStacks=1
export gdbStacks=0
if $ENABLE_NETCONF; then
echo "clearing shared memory for sysrepo"
rm -rf /dev/shm/sr*
if [ $? -eq 0 ]; then
echo "succeeded"
else
echo "failed"
fi
echo "=================================="
echo "== starting netconf server in background"
netopeer2-server -v2 -d &
fi
echo "=================================="
echo "== Starting gNB soft modem"
@@ -92,3 +105,4 @@ else
echo "$@"
exec "$@"
fi

View File

@@ -0,0 +1,78 @@
#!/bin/bash
INSTALL_PATH="/opt/dev/install"
# exit when any command fails
set -e
BUILD_MODE="Release"
# supress warnings from git
git config --global advice.detachedHead false
mkdir -p $INSTALL_PATH
# build and install libssh-dev
cd $INSTALL_PATH
git clone --single-branch --branch libssh-0.9.2 https://git.libssh.org/projects/libssh.git
cd $INSTALL_PATH/libssh
mkdir -p build
cd build
cmake -DWITH_EXAMPLES=OFF ..
make -j4
make install
ldconfig
# build and install libyang
cd $INSTALL_PATH
git clone --single-branch --branch v2.1.30 https://github.com/CESNET/libyang.git
cd $INSTALL_PATH/libyang
mkdir -p build
cd build
cmake -DCMAKE_BUILD_TYPE:String="$BUILD_MODE" -DGEN_LANGUAGE_BINDINGS=ON -DENABLE_BUILD_TESTS=OFF ..
make -j4
make install
ldconfig
# build and install sysrepo
cd $INSTALL_PATH
git clone --single-branch --branch v2.2.36 https://github.com/sysrepo/sysrepo.git
cd $INSTALL_PATH/sysrepo
mkdir -p build
cd build
cmake -DCMAKE_BUILD_TYPE:String="$BUILD_MODE" -DGEN_LANGUAGE_BINDINGS=ON -DGEN_CPP_BINDINGS=ON -DGEN_PYTHON_BINDINGS=OFF -DENABLE_TESTS=OFF -DREPOSITORY_LOC:PATH=/etc/sysrepo -DREQUEST_TIMEOUT=60 -DOPER_DATA_PROVIDE_TIMEOUT=60 ..
make -j4
make install
ldconfig
# build and install libnetconf2
cd $INSTALL_PATH
git clone --single-branch --branch v2.1.28 https://github.com/CESNET/libnetconf2.git
cd $INSTALL_PATH/libnetconf2
mkdir -p build
cd build
cmake -DCMAKE_BUILD_TYPE:String="$BUILD_MODE" -DENABLE_BUILD_TESTS=OFF ..
make -j4
make install
ldconfig
# build and install netopeer2
cd $INSTALL_PATH
git clone --single-branch --branch v2.1.49 https://github.com/CESNET/netopeer2.git
cd $INSTALL_PATH/netopeer2
mkdir -p build
cd build
cmake -DCMAKE_BUILD_TYPE:String="$BUILD_MODE" -DGENERATE_HOSTKEY=OFF -DMERGE_LISTEN_CONFIG=OFF ..
make -j4
make install
# build and install cURL
cd $INSTALL_PATH
git clone --single-branch --branch curl-7_87_0 https://github.com/curl/curl.git
cd $INSTALL_PATH/curl
mkdir -p build
cd build
cmake -DBUILD_TESTING=OFF ..
make -j4
make install
ldconfig

View File

@@ -55,8 +55,6 @@
#include <openair1/PHY/phy_extern_ue.h>
#include "PHY/phy_vars.h"
#include "SCHED/sched_common_vars.h"
#include "LAYER2/MAC/mac_vars.h"
#include "LAYER2/MAC/mac.h"
#include "LAYER2/MAC/mac_proto.h"
@@ -107,6 +105,7 @@ uint16_t runtime_phy_tx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75,
int oai_exit = 0;
int NB_UE_INST = 0;
uint64_t downlink_frequency[MAX_NUM_CCs][4];
int32_t uplink_frequency_offset[MAX_NUM_CCs][4];

View File

@@ -88,9 +88,9 @@
/* command line parameters specific to UE */
/* optname helpstr paramflags XXXptr defXXXval type numelt */
/*-------------------------------------------------------------------------------------------------------------------------------------------------------*/
// clang-format off
#define CMDLINE_UEPARAMS_DESC { \
{"U", CONFIG_HLP_NUMUE, 0, u16ptr:&NB_UE_INST, defuintval:1, TYPE_UINT16, 0}, \
{"U", CONFIG_HLP_NUMUE, 0, iptr:&NB_UE_INST, defuintval:1, TYPE_INT, 0}, \
{"ue-rxgain", CONFIG_HLP_UERXG, 0, dblptr:&(rx_gain[0][0]), defdblval:130, TYPE_DOUBLE, 0}, \
{"ue-rxgain-off", CONFIG_HLP_UERXGOFF, 0, dblptr:&rx_gain_off, defdblval:0, TYPE_DOUBLE, 0}, \
{"ue-txgain", CONFIG_HLP_UETXG, 0, dblptr:&(tx_gain[0][0]), defdblval:0, TYPE_DOUBLE, 0}, \
@@ -100,8 +100,7 @@
{"ue-max-power", NULL, 0, iptr:&(tx_max_power[0]), defintval:23, TYPE_INT, 0}, \
{"emul-iface", CONFIG_HLP_EMULIFACE, 0, strptr:&emul_iface, defstrval:"lo", TYPE_STRING, 100}, \
{"L2-emul", NULL, 0, u8ptr:&nfapi_mode, defuintval:3, TYPE_UINT8, 0}, \
{"num-ues", NULL, 0, u16ptr:&(NB_UE_INST), defuintval:1, TYPE_UINT16, 0}, \
{"nums_ue_thread", NULL, 0, u16ptr:&(NB_THREAD_INST), defuintval:1, TYPE_UINT16, 0}, \
{"num-ues", NULL, 0, iptr:&(NB_UE_INST), defuintval:1, TYPE_INT, 0}, \
{"r" , CONFIG_HLP_PRB, 0, u8ptr:&(frame_parms[0]->N_RB_DL), defintval:25, TYPE_UINT8, 0}, \
{"dlsch-demod-shift", CONFIG_HLP_DLSHIFT, 0, iptr:(int32_t *)&dlsch_demod_shift, defintval:0, TYPE_INT, 0}, \
{"usrp-args", CONFIG_HLP_USRP_ARGS, 0, strptr:&usrp_args, defstrval:"type=b200",TYPE_STRING, 0}, \
@@ -111,6 +110,7 @@
{"ue-idx-standalone", NULL, 0, u16ptr:&ue_idx_standalone, defuintval:0xFFFF, TYPE_UINT16, 0}, \
{"node-number", NULL, 0, u16ptr:&node_number, defuintval:2, TYPE_UINT16, 0}, \
}
// clang-format on
/*-----------------------------------------------------------------------------------------------------------------------------*/
/* command line parameters specific to UE threads */

View File

@@ -69,7 +69,7 @@ extern double cpuf;
#define FRAME_PERIOD 100000000ULL
#define DAQ_PERIOD 66667ULL
#define FIFO_PRIORITY 40
#define NB_THREAD_INST 1
typedef enum {
pss=0,
pbch=1,

View File

@@ -54,11 +54,8 @@
#include "PHY/phy_vars_ue.h"
#include "PHY/LTE_TRANSPORT/transport_vars.h"
#include "SCHED/sched_common_vars.h"
#include "PHY/MODULATION/modulation_vars.h"
#include "LAYER2/MAC/mac.h"
#include "LAYER2/MAC/mac_vars.h"
#include "LAYER2/MAC/mac_proto.h"
#include "RRC/LTE/rrc_vars.h"
#include "PHY_INTERFACE/phy_interface_vars.h"
@@ -102,7 +99,7 @@ uint16_t runtime_phy_tx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75,
int oai_exit = 0;
unsigned int mmapped_dma=0;
UE_MAC_INST *UE_mac_inst = NULL;
uint64_t downlink_frequency[MAX_NUM_CCs][4];
int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
@@ -518,14 +515,14 @@ AssertFatal(false,"");
return NULL;
}
int NB_UE_INST = 1;
int main( int argc, char **argv ) {
int CC_id;
uint8_t abstraction_flag=0;
// Default value for the number of UEs. It will hold,
// if not changed from the command line option --num-ues
NB_UE_INST=1;
NB_THREAD_INST=1;
configmodule_interface_t *config_mod;
start_background_system();
config_mod = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY);
@@ -552,18 +549,6 @@ int main( int argc, char **argv ) {
EPC_MODE_ENABLED = !IS_SOFTMODEM_NOS1;
printf("Running with %d UE instances\n",NB_UE_INST);
// Checking option of nums_ue_thread.
if(NB_THREAD_INST < 1) {
printf("Running with 0 UE rxtx thread, exiting.\n");
abort();
}
// Checking option's relation between nums_ue_thread and num-ues
if(NB_UE_INST <NB_THREAD_INST ) {
printf("Number of UEs < number of UE rxtx threads, exiting.\n");
abort();
}
#if T_TRACER
T_Config_Init();
#endif
@@ -606,8 +591,6 @@ int main( int argc, char **argv ) {
frame_parms[CC_id]->nb_antenna_ports_eNB = 1; //initial value overwritten by initial sync later
}
NB_INST=1;
if(NFAPI_MODE==NFAPI_UE_STUB_PNF || NFAPI_MODE==NFAPI_MODE_STANDALONE_PNF) {
PHY_vars_UE_g = malloc(sizeof(PHY_VARS_UE **)*NB_UE_INST);

View File

@@ -60,7 +60,6 @@ static int DEFENBS[] = {0};
#include <openair2/UTIL/OPT/opt.h>
#include <openair1/SIMULATION/TOOLS/sim.h>
#include <openair1/PHY/phy_vars.h>
#include <openair1/SCHED/sched_common_vars.h>
#include <openair2/LAYER2/MAC/mac_vars.h>
#include <openair2/RRC/LTE/rrc_vars.h>

View File

@@ -48,9 +48,7 @@
#include "radio/COMMON/common_lib.h"
#include "radio/ETHERNET/USERSPACE/LIB/if_defs.h"
#include "PHY/phy_vars.h"
#include "SCHED/sched_common_vars.h"
#include "PHY/TOOLS/phy_scope_interface.h"
#include "common/utils/LOG/log.h"
#include "common/utils/LOG/vcd_signal_dumper.h"

View File

@@ -622,6 +622,7 @@ void *emulatedRF_thread(void *param) {
void rx_rf(RU_t *ru,int *frame,int *slot) {
RU_proc_t *proc = &ru->proc;
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
openair0_config_t *cfg = &ru->openair0_cfg;
void *rxp[ru->nb_rx];
unsigned int rxs;
int i;
@@ -658,10 +659,7 @@ void rx_rf(RU_t *ru,int *frame,int *slot) {
//"rx_rf: Asked for %d samples, got %d from USRP\n",fp->samples_per_subframe,rxs);
if (rxs != samples_per_slot) LOG_E(PHY, "rx_rf: Asked for %d samples, got %d from USRP\n",samples_per_slot,rxs);
if (proc->first_rx == 1) {
ru->ts_offset = proc->timestamp_rx;
proc->timestamp_rx = 0;
} else {
if (proc->first_rx != 1) {
samples_per_slot_prev = fp->get_samples_per_slot((*slot-1)%fp->slots_per_frame,fp);
if (proc->timestamp_rx - old_ts != samples_per_slot_prev) {
@@ -671,13 +669,22 @@ void rx_rf(RU_t *ru,int *frame,int *slot) {
}
}
//compute system frame number (SFN) according to O-RAN-WG4-CUS.0-v02.00 (using alpha=beta=0)
// this assumes that the USRP has been synchronized to the GPS time
// OAI uses timestamps in sample time stored in int64_t, but it will fit in double precision for many years to come.
double gps_sec = ((double) ts)/cfg->sample_rate;
//proc->frame_rx = ((int64_t) (gps_sec/0.01)) & 1023;
// in fact the following line is the same as long as the timestamp_rx is synchronized to GPS.
proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_subframe*10))&1023;
proc->tti_rx = fp->get_slot_from_timestamp(proc->timestamp_rx,fp);
// synchronize first reception to frame 0 subframe 0
LOG_D(PHY,"RU %d/%d TS %llu , frame %d, slot %d.%d / %d\n",
LOG_D(PHY,"RU %d/%d TS %ld, GPS %f, SR %f, frame %d, slot %d.%d / %d\n",
ru->idx,
0,
(unsigned long long int)(proc->timestamp_rx+ru->ts_offset),
ts, //(unsigned long long int)(proc->timestamp_rx+ru->ts_offset),
gps_sec,
cfg->sample_rate,
proc->frame_rx,proc->tti_rx,proc->tti_tx,fp->slots_per_frame);
// dump VCD output for first RU in list

View File

@@ -45,8 +45,6 @@
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
#include "PHY/phy_vars.h"
#include "SCHED/sched_common_vars.h"
#include "LAYER2/MAC/mac_vars.h"
#include "RRC/LTE/rrc_vars.h"
#include "PHY_INTERFACE/phy_interface_vars.h"
#include "gnb_config.h"
@@ -81,6 +79,8 @@ unsigned short config_frames[4] = {2,9,11,13};
#include <openair3/ocp-gtpu/gtp_itf.h>
#include "nfapi/oai_integration/vendor_ext.h"
#include "common/utils/netconf/netconf.h"
pthread_cond_t nfapi_sync_cond;
pthread_mutex_t nfapi_sync_mutex;
int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex
@@ -95,6 +95,8 @@ int config_sync_var=-1;
volatile int start_gNB = 0;
int oai_exit = 0;
int NB_UE_INST = 0;
static int wait_for_sync = 0;
unsigned int mmapped_dma=0;
@@ -523,6 +525,10 @@ int main( int argc, char **argv ) {
exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
}
//netconf
netconf_init();
set_softmodem_sighandler();
#ifdef DEBUG_CONSOLE
setvbuf(stdout, NULL, _IONBF, 0);
@@ -727,6 +733,7 @@ int main( int argc, char **argv ) {
}
logClean();
netconf_free();
printf("Bye.\n");
return 0;
}

View File

@@ -42,12 +42,9 @@
#include "openair1/PHY/MODULATION/nr_modulation.h"
#include "PHY/phy_vars_nr_ue.h"
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
#include "SCHED/sched_common_vars.h"
#include "PHY/MODULATION/modulation_vars.h"
#include "PHY/NR_TRANSPORT/nr_dlsch.h"
//#include "../../SIMU/USER/init_lte.h"
#include "LAYER2/MAC/mac_vars.h"
#include "RRC/LTE/rrc_vars.h"
#include "PHY_INTERFACE/phy_interface_vars.h"
#include "NR_IF_Module.h"
@@ -403,6 +400,7 @@ static void get_channel_model_mode() {
init_bler_table("NR_AWGN_RESULTS_DIR");
}
int NB_UE_INST = 1;
int main( int argc, char **argv ) {
int set_exe_prio = 1;
@@ -469,8 +467,6 @@ int main( int argc, char **argv ) {
}
}
NB_UE_INST=1;
NB_INST=1;
PHY_vars_UE_g = malloc(sizeof(PHY_VARS_NR_UE **));
PHY_vars_UE_g[0] = malloc(sizeof(PHY_VARS_NR_UE *)*MAX_NUM_CCs);
if (get_softmodem_params()->emulate_l1) {

View File

@@ -45,7 +45,7 @@
#include "openair1/SIMULATION/TOOLS/sim.h"
#include "enb_config.h"
#include "enb_paramdef.h"
#include "platform_constants.h"
#include "common/platform_constants.h"
#include "common/config/config_paramdesc.h"
#include "common/config/config_userapi.h"
#include "common/ran_context.h"
@@ -180,11 +180,12 @@ int ru_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SIM_DO_UL_SIGNAL,1);
do_UL_sig(&sim,
subframe,
0, // abstraction_flag
0, // abstraction_flag
RC.ru[ru_id]->frame_parms,
0, // frame is only used for abstraction
0, // frame is only used for abstraction
ru_id,
CC_id);
CC_id,
1);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SIM_DO_UL_SIGNAL,0);
}

29
integration/.env Normal file
View File

@@ -0,0 +1,29 @@
ADMIN_PASSWORD=admin
PUBPORT_SDNCWEB=8080
PUBPORT_VES=8443
SDNC_WEB_IMAGE=nexus3.onap.org:10001/onap/sdnc-web-image:2.4.2
#SDNC_IMAGE=nexus3.onap.org:10001/onap/sdnc-image:2.4.2
SDNC_IMAGE=hightec/sdnc-image:1.4.0-SNAPSHOT-20230213T025757Z
SDNRDB_IMAGE=docker.elastic.co/elasticsearch/elasticsearch-oss:7.9.3
VES_COLLECTOR_IMAGE=nexus3.onap.org:10001/onap/org.onap.dcaegen2.collectors.ves.vescollector:1.8.0
ZOOKEEPER_IMAGE=nexus3.onap.org:10001/onap/dmaap/zookeeper:6.0.3
KAFKA_IMAGE=nexus3.onap.org:10001/onap/dmaap/kafka111:1.0.4
DMAAP_IMAGE=nexus3.onap.org:10001/onap/dmaap/dmaap-mr:1.1.18
DMAAP_DR_DB_IMAGE=nexus3.onap.org:10001/mariadb:10.2.14
# dcae configs
PM_MAPPER_TARGET_CONFIG_PATH=/app-config/application_config.yaml
SOLUTION_DOMAIN=local
DCAE_VES_COLLECTOR_IMAGE=nexus3.onap.org:10001/onap/org.onap.dcaegen2.collectors.ves.vescollector:1.10.3
PM_MAPPER_IMAGE=nexus3.onap.org:10001/onap/org.onap.dcaegen2.services.pm-mapper:latest
PM_MAPPER_TARGET_CONFIG_PATH=/app-config/application_config.yaml
## oh oh
DCAE_DFC_IMAGE=nexus3.onap.org:10003/onap/org.onap.dcaegen2.collectors.datafile.datafile-app-server:latest
DCAE_DFC_TARGET_CONFIG_PATH=/app-config/application_config.yaml
DCAE_DFC_TARGET_SPRING_CONFIG=/opt/app/datafile/config/application.yaml
#dmaap config
DMAAP_DR_NODE_IMAGE=nexus3.onap.org:10001/onap/dmaap/datarouter-node:2.1.11
DMAAP_DR_PROV_IP_IMAGE=nexus3.onap.org:10001/onap/dmaap/datarouter-prov:2.1.11
DMAAP_KAFKA_IMAGE=nexus3.onap.org:10001/onap/dmaap/kafka111:1.0.4
DMAAP_MR_IMAGE=nexus3.onap.org:10001/onap/dmaap/dmaap-mr:1.1.18
DMAAP_ZOOKEEPER_IMAGE=nexus3.onap.org:10001/onap/dmaap/zookeeper:6.0.3

120
integration/README.md Normal file
View File

@@ -0,0 +1,120 @@
# Integration
## How to build gNodeB image
We created a script which is doing the same as the instructions inside of the docker folder.
```
./build-gnb-docker.sh --base --build --gnb
```
If the base is already created once, only ```--build``` and ```--gnb``` args are neccessary.
## How to run
### Prerequisites
* docker (sudo apt install docker.io)
* docker-compose (pip3 install docker-compose)
### Start SDN-Controller and its components
* edit ```.env``` file to set image versions and public available ports
* run cmd:
```
docker-compose up -d
```
### Start gNodeB
```
docker-compose -f docker-compose.gnb.yml up -d
```
depending on if VES is configured or not you have to mount the device manually.
### Go to ODLUX gui
* Open URL in the browser: http://your-deployed-ip-address:8181
* login with credentials defined in .env file (default: admin:admin)
* find out ip address of the gnodeb container (```docker inspect gnodeb01-test | grep -i ipaddress)
* mount the device in the connectApp
* node-id: whatever you like
* host: ip address you found out
* port: 830
* username: netconf
* password: netconf!
* now the node should get into the connected state
## Using ODLUX Gui
By default this is available on ```http://localhost:8080```. Default user credentials are username ```admin``` and password ```admin```. The password is configured in the .env file ```ADMIN_PASSWORD```.
On an already started OAI gNodeB you should already see the an entry in the ConnectApp in state ```Connected```. The node-id is corresponding with the gnb.conf of the device. By right-click on it you can see in the context menu ```Info``` all the supported yang specifications, this device is supporting.
If the gnb.conf property ```demoAlarmingInterval``` is set, you should also see an alarm inside of the FaultApp. There you have also a tab ```Alarm Log``` which shows the complete history of incoming alarms into the SDNC.
HINT: If you want to see Notifications as they are coming into the SDNC you have to enable Notifications. Therefore you have to click on your username on the top right corner and then go to settings. There you can enable and disable it. It is disabled by default to prevent flooding the browser with incoming messages, which can cause some instability.
In the ConfigurationApp you are able to read and write configuration from and to the device. Sadly up to now there is a bug in the opendaylight project which is preventing to access a List of objects in the root structure, which is the way 3GPP has designed their Models. Since we are just implementing one root element this list has now the size of one, we have to access this by url and cannot click through from beginning.
```
http://localhost:8080/odlux/index.html#/configuration/{node-id}/_3gpp-common-managed-element:ManagedElement[OAI%20gNodeB]
```
But from there on you have access to all the containers and leafs inside.
## Troubleshooting
### Node does not get into connected state
* check if the gnodeb container is running
* get inside of the gnodeb container and check if the netopeer2 server is running
```
docker exec -ti gnodeb-test bash
ps -ef | grep netopeer
```
* check if exceptions are thrown inside of the SDN-Controller
```
docker exec -ti sdnc bash
less /opt/opendaylight/data/log/karaf.log
go to the end of the log (SHIFT+G) and then upwards to search for exceptions/stacktraces (e.g. wrong username or password)
```
### Node does not even show up after started up
* check the gnb.conf if ```vesUrl``` is correct
* check the VES-Collector if message is coming in
```
$ docker logs -f dcae-ves-collector
```
* there should be a log with something like
```
2023-03-20 13:12:59.697 INFO 28 [nio-8443-exec-5] o.o.d.c.p.MessageRouterHttpStatusMapper : Successfully send event to MR
```
* if not please check the gnb logs
* if yes please make sure that all components of the docker-compose.yml are up running
```
$ docker-compose ps -a
Name Command State Ports
-------------------------------------------------------------------------------------------------------------------------
dcae-dfc java -jar /opt/app/datafil ... Up 8100/tcp, 8433/tcp
dcae-pm-mapper java -jar pm-mapper-1.10.0.jar Up
dcae-ves-collector /bin/sh -c bin/docker-entry.sh Up 8080/tcp, 8443/tcp
dmaap-dr-mariadb docker-entrypoint.sh mysqld Up (healthy) 3306/tcp
dmaap-dr-node sh startup.sh Up 8080/tcp, 8443/tcp
dmaap-dr-prov sh startup.sh Up (healthy) 8080/tcp, 8443/tcp
dmaap-kafka /etc/confluent/docker/run Up 9092/tcp, 9093/tcp
dmaap-message-router sh startup.sh Up 3904/tcp, 3905/tcp
dmaap-zookeeper /etc/confluent/docker/run Up 2181/tcp, 2888/tcp, 3888/tcp
sdnc /bin/sh -c /opt/onap/sdnc/ ... Up 1090/tcp, 1099/tcp, 8181/tcp
sdnc-web /opt/bitnami/scripts/nginx ... Up 0.0.0.0:8080->8080/tcp,:::8080->8080/tcp, 8443/tcp
sdnrdb /tini -- /usr/local/bin/do ... Up 9200/tcp, 9300/tcp
```

Binary file not shown.

View File

@@ -0,0 +1 @@
Er1tmip;T4w[%1}YE?x{fN9v

Binary file not shown.

View File

@@ -0,0 +1 @@
583Ls;XF(qDQu3p!L22gyh1t

View File

@@ -0,0 +1,76 @@
###############################################################################
##
## Collector Server config
##
## - Default values are shown as commented settings.
##
###############################################################################
##
## HTTP(S) service
##
## Normally:
##
## - 8080 is http service
## - https is disabled by default
##
## - At this time, the server always binds to 0.0.0.0
##
##
#collector.service.port=8080
## Authentication is only supported via secure port
## When enabled - require valid keystore defined
collector.service.secure.port=8443
# auth.method flags:
#
# noAuth - default option - no security (http)
# certBasicAuth - auth by certificate and basic auth username / password (https)
auth.method=certBasicAuth
## Combination of userid,hashPassword encoded pwd list to be supported
## userid and pwd comma separated; pipe delimitation between each pair
## Password is generated by crypt-password library using BCrypt algorithm stored in dcaegen2/sdk package
## or https://nexus.onap.org/#nexus-search;quick~crypt-password
header.authlist=sample1,$2a$10$0buh.2WeYwN868YMwnNNEuNEAMNYVU9.FSMJGyIKV3dGET/7oGOi6
## The keystore must be setup per installation when secure port is configured
collector.keystore.file.location=etc/keystore
collector.keystore.passwordfile=etc/passwordfile
collector.cert.subject.matcher=etc/certSubjectMatcher.properties
## The truststore must be setup per installation when mutual tls support is configured
collector.truststore.file.location=etc/truststore
collector.truststore.passwordfile=etc/trustpasswordfile
## Schema Validation checkflag
## default no validation checkflag (-1)
## If enabled (1) - schemafile location must be specified
collector.schema.checkflag=1
collector.schema.file={\"v1\":\"./etc/CommonEventFormat_27.2.json\",\"v2\":\"./etc/CommonEventFormat_27.2.json\",\"v3\":\"./etc/CommonEventFormat_27.2.json\",\"v4\":\"./etc/CommonEventFormat_27.2.json\",\"v5\":\"./etc/CommonEventFormat_28.4.1.json\",\"v7\":\"./etc/CommonEventFormat_30.2.1_ONAP.json\"}
## Schema StndDefinedFields Validation checkflag
## default no validation checkflag (-1)
## If enabled (1) - schema files locations must be specified, mapping file path must be specified, schema reference path
## in event json must be specified, path to stndDefined data field in event json must be specified
collector.externalSchema.checkflag=1
collector.externalSchema.schemasLocation=etc/externalRepo/
collector.externalSchema.mappingFileLocation=etc/externalRepo/schema-map.json
event.externalSchema.schemaRefPath=$.event.stndDefinedFields.schemaReference
event.externalSchema.stndDefinedDataPath=$.event.stndDefinedFields.data
## List all streamid per domain to be supported. The streamid should match to channel name on dmaapfile
collector.dmaap.streamid=fault=ves-fault|syslog=ves-syslog|heartbeat=ves-heartbeat|measurementsForVfScaling=ves-measurement|mobileFlow=ves-mobileflow|other=ves-other|stateChange=ves-statechange|thresholdCrossingAlert=ves-thresholdCrossingAlert|voiceQuality=ves-voicequality|sipSignaling=ves-sipsignaling|notification=ves-notification|pnfRegistration=ves-pnfRegistration|3GPP-FaultSupervision=ves-3gpp-fault-supervision|3GPP-Heartbeat=ves-3gpp-heartbeat|3GPP-Provisioning=ves-3gpp-provisioning|3GPP-PerformanceAssurance=ves-3gpp-performance-assurance|o-ran-sc-du-hello-world-pm-streaming-oas3=ves-o-ran-sc-du-hello-world-pm-streaming-oas3|o1-notify-pnf-registration=ves-o1-notify-pnf-registration
collector.dmaapfile=etc/ves-dmaap-config.json
## Path to the file containing description of api versions
collector.description.api.version.location=etc/api_version_description.json
## Event transformation Flag - when set expects configurable transformation
## defined under ./etc/eventTransform.json
## Enabled by default; to disable set to 0
event.transform.flag=0
# Describes at what frequency (measured in minutes) should application try to fetch config from CBS
collector.dynamic.config.update.frequency=5

View File

@@ -0,0 +1,29 @@
dmaap.certificateConfig.keyCert: /opt/app/datafile/etc/cert/cert.p12
dmaap.certificateConfig.keyPasswordPath: /opt/app/datafile/etc/cert/p12.pass
dmaap.certificateConfig.trustedCa: /opt/app/datafile/etc/cert/trust.jks
dmaap.certificateConfig.trustedCaPasswordPath: /opt/app/datafile/etc/cert/trust.pass
dmaap.dmaapConsumerConfiguration.consumerGroup: OpenDcae-c12
dmaap.dmaapConsumerConfiguration.consumerId: C12
dmaap.dmaapConsumerConfiguration.timeoutMs: -1
dmaap.security.enableDmaapCertAuth: false
dmaap.security.keyStorePasswordPath: /opt/app/datafile/etc/cert/jks.pass
dmaap.security.keyStorePath: /opt/app/datafile/etc/cert/cert.jks
dmaap.security.trustStorePasswordPath: /opt/app/datafile/etc/cert/trust.pass
dmaap.security.trustStorePath: /opt/app/datafile/etc/cert/trust.jks
service_calls: []
sftp.security.strictHostKeyChecking: true
streams_publishes:
PM_MEAS_FILES:
dmaap_info:
location: loc00
log_url: https://dmaap-dr-prov:8443/feedlog/1
password: pmmapper
publish_url: http://dmaap-dr-prov:8080/publish/1
publisher_id: 1.85gkg
username: pmmapper
type: data_router
streams_subscribes:
dmaap_subscriber:
dmaap_info:
topic_url: http://dmaap-message-router:3904/events/unauthenticated.VES_NOTIFICATION_OUTPUT
type: message_router

View File

@@ -0,0 +1,31 @@
spring:
profiles:
active: prod
management:
endpoints:
web:
exposure:
include: "loggers,logfile,health,info,metrics"
server:
port: 8433
ssl:
key-store-type: PKCS12
key-store-password: ericssondfc
key-store: classpath:keystore.jks
key-password: ericssondfc
keyAlias: tomcat-localhost
logging:
level:
ROOT: INFO
org.springframework: INFO
org.springframework.data: INFO
org.springframework.web.reactive.function.client.ExchangeFunctions: INFO
org.onap.dcaegen2.collectors.datafile: TRACE
org.onap.dcaegen2: TRACE
file: /var/log/ONAP/application.log
app:
filepath: config/datafile_endpoints_test.json
springdoc:
show-actuator: true
swagger-ui.disable-swagger-default-url: true

View File

@@ -0,0 +1,36 @@
pm-mapper-filter:
# filters:
# - pmDefVsn: "1.0"
# nfType: "gnb"
# vendor: "Nokia"
# measTypes:
# - attTCHSeizures
# - succTCHSeizures2
# - succImmediateAssignProcs8
filters: [] #disabling filters
key_store_path: "/opt/app/pm-mapper/etc/certs/cert.jks"
key_store_pass_path: "/opt/app/pm-mapper/etc/certs/jks.pass"
trust_store_path: "/opt/app/pm-mapper/etc/certs/trust.jks"
trust_store_pass_path: "/opt/app/pm-mapper/etc/certs/trust.pass"
dmaap_dr_delete_endpoint: "http://dmaap-dr-node:8080/delete"
dmaap_dr_feed_name: "1"
aaf_identity: "aaf_admin@people.osaaf.org"
aaf_password: "demo123456!"
enable_http: true
streams_publishes:
dmaap_publisher:
type: "message_router"
dmaap_info:
topic_url: "http://message-router:3904/events/unauthenticated.PERFORMANCE_MEASUREMENTS"
client_role: "org.onap.dcae.pmPublisher"
location: "csit-pmmapper"
client_id: "1562763644939"
streams_subscribes:
dmaap_subscriber:
type: "data_router"
dmaap_info:
username: "username"
password: "password"
location: "csit-pmmapper"
delivery_url: "http://dcae-pm-mapper:8081/delivery"
subscriber_id: 1

View File

@@ -0,0 +1,9 @@
{
"destination":"/opt/app/VESCollector/etc/externalRepo",
"repositories":[
{
"url":"https://forge.3gpp.org/rep/sa5/MnS.git",
"branch":"Rel-18"
}
]
}

View File

@@ -0,0 +1,226 @@
{
"ves-syslog": {
"type": "message_router",
"dmaap_info": {
"location": "mtl5",
"topic_url": "http://dmaap-message-router:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV"
}
},
"ves-statechange": {
"type": "message_router",
"dmaap_info": {
"location": "mtl5",
"topic_url": "http://dmaap-message-router:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV"
}
},
"ves-thresholdCrossingAlert": {
"type": "message_router",
"dmaap_info": {
"location": "mtl5",
"topic_url": "http://dmaap-message-router:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV"
}
},
"ves-heartbeat": {
"type": "message_router",
"dmaap_info": {
"location": "mtl5",
"topic_url": "http://dmaap-message-router:3904/events/unauthenticated.SEC_HEARTBEAT_OUTPUT/"
}
},
"ves-other": {
"type": "message_router",
"dmaap_info": {
"location": "mtl5",
"topic_url": "http://dmaap-message-router:3904/events/unauthenticated.SEC_OTHER_OUTPUT/"
}
},
"ves-mobileflow": {
"type": "message_router",
"dmaap_info": {
"location": "mtl5",
"topic_url": "http://dmaap-message-router:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV"
}
},
"ves-sipsignaling": {
"type": "message_router",
"dmaap_info": {
"location": "mtl5",
"topic_url": "http://dmaap-message-router:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV"
}
},
"ves-voicequality": {
"type": "message_router",
"dmaap_info": {
"location": "mtl5",
"topic_url": "http://dmaap-message-router:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV"
}
},
"ves-fault": {
"type": "message_router",
"dmaap_info": {
"location": "mtl5",
"topic_url": "http://dmaap-message-router:3904/events/unauthenticated.SEC_FAULT_OUTPUT/"
}
},
"ves-measurement": {
"type": "message_router",
"dmaap_info": {
"location": "mtl5",
"topic_url": "http://dmaap-message-router:3904/events/unauthenticated.VES_MEASUREMENT_OUTPUT/"
}
},
"ves-3gpp-fault-supervision": {
"type": "message_router",
"dmaap_info": {
"location": "mtl5",
"topic_url": "http://dmaap-message-router:3904/events/unauthenticated.SEC_3GPP_FAULTSUPERVISION_OUTPUT/"
}
},
"ves-3gpp-provisioning": {
"type": "message_router",
"dmaap_info": {
"location": "mtl5",
"topic_url": "http://dmaap-message-router:3904/events/unauthenticated.SEC_3GPP_PROVISIONING_OUTPUT/"
}
},
"ves-3gpp-heartbeat": {
"type": "message_router",
"dmaap_info": {
"location": "mtl5",
"topic_url": "http://dmaap-message-router:3904/events/unauthenticated.SEC_3GPP_HEARTBEAT_OUTPUT/"
}
},
"ves-3gpp-performance-assurance": {
"type": "message_router",
"dmaap_info": {
"location": "mtl5",
"topic_url": "http://dmaap-message-router:3904/events/unauthenticated.SEC_3GPP_PERFORMANCEASSURANCE_OUTPUT/"
}
},
"ves-syslog-secondary": {
"type": "message_router",
"dmaap_info": {
"location": "mtl5",
"topic_url": "http://dmaap-message-router:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV"
}
},
"ves-statechange-secondary": {
"type": "message_router",
"dmaap_info": {
"location": "mtl5",
"topic_url": "http://dmaap-message-router:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV"
}
},
"ves-thresholdCrossingAlert-secondary": {
"type": "message_router",
"dmaap_info": {
"location": "mtl5",
"topic_url": "http://dmaap-message-router:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV"
}
},
"ves-heartbeat-secondary": {
"type": "message_router",
"dmaap_info": {
"location": "mtl5",
"topic_url": "http://dmaap-message-router:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV"
}
},
"ves-other-secondary": {
"type": "message_router",
"dmaap_info": {
"location": "mtl5",
"topic_url": "http://dmaap-message-router:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV"
}
},
"ves-mobileflow-secondary": {
"type": "message_router",
"dmaap_info": {
"location": "mtl5",
"topic_url": "http://dmaap-message-router:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV"
}
},
"ves-sipsignaling-secondary": {
"type": "message_router",
"dmaap_info": {
"location": "mtl5",
"topic_url": "http://dmaap-message-router:3904/events/DCAE-SE-COLLECTOR-EVENTSves7_valid_ip_v4.json-DEV"
}
},
"ves-voicequality-secondary": {
"type": "message_router",
"dmaap_info": {
"location": "mtl5",
"topic_url": "http://dmaap-message-router:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV"
}
},
"ves-fault-secondary": {
"type": "message_router",
"dmaap_info": {
"location": "mtl5",
"topic_url": "http://dmaap-message-router:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV"
}
},
"ves-measurement-secondary": {
"type": "message_router",
"dmaap_info": {
"location": "mtl5",
"topic_url": "http://dmaap-message-router:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV"
}
},
"ves-3gpp-fault-supervision-secondary": {
"type": "message_router",
"dmaap_info": {
"location": "mtl5",
"topic_url": "http://dmaap-message-router:3904/events/unauthenticated.SEC_3GPP_FAULTSUPERVISION_OUTPUT"
}
},
"ves-3gpp-provisioning-secondary": {
"type": "message_router",
"dmaap_info": {
"location": "mtl5",
"topic_url": "http://dmaap-message-router:3904/events/unauthenticated.SEC_3GPP_FAULTSUPERVISION_OUTPUT"
}
},
"ves-3gpp-heartbeat-secondary": {
"type": "message_router",
"dmaap_info": {
"location": "mtl5",
"topic_url": "http://dmaap-message-router:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV"
}
},
"ves-3gpp-performance-assurance-secondary": {
"type": "message_router",
"dmaap_info": {
"location": "mtl5",
"topic_url": "http://dmaap-message-router:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV"
}
},
"ves-pnfRegistration": {
"type": "message_router",
"dmaap_info": {
"location": "mtl5",
"topic_url": "http://dmaap-message-router:3904/events/unauthenticated.VES_PNFREG_OUTPUT/"
}
},
"ves-o1-notify-pnf-registration": {
"type": "message_router",
"dmaap_info": {
"location": "mtl5",
"topic_url": "http://dmaap-message-router:3904/events/unauthenticated.VES_O1_NOTIFY_PNF_REGISTRATION_OUTPUT/"
}
},
"ves-o-ran-sc-du-hello-world-pm-streaming-oas3": {
"type": "message_router",
"dmaap_info": {
"location": "mtl5",
"topic_url": "http://dmaap-message-router:3904/events/unauthenticated.VES_O_RAN_SC_HELLO_WORLD_PM_STREAMING_OUTPUT/"
}
},
"ves-file-ready": {
"type": "message_router",
"dmaap_info": {
"location": "mtl5",
"topic_url": "http://dmaap-message-router:3904/events/unauthenticated.VES_FILE_READY_OUTPUT/"
}
}
}

View File

@@ -0,0 +1,16 @@
ARG BASEIMAGE=nexus3.onap.org:10001/onap/org.onap.dcaegen2.collectors.ves.vescollector:1.8.0
FROM ubuntu:22.04 AS stage-0
ARG DLREPO=https://forge.3gpp.org/rep/sa5/MnS.git
ARG DLBRANCH=Rel-18
RUN apt update && apt install -y python3 git
COPY install.py /
RUN python3 install.py $DLREPO $DLBRANCH /opt/app/VESCollector/etc/externalRepo
FROM ${BASEIMAGE}
COPY --from=stage-0 --chown=vescollector:vescollector /opt/app/VESCollector/etc/externalRepo /opt/app/VESCollector/etc/externalRepo

View File

@@ -0,0 +1,133 @@
#!/usr/bin/python3
import sys
import os
import subprocess
import json
import re
from typing import List
class Installer:
def __init__(self, url, branch, dstFolder) -> None:
self.downloadUrl = url
self.publicUrlFormat = self.createPublicUrlFormat(url, branch)
print(f'fmt={self.publicUrlFormat}')
self.branch = branch
self.baseFolder = dstFolder
self.subfolder = self.createSubFolder(url, branch)
def createPublicUrlFormat(self, url:str, branch:str)->str:
if url.endswith('.git'):
url = url[:-4]
if url.startswith('git@'):
url = 'https://'+url[4:]
fmt=url+'/raw/'+branch+'/{}'
return fmt
def createSubFolder(self, gitUrl:str, branch:str) -> str:
regex = r"^[^\/]+\/\/(.*)$"
matches = re.finditer(regex, gitUrl)
match = next(matches)
name = match.group(1)
if name.endswith('.git'):
name=name[:-4]
tmp:List[str]=[]
hlp1 = name.split('/')
for h in hlp1:
if '.' in h:
hlp2=h.split('.')
for h2 in hlp2:
tmp.append(h2)
else:
tmp.append(h)
return '/'.join(tmp)+'/'+branch
def getDstFolder(self)->str:
return f'{self.baseFolder}/{self.subfolder}'
def exec(self, cmd:str):
output = subprocess.Popen(
cmd, shell=True, stdout=subprocess.PIPE).stdout.read()
return output
def download(self) -> bool:
print(f'try to download repo {self.downloadUrl} to {self.getDstFolder()}')
self.exec(f'git clone --single-branch --branch {self.branch} {self.downloadUrl} {self.getDstFolder()}')
def getFilesFiltered(self, lst:List[str]=None, path=None, root=None, filter=['yaml','yml'])->List[str]:
if lst is None:
lst=[]
if root is None:
root=str(self.getDstFolder())
if path is None:
path=self.getDstFolder()
if os.path.exists(path) and os.path.isdir(path):
# Iterate over all files and directories in the given path
for filename in os.listdir(path):
if filename.startswith("."):
continue
fmatch=False
# Get the absolute path of the file/directory
abs_path = os.path.join(path, filename)
# If it is a directory, recursively call this function on it
if os.path.isdir(abs_path):
self.getFilesFiltered(lst=lst, path=abs_path, root=root, filter=filter )
# If it is a file, print its absolute path
elif os.path.isfile(abs_path):
for fi in filter:
if abs_path.endswith(fi):
fmatch=True
break
if not fmatch:
continue
relpath=abs_path[len(root)+1:]
lst.append(relpath)
return lst
def urlAlreadyInData(self, data:List[dict], pubUrl:str, key='publicURL'):
for item in data:
if key in item and item[key]==pubUrl:
return True
return False
def createSchemaMap(self):
schemaMapFile = f'{self.baseFolder}/schema-map.json'
if os.path.isfile(schemaMapFile):
with open(schemaMapFile) as fp:
data = json.load(fp)
else:
data:List[dict] = []
files = self.getFilesFiltered()
for file in files:
print(file)
pubUrl = self.publicUrlFormat.format(file)
if self.urlAlreadyInData(data,pubUrl):
print(f'entry with url {pubUrl} already exists. ignoring')
continue
data.append({
'publicURL': pubUrl,
'localURL': f'{self.subfolder}/{file}'
})
with open(schemaMapFile,'w') as fp:
json.dump(data,fp)
def printHelp():
print("Installation script for VES additional formats")
print(" usage: ")
print(" install.py DOWNLOAD-REPO BRANCH DESTINATION-FOLDER")
args = sys.argv
args.pop(0)
if len(args)<3:
print(f'bad parameters ${args}')
printHelp()
exit(1)
dlRepo = args.pop(0)
dlBranch = args.pop(0)
dst = args.pop(0)
installer = Installer(dlRepo, dlBranch, dst)
installer.download()
installer.createSchemaMap()

Some files were not shown because too many files have changed in this diff Show More