Update pipeline to cover all micro-services

This commit is contained in:
Amin Ben Romdhane 2025-05-08 17:34:23 +00:00 committed by IOPSYS Dev
parent c4701f0968
commit c7e783aecd
No known key found for this signature in database
20 changed files with 1002 additions and 1069 deletions

View file

@ -5,6 +5,14 @@ variables:
CPPCHECK_OPTIONS: "--suppress=cert-MSC24-C -DBBF_VENDOR_PREFIX=X_IOPSYS_EU_" CPPCHECK_OPTIONS: "--suppress=cert-MSC24-C -DBBF_VENDOR_PREFIX=X_IOPSYS_EU_"
CPD_OPTIONS: "--exclude ./build/ --minimum-tokens 200" CPD_OPTIONS: "--exclude ./build/ --minimum-tokens 200"
before_script:
- |
echo "
machine dev.iopsys.eu
login gitlab-ci-token
password $CI_JOB_TOKEN
" > ~/.netrc
include: include:
- project: 'iopsys/gitlab-ci-pipeline' - project: 'iopsys/gitlab-ci-pipeline'
file: '/static-code-analysis.yml' file: '/static-code-analysis.yml'
@ -26,7 +34,7 @@ run_unit_test:
allow_failure: false allow_failure: false
script: script:
- "./gitlab-ci/pipeline_setup.sh" - "./gitlab-ci/pipeline_setup.sh"
- "./gitlab-ci/install-dependencies.sh ms" - "./gitlab-ci/install-dependencies-ms.sh bbfdm"
- "./gitlab-ci/setup.sh ms" - "./gitlab-ci/setup.sh ms"
- "./gitlab-ci/unit-test.sh" - "./gitlab-ci/unit-test.sh"
@ -40,17 +48,10 @@ run_tools_test:
image: ${COMMON_IMAGE} image: ${COMMON_IMAGE}
allow_failure: false allow_failure: false
script: script:
- |
echo "
machine dev.iopsys.eu
login gitlab-ci-token
password $CI_JOB_TOKEN
" > ~/.netrc
- "./gitlab-ci/pipeline_setup.sh" - "./gitlab-ci/pipeline_setup.sh"
- "./gitlab-ci/setup.sh" - "./gitlab-ci/install-dependencies-ms.sh tools"
- "./gitlab-ci/tools-test.sh" - "./gitlab-ci/tools-test.sh"
- "./gitlab-ci/generate_supported_dm.sh" - "./gitlab-ci/generate_supported_dm.sh"
artifacts: artifacts:
when: always when: always
paths: paths:
@ -64,7 +65,7 @@ run_libbbfdm_api_functional_test:
allow_failure: false allow_failure: false
script: script:
- "./gitlab-ci/pipeline_setup.sh" - "./gitlab-ci/pipeline_setup.sh"
- "./gitlab-ci/install-dependencies.sh ms" - "./gitlab-ci/install-dependencies-ms.sh bbfdm"
- "./gitlab-ci/setup.sh ms" - "./gitlab-ci/setup.sh ms"
- "./gitlab-ci/functional-api-test.sh" - "./gitlab-ci/functional-api-test.sh"
@ -79,7 +80,7 @@ run_libbbfdm_functional_test:
allow_failure: false allow_failure: false
script: script:
- "./gitlab-ci/pipeline_setup.sh" - "./gitlab-ci/pipeline_setup.sh"
- "./gitlab-ci/install-dependencies.sh ms" - "./gitlab-ci/install-dependencies-ms.sh bbfdm"
- "./gitlab-ci/setup.sh ms" - "./gitlab-ci/setup.sh ms"
- "./gitlab-ci/functional-test.sh" - "./gitlab-ci/functional-test.sh"
@ -94,7 +95,7 @@ run_libbbfdm_memory_test:
allow_failure: false allow_failure: false
script: script:
- "./gitlab-ci/pipeline_setup.sh" - "./gitlab-ci/pipeline_setup.sh"
- "./gitlab-ci/install-dependencies.sh ms" - "./gitlab-ci/install-dependencies-ms.sh bbfdm"
- "./gitlab-ci/setup.sh ms" - "./gitlab-ci/setup.sh ms"
- "./gitlab-ci/memory-test.sh" - "./gitlab-ci/memory-test.sh"
artifacts: artifacts:
@ -109,7 +110,7 @@ run_bbfd_functional_test:
allow_failure: false allow_failure: false
script: script:
- "./gitlab-ci/pipeline_setup.sh" - "./gitlab-ci/pipeline_setup.sh"
- "./gitlab-ci/install-dependencies.sh ms" - "./gitlab-ci/install-dependencies-ms.sh bbfdm"
- "./gitlab-ci/setup.sh ms" - "./gitlab-ci/setup.sh ms"
- "./gitlab-ci/bbfdmd-functional-test.sh" - "./gitlab-ci/bbfdmd-functional-test.sh"
artifacts: artifacts:

View file

@ -24,15 +24,6 @@ echo "Checking system resources"
free -h free -h
df -h df -h
# Check if the specified log file exists, which indicates errors during plugin loading
if [ -f ${BBFDM_LOG_FILE} ]; then
echo "Some plugins failed to load! Please check the errors below"
echo "*****************************************************"
cat "${BBFDM_LOG_FILE}"
echo "*****************************************************"
exit 1
fi
echo "## Running python based verification of functionalities ##" echo "## Running python based verification of functionalities ##"
echo > ./funl-result.log echo > ./funl-result.log
num=0 num=0

View file

@ -0,0 +1,131 @@
[program:sysmngr]
priority=10
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-sysmngr-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/sysmngr -l 3"
[program:netmngr]
priority=10
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-netmngr-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/dm-service -m netmngr -l 3"
[program:wifidmd]
priority=10
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-wifidmd-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/wifidmd -l 3"
[program:core]
priority=10
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-core-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/dm-service -m core -l 3"
[program:ethmngr]
priority=10
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-ethmngr-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/ethmngr -l 3"
[program:icwmp]
priority=10
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-icwmp-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/dm-service -m icwmp -l 3"
[program:bulkdata]
priority=10
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-bulkdata-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/bulkdatad -l 3"
[program:periodicstats]
priority=10
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-periodicstats-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/periodicstatsd -l 3"
[program:ponmngr]
priority=10
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-ponmngr-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/dm-service -m ponmngr -l 3"
[program:ssdpd]
priority=10
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-ssdpd-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/dm-service -m ssdpd -l 3"
[program:swmodd]
priority=10
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-swmodd-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/dm-service -m swmodd -l 3"
[program:usermngr]
priority=10
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-usermngr-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/usermngr -l 3"
[program:parentalcontrol]
priority=10
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-parentalcontrol-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/urlfilter -l 3"
[program:hostmngr]
priority=10
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-hostmngr-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/dm-service -m hostmngr -l 3"
[program:timemngr]
priority=10
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-timemngr-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/timemngr -l 3"
[program:dnsmngr]
priority=10
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-dnsmngr-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/dm-service -m dnsmngr -l 3"
[program:dhcpmngr]
priority=10
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-dhcpmngr-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/dm-service -m dhcpmngr -l 3"
[program:qosmngr]
priority=10
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-qosmngr-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/qosmngr -l 3"
[program:tr104]
priority=10
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-tr104-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/dm-service -m tr104 -l 3"
[program:mcastmngr]
priority=10
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-mcastmngr-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/dm-service -m mcastmngr -l 3"
[program:ieee1905]
priority=10
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-ieee1905-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/dm-service -m ieee1905 -l 3"
[program:bridgemngr]
priority=10
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-bridgemngr-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/dm-service -m bridgemngr -l 3"
[program:ddnsmngr]
priority=10
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-ddnsmngr-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/dm-service -m ddnsmngr -l 3"
[program:sshmngr]
priority=10
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-sshmngr-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/dm-service -m sshmngr -l 3"
[program:firewallmngr]
priority=10
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-firewallmngr-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/dm-service -m firewallmngr -l 3"
[program:dslmngr]
priority=10
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-dslmngr-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/dm-service -m dslmngr -l 3"
[program:usbmngr]
priority=10
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-usbmngr-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/dm-service -m usbmngr -l 3"
[program:obuspa]
priority=10
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-obuspa-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/dm-service -m obuspa -l 3"
[program:gnx-ux-manager]
priority=10
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-gnx-ux-manager-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/dm-service -m gnx-ux-manager -l 3"
[program:gnx-catv]
priority=10
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-gnx-catv-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/dm-service -m gnx-catv -l 3"
[program:dhcp-on-boarding]
priority=10
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-dhcp-on-boarding-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/dm-service -m dhcp-on-boarding -l 3"
[program:gnx-loop-detector]
priority=10
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-gnx-loop-detector-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/dm-service -m gnx-loop-detector -l 3"
[program:gnx-sfp]
priority=10
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-gnx-sfp-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/dm-service -m gnx-sfp -l 3"

View file

@ -15,15 +15,6 @@ if [ -n "${CI_SERVER_HOST}" ]; then
echo "password ${CI_JOB_TOKEN}" >>~/.netrc echo "password ${CI_JOB_TOKEN}" >>~/.netrc
fi fi
install_cmph
install_libeasy
install_libethernet
install_libqos
[ ! -d "${BBFDM_MS_DIR}" ] && mkdir -p "${BBFDM_MS_DIR}"
rm -rf ${BBFDM_MS_DIR}/*
mkdir -p ${BBFDM_MS_DIR}/core
if [ -z "${1}" ]; then if [ -z "${1}" ]; then
./tools/generate_dm.py tools/tools_input.json ./tools/generate_dm.py tools/tools_input.json
else else
@ -45,13 +36,4 @@ echo "Validate datamodel_default generated XML file"
xmllint --schema test/tools/cwmp-datamodel-*.xsd out/datamodel_default.xml --noout xmllint --schema test/tools/cwmp-datamodel-*.xsd out/datamodel_default.xml --noout
check_ret $? check_ret $?
# Check if the specified log file exists, which indicates errors during plugin loading
if [ -f ${BBFDM_LOG_FILE} ]; then
echo "Some plugins failed to load! Please check the errors below"
echo "*****************************************************"
cat "${BBFDM_LOG_FILE}"
echo "*****************************************************"
exit 1
fi
echo "Generation of xml and xls artifacts :: PASS" echo "Generation of xml and xls artifacts :: PASS"

View file

@ -0,0 +1,109 @@
#!/bin/bash
echo "install dependencies of bbfdm"
source ./gitlab-ci/shared.sh
# install required packages
exec_cmd apt update
exec_cmd pip3 install xlwt
# Create directories for micro-service configuration and shared files
[ ! -d "${BBFDM_MS_CONF}" ] && mkdir -p "${BBFDM_MS_CONF}"
[ ! -d "${BBFDM_MS_DIR}" ] && mkdir -p "${BBFDM_MS_DIR}"
# Clean up generated files
rm -rf ${BBFDM_MS_DIR}/*
rm -f ${BBFDM_MS_CONF}/*
rm -f ${BBFDM_DMMAP_DIR}/*
# compile and install Core Data Model as a micro-service
install_libbbf ${1}
if [ "$1" == "bbfdm" ]; then
#compile and install libbbf_test dynamic extension library
install_libbbf_test
fi
# Install datamodel plugins/micro-service only when pipeline trigger for bbfdm
if [ -z "${1}" ]; then
echo "Skip installation of micro-services ...."
else
JSON_FILE=$BBFDM_TOOLS_INPUT_FILE
JSON_DESC_PATH="/tmp/desc_files"
plugin_count=$(jq '.plugins | length' "$JSON_FILE")
# Create desc_files directory
[ -d "${JSON_DESC_PATH}" ] && rm -f ${JSON_DESC_PATH}
mkdir -p ${JSON_DESC_PATH}
for i in $(seq 0 $((plugin_count - 1))); do
echo "==== Processing plugin [$i] ===="
repo=$(jq -r ".plugins[$i].repo" "$JSON_FILE")
version=$(jq -r ".plugins[$i].version" "$JSON_FILE")
plugin_name=$(basename "$repo" .git)
dest="$BBFDM_PLUGIN_DEST/$plugin_name"
# Adjust repo URL based on ~/.netrc existence
NETRC_PATH="$HOME/.netrc"
if [ ! -f "$NETRC_PATH" ]; then
repo=${repo/https:\/\/dev.iopsys.eu\//git@dev.iopsys.eu:}
fi
echo "Repo path: $repo"
echo "Plugin name: $plugin_name"
echo "Destination: $dest"
# Install dependencies
if [ "$plugin_name" == "ethmngr" ]; then
install_libeasy
install_libethernet
install_libqos
fi
if [ "$plugin_name" == "parental-control" ]; then
install_cmph
fi
if [ -d "$dest" ]; then
echo "Directory $dest already exists, skipping clone."
else
echo "Cloning $repo into $dest..."
git clone -b "$version" "$repo" "$dest" || { echo "❌ Git clone failed"; exit -1; }
fi
cd $dest
# Compilation
echo "Starting compilation..."
jq -r ".plugins[$i].compile[]" "$JSON_FILE" | while read -r cmd; do
echo "Executing: $cmd"
eval "$cmd" || { echo "❌ Compilation command failed"; exit -1; }
done
# Post-install
echo "Running post-install steps..."
jq -r ".plugins[$i].post_install[]" "$JSON_FILE" 2>/dev/null | while read -r post_cmd; do
echo "Executing: $post_cmd"
eval "$post_cmd" || { echo "❌ Post-install command failed"; exit -1; }
done
# Save dm_info_file if defined
dm_info_file=$(jq -r ".plugins[$i].dm_info_file // empty" "$JSON_FILE")
if [ -n "$dm_info_file" ]; then
src_file="$dest/$dm_info_file"
out_file="/tmp/desc_files/${i}_${plugin_name}.json"
if [ -f "$src_file" ]; then
echo "Saving dm_info_file to $out_file"
cp -f "$src_file" "$out_file"
else
echo "❌ dm_info_file not found: $src_file"
fi
fi
cd $(pwd)
echo "✅ Plugin [$plugin_name] build complete."
done
fi

View file

@ -16,7 +16,6 @@ exec_cmd pip3 install xlwt
rm -rf ${BBFDM_MS_DIR}/* rm -rf ${BBFDM_MS_DIR}/*
rm -f ${BBFDM_MS_CONF}/* rm -f ${BBFDM_MS_CONF}/*
rm -f ${BBFDM_DMMAP_DIR}/* rm -f ${BBFDM_DMMAP_DIR}/*
rm -f ${BBFDM_LOG_FILE}
# compile and install Core Data Model as a micro-service # compile and install Core Data Model as a micro-service
install_libbbf ${1} install_libbbf ${1}

View file

@ -58,8 +58,9 @@ supervisorctl stop all
supervisorctl status supervisorctl status
cp /tmp/memory-*.xml . cp /tmp/memory-*.xml .
check_valgrind_xml "memory-report.xml" "bbfdmd" for file in memory-*.xml; do
check_valgrind_xml "memory-config-report.xml" "bbf.config" check_valgrind_xml "$file"
done
#report part #report part
#GitLab-CI output #GitLab-CI output

View file

@ -26,7 +26,11 @@ cp ./gitlab-ci/core_service.conf /etc/supervisor/conf.d/
cp ./gitlab-ci/reload_service.conf /etc/supervisor/conf.d/ cp ./gitlab-ci/reload_service.conf /etc/supervisor/conf.d/
if [ -n "$1" ]; then if [ -n "$1" ]; then
cp ./gitlab-ci/micro_service.conf /etc/supervisor/conf.d/ if [ "$1" == "bbfdm" ]; then
cp ./gitlab-ci/full_micro_service.conf /etc/supervisor/conf.d/
else
cp ./gitlab-ci/micro_service.conf /etc/supervisor/conf.d/
fi
fi fi
rm -f /etc/bbfdm/dmmap/* rm -f /etc/bbfdm/dmmap/*

View file

@ -1,9 +1,10 @@
#!/bin/bash #!/bin/bash
BBFDM_TOOLS_INPUT_FILE="$(pwd)/tools/tools_input.json"
BBFDM_PLUGIN_DEST="/opt/dev"
BBFDM_MS_DIR="/usr/share/bbfdm/micro_services" BBFDM_MS_DIR="/usr/share/bbfdm/micro_services"
BBFDM_MS_CONF="/etc/bbfdm/services" BBFDM_MS_CONF="/etc/bbfdm/services"
BBFDM_DMMAP_DIR="etc/bbfdm/dmmap/" BBFDM_DMMAP_DIR="etc/bbfdm/dmmap/"
BBFDM_LOG_FILE="/tmp/bbfdm.log"
if [ -z "${CI_PROJECT_PATH}" ]; then if [ -z "${CI_PROJECT_PATH}" ]; then
CI_PROJECT_PATH=${PWD} CI_PROJECT_PATH=${PWD}
@ -55,10 +56,15 @@ function install_ms_plugin()
exec_cmd cp -f "${1}" ${BBFDM_MS_DIR}/${2}/ exec_cmd cp -f "${1}" ${BBFDM_MS_DIR}/${2}/
} }
function install_ms_config()
{
exec_cmd cp -f "${1}" ${BBFDM_MS_CONF}/${2}.json
}
function install_libbbf() function install_libbbf()
{ {
# Enable coverage flags only for test # Enable coverage flags only for bbfdm test
if [ -z "${1}" ]; then if [ "$1" == "bbfdm" ]; then
COV_CFLAGS='-fprofile-arcs -ftest-coverage' COV_CFLAGS='-fprofile-arcs -ftest-coverage'
COV_LDFLAGS='--coverage' COV_LDFLAGS='--coverage'
fi fi
@ -72,7 +78,27 @@ function install_libbbf()
mkdir -p build mkdir -p build
cd build cd build
cmake ../ -DCMAKE_C_FLAGS="$COV_CFLAGS " -DCMAKE_EXE_LINKER_FLAGS="$COV_LDFLAGS -lm" -DBBF_VENDOR_PREFIX="$VENDOR_PREFIX" -DBBF_MAX_OBJECT_INSTANCES=255 -DBBFDMD_MAX_MSG_LEN=1048576 -DCMAKE_INSTALL_PREFIX=/
# Construct the CMake command as an array for safety
cmake_args=(
../
-DCMAKE_C_FLAGS="$COV_CFLAGS"
-DCMAKE_EXE_LINKER_FLAGS="$COV_LDFLAGS -lm"
-DBBF_VENDOR_PREFIX="$VENDOR_PREFIX"
-DBBF_MAX_OBJECT_INSTANCES=255
-DBBFDMD_MAX_MSG_LEN=1048576
-DCMAKE_INSTALL_PREFIX=/
)
# Add this flag only if $1 is "tools"
if [ "$1" == "tools" ]; then
cmake_args+=(-DBBF_SCHEMA_FULL_TREE=ON)
fi
# Run cmake with arguments
cmake "${cmake_args[@]}"
# Compile and install
exec_cmd_verbose make exec_cmd_verbose make
echo "installing libbbf" echo "installing libbbf"
@ -80,7 +106,8 @@ function install_libbbf()
echo "371d530c95a17d1ca223a29b7a6cdc97e1135c1e0959b51106cca91a0b148b5e42742d372a359760742803f2a44bd88fca67ccdcfaeed26d02ce3b6049cb1e04" > /etc/bbfdm/.secure_hash echo "371d530c95a17d1ca223a29b7a6cdc97e1135c1e0959b51106cca91a0b148b5e42742d372a359760742803f2a44bd88fca67ccdcfaeed26d02ce3b6049cb1e04" > /etc/bbfdm/.secure_hash
cd .. cd ..
exec_cmd cp utilities/bbf_configd /usr/sbin/ exec_cmd cp utilities/bbf_configd /usr/sbin/
install_ms /usr/lib/libcore.so core exec_cmd cp -f utilities/files/usr/share/bbfdm/scripts/bbf_api /usr/share/bbfdm/scripts/
install_ms build/libbbfdm/libcore.so core
} }
function install_libbbf_test() function install_libbbf_test()
@ -96,22 +123,22 @@ function install_libbbf_test()
function install_wifidmd_as_micro_service() function install_wifidmd_as_micro_service()
{ {
[ -d "/opt/dev/wifidmd" ] && return 0 [ -d "${BBFDM_PLUGIN_DEST}/wifidmd" ] && return 0
exec_cmd git clone https://dev.iopsys.eu/bbf/wifidmd.git /opt/dev/wifidmd exec_cmd git clone https://dev.iopsys.eu/bbf/wifidmd.git ${BBFDM_PLUGIN_DEST}/wifidmd
exec_cmd make -C /opt/dev/wifidmd/src/ clean && make -C /opt/dev/wifidmd/src/ WIFIDMD_ENABLE_WIFI_DATAELEMENTS='y' exec_cmd make -C ${BBFDM_PLUGIN_DEST}/wifidmd/src/ clean && make -C ${BBFDM_PLUGIN_DEST}/wifidmd/src/ WIFIDMD_ENABLE_WIFI_DATAELEMENTS='y'
exec_cmd cp -f /opt/dev/wifidmd/src/wifidmd /usr/sbin/ exec_cmd cp -f ${BBFDM_PLUGIN_DEST}/wifidmd/src/wifidmd /usr/sbin/
} }
function install_libeasy() function install_libeasy()
{ {
[ -d "/opt/dev/libeasy" ] && return 0 [ -d "${BBFDM_PLUGIN_DEST}/libeasy" ] && return 0
exec_cmd git clone https://dev.iopsys.eu/iopsys/libeasy.git /opt/dev/libeasy exec_cmd git clone https://dev.iopsys.eu/iopsys/libeasy.git ${BBFDM_PLUGIN_DEST}/libeasy
( (
cd /opt/dev/libeasy cd ${BBFDM_PLUGIN_DEST}/libeasy
exec_cmd make exec_cmd make
sudo mkdir -p /usr/include/easy sudo mkdir -p /usr/include/easy
sudo cp -a libeasy*.so* /usr/lib sudo cp -a libeasy*.so* /usr/lib
@ -121,12 +148,12 @@ function install_libeasy()
function install_libqos() function install_libqos()
{ {
[ -d "/opt/dev/libqos" ] && return 0 [ -d "${BBFDM_PLUGIN_DEST}/libqos" ] && return 0
exec_cmd git clone https://dev.iopsys.eu/hal/libqos.git /opt/dev/libqos exec_cmd git clone https://dev.iopsys.eu/hal/libqos.git ${BBFDM_PLUGIN_DEST}/libqos
( (
cd /opt/dev/libqos cd ${BBFDM_PLUGIN_DEST}/libqos
exec_cmd make exec_cmd make
sudo mkdir -p /usr/include/ sudo mkdir -p /usr/include/
sudo cp -a libqos*.so* /usr/lib/ sudo cp -a libqos*.so* /usr/lib/
@ -136,11 +163,11 @@ function install_libqos()
function install_libethernet() function install_libethernet()
{ {
[ -d "/opt/dev/libethernet" ] && return 0 [ -d "${BBFDM_PLUGIN_DEST}/libethernet" ] && return 0
exec_cmd git clone https://dev.iopsys.eu/iopsys/libethernet.git /opt/dev/libethernet exec_cmd git clone https://dev.iopsys.eu/iopsys/libethernet.git ${BBFDM_PLUGIN_DEST}/libethernet
( (
cd /opt/dev/libethernet cd ${BBFDM_PLUGIN_DEST}/libethernet
make PLATFORM=TEST make PLATFORM=TEST
sudo cp ethernet.h /usr/include sudo cp ethernet.h /usr/include
sudo cp -a libethernet*.so* /usr/lib sudo cp -a libethernet*.so* /usr/lib
@ -150,56 +177,56 @@ function install_libethernet()
function install_ethmngr_as_micro_service() function install_ethmngr_as_micro_service()
{ {
[ -d "/opt/dev/ethmngr" ] && return 0 [ -d "${BBFDM_PLUGIN_DEST}/ethmngr" ] && return 0
install_libeasy install_libeasy
install_libethernet install_libethernet
install_libqos install_libqos
exec_cmd git clone https://dev.iopsys.eu/hal/ethmngr.git /opt/dev/ethmngr exec_cmd git clone https://dev.iopsys.eu/hal/ethmngr.git ${BBFDM_PLUGIN_DEST}/ethmngr
exec_cmd make -C /opt/dev/ethmngr exec_cmd make -C ${BBFDM_PLUGIN_DEST}/ethmngr
exec_cmd sudo cp -f /opt/dev/ethmngr/ethmngr /usr/sbin/ethmngr exec_cmd sudo cp -f ${BBFDM_PLUGIN_DEST}/ethmngr/ethmngr /usr/sbin/ethmngr
} }
function install_netmngr_as_micro_service() function install_netmngr_as_micro_service()
{ {
[ -d "/opt/dev/netmngr" ] && return 0 [ -d "${BBFDM_PLUGIN_DEST}/netmngr" ] && return 0
exec_cmd git clone -b devel https://dev.iopsys.eu/network/netmngr.git /opt/dev/netmngr exec_cmd git clone -b devel https://dev.iopsys.eu/network/netmngr.git ${BBFDM_PLUGIN_DEST}/netmngr
exec_cmd apt install iproute2 -y exec_cmd apt install iproute2 -y
exec_cmd make -C /opt/dev/netmngr/src/ clean exec_cmd make -C ${BBFDM_PLUGIN_DEST}/netmngr/src/ clean
exec_cmd make -C /opt/dev/netmngr/src/ NETMNGR_GRE_OBJ=y NETMNGR_IP_OBJ=y NETMNGR_ROUTING_OBJ=y NETMNGR_PPP_OBJ=y NETMNGR_ROUTER_ADVERTISEMENT_OBJ=y NETMNGR_IPV6RD_OBJ=y exec_cmd make -C ${BBFDM_PLUGIN_DEST}/netmngr/src/ NETMNGR_GRE_OBJ=y NETMNGR_IP_OBJ=y NETMNGR_ROUTING_OBJ=y NETMNGR_PPP_OBJ=y NETMNGR_ROUTER_ADVERTISEMENT_OBJ=y NETMNGR_IPV6RD_OBJ=y
install_ms /opt/dev/netmngr/src/libnetmngr.so netmngr install_ms ${BBFDM_PLUGIN_DEST}/netmngr/src/libnetmngr.so netmngr
exec_cmd git clone https://dev.iopsys.eu/bbf/tr143d.git /opt/dev/tr143d exec_cmd git clone https://dev.iopsys.eu/bbf/tr143d.git ${BBFDM_PLUGIN_DEST}/tr143d
exec_cmd make -C /opt/dev/tr143d/src/ clean && make -C /opt/dev/tr143d/src/ exec_cmd make -C ${BBFDM_PLUGIN_DEST}/tr143d/src/ clean && make -C ${BBFDM_PLUGIN_DEST}/tr143d/src/
exec_cmd cp -f utilities/files/usr/share/bbfdm/scripts/bbf_api /usr/share/bbfdm/scripts/ exec_cmd cp -f utilities/files/usr/share/bbfdm/scripts/bbf_api /usr/share/bbfdm/scripts/
exec_cmd cp -rf /opt/dev/tr143d/scripts/* /usr/share/bbfdm/scripts/ exec_cmd cp -rf ${BBFDM_PLUGIN_DEST}/tr143d/scripts/* /usr/share/bbfdm/scripts/
install_ms_plugin /opt/dev/tr143d/src/libtr143d.so netmngr install_ms_plugin ${BBFDM_PLUGIN_DEST}/tr143d/src/libtr143d.so netmngr
exec_cmd git clone https://dev.iopsys.eu/bbf/tr471d.git /opt/dev/tr471d exec_cmd git clone https://dev.iopsys.eu/bbf/tr471d.git ${BBFDM_PLUGIN_DEST}/tr471d
exec_cmd make -C /opt/dev/tr471d/src/ clean && make -C /opt/dev/tr471d/src/ exec_cmd make -C ${BBFDM_PLUGIN_DEST}/tr471d/src/ clean && make -C ${BBFDM_PLUGIN_DEST}/tr471d/src/
install_ms_plugin /opt/dev/tr471d/src/libtr471d.so netmngr install_ms_plugin ${BBFDM_PLUGIN_DEST}/tr471d/src/libtr471d.so netmngr
exec_cmd git clone https://dev.iopsys.eu/bbf/twamp-light.git /opt/dev/twamp exec_cmd git clone https://dev.iopsys.eu/bbf/twamp-light.git ${BBFDM_PLUGIN_DEST}/twamp
exec_cmd make -C /opt/dev/twamp clean && make -C /opt/dev/twamp exec_cmd make -C ${BBFDM_PLUGIN_DEST}/twamp clean && make -C ${BBFDM_PLUGIN_DEST}/twamp
install_ms_plugin /opt/dev/twamp/libtwamp.so netmngr install_ms_plugin ${BBFDM_PLUGIN_DEST}/twamp/libtwamp.so netmngr
exec_cmd git clone https://dev.iopsys.eu/bbf/udpecho.git /opt/dev/udpecho exec_cmd git clone https://dev.iopsys.eu/bbf/udpecho.git ${BBFDM_PLUGIN_DEST}/udpecho
exec_cmd make -C /opt/dev/udpecho/src/ clean && make -C /opt/dev/udpecho/src/ exec_cmd make -C ${BBFDM_PLUGIN_DEST}/udpecho/src/ clean && make -C ${BBFDM_PLUGIN_DEST}/udpecho/src/
install_ms_plugin /opt/dev/udpecho/src/libudpechoserver.so netmngr install_ms_plugin ${BBFDM_PLUGIN_DEST}/udpecho/src/libudpechoserver.so netmngr
} }
function install_sysmngr_as_micro_service() function install_sysmngr_as_micro_service()
{ {
[ -d "/opt/dev/sysmngr" ] && return 0 [ -d "${BBFDM_PLUGIN_DEST}/sysmngr" ] && return 0
exec_cmd git clone -b devel https://dev.iopsys.eu/system/sysmngr.git /opt/dev/sysmngr exec_cmd git clone -b devel https://dev.iopsys.eu/system/sysmngr.git ${BBFDM_PLUGIN_DEST}/sysmngr
exec_cmd make -C /opt/dev/sysmngr/src/ clean && \ exec_cmd make -C ${BBFDM_PLUGIN_DEST}/sysmngr/src/ clean && \
exec_cmd make -C /opt/dev/sysmngr/src/ \ exec_cmd make -C ${BBFDM_PLUGIN_DEST}/sysmngr/src/ \
CFLAGS+="-DBBF_VENDOR_PREFIX=\\\"X_IOWRT_EU_\\\"" \ CFLAGS+="-DBBF_VENDOR_PREFIX=\\\"X_IOWRT_EU_\\\"" \
SYSMNGR_VENDOR_CONFIG_FILE='y' \ SYSMNGR_VENDOR_CONFIG_FILE='y' \
SYSMNGR_MEMORY_STATUS='y' \ SYSMNGR_MEMORY_STATUS='y' \
@ -211,7 +238,7 @@ function install_sysmngr_as_micro_service()
SYSMNGR_VENDOR_EXTENSIONS='y' \ SYSMNGR_VENDOR_EXTENSIONS='y' \
SYSMNGR_FWBANK_UBUS_SUPPORT='y' SYSMNGR_FWBANK_UBUS_SUPPORT='y'
exec_cmd cp -f /opt/dev/sysmngr/src/sysmngr /usr/sbin/ exec_cmd cp -f ${BBFDM_PLUGIN_DEST}/sysmngr/src/sysmngr /usr/sbin/
exec_cmd mkdir /etc/sysmngr exec_cmd mkdir /etc/sysmngr
} }
@ -239,15 +266,14 @@ function generate_report()
function install_cmph() function install_cmph()
{ {
[ -d "/opt/dev/cmph" ] && return 0 [ -d "${BBFDM_PLUGIN_DEST}/cmph" ] && return 0
exec_cmd git clone https://git.code.sf.net/p/cmph/git /opt/dev/cmph exec_cmd git clone https://git.code.sf.net/p/cmph/git ${BBFDM_PLUGIN_DEST}/cmph
( (
cd /opt/dev/cmph cd ${BBFDM_PLUGIN_DEST}/cmph
exec_cmd autoreconf -i exec_cmd autoreconf -i
exec_cmd ./configure exec_cmd ./configure
exec_cmd make exec_cmd make
exec_cmd sudo make install exec_cmd sudo make install
) )
} }

View file

@ -32,7 +32,7 @@ for plugin in $(ls -1 test/vendor_test/*); do
check_ret $? check_ret $?
done done
echo "Validate Data Model JSON Plugin after generating from TR-181, TR-104 and TR-135 XML Files" echo "Validate Data Model JSON Plugin after generating from TR-181 and TR-104 XML Files"
json_path=$(./tools/convert_dm_xml_to_json.py -d test/tools/) json_path=$(./tools/convert_dm_xml_to_json.py -d test/tools/)
./tools/validate_json_plugin.py $json_path ./tools/validate_json_plugin.py $json_path
check_ret $? check_ret $?

View file

@ -62,16 +62,9 @@ static void dotso_plugin_disable_requested_entries(DMOBJ *entryobj, DMOBJ *reque
int load_dotso_plugins(DMOBJ *entryobj, const char *plugin_path) int load_dotso_plugins(DMOBJ *entryobj, const char *plugin_path)
{ {
#ifndef BBF_SCHEMA_FULL_TREE
void *handle = dlopen(plugin_path, RTLD_NOW|RTLD_LOCAL); void *handle = dlopen(plugin_path, RTLD_NOW|RTLD_LOCAL);
#else
void *handle = dlopen(plugin_path, RTLD_LAZY);
#endif
if (!handle) { if (!handle) {
char *err_msg = dlerror(); char *err_msg = dlerror();
#ifdef BBF_SCHEMA_FULL_TREE
TRACE_FILE("Failed to add DotSo plugin '%s', [%s]\n", plugin_path, err_msg);
#endif
BBF_ERR("Failed to add DotSo plugin '%s', [%s]\n", plugin_path, err_msg); BBF_ERR("Failed to add DotSo plugin '%s', [%s]\n", plugin_path, err_msg);
return 0; return 0;
} }
@ -82,9 +75,6 @@ int load_dotso_plugins(DMOBJ *entryobj, const char *plugin_path)
if (dynamic_obj == NULL) { if (dynamic_obj == NULL) {
dlclose(handle); dlclose(handle);
#ifdef BBF_SCHEMA_FULL_TREE
TRACE_FILE("Plugin %s missing init symbol ...\n", plugin_path);
#endif
BBF_ERR("Plugin %s missing init symbol ...", plugin_path); BBF_ERR("Plugin %s missing init symbol ...", plugin_path);
return 0; return 0;
} }
@ -93,9 +83,6 @@ int load_dotso_plugins(DMOBJ *entryobj, const char *plugin_path)
DMOBJ *dm_entryobj = find_entry_obj(entryobj, dynamic_obj[i].path); DMOBJ *dm_entryobj = find_entry_obj(entryobj, dynamic_obj[i].path);
if (!dm_entryobj) { if (!dm_entryobj) {
#ifdef BBF_SCHEMA_FULL_TREE
TRACE_FILE("Failed to add DotSo plugin '%s' to main tree with parent DM index '%d' => '%s'", plugin_path, i, dynamic_obj[i].path);
#endif
BBF_ERR("Failed to add DotSo plugin '%s' to main tree with parent DM index '%d' => '%s'", plugin_path, i, dynamic_obj[i].path); BBF_ERR("Failed to add DotSo plugin '%s' to main tree with parent DM index '%d' => '%s'", plugin_path, i, dynamic_obj[i].path);
continue; continue;
} }

View file

@ -11,12 +11,6 @@ IF(${BBFDMD_MAX_MSG_LEN})
ADD_DEFINITIONS(-DBBFDM_MAX_MSG_LEN=${BBFDMD_MAX_MSG_LEN}) ADD_DEFINITIONS(-DBBFDM_MAX_MSG_LEN=${BBFDMD_MAX_MSG_LEN})
ENDIF() ENDIF()
OPTION(BBF_SCHEMA_FULL_TREE "build with schema full tree" OFF)
IF(BBF_SCHEMA_FULL_TREE)
add_compile_definitions(BBF_SCHEMA_FULL_TREE)
ENDIF(BBF_SCHEMA_FULL_TREE)
FILE(GLOB BBF_UBUS_SOURCES *.c) FILE(GLOB BBF_UBUS_SOURCES *.c)
ADD_LIBRARY(bbfdm-ubus SHARED ${BBF_UBUS_SOURCES}) ADD_LIBRARY(bbfdm-ubus SHARED ${BBF_UBUS_SOURCES})

View file

@ -259,10 +259,6 @@ static int bbfdm_schema_handler(struct ubus_context *ctx, struct ubus_object *ob
data.bbf_ctx.isinfo = (dm_type == BBFDM_CWMP) ? false : true; data.bbf_ctx.isinfo = (dm_type == BBFDM_CWMP) ? false : true;
data.plist = &paths_list; data.plist = &paths_list;
#ifdef BBF_SCHEMA_FULL_TREE
data.bbf_ctx.isinfo = true;
bbfdm_get(&data, BBF_SCHEMA);
#else
if (dm_type == BBFDM_CWMP) { if (dm_type == BBFDM_CWMP) {
char *service_name = strdup(u->config.service_name); char *service_name = strdup(u->config.service_name);
data.bbf_ctx.in_value = (dm_type == BBFDM_CWMP) ? service_name : NULL; data.bbf_ctx.in_value = (dm_type == BBFDM_CWMP) ? service_name : NULL;
@ -271,7 +267,6 @@ static int bbfdm_schema_handler(struct ubus_context *ctx, struct ubus_object *ob
} else { } else {
bbfdm_get(&data, BBF_SCHEMA); bbfdm_get(&data, BBF_SCHEMA);
} }
#endif
free_path_list(&paths_list); free_path_list(&paths_list);
return 0; return 0;

View file

@ -19,8 +19,21 @@
}, },
{ {
"parent_dm": "Device.", "parent_dm": "Device.",
"object": "GatewayInfo" "object": "PacketCaptureDiagnostics"
}, },
{
"parent_dm": "Device.",
"object": "SelfTestDiagnostics"
},
{
"parent_dm": "Device.",
"object": "Syslog"
},
{
"parent_dm": "Device.",
"object": "{BBF_VENDOR_PREFIX}OpenVPN",
"proto": "usp"
},
{ {
"parent_dm": "Device.", "parent_dm": "Device.",
"object": "RootDataModelVersion" "object": "RootDataModelVersion"
@ -28,14 +41,14 @@
{ {
"parent_dm": "Device.", "parent_dm": "Device.",
"object": "Reboot()" "object": "Reboot()"
}, },
{ {
"parent_dm": "Device.", "parent_dm": "Device.",
"object": "FactoryReset()" "object": "FactoryReset()"
} }
], ],
"config": { "config": {
"loglevel": "3" "loglevel": "3"
} }
} }
} }

View file

@ -1,126 +0,0 @@
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <libubox/blobmsg.h>
#include <libbbfdm-api/dmapi.h>
#include <libbbfdm-ubus/bbfdm-ubus.h>
#include <libbbfdm-api/dmentry.h>
#include "../../libbbfdm-ubus/plugin.h"
#include "../../libbbfdm/device.h"
extern struct list_head loaded_json_files;
extern struct list_head json_list;
extern struct list_head json_memhead;
static int cli_exec_schema(struct dmctx *bbfdm_ctx, char *in_path)
{
int err = 0;
bbfdm_ctx->in_param = in_path;
bbfdm_ctx->nextlevel = false;
bbfdm_ctx->iscommand = true;
bbfdm_ctx->isevent = true;
bbfdm_ctx->isinfo = true;
err = bbf_entry_method(bbfdm_ctx, BBF_SCHEMA);
if (!err) {
struct blob_attr *cur = NULL;
size_t rem = 0;
blobmsg_for_each_attr(cur, bbfdm_ctx->bb.head, rem) {
struct blob_attr *tb[3] = {0};
const struct blobmsg_policy p[3] = {
{ "path", BLOBMSG_TYPE_STRING },
{ "data", BLOBMSG_TYPE_STRING },
{ "type", BLOBMSG_TYPE_STRING }
};
blobmsg_parse(p, 3, tb, blobmsg_data(cur), blobmsg_len(cur));
char *name = (tb[0]) ? blobmsg_get_string(tb[0]) : "";
char *data = (tb[1]) ? blobmsg_get_string(tb[1]) : "";
char *type = (tb[2]) ? blobmsg_get_string(tb[2]) : "";
printf("%s %s %s\n", name, type, strlen(data) ? data : "0"); // Added a data check to handle events with empty or missing data
}
} else {
printf("ERROR: %d retrieving %s\n", err, bbfdm_ctx->in_param);
err = -1;
}
return err;
}
int main(int argc, char **argv)
{
DMOBJ *CLI_DM_ROOT_OBJ = NULL;
void *cli_lib_handle = NULL;
struct dmctx bbfdm_ctx = {0};
char *plugin_path = NULL, *plugin_dir = NULL, *dm_path = NULL;
unsigned int proto = BBFDM_BOTH;
int err = 0, ch;
memset(&bbfdm_ctx, 0, sizeof(struct dmctx));
while ((ch = getopt(argc, argv, "hc:u:l:p:")) != -1) {
switch (ch) {
case 'c':
bbfdm_ctx.dm_type = BBFDM_CWMP;
dm_path = argv[optind - 1];
break;
case 'u':
bbfdm_ctx.dm_type = BBFDM_USP;
dm_path = argv[optind - 1];
break;
case 'l':
plugin_path = optarg;
break;
case 'p':
plugin_dir = optarg;
break;
default:
break;
}
}
if (plugin_path == NULL) {
err = bbfdm_load_internal_plugin(NULL, tDynamicObj, &CLI_DM_ROOT_OBJ);
} else {
if (strstr(plugin_path, ".json") != NULL)
err = bbfdm_load_json_plugin(NULL, &loaded_json_files, &json_list, &json_memhead, plugin_path, &CLI_DM_ROOT_OBJ);
else
err = bbfdm_load_dotso_plugin(NULL, &cli_lib_handle, plugin_path, &CLI_DM_ROOT_OBJ);
}
if (err || !CLI_DM_ROOT_OBJ) {
printf("ERROR: Failed to load plugin\n");
return -1;
}
if (!dm_path) {
printf("ERROR: Data Model path should be defined\n");
return -1;
}
// Initialize global context
bbf_global_init(CLI_DM_ROOT_OBJ, plugin_dir);
// Initialize the bbfdm context
bbf_ctx_init(&bbfdm_ctx, CLI_DM_ROOT_OBJ);
err = cli_exec_schema(&bbfdm_ctx, dm_path);
// Clean up the context and global resources
bbf_ctx_clean(&bbfdm_ctx);
bbf_global_clean(CLI_DM_ROOT_OBJ);
// Free plugin handle
bbfdm_free_dotso_plugin(NULL, &cli_lib_handle);
// Free JSON plugin handle
bbfdm_free_json_plugin();
return err;
}

View file

@ -1,19 +1,16 @@
#!/usr/bin/python3 #!/usr/bin/python3
# Copyright (C) 2024 iopsys Software Solutions AB # Copyright (C) 2024-2025 iopsys Software Solutions AB
# Author: Amin Ben Romdhane <amin.benromdhane@iopsys.eu> # Author: Amin Ben Romdhane <amin.benromdhane@iopsys.eu>
import sys import sys
import os import os
import subprocess import subprocess
import shutil import shutil
import glob
# Constants # Constants
BBF_ERROR_CODE = 0 BBF_ERROR_CODE = 0
CURRENT_PATH = os.getcwd() CURRENT_PATH = os.getcwd()
BBF_MS_CORE_DIR = "/usr/share/bbfdm/micro_services/core/"
BBF_MS_DIR = "/usr/share/bbfdm/micro_services/"
DM_JSON_FILE = os.path.join(CURRENT_PATH, "tools", "datamodel.json") DM_JSON_FILE = os.path.join(CURRENT_PATH, "tools", "datamodel.json")
@ -35,25 +32,6 @@ Array_Types = {
} }
def rename_file(old_path, new_path):
try:
os.rename(old_path, new_path)
except OSError:
pass
def move_file(source_path, destination_path):
shutil.move(source_path, destination_path)
def install_json_plugin(source_path, destination_path, vendor_extn):
with open(source_path, 'r', encoding='UTF-8') as src, open(destination_path, 'w', encoding='UTF-8') as dest:
data = src.read()
data = data.replace("{BBF_VENDOR_PREFIX}", vendor_extn)
dest.write(data)
def remove_file(file_path): def remove_file(file_path):
try: try:
os.remove(file_path) os.remove(file_path)
@ -73,13 +51,6 @@ def remove_folder(folder_path):
shutil.rmtree(folder_path) shutil.rmtree(folder_path)
def cd_dir(path):
try:
os.chdir(path)
except OSError:
pass
def obj_has_child(value): def obj_has_child(value):
if isinstance(value, dict): if isinstance(value, dict):
for _obj, val in value.items(): for _obj, val in value.items():
@ -138,146 +109,37 @@ def is_proto_exist(value, proto):
return proto in protocols return proto in protocols
def clear_list(input_list): def build_command(plugin, proto):
input_list.clear() service_name = get_option_value(plugin, "service_name")
unified = get_option_value(plugin, "unified_daemon", False)
daemon_name = get_option_value(plugin, "daemon_name", "")
if not service_name:
return None # skip this plugin
def generate_shared_library(dm_name, source_files, vendor_prefix, if unified:
extra_dependencies, is_microservice=False): base_cmd = f"{daemon_name}"
# Return if source_files (list) is empty
if len(source_files) == 0:
return
if is_microservice:
outdir = BBF_MS_DIR
else: else:
outdir = BBF_MS_CORE_DIR base_cmd = f"dm-service -m {service_name}"
output_library = outdir + dm_name
# Set vendor prefix
if vendor_prefix is not None:
VENDOR_PREFIX = vendor_prefix
else:
VENDOR_PREFIX = "X_IOWRT_EU_"
# Ensure that the source files exist
for source_file in source_files:
if not os.path.exists(source_file):
print(f" Error: Source file {source_file} does not exist.")
return False
cmd = ['gcc', '-shared', '-o', output_library, '-fPIC',
'-DBBF_VENDOR_PREFIX=\\"{}\\"'.format(VENDOR_PREFIX)]
cmd = cmd + source_files + extra_dependencies
# Compile the shared library
try:
cmdstr = ' '.join(str(e) for e in cmd)
subprocess.run(cmdstr, shell=True, check=True)
print(f" Shared library {output_library} successfully created.")
return True
except subprocess.CalledProcessError as e:
print(f" Error during compilation: {e}")
sys.exit(-1)
def build_and_install_bbfdm(vendor_prefix):
print("Compiling and installing bbfdmd in progress ...")
create_folder(os.path.join(CURRENT_PATH, "build"))
cd_dir(os.path.join(CURRENT_PATH, "build"))
# Set vendor prefix
if vendor_prefix is not None:
VENDOR_PREFIX = vendor_prefix
else:
VENDOR_PREFIX = "X_IOWRT_EU_"
# Build and install bbfdm
cmake_command = [
"cmake",
"../",
"-DBBF_SCHEMA_FULL_TREE=ON",
f"-DBBF_VENDOR_PREFIX={VENDOR_PREFIX}",
"-DBBF_MAX_OBJECT_INSTANCES=255",
"-DBBFDMD_MAX_MSG_LEN=1048576",
"-DCMAKE_INSTALL_PREFIX=/"
]
make_command = ["make"]
make_install_command = ["sudo", "make", "install"]
try:
subprocess.check_call(cmake_command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
subprocess.check_call(make_command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
subprocess.check_call(make_install_command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
except subprocess.CalledProcessError as e:
print(f"Error running commands: {e}")
sys.exit(1)
cd_dir(CURRENT_PATH)
remove_folder(os.path.join(CURRENT_PATH, "build"))
print('Compiling and installing bbfdmd done')
def build_and_install_dmcli():
print("Compiling and installing dm-cli in progress ...")
create_folder(os.path.join(CURRENT_PATH, "build"))
cd_dir(os.path.join(CURRENT_PATH, "build"))
# GCC command to compile dm-cli
gcc_command = [
"gcc",
"../test/tools/dm-cli.c",
"-lbbfdm-api",
"-lbbfdm-ubus",
"-lubox",
"-lblobmsg_json",
"-lcore",
"-ljson-c",
"-lssl",
"-lcrypto",
"-o", "dm-cli"
]
try:
subprocess.check_call(gcc_command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
subprocess.check_call(["sudo", "mv", "dm-cli", "/usr/sbin/dm-cli"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
except subprocess.CalledProcessError as e:
print(f"Error running commands: {e}")
sys.exit(1)
cd_dir(CURRENT_PATH)
remove_folder(os.path.join(CURRENT_PATH, "build"))
print('Compiling and installing dm-cli done')
def fill_list_dm(proto, dm_list, dm_name=None):
# Determine the base command depending on the presence of dm_name
if dm_name:
command = f"dm-cli -l {dm_name}"
else:
command = "dm-cli -p /usr/share/bbfdm/micro_services/core"
# Add the appropriate flag (-c or -u) based on the proto value
if proto == "cwmp": if proto == "cwmp":
command += " -c Device." base_cmd += " -d"
elif proto == "usp": elif proto == "usp":
command += " -u Device." base_cmd += " -dd"
return base_cmd
def fill_list_dm(command, dm_list):
try: try:
# Run the command
result = subprocess.run(command, shell=True, text=True, capture_output=True, check=True) result = subprocess.run(command, shell=True, text=True, capture_output=True, check=True)
# Get the output from the result
output = result.stdout output = result.stdout
# Split the output into lines
lines = output.strip().split('\n') lines = output.strip().split('\n')
# Iterate through each line and parse the information
for line in lines: for line in lines:
parts = line.split() parts = line.split()
if len(parts) < 3:
continue
path, n_type, data = parts[0], parts[1], parts[2] path, n_type, data = parts[0], parts[1], parts[2]
permission = "readWrite" if data == "1" else "readOnly" permission = "readWrite" if data == "1" else "readOnly"
p_type = n_type[4:] p_type = n_type[4:]
@ -289,8 +151,7 @@ def fill_list_dm(proto, dm_list, dm_name=None):
dm_list.append(entry) dm_list.append(entry)
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
# Handle subprocess errors here print(f"Error running command '{command}': {e}")
print(f"Error running command: {e}")
sys.exit(1) sys.exit(1)
@ -307,154 +168,30 @@ def remove_duplicate_elements(input_list):
return result_list return result_list
def fill_list_supported_dm(): def fill_list_supported_dm(plugins):
for proto, DB in [("usp", LIST_SUPPORTED_USP_DM), ("cwmp", LIST_SUPPORTED_CWMP_DM)]:
fill_list_dm(proto, DB)
DB.sort(key=lambda x: x['param'], reverse=False)
DB[:] = remove_duplicate_elements(DB)
for file in os.listdir(BBF_MS_DIR):
f = os.path.join(BBF_MS_DIR, file)
if os.path.isfile(f):
for proto, DB in [("usp", LIST_SUPPORTED_USP_DM), ("cwmp", LIST_SUPPORTED_CWMP_DM)]:
fill_list_dm(proto, DB, f)
DB.sort(key=lambda x: x['param'], reverse=False)
DB[:] = remove_duplicate_elements(DB)
def clone_git_repository(repo, version=None):
repo_path = '/tmp/repo/'+os.path.basename(repo).replace('.git', '')
if os.path.exists(repo_path):
print(f' {repo} already exists at {repo_path} !')
return True
try:
cmd = ["git", "clone", repo, repo_path]
if version is not None:
cmd.extend(["-b", version])
subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, check=True)
return True
except (OSError, subprocess.SubprocessError):
print(f' Failed to clone {repo} !!!!!')
return False
def get_repo_version_info(repo, version=None):
if version is None:
return repo
return f'{repo}^{version}'
def download_and_build_plugins(plugins, vendor_prefix):
global BBF_ERROR_CODE
if plugins is None or not isinstance(plugins, list) or not plugins: if plugins is None or not isinstance(plugins, list) or not plugins:
print("No plugins provided.") print("No plugins provided.")
return return
print("Generating data models from defined plugins...") for proto, DB in [("usp", LIST_SUPPORTED_USP_DM), ("cwmp", LIST_SUPPORTED_CWMP_DM)]:
for plugin in plugins:
command = build_command(plugin, proto)
if command:
print(f"Running command for {proto}: {command}")
fill_list_dm(command, DB)
remove_folder("/tmp/repo") DB.sort(key=lambda x: x['param'], reverse=False)
DB[:] = remove_duplicate_elements(DB)
for plugin_index, plugin in enumerate(plugins):
repo = get_option_value(plugin, "repo")
proto = get_option_value(plugin, "proto")
dm_files = get_option_value(plugin, "dm_files")
is_microservice = get_option_value(plugin, "is_microservice")
extra_dependencies = get_option_value(plugin, "extra_dependencies", [])
dm_desc_file = get_option_value(plugin, "dm_info_file", "")
prefix = get_option_value(plugin, "vendor_prefix", None)
repo_path = None
name = os.path.basename(repo).replace('.git', '')
path = os.path.expanduser("~/.netrc")
if not os.path.isfile(path):
repo = repo.replace("https://dev.iopsys.eu/", "git@dev.iopsys.eu:")
print(f"## Repo is {repo}")
if not prefix:
prefix = vendor_prefix
if repo is None or proto is None or dm_files is None or not isinstance(dm_files, list):
BBF_ERROR_CODE += 1
print(f"# Necessary input missing {BBF_ERROR_CODE}")
continue
print(f' - Processing plugin: MS({is_microservice}) {plugin}')
if proto == "git":
repo_path = "/tmp/repo/"+name
version = get_option_value(plugin, "version")
if not clone_git_repository(repo, version):
BBF_ERROR_CODE += 1
print(f"# Failed to clone {repo} {BBF_ERROR_CODE}")
continue
print(f' Processing {get_repo_version_info(repo, version)}')
elif proto == "local":
repo_path = repo
print(f' Processing {get_repo_version_info(repo, proto)}')
if repo_path is None:
BBF_ERROR_CODE += 1
print(f"# Repository path not defined {BBF_ERROR_CODE}!!!")
continue
create_folder("/tmp/repo/dm_info")
if dm_desc_file.endswith('.json'):
dest_file = "/tmp/repo/dm_info/" + os.path.basename(dm_desc_file).replace('.json', f"_{plugin_index}.json")
rename_file(repo_path + "/" + dm_desc_file, dest_file)
LIST_FILES = []
os.chdir(repo_path)
for dm_file in dm_files:
filename = dm_file
if filename.endswith('*.c'):
LIST_FILES.extend(glob.glob(filename))
else:
if os.path.isfile(filename):
if filename.endswith('.c'):
LIST_FILES.append(filename)
elif filename.endswith('.json'):
if is_microservice is True:
install_json_plugin(filename, "/usr/share/bbfdm/micro_services/"+f"{plugin_index}_{name}.json", prefix)
else:
install_json_plugin(filename, "/usr/share/bbfdm/micro_services/core/"+f"{plugin_index}_{name}.json", prefix)
else:
BBF_ERROR_CODE += 1
print(f"# Unknown file format {filename} {BBF_ERROR_CODE}")
else:
BBF_ERROR_CODE += 1
print(f"# Error: File not accessible {filename} {BBF_ERROR_CODE}!!!!!!")
if len(LIST_FILES) > 0:
if not generate_shared_library(f"{plugin_index}_{name}.so", LIST_FILES, prefix, extra_dependencies, is_microservice):
BBF_ERROR_CODE += 1
print(f"# Error: Failed to generate shared library for {plugin_index}_{name}, error {BBF_ERROR_CODE}")
clear_list(LIST_FILES)
cd_dir(CURRENT_PATH)
print(f'Generating plugins completed, error {BBF_ERROR_CODE}')
def generate_supported_dm(vendor_prefix=None, plugins=None): def generate_supported_dm(plugins=None):
''' '''
Generates supported data models and performs necessary actions. Generates supported data models and performs necessary actions.
Args: Args:
vendor_prefix (str, optional): Vendor prefix for shared libraries.
plugins (list, optional): List of plugin configurations. plugins (list, optional): List of plugin configurations.
''' '''
# Build && Install bbfdm
build_and_install_bbfdm(vendor_prefix)
# Build && Install dm-cli
build_and_install_dmcli()
# Download && Build Plugins Data Models
download_and_build_plugins(plugins, vendor_prefix)
# Fill the list supported data model # Fill the list supported data model
fill_list_supported_dm() fill_list_supported_dm(plugins)

View file

@ -24,7 +24,6 @@ def print_dm_usage():
if len(sys.argv) < 2: if len(sys.argv) < 2:
print_dm_usage() print_dm_usage()
VENDOR_PREFIX = None
PLUGINS = None PLUGINS = None
OUTPUT = None OUTPUT = None
DM_JSON_FILES = None DM_JSON_FILES = None
@ -62,10 +61,6 @@ for option, value in json_data.items():
bbf_xml.SOFTWARE_VERSION = value bbf_xml.SOFTWARE_VERSION = value
continue continue
elif option == "vendor_prefix":
VENDOR_PREFIX = value
continue
elif option == "dm_json_files": elif option == "dm_json_files":
DM_JSON_FILES = value DM_JSON_FILES = value
continue continue
@ -82,43 +77,39 @@ for option, value in json_data.items():
print_dm_usage() print_dm_usage()
exit(1) exit(1)
if OUTPUT is None: bbf.generate_supported_dm(PLUGINS)
bbf.download_and_build_plugins(PLUGINS, VENDOR_PREFIX)
else:
bbf.generate_supported_dm(VENDOR_PREFIX, PLUGINS)
file_format = bbf.get_option_value(OUTPUT, "file_format", ['xml']) file_format = bbf.get_option_value(OUTPUT, "file_format", ['xml'])
output_file_prefix = bbf.get_option_value(OUTPUT, "output_file_prefix", "datamodel") output_file_prefix = bbf.get_option_value(OUTPUT, "output_file_prefix", "datamodel")
output_dir = bbf.get_option_value(OUTPUT, "output_dir", "./out") output_dir = bbf.get_option_value(OUTPUT, "output_dir", "./out")
bbf.create_folder(output_dir)
print("Dumping default DM_JSON_FILES") bbf.create_folder(output_dir)
print(DM_JSON_FILES)
DM_JSON_FILES.extend(glob.glob('/tmp/repo/dm_info/*.json'))
print("Dumping all")
print(DM_JSON_FILES)
print("Dumping default DM_JSON_FILES")
print(DM_JSON_FILES)
DM_JSON_FILES.extend(glob.glob('/tmp/desc_files/*.json'))
print("Dumping all")
print(DM_JSON_FILES)
if isinstance(file_format, list): if isinstance(file_format, list):
for _format in file_format: for _format in file_format:
if _format == "xml": if _format == "xml":
acs = bbf.get_option_value(OUTPUT, "acs", ['default']) acs = bbf.get_option_value(OUTPUT, "acs", ['default'])
if isinstance(acs, list): if isinstance(acs, list):
for acs_format in acs: for acs_format in acs:
output_file_name = output_dir + '/' + output_file_prefix + '_' + acs_format + '.xml' output_file_name = output_dir + '/' + output_file_prefix + '_' + acs_format + '.xml'
if acs_format == "hdm": if acs_format == "hdm":
bbf_xml.generate_xml('HDM', DM_JSON_FILES, output_file_name) bbf_xml.generate_xml('HDM', DM_JSON_FILES, output_file_name)
if acs_format == "default": if acs_format == "default":
bbf_xml.generate_xml('default', DM_JSON_FILES, output_file_name) bbf_xml.generate_xml('default', DM_JSON_FILES, output_file_name)
if _format == "xls": if _format == "xls":
output_file_name = output_dir + '/' + output_file_prefix + '.xls' output_file_name = output_dir + '/' + output_file_prefix + '.xls'
bbf_excel.generate_excel(output_file_name) bbf_excel.generate_excel(output_file_name)
print("Datamodel generation completed, aritifacts shall be available in out directory or as per input json configuration") print("Datamodel generation completed, aritifacts shall be available in out directory or as per input json configuration")
sys.exit(bbf.BBF_ERROR_CODE) sys.exit(bbf.BBF_ERROR_CODE)

View file

@ -196,13 +196,6 @@ if __name__ == '__main__':
help= 'Includes OBJ/PARAM defined under remote repositories defined as bbf plugin' help= 'Includes OBJ/PARAM defined under remote repositories defined as bbf plugin'
) )
parser.add_argument(
'-p', '--vendor-prefix',
default = 'X_IOWRT_EU_',
metavar = 'X_IOWRT_EU_',
help = 'Generate data model tree using provided vendor prefix for vendor defined objects'
)
parser.add_argument( parser.add_argument(
'-o', '--output', '-o', '--output',
default = "datamodel.xls", default = "datamodel.xls",
@ -225,7 +218,7 @@ if __name__ == '__main__':
plugins.append(r) plugins.append(r)
bbf.generate_supported_dm(args.vendor_prefix, plugins) bbf.generate_supported_dm(plugins)
generate_excel(args.output) generate_excel(args.output)
print(f'Datamodel generation completed, aritifacts available in {args.output}') print(f'Datamodel generation completed, aritifacts available in {args.output}')
sys.exit(bbf.BBF_ERROR_CODE) sys.exit(bbf.BBF_ERROR_CODE)

View file

@ -394,13 +394,6 @@ if __name__ == '__main__':
help= 'Includes OBJ/PARAM defined under remote repositories defined as bbf plugin' help= 'Includes OBJ/PARAM defined under remote repositories defined as bbf plugin'
) )
parser.add_argument(
'-p', '--vendor-prefix',
default = 'X_IOWRT_EU_',
metavar = 'X_IOWRT_EU_',
help = 'Generate data model tree using provided vendor prefix for vendor defined objects.'
)
parser.add_argument( parser.add_argument(
'-d', '--device-protocol', '-d', '--device-protocol',
default = 'DEVICE_PROTOCOL_DSLFTR069v1', default = 'DEVICE_PROTOCOL_DSLFTR069v1',
@ -480,7 +473,7 @@ if __name__ == '__main__':
plugins.append(r) plugins.append(r)
bbf.generate_supported_dm(args.vendor_prefix, plugins) bbf.generate_supported_dm(plugins)
generate_xml(args.format, args.dm_json_files, args.output) generate_xml(args.format, args.dm_json_files, args.output)
print(f'Datamodel generation completed, aritifacts available in {args.output}') print(f'Datamodel generation completed, aritifacts available in {args.output}')
sys.exit(bbf.BBF_ERROR_CODE) sys.exit(bbf.BBF_ERROR_CODE)

File diff suppressed because it is too large Load diff