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.
ngcpcfg/scripts/services

255 lines
6.5 KiB

#!/bin/bash
# Purpose: detect modified files in config tree and execute
# any defined service modifications
################################################################################
set -e
set -E
set -u
# support testsuite
FUNCTIONS="${FUNCTIONS:-/usr/share/ngcp-ngcpcfg/functions/}"
CLEANUP_FILES=()
# load modules
if [[ ! -r "${FUNCTIONS}"/main ]]; then
printf "Error: %s/main could not be read. Exiting.\n" "${FUNCTIONS}">&2
exit 1
fi
# shellcheck disable=SC1090
. "${FUNCTIONS}"/main
# functions
exec_wrapper() {
if ${DRYRUN} ; then
log_info "TEST MODE: Would execute action for ${line}"
return 0
fi
log_info "Executing action for ${line}"
if [[ -x "${line}" ]]; then
log_debug "${line}"
if ! "${line}" ; then
log_warn "${line} returned with error code, continuing anyway."
fi
elif [[ -r "${line}" ]]; then
log_debug "bash ${line}"
if ! bash "${line}" ; then
log_warn "${line} returned with error code, continuing anyway."
fi
else
log_error "Error: ${line} could not be read."
exit 1
fi
}
# get rid of "./" and "//" in file names
normalize_files() {
NORMALIZED_FILES="$(mktemp)"
log_debug "NORMALIZED_FILES = ${NORMALIZED_FILES}"
CLEANUP_FILES+=("${NORMALIZED_FILES}")
while read -r line ; do
# shellcheck disable=SC2001
echo "${line}" | sed -e 's_\./_/_g ; s_//_/_g' >> "${NORMALIZED_FILES}"
done < "${TMPFILE}"
}
# restart sysctl services before the rest (see TT#58703)
# restart monit services before the rest (see MT#9971)
# restart HA just after monit (see MT#17163)
# restart other services in alphabetical order
sort_service_list() {
SORTED_LIST="$(mktemp)"
log_debug "SORTED_LIST = ${SORTED_LIST}"
CLEANUP_FILES+=("${SORTED_LIST}")
for dir in sysctl.d monit corosync pacemaker ha.d; do
grep "${SERVICES_POOL_BASE}"/etc/${dir}/'.*services' \
"${NORMALIZED_FILES}" >> "${SORTED_LIST}" || true
done
# Sort loads the entire contents before outputting, and we are appending
# instead of truncating, so this should be safe.
# shellcheck disable=SC2094
sort "${NORMALIZED_FILES}" "${SORTED_LIST}" | uniq -u \
>> "${SORTED_LIST}" || true
}
services_start_queue()
{
log_info "Clearing out enqueued services actions"
ngcp-service queue-clear
log_info "Starting enqueued services actions mode"
ngcp-service queue-start
}
execute() {
while read -r line ; do
exec_wrapper "${line}"
done < "${SORTED_LIST}"
}
services_flush_enqueued()
{
log_info "Executing enqueued services actions"
ngcp-service --queue=default,policy-rc.d queue-show
ngcp-service --queue=default,policy-rc.d queue-run
}
services_sync_state() {
log_info "Synchronizing current with expected services state"
ngcp-service sync-state
}
systemd_daemon_reload_preset() {
if [[ -d "/run/systemd/system" ]]; then
log_info "Reloading systemd daemon and preset all services"
log_debug "systemd needs daemon-reload so the unit files loaded are in sync"
log_debug "Running: systemctl daemon-reload 2>&1 || true"
systemctl daemon-reload 2>&1 || true
log_debug "systemd needs preset-all to enable/disable services (to start them on boot)"
log_debug "Running: rm -rf /etc/systemd/system/*.wants/ || true"
rm -rf /etc/systemd/system/*.wants/ || true
log_debug "Running: systemctl preset-all 2>&1 || true"
systemctl preset-all 2>&1 || true
fi
}
is_absolute_path() {
local dir="$1"
if [[ ! "${dir}" =~ ^/ ]]; then
log_error "${dir} is not an absolute path"
return 1
fi
return 0
}
is_non_git_folder() {
local dir="$1"
if [[ ! -d "${dir}/.git" ]]; then
log_info "${dir} has no support of .services"
return 1
fi
return 0
}
generate_list_to_process() {
local dir="$1"
if ${FORCE_ALL_SERVICES} ; then
log_debug "calling function find_all_services()"
find_all_services "${dir}"
else
log_debug "calling function find_all_changed_services()"
find_all_changed_services "${dir}"
fi
}
find_all_services() {
local dir="$1"
while read -r file ; do
if [[ ! -r "${file}" ]]; then
log_warn "Cannot read file '${file}'"
fi
log_debug "Storing ${file} in '${TMPFILE}'"
echo "${file}" >> "${TMPFILE}"
done < <(find "${SERVICES_POOL_BASE}/${dir}" -name '*.services' | sort -u)
}
find_all_changed_services() {
local dir="$1"
log_debug "${FUNCNAME[0]}(): Working in ${dir}"
pushd "${dir}" >/dev/null
for file in $(git status -uall --porcelain | sed 's/^...//') ; do
if [[ -r "${file}" ]] && [[ -r "${SERVICES_POOL_BASE}/${dir}/${file}".services ]]; then
log_debug "Storing ${SERVICES_POOL_BASE}/${dir}/${file}.services in '${TMPFILE}'"
echo "${SERVICES_POOL_BASE}/${dir}/${file}".services
elif [[ -r "${file}" ]] && [[ -r "${SERVICES_POOL_BASE}/${dir}/$(dirname "${file}")"/ngcpcfg.services ]]; then
log_debug "Storing ${SERVICES_POOL_BASE}/${dir}/$(dirname "$file")/ngcpcfg.services in '${TMPFILE}'"
echo "${SERVICES_POOL_BASE}/${dir}/$(dirname "$file")/ngcpcfg.services"
fi
done | sort -u >> "${TMPFILE}"
popd >/dev/null
}
# main script
RUNNING_FILE="${RUN_DIR}/ngcpcfg-services.running"
DRYRUN='false'
FORCE_ALL_SERVICES='false'
if [[ "${1:-}" == "test" ]] || [[ "${1:-}" == "--dry-run" ]]; then
DRYRUN='true'
elif [[ "${1:-}" == "--force-all-services" ]]; then
FORCE_ALL_SERVICES='true'
fi
log_debug "DRYRUN = ${DRYRUN}"
log_debug "FORCE_ALL_SERVICES = ${FORCE_ALL_SERVICES}"
if ! ${DRYRUN}; then
log_debug "creating current execution filesystem trail"
trap 'rm -f "${RUNNING_FILE}"' EXIT ERR
echo $$ >"${RUNNING_FILE}"
fi
log_debug "systemd_daemon_reload_preset function"
systemd_daemon_reload_preset
TMPFILE="$(mktemp)"
log_debug "TMPFILE = ${TMPFILE}"
CLEANUP_FILES+=("${TMPFILE}")
for dir in ${CONFIG_POOL} ; do
is_absolute_path "${dir}" || continue
is_non_git_folder "${dir}" || continue
generate_list_to_process "${dir}"
done
if [[ -s "${TMPFILE}" ]]; then
log_debug "normalize_files function"
normalize_files
log_debug "sort_service_list function"
sort_service_list
services_start_queue
log_debug "execute function"
execute
else
log_debug "No services file(s) reported - no explicit service state changed."
fi
# Always flush the queues, to handle actions from package upgrades.
services_flush_enqueued
log_debug "services_sync_state function"
services_sync_state
if [[ -n "${DEBUG:-}" ]]; then
log_debug "Not removing temporary files"
else
rm -f "${CLEANUP_FILES[@]}"
fi
## END OF FILE #################################################################