mirror of
https://github.com/netdata/netdata.git
synced 2025-04-29 07:00:01 +00:00
stock configs in /usr/lib/netdata (#4283)
* makefiles install configs in /usr/lib/netdata/conf.d; #4182 * stock health config in /usr/lib/netdata/conf.d/health.d * unit test path concatenation * simplified health file management * use stream.conf from stock config if it does not exist in /etc/netdata * indicate loading of user config in function call * load netdata.conf from stock dir if not found in /etc/netdata * added NETDATA_USER_CONFIG_DIR * provide defaults before loading config * charts.d uses stock files * fping now uses the stock config files * tc-qos-helper.sh now uses stock configs * cgroup-name.sh now uses stock configs too * simplified cgroup-name.sh for user and stock config * alarm-notify.sh uses stock configs too * simplified fping plugin configs loading * simplified tc-qos-helper.sh configs loading * added error handling to charts.d.plugin * apps.plugin used stock configs * generalized recursive double-directory configs loading * statsd uses stock configs * node.d.plugin uses stock configs * compile-time decision of netdata default paths for all files * makeself cleans up old stock config files from user configuration directories * fixed makeself typo * netdata-installer.sh removes stock files from user configuration directories * python.d.plugin user/stock configs update * cleanup stock config files from /etc/netdata, only once * python.d.plugin log loaded files * fix permissions of stock config files and provide an "orig" link for quick access * create help link on stock configs migration for static installations * create user config directories * example statsd synthetic charts now state they are examples * updated configs.signatures * spec file * fixes in spec file * fix typo * install netdata after cleaning up stock configs from /etc/netdata * python.d: add cpuidle stock conf
This commit is contained in:
parent
a440a24688
commit
73608f86b4
32 changed files with 966 additions and 591 deletions
8
.gitignore
vendored
8
.gitignore
vendored
|
@ -75,6 +75,14 @@ system/netdata.service
|
|||
system/netdata.plist
|
||||
system/netdata-freebsd
|
||||
|
||||
plugins.d/alarm-notify.sh
|
||||
plugins.d/cgroup-name.sh
|
||||
plugins.d/charts.d.plugin
|
||||
plugins.d/fping.plugin
|
||||
plugins.d/node.d.plugin
|
||||
plugins.d/python.d.plugin
|
||||
plugins.d/tc-qos-helper.sh
|
||||
|
||||
# installer generated files
|
||||
netdata-uninstaller.sh
|
||||
netdata-updater.sh
|
||||
|
|
|
@ -250,7 +250,7 @@ set(CGROUP_NETWORK_SOURCE_FILES
|
|||
|
||||
include_directories(AFTER .)
|
||||
|
||||
add_definitions(-DHAVE_CONFIG_H -DCACHE_DIR="/var/cache/netdata" -DCONFIG_DIR="/etc/netdata" -DLOG_DIR="/var/log/netdata" -DPLUGINS_DIR="/usr/libexec/netdata" -DWEB_DIR="/usr/share/netdata" -DVARLIB_DIR="/var/lib/netdata")
|
||||
add_definitions(-DHAVE_CONFIG_H -DCACHE_DIR="/var/cache/netdata" -DCONFIG_DIR="/etc/netdata" -DLIBCONFIG_DIR="/usr/lib/netdata/conf.d" -DLOG_DIR="/var/log/netdata" -DPLUGINS_DIR="/usr/libexec/netdata" -DWEB_DIR="/usr/share/netdata" -DVARLIB_DIR="/var/lib/netdata")
|
||||
|
||||
add_executable(netdata ${NETDATA_COMMON_FILES} ${NETDATA_LINUX_FILES})
|
||||
target_link_libraries (netdata m z uuid mnl netfilter_acct ${CMAKE_THREAD_LIBS_INIT})
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
-e 's#[@]sbindir_POST@#$(sbindir)#g' \
|
||||
-e 's#[@]sysconfdir_POST@#$(sysconfdir)#g' \
|
||||
-e 's#[@]pythondir_POST@#$(pythondir)#g' \
|
||||
-e 's#[@]configdir_POST@#$(configdir)#g' \
|
||||
-e 's#[@]libconfigdir_POST@#$(libconfigdir)#g' \
|
||||
-e 's#[@]cachedir_POST@#$(cachedir)#g' \
|
||||
$< > $@.tmp; then \
|
||||
mv "$@.tmp" "$@"; \
|
||||
else \
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#
|
||||
MAINTAINERCLEANFILES= $(srcdir)/Makefile.in
|
||||
|
||||
dist_config_DATA = \
|
||||
dist_libconfig_DATA = \
|
||||
apps_groups.conf \
|
||||
charts.d.conf \
|
||||
fping.conf \
|
||||
|
@ -15,7 +15,7 @@ dist_config_DATA = \
|
|||
stream.conf \
|
||||
$(NULL)
|
||||
|
||||
nodeconfigdir=$(configdir)/node.d
|
||||
nodeconfigdir=$(libconfigdir)/node.d
|
||||
dist_nodeconfig_DATA = \
|
||||
node.d/README.md \
|
||||
node.d/fronius.conf.md \
|
||||
|
@ -25,7 +25,7 @@ dist_nodeconfig_DATA = \
|
|||
node.d/stiebeleltron.conf.md \
|
||||
$(NULL)
|
||||
|
||||
pythonconfigdir=$(configdir)/python.d
|
||||
pythonconfigdir=$(libconfigdir)/python.d
|
||||
dist_pythonconfig_DATA = \
|
||||
python.d/apache.conf \
|
||||
python.d/beanstalk.conf \
|
||||
|
@ -34,6 +34,7 @@ dist_pythonconfig_DATA = \
|
|||
python.d/ceph.conf \
|
||||
python.d/chrony.conf \
|
||||
python.d/couchdb.conf \
|
||||
python.d/cpuidle.conf \
|
||||
python.d/cpufreq.conf \
|
||||
python.d/dns_query_time.conf \
|
||||
python.d/dnsdist.conf \
|
||||
|
@ -88,8 +89,7 @@ dist_pythonconfig_DATA = \
|
|||
python.d/web_log.conf \
|
||||
$(NULL)
|
||||
|
||||
healthconfigdir=$(configdir)/health.d
|
||||
|
||||
healthconfigdir=$(libconfigdir)/health.d
|
||||
dist_healthconfig_DATA = \
|
||||
health.d/apache.conf \
|
||||
health.d/apcupsd.conf \
|
||||
|
@ -148,7 +148,7 @@ dist_healthconfig_DATA = \
|
|||
health.d/zfs.conf \
|
||||
$(NULL)
|
||||
|
||||
chartsconfigdir=$(configdir)/charts.d
|
||||
chartsconfigdir=$(libconfigdir)/charts.d
|
||||
dist_chartsconfig_DATA = \
|
||||
charts.d/apache.conf \
|
||||
charts.d/apcupsd.conf \
|
||||
|
@ -172,7 +172,7 @@ dist_chartsconfig_DATA = \
|
|||
charts.d/squid.conf \
|
||||
$(NULL)
|
||||
|
||||
statsdconfigdir=$(configdir)/statsd.d
|
||||
statsdconfigdir=$(libconfigdir)/statsd.d
|
||||
dist_statsdconfig_DATA = \
|
||||
statsd.d/example.conf \
|
||||
$(NULL)
|
||||
|
|
40
conf.d/python.d/cpuidle.conf
Normal file
40
conf.d/python.d/cpuidle.conf
Normal file
|
@ -0,0 +1,40 @@
|
|||
# netdata python.d.plugin configuration for cpuidle
|
||||
#
|
||||
# This file is in YaML format. Generally the format is:
|
||||
#
|
||||
# name: value
|
||||
#
|
||||
# There are 2 sections:
|
||||
# - global variables
|
||||
# - one or more JOBS
|
||||
#
|
||||
# JOBS allow you to collect values from multiple sources.
|
||||
# Each source will have its own set of charts.
|
||||
#
|
||||
# JOB parameters have to be indented (using spaces only, example below).
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Global Variables
|
||||
# These variables set the defaults for all JOBs, however each JOB
|
||||
# may define its own, overriding the defaults.
|
||||
|
||||
# update_every sets the default data collection frequency.
|
||||
# If unset, the python.d.plugin default is used.
|
||||
# update_every: 1
|
||||
|
||||
# priority controls the order of charts at the netdata dashboard.
|
||||
# Lower numbers move the charts towards the top of the page.
|
||||
# If unset, the default for python.d.plugin is used.
|
||||
# priority: 60000
|
||||
|
||||
# retries sets the number of retries to be made in case of failures.
|
||||
# If unset, the default for python.d.plugin is used.
|
||||
# Attempts to restore the service are made once every update_every
|
||||
# and only if the module has collected values in the past.
|
||||
# retries: 60
|
||||
|
||||
# autodetection_retry sets the job re-check interval in seconds.
|
||||
# The job is not deleted if check fails.
|
||||
# Attempts to start the job are made once every autodetection_retry.
|
||||
# This feature is disabled by default.
|
||||
# autodetection_retry: 0
|
|
@ -7,10 +7,10 @@
|
|||
# give a name for this app
|
||||
# this controls the main menu on the dashboard
|
||||
# and will be the prefix for all charts of the app
|
||||
name = myapp
|
||||
name = myexampleapp
|
||||
|
||||
# match all the metrics of the app
|
||||
metrics = myapp.*
|
||||
metrics = myexampleapp.*
|
||||
|
||||
# shall private charts of these metrics be created?
|
||||
private charts = no
|
||||
|
@ -29,10 +29,10 @@
|
|||
|
||||
|
||||
# create a chart
|
||||
# this is its id - the chart will be named myapp.mychart
|
||||
[mychart]
|
||||
# this is its id - the chart will be named myexampleapp.myexamplechart
|
||||
[myexamplechart]
|
||||
# a name for the chart, similar to the id (2 names for each chart)
|
||||
name = mychart
|
||||
name = myexamplechart
|
||||
|
||||
# the chart title
|
||||
title = my chart title
|
||||
|
@ -57,9 +57,9 @@
|
|||
# events = the number of events for this metric
|
||||
# last = the last value collected
|
||||
# all the others are only valid for histograms and timers
|
||||
dimension = myapp.metric1 avg average 1 1
|
||||
dimension = myapp.metric1 lower min 1 1
|
||||
dimension = myapp.metric1 upper max 1 1
|
||||
dimension = myapp.metric2 other last 1 1
|
||||
dimension = myexampleapp.metric1 avg average 1 1
|
||||
dimension = myexampleapp.metric1 lower min 1 1
|
||||
dimension = myexampleapp.metric1 upper max 1 1
|
||||
dimension = myexampleapp.metric2 other last 1 1
|
||||
|
||||
# You can add as many charts as needed
|
||||
|
|
|
@ -65,6 +65,7 @@ declare -A configs_signatures=(
|
|||
['111ead4b350593dd69b6f7ac0307b49b']='python.d/httpcheck.conf'
|
||||
['12a4c7803ae79506a14ea784fea60dce']='health.d/net.conf'
|
||||
['12d27b9f4d1696c2d49a77ed71d68e6f']='python.d/w1sensor.conf'
|
||||
['12e57bea1127933a4fe49ce2e9674f4d']='statsd.d/example.conf'
|
||||
['13141998a5d71308d9c119834c27bfd3']='python.d.conf'
|
||||
['13ccf65fd879795f0fcea89ade27c2d0']='health.d/swap.conf'
|
||||
['13e861a3d2f3075de883994ab54df658']='health.d/megacli.conf'
|
||||
|
|
|
@ -493,6 +493,7 @@ AC_SUBST([chartsdir], ["\$(libexecdir)/netdata/charts.d"])
|
|||
AC_SUBST([nodedir], ["\$(libexecdir)/netdata/node.d"])
|
||||
AC_SUBST([pythondir], ["\$(libexecdir)/netdata/python.d"])
|
||||
AC_SUBST([configdir], ["\$(sysconfdir)/netdata"])
|
||||
AC_SUBST([libconfigdir], ["\$(libdir)/netdata/conf.d"])
|
||||
AC_SUBST([logdir], ["\$(localstatedir)/log/netdata"])
|
||||
AC_SUBST([pluginsdir], ["\$(libexecdir)/netdata/plugins.d"])
|
||||
AC_SUBST([webdir])
|
||||
|
|
|
@ -24,62 +24,49 @@ do
|
|||
shift
|
||||
done
|
||||
|
||||
deleted_stock_configs=0
|
||||
if [ ! -f "etc/netdata/.installer-cleanup-of-stock-configs-done" ]
|
||||
then
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
progress "Checking new configuration files"
|
||||
# -----------------------------------------------------------------------------
|
||||
progress "Deleting stock configuration files from user configuration directory"
|
||||
|
||||
declare -A configs_signatures=()
|
||||
. system/configs.signatures
|
||||
declare -A configs_signatures=()
|
||||
source "system/configs.signatures"
|
||||
|
||||
if [ ! -d etc/netdata ]
|
||||
then
|
||||
run mkdir -p etc/netdata
|
||||
fi
|
||||
|
||||
md5sum="$(which md5sum 2>/dev/null || command -v md5sum 2>/dev/null || command -v md5 2>/dev/null)"
|
||||
for x in $(find etc.new -type f)
|
||||
do
|
||||
# find it relative filename
|
||||
f="${x/etc.new\/netdata\//}"
|
||||
t="${x/etc.new\//etc\/}"
|
||||
d=$(dirname "${t}")
|
||||
|
||||
#echo >&2 "x: ${x}"
|
||||
#echo >&2 "t: ${t}"
|
||||
#echo >&2 "d: ${d}"
|
||||
|
||||
if [ ! -d "${d}" ]
|
||||
if [ ! -d etc/netdata ]
|
||||
then
|
||||
run mkdir -p "${d}"
|
||||
run mkdir -p etc/netdata
|
||||
fi
|
||||
|
||||
if [ ! -f "${t}" ]
|
||||
then
|
||||
run cp "${x}" "${t}"
|
||||
continue
|
||||
fi
|
||||
md5sum="$(which md5sum 2>/dev/null || command -v md5sum 2>/dev/null || command -v md5 2>/dev/null)"
|
||||
for x in $(find etc -type f)
|
||||
do
|
||||
# find it relative filename
|
||||
f="${x/etc\/netdata\//}"
|
||||
|
||||
if [ ! -z "${md5sum}" ]
|
||||
then
|
||||
# find the checksum of the existing file
|
||||
md5="$(cat "${t}" | ${md5sum} | cut -d ' ' -f 1)"
|
||||
#echo >&2 "md5: ${md5}"
|
||||
# find the stock filename
|
||||
t="${f/.conf.old/.conf}"
|
||||
t="${t/.conf.orig/.conf}"
|
||||
|
||||
# check if it matches
|
||||
if [ "${configs_signatures[${md5}]}" = "${f}" ]
|
||||
if [ ! -z "${md5sum}" ]
|
||||
then
|
||||
run cp "${x}" "${t}"
|
||||
# find the checksum of the existing file
|
||||
md5="$( ${md5sum} <"${x}" | cut -d ' ' -f 1)"
|
||||
#echo >&2 "md5: ${md5}"
|
||||
|
||||
# check if it matches
|
||||
if [ "${configs_signatures[${md5}]}" = "${t}" ]
|
||||
then
|
||||
# it matches the default
|
||||
run rm -f "${x}"
|
||||
deleted_stock_configs=$(( deleted_stock_configs + 1 ))
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! [[ "${x}" =~ .*\.orig ]]
|
||||
then
|
||||
run mv "${x}" "${t}.orig"
|
||||
fi
|
||||
done
|
||||
|
||||
run rm -rf etc.new
|
||||
done
|
||||
|
||||
touch "etc/netdata/.installer-cleanup-of-stock-configs-done"
|
||||
fi
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
progress "Add user netdata to required user groups"
|
||||
|
@ -166,6 +153,26 @@ dir_should_be_link . var/lib/netdata netdata-dbs
|
|||
dir_should_be_link . var/cache/netdata netdata-metrics
|
||||
dir_should_be_link . var/log/netdata netdata-logs
|
||||
|
||||
dir_should_be_link etc/netdata ../../usr/lib/netdata/conf.d orig
|
||||
|
||||
if [ ${deleted_stock_configs} -gt 0 ]
|
||||
then
|
||||
dir_should_be_link etc/netdata ../../usr/lib/netdata/conf.d "000.-.USE.THE.orig.LINK.TO.COPY.AND.EDIT.STOCK.CONFIG.FILES"
|
||||
fi
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
progress "create user config directories"
|
||||
|
||||
for x in "python.d" "charts.d" "node.d" "health.d" "statsd.d"
|
||||
do
|
||||
if [ ! -d "etc/netdata/${x}" ]
|
||||
then
|
||||
run mkdir -p "etc/netdata/${x}" || exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
progress "fix permissions"
|
||||
|
|
|
@ -13,13 +13,6 @@ else
|
|||
# export CFLAGS="-static -O1 -ggdb -Wall -Wextra -Wformat-signedness"
|
||||
fi
|
||||
|
||||
if [ ! -z "${NETDATA_INSTALL_PATH}" -a -d "${NETDATA_INSTALL_PATH}/etc" ]
|
||||
then
|
||||
# make sure we don't have an old etc path, so that the installer
|
||||
# will install all files without examining changes
|
||||
run mv "${NETDATA_INSTALL_PATH}/etc" "${NETDATA_INSTALL_PATH}/etc.new"
|
||||
fi
|
||||
|
||||
run ./netdata-installer.sh --install "${NETDATA_INSTALL_PARENT}" \
|
||||
--dont-wait \
|
||||
--dont-start-it \
|
||||
|
|
|
@ -72,27 +72,6 @@ EOF
|
|||
run chmod 755 "${NETDATA_INSTALL_PATH}/bin/netdata"
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# move etc to protect the destination when unpacked
|
||||
|
||||
if [ ! -z "${NETDATA_INSTALL_PATH}" -a -d "${NETDATA_INSTALL_PATH}/etc" ]
|
||||
then
|
||||
if [ -d "${NETDATA_INSTALL_PATH}/etc.new" ]
|
||||
then
|
||||
run rm -rf "${NETDATA_INSTALL_PATH}/etc.new" || exit 1
|
||||
fi
|
||||
|
||||
run mv "${NETDATA_INSTALL_PATH}/etc" \
|
||||
"${NETDATA_INSTALL_PATH}/etc.new" || exit 1
|
||||
|
||||
if [ -f "${NETDATA_INSTALL_PATH}/etc.new/netdata/netdata.conf" ]
|
||||
then
|
||||
# delete the generated netdata.conf, so that the static installer will generate a new one
|
||||
run rm "${NETDATA_INSTALL_PATH}/etc.new/netdata/netdata.conf"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# remove the links to allow untaring the archive
|
||||
|
||||
|
|
|
@ -492,6 +492,7 @@ progress "Cleanup compilation directory"
|
|||
|
||||
[ -f src/netdata ] && run make clean
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
progress "Compile netdata"
|
||||
|
||||
|
@ -543,79 +544,76 @@ if [ -d "${NETDATA_PREFIX}/etc/netdata" ]
|
|||
fi
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
progress "Backup existing netdata configuration before installing it"
|
||||
|
||||
if [ "${BASH_VERSINFO[0]}" -ge "4" ]
|
||||
deleted_stock_configs=0
|
||||
if [ ! -f "${NETDATA_PREFIX}/etc/netdata/.installer-cleanup-of-stock-configs-done" ]
|
||||
then
|
||||
declare -A configs_signatures=()
|
||||
if [ -f "configs.signatures" ]
|
||||
then
|
||||
source "configs.signatures" || echo >&2 "ERROR: Failed to load configs.signatures !"
|
||||
fi
|
||||
fi
|
||||
|
||||
config_signature_matches() {
|
||||
local md5="${1}" file="${2}"
|
||||
progress "Backup existing netdata configuration before installing it"
|
||||
|
||||
if [ "${BASH_VERSINFO[0]}" -ge "4" ]
|
||||
then
|
||||
[ "${configs_signatures[${md5}]}" = "${file}" ] && return 0
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ -f "configs.signatures" ]
|
||||
then
|
||||
grep "\['${md5}'\]='${file}'" "configs.signatures" >/dev/null
|
||||
return $?
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# backup user configurations
|
||||
installer_backup_suffix="${PID}.${RANDOM}"
|
||||
for x in $(find -L "${NETDATA_PREFIX}/etc/netdata" -name '*.conf' -type f)
|
||||
do
|
||||
if [ -f "${x}" ]
|
||||
then
|
||||
# make a backup of the configuration file
|
||||
cp -p "${x}" "${x}.old"
|
||||
|
||||
if [ -z "${md5sum}" -o ! -x "${md5sum}" ]
|
||||
then
|
||||
declare -A configs_signatures=()
|
||||
if [ -f "configs.signatures" ]
|
||||
then
|
||||
# we don't have md5sum - keep it
|
||||
echo >&2 "File '${TPUT_CYAN}${x}${TPUT_RESET}' ${TPUT_RET}is not known to distribution${TPUT_RESET}. Keeping it."
|
||||
run cp -a "${x}" "${x}.installer_backup.${installer_backup_suffix}"
|
||||
else
|
||||
# find it relative filename
|
||||
f="${x/*\/etc\/netdata\//}"
|
||||
source "configs.signatures" || echo >&2 "ERROR: Failed to load configs.signatures !"
|
||||
fi
|
||||
fi
|
||||
|
||||
# find its checksum
|
||||
md5="$(cat "${x}" | ${md5sum} | cut -d ' ' -f 1)"
|
||||
config_signature_matches() {
|
||||
local md5="${1}" file="${2}"
|
||||
|
||||
# copy the original
|
||||
if [ -f "conf.d/${f}" ]
|
||||
then
|
||||
cp "conf.d/${f}" "${x}.orig"
|
||||
fi
|
||||
|
||||
if config_signature_matches "${md5}" "${f}"
|
||||
then
|
||||
# it is a stock version - don't keep it
|
||||
echo >&2 "File '${TPUT_CYAN}${x}${TPUT_RESET}' is stock version."
|
||||
else
|
||||
# edited by user - keep it
|
||||
echo >&2 "File '${TPUT_CYAN}${x}${TPUT_RESET}' ${TPUT_RED} has been edited by user${TPUT_RESET}. Keeping it."
|
||||
run cp -a "${x}" "${x}.installer_backup.${installer_backup_suffix}"
|
||||
fi
|
||||
if [ "${BASH_VERSINFO[0]}" -ge "4" ]
|
||||
then
|
||||
[ "${configs_signatures[${md5}]}" = "${file}" ] && return 0
|
||||
return 1
|
||||
fi
|
||||
|
||||
elif [ -f "${x}.installer_backup.${installer_backup_suffix}" ]
|
||||
then
|
||||
rm -f "${x}.installer_backup.${installer_backup_suffix}"
|
||||
fi
|
||||
done
|
||||
if [ -f "configs.signatures" ]
|
||||
then
|
||||
grep "\['${md5}'\]='${file}'" "configs.signatures" >/dev/null
|
||||
return $?
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# clean up stock config files from the user configuration directory
|
||||
for x in $(find -L "${NETDATA_PREFIX}/etc/netdata" -type f)
|
||||
do
|
||||
if [ -f "${x}" ]
|
||||
then
|
||||
# find it relative filename
|
||||
f="${x/${NETDATA_PREFIX}\/etc\/netdata\//}"
|
||||
|
||||
# find the stock filename
|
||||
t="${f/.conf.installer_backup.*/.conf}"
|
||||
t="${t/.conf.old/.conf}"
|
||||
t="${t/.conf.orig/.conf}"
|
||||
|
||||
if [ -z "${md5sum}" -o ! -x "${md5sum}" ]
|
||||
then
|
||||
# we don't have md5sum - keep it
|
||||
echo >&2 "File '${TPUT_CYAN}${x}${TPUT_RESET}' ${TPUT_RET}is not known to distribution${TPUT_RESET}. Keeping it."
|
||||
else
|
||||
# find its checksum
|
||||
md5="$(${md5sum} <"${x}" | cut -d ' ' -f 1)"
|
||||
|
||||
if config_signature_matches "${md5}" "${t}"
|
||||
then
|
||||
# it is a stock version - remove it
|
||||
echo >&2 "File '${TPUT_CYAN}${x}${TPUT_RESET}' is stock version of '${t}'."
|
||||
run rm -f "${x}"
|
||||
deleted_stock_configs=$(( deleted_stock_configs + 1 ))
|
||||
else
|
||||
# edited by user - keep it
|
||||
echo >&2 "File '${TPUT_CYAN}${x}${TPUT_RESET}' ${TPUT_RED} does not match stock of '${t}'${TPUT_RESET}. Keeping it."
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
touch "${NETDATA_PREFIX}/etc/netdata/.installer-cleanup-of-stock-configs-done"
|
||||
fi
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
progress "Install netdata"
|
||||
|
@ -623,19 +621,6 @@ progress "Install netdata"
|
|||
run make install || exit 1
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
progress "Restore user edited netdata configuration files"
|
||||
|
||||
for x in $(find -L "${NETDATA_PREFIX}/etc/netdata/" -name '*.conf' -type f)
|
||||
do
|
||||
if [ -f "${x}.installer_backup.${installer_backup_suffix}" ]
|
||||
then
|
||||
run cp -a "${x}.installer_backup.${installer_backup_suffix}" "${x}" && \
|
||||
run rm -f "${x}.installer_backup.${installer_backup_suffix}"
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
progress "Fix generated files permissions"
|
||||
|
||||
|
@ -709,28 +694,30 @@ NETDATA_LIB_DIR="$( config_option "global" "lib directory" "${NETDATA_PREFIX}/va
|
|||
NETDATA_CACHE_DIR="$( config_option "global" "cache directory" "${NETDATA_PREFIX}/var/cache/netdata" )"
|
||||
NETDATA_WEB_DIR="$( config_option "global" "web files directory" "${NETDATA_PREFIX}/usr/share/netdata/web" )"
|
||||
NETDATA_LOG_DIR="$( config_option "global" "log directory" "${NETDATA_PREFIX}/var/log/netdata" )"
|
||||
NETDATA_CONF_DIR="$( config_option "global" "config directory" "${NETDATA_PREFIX}/etc/netdata" )"
|
||||
NETDATA_USER_CONFIG_DIR="$( config_option "global" "config directory" "${NETDATA_PREFIX}/etc/netdata" )"
|
||||
NETDATA_STOCK_CONFIG_DIR="$( config_option "global" "stock config directory" "${NETDATA_PREFIX}/usr/lib/netdata/conf.d" )"
|
||||
NETDATA_RUN_DIR="${NETDATA_PREFIX}/var/run"
|
||||
|
||||
cat <<OPTIONSEOF
|
||||
|
||||
Permissions
|
||||
- netdata user : ${NETDATA_USER}
|
||||
- netdata group : ${NETDATA_GROUP}
|
||||
- web files user : ${NETDATA_WEB_USER}
|
||||
- web files group : ${NETDATA_WEB_GROUP}
|
||||
- root user : ${ROOT_USER}
|
||||
- netdata user : ${NETDATA_USER}
|
||||
- netdata group : ${NETDATA_GROUP}
|
||||
- web files user : ${NETDATA_WEB_USER}
|
||||
- web files group : ${NETDATA_WEB_GROUP}
|
||||
- root user : ${ROOT_USER}
|
||||
|
||||
Directories
|
||||
- netdata conf dir : ${NETDATA_CONF_DIR}
|
||||
- netdata log dir : ${NETDATA_LOG_DIR}
|
||||
- netdata run dir : ${NETDATA_RUN_DIR}
|
||||
- netdata lib dir : ${NETDATA_LIB_DIR}
|
||||
- netdata web dir : ${NETDATA_WEB_DIR}
|
||||
- netdata cache dir: ${NETDATA_CACHE_DIR}
|
||||
- netdata user config dir : ${NETDATA_USER_CONFIG_DIR}
|
||||
- netdata stock config dir : ${NETDATA_STOCK_CONFIG_DIR}
|
||||
- netdata log dir : ${NETDATA_LOG_DIR}
|
||||
- netdata run dir : ${NETDATA_RUN_DIR}
|
||||
- netdata lib dir : ${NETDATA_LIB_DIR}
|
||||
- netdata web dir : ${NETDATA_WEB_DIR}
|
||||
- netdata cache dir : ${NETDATA_CACHE_DIR}
|
||||
|
||||
Other
|
||||
- netdata port : ${NETDATA_PORT}
|
||||
- netdata port : ${NETDATA_PORT}
|
||||
|
||||
OPTIONSEOF
|
||||
|
||||
|
@ -745,17 +732,35 @@ fi
|
|||
|
||||
# --- conf dir ----
|
||||
|
||||
for x in "python.d" "charts.d" "node.d"
|
||||
for x in "python.d" "charts.d" "node.d" "health.d" "statsd.d"
|
||||
do
|
||||
if [ ! -d "${NETDATA_CONF_DIR}/${x}" ]
|
||||
if [ ! -d "${NETDATA_USER_CONFIG_DIR}/${x}" ]
|
||||
then
|
||||
echo >&2 "Creating directory '${NETDATA_CONF_DIR}/${x}'"
|
||||
run mkdir -p "${NETDATA_CONF_DIR}/${x}" || exit 1
|
||||
echo >&2 "Creating directory '${NETDATA_USER_CONFIG_DIR}/${x}'"
|
||||
run mkdir -p "${NETDATA_USER_CONFIG_DIR}/${x}" || exit 1
|
||||
fi
|
||||
done
|
||||
run chown -R "${ROOT_USER}:${NETDATA_GROUP}" "${NETDATA_CONF_DIR}"
|
||||
run find "${NETDATA_CONF_DIR}" -type f -exec chmod 0640 {} \;
|
||||
run find "${NETDATA_CONF_DIR}" -type d -exec chmod 0755 {} \;
|
||||
run chown -R "${ROOT_USER}:${NETDATA_GROUP}" "${NETDATA_USER_CONFIG_DIR}"
|
||||
run find "${NETDATA_USER_CONFIG_DIR}" -type f -exec chmod 0640 {} \;
|
||||
run find "${NETDATA_USER_CONFIG_DIR}" -type d -exec chmod 0755 {} \;
|
||||
|
||||
# --- stock conf dir ----
|
||||
|
||||
[ ! -d "${NETDATA_STOCK_CONFIG_DIR}" ] && mkdir -p "${NETDATA_STOCK_CONFIG_DIR}"
|
||||
|
||||
helplink="000.-.USE.THE.orig.LINK.TO.COPY.AND.EDIT.STOCK.CONFIG.FILES"
|
||||
[ ${deleted_stock_configs} -eq 0 ] && helplink=""
|
||||
for link in "orig" "${helplink}"
|
||||
do
|
||||
if [ ! -z "${link}" ]
|
||||
then
|
||||
[ -L "${NETDATA_USER_CONFIG_DIR}/${link}" ] && run rm -f "${NETDATA_USER_CONFIG_DIR}/${link}"
|
||||
run ln -s "${NETDATA_STOCK_CONFIG_DIR}" "${NETDATA_USER_CONFIG_DIR}/${link}"
|
||||
fi
|
||||
done
|
||||
run chown -R "${ROOT_USER}:${NETDATA_GROUP}" "${NETDATA_STOCK_CONFIG_DIR}"
|
||||
run find "${NETDATA_STOCK_CONFIG_DIR}" -type f -exec chmod 0640 {} \;
|
||||
run find "${NETDATA_STOCK_CONFIG_DIR}" -type d -exec chmod 0755 {} \;
|
||||
|
||||
# --- web dir ----
|
||||
|
||||
|
|
|
@ -181,17 +181,18 @@ rm -rf "${RPM_BUILD_ROOT}"
|
|||
%defattr(-,root,root)
|
||||
|
||||
%dir %{_sysconfdir}/%{name}
|
||||
%dir %{_libdir}/%{name}
|
||||
|
||||
%config(noreplace) %{_sysconfdir}/%{name}/*.conf
|
||||
%config(noreplace) %{_sysconfdir}/%{name}/charts.d/*.conf
|
||||
%config(noreplace) %{_sysconfdir}/%{name}/health.d/*.conf
|
||||
#%%config(noreplace) %{_sysconfdir}/%{name}/node.d/*.conf
|
||||
%config(noreplace) %{_sysconfdir}/%{name}/python.d/*.conf
|
||||
%config(noreplace) %{_sysconfdir}/%{name}/statsd.d/*.conf
|
||||
%config(noreplace) %{_sysconfdir}/logrotate.d/%{name}
|
||||
%config %{_libdir}/%{name}/*.conf
|
||||
%config %{_libdir}/%{name}/charts.d/*.conf
|
||||
%config %{_libdir}/%{name}/health.d/*.conf
|
||||
%config %{_libdir}/%{name}/node.d/*.conf
|
||||
%config %{_libdir}/%{name}/python.d/*.conf
|
||||
%config %{_libdir}/%{name}/statsd.d/*.conf
|
||||
%config %{_sysconfdir}/logrotate.d/%{name}
|
||||
|
||||
# To be eventually moved to %%_defaultdocdir
|
||||
%{_sysconfdir}/%{name}/node.d/*.md
|
||||
%{_libdir}/%{name}/node.d/*.md
|
||||
%{_libexecdir}/%{name}
|
||||
%{_sbindir}/%{name}
|
||||
|
||||
|
@ -215,9 +216,16 @@ rm -rf "${RPM_BUILD_ROOT}"
|
|||
|
||||
%dir %{_datadir}/%{name}
|
||||
%dir %{_sysconfdir}/%{name}/health.d
|
||||
%dir %{_libdir}/%{name}/health.d
|
||||
%dir %{_sysconfdir}/%{name}/python.d
|
||||
%dir %{_libdir}/%{name}/python.d
|
||||
%dir %{_sysconfdir}/%{name}/charts.d
|
||||
%dir %{_libdir}/%{name}/charts.d
|
||||
%dir %{_sysconfdir}/%{name}/node.d
|
||||
%dir %{_libdir}/%{name}/node.d
|
||||
%dir %{_sysconfdir}/%{name}/statsd.d
|
||||
%dir %{_libdir}/%{name}/statsd.d
|
||||
|
||||
|
||||
%if %{with systemd}
|
||||
%{_unitdir}/netdata.service
|
||||
|
|
|
@ -3,6 +3,19 @@
|
|||
# SPDX-License-Identifier: GPL-3.0+
|
||||
#
|
||||
MAINTAINERCLEANFILES= $(srcdir)/Makefile.in
|
||||
CLEANFILES = \
|
||||
alarm-notify.sh \
|
||||
cgroup-name.sh \
|
||||
charts.d.plugin \
|
||||
fping.plugin \
|
||||
node.d.plugin \
|
||||
python.d.plugin \
|
||||
tc-qos-helper.sh \
|
||||
$(NULL)
|
||||
|
||||
include $(top_srcdir)/build/subst.inc
|
||||
|
||||
SUFFIXES = .in
|
||||
|
||||
dist_plugins_DATA = \
|
||||
README.md \
|
||||
|
@ -22,3 +35,13 @@ dist_plugins_SCRIPTS = \
|
|||
tc-qos-helper.sh \
|
||||
loopsleepms.sh.inc \
|
||||
$(NULL)
|
||||
|
||||
dist_noinst_DATA = \
|
||||
alarm-notify.sh.in \
|
||||
cgroup-name.sh.in \
|
||||
charts.d.plugin.in \
|
||||
fping.plugin.in \
|
||||
node.d.plugin.in \
|
||||
python.d.plugin.in \
|
||||
tc-qos-helper.sh.in \
|
||||
$(NULL)
|
||||
|
|
|
@ -159,9 +159,10 @@ custom_sender() {
|
|||
# -----------------------------------------------------------------------------
|
||||
# defaults to allow running this script by hand
|
||||
|
||||
[ -z "${NETDATA_CONFIG_DIR}" ] && NETDATA_CONFIG_DIR="$(dirname "${0}")/../../../../etc/netdata"
|
||||
[ -z "${NETDATA_CACHE_DIR}" ] && NETDATA_CACHE_DIR="$(dirname "${0}")/../../../../var/cache/netdata"
|
||||
[ -z "${NETDATA_REGISTRY_URL}" ] && NETDATA_REGISTRY_URL="https://registry.my-netdata.io"
|
||||
[ -z "${NETDATA_USER_CONFIG_DIR}" ] && NETDATA_USER_CONFIG_DIR="@configdir_POST@"
|
||||
[ -z "${NETDATA_STOCK_CONFIG_DIR}" ] && NETDATA_STOCK_CONFIG_DIR="@libconfigdir_POST@"
|
||||
[ -z "${NETDATA_CACHE_DIR}" ] && NETDATA_CACHE_DIR="@cachedir_POST@"
|
||||
[ -z "${NETDATA_REGISTRY_URL}" ] && NETDATA_REGISTRY_URL="https://registry.my-netdata.io"
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# parse command line parameters
|
||||
|
@ -362,14 +363,20 @@ DEFAULT_RECIPIENT_IRC=
|
|||
IRC_NETWORK=
|
||||
declare -A role_recipients_irc=()
|
||||
|
||||
# load the user configuration
|
||||
# this will overwrite the variables above
|
||||
if [ -f "${NETDATA_CONFIG_DIR}/health_alarm_notify.conf" ]
|
||||
then
|
||||
source "${NETDATA_CONFIG_DIR}/health_alarm_notify.conf"
|
||||
else
|
||||
error "Cannot find file ${NETDATA_CONFIG_DIR}/health_alarm_notify.conf. Using internal defaults."
|
||||
fi
|
||||
# load the stock and user configuration files
|
||||
# these will overwrite the variables above
|
||||
|
||||
for CONFIG in "${NETDATA_STOCK_CONFIG_DIR}/health_alarm_notify.conf" "${NETDATA_USER_CONFIG_DIR}/health_alarm_notify.conf"
|
||||
do
|
||||
if [ -f "${CONFIG}" ]
|
||||
then
|
||||
debug "Loading config file '${CONFIG}'..."
|
||||
source "${CONFIG}"
|
||||
[ $? -ne 0 ] && error "Failed to load config file '${CONFIG}'."
|
||||
else
|
||||
warning "Cannot find file '${CONFIG}'."
|
||||
fi
|
||||
done
|
||||
|
||||
# If we didn't autodetect the character set for e-mail and it wasn't
|
||||
# set by the user, we need to set it to a reasonable default. UTF-8
|
|
@ -51,9 +51,10 @@ debug() {
|
|||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
[ -z "${NETDATA_CONFIG_DIR}" ] && NETDATA_CONFIG_DIR="$(dirname "${0}")/../../../../etc/netdata"
|
||||
[ -z "${NETDATA_USER_CONFIG_DIR}" ] && NETDATA_USER_CONFIG_DIR="@configdir_POST@"
|
||||
[ -z "${NETDATA_STOCK_CONFIG_DIR}" ] && NETDATA_STOCK_CONFIG_DIR="@libconfigdir_POST@"
|
||||
|
||||
DOCKER_HOST="${DOCKER_HOST:=/var/run/docker.sock}"
|
||||
CONFIG="${NETDATA_CONFIG_DIR}/cgroups-names.conf"
|
||||
CGROUP="${1}"
|
||||
NAME=
|
||||
|
||||
|
@ -64,16 +65,21 @@ if [ -z "${CGROUP}" ]
|
|||
fatal "called without a cgroup name. Nothing to do."
|
||||
fi
|
||||
|
||||
if [ -f "${CONFIG}" ]
|
||||
for CONFIG in "${NETDATA_USER_CONFIG_DIR}/cgroups-names.conf" "${NETDATA_STOCK_CONFIG_DIR}/cgroups-names.conf"
|
||||
do
|
||||
if [ -f "${CONFIG}" ]
|
||||
then
|
||||
NAME="$(grep "^${CGROUP} " "${CONFIG}" | sed "s/[[:space:]]\+/ /g" | cut -d ' ' -f 2)"
|
||||
if [ -z "${NAME}" ]
|
||||
then
|
||||
info "cannot find cgroup '${CGROUP}' in '${CONFIG}'."
|
||||
NAME="$(grep "^${CGROUP} " "${CONFIG}" | sed "s/[[:space:]]\+/ /g" | cut -d ' ' -f 2)"
|
||||
if [ -z "${NAME}" ]
|
||||
then
|
||||
info "cannot find cgroup '${CGROUP}' in '${CONFIG}'."
|
||||
else
|
||||
break
|
||||
fi
|
||||
#else
|
||||
# info "configuration file '${CONFIG}' is not available."
|
||||
fi
|
||||
#else
|
||||
# info "configuration file '${CONFIG}' is not available."
|
||||
fi
|
||||
done
|
||||
|
||||
function docker_get_name_classic {
|
||||
local id="${1}"
|
|
@ -117,14 +117,15 @@ info "started from '$PROGRAM_FILE' with options: $*"
|
|||
# netdata exposes a few environment variables for us
|
||||
|
||||
[ -z "${NETDATA_PLUGINS_DIR}" ] && NETDATA_PLUGINS_DIR="$(dirname "${0}")"
|
||||
[ -z "${NETDATA_CONFIG_DIR}" ] && NETDATA_CONFIG_DIR="$(dirname "${0}")/../../../../etc/netdata"
|
||||
[ -z "${NETDATA_USER_CONFIG_DIR}" ] && NETDATA_USER_CONFIG_DIR="@configdir_POST@"
|
||||
[ -z "${NETDATA_STOCK_CONFIG_DIR}" ] && NETDATA_STOCK_CONFIG_DIR="@libconfigdir_POST@"
|
||||
|
||||
pluginsd="${NETDATA_PLUGINS_DIR}"
|
||||
confd="${NETDATA_CONFIG_DIR}"
|
||||
stockconfd="${NETDATA_STOCK_CONFIG_DIR}/${PROGRAM_NAME}"
|
||||
userconfd="${NETDATA_USER_CONFIG_DIR}/${PROGRAM_NAME}"
|
||||
olduserconfd="${NETDATA_USER_CONFIG_DIR}"
|
||||
chartsd="$pluginsd/../charts.d"
|
||||
|
||||
myconfig="$confd/$PROGRAM_NAME.conf"
|
||||
|
||||
minimum_update_frequency="${NETDATA_UPDATE_EVERY-1}"
|
||||
update_every=${minimum_update_frequency} # this will be overwritten by the command line
|
||||
|
||||
|
@ -231,22 +232,33 @@ mysleep="sleep"
|
|||
# if found and included, this file overwrites loopsleepms()
|
||||
# and current_time_ms() with a high resolution timer function
|
||||
# for precise looping.
|
||||
. "$pluginsd/loopsleepms.sh.inc"
|
||||
source "$pluginsd/loopsleepms.sh.inc"
|
||||
[ $? -ne 0 ] && error "Failed to load '$pluginsd/loopsleepms.sh.inc'."
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# load my configuration
|
||||
|
||||
if [ -f "$myconfig" ]
|
||||
for myconfig in "${NETDATA_STOCK_CONFIG_DIR}/${PROGRAM_NAME}.conf" "${NETDATA_USER_CONFIG_DIR}/${PROGRAM_NAME}.conf"
|
||||
do
|
||||
if [ -f "$myconfig" ]
|
||||
then
|
||||
. "$myconfig"
|
||||
[ $? -ne 0 ] && fatal "cannot load $myconfig"
|
||||
source "$myconfig"
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
error "Config file '$myconfig' loaded with errors."
|
||||
else
|
||||
info "Configuration file '$myconfig' loaded."
|
||||
fi
|
||||
else
|
||||
warning "Configuration file '$myconfig' not found."
|
||||
fi
|
||||
done
|
||||
|
||||
# make sure time_divisor is right
|
||||
time_divisor=$((time_divisor))
|
||||
[ $time_divisor -lt 10 ] && time_divisor=10
|
||||
[ $time_divisor -gt 100 ] && time_divisor=100
|
||||
|
||||
time_divisor=$((time_divisor))
|
||||
[ $time_divisor -lt 10 ] && time_divisor=10
|
||||
[ $time_divisor -gt 100 ] && time_divisor=100
|
||||
else
|
||||
info "configuration file '$myconfig' not found. Using defaults."
|
||||
fi
|
||||
|
||||
# we check for the timeout command, after we load our
|
||||
# configuration, so that the user may overwrite the
|
||||
|
@ -412,7 +424,7 @@ all_enabled_charts() {
|
|||
|
||||
if [ ! "${enabled}" = "${required}" ]
|
||||
then
|
||||
info "is disabled. Add a line with $chart=$required in $myconfig to enable it (or remove the line that disables it)."
|
||||
info "is disabled. Add a line with $chart=$required in '${NETDATA_USER_CONFIG_DIR}/${PROGRAM_NAME}.conf' to enable it (or remove the line that disables it)."
|
||||
else
|
||||
debug "is enabled for auto-detection."
|
||||
local charts="$charts $chart"
|
||||
|
@ -448,18 +460,18 @@ all_enabled_charts() {
|
|||
fi
|
||||
|
||||
# check its config
|
||||
#if [ -f "$confd/$chart.conf" ]
|
||||
#if [ -f "$userconfd/$chart.conf" ]
|
||||
#then
|
||||
# if [ ! -z "$( cat "$confd/$chart.conf" | sed "s/^ \+//g" | grep -v "^$" | grep -v "^#" | grep -v "^$chart$charts_undescore" )" ]
|
||||
# if [ ! -z "$( cat "$userconfd/$chart.conf" | sed "s/^ \+//g" | grep -v "^$" | grep -v "^#" | grep -v "^$chart$charts_undescore" )" ]
|
||||
# then
|
||||
# error "module's $chart config $confd/$chart.conf should only have lines starting with $chart$charts_undescore . Disabling it."
|
||||
# error "module's $chart config $userconfd/$chart.conf should only have lines starting with $chart$charts_undescore . Disabling it."
|
||||
# continue
|
||||
# fi
|
||||
#fi
|
||||
|
||||
#if [ $dryrunner -eq 1 ]
|
||||
# then
|
||||
# "$pluginsd/charts.d.dryrun-helper.sh" "$chart" "$chartsd/$chart.chart.sh" "$confd/$chart.conf" >/dev/null
|
||||
# "$pluginsd/charts.d.dryrun-helper.sh" "$chart" "$chartsd/$chart.chart.sh" "$userconfd/$chart.conf" >/dev/null
|
||||
# if [ $? -ne 0 ]
|
||||
# then
|
||||
# error "module's $chart did not pass the dry run check. This means it uses global variables not starting with $chart. Disabling it."
|
||||
|
@ -487,18 +499,35 @@ do
|
|||
|
||||
debug "loading module: '$chartsd/$chart.chart.sh'"
|
||||
|
||||
. "$chartsd/$chart.chart.sh"
|
||||
source "$chartsd/$chart.chart.sh"
|
||||
[ $? -ne 0 ] && warning "Module '$chartsd/$chart.chart.sh' loaded with errors."
|
||||
|
||||
if [ -f "$confd/$PROGRAM_NAME/$chart.conf" ]
|
||||
# first load the stock config
|
||||
if [ -f "$stockconfd/$chart.conf" ]
|
||||
then
|
||||
debug "loading module configuration: '$confd/$PROGRAM_NAME/$chart.conf'"
|
||||
. "$confd/$PROGRAM_NAME/$chart.conf"
|
||||
elif [ -f "$confd/$chart.conf" ]
|
||||
then
|
||||
debug "loading module configuration: '$confd/$chart.conf'"
|
||||
. "$confd/$chart.conf"
|
||||
debug "loading module configuration: '$stockconfd/$chart.conf'"
|
||||
source "$stockconfd/$chart.conf"
|
||||
[ $? -ne 0 ] && warning "Config file '$stockconfd/$chart.conf' loaded with errors."
|
||||
else
|
||||
warning "configuration file '$confd/$PROGRAM_NAME/$chart.conf' not found. Using defaults."
|
||||
debug "not found module configuration: '$stockconfd/$chart.conf'"
|
||||
fi
|
||||
|
||||
# then load the user config (it overwrites the stock)
|
||||
if [ -f "$userconfd/$chart.conf" ]
|
||||
then
|
||||
debug "loading module configuration: '$userconfd/$chart.conf'"
|
||||
source "$userconfd/$chart.conf"
|
||||
[ $? -ne 0 ] && warning "Config file '$userconfd/$chart.conf' loaded with errors."
|
||||
else
|
||||
debug "not found module configuration: '$userconfd/$chart.conf'"
|
||||
|
||||
if [ -f "$olduserconfd/$chart.conf" ]
|
||||
then
|
||||
# support for very old netdata that had the charts.d module configs in /etc/netdata
|
||||
info "loading module configuration from obsolete location: '$olduserconfd/$chart.conf'"
|
||||
source "$olduserconfd/$chart.conf"
|
||||
[ $? -ne 0 ] && warning "Config file '$olduserconfd/$chart.conf' loaded with errors."
|
||||
fi
|
||||
fi
|
||||
|
||||
eval "dt=\$$chart$suffix_update_every"
|
|
@ -130,7 +130,8 @@ update_every="${1-1}"
|
|||
|
||||
# the netdata configuration directory
|
||||
# passed by netdata as an environment variable
|
||||
[ -z "${NETDATA_CONFIG_DIR}" ] && NETDATA_CONFIG_DIR="$(dirname "${0}")/../../../../etc/netdata"
|
||||
[ -z "${NETDATA_USER_CONFIG_DIR}" ] && NETDATA_USER_CONFIG_DIR="@configdir_POST@"
|
||||
[ -z "${NETDATA_STOCK_CONFIG_DIR}" ] && NETDATA_STOCK_CONFIG_DIR="@libconfigdir_POST@"
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# configuration options
|
||||
|
@ -153,23 +154,33 @@ ping_every="$((update_every * 1000 / 5))"
|
|||
fping_opts="-R -b 56 -i 1 -r 0 -t 5000"
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# load the configuration file
|
||||
# load the configuration files
|
||||
|
||||
if [ ! -f "${NETDATA_CONFIG_DIR}/${plugin}.conf" ]
|
||||
then
|
||||
fatal "configuration file '${NETDATA_CONFIG_DIR}/${plugin}.conf' not found - nothing to do."
|
||||
fi
|
||||
|
||||
source "${NETDATA_CONFIG_DIR}/${plugin}.conf"
|
||||
for CONFIG in "${NETDATA_STOCK_CONFIG_DIR}/${plugin}.conf" "${NETDATA_USER_CONFIG_DIR}/${plugin}.conf"
|
||||
do
|
||||
if [ -f "${CONFIG}" ]
|
||||
then
|
||||
info "Loading config file '${CONFIG}'..."
|
||||
source "${CONFIG}"
|
||||
[ $? -ne 0 ] && error "Failed to load config file '${CONFIG}'."
|
||||
else
|
||||
warning "Cannot find file '${CONFIG}'."
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -z "${hosts}" ]
|
||||
then
|
||||
fatal "no hosts configured in '${NETDATA_CONFIG_DIR}/${plugin}.conf' - nothing to do."
|
||||
fatal "no hosts configured - nothing to do."
|
||||
fi
|
||||
|
||||
if [ -z "${fping}" -o ! -x "${fping}" ]
|
||||
if [ -z "${fping}" ]
|
||||
then
|
||||
fatal "command '${fping}' is not found or is not executable - cannot proceed."
|
||||
fatal "fping command is not found. Please set its full path in '${NETDATA_USER_CONFIG_DIR}/${plugin}.conf'"
|
||||
fi
|
||||
|
||||
if [ ! -x "${fping}" ]
|
||||
then
|
||||
fatal "fping command '${fping}' is not executable - cannot proceed."
|
||||
fi
|
||||
|
||||
if [ ${ping_every} -lt 20 ]
|
||||
|
@ -186,4 +197,4 @@ info "starting fping: ${fping} ${options[*]}"
|
|||
exec "${fping}" "${options[@]}"
|
||||
|
||||
# if we cannot execute fping, stop
|
||||
fatal "command '${fping} ${options[@]}' failed to be executed."
|
||||
fatal "command '${fping} ${options[*]}' failed to be executed (returned code $?)."
|
|
@ -21,7 +21,8 @@
|
|||
// get NETDATA environment variables
|
||||
|
||||
var NETDATA_PLUGINS_DIR = process.env.NETDATA_PLUGINS_DIR || __dirname;
|
||||
var NETDATA_CONFIG_DIR = process.env.NETDATA_CONFIG_DIR || __dirname + '/../../../../etc/netdata';
|
||||
var NETDATA_USER_CONFIG_DIR = process.env.NETDATA_USER_CONFIG_DIR || '@configdir_POST@';
|
||||
var NETDATA_STOCK_CONFIG_DIR = process.env.NETDATA_STOCK_CONFIG_DIR || '@libconfigdir_POST@';
|
||||
var NETDATA_UPDATE_EVERY = process.env.NETDATA_UPDATE_EVERY || 1;
|
||||
var NODE_D_DIR = NETDATA_PLUGINS_DIR + '/../node.d';
|
||||
|
||||
|
@ -45,20 +46,42 @@ var netdata = require('netdata');
|
|||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// configuration
|
||||
|
||||
function pluginConfig(filename) {
|
||||
var f = path.basename(filename);
|
||||
function netdata_read_json_config_file(module_filename) {
|
||||
var f = path.basename(module_filename);
|
||||
|
||||
var ufilename, sfilename;
|
||||
|
||||
// node.d.plugin configuration
|
||||
var m = f.match('.plugin' + '$');
|
||||
if(m !== null)
|
||||
return netdata.options.paths.config + '/' + f.substring(0, m.index) + '.conf';
|
||||
if(m !== null) {
|
||||
ufilename = netdata.options.paths.config + '/' + f.substring(0, m.index) + '.conf';
|
||||
sfilename = netdata.options.paths.stock_config + '/' + f.substring(0, m.index) + '.conf';
|
||||
}
|
||||
|
||||
// node.d modules configuration
|
||||
m = f.match('.node.js' + '$');
|
||||
if(m !== null)
|
||||
return netdata.options.paths.config + '/node.d/' + f.substring(0, m.index) + '.conf';
|
||||
if(m !== null) {
|
||||
ufilename = netdata.options.paths.config + '/node.d/' + f.substring(0, m.index) + '.conf';
|
||||
sfilename = netdata.options.paths.stock_config + '/node.d/' + f.substring(0, m.index) + '.conf';
|
||||
}
|
||||
|
||||
return netdata.options.paths.config + '/node.d/' + f + '.conf';
|
||||
try {
|
||||
netdata.debug('loading module\'s ' + module_filename + ' user-config ' + ufilename);
|
||||
return JSON.parse(fs.readFileSync(ufilename, 'utf8'));
|
||||
}
|
||||
catch(e) {
|
||||
netdata.error('Cannot read user-configuration file ' + ufilename + ': ' + e.message + '.');
|
||||
dumpError(e);
|
||||
}
|
||||
|
||||
try {
|
||||
netdata.debug('loading module\'s ' + module_filename + ' stock-config ' + sfilename);
|
||||
return JSON.parse(fs.readFileSync(sfilename, 'utf8'));
|
||||
}
|
||||
catch(e) {
|
||||
netdata.error('Cannot read stock-configuration file ' + sfilename + ': ' + e.message + ', using internal defaults.');
|
||||
dumpError(e);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
// internal defaults
|
||||
|
@ -69,35 +92,31 @@ extend(true, netdata.options, {
|
|||
|
||||
paths: {
|
||||
plugins: NETDATA_PLUGINS_DIR,
|
||||
config: NETDATA_CONFIG_DIR,
|
||||
modules: [],
|
||||
config: NETDATA_USER_CONFIG_DIR,
|
||||
stock_config: NETDATA_STOCK_CONFIG_DIR,
|
||||
modules: []
|
||||
},
|
||||
|
||||
modules_enable_autodetect: true,
|
||||
modules_enable_all: true,
|
||||
modules: {},
|
||||
modules: {}
|
||||
});
|
||||
netdata.options.config_filename = pluginConfig(__filename);
|
||||
|
||||
// load configuration file
|
||||
try {
|
||||
netdata.options_loaded = JSON.parse(fs.readFileSync(netdata.options.config_filename, 'utf8'));
|
||||
extend(true, netdata.options, netdata.options_loaded);
|
||||
netdata.options_loaded = netdata_read_json_config_file(__filename);
|
||||
extend(true, netdata.options, netdata.options_loaded);
|
||||
|
||||
if(!netdata.options.paths.plugins)
|
||||
netdata.options.paths.plugins = NETDATA_PLUGINS_DIR;
|
||||
if(!netdata.options.paths.plugins)
|
||||
netdata.options.paths.plugins = NETDATA_PLUGINS_DIR;
|
||||
|
||||
if(!netdata.options.paths.config)
|
||||
netdata.options.paths.config = NETDATA_CONFIG_DIR;
|
||||
if(!netdata.options.paths.config)
|
||||
netdata.options.paths.config = NETDATA_USER_CONFIG_DIR;
|
||||
|
||||
// console.error('merged netdata object:');
|
||||
// console.error(util.inspect(netdata, {depth: 10}));
|
||||
}
|
||||
catch(e) {
|
||||
netdata.error('Cannot read configuration file ' + netdata.options.config_filename + ': ' + e.message + ', using internal defaults.');
|
||||
netdata.options_loaded = undefined;
|
||||
dumpError(e);
|
||||
}
|
||||
if(!netdata.options.paths.stock_config)
|
||||
netdata.options.paths.stock_config = NETDATA_STOCK_CONFIG_DIR;
|
||||
|
||||
// console.error('merged netdata object:');
|
||||
// console.error(util.inspect(netdata, {depth: 10}));
|
||||
|
||||
|
||||
// apply module paths to node.js process
|
||||
|
@ -206,9 +225,6 @@ function findModules() {
|
|||
netdata.options.modules[n].filename = NODE_D_DIR + '/' + files[len];
|
||||
netdata.options.modules[n].loaded = false;
|
||||
|
||||
if(typeof(netdata.options.modules[n].config_filename) !== 'string')
|
||||
netdata.options.modules[n].config_filename = pluginConfig(files[len]);
|
||||
|
||||
// load the module
|
||||
try {
|
||||
netdata.debug('loading module ' + netdata.options.modules[n].filename);
|
||||
|
@ -228,16 +244,9 @@ function findModules() {
|
|||
enable_autodetect: netdata.options.modules_enable_autodetect,
|
||||
update_every: netdata.options.update_every
|
||||
};
|
||||
try {
|
||||
netdata.debug('loading module\'s ' + netdata.options.modules[n].name + ' config ' + netdata.options.modules[n].config_filename);
|
||||
var c2 = JSON.parse(fs.readFileSync(netdata.options.modules[n].config_filename, 'utf8'));
|
||||
extend(true, c, c2);
|
||||
netdata.debug('loaded module\'s ' + netdata.options.modules[n].name + ' config ' + netdata.options.modules[n].config_filename);
|
||||
}
|
||||
catch(e) {
|
||||
netdata.error('Cannot load module\'s ' + netdata.options.modules[n].name + ' config from ' + netdata.options.modules[n].config_filename + ' exception: ' + e + ', using internal defaults.');
|
||||
dumpError(e);
|
||||
}
|
||||
|
||||
var c2 = netdata_read_json_config_file(files[len]);
|
||||
extend(true, c, c2);
|
||||
|
||||
// call module auto-detection / configuration
|
||||
try {
|
|
@ -21,10 +21,20 @@ GC_RUN = True
|
|||
GC_COLLECT_EVERY = 300
|
||||
|
||||
PY_VERSION = version_info[:2]
|
||||
PLUGIN_CONFIG_DIR = os.getenv('NETDATA_CONFIG_DIR', os.path.dirname(__file__) + '/../../../../etc/netdata') + '/'
|
||||
CHARTS_PY_DIR = os.path.abspath(os.getenv('NETDATA_PLUGINS_DIR', os.path.dirname(__file__)) + '/../python.d') + '/'
|
||||
CHARTS_PY_CONFIG_DIR = PLUGIN_CONFIG_DIR + 'python.d/'
|
||||
PYTHON_MODULES_DIR = CHARTS_PY_DIR + 'python_modules'
|
||||
|
||||
USER_CONFIG_DIR = os.getenv('NETDATA_USER_CONFIG_DIR', '@configdir_POST@')
|
||||
STOCK_CONFIG_DIR = os.getenv('NETDATA_STOCK_CONFIG_DIR', '@libconfigdir_POST@')
|
||||
|
||||
PLUGINS_USER_CONFIG_DIR = os.path.join(USER_CONFIG_DIR, 'python.d')
|
||||
PLUGINS_STOCK_CONFIG_DIR = os.path.join(STOCK_CONFIG_DIR, 'python.d')
|
||||
|
||||
|
||||
PLUGINS_DIR = os.path.abspath(os.getenv(
|
||||
'NETDATA_PLUGINS_DIR',
|
||||
os.path.dirname(__file__)) + '/../python.d')
|
||||
|
||||
|
||||
PYTHON_MODULES_DIR = os.path.join(PLUGINS_DIR, 'python_modules')
|
||||
|
||||
sys.path.append(PYTHON_MODULES_DIR)
|
||||
|
||||
|
@ -53,7 +63,7 @@ def module_ok(m):
|
|||
return m.endswith(MODULE_EXTENSION) and m[:-len(MODULE_EXTENSION)] not in OBSOLETE_MODULES
|
||||
|
||||
|
||||
ALL_MODULES = [m for m in sorted(os.listdir(CHARTS_PY_DIR)) if module_ok(m)]
|
||||
ALL_MODULES = [m for m in sorted(os.listdir(PLUGINS_DIR)) if module_ok(m)]
|
||||
|
||||
|
||||
def parse_cmd():
|
||||
|
@ -69,10 +79,9 @@ def multi_job_check(config):
|
|||
|
||||
|
||||
class RawModule:
|
||||
def __init__(self, name, path, conf_path, explicitly_enabled=True):
|
||||
def __init__(self, name, path, explicitly_enabled=True):
|
||||
self.name = name
|
||||
self.path = path
|
||||
self.conf_path = conf_path
|
||||
self.explicitly_enabled = explicitly_enabled
|
||||
|
||||
|
||||
|
@ -202,9 +211,20 @@ class Plugin(object):
|
|||
self.modules = OrderedDict()
|
||||
self.sleep_time = 1
|
||||
self.runs_counter = 0
|
||||
self.config, error = self.loader.load_config_from_file(PLUGIN_CONFIG_DIR + 'python.d.conf')
|
||||
|
||||
user_config = os.path.join(USER_CONFIG_DIR, 'python.d.conf')
|
||||
stock_config = os.path.join(STOCK_CONFIG_DIR, 'python.d.conf')
|
||||
|
||||
Logger.debug("loading '{0}'".format(user_config))
|
||||
self.config, error = self.loader.load_config_from_file(user_config)
|
||||
|
||||
if error:
|
||||
Logger.error('"python.d.conf" configuration file not found. Using defaults.')
|
||||
Logger.error("cannot load '{0}': {1}. Will try stock version.".format(user_config, error))
|
||||
Logger.debug("loading '{0}'".format(stock_config))
|
||||
self.config, error = self.loader.load_config_from_file(stock_config)
|
||||
if error:
|
||||
Logger.error("cannot load '{0}': {1}".format(stock_config, error))
|
||||
|
||||
self.do_gc = self.config.get("gc_run", GC_RUN)
|
||||
self.gc_interval = self.config.get("gc_interval", GC_COLLECT_EVERY)
|
||||
|
||||
|
@ -233,8 +253,7 @@ class Plugin(object):
|
|||
def enabled_modules(self):
|
||||
for mod in MODULES_TO_RUN:
|
||||
mod_name = mod[:-len(MODULE_EXTENSION)]
|
||||
mod_path = CHARTS_PY_DIR + mod
|
||||
conf_path = ''.join([CHARTS_PY_CONFIG_DIR, mod_name, '.conf'])
|
||||
mod_path = os.path.join(PLUGINS_DIR, mod)
|
||||
if any(
|
||||
[
|
||||
self.config.get('default_run', True) and self.config.get(mod_name, True),
|
||||
|
@ -244,7 +263,6 @@ class Plugin(object):
|
|||
yield RawModule(
|
||||
name=mod_name,
|
||||
path=mod_path,
|
||||
conf_path=conf_path,
|
||||
explicitly_enabled=self.config.get(mod_name),
|
||||
)
|
||||
|
||||
|
@ -261,12 +279,18 @@ class Plugin(object):
|
|||
continue
|
||||
|
||||
# Load module config from file ------------------------------------------------------
|
||||
loaded_config, error = self.loader.load_config_from_file(mod.conf_path)
|
||||
log = Logger.error if error else Logger.debug
|
||||
log("module load config: '{module_name}' => [{status}]".format(status='FAILED' if error else 'OK',
|
||||
module_name=mod.name))
|
||||
user_config = os.path.join(PLUGINS_USER_CONFIG_DIR, mod.name + '.conf')
|
||||
stock_config = os.path.join(PLUGINS_STOCK_CONFIG_DIR, mod.name + '.conf')
|
||||
|
||||
Logger.debug("loading '{0}'".format(user_config))
|
||||
loaded_config, error = self.loader.load_config_from_file(user_config)
|
||||
if error:
|
||||
Logger.error('load config error : {0}'.format(error))
|
||||
Logger.error("cannot load '{0}' : {1}. Will try stock version.".format(user_config, error))
|
||||
Logger.debug("loading '{0}'".format(stock_config))
|
||||
loaded_config, error = self.loader.load_config_from_file(stock_config)
|
||||
|
||||
if error:
|
||||
Logger.error("cannot load '{0}': {1}".format(stock_config, error))
|
||||
|
||||
# Skip disabled modules
|
||||
if getattr(loaded_module, 'disabled_by_default', False) and not mod.explicitly_enabled:
|
|
@ -107,10 +107,10 @@ fi
|
|||
# -----------------------------------------------------------------------------
|
||||
|
||||
[ -z "${NETDATA_PLUGINS_DIR}" ] && NETDATA_PLUGINS_DIR="$(dirname "${0}")"
|
||||
[ -z "${NETDATA_CONFIG_DIR}" ] && NETDATA_CONFIG_DIR="$(dirname "${0}")/../../../../etc/netdata"
|
||||
[ -z "${NETDATA_USER_CONFIG_DIR}" ] && NETDATA_USER_CONFIG_DIR="@configdir_POST@"
|
||||
[ -z "${NETDATA_STOCK_CONFIG_DIR}" ] && NETDATA_STOCK_CONFIG_DIR="@libconfigdir_POST@"
|
||||
|
||||
plugins_dir="${NETDATA_PLUGINS_DIR}"
|
||||
config_dir="${NETDATA_CONFIG_DIR}"
|
||||
tc="$(which tc 2>/dev/null || command -v tc 2>/dev/null)"
|
||||
|
||||
|
||||
|
@ -139,10 +139,17 @@ update_every=$((t))
|
|||
# -----------------------------------------------------------------------------
|
||||
# allow the user to override our defaults
|
||||
|
||||
if [ -f "${config_dir}/tc-qos-helper.conf" ]
|
||||
then
|
||||
source "${config_dir}/tc-qos-helper.conf"
|
||||
fi
|
||||
for CONFIG in "${NETDATA_STOCK_CONFIG_DIR}/tc-qos-helper.conf" "${NETDATA_USER_CONFIG_DIR}/tc-qos-helper.conf"
|
||||
do
|
||||
if [ -f "${CONFIG}" ]
|
||||
then
|
||||
info "Loading config file '${CONFIG}'..."
|
||||
source "${CONFIG}"
|
||||
[ $? -ne 0 ] && error "Failed to load config file '${CONFIG}'."
|
||||
else
|
||||
warning "Cannot find file '${CONFIG}'."
|
||||
fi
|
||||
done
|
||||
|
||||
case "${tc_show}" in
|
||||
qdisc|class)
|
|
@ -8,6 +8,7 @@ AM_CPPFLAGS = \
|
|||
-DVARLIB_DIR="\"$(varlibdir)\"" \
|
||||
-DCACHE_DIR="\"$(cachedir)\"" \
|
||||
-DCONFIG_DIR="\"$(configdir)\"" \
|
||||
-DLIBCONFIG_DIR="\"$(libconfigdir)\"" \
|
||||
-DLOG_DIR="\"$(logdir)\"" \
|
||||
-DPLUGINS_DIR="\"$(pluginsdir)\"" \
|
||||
-DRUN_DIR="\"$(localstatedir)/run/netdata\"" \
|
||||
|
|
|
@ -100,8 +100,9 @@ static int
|
|||
include_exited_childs = 1;
|
||||
|
||||
|
||||
// will be changed to getenv(NETDATA_CONFIG_DIR) if it exists
|
||||
static char *config_dir = CONFIG_DIR;
|
||||
// will be changed to getenv(NETDATA_USER_CONFIG_DIR) if it exists
|
||||
static char *user_config_dir = CONFIG_DIR;
|
||||
static char *stock_config_dir = LIBCONFIG_DIR;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// internal flags
|
||||
|
@ -631,11 +632,11 @@ static struct target *get_apps_groups_target(const char *id, struct target *targ
|
|||
}
|
||||
|
||||
// read the apps_groups.conf file
|
||||
static int read_apps_groups_conf(const char *file)
|
||||
static int read_apps_groups_conf(const char *path, const char *file)
|
||||
{
|
||||
char filename[FILENAME_MAX + 1];
|
||||
|
||||
snprintfz(filename, FILENAME_MAX, "%s/apps_%s.conf", config_dir, file);
|
||||
snprintfz(filename, FILENAME_MAX, "%s/apps_%s.conf", path, file);
|
||||
|
||||
debug_log("process groups file: '%s'", filename);
|
||||
|
||||
|
@ -3569,10 +3570,18 @@ static void parse_args(int argc, char **argv)
|
|||
|
||||
if(freq > 0) update_every = freq;
|
||||
|
||||
if(read_apps_groups_conf("groups")) {
|
||||
error("Cannot read process groups '%s/apps_groups.conf'. There are no internal defaults. Failing.", config_dir);
|
||||
exit(1);
|
||||
if(read_apps_groups_conf(user_config_dir, "groups")) {
|
||||
error("Cannot read process groups configuration file '%s/apps_groups.conf'. Will try '%s/apps_groups.conf'", user_config_dir, stock_config_dir);
|
||||
|
||||
if(read_apps_groups_conf(stock_config_dir, "groups")) {
|
||||
error("Cannot read process groups '%s/apps_groups.conf'. There are no internal defaults. Failing.", stock_config_dir);
|
||||
exit(1);
|
||||
}
|
||||
else
|
||||
info("Loaded config file '%s/apps_groups.conf'", stock_config_dir);
|
||||
}
|
||||
else
|
||||
info("Loaded config file '%s/apps_groups.conf'", user_config_dir);
|
||||
}
|
||||
|
||||
static int am_i_running_as_root() {
|
||||
|
@ -3658,12 +3667,19 @@ int main(int argc, char **argv) {
|
|||
netdata_configured_host_prefix = getenv("NETDATA_HOST_PREFIX");
|
||||
if(verify_netdata_host_prefix() == -1) exit(1);
|
||||
|
||||
config_dir = getenv("NETDATA_CONFIG_DIR");
|
||||
if(config_dir == NULL) {
|
||||
user_config_dir = getenv("NETDATA_USER_CONFIG_DIR");
|
||||
if(user_config_dir == NULL) {
|
||||
// info("NETDATA_CONFIG_DIR is not passed from netdata");
|
||||
config_dir = CONFIG_DIR;
|
||||
user_config_dir = CONFIG_DIR;
|
||||
}
|
||||
// else info("Found NETDATA_CONFIG_DIR='%s'", config_dir);
|
||||
// else info("Found NETDATA_USER_CONFIG_DIR='%s'", user_config_dir);
|
||||
|
||||
stock_config_dir = getenv("NETDATA_STOCK_CONFIG_DIR");
|
||||
if(stock_config_dir == NULL) {
|
||||
// info("NETDATA_CONFIG_DIR is not passed from netdata");
|
||||
stock_config_dir = LIBCONFIG_DIR;
|
||||
}
|
||||
// else info("Found NETDATA_USER_CONFIG_DIR='%s'", user_config_dir);
|
||||
|
||||
#ifdef NETDATA_INTERNAL_CHECKS
|
||||
if(debug_flags != 0) {
|
||||
|
|
209
src/common.c
209
src/common.c
|
@ -10,16 +10,17 @@
|
|||
# define MADV_DONTFORK INHERIT_NONE
|
||||
#endif /* __FreeBSD__ || __APPLE__*/
|
||||
|
||||
char *netdata_configured_hostname = NULL;
|
||||
char *netdata_configured_config_dir = NULL;
|
||||
char *netdata_configured_log_dir = NULL;
|
||||
char *netdata_configured_plugins_dir = NULL;
|
||||
char *netdata_configured_web_dir = NULL;
|
||||
char *netdata_configured_cache_dir = NULL;
|
||||
char *netdata_configured_varlib_dir = NULL;
|
||||
char *netdata_configured_home_dir = NULL;
|
||||
char *netdata_configured_host_prefix = NULL;
|
||||
char *netdata_configured_timezone = NULL;
|
||||
char *netdata_configured_hostname = NULL;
|
||||
char *netdata_configured_user_config_dir = CONFIG_DIR;
|
||||
char *netdata_configured_stock_config_dir = LIBCONFIG_DIR;
|
||||
char *netdata_configured_log_dir = LOG_DIR;
|
||||
char *netdata_configured_plugins_dir = NULL;
|
||||
char *netdata_configured_web_dir = WEB_DIR;
|
||||
char *netdata_configured_cache_dir = CACHE_DIR;
|
||||
char *netdata_configured_varlib_dir = VARLIB_DIR;
|
||||
char *netdata_configured_home_dir = CACHE_DIR;
|
||||
char *netdata_configured_host_prefix = NULL;
|
||||
char *netdata_configured_timezone = NULL;
|
||||
|
||||
struct rlimit rlimit_nofile = { .rlim_cur = 1024, .rlim_max = 1024 };
|
||||
int enable_ksm = 1;
|
||||
|
@ -1431,3 +1432,191 @@ failed:
|
|||
netdata_configured_host_prefix = "";
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *strdupz_path_subpath(const char *path, const char *subpath) {
|
||||
if(unlikely(!path || !*path)) path = ".";
|
||||
if(unlikely(!subpath)) subpath = "";
|
||||
|
||||
// skip trailing slashes in path
|
||||
size_t len = strlen(path);
|
||||
while(len > 0 && path[len - 1] == '/') len--;
|
||||
|
||||
// skip leading slashes in subpath
|
||||
while(subpath && subpath[0] == '/') subpath++;
|
||||
|
||||
// if the last character in path is / and (there is a subpath or path is now empty)
|
||||
// keep the trailing slash in path and remove the additional slash
|
||||
char *slash = "/";
|
||||
if(path[len] == '/' && (*subpath || len == 0)) {
|
||||
slash = "";
|
||||
len++;
|
||||
}
|
||||
else if(!*subpath) {
|
||||
// there is no subpath
|
||||
// no need for trailing slash
|
||||
slash = "";
|
||||
}
|
||||
|
||||
char buffer[FILENAME_MAX + 1];
|
||||
snprintfz(buffer, FILENAME_MAX, "%.*s%s%s", (int)len, path, slash, (subpath)?subpath:"");
|
||||
return strdupz(buffer);
|
||||
}
|
||||
|
||||
int path_is_dir(const char *path, const char *subpath) {
|
||||
char *s = strdupz_path_subpath(path, subpath);
|
||||
|
||||
size_t max_links = 100;
|
||||
|
||||
int is_dir = 0;
|
||||
struct stat statbuf;
|
||||
while(max_links-- && stat(s, &statbuf) == 0) {
|
||||
if((statbuf.st_mode & S_IFMT) == S_IFDIR) {
|
||||
is_dir = 1;
|
||||
break;
|
||||
}
|
||||
else if((statbuf.st_mode & S_IFMT) == S_IFLNK) {
|
||||
char buffer[FILENAME_MAX + 1];
|
||||
ssize_t l = readlink(s, buffer, FILENAME_MAX);
|
||||
if(l > 0) {
|
||||
buffer[l] = '\0';
|
||||
freez(s);
|
||||
s = strdupz(buffer);
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
is_dir = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
is_dir = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
freez(s);
|
||||
return is_dir;
|
||||
}
|
||||
|
||||
int path_is_file(const char *path, const char *subpath) {
|
||||
char *s = strdupz_path_subpath(path, subpath);
|
||||
|
||||
size_t max_links = 100;
|
||||
|
||||
int is_file = 0;
|
||||
struct stat statbuf;
|
||||
while(max_links-- && stat(s, &statbuf) == 0) {
|
||||
if((statbuf.st_mode & S_IFMT) == S_IFREG) {
|
||||
is_file = 1;
|
||||
break;
|
||||
}
|
||||
else if((statbuf.st_mode & S_IFMT) == S_IFLNK) {
|
||||
char buffer[FILENAME_MAX + 1];
|
||||
ssize_t l = readlink(s, buffer, FILENAME_MAX);
|
||||
if(l > 0) {
|
||||
buffer[l] = '\0';
|
||||
freez(s);
|
||||
s = strdupz(buffer);
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
is_file = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
is_file = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
freez(s);
|
||||
return is_file;
|
||||
}
|
||||
|
||||
void recursive_config_double_dir_load(const char *user_path, const char *stock_path, const char *subpath, int (*callback)(const char *filename, void *data), void *data) {
|
||||
char *udir = strdupz_path_subpath(user_path, subpath);
|
||||
char *sdir = strdupz_path_subpath(stock_path, subpath);
|
||||
|
||||
debug(D_HEALTH, "Configuration traversing user-config directory '%s', stock config directory '%s'", udir, sdir);
|
||||
|
||||
DIR *dir = opendir(udir);
|
||||
if (!dir) {
|
||||
error("Configuration cannot open user-config directory '%s'.", udir);
|
||||
}
|
||||
else {
|
||||
struct dirent *de = NULL;
|
||||
while((de = readdir(dir))) {
|
||||
if(de->d_type == DT_DIR
|
||||
&& ( (de->d_name[0] == '.' && de->d_name[1] == '\0')
|
||||
|| (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')
|
||||
)) {
|
||||
debug(D_HEALTH, "Configuration ignoring user-config directory '%s/%s'", udir, de->d_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(path_is_dir(udir, de->d_name)) {
|
||||
recursive_config_double_dir_load(udir, sdir, de->d_name, callback, data);
|
||||
continue;
|
||||
}
|
||||
|
||||
size_t len = strlen(de->d_name);
|
||||
if(path_is_file(udir, de->d_name) &&
|
||||
len > 5 && !strcmp(&de->d_name[len - 5], ".conf")) {
|
||||
char *filename = strdupz_path_subpath(udir, de->d_name);
|
||||
callback(filename, data);
|
||||
freez(filename);
|
||||
}
|
||||
|
||||
else
|
||||
debug(D_HEALTH, "Health ignoring user config file '%s/%s'", udir, de->d_name);
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
debug(D_HEALTH, "Health configuration traversing stock config directory '%s', user config directory '%s'", sdir, udir);
|
||||
|
||||
dir = opendir(sdir);
|
||||
if (!dir) {
|
||||
error("Health configuration cannot open stock config directory '%s'.", sdir);
|
||||
}
|
||||
else {
|
||||
struct dirent *de = NULL;
|
||||
while((de = readdir(dir))) {
|
||||
if(de->d_type == DT_DIR
|
||||
&& ( (de->d_name[0] == '.' && de->d_name[1] == '\0')
|
||||
|| (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')
|
||||
)) {
|
||||
debug(D_HEALTH, "Health ignoring stock config directory '%s/%s'", sdir, de->d_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(path_is_dir(sdir, de->d_name)) {
|
||||
// we recurse in stock subdirectory, only when there is no corresponding
|
||||
// user subdirectory - to avoid reading the files twice
|
||||
|
||||
if(!path_is_dir(udir, de->d_name))
|
||||
recursive_config_double_dir_load(udir, sdir, de->d_name, callback, data);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
size_t len = strlen(de->d_name);
|
||||
if(path_is_file(sdir, de->d_name) && !path_is_file(udir, de->d_name) &&
|
||||
len > 5 && !strcmp(&de->d_name[len - 5], ".conf")) {
|
||||
char *filename = strdupz_path_subpath(sdir, de->d_name);
|
||||
callback(filename, data);
|
||||
freez(filename);
|
||||
}
|
||||
|
||||
else
|
||||
debug(D_HEALTH, "Health ignoring stock config file '%s/%s'", sdir, de->d_name);
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
freez(udir);
|
||||
freez(sdir);
|
||||
}
|
||||
|
|
10
src/common.h
10
src/common.h
|
@ -42,6 +42,7 @@
|
|||
#include <arpa/inet.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <libgen.h>
|
||||
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
|
@ -349,7 +350,8 @@ typedef enum rrdcalc_status {
|
|||
#include "web_api_v1.h"
|
||||
|
||||
extern char *netdata_configured_hostname;
|
||||
extern char *netdata_configured_config_dir;
|
||||
extern char *netdata_configured_user_config_dir;
|
||||
extern char *netdata_configured_stock_config_dir;
|
||||
extern char *netdata_configured_log_dir;
|
||||
extern char *netdata_configured_plugins_dir_base;
|
||||
extern char *netdata_configured_plugins_dir;
|
||||
|
@ -426,6 +428,12 @@ extern const char *os_type;
|
|||
|
||||
extern const char *program_version;
|
||||
|
||||
extern char *strdupz_path_subpath(const char *path, const char *subpath);
|
||||
extern int path_is_dir(const char *path, const char *subpath);
|
||||
extern int path_is_file(const char *path, const char *subpath);
|
||||
extern void recursive_config_double_dir_load(const char *user_path, const char *stock_path, const char *subpath
|
||||
, int (*callback)(const char *filename, void *data), void *data);
|
||||
|
||||
/* fix for alpine linux */
|
||||
#ifndef RUSAGE_THREAD
|
||||
#ifdef RUSAGE_CHILDREN
|
||||
|
|
15
src/health.c
15
src/health.c
|
@ -8,12 +8,18 @@ unsigned int default_health_enabled = 1;
|
|||
// ----------------------------------------------------------------------------
|
||||
// health initialization
|
||||
|
||||
inline char *health_config_dir(void) {
|
||||
inline char *health_user_config_dir(void) {
|
||||
char buffer[FILENAME_MAX + 1];
|
||||
snprintfz(buffer, FILENAME_MAX, "%s/health.d", netdata_configured_config_dir);
|
||||
snprintfz(buffer, FILENAME_MAX, "%s/health.d", netdata_configured_user_config_dir);
|
||||
return config_get(CONFIG_SECTION_HEALTH, "health configuration directory", buffer);
|
||||
}
|
||||
|
||||
inline char *health_stock_config_dir(void) {
|
||||
char buffer[FILENAME_MAX + 1];
|
||||
snprintfz(buffer, FILENAME_MAX, "%s/health.d", netdata_configured_stock_config_dir);
|
||||
return config_get(CONFIG_SECTION_HEALTH, "stock health configuration directory", buffer);
|
||||
}
|
||||
|
||||
void health_init(void) {
|
||||
debug(D_HEALTH, "Health configuration initializing");
|
||||
|
||||
|
@ -30,7 +36,8 @@ void health_reload_host(RRDHOST *host) {
|
|||
if(unlikely(!host->health_enabled))
|
||||
return;
|
||||
|
||||
char *path = health_config_dir();
|
||||
char *user_path = health_user_config_dir();
|
||||
char *stock_path = health_stock_config_dir();
|
||||
|
||||
// free all running alarms
|
||||
rrdhost_wrlock(host);
|
||||
|
@ -61,7 +68,7 @@ void health_reload_host(RRDHOST *host) {
|
|||
|
||||
// load the new alarms
|
||||
rrdhost_wrlock(host);
|
||||
health_readdir(host, path);
|
||||
health_readdir(host, user_path, stock_path, NULL);
|
||||
|
||||
// link the loaded alarms to their charts
|
||||
rrdset_foreach_write(st, host) {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#ifndef NETDATA_HEALTH_H
|
||||
#define NETDATA_HEALTH_H 1
|
||||
|
||||
|
@ -415,8 +417,9 @@ extern void health_alarm_log(
|
|||
uint32_t flags
|
||||
);
|
||||
|
||||
extern void health_readdir(RRDHOST *host, const char *path);
|
||||
extern char *health_config_dir(void);
|
||||
extern void health_readdir(RRDHOST *host, const char *user_path, const char *stock_path, const char *subpath);
|
||||
extern char *health_user_config_dir(void);
|
||||
extern char *health_stock_config_dir(void);
|
||||
extern void health_reload_host(RRDHOST *host);
|
||||
extern void health_alarm_log_free(RRDHOST *host);
|
||||
|
||||
|
|
|
@ -178,7 +178,7 @@ static inline int health_parse_duration(char *string, int *result) {
|
|||
}
|
||||
|
||||
static inline int health_parse_delay(
|
||||
size_t line, const char *path, const char *file, char *string,
|
||||
size_t line, const char *filename, char *string,
|
||||
int *delay_up_duration,
|
||||
int *delay_down_duration,
|
||||
int *delay_max_duration,
|
||||
|
@ -204,36 +204,36 @@ static inline int health_parse_delay(
|
|||
|
||||
if(!strcasecmp(key, "up")) {
|
||||
if (!health_parse_duration(value, delay_up_duration)) {
|
||||
error("Health configuration at line %zu of file '%s/%s': invalid value '%s' for '%s' keyword",
|
||||
line, path, file, value, key);
|
||||
error("Health configuration at line %zu of file '%s': invalid value '%s' for '%s' keyword",
|
||||
line, filename, value, key);
|
||||
}
|
||||
else given_up = 1;
|
||||
}
|
||||
else if(!strcasecmp(key, "down")) {
|
||||
if (!health_parse_duration(value, delay_down_duration)) {
|
||||
error("Health configuration at line %zu of file '%s/%s': invalid value '%s' for '%s' keyword",
|
||||
line, path, file, value, key);
|
||||
error("Health configuration at line %zu of file '%s': invalid value '%s' for '%s' keyword",
|
||||
line, filename, value, key);
|
||||
}
|
||||
else given_down = 1;
|
||||
}
|
||||
else if(!strcasecmp(key, "multiplier")) {
|
||||
*delay_multiplier = strtof(value, NULL);
|
||||
if(isnan(*delay_multiplier) || isinf(*delay_multiplier) || islessequal(*delay_multiplier, 0)) {
|
||||
error("Health configuration at line %zu of file '%s/%s': invalid value '%s' for '%s' keyword",
|
||||
line, path, file, value, key);
|
||||
error("Health configuration at line %zu of file '%s': invalid value '%s' for '%s' keyword",
|
||||
line, filename, value, key);
|
||||
}
|
||||
else given_multiplier = 1;
|
||||
}
|
||||
else if(!strcasecmp(key, "max")) {
|
||||
if (!health_parse_duration(value, delay_max_duration)) {
|
||||
error("Health configuration at line %zu of file '%s/%s': invalid value '%s' for '%s' keyword",
|
||||
line, path, file, value, key);
|
||||
error("Health configuration at line %zu of file '%s': invalid value '%s' for '%s' keyword",
|
||||
line, filename, value, key);
|
||||
}
|
||||
else given_max = 1;
|
||||
}
|
||||
else {
|
||||
error("Health configuration at line %zu of file '%s/%s': unknown keyword '%s'",
|
||||
line, path, file, key);
|
||||
error("Health configuration at line %zu of file '%s': unknown keyword '%s'",
|
||||
line, filename, key);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -287,11 +287,11 @@ static inline uint32_t health_parse_options(const char *s) {
|
|||
}
|
||||
|
||||
static inline int health_parse_db_lookup(
|
||||
size_t line, const char *path, const char *file, char *string,
|
||||
size_t line, const char *filename, char *string,
|
||||
int *group_method, int *after, int *before, int *every,
|
||||
uint32_t *options, char **dimensions
|
||||
) {
|
||||
debug(D_HEALTH, "Health configuration parsing database lookup %zu@%s/%s: %s", line, path, file, string);
|
||||
debug(D_HEALTH, "Health configuration parsing database lookup %zu@%s: %s", line, filename, string);
|
||||
|
||||
if(*dimensions) freez(*dimensions);
|
||||
*dimensions = NULL;
|
||||
|
@ -307,14 +307,14 @@ static inline int health_parse_db_lookup(
|
|||
while(*s && !isspace(*s)) s++;
|
||||
while(*s && isspace(*s)) *s++ = '\0';
|
||||
if(!*s) {
|
||||
error("Health configuration invalid chart calculation at line %zu of file '%s/%s': expected group method followed by the 'after' time, but got '%s'",
|
||||
line, path, file, key);
|
||||
error("Health configuration invalid chart calculation at line %zu of file '%s': expected group method followed by the 'after' time, but got '%s'",
|
||||
line, filename, key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if((*group_method = web_client_api_request_v1_data_group(key, -1)) == -1) {
|
||||
error("Health configuration at line %zu of file '%s/%s': invalid group method '%s'",
|
||||
line, path, file, key);
|
||||
error("Health configuration at line %zu of file '%s': invalid group method '%s'",
|
||||
line, filename, key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -324,8 +324,8 @@ static inline int health_parse_db_lookup(
|
|||
while(*s && isspace(*s)) *s++ = '\0';
|
||||
|
||||
if(!health_parse_duration(key, after)) {
|
||||
error("Health configuration at line %zu of file '%s/%s': invalid duration '%s' after group method",
|
||||
line, path, file, key);
|
||||
error("Health configuration at line %zu of file '%s': invalid duration '%s' after group method",
|
||||
line, filename, key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -345,8 +345,8 @@ static inline int health_parse_db_lookup(
|
|||
while(*s && isspace(*s)) *s++ = '\0';
|
||||
|
||||
if (!health_parse_duration(value, before)) {
|
||||
error("Health configuration at line %zu of file '%s/%s': invalid duration '%s' for '%s' keyword",
|
||||
line, path, file, value, key);
|
||||
error("Health configuration at line %zu of file '%s': invalid duration '%s' for '%s' keyword",
|
||||
line, filename, value, key);
|
||||
}
|
||||
}
|
||||
else if(!strcasecmp(key, HEALTH_EVERY_KEY)) {
|
||||
|
@ -355,8 +355,8 @@ static inline int health_parse_db_lookup(
|
|||
while(*s && isspace(*s)) *s++ = '\0';
|
||||
|
||||
if (!health_parse_duration(value, every)) {
|
||||
error("Health configuration at line %zu of file '%s/%s': invalid duration '%s' for '%s' keyword",
|
||||
line, path, file, value, key);
|
||||
error("Health configuration at line %zu of file '%s': invalid duration '%s' for '%s' keyword",
|
||||
line, filename, value, key);
|
||||
}
|
||||
}
|
||||
else if(!strcasecmp(key, "absolute") || !strcasecmp(key, "abs") || !strcasecmp(key, "absolute_sum")) {
|
||||
|
@ -386,17 +386,17 @@ static inline int health_parse_db_lookup(
|
|||
break;
|
||||
}
|
||||
else {
|
||||
error("Health configuration at line %zu of file '%s/%s': unknown keyword '%s'",
|
||||
line, path, file, key);
|
||||
error("Health configuration at line %zu of file '%s': unknown keyword '%s'",
|
||||
line, filename, key);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline char *health_source_file(size_t line, const char *path, const char *filename) {
|
||||
static inline char *health_source_file(size_t line, const char *file) {
|
||||
char buffer[FILENAME_MAX + 1];
|
||||
snprintfz(buffer, FILENAME_MAX, "%zu@%s/%s", line, path, filename);
|
||||
snprintfz(buffer, FILENAME_MAX, "%zu@%s", line, file);
|
||||
return strdupz(buffer);
|
||||
}
|
||||
|
||||
|
@ -407,8 +407,10 @@ static inline void strip_quotes(char *s) {
|
|||
}
|
||||
}
|
||||
|
||||
int health_readfile(RRDHOST *host, const char *path, const char *filename) {
|
||||
debug(D_HEALTH, "Health configuration reading file '%s/%s'", path, filename);
|
||||
static int health_readfile(const char *filename, void *data) {
|
||||
RRDHOST *host = (RRDHOST *)data;
|
||||
|
||||
debug(D_HEALTH, "Health configuration reading file '%s'", filename);
|
||||
|
||||
static uint32_t
|
||||
hash_alarm = 0,
|
||||
|
@ -455,10 +457,9 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) {
|
|||
hash_options = simple_uhash(HEALTH_OPTIONS_KEY);
|
||||
}
|
||||
|
||||
snprintfz(buffer, HEALTH_CONF_MAX_LINE, "%s/%s", path, filename);
|
||||
FILE *fp = fopen(buffer, "r");
|
||||
FILE *fp = fopen(filename, "r");
|
||||
if(!fp) {
|
||||
error("Health configuration cannot read file '%s'.", buffer);
|
||||
error("Health configuration cannot read file '%s'.", filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -481,7 +482,7 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) {
|
|||
if(append < HEALTH_CONF_MAX_LINE)
|
||||
continue;
|
||||
else {
|
||||
error("Health configuration has too long muli-line at line %zu of file '%s/%s'.", line, path, filename);
|
||||
error("Health configuration has too long muli-line at line %zu of file '%s'.", line, filename);
|
||||
}
|
||||
}
|
||||
append = 0;
|
||||
|
@ -489,7 +490,7 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) {
|
|||
char *key = s;
|
||||
while(*s && *s != ':') s++;
|
||||
if(!*s) {
|
||||
error("Health configuration has invalid line %zu of file '%s/%s'. It does not contain a ':'. Ignoring it.", line, path, filename);
|
||||
error("Health configuration has invalid line %zu of file '%s'. It does not contain a ':'. Ignoring it.", line, filename);
|
||||
continue;
|
||||
}
|
||||
*s = '\0';
|
||||
|
@ -500,12 +501,12 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) {
|
|||
value = trim_all(value);
|
||||
|
||||
if(!key) {
|
||||
error("Health configuration has invalid line %zu of file '%s/%s'. Keyword is empty. Ignoring it.", line, path, filename);
|
||||
error("Health configuration has invalid line %zu of file '%s'. Keyword is empty. Ignoring it.", line, filename);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!value) {
|
||||
error("Health configuration has invalid line %zu of file '%s/%s'. value is empty. Ignoring it.", line, path, filename);
|
||||
error("Health configuration has invalid line %zu of file '%s'. value is empty. Ignoring it.", line, filename);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -526,7 +527,7 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) {
|
|||
rc->next_event_id = 1;
|
||||
rc->name = strdupz(value);
|
||||
rc->hash = simple_hash(rc->name);
|
||||
rc->source = health_source_file(line, path, filename);
|
||||
rc->source = health_source_file(line, filename);
|
||||
rc->green = NAN;
|
||||
rc->red = NAN;
|
||||
rc->value = NAN;
|
||||
|
@ -552,7 +553,7 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) {
|
|||
rt = callocz(1, sizeof(RRDCALCTEMPLATE));
|
||||
rt->name = strdupz(value);
|
||||
rt->hash_name = simple_hash(rt->name);
|
||||
rt->source = health_source_file(line, path, filename);
|
||||
rt->source = health_source_file(line, filename);
|
||||
rt->green = NAN;
|
||||
rt->red = NAN;
|
||||
rt->delay_multiplier = 1.0;
|
||||
|
@ -568,10 +569,10 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) {
|
|||
|
||||
if(!simple_pattern_matches(os_pattern, host->os)) {
|
||||
if(rc)
|
||||
debug(D_HEALTH, "HEALTH on '%s' ignoring alarm '%s' defined at %zu@%s/%s: host O/S does not match '%s'", host->hostname, rc->name, line, path, filename, os_match);
|
||||
debug(D_HEALTH, "HEALTH on '%s' ignoring alarm '%s' defined at %zu@%s: host O/S does not match '%s'", host->hostname, rc->name, line, filename, os_match);
|
||||
|
||||
if(rt)
|
||||
debug(D_HEALTH, "HEALTH on '%s' ignoring template '%s' defined at %zu@%s/%s: host O/S does not match '%s'", host->hostname, rt->name, line, path, filename, os_match);
|
||||
debug(D_HEALTH, "HEALTH on '%s' ignoring template '%s' defined at %zu@%s: host O/S does not match '%s'", host->hostname, rt->name, line, filename, os_match);
|
||||
|
||||
ignore_this = 1;
|
||||
}
|
||||
|
@ -584,10 +585,10 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) {
|
|||
|
||||
if(!simple_pattern_matches(host_pattern, host->hostname)) {
|
||||
if(rc)
|
||||
debug(D_HEALTH, "HEALTH on '%s' ignoring alarm '%s' defined at %zu@%s/%s: hostname does not match '%s'", host->hostname, rc->name, line, path, filename, host_match);
|
||||
debug(D_HEALTH, "HEALTH on '%s' ignoring alarm '%s' defined at %zu@%s: hostname does not match '%s'", host->hostname, rc->name, line, filename, host_match);
|
||||
|
||||
if(rt)
|
||||
debug(D_HEALTH, "HEALTH on '%s' ignoring template '%s' defined at %zu@%s/%s: hostname does not match '%s'", host->hostname, rt->name, line, path, filename, host_match);
|
||||
debug(D_HEALTH, "HEALTH on '%s' ignoring template '%s' defined at %zu@%s: hostname does not match '%s'", host->hostname, rt->name, line, filename, host_match);
|
||||
|
||||
ignore_this = 1;
|
||||
}
|
||||
|
@ -598,8 +599,8 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) {
|
|||
if(hash == hash_on && !strcasecmp(key, HEALTH_ON_KEY)) {
|
||||
if(rc->chart) {
|
||||
if(strcmp(rc->chart, value) != 0)
|
||||
error("Health configuration at line %zu of file '%s/%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').",
|
||||
line, path, filename, rc->name, key, rc->chart, value, value);
|
||||
error("Health configuration at line %zu of file '%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').",
|
||||
line, filename, rc->name, key, rc->chart, value, value);
|
||||
|
||||
freez(rc->chart);
|
||||
}
|
||||
|
@ -607,29 +608,29 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) {
|
|||
rc->hash_chart = simple_hash(rc->chart);
|
||||
}
|
||||
else if(hash == hash_lookup && !strcasecmp(key, HEALTH_LOOKUP_KEY)) {
|
||||
health_parse_db_lookup(line, path, filename, value, &rc->group, &rc->after, &rc->before,
|
||||
health_parse_db_lookup(line, filename, value, &rc->group, &rc->after, &rc->before,
|
||||
&rc->update_every,
|
||||
&rc->options, &rc->dimensions);
|
||||
}
|
||||
else if(hash == hash_every && !strcasecmp(key, HEALTH_EVERY_KEY)) {
|
||||
if(!health_parse_duration(value, &rc->update_every))
|
||||
error("Health configuration at line %zu of file '%s/%s' for alarm '%s' at key '%s' cannot parse duration: '%s'.",
|
||||
line, path, filename, rc->name, key, value);
|
||||
error("Health configuration at line %zu of file '%s' for alarm '%s' at key '%s' cannot parse duration: '%s'.",
|
||||
line, filename, rc->name, key, value);
|
||||
}
|
||||
else if(hash == hash_green && !strcasecmp(key, HEALTH_GREEN_KEY)) {
|
||||
char *e;
|
||||
rc->green = str2ld(value, &e);
|
||||
if(e && *e) {
|
||||
error("Health configuration at line %zu of file '%s/%s' for alarm '%s' at key '%s' leaves this string unmatched: '%s'.",
|
||||
line, path, filename, rc->name, key, e);
|
||||
error("Health configuration at line %zu of file '%s' for alarm '%s' at key '%s' leaves this string unmatched: '%s'.",
|
||||
line, filename, rc->name, key, e);
|
||||
}
|
||||
}
|
||||
else if(hash == hash_red && !strcasecmp(key, HEALTH_RED_KEY)) {
|
||||
char *e;
|
||||
rc->red = str2ld(value, &e);
|
||||
if(e && *e) {
|
||||
error("Health configuration at line %zu of file '%s/%s' for alarm '%s' at key '%s' leaves this string unmatched: '%s'.",
|
||||
line, path, filename, rc->name, key, e);
|
||||
error("Health configuration at line %zu of file '%s' for alarm '%s' at key '%s' leaves this string unmatched: '%s'.",
|
||||
line, filename, rc->name, key, e);
|
||||
}
|
||||
}
|
||||
else if(hash == hash_calc && !strcasecmp(key, HEALTH_CALC_KEY)) {
|
||||
|
@ -637,8 +638,8 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) {
|
|||
int error = 0;
|
||||
rc->calculation = expression_parse(value, &failed_at, &error);
|
||||
if(!rc->calculation) {
|
||||
error("Health configuration at line %zu of file '%s/%s' for alarm '%s' at key '%s' has unparse-able expression '%s': %s at '%s'",
|
||||
line, path, filename, rc->name, key, value, expression_strerror(error), failed_at);
|
||||
error("Health configuration at line %zu of file '%s' for alarm '%s' at key '%s' has unparse-able expression '%s': %s at '%s'",
|
||||
line, filename, rc->name, key, value, expression_strerror(error), failed_at);
|
||||
}
|
||||
}
|
||||
else if(hash == hash_warn && !strcasecmp(key, HEALTH_WARN_KEY)) {
|
||||
|
@ -646,8 +647,8 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) {
|
|||
int error = 0;
|
||||
rc->warning = expression_parse(value, &failed_at, &error);
|
||||
if(!rc->warning) {
|
||||
error("Health configuration at line %zu of file '%s/%s' for alarm '%s' at key '%s' has unparse-able expression '%s': %s at '%s'",
|
||||
line, path, filename, rc->name, key, value, expression_strerror(error), failed_at);
|
||||
error("Health configuration at line %zu of file '%s' for alarm '%s' at key '%s' has unparse-able expression '%s': %s at '%s'",
|
||||
line, filename, rc->name, key, value, expression_strerror(error), failed_at);
|
||||
}
|
||||
}
|
||||
else if(hash == hash_crit && !strcasecmp(key, HEALTH_CRIT_KEY)) {
|
||||
|
@ -655,15 +656,15 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) {
|
|||
int error = 0;
|
||||
rc->critical = expression_parse(value, &failed_at, &error);
|
||||
if(!rc->critical) {
|
||||
error("Health configuration at line %zu of file '%s/%s' for alarm '%s' at key '%s' has unparse-able expression '%s': %s at '%s'",
|
||||
line, path, filename, rc->name, key, value, expression_strerror(error), failed_at);
|
||||
error("Health configuration at line %zu of file '%s' for alarm '%s' at key '%s' has unparse-able expression '%s': %s at '%s'",
|
||||
line, filename, rc->name, key, value, expression_strerror(error), failed_at);
|
||||
}
|
||||
}
|
||||
else if(hash == hash_exec && !strcasecmp(key, HEALTH_EXEC_KEY)) {
|
||||
if(rc->exec) {
|
||||
if(strcmp(rc->exec, value) != 0)
|
||||
error("Health configuration at line %zu of file '%s/%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').",
|
||||
line, path, filename, rc->name, key, rc->exec, value, value);
|
||||
error("Health configuration at line %zu of file '%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').",
|
||||
line, filename, rc->name, key, rc->exec, value, value);
|
||||
|
||||
freez(rc->exec);
|
||||
}
|
||||
|
@ -672,8 +673,8 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) {
|
|||
else if(hash == hash_recipient && !strcasecmp(key, HEALTH_RECIPIENT_KEY)) {
|
||||
if(rc->recipient) {
|
||||
if(strcmp(rc->recipient, value) != 0)
|
||||
error("Health configuration at line %zu of file '%s/%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').",
|
||||
line, path, filename, rc->name, key, rc->recipient, value, value);
|
||||
error("Health configuration at line %zu of file '%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').",
|
||||
line, filename, rc->name, key, rc->recipient, value, value);
|
||||
|
||||
freez(rc->recipient);
|
||||
}
|
||||
|
@ -682,8 +683,8 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) {
|
|||
else if(hash == hash_units && !strcasecmp(key, HEALTH_UNITS_KEY)) {
|
||||
if(rc->units) {
|
||||
if(strcmp(rc->units, value) != 0)
|
||||
error("Health configuration at line %zu of file '%s/%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').",
|
||||
line, path, filename, rc->name, key, rc->units, value, value);
|
||||
error("Health configuration at line %zu of file '%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').",
|
||||
line, filename, rc->name, key, rc->units, value, value);
|
||||
|
||||
freez(rc->units);
|
||||
}
|
||||
|
@ -693,8 +694,8 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) {
|
|||
else if(hash == hash_info && !strcasecmp(key, HEALTH_INFO_KEY)) {
|
||||
if(rc->info) {
|
||||
if(strcmp(rc->info, value) != 0)
|
||||
error("Health configuration at line %zu of file '%s/%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').",
|
||||
line, path, filename, rc->name, key, rc->info, value, value);
|
||||
error("Health configuration at line %zu of file '%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').",
|
||||
line, filename, rc->name, key, rc->info, value, value);
|
||||
|
||||
freez(rc->info);
|
||||
}
|
||||
|
@ -702,22 +703,22 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) {
|
|||
strip_quotes(rc->info);
|
||||
}
|
||||
else if(hash == hash_delay && !strcasecmp(key, HEALTH_DELAY_KEY)) {
|
||||
health_parse_delay(line, path, filename, value, &rc->delay_up_duration, &rc->delay_down_duration, &rc->delay_max_duration, &rc->delay_multiplier);
|
||||
health_parse_delay(line, filename, value, &rc->delay_up_duration, &rc->delay_down_duration, &rc->delay_max_duration, &rc->delay_multiplier);
|
||||
}
|
||||
else if(hash == hash_options && !strcasecmp(key, HEALTH_OPTIONS_KEY)) {
|
||||
rc->options |= health_parse_options(value);
|
||||
}
|
||||
else {
|
||||
error("Health configuration at line %zu of file '%s/%s' for alarm '%s' has unknown key '%s'.",
|
||||
line, path, filename, rc->name, key);
|
||||
error("Health configuration at line %zu of file '%s' for alarm '%s' has unknown key '%s'.",
|
||||
line, filename, rc->name, key);
|
||||
}
|
||||
}
|
||||
else if(rt) {
|
||||
if(hash == hash_on && !strcasecmp(key, HEALTH_ON_KEY)) {
|
||||
if(rt->context) {
|
||||
if(strcmp(rt->context, value) != 0)
|
||||
error("Health configuration at line %zu of file '%s/%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').",
|
||||
line, path, filename, rt->name, key, rt->context, value, value);
|
||||
error("Health configuration at line %zu of file '%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').",
|
||||
line, filename, rt->name, key, rt->context, value, value);
|
||||
|
||||
freez(rt->context);
|
||||
}
|
||||
|
@ -732,28 +733,28 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) {
|
|||
rt->family_pattern = simple_pattern_create(rt->family_match, NULL, SIMPLE_PATTERN_EXACT);
|
||||
}
|
||||
else if(hash == hash_lookup && !strcasecmp(key, HEALTH_LOOKUP_KEY)) {
|
||||
health_parse_db_lookup(line, path, filename, value, &rt->group, &rt->after, &rt->before,
|
||||
health_parse_db_lookup(line, filename, value, &rt->group, &rt->after, &rt->before,
|
||||
&rt->update_every, &rt->options, &rt->dimensions);
|
||||
}
|
||||
else if(hash == hash_every && !strcasecmp(key, HEALTH_EVERY_KEY)) {
|
||||
if(!health_parse_duration(value, &rt->update_every))
|
||||
error("Health configuration at line %zu of file '%s/%s' for template '%s' at key '%s' cannot parse duration: '%s'.",
|
||||
line, path, filename, rt->name, key, value);
|
||||
error("Health configuration at line %zu of file '%s' for template '%s' at key '%s' cannot parse duration: '%s'.",
|
||||
line, filename, rt->name, key, value);
|
||||
}
|
||||
else if(hash == hash_green && !strcasecmp(key, HEALTH_GREEN_KEY)) {
|
||||
char *e;
|
||||
rt->green = str2ld(value, &e);
|
||||
if(e && *e) {
|
||||
error("Health configuration at line %zu of file '%s/%s' for template '%s' at key '%s' leaves this string unmatched: '%s'.",
|
||||
line, path, filename, rt->name, key, e);
|
||||
error("Health configuration at line %zu of file '%s' for template '%s' at key '%s' leaves this string unmatched: '%s'.",
|
||||
line, filename, rt->name, key, e);
|
||||
}
|
||||
}
|
||||
else if(hash == hash_red && !strcasecmp(key, HEALTH_RED_KEY)) {
|
||||
char *e;
|
||||
rt->red = str2ld(value, &e);
|
||||
if(e && *e) {
|
||||
error("Health configuration at line %zu of file '%s/%s' for template '%s' at key '%s' leaves this string unmatched: '%s'.",
|
||||
line, path, filename, rt->name, key, e);
|
||||
error("Health configuration at line %zu of file '%s' for template '%s' at key '%s' leaves this string unmatched: '%s'.",
|
||||
line, filename, rt->name, key, e);
|
||||
}
|
||||
}
|
||||
else if(hash == hash_calc && !strcasecmp(key, HEALTH_CALC_KEY)) {
|
||||
|
@ -761,8 +762,8 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) {
|
|||
int error = 0;
|
||||
rt->calculation = expression_parse(value, &failed_at, &error);
|
||||
if(!rt->calculation) {
|
||||
error("Health configuration at line %zu of file '%s/%s' for template '%s' at key '%s' has unparse-able expression '%s': %s at '%s'",
|
||||
line, path, filename, rt->name, key, value, expression_strerror(error), failed_at);
|
||||
error("Health configuration at line %zu of file '%s' for template '%s' at key '%s' has unparse-able expression '%s': %s at '%s'",
|
||||
line, filename, rt->name, key, value, expression_strerror(error), failed_at);
|
||||
}
|
||||
}
|
||||
else if(hash == hash_warn && !strcasecmp(key, HEALTH_WARN_KEY)) {
|
||||
|
@ -770,8 +771,8 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) {
|
|||
int error = 0;
|
||||
rt->warning = expression_parse(value, &failed_at, &error);
|
||||
if(!rt->warning) {
|
||||
error("Health configuration at line %zu of file '%s/%s' for template '%s' at key '%s' has unparse-able expression '%s': %s at '%s'",
|
||||
line, path, filename, rt->name, key, value, expression_strerror(error), failed_at);
|
||||
error("Health configuration at line %zu of file '%s' for template '%s' at key '%s' has unparse-able expression '%s': %s at '%s'",
|
||||
line, filename, rt->name, key, value, expression_strerror(error), failed_at);
|
||||
}
|
||||
}
|
||||
else if(hash == hash_crit && !strcasecmp(key, HEALTH_CRIT_KEY)) {
|
||||
|
@ -779,15 +780,15 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) {
|
|||
int error = 0;
|
||||
rt->critical = expression_parse(value, &failed_at, &error);
|
||||
if(!rt->critical) {
|
||||
error("Health configuration at line %zu of file '%s/%s' for template '%s' at key '%s' has unparse-able expression '%s': %s at '%s'",
|
||||
line, path, filename, rt->name, key, value, expression_strerror(error), failed_at);
|
||||
error("Health configuration at line %zu of file '%s' for template '%s' at key '%s' has unparse-able expression '%s': %s at '%s'",
|
||||
line, filename, rt->name, key, value, expression_strerror(error), failed_at);
|
||||
}
|
||||
}
|
||||
else if(hash == hash_exec && !strcasecmp(key, HEALTH_EXEC_KEY)) {
|
||||
if(rt->exec) {
|
||||
if(strcmp(rt->exec, value) != 0)
|
||||
error("Health configuration at line %zu of file '%s/%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').",
|
||||
line, path, filename, rt->name, key, rt->exec, value, value);
|
||||
error("Health configuration at line %zu of file '%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').",
|
||||
line, filename, rt->name, key, rt->exec, value, value);
|
||||
|
||||
freez(rt->exec);
|
||||
}
|
||||
|
@ -796,8 +797,8 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) {
|
|||
else if(hash == hash_recipient && !strcasecmp(key, HEALTH_RECIPIENT_KEY)) {
|
||||
if(rt->recipient) {
|
||||
if(strcmp(rt->recipient, value) != 0)
|
||||
error("Health configuration at line %zu of file '%s/%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').",
|
||||
line, path, filename, rt->name, key, rt->recipient, value, value);
|
||||
error("Health configuration at line %zu of file '%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').",
|
||||
line, filename, rt->name, key, rt->recipient, value, value);
|
||||
|
||||
freez(rt->recipient);
|
||||
}
|
||||
|
@ -806,8 +807,8 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) {
|
|||
else if(hash == hash_units && !strcasecmp(key, HEALTH_UNITS_KEY)) {
|
||||
if(rt->units) {
|
||||
if(strcmp(rt->units, value) != 0)
|
||||
error("Health configuration at line %zu of file '%s/%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').",
|
||||
line, path, filename, rt->name, key, rt->units, value, value);
|
||||
error("Health configuration at line %zu of file '%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').",
|
||||
line, filename, rt->name, key, rt->units, value, value);
|
||||
|
||||
freez(rt->units);
|
||||
}
|
||||
|
@ -817,8 +818,8 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) {
|
|||
else if(hash == hash_info && !strcasecmp(key, HEALTH_INFO_KEY)) {
|
||||
if(rt->info) {
|
||||
if(strcmp(rt->info, value) != 0)
|
||||
error("Health configuration at line %zu of file '%s/%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').",
|
||||
line, path, filename, rt->name, key, rt->info, value, value);
|
||||
error("Health configuration at line %zu of file '%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').",
|
||||
line, filename, rt->name, key, rt->info, value, value);
|
||||
|
||||
freez(rt->info);
|
||||
}
|
||||
|
@ -826,19 +827,19 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) {
|
|||
strip_quotes(rt->info);
|
||||
}
|
||||
else if(hash == hash_delay && !strcasecmp(key, HEALTH_DELAY_KEY)) {
|
||||
health_parse_delay(line, path, filename, value, &rt->delay_up_duration, &rt->delay_down_duration, &rt->delay_max_duration, &rt->delay_multiplier);
|
||||
health_parse_delay(line, filename, value, &rt->delay_up_duration, &rt->delay_down_duration, &rt->delay_max_duration, &rt->delay_multiplier);
|
||||
}
|
||||
else if(hash == hash_options && !strcasecmp(key, HEALTH_OPTIONS_KEY)) {
|
||||
rt->options |= health_parse_options(value);
|
||||
}
|
||||
else {
|
||||
error("Health configuration at line %zu of file '%s/%s' for template '%s' has unknown key '%s'.",
|
||||
line, path, filename, rt->name, key);
|
||||
error("Health configuration at line %zu of file '%s' for template '%s' has unknown key '%s'.",
|
||||
line, filename, rt->name, key);
|
||||
}
|
||||
}
|
||||
else {
|
||||
error("Health configuration at line %zu of file '%s/%s' has unknown key '%s'. Expected either '" HEALTH_ALARM_KEY "' or '" HEALTH_TEMPLATE_KEY "'.",
|
||||
line, path, filename, key);
|
||||
error("Health configuration at line %zu of file '%s' has unknown key '%s'. Expected either '" HEALTH_ALARM_KEY "' or '" HEALTH_TEMPLATE_KEY "'.",
|
||||
line, filename, key);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -852,51 +853,7 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
void health_readdir(RRDHOST *host, const char *path) {
|
||||
if(!host->health_enabled) return;
|
||||
|
||||
size_t pathlen = strlen(path);
|
||||
|
||||
debug(D_HEALTH, "Health configuration reading directory '%s'", path);
|
||||
|
||||
DIR *dir = opendir(path);
|
||||
if (!dir) {
|
||||
error("Health configuration cannot open directory '%s'.", path);
|
||||
return;
|
||||
}
|
||||
|
||||
struct dirent *de = NULL;
|
||||
while ((de = readdir(dir))) {
|
||||
size_t len = strlen(de->d_name);
|
||||
|
||||
if(de->d_type == DT_DIR
|
||||
&& (
|
||||
(de->d_name[0] == '.' && de->d_name[1] == '\0')
|
||||
|| (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')
|
||||
)) {
|
||||
debug(D_HEALTH, "Ignoring directory '%s'", de->d_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
else if(de->d_type == DT_DIR) {
|
||||
char *s = mallocz(pathlen + strlen(de->d_name) + 2);
|
||||
strcpy(s, path);
|
||||
strcat(s, "/");
|
||||
strcat(s, de->d_name);
|
||||
health_readdir(host, s);
|
||||
freez(s);
|
||||
continue;
|
||||
}
|
||||
|
||||
else if((de->d_type == DT_LNK || de->d_type == DT_REG || de->d_type == DT_UNKNOWN) &&
|
||||
len > 5 && !strcmp(&de->d_name[len - 5], ".conf")) {
|
||||
health_readfile(host, path, de->d_name);
|
||||
}
|
||||
|
||||
else debug(D_HEALTH, "Ignoring file '%s'", de->d_name);
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
void health_readdir(RRDHOST *host, const char *user_path, const char *stock_path, const char *subpath) {
|
||||
if(unlikely(!host->health_enabled)) return;
|
||||
recursive_config_double_dir_load(user_path, stock_path, subpath, health_readfile, (void *) host);
|
||||
}
|
||||
|
||||
|
||||
|
|
79
src/main.c
79
src/main.c
|
@ -460,12 +460,13 @@ static void get_netdata_configured_variables() {
|
|||
// ------------------------------------------------------------------------
|
||||
// get system paths
|
||||
|
||||
netdata_configured_config_dir = config_get(CONFIG_SECTION_GLOBAL, "config directory", CONFIG_DIR);
|
||||
netdata_configured_log_dir = config_get(CONFIG_SECTION_GLOBAL, "log directory", LOG_DIR);
|
||||
netdata_configured_web_dir = config_get(CONFIG_SECTION_GLOBAL, "web files directory", WEB_DIR);
|
||||
netdata_configured_cache_dir = config_get(CONFIG_SECTION_GLOBAL, "cache directory", CACHE_DIR);
|
||||
netdata_configured_varlib_dir = config_get(CONFIG_SECTION_GLOBAL, "lib directory", VARLIB_DIR);
|
||||
netdata_configured_home_dir = config_get(CONFIG_SECTION_GLOBAL, "home directory", CACHE_DIR);
|
||||
netdata_configured_user_config_dir = config_get(CONFIG_SECTION_GLOBAL, "config directory", netdata_configured_user_config_dir);
|
||||
netdata_configured_stock_config_dir = config_get(CONFIG_SECTION_GLOBAL, "stock config directory", netdata_configured_stock_config_dir);
|
||||
netdata_configured_log_dir = config_get(CONFIG_SECTION_GLOBAL, "log directory", netdata_configured_log_dir);
|
||||
netdata_configured_web_dir = config_get(CONFIG_SECTION_GLOBAL, "web files directory", netdata_configured_web_dir);
|
||||
netdata_configured_cache_dir = config_get(CONFIG_SECTION_GLOBAL, "cache directory", netdata_configured_cache_dir);
|
||||
netdata_configured_varlib_dir = config_get(CONFIG_SECTION_GLOBAL, "lib directory", netdata_configured_varlib_dir);
|
||||
netdata_configured_home_dir = config_get(CONFIG_SECTION_GLOBAL, "home directory", netdata_configured_home_dir);
|
||||
|
||||
{
|
||||
char plugins_dirs[(FILENAME_MAX * 2) + 1];
|
||||
|
@ -596,15 +597,17 @@ void set_global_environment() {
|
|||
setenv("NETDATA_UPDATE_EVERY", b, 1);
|
||||
}
|
||||
|
||||
setenv("NETDATA_HOSTNAME" , netdata_configured_hostname, 1);
|
||||
setenv("NETDATA_CONFIG_DIR" , verify_required_directory(netdata_configured_config_dir), 1);
|
||||
setenv("NETDATA_PLUGINS_DIR", verify_required_directory(netdata_configured_plugins_dir), 1);
|
||||
setenv("NETDATA_WEB_DIR" , verify_required_directory(netdata_configured_web_dir), 1);
|
||||
setenv("NETDATA_CACHE_DIR" , verify_required_directory(netdata_configured_cache_dir), 1);
|
||||
setenv("NETDATA_LIB_DIR" , verify_required_directory(netdata_configured_varlib_dir), 1);
|
||||
setenv("NETDATA_LOG_DIR" , verify_required_directory(netdata_configured_log_dir), 1);
|
||||
setenv("HOME" , verify_required_directory(netdata_configured_home_dir), 1);
|
||||
setenv("NETDATA_HOST_PREFIX", netdata_configured_host_prefix, 1);
|
||||
setenv("NETDATA_HOSTNAME" , netdata_configured_hostname, 1);
|
||||
setenv("NETDATA_CONFIG_DIR" , verify_required_directory(netdata_configured_user_config_dir), 1);
|
||||
setenv("NETDATA_USER_CONFIG_DIR" , verify_required_directory(netdata_configured_user_config_dir), 1);
|
||||
setenv("NETDATA_STOCK_CONFIG_DIR" , verify_required_directory(netdata_configured_stock_config_dir), 1);
|
||||
setenv("NETDATA_PLUGINS_DIR" , verify_required_directory(netdata_configured_plugins_dir), 1);
|
||||
setenv("NETDATA_WEB_DIR" , verify_required_directory(netdata_configured_web_dir), 1);
|
||||
setenv("NETDATA_CACHE_DIR" , verify_required_directory(netdata_configured_cache_dir), 1);
|
||||
setenv("NETDATA_LIB_DIR" , verify_required_directory(netdata_configured_varlib_dir), 1);
|
||||
setenv("NETDATA_LOG_DIR" , verify_required_directory(netdata_configured_log_dir), 1);
|
||||
setenv("HOME" , verify_required_directory(netdata_configured_home_dir), 1);
|
||||
setenv("NETDATA_HOST_PREFIX" , netdata_configured_host_prefix, 1);
|
||||
|
||||
get_system_timezone();
|
||||
|
||||
|
@ -626,6 +629,33 @@ void set_global_environment() {
|
|||
setenv("LC_ALL", "C", 1);
|
||||
}
|
||||
|
||||
static int load_netdata_conf(char *filename, char overwrite_used) {
|
||||
if(filename)
|
||||
return config_load(filename, overwrite_used);
|
||||
|
||||
filename = strdupz_path_subpath(netdata_configured_user_config_dir, "netdata.conf");
|
||||
|
||||
int ret = config_load(filename, overwrite_used);
|
||||
if(!ret) {
|
||||
freez(filename);
|
||||
filename = strdupz_path_subpath(netdata_configured_stock_config_dir, "netdata.conf");
|
||||
ret = config_load(filename, overwrite_used);
|
||||
}
|
||||
freez(filename);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void load_stream_conf() {
|
||||
char *filename = strdupz_path_subpath(netdata_configured_user_config_dir, "stream.conf");
|
||||
if(!appconfig_load(&stream_config, filename, 0)) {
|
||||
freez(filename);
|
||||
filename = strdupz_path_subpath(netdata_configured_stock_config_dir, "stream.conf");
|
||||
appconfig_load(&stream_config, filename, 0);
|
||||
}
|
||||
freez(filename);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int i;
|
||||
int config_loaded = 0;
|
||||
|
@ -686,7 +716,7 @@ int main(int argc, char **argv) {
|
|||
while( (opt = getopt(argc, argv, optstring)) != -1 ) {
|
||||
switch(opt) {
|
||||
case 'c':
|
||||
if(config_load(optarg, 1) != 1) {
|
||||
if(load_netdata_conf(optarg, 1) != 1) {
|
||||
error("Cannot load configuration file %s.", optarg);
|
||||
return 1;
|
||||
}
|
||||
|
@ -731,9 +761,6 @@ int main(int argc, char **argv) {
|
|||
if(strcmp(optarg, "unittest") == 0) {
|
||||
if(unit_test_buffer()) return 1;
|
||||
if(unit_test_str2ld()) return 1;
|
||||
//default_rrd_update_every = 1;
|
||||
//default_rrd_memory_mode = RRD_MEMORY_MODE_RAM;
|
||||
//if(!config_loaded) config_load(NULL, 0);
|
||||
get_netdata_configured_variables();
|
||||
default_rrd_update_every = 1;
|
||||
default_rrd_memory_mode = RRD_MEMORY_MODE_RAM;
|
||||
|
@ -841,7 +868,7 @@ int main(int argc, char **argv) {
|
|||
|
||||
if(!config_loaded) {
|
||||
fprintf(stderr, "warning: no configuration file has been loaded. Use -c CONFIG_FILE, before -W get. Using default config.\n");
|
||||
config_load(NULL, 0);
|
||||
load_netdata_conf(NULL, 0);
|
||||
}
|
||||
|
||||
backwards_compatible_config();
|
||||
|
@ -879,7 +906,7 @@ int main(int argc, char **argv) {
|
|||
#endif
|
||||
|
||||
if(!config_loaded)
|
||||
config_load(NULL, 0);
|
||||
load_netdata_conf(NULL, 0);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// initialize netdata
|
||||
|
@ -902,8 +929,8 @@ int main(int argc, char **argv) {
|
|||
// work while we are cd into config_dir
|
||||
// to allow the plugins refer to their config
|
||||
// files using relative filenames
|
||||
if(chdir(netdata_configured_config_dir) == -1)
|
||||
fatal("Cannot cd to '%s'", netdata_configured_config_dir);
|
||||
if(chdir(netdata_configured_user_config_dir) == -1)
|
||||
fatal("Cannot cd to '%s'", netdata_configured_user_config_dir);
|
||||
}
|
||||
|
||||
char *user = NULL;
|
||||
|
@ -938,11 +965,7 @@ int main(int argc, char **argv) {
|
|||
|
||||
// --------------------------------------------------------------------
|
||||
// load stream.conf
|
||||
{
|
||||
char filename[FILENAME_MAX + 1];
|
||||
snprintfz(filename, FILENAME_MAX, "%s/stream.conf", netdata_configured_config_dir);
|
||||
appconfig_load(&stream_config, filename, 0);
|
||||
}
|
||||
load_stream_conf();
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
|
|
@ -240,7 +240,7 @@ RRDHOST *rrdhost_create(const char *hostname,
|
|||
health_alarm_log_open(host);
|
||||
|
||||
rrdhost_wrlock(host);
|
||||
health_readdir(host, health_config_dir());
|
||||
health_readdir(host, health_user_config_dir(), health_stock_config_dir(), NULL);
|
||||
rrdhost_unlock(host);
|
||||
}
|
||||
|
||||
|
|
110
src/statsd.c
110
src/statsd.c
|
@ -1031,7 +1031,7 @@ void *statsd_collector_thread(void *ptr) {
|
|||
|
||||
#define STATSD_CONF_LINE_MAX 8192
|
||||
|
||||
static STATSD_APP_CHART_DIM_VALUE_TYPE string2valuetype(const char *type, size_t line, const char *path, const char *filename) {
|
||||
static STATSD_APP_CHART_DIM_VALUE_TYPE string2valuetype(const char *type, size_t line, const char *filename) {
|
||||
if(!type || !*type) type = "last";
|
||||
|
||||
if(!strcmp(type, "events")) return STATSD_APP_CHART_DIM_VALUE_TYPE_EVENTS;
|
||||
|
@ -1044,7 +1044,7 @@ static STATSD_APP_CHART_DIM_VALUE_TYPE string2valuetype(const char *type, size_t
|
|||
else if(!strcmp(type, "stddev")) return STATSD_APP_CHART_DIM_VALUE_TYPE_STDDEV;
|
||||
else if(!strcmp(type, "percentile")) return STATSD_APP_CHART_DIM_VALUE_TYPE_PERCENTILE;
|
||||
|
||||
error("STATSD: invalid type '%s' at line %zu of file '%s/%s'. Using 'last'.", type, line, path, filename);
|
||||
error("STATSD: invalid type '%s' at line %zu of file '%s'. Using 'last'.", type, line, filename);
|
||||
return STATSD_APP_CHART_DIM_VALUE_TYPE_LAST;
|
||||
}
|
||||
|
||||
|
@ -1110,19 +1110,14 @@ static STATSD_APP_CHART_DIM *add_dimension_to_app_chart(
|
|||
return dim;
|
||||
}
|
||||
|
||||
static int statsd_readfile(const char *path, const char *filename, STATSD_APP *app, STATSD_APP_CHART *chart, DICTIONARY *dict) {
|
||||
debug(D_STATSD, "STATSD configuration reading file '%s/%s'", path, filename);
|
||||
static int statsd_readfile(const char *filename, STATSD_APP *app, STATSD_APP_CHART *chart, DICTIONARY *dict) {
|
||||
debug(D_STATSD, "STATSD configuration reading file '%s'", filename);
|
||||
|
||||
char *buffer = mallocz(STATSD_CONF_LINE_MAX + 1);
|
||||
|
||||
if(filename[0] == '/')
|
||||
strncpyz(buffer, filename, STATSD_CONF_LINE_MAX);
|
||||
else
|
||||
snprintfz(buffer, STATSD_CONF_LINE_MAX, "%s/%s", path, filename);
|
||||
|
||||
FILE *fp = fopen(buffer, "r");
|
||||
FILE *fp = fopen(filename, "r");
|
||||
if(!fp) {
|
||||
error("STATSD: cannot open file '%s'.", buffer);
|
||||
error("STATSD: cannot open file '%s'.", filename);
|
||||
freez(buffer);
|
||||
return -1;
|
||||
}
|
||||
|
@ -1135,18 +1130,31 @@ static int statsd_readfile(const char *path, const char *filename, STATSD_APP *a
|
|||
|
||||
s = trim(buffer);
|
||||
if (!s || *s == '#') {
|
||||
debug(D_STATSD, "STATSD: ignoring line %zu of file '%s/%s', it is empty.", line, path, filename);
|
||||
debug(D_STATSD, "STATSD: ignoring line %zu of file '%s', it is empty.", line, filename);
|
||||
continue;
|
||||
}
|
||||
|
||||
debug(D_STATSD, "STATSD: processing line %zu of file '%s/%s': %s", line, path, filename, buffer);
|
||||
debug(D_STATSD, "STATSD: processing line %zu of file '%s': %s", line, filename, buffer);
|
||||
|
||||
if(*s == 'i' && strncmp(s, "include", 7) == 0) {
|
||||
s = trim(&s[7]);
|
||||
if(s && *s)
|
||||
statsd_readfile(path, s, app, chart, dict);
|
||||
if(s && *s) {
|
||||
char *tmp;
|
||||
if(*s == '/')
|
||||
tmp = strdupz(s);
|
||||
else {
|
||||
// the file to be included is relative to current file
|
||||
// find the directory name from the file we already read
|
||||
char *filename2 = strdupz(filename); // copy filename, since dirname() will change it
|
||||
char *dir = dirname(filename2); // find the directory part of the filename
|
||||
tmp = strdupz_path_subpath(dir, s); // compose the new filename to read;
|
||||
freez(filename2); // free the filename we copied
|
||||
}
|
||||
statsd_readfile(tmp, app, chart, dict);
|
||||
freez(tmp);
|
||||
}
|
||||
else
|
||||
error("STATSD: ignoring line %zu of file '%s/%s', include filename is empty", line, path, s);
|
||||
error("STATSD: ignoring line %zu of file '%s', include filename is empty", line, filename);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
@ -1208,20 +1216,20 @@ static int statsd_readfile(const char *path, const char *filename, STATSD_APP *a
|
|||
}
|
||||
}
|
||||
else
|
||||
error("STATSD: ignoring line %zu ('%s') of file '%s/%s', [app] is not defined.", line, s, path, filename);
|
||||
error("STATSD: ignoring line %zu ('%s') of file '%s', [app] is not defined.", line, s, filename);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!app) {
|
||||
error("STATSD: ignoring line %zu ('%s') of file '%s/%s', it is outside all sections.", line, s, path, filename);
|
||||
error("STATSD: ignoring line %zu ('%s') of file '%s', it is outside all sections.", line, s, filename);
|
||||
continue;
|
||||
}
|
||||
|
||||
char *name = s;
|
||||
char *value = strchr(s, '=');
|
||||
if(!value) {
|
||||
error("STATSD: ignoring line %zu ('%s') of file '%s/%s', there is no = in it.", line, s, path, filename);
|
||||
error("STATSD: ignoring line %zu ('%s') of file '%s', there is no = in it.", line, s, filename);
|
||||
continue;
|
||||
}
|
||||
*value = '\0';
|
||||
|
@ -1231,11 +1239,11 @@ static int statsd_readfile(const char *path, const char *filename, STATSD_APP *a
|
|||
value = trim(value);
|
||||
|
||||
if(!name || *name == '#') {
|
||||
error("STATSD: ignoring line %zu of file '%s/%s', name is empty.", line, path, filename);
|
||||
error("STATSD: ignoring line %zu of file '%s', name is empty.", line, filename);
|
||||
continue;
|
||||
}
|
||||
if(!value) {
|
||||
debug(D_CONFIG, "STATSD: ignoring line %zu of file '%s/%s', value is empty.", line, path, filename);
|
||||
debug(D_CONFIG, "STATSD: ignoring line %zu of file '%s', value is empty.", line, filename);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1275,7 +1283,7 @@ static int statsd_readfile(const char *path, const char *filename, STATSD_APP *a
|
|||
app->rrd_history_entries = 5;
|
||||
}
|
||||
else {
|
||||
error("STATSD: ignoring line %zu ('%s') of file '%s/%s'. Unknown keyword for the [app] section.", line, name, path, filename);
|
||||
error("STATSD: ignoring line %zu ('%s') of file '%s'. Unknown keyword for the [app] section.", line, name, filename);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -1360,14 +1368,14 @@ static int statsd_readfile(const char *path, const char *filename, STATSD_APP *a
|
|||
, (multipler && *multipler)?str2l(multipler):1
|
||||
, (divisor && *divisor)?str2l(divisor):1
|
||||
, flags
|
||||
, string2valuetype(type, line, path, filename)
|
||||
, string2valuetype(type, line, filename)
|
||||
);
|
||||
|
||||
if(pattern)
|
||||
dim->metric_pattern = simple_pattern_create(dim->metric, NULL, SIMPLE_PATTERN_EXACT);
|
||||
}
|
||||
else {
|
||||
error("STATSD: ignoring line %zu ('%s') of file '%s/%s'. Unknown keyword for the [%s] section.", line, name, path, filename, chart->id);
|
||||
error("STATSD: ignoring line %zu ('%s') of file '%s'. Unknown keyword for the [%s] section.", line, name, filename, chart->id);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -1378,49 +1386,13 @@ static int statsd_readfile(const char *path, const char *filename, STATSD_APP *a
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void statsd_readdir(const char *path) {
|
||||
size_t pathlen = strlen(path);
|
||||
static int statsd_file_callback(const char *filename, void *data) {
|
||||
(void)data;
|
||||
return statsd_readfile(filename, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
debug(D_STATSD, "STATSD configuration reading directory '%s'", path);
|
||||
|
||||
DIR *dir = opendir(path);
|
||||
if (!dir) {
|
||||
error("STATSD configuration cannot open directory '%s'.", path);
|
||||
return;
|
||||
}
|
||||
|
||||
struct dirent *de = NULL;
|
||||
while ((de = readdir(dir))) {
|
||||
size_t len = strlen(de->d_name);
|
||||
|
||||
if(de->d_type == DT_DIR
|
||||
&& (
|
||||
(de->d_name[0] == '.' && de->d_name[1] == '\0')
|
||||
|| (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')
|
||||
)) {
|
||||
debug(D_STATSD, "STATSD: ignoring directory '%s'", de->d_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
else if(de->d_type == DT_DIR) {
|
||||
char *s = mallocz(pathlen + strlen(de->d_name) + 2);
|
||||
strcpy(s, path);
|
||||
strcat(s, "/");
|
||||
strcat(s, de->d_name);
|
||||
statsd_readdir(s);
|
||||
freez(s);
|
||||
continue;
|
||||
}
|
||||
|
||||
else if((de->d_type == DT_LNK || de->d_type == DT_REG || de->d_type == DT_UNKNOWN) &&
|
||||
len > 5 && !strcmp(&de->d_name[len - 5], ".conf")) {
|
||||
statsd_readfile(path, de->d_name, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
else debug(D_STATSD, "STATSD: ignoring file '%s'", de->d_name);
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
static inline void statsd_readdir(const char *user_path, const char *stock_path, const char *subpath) {
|
||||
recursive_config_double_dir_load(user_path, stock_path, subpath, statsd_file_callback, NULL);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -2243,11 +2215,7 @@ void *statsd_main(void *ptr) {
|
|||
#endif
|
||||
|
||||
// read custom application definitions
|
||||
{
|
||||
char filename[FILENAME_MAX + 1];
|
||||
snprintfz(filename, FILENAME_MAX, "%s/statsd.d", netdata_configured_config_dir);
|
||||
statsd_readdir(filename);
|
||||
}
|
||||
statsd_readdir(netdata_configured_user_config_dir, netdata_configured_stock_config_dir, "statsd.d");
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------------
|
||||
// statsd setup
|
||||
|
|
|
@ -1199,8 +1199,50 @@ static int test_variable_renames(void) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
int check_strdupz_path_subpath() {
|
||||
|
||||
struct strdupz_path_subpath_checks {
|
||||
const char *path;
|
||||
const char *subpath;
|
||||
const char *result;
|
||||
} checks[] = {
|
||||
{ "", "", "." },
|
||||
{ "/", "", "/" },
|
||||
{ "/etc/netdata", "", "/etc/netdata" },
|
||||
{ "/etc/netdata///", "", "/etc/netdata" },
|
||||
{ "/etc/netdata///", "health.d", "/etc/netdata/health.d" },
|
||||
{ "/etc/netdata///", "///health.d", "/etc/netdata/health.d" },
|
||||
{ "/etc/netdata", "///health.d", "/etc/netdata/health.d" },
|
||||
{ "", "///health.d", "./health.d" },
|
||||
{ "/", "///health.d", "/health.d" },
|
||||
|
||||
// terminator
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
size_t i;
|
||||
for(i = 0; checks[i].result ; i++) {
|
||||
char *s = strdupz_path_subpath(checks[i].path, checks[i].subpath);
|
||||
fprintf(stderr, "strdupz_path_subpath(\"%s\", \"%s\") = \"%s\": ", checks[i].path, checks[i].subpath, s);
|
||||
if(!s || strcmp(s, checks[i].result) != 0) {
|
||||
freez(s);
|
||||
fprintf(stderr, "FAILED\n");
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
freez(s);
|
||||
fprintf(stderr, "OK\n");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int run_all_mockup_tests(void)
|
||||
{
|
||||
if(check_strdupz_path_subpath())
|
||||
return 1;
|
||||
|
||||
if(check_number_printing())
|
||||
return 1;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue