diff --git a/install.sh b/install.sh index 9b616e2..f1e1e24 100755 --- a/install.sh +++ b/install.sh @@ -225,7 +225,7 @@ zaf_configure(){ zaf_get_option ZAF_AGENT_CONFIGD "Zabbix agent config.d" "/etc/zabbix/zabbix_agentd.conf.d/" "$INSTALL_MODE" zaf_get_option ZAF_AGENT_BIN "Zabbix agent binary" "/usr/sbin/zabbix_agentd" "$INSTALL_MODE" zaf_get_option ZAF_AGENT_RESTART "Zabbix agent restart cmd" "service zabbix-agent restart" "$INSTALL_MODE" - zaf_get_option ZAF_CACHE_DIR "Cache directory" "${ZAF_TMP_BASE}c/" "$INSTALL_MODE" + zaf_get_option ZAF_SUDOERSD "Sudo sudoers.d directory" "/etc/sudoers.d" "$INSTALL_MODE" zaf_get_option ZAF_ZBXAPI_URL "Zabbix API url" "http://localhost/zabbix/api_jsonrpc.php" "$INSTALL_MODE" zaf_get_option ZAF_ZBXAPI_USER "Zabbix API user" "zaf" "$INSTALL_MODE" zaf_get_option ZAF_ZBXAPI_PASS "Zabbix API password" "" "$INSTALL_MODE" @@ -257,7 +257,7 @@ zaf_configure(){ zaf_set_option ZAF_AGENT_CONFIGD "$ZAF_AGENT_CONFIGD" zaf_set_option ZAF_AGENT_BIN "$ZAF_AGENT_BIN" zaf_set_option ZAF_AGENT_RESTART "$ZAF_AGENT_RESTART" - zaf_set_option ZAF_CACHE_DIR "$ZAF_CACHE_DIR" + zaf_set_option ZAF_SUDOERSD "$ZAF_SUDOERSD" zaf_set_option ZAF_ZBXAPI_URL "$ZAF_ZBXAPI_URL" zaf_set_option ZAF_ZBXAPI_USER "$ZAF_ZBXAPI_USER" zaf_set_option ZAF_ZBXAPI_PASS "$ZAF_ZBXAPI_PASS" diff --git a/lib/cache.lib.sh b/lib/cache.lib.sh index bc665f8..93d8695 100644 --- a/lib/cache.lib.sh +++ b/lib/cache.lib.sh @@ -1,13 +1,18 @@ # Zaf cache related functions -zaf_cache_init(){ - [ -n "$ZAF_CACHE_DIR" ] && rm -rf "$ZAF_CACHE_DIR" +zaf_cache_clean(){ + if [ -n "$ZAF_CACHE_DIR" ]; then + zaf_wrn "Removing cache entries" + rm -rf "$ZAF_CACHE_DIR" + else + zaf_err "Cache dir not set." + fi mkdir -p "$ZAF_CACHE_DIR" } # Get cache key from requested param zaf_cachekey(){ - echo "$1" | md5sum - | cut -d ' ' -f 1 + echo $1 | md5sum - | cut -d ' ' -f 1 } # Put object into cache @@ -18,9 +23,10 @@ zaf_tocache(){ local key local value local lifetime - key=$(zaf_cachekey "$1") + key=$(zaf_cachekey $1) echo "$2" >$ZAF_CACHE_DIR/$key touch -m -d "$3 seconds" $ZAF_CACHE_DIR/$key.tme + zaf_trc "Cache: Saving entry $1($key)" } # Put object into cache from stdin and copy to stdout @@ -30,9 +36,10 @@ zaf_tocache_stdin(){ local key local lifetime - key=$(zaf_cachekey "$1") + key=$(zaf_cachekey $1) cat >$ZAF_CACHE_DIR/$key touch -m -d "$3 seconds" $ZAF_CACHE_DIR/$key.tme + zaf_trc "Cache: Saving entry $1($key)" cat $ZAF_CACHE_DIR/$key } @@ -41,7 +48,7 @@ zaf_tocache_stdin(){ zaf_fromcache(){ local key local value - key=$(zaf_cachekey "$1") + key=$(zaf_cachekey $1) if [ -f $ZAF_CACHE_DIR/$key ]; then if [ "$ZAF_CACHE_DIR/$key.tme" -nt "$ZAF_CACHE_DIR/$key" ]; then zaf_trc "Cache: serving $1($key) from cache" diff --git a/lib/ctrl.lib.sh b/lib/ctrl.lib.sh index 05f9b12..35612dc 100644 --- a/lib/ctrl.lib.sh +++ b/lib/ctrl.lib.sh @@ -82,7 +82,25 @@ zaf_ctrl_check_deps() { done } -# Install binaries from control +# Install sudo config from control +# $1 plugin +# $2 control +# $3 plugindir +zaf_ctrl_sudo() { + local pdir + local plugin + + if ! which sudo >/dev/null; then + zaf_wrn "Sudo needed bud not installed?" + fi + pdir="$3" + plugin=$1 + (echo -n "zabbix ALL=NOPASSWD: " + zaf_ctrl_get_global_option $2 "Sudo" | zaf_far '{PLUGINDIR}' "${plugindir}"; + echo ) >$ZAF_SUDOERSD/zaf_$plugin +} + +# Install sudo options from control # $1 pluginurl # $2 control # $3 plugindir @@ -104,6 +122,7 @@ zaf_ctrl_install() { [ -n "$cmd" ] && $cmd } + # Generates zabbix cfg from control file # $1 control # $2 pluginname @@ -113,6 +132,7 @@ zaf_ctrl_generate_cfg() { local iscript local ikey local lock + local cache items=$(zaf_ctrl_get_items <"$1") for i in $items; do @@ -133,21 +153,25 @@ zaf_ctrl_generate_cfg() { if [ -n "$lock" ]; then lock="${ZAF_LIB_DIR}/zaflock $lock " fi + cache=$(zaf_ctrl_get_item_option $1 $i "Cache") + if [ -n "$cache" ]; then + cache="_cache '$cache' " + fi cmd=$(zaf_ctrl_get_item_option $1 $i "Cmd") if [ -n "$cmd" ]; then - $(which echo) "UserParameter=$ikey,${ZAF_LIB_DIR}/preload.sh $lock$cmd"; + $(which echo) "UserParameter=$ikey,${ZAF_LIB_DIR}/preload.sh $cache $lock$cmd"; continue fi cmd=$(zaf_ctrl_get_item_option $1 $i "Function") if [ -n "$cmd" ]; then - $(which echo) "UserParameter=$ikey,${ZAF_LIB_DIR}/preload.sh $lock$cmd"; + $(which echo) "UserParameter=$ikey,${ZAF_LIB_DIR}/preload.sh $cache $lock$cmd"; continue; fi cmd=$(zaf_ctrl_get_item_option $1 $i "Script") if [ -n "$cmd" ]; then zaf_ctrl_get_item_option $1 $i "Script" >${ZAF_TMP_DIR}/${iscript}.sh; zaf_install_bin ${ZAF_TMP_DIR}/${iscript}.sh ${ZAF_PLUGINS_DIR}/$2/ - $(which echo) "UserParameter=$ikey,${ZAF_LIB_DIR}/preload.sh $lock${ZAF_PLUGINS_DIR}/$2/${iscript}.sh $args"; + $(which echo) "UserParameter=$ikey,${ZAF_LIB_DIR}/preload.sh $cache $lock${ZAF_PLUGINS_DIR}/$2/${iscript}.sh $args"; continue; fi zaf_err "Item $i declared in control file but has no Cmd, Function or Script!" diff --git a/lib/preload.sh b/lib/preload.sh index 641616a..fefde66 100644 --- a/lib/preload.sh +++ b/lib/preload.sh @@ -4,19 +4,33 @@ [ -z "$ZAF_TMP_BASE" ] && ZAF_TMP_BASE=/tmp/zaf ZAF_TMP_DIR="${ZAF_TMP_BASE}-${USER}" -trap "rm -rif ${ZAF_TMP_DIR}" EXIT +[ -z "$ZAF_CACHE_DIR" ] && ZAF_CACHE_DIR=${ZAF_TMP_BASE}-${USER}c + +#trap "rm -rif ${ZAF_TMP_DIR}" EXIT ! [ -d "${ZAF_TMP_DIR}" ] && mkdir "${ZAF_TMP_DIR}" +! [ -d "${ZAF_CACHE_DIR}" ] && mkdir "${ZAF_CACHE_DIR}" [ -z "$ZAF_DEBUG" ] && ZAF_DEBUG=1 . ${ZAF_LIB_DIR}/zaf.lib.sh . ${ZAF_LIB_DIR}/ctrl.lib.sh . ${ZAF_LIB_DIR}/os.lib.sh +. ${ZAF_LIB_DIR}/zbxapi.lib.sh +. ${ZAF_LIB_DIR}/cache.lib.sh export ZAF_LIB_DIR export ZAF_TMP_DIR export ZAF_PLUGINS_DIR -[ "$(basename $0)" = "preload.sh" ] && [ -n "$*" ] && $@ - +if [ "$1" = "_cache" ]; then + shift + seconds=$1 + shift + parms=$(echo $*|tr -d ' ') + if ! zaf_fromcache $parms; then + ([ "$(basename $0)" = "preload.sh" ] && [ -n "$*" ] && $@ ) | zaf_tocache_stdin $parms $seconds + fi +else + [ "$(basename $0)" = "preload.sh" ] && [ -n "$*" ] && $@ +fi diff --git a/lib/zaf.lib.sh b/lib/zaf.lib.sh index acf7a4d..5294cc0 100644 --- a/lib/zaf.lib.sh +++ b/lib/zaf.lib.sh @@ -73,6 +73,27 @@ zaf_far(){ eval $sedcmd } +# Limit concurrent processes or continue +zaf_bglimit(){ + local maxbg + local maxnumber + local cnumber + if [ $# -eq 0 ] ; then + maxbg=5 + else + maxbg=$1 + fi + maxnumber=$((0 + ${1:-0})) + while true; do + cnumber=$(jobs | wc -l) + if [ $cnumber -lt $maxnumber ]; then + break + fi + zaf_dbg "Limiting next job due to $maxbg limit of bg jobs" + sleep 1 + done +} + # Initialises discovery function zaf_discovery_begin(){ cat <${ZAF_AGENT_CONFIGD}/zaf_${plugin}.conf zaf_dbg "Generated ${ZAF_AGENT_CONFIGD}/zaf_${plugin}.conf" diff --git a/lib/zbxapi.lib.sh b/lib/zbxapi.lib.sh index be30bbb..24a6b5e 100644 --- a/lib/zbxapi.lib.sh +++ b/lib/zbxapi.lib.sh @@ -3,10 +3,14 @@ zaf_zbxapi_do() { local result if ! zaf_fromcache "$1"; then - zaf_dbg "Zabbix API: $1" + zaf_trc "Zabbix API: $1" result=$(curl -s -f -L -X POST -H 'Content-Type: application/json-rpc' -d "$1" "$ZAF_ZBXAPI_URL") - zaf_tocache "$1" "$result" 60 - echo $result + if [ $? = 0 ] && echo $result | grep -q '"result":'; then + zaf_tocache "$1" "$result" 60 + echo $result + else + zaf_err "Error processing API request. ($?,$result)" + fi fi } @@ -55,7 +59,6 @@ zaf_zbxapi_login(){ ZAF_ZBXAPI_URL=$(echo $ZAF_ZBXAPI_URL | cut -d '/' -f 1)//$ZAF_ZBXAPI_USER:$ZAF_ZBXAPI_PASS@$(echo $ZAF_ZBXAPI_URL | cut -d '/' -f 3-) fi result=$(zaf_zbxapi_do "$authstr") - echo $result | grep -vq '"result":"' && zaf_err "Cannot login to API" ZAF_ZBXAPI_AUTH=$(echo $result |zaf_zbxapi_getresult| zaf_zbxapi_getstring) zaf_dbg "Logged into zabbix API ($ZAF_ZBXAPI_AUTH)" } diff --git a/zaf b/zaf index 3ea1a22..11c289f 100755 --- a/zaf +++ b/zaf @@ -18,6 +18,8 @@ done [ -z "$ZAF_TMP_BASE" ] && ZAF_TMP_BASE=/tmp/zaf ZAF_TMP_DIR="${ZAF_TMP_BASE}-${USER}" +[ -z "$ZAF_CACHE_DIR" ] && ZAF_CACHE_DIR=${ZAF_TMP_BASE}-${USER}c + [ -z "$ZAF_DEBUG" ] && ZAF_DEBUG=1 export ZAF_DEBUG @@ -70,6 +72,28 @@ check-agent-config) zaf_check_agent_config ;; +cache-clean) + zaf_cache_clean + ;; + +userparms) + for plugin in $(zaf_list_plugins); do + plugindir=$ZAF_PLUGINS_DIR/$plugin + control=$plugindir/control.zaf + zaf_ctrl_generate_cfg "${control}" "${plugin}" \ + | zaf_far '{PLUGINDIR}' "${plugindir}" + done + ;; + +agent-config) + for plugin in $(zaf_list_plugins); do + plugindir=$ZAF_PLUGINS_DIR/$plugin + control=$plugindir/control.zaf + zaf_ctrl_generate_cfg "${control}" "${plugin}" \ + | zaf_far '{PLUGINDIR}' "${plugindir}" >${ZAF_AGENT_CONFIGD}/zaf_${plugin}.conf + done + ;; + update) zaf_wrn "Updating repository ${ZAF_REPO_GITURL}..." zaf_update_repo @@ -241,17 +265,29 @@ api) zaf_zbxapi_gethostsingroup $gid ;; backup-group) - gid=$(zaf_zbxapi_gethostgroupid "$3") + set -e + shift $(zaf_shift) + shift; shift + gid=$(zaf_zbxapi_gethostgroupid "$1") + shift $(zaf_shift) + shift hosts=$(zaf_zbxapi_gethostsingroup $gid) + dir="." + [ -n "$1" ] && dir="$1" zaf_wrn "Will backup this hosts: $hosts" + zaf_wrn "Output dir: $dir" for h in $hosts; do - hn=$(zaf_zbxapi_gethost $h) + zaf_bglimit 5 + (hn=$(zaf_zbxapi_gethost $h) zaf_wrn "Exporting host $hn($h)..." - zaf_zbxapi_backuphost $h >$hn.xml + zaf_zbxapi_backuphost $h >$dir/$hn.xml ) done + wait ;; backup-host) - hostid=$(zaf_zbxapi_gethostid "$3") + shift $(zaf_shift) + shift; shift + hostid=$(zaf_zbxapi_gethostid "$1") zaf_wrn "Exporting host $3($hostid)..." zaf_zbxapi_backuphost $hostid ;; @@ -283,8 +319,12 @@ api) echo "$0 install plugin To install plugin" echo "$0 remove plugin To remove plugin" echo "$0 api To zabbix API functions. See $0 api for more info." + echo "$0 userparms See userparms generated from zaf on stdout" + echo "$0 agent-config Reconfigure zabbix userparms in $ZAF_AGENT_CONFIGD" + echo "$0 self-upgrade To self-upgrade zaf" echo "$0 self-remove To self-remove zaf and its config" + echo "$0 cache-clean To remove all entries from cache" echo ;;