mirror of https://github.com/sipwise/ngcpcfg.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
392 lines
11 KiB
392 lines
11 KiB
# Filename: /usr/share/ngcp-ngcpcfg/functions/main
|
|
# Purpose: helper functions for ngcpcfg
|
|
################################################################################
|
|
|
|
# console output including timestamps {{{
|
|
timestamp_replacementchars='' # unset by default
|
|
|
|
console_output() {
|
|
if [ -z "${TIME_FORMAT:-}" ] ; then
|
|
printf -- "$*"
|
|
return 0
|
|
fi
|
|
|
|
local timestamp="$(date "$TIME_FORMAT")"
|
|
|
|
# indent depending on number of characters in date output
|
|
timestamp_replacementchars="$(printf -- "%s: " "$timestamp" | sed 's/./ /g')"
|
|
printf -- "$timestamp ${HNAME:-}: $*"
|
|
}
|
|
# }}}
|
|
|
|
## logging functions {{{
|
|
log_info() {
|
|
logger -t ngcpcfg -- "$*"
|
|
console_output "$*\n"
|
|
}
|
|
|
|
# info without ending newline
|
|
log_info_n() {
|
|
logger -t ngcpcfg -- "$*"
|
|
console_output "$*"
|
|
}
|
|
|
|
log_warn() {
|
|
logger -t ngcpcfg -- "Warning: $*"
|
|
console_output "Warning: $*\n"
|
|
}
|
|
|
|
log_error() {
|
|
logger -t ngcpcfg -- "Error: $*"
|
|
console_output "Error: $*\n" >&2
|
|
}
|
|
|
|
log_debug() {
|
|
if [ -n "${DEBUG:-}" ] ; then
|
|
logger -t ngcpcfg -- "Debug: $*"
|
|
console_output "DEBUG: $*\n" >&2
|
|
fi
|
|
}
|
|
## }}}
|
|
|
|
## important variables we depend on to operate successfully {{{
|
|
# support test suite which requires system independent configuration
|
|
if [ -r "${NGCPCFG:-}" ] ; then
|
|
log_debug "sourcing configuration file ${NGCPCFG:-}"
|
|
. "${NGCPCFG:-}"
|
|
else
|
|
if [ -r /etc/ngcp-config/ngcpcfg.cfg ] ; then
|
|
. /etc/ngcp-config/ngcpcfg.cfg
|
|
log_debug "sourced configuration file /etc/ngcp-config/ngcpcfg.cfg"
|
|
|
|
if [ -d /etc/ngcp-config/ngcpcfg.d ] ; then
|
|
for file in /etc/ngcp-config/ngcpcfg.d/*.cfg ; do
|
|
if [ -r "${file}" ]; then
|
|
. "${file}"
|
|
log_debug "sourced configuration file '${file}'"
|
|
fi
|
|
done
|
|
fi
|
|
elif [ -r /etc/ngcp-config-crypted.tgz.gpg ] ; then
|
|
log_error "Configuration pool locked. Please contact your distributor. Exiting."
|
|
exit 1
|
|
else
|
|
log_error "Could not read configuration file /etc/ngcp-config/ngcpcfg.cfg. Exiting."
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
if ! [ -r "${NGCPCTL_CONFIG}" ] ; then
|
|
log_error "Configuration file ${NGCPCTL_CONFIG} does not exist (unconfigured?) - exiting."
|
|
exit 1
|
|
fi
|
|
|
|
if ! [ -r "${CONSTANTS_CONFIG}" ] ; then
|
|
log_error "Constants file ${CONSTANTS_CONFIG} does not exist (unconfigured?) - exiting."
|
|
exit 1
|
|
fi
|
|
|
|
if ! [ -n "${NETWORK_CONFIG:-}" ] ; then
|
|
log_warn "NETWORK_CONFIG is not configured in ${NGCPCTL_CONFIG} - continuing anyway."
|
|
elif ! [ -r "${NETWORK_CONFIG}" ] ; then
|
|
log_error "Constants file ${NETWORK_CONFIG} does not exist (unconfigured?) - exiting."
|
|
exit 1
|
|
fi
|
|
|
|
if ! [ -d "${TEMPLATE_POOL_BASE}" ] ; then
|
|
log_error "No template directory (${TEMPLATE_POOL_BASE}) found - exiting."
|
|
exit 1
|
|
fi
|
|
|
|
if [ -d "${EXTRA_CONFIG_DIR:-}" ] && ls "${EXTRA_CONFIG_DIR}"/*.yml &>/dev/null ; then
|
|
log_debug "EXTRA_CONFIG_DIR is configured and *.yml files are present, setting EXTRA_CONFIG_FILES"
|
|
EXTRA_CONFIG_FILES=("${EXTRA_CONFIG_DIR}"/*.yml)
|
|
fi
|
|
|
|
## }}}
|
|
|
|
## environment variables {{{
|
|
export PN="ngcpcfg"
|
|
export HNAME="$(hostname)"
|
|
export NNAME="$(ngcp-nodename)"
|
|
|
|
# avoid warnings by perl script complaining about locales
|
|
export LANG=C
|
|
export LC_ALL=C
|
|
|
|
# make sure it's available in all helper scripts
|
|
[ -n "${DEBUG:-}" ] && export DEBUG
|
|
[ -n "${NO_DB_SYNC:-}" ] && export NO_DB_SYNC
|
|
|
|
# export for access via build_config etc
|
|
export CONFIG_POOL
|
|
export HOST_CONFIG
|
|
export LOCAL_CONFIG
|
|
export NGCPCTL_CONFIG
|
|
export CONSTANTS_CONFIG
|
|
export NETWORK_CONFIG
|
|
export EXTRA_CONFIG_DIR
|
|
export EXTRA_CONFIG_FILES
|
|
## }}}
|
|
|
|
## HA / carrier features {{{
|
|
if [ -r /usr/share/ngcp-ngcpcfg/functions/ha_features ] ; then
|
|
. /usr/share/ngcp-ngcpcfg/functions/ha_features
|
|
set_ha_file # set ${HA_FILE} for usage in generate_template_list
|
|
fi
|
|
|
|
if [ -r /usr/share/ngcp-ngcpcfg/functions/carrier_features ] ; then
|
|
. /usr/share/ngcp-ngcpcfg/functions/carrier_features
|
|
set_host_and_pair_files # set ${HOST_FILE} + ${PAIR_FILE} for usage in generate_template_list
|
|
fi
|
|
## }}}
|
|
|
|
## functions {{{
|
|
hook_setup() {
|
|
log_debug "hook_setup ${1:-}"
|
|
|
|
if ! [ -d "${HOOKS}" ] ; then
|
|
log_debug "Directory ${HOOKS} does not exist."
|
|
return 0
|
|
fi
|
|
|
|
local target_directory="$1"
|
|
|
|
if [ -z "${1:-}" ] ; then
|
|
log_error "Missing argument for target directory in hook_setup. Exiting."
|
|
exit 1
|
|
fi
|
|
|
|
if ! [ -d "${target_directory}" ] ; then
|
|
if [ "${NGCP_TESTSUITE:-false}" = "true" ]; then
|
|
log_info "Hook target directory ${target_directory} not a directory. Creating it."
|
|
mkdir -p "${target_directory}"
|
|
else
|
|
log_error "Hook target directory ${target_directory} not a directory. Exiting."
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
for hook in "${HOOKS}"/* ; do
|
|
[ -r "${hook}" ] || continue
|
|
log_debug "Creating symlink for ${hook} in ${target_directory}"
|
|
ln -sf "$(readlink -f "${hook}")" "${target_directory}"/
|
|
done
|
|
}
|
|
|
|
compare_active_branch() {
|
|
log_debug "get_active_branch ${1:-}"
|
|
|
|
log_debug "cd ${NGCPCTL_MAIN}"
|
|
cd "${NGCPCTL_MAIN}"
|
|
|
|
local current_branch
|
|
current_branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null)
|
|
log_debug "current_branch = ${current_branch}"
|
|
echo "${current_branch}"
|
|
}
|
|
|
|
get_branch_status() {
|
|
log_debug "cd ${NGCPCTL_MAIN}"
|
|
cd "${NGCPCTL_MAIN}"
|
|
|
|
log_debug "git rev-parse HEAD"
|
|
local LOCAL=$(git rev-parse HEAD)
|
|
|
|
log_debug "git rev-parse @{u}"
|
|
local REMOTE=$(git rev-parse @{u})
|
|
|
|
log_debug "git merge-base HEAD @{u}"
|
|
local BASE=$(git merge-base HEAD @{u})
|
|
|
|
if [ "${LOCAL}" = "${REMOTE}" ]; then
|
|
# Up-to-date
|
|
return 0
|
|
elif [ "${LOCAL}" = "${BASE}" ]; then
|
|
# Need to pull
|
|
return 1
|
|
elif [ "${REMOTE}" = "${BASE}" ]; then
|
|
# Need to push
|
|
return 2
|
|
else
|
|
# Diverged
|
|
return 3
|
|
fi
|
|
}
|
|
|
|
generate_template_list() {
|
|
[ -n "${TEMPLATE_POOL_BASE}" ] || return 1
|
|
|
|
local filelist_allfiles=$(mktemp)
|
|
local filelist_prepared=$(mktemp)
|
|
local filelist_final=$(mktemp)
|
|
local filelist_sorted=$(mktemp)
|
|
declare -a dirs_to_process=()
|
|
|
|
for dir in ${CONFIG_POOL} ; do
|
|
[ -n "${dir}" ] || ( log_warn "${dir} doesn't exist" ; continue )
|
|
dirs_to_process+=("${TEMPLATE_POOL_BASE}/${dir}")
|
|
done
|
|
|
|
# find all files we should process
|
|
find "${dirs_to_process[@]}" \
|
|
-name \*.tt2 \
|
|
-o -name \*.tt2"${HA_FILE:-}" \
|
|
-o -name \*.tt2"${HOST_FILE:-}" \
|
|
-o -name \*.tt2"${PAIR_FILE:-}" \
|
|
> "${filelist_allfiles}"
|
|
|
|
# argument(s) (file list/pattern) provided via cmdline
|
|
if [ -z "${1:-}" ] ; then
|
|
cat "${filelist_allfiles}" >> "${filelist_prepared}"
|
|
else
|
|
# limit processing to requested file(s) only
|
|
for arg in "$@"; do
|
|
grep -- "${arg}" "${filelist_allfiles}" >> "${filelist_prepared}"
|
|
done
|
|
fi
|
|
|
|
# remove all filenames where a preferred filename exists
|
|
# foo.customtt.tt2.hostname > foo.customtt.tt2.pairname > foo.customtt.tt2.spX > foo.customtt.tt2 > foo.tt2.hostname > foo.tt2.pairname > foo.tt2.spX > foo.tt2
|
|
for line in $(cat ${filelist_prepared}); do
|
|
|
|
# ignoring foo.patchtt.tt2.* completely (it is not a tt2 template to be built)
|
|
if [[ "${line}" =~ .*\.patchtt\.tt2(.*)?$ ]]; then
|
|
log_debug "Ignored patchtt file '${line}'"
|
|
continue
|
|
fi
|
|
|
|
normalized_filename="${line}"
|
|
|
|
if [ -n "${HA_FILE:-}" ] ; then
|
|
normalized_filename="${normalized_filename%${HA_FILE}}"
|
|
fi
|
|
|
|
if [ -n "${HOST_FILE:-}" ] ; then
|
|
normalized_filename="${normalized_filename%${HOST_FILE}}"
|
|
fi
|
|
|
|
if [ -n "${PAIR_FILE:-}" ] ; then
|
|
normalized_filename="${normalized_filename%${PAIR_FILE}}"
|
|
fi
|
|
|
|
normalized_filename="${normalized_filename%.customtt.tt2}"
|
|
normalized_filename="${normalized_filename%.tt2}"
|
|
|
|
# skipping all further checks IF we have only one entry in 'filelist_prepared' (90% cases)
|
|
if [[ "$(grep -Ec "^${normalized_filename}" "${filelist_prepared}")" == "1" ]]; then
|
|
log_debug "Using the only one available file '${line}' matching on '${normalized_filename}'"
|
|
echo "${line}" >> "${filelist_final}"
|
|
continue
|
|
fi
|
|
|
|
# foo.custom.tt2.hostname
|
|
if [ -n "${HOST_FILE:-}" ] ; then
|
|
if grep -q -- "^${normalized_filename}.customtt.tt2${HOST_FILE}$" "${filelist_prepared}" ; then
|
|
echo "${normalized_filename}.customtt.tt2${HOST_FILE}" >> "${filelist_final}"
|
|
continue
|
|
fi
|
|
fi
|
|
|
|
# foo.custom.tt2.pairname
|
|
if [ -n "${PAIR_FILE:-}" ] ; then
|
|
if grep -q -- "^${normalized_filename}.customtt.tt2${PAIR_FILE}$" "${filelist_prepared}" ; then
|
|
echo "${normalized_filename}.customtt.tt2${PAIR_FILE}" >> "${filelist_final}"
|
|
continue
|
|
fi
|
|
fi
|
|
|
|
# foo.customtt.tt2.sp{1,2}
|
|
if [ -n "${HA_FILE:-}" ] ; then
|
|
if grep -q -- "^${normalized_filename}.customtt.tt2${HA_FILE:-}" "${filelist_prepared}" ; then
|
|
echo "${normalized_filename}.customtt.tt2${HA_FILE:-}" >> "${filelist_final}"
|
|
continue
|
|
fi
|
|
fi
|
|
|
|
# foo.customtt.tt2
|
|
if grep -q -- "^${normalized_filename}.customtt.tt2$" "${filelist_prepared}" ; then
|
|
echo "${normalized_filename}.customtt.tt2" >> "${filelist_final}"
|
|
continue
|
|
fi
|
|
|
|
# foo.tt2.hostname
|
|
if [ -n "${HOST_FILE:-}" ] ; then
|
|
if grep -q -- "^${normalized_filename}.tt2${HOST_FILE}" "${filelist_prepared}" ; then
|
|
echo "${normalized_filename}.tt2${HOST_FILE}" >> "${filelist_final}"
|
|
continue
|
|
fi
|
|
fi
|
|
|
|
# foo.tt2.pairname
|
|
if [ -n "${HOST_FILE:-}" ] ; then
|
|
if grep -q -- "^${normalized_filename}.tt2${PAIR_FILE}" "${filelist_prepared}" ; then
|
|
echo "${normalized_filename}.tt2${PAIR_FILE}" >> "${filelist_final}"
|
|
continue
|
|
fi
|
|
fi
|
|
|
|
# foo.tt2.sp{1,2}
|
|
if [ -n "${HA_FILE:-}" ] ; then
|
|
if grep -q -- "^${normalized_filename}.tt2${HA_FILE}" "${filelist_prepared}" ; then
|
|
echo "${normalized_filename}.tt2${HA_FILE}" >> "${filelist_final}"
|
|
continue
|
|
fi
|
|
fi
|
|
|
|
# another file not matching any previous checks
|
|
echo "${line}" >> "${filelist_final}"
|
|
done
|
|
|
|
sort -u ${filelist_final} >${filelist_sorted}
|
|
|
|
# Output file list, make sure we provide the file names just once, and
|
|
# special case the ngcp-service files, as they are a second stage source
|
|
# of data required during configuration file building, which depends at
|
|
# the same time on the main YAML files.
|
|
grep ngcp-service ${filelist_sorted} || true
|
|
grep -v ngcp-service ${filelist_sorted} || true
|
|
|
|
if [ -n "${DEBUG:-}" ] ; then
|
|
# send to stderr since stdout is used from outside
|
|
log_debug "Not removing temporary filelist files since we are in debug mode:" >&2
|
|
log_debug " filelist_allfiles = ${filelist_allfiles}" >&2
|
|
log_debug " filelist_prepared = ${filelist_prepared}" >&2
|
|
log_debug " filelist_final = ${filelist_final}" >&2
|
|
log_debug " filelist_sorted = ${filelist_sorted}" >&2
|
|
else
|
|
rm -f "${filelist_allfiles}" "${filelist_prepared}" "${filelist_final}" "${filelist_sorted}"
|
|
fi
|
|
|
|
unset filelist_allfiles filelist_prepared filelist_final dirs_to_process
|
|
}
|
|
|
|
record_commit_id() {
|
|
log_debug "cd ${NGCPCTL_MAIN}"
|
|
cd "${NGCPCTL_MAIN}"
|
|
|
|
log_debug "mkdir -p ${STATE_FILES_DIR}"
|
|
mkdir -p "${STATE_FILES_DIR}"
|
|
|
|
# if there are uncommitted changes then record it as such
|
|
if git status --porcelain | grep -q . ; then
|
|
echo "dirty" > "${STATE_FILES_DIR}/build"
|
|
else
|
|
local latest_commit=$(git log -1 --format="%H")
|
|
log_debug "echo ${latest_commit} > ${STATE_FILES_DIR}/build"
|
|
echo "${latest_commit}" > "${STATE_FILES_DIR}/build"
|
|
fi
|
|
}
|
|
|
|
is_git_clean() {
|
|
log_debug "call 'git status --porcelain=v2'. it must have no output"
|
|
if [ -z "$(git status --porcelain=v2)" ]; then
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
## }}}
|
|
|
|
## END OF FILE #################################################################
|