Merge branch '1.2'

1.3
Lukas Macura 2016-06-17 12:07:14 +02:00
commit 8e9d950411
15 changed files with 971 additions and 234 deletions

View File

@ -1,13 +1,15 @@
# Zabbix Agent Framework # Zabbix (Agent) Framework
This tool is used to maintain external zabbix checks in *one place*. There are lot of places where it is possible to download many external checks. This tool is used to maintain external zabbix checks in *one place*. There are lot of places where it is possible to download many external checks.
But there is problem with installation, update and centralised management. This tool should do all of this in easy steps. In future it can be *starting point* to But there is problem with installation, update and centralised management. This tool should do all of this in easy steps. In future it can be *starting point* to
install and configure zabbix agent on systems with one step. Primary goal is not to make all plugins available here but to be able to use any plugin and decentralized development. install and configure zabbix agent on systems with one step. Primary goal is not to make all plugins available here but to be able to use any plugin and decentralized development.
If you are maintainer of some external check, it is enough to create zaf file in your repo and use zaf installer everywhere. If you are maintainer of some external check, it is enough to create zaf file in your repo and use zaf installer everywhere.
Next to this, this tool can even communicate with Zabbix API with *NO dependencies* to high level languages. Shell, sed and awk only.
## Motivation ## Motivation
Did you install lot of zabbix agents and try to setup similar common user parameters? Do you want to setup them all? Do you want to change some zabbix agent options on lot of system? Do you want to write your own simple check or discovery rule for zabbix and it is nightmare to deploy same script on more zabbix agents? Are you tired searching some system specific agent check and setup them individualy? Did you install lot of zabbix agents and try to setup similar common user parameters? Do you want to setup them all? Do you want to change some zabbix agent options on lot of system? Do you want to write your own simple check or discovery rule for zabbix and it is nightmare to deploy same script on more zabbix agents? Are you tired searching some system specific agent check and setup them individualy? Do you want to auto simple backup all hosts in your zabbix to xml files? Or do you want to do some scripting on host depending on Zabbix server configuration?
So zaf is here for you :) So zaf is here for you :)
## Features ## Features
@ -21,6 +23,7 @@ So zaf is here for you :)
* Zabbix discovery simplification. Creating zabbix item for discovery is not so easy in shell based system and result is not nice. But you can use framework function to do so. * Zabbix discovery simplification. Creating zabbix item for discovery is not so easy in shell based system and result is not nice. But you can use framework function to do so.
* Zabbix agent autoinstallation and autoconfiguration suitable to use in puppet or another tool * Zabbix agent autoinstallation and autoconfiguration suitable to use in puppet or another tool
* OS packaging support * OS packaging support
* Zabbix API support
## Installing Zaf ## Installing Zaf
You need to be root and you must have curl installed on your system. Depending on your system, github certificates may not be available so you have to use *-k* option for curl (insecure). Default installation type is silent. So there will be no questions and everything will be autodetected. This simple command should be used on most systems: You need to be root and you must have curl installed on your system. Depending on your system, github certificates may not be available so you have to use *-k* option for curl (insecure). Default installation type is silent. So there will be no questions and everything will be autodetected. This simple command should be used on most systems:
@ -32,13 +35,15 @@ curl -k https://raw.githubusercontent.com/limosek/zaf/1.3/install.sh | sh
General parameters for install.sh on any system (simplest way how to install) General parameters for install.sh on any system (simplest way how to install)
``` ```
curl -k https://raw.githubusercontent.com/limosek/zaf/1.3/install.sh | \ curl -k https://raw.githubusercontent.com/limosek/zaf/1.3/install.sh | \
sh -s {auto|interactive|debug-auto|debug-interactive} [Agent-Options] [Zaf-Options] sh -s {auto|interactive|debug-auto|debug-interactive} [Agent-Options] [Server-Options] [Zaf-Options]
``` ```
or use git version: or use git version:
``` ```
git clone https://github.com/limosek/zaf.git; cd zaf; git checkout 1.3 git clone https://github.com/limosek/zaf.git; cd zaf; git checkout 1.3
./install.sh {auto|interactive|debug-auto|debug-interactive} [Agent-Options] [Zaf-Options]
./install.sh {auto|interactive|debug-auto|debug-interactive} [Agent-Options] [Server-Options] [Zaf-Options]
Agent-Options: Z_Option=value [...] Agent-Options: Z_Option=value [...]
Server-Options: S_Option=value [...]
Zaf-Options: ZAF_OPT=value [...] Zaf-Options: ZAF_OPT=value [...]
To unset Agent-Option use Z_Option='' To unset Agent-Option use Z_Option=''
``` ```
@ -126,37 +131,50 @@ Zaf binary can be installed on any system from openwrt to big system. It has min
./zaf ./zaf
./zaf Version 1.3master. Please use some of this commands: ./zaf Version 1.3master. Please use some of this commands:
./zaf Cmd [ZAF_OPTION=value] [ZAF_CTRL_Option=value] [ZAF_CTRLI_Item_Option=value] ... ./zaf Cmd [ZAF_OPTION=value] [ZAF_CTRL_Option=value] [ZAF_CTRLI_Item_Option=value] ...
Commands: Plugin manipulation commands:
./zaf update To update repo (not plugins, similar to apt-get update) ./zaf update To update repo (not plugins, similar to apt-get update)
./zaf upgrade To upgrade installed plugins from repo ./zaf upgrade To upgrade installed plugins from repo
./zaf plugins To list installed plugins ./zaf install plugin To install plugin
./zaf show [plugin] To show installed plugins or plugin info ./zaf remove plugin To remove plugin
./zaf items [plugin] To list all suported items [for plugin]
./zaf test [plugin[.item]] To test [all] suported items by zabbix_agentd [for plugin] Plugin info commands:
./zaf get [plugin[.item]] To test [all] suported items by zabbix_get [for plugin] ./zaf plugins To list installed plugins
./zaf precache [plugin[.item]] To precache [all] suported items ./zaf show [plugin] To show installed plugins or plugin info
./zaf install plugin To install plugin ./zaf items [plugin] To list all suported items [for plugin]
./zaf remove plugin To remove plugin
./zaf api To zabbix API functions. See ./zaf api for more info. Plugin diagnostic commands:
./zaf userparms See userparms generated from zaf on stdout ./zaf test [plugin[.item]] To test [all] suported items by zabbix_agentd [for plugin]
./zaf agent-config Reconfigure zabbix userparms in /etc/zabbix/zabbix_agentd.d ./zaf get [plugin[.item]] To test [all] suported items by zabbix_get [for plugin]
./zaf self-upgrade To self-upgrade zaf ./zaf precache [plugin[.item]] To precache [all] suported items
./zaf self-remove To self-remove zaf and its config
./zaf cache-clean To remove all entries from cache Zabbix API commands:
./zaf api To zabbix API functions. See ./zaf api for more info.
Agent config info commands:
./zaf userparms See userparms generated from zaf on stdout
./zaf agent-config Reconfigure zabbix userparms in /etc/zabbix/zabbix_agentd.d
Zaf related commands:
./zaf self-upgrade To self-upgrade zaf
./zaf self-remove To self-remove zaf and its config
./zaf cache-clean To remove all entries from cache
``` ```
Zaf can even communicate with zabbix server using its API. If you set ZAF_ZBXAPI_URL, ZAF_ZBXAPI_USER and ZAF_ZBXAPI_PASS in /etc/zaf.conf, you can use it: Zaf can even communicate with zabbix server using its API. If you set ZAF_ZBXAPI_URL, ZAF_ZBXAPI_USER and ZAF_ZBXAPI_PASS in /etc/zaf.conf, you can use it:
``` ```
./zaf api command [parameters] ./zaf api command [parameters]
hostid 'host' Get hostid from hostname get-host-id host Get host id
host 'hostid' Get hostname from hostid get-byid-host id [property] Get host property from id. Leave empty property for JSON
hostgroupid 'hostgroup' Get hostgroup id from hostgroup get-template-id template Get template id
hosts 'hostgroup' Get hosts in group get-byid-template id [property] Get template property from id. Leave empty property for JSON
export-hosts dir [hostgroup] Backup all hosts [in group] (get their config from zabbix and save to dir/hostname.xml) get-map-id map Get map id
export-host 'host' Backup host (get config from zabbix to stdout) get-byid-map id [property] Get map property from id. Leave empty property for JSON
import-template {plugin|file} Import template for plugin or from file get-inventory host [fields] Get inventory fields [or all fields]
export-template 'name' Export template to stdout export-hosts dir [hg] Backup all hosts [in group hg] (get their config from zabbix and save to dir/hostname.xml)
export-templates dir Export all template to dir export-host host Backup host (get config from zabbix to stdout)
import-template {plugin|file} Import template for plugin or from file
export-template name Export template to stdout
export-templates dir Export all templates to dir
``` ```
### Installing plugin ### Installing plugin

15
contrib/zafdeb.sh Executable file
View File

@ -0,0 +1,15 @@
#!/bin/sh
. lib/zaf.lib.sh
! [ -d plugins ] && git clone https://github.com/limosek/zaf-plugins.git plugins
make deb DEBIAN_PKG="out/zaf-$ZAF_VERSION-git.deb" \
ZAF_OPTIONS="ZAF_GIT=1 ZAF_REPO_GITURL='https://github.com/limosek/zaf-plugins.git'"
make deb DEBIAN_PKG="out/zaf-$ZAF_VERSION.deb" \
ZAF_OPTIONS="ZAF_GIT=0"
make deb DEBIAN_PKG="out/zaf-$ZAF_VERSION-all.deb" ZAF_OPTIONS="ZAF_GIT=0" \
PLUGINS="./plugins/fsx ./plugins/openssh ./plugins/psx ./plugins/tcqos ./plugins/zaf ./plugins/fail2ban"

View File

@ -8,7 +8,12 @@ configure)
. /usr/lib/zaf/os.lib.sh . /usr/lib/zaf/os.lib.sh
. /usr/lib/zaf/ctrl.lib.sh . /usr/lib/zaf/ctrl.lib.sh
cd /usr/lib/zaf && /usr/lib/zaf/install.sh reconf cd /usr/lib/zaf && /usr/lib/zaf/install.sh reconf
[ -n "{PLUGINS}" ] && zaf reinstall {PLUGINS} {IPLUGINS} [ -n "{PLUGINS}" ] && for p in {PLUGINS}; do
if ! zaf_is_plugin $p;then
zaf install $ZAF_PREPACKAGED_DIR/$p;
fi
done
[ -n "{IPLUGINS}" ] && zaf reinstall {IPLUGINS}
fi fi
;; ;;
esac esac

View File

@ -8,55 +8,28 @@ fi
[ -z "$ZAF_GITBRANCH" ] && ZAF_GITBRANCH=master [ -z "$ZAF_GITBRANCH" ] && ZAF_GITBRANCH=master
############### Functions
# Lite version of zaf_fetch_url, full version will be loaded later # Lite version of zaf_fetch_url, full version will be loaded later
zaf_fetch_url(){ zaf_fetch_url(){
if [ -z "$ZAF_OFFLINE" ]; then echo curl -f -k -s -L -o - "$1" >&2;
echo curl -f -k -s -L -o - "$1" >&2; curl -f -k -s -L -o - "$1" curl -f -k -s -L -o - "$1"
else
echo "Offline mode wants to download $1. Exiting." >&2
exit 2
fi
} }
# Download tgz and extract to /tmp/zaf-installer # Lite version of zaf_err, full version will be loaded later
zaf_err() {
logger ${ZAF_LOG_STDERR} -p user.err -t zaf-error -- $@
logger ${ZAF_LOG_STDERR} -p user.err -t zaf-error "Exiting with error!"
exit 1
}
# Download tgz and extract to tmpdir
zaf_download_files() { zaf_download_files() {
rm -rf /tmp/zaf-installer [ -z $ZAF_DIR ] && zaf_err "ZAF_DIR not set!"
zaf_fetch_url $ZAF_URL/archive/$ZAF_GITBRANCH.tar.gz | tar -f - -C /tmp -zx && mv /tmp/zaf-$ZAF_GITBRANCH /tmp/zaf-installer rm -rf $ZAF_DIR
zaf_fetch_url $ZAF_URL/archive/$ZAF_GITBRANCH.tar.gz | tar -f - -C $ZAF_TMP_DIR -zx && mv $ZAF_TMP_DIR/zaf-$ZAF_GITBRANCH $ZAF_DIR || zaf_err "Cannot download and unpack zaf!"
} }
if ! [ -f README.md ]; then
# We are runing from stdin
if ! which curl >/dev/null;
then
zaf_err "Curl not found. Cannot continue. Please install it."
fi
echo "Installing from url $url..."
[ -z "$*" ] && auto=auto
zaf_download_files && cd /tmp/zaf-installer && exec ./install.sh $auto "$@"
echo "Error downloading and runing installer!" >&2
exit 2
fi
if ! type zaf_version >/dev/null; then
. lib/zaf.lib.sh
. lib/os.lib.sh
. lib/ctrl.lib.sh
. lib/cache.lib.sh
. lib/zbxapi.lib.sh
fi
# Read options as config for ZAF
for pair in "$@"; do
echo $pair | grep -q '^ZAF\_' || continue
option=$(echo $pair|cut -d '=' -f 1)
value=$(echo $pair|cut -d '=' -f 2-)
eval "C_${option}='$value'"
zaf_wrn "Overriding $option from cmdline."
done
[ -z "$ZAF_CFG_FILE" ] && ZAF_CFG_FILE=$INSTALL_PREFIX/etc/zaf.conf
[ -n "$C_ZAF_DEBUG" ] && ZAF_DEBUG=$C_ZAF_DEBUG
# Read option. If it is already set in zaf.conf, it is skipped. If env variable is set, it is used instead of default # Read option. If it is already set in zaf.conf, it is skipped. If env variable is set, it is used instead of default
# It sets global variable name on result. # It sets global variable name on result.
# $1 - option name # $1 - option name
@ -265,7 +238,8 @@ zaf_configure(){
fi fi
zaf_get_option ZAF_GIT "Git is installed" "$ZAF_GIT" "$INSTALL_MODE" zaf_get_option ZAF_GIT "Git is installed" "$ZAF_GIT" "$INSTALL_MODE"
zaf_get_option ZAF_CURL_INSECURE "Insecure curl (accept all certificates)" "1" "$INSTALL_MODE" zaf_get_option ZAF_CURL_INSECURE "Insecure curl (accept all certificates)" "1" "$INSTALL_MODE"
zaf_get_option ZAF_TMP_BASE "Tmp directory prefix (\$USER will be added)" "/tmp/zaf" "$INSTALL_MODE" zaf_get_option ZAF_TMP_DIR "Tmp directory" "/tmp/" "$INSTALL_MODE"
zaf_get_option ZAF_CACHE_DIR "Cache directory" "/tmp/zafc" "$INSTALL_MODE"
zaf_get_option ZAF_LIB_DIR "Libraries directory" "/usr/lib/zaf" "$INSTALL_MODE" zaf_get_option ZAF_LIB_DIR "Libraries directory" "/usr/lib/zaf" "$INSTALL_MODE"
zaf_get_option ZAF_BIN_DIR "Directory to put binaries" "/usr/bin" "$INSTALL_MODE" zaf_get_option ZAF_BIN_DIR "Directory to put binaries" "/usr/bin" "$INSTALL_MODE"
zaf_get_option ZAF_PLUGINS_DIR "Plugins directory" "${ZAF_LIB_DIR}/plugins" "$INSTALL_MODE" zaf_get_option ZAF_PLUGINS_DIR "Plugins directory" "${ZAF_LIB_DIR}/plugins" "$INSTALL_MODE"
@ -306,7 +280,8 @@ zaf_configure(){
zaf_set_option ZAF_AGENT_PKG "${ZAF_AGENT_PKG}" zaf_set_option ZAF_AGENT_PKG "${ZAF_AGENT_PKG}"
zaf_set_option ZAF_GIT "${ZAF_GIT}" zaf_set_option ZAF_GIT "${ZAF_GIT}"
zaf_set_option ZAF_CURL_INSECURE "${ZAF_CURL_INSECURE}" zaf_set_option ZAF_CURL_INSECURE "${ZAF_CURL_INSECURE}"
zaf_set_option ZAF_TMP_BASE "$ZAF_TMP_BASE" zaf_set_option ZAF_TMP_DIR "$ZAF_TMP_DIR"
zaf_set_option ZAF_CACHE_DIR "$ZAF_CACHE_DIR"
zaf_set_option ZAF_LIB_DIR "$ZAF_LIB_DIR" zaf_set_option ZAF_LIB_DIR "$ZAF_LIB_DIR"
zaf_set_option ZAF_BIN_DIR "$ZAF_BIN_DIR" zaf_set_option ZAF_BIN_DIR "$ZAF_BIN_DIR"
zaf_set_option ZAF_PLUGINS_DIR "$ZAF_PLUGINS_DIR" zaf_set_option ZAF_PLUGINS_DIR "$ZAF_PLUGINS_DIR"
@ -316,6 +291,9 @@ zaf_configure(){
zaf_set_option ZAF_AGENT_CONFIG "$ZAF_AGENT_CONFIG" zaf_set_option ZAF_AGENT_CONFIG "$ZAF_AGENT_CONFIG"
zaf_set_option ZAF_AGENT_CONFIGD "$ZAF_AGENT_CONFIGD" zaf_set_option ZAF_AGENT_CONFIGD "$ZAF_AGENT_CONFIGD"
zaf_set_option ZAF_AGENT_BIN "$ZAF_AGENT_BIN" zaf_set_option ZAF_AGENT_BIN "$ZAF_AGENT_BIN"
zaf_set_option ZAF_FILES_UID "$ZAF_FILES_UID"
zaf_set_option ZAF_FILES_GID "$ZAF_FILES_GID"
zaf_set_option ZAF_FILES_UMASK "$ZAF_FILES_UMASK"
zaf_set_option ZAF_AGENT_RESTART "$ZAF_AGENT_RESTART" zaf_set_option ZAF_AGENT_RESTART "$ZAF_AGENT_RESTART"
if [ -f $ZABBIX_SERVER_BIN ]; then if [ -f $ZABBIX_SERVER_BIN ]; then
zaf_set_option ZAF_SERVER_CONFIG "$ZAF_SERVER_CONFIG" zaf_set_option ZAF_SERVER_CONFIG "$ZAF_SERVER_CONFIG"
@ -340,16 +318,25 @@ zaf_configure(){
zaf_wrn "Skipping server config. Zabbix server binary '$ZAF_SERVER_BIN' not found." zaf_wrn "Skipping server config. Zabbix server binary '$ZAF_SERVER_BIN' not found."
fi fi
fi fi
if ! [ -d $ZAF_CACHE_DIR ]; then
mkdir -p "$ZAF_CACHE_DIR"
if zaf_is_root && [ -n "$ZAF_FILES_UID" ] && [ -n "$ZAF_FILES_GID" ]; then
zaf_wrn "Cache: Changing perms to $ZAF_CACHE_DIR (zabbix/$ZAF_ZABBIX_GID/0770)"
chown $ZAF_FILES_UID "$ZAF_CACHE_DIR"
chgrp $ZAF_FILES_GID "$ZAF_CACHE_DIR"
chmod $ZAF_FILES_UMASK "$ZAF_CACHE_DIR"
fi
fi
zaf_cache_init
} }
zaf_install_all() { zaf_install_all() {
rm -rif ${ZAF_TMP_DIR}
mkdir -p ${ZAF_TMP_DIR}
zaf_install_dir ${ZAF_LIB_DIR} zaf_install_dir ${ZAF_LIB_DIR}
for i in lib/zaf.lib.sh lib/os.lib.sh lib/ctrl.lib.sh lib/cache.lib.sh lib/zbxapi.lib.sh README.md; do for i in lib/zaf.lib.sh lib/plugin.lib.sh lib/os.lib.sh lib/ctrl.lib.sh lib/cache.lib.sh lib/zbxapi.lib.sh lib/JSON.sh README.md; do
zaf_install $i ${ZAF_LIB_DIR}/ || zaf_err "Error installing $i" zaf_install $i ${ZAF_LIB_DIR}/ || zaf_err "Error installing $i"
done done
for i in lib/zaflock lib/preload.sh; do for i in lib/zaflock lib/zafcache lib/preload.sh; do
zaf_install_bin $i ${ZAF_LIB_DIR}/ || zaf_err "Error installing $i" zaf_install_bin $i ${ZAF_LIB_DIR}/ || zaf_err "Error installing $i"
done done
zaf_install_dir ${ZAF_BIN_DIR} zaf_install_dir ${ZAF_BIN_DIR}
@ -363,8 +350,10 @@ zaf_install_all() {
zaf_postconfigure() { zaf_postconfigure() {
if zaf_is_root; then if zaf_is_root; then
${INSTALL_PREFIX}/${ZAF_BIN_DIR}/zaf cache-clean
[ "${ZAF_GIT}" = 1 ] && ${INSTALL_PREFIX}/${ZAF_BIN_DIR}/zaf update [ "${ZAF_GIT}" = 1 ] && ${INSTALL_PREFIX}/${ZAF_BIN_DIR}/zaf update
${INSTALL_PREFIX}/${ZAF_BIN_DIR}/zaf reinstall zaf || zaf_err "Error installing zaf plugin." ${INSTALL_PREFIX}/${ZAF_BIN_DIR}/zaf reinstall zaf || zaf_err "Error installing zaf plugin."
${INSTALL_PREFIX}/${ZAF_BIN_DIR}/zaf agent-config || zaf_err "Error configuring agent."
if zaf_is_root && ! zaf_test_item zaf.framework_version; then if zaf_is_root && ! zaf_test_item zaf.framework_version; then
echo "Something is wrong with zabbix agent config." echo "Something is wrong with zabbix agent config."
echo "Ensure that zabbix_agentd reads ${ZAF_AGENT_CONFIG}" echo "Ensure that zabbix_agentd reads ${ZAF_AGENT_CONFIG}"
@ -379,17 +368,65 @@ zaf_postconfigure() {
true true
} }
############ First stage Init
if ! [ -f README.md ]; then
# Hardcoded variables
ZAF_VERSION="1.2"
ZAF_GITBRANCH="1.2"
ZAF_URL="https://github.com/limosek/zaf"
ZAF_RAW_URL="https://raw.githubusercontent.com/limosek/zaf"
export ZAF_TMP_DIR="/tmp/zaf-installer"
export ZAF_DIR="$ZAF_TMP_DIR/zaf"
mkdir -p $ZAF_TMP_DIR
if ! which curl >/dev/null;
then
zaf_err "Curl not found. Cannot continue. Please install it."
fi
echo "Installing from url $url..."
[ -z "$*" ] && auto=auto
zaf_download_files && cd $ZAF_DIR && exec ./install.sh $auto "$@"
echo "Error downloading and runing installer!" >&2
exit 2
fi
# Try to load local downloaded libs
if ! type zaf_version >/dev/null; then
. lib/zaf.lib.sh
. lib/plugin.lib.sh
. lib/os.lib.sh
. lib/ctrl.lib.sh
. lib/cache.lib.sh
. lib/zbxapi.lib.sh
fi
# If something was wrong reading libs, then exit
if ! type zaf_version >/dev/null; then
echo "Problem loading libraries?"
exit 2
fi
########### Second stage init (all functions loaded)
[ -z "$ZAF_CFG_FILE" ] && ZAF_CFG_FILE=$INSTALL_PREFIX/etc/zaf.conf
if [ -f "${ZAF_CFG_FILE}" ]; then if [ -f "${ZAF_CFG_FILE}" ]; then
. "${ZAF_CFG_FILE}" . "${ZAF_CFG_FILE}"
fi fi
ZAF_TMP_DIR="/tmp/zaf-installer-tmp/" export ZAF_TMP_DIR="/tmp/zaf-installer"
export ZAF_DIR="$ZAF_TMP_DIR/zaf"
# If debug is on, do not remove tmp dir ! [ -d $ZAF_TMP_DIR ] && mkdir -p $ZAF_TMP_DIR
if [ "$ZAF_DEBUG" -le 3 ]; then zaf_debug_init stderr
trap "rm -rif ${ZAF_TMP_DIR}" EXIT zaf_tmp_init
trap "rm -rif /tmp/zaf-installer" EXIT
fi # Read options as config for ZAF
! [ -d "${ZAF_TMP_DIR}" ] && mkdir "${ZAF_TMP_DIR}" for pair in "$@"; do
echo $pair | grep -q '^ZAF\_' || continue
option=$(echo $pair|cut -d '=' -f 1)
value=$(echo $pair|cut -d '=' -f 2-)
eval "C_${option}='$value'"
zaf_wrn "Overriding $option from cmdline."
done
[ -z "$C_ZAF_TMP_DIR" ] && C_ZAF_TMP_DIR="/tmp/"
case $1 in case $1 in
interactive) interactive)

208
lib/JSON.sh Executable file
View File

@ -0,0 +1,208 @@
#!/bin/sh
throw() {
echo "$*" >&2
exit 1
}
BRIEF=0
LEAFONLY=0
PRUNE=0
NO_HEAD=0
NORMALIZE_SOLIDUS=0
usage() {
echo
echo "Usage: JSON.sh [-b] [-l] [-p] [-s] [-h]"
echo
echo "-p - Prune empty. Exclude fields with empty values."
echo "-l - Leaf only. Only show leaf nodes, which stops data duplication."
echo "-b - Brief. Combines 'Leaf only' and 'Prune empty' options."
echo "-n - No-head. Do not show nodes that have no path (lines that start with [])."
echo "-s - Remove escaping of the solidus symbol (stright slash)."
echo "-h - This help text."
echo
}
parse_options() {
set -- "$@"
local ARGN=$#
while [ "$ARGN" -ne 0 ]
do
case $1 in
-h) usage
exit 0
;;
-b) BRIEF=1
LEAFONLY=1
PRUNE=1
;;
-l) LEAFONLY=1
;;
-p) PRUNE=1
;;
-n) NO_HEAD=1
;;
-s) NORMALIZE_SOLIDUS=1
;;
?*) echo "ERROR: Unknown option."
usage
exit 0
;;
esac
shift 1
ARGN=$((ARGN-1))
done
}
awk_egrep () {
local pattern_string=$1
gawk '{
while ($0) {
start=match($0, pattern);
token=substr($0, start, RLENGTH);
print token;
$0=substr($0, start+RLENGTH);
}
}' pattern="$pattern_string"
}
tokenize () {
local GREP
local ESCAPE
local CHAR
if echo "test string" | egrep -ao --color=never "test" >/dev/null 2>&1
then
GREP='egrep -ao --color=never'
else
GREP='egrep -ao'
fi
if echo "test string" | egrep -o "test" >/dev/null 2>&1
then
ESCAPE='(\\[^u[:cntrl:]]|\\u[0-9a-fA-F]{4})'
CHAR='[^[:cntrl:]"\\]'
else
GREP=awk_egrep
ESCAPE='(\\\\[^u[:cntrl:]]|\\u[0-9a-fA-F]{4})'
CHAR='[^[:cntrl:]"\\\\]'
fi
local STRING="\"$CHAR*($ESCAPE$CHAR*)*\""
local NUMBER='-?(0|[1-9][0-9]*)([.][0-9]*)?([eE][+-]?[0-9]*)?'
local KEYWORD='null|false|true'
local SPACE='[[:space:]]+'
# Force zsh to expand $A into multiple words
local is_wordsplit_disabled=$(unsetopt 2>/dev/null | grep -c '^shwordsplit$')
if [ $is_wordsplit_disabled != 0 ]; then setopt shwordsplit; fi
$GREP "$STRING|$NUMBER|$KEYWORD|$SPACE|." | egrep -v "^$SPACE$"
if [ $is_wordsplit_disabled != 0 ]; then unsetopt shwordsplit; fi
}
parse_array () {
local index=0
local ary=''
read -r token
case "$token" in
']') ;;
*)
while :
do
parse_value "$1" "$index"
index=$((index+1))
ary="$ary""$value"
read -r token
case "$token" in
']') break ;;
',') ary="$ary," ;;
*) throw "EXPECTED , or ] GOT ${token:-EOF}" ;;
esac
read -r token
done
;;
esac
[ "$BRIEF" -eq 0 ] && value=$(printf '[%s]' "$ary") || value=
:
}
parse_object () {
local key
local obj=''
read -r token
case "$token" in
'}') ;;
*)
while :
do
case "$token" in
'"'*'"') key=$token ;;
*) throw "EXPECTED string GOT ${token:-EOF}" ;;
esac
read -r token
case "$token" in
':') ;;
*) throw "EXPECTED : GOT ${token:-EOF}" ;;
esac
read -r token
parse_value "$1" "$key"
obj="$obj$key:$value"
read -r token
case "$token" in
'}') break ;;
',') obj="$obj," ;;
*) throw "EXPECTED , or } GOT ${token:-EOF}" ;;
esac
read -r token
done
;;
esac
[ "$BRIEF" -eq 0 ] && value=$(printf '{%s}' "$obj") || value=
:
}
parse_value () {
local jpath="${1:+$1,}$2" isleaf=0 isempty=0 print=0
case "$token" in
'{') parse_object "$jpath" ;;
'[') parse_array "$jpath" ;;
# At this point, the only valid single-character tokens are digits.
''|[!0-9]) throw "EXPECTED value GOT ${token:-EOF}" ;;
*) value=$token
# if asked, replace solidus ("\/") in json strings with normalized value: "/"
[ "$NORMALIZE_SOLIDUS" -eq 1 ] && value=$(echo "$value" | sed 's#\\/#/#g')
isleaf=1
[ "$value" = '""' ] && isempty=1
;;
esac
[ "$value" = '' ] && return
[ "$NO_HEAD" -eq 1 ] && [ -z "$jpath" ] && return
[ "$LEAFONLY" -eq 0 ] && [ "$PRUNE" -eq 0 ] && print=1
[ "$LEAFONLY" -eq 1 ] && [ "$isleaf" -eq 1 ] && [ $PRUNE -eq 0 ] && print=1
[ "$LEAFONLY" -eq 0 ] && [ "$PRUNE" -eq 1 ] && [ "$isempty" -eq 0 ] && print=1
[ "$LEAFONLY" -eq 1 ] && [ "$isleaf" -eq 1 ] && \
[ $PRUNE -eq 1 ] && [ $isempty -eq 0 ] && print=1
[ "$print" -eq 1 ] && printf "[%s]\t%s\n" "$jpath" "$value"
:
}
parse () {
read -r token
parse_value
read -r token
case "$token" in
'') ;;
*) throw "EXPECTED EOF GOT $token" ;;
esac
}
if ([ "$0" = "$BASH_SOURCE" ] || ! [ -n "$BASH_SOURCE" ]);
then
parse_options "$@"
tokenize | parse
fi
# vi: expandtab sw=2 ts=2

View File

@ -1,18 +1,36 @@
# Zaf cache related functions # Zaf cache related functions
zaf_cache_init(){
[ -z "$ZAF_CACHE_DIR" ] && ZAF_CACHE_DIR=${ZAF_TMP_DIR}/zafc
if [ -w $ZAF_CACHE_DIR ]; then
zaf_trc "Cache: Removing stale entries"
(cd $ZAF_CACHE_DIR && find ./ -type f -name '*.info' -mmin +1 2>/dev/null | \
while read line ; do
rm -f $line $(basename $line .info)
done
)
else
zaf_dbg "Cache dir $ZAF_CACHE_DIR is not accessible! Disabling cache."
fi
}
zaf_cache_clean(){ zaf_cache_clean(){
if [ -n "$ZAF_CACHE_DIR" ]; then if [ -n "$ZAF_CACHE_DIR" ]; then
zaf_wrn "Removing cache entries" zaf_wrn "Removing cache entries"
rm -rf "$ZAF_CACHE_DIR" (cd $ZAF_CACHE_DIR && find ./ -type f -name '*.info' 2>/dev/null | \
while read line ; do
rm -f $line $(basename $line .info)
done
)
else else
zaf_err "Cache dir not set." zaf_dbg "Cache dir not set. Disabling cache."
fi fi
mkdir -p "$ZAF_CACHE_DIR" zaf_cache_init
} }
# Get cache key from requested param # Get cache key from requested param
zaf_cache_key(){ zaf_cache_key(){
echo "$1" | md5sum - | cut -d ' ' -f 1 echo "$1" | (md5sum - ||md5) 2>/dev/null | cut -d ' ' -f 1
} }
# Put object into cache # Put object into cache
@ -23,12 +41,15 @@ zaf_tocache(){
! [ -w $ZAF_CACHE_DIR ] && return 1 ! [ -w $ZAF_CACHE_DIR ] && return 1
local key local key
local value local value
local expiry
key=$(zaf_cache_key "$1") key=$(zaf_cache_key "$1")
rm -f $ZAF_CACHE_DIR/$key $ZAF_CACHE_DIR/${key}.info
echo "$2" >$ZAF_CACHE_DIR/$key echo "$2" >$ZAF_CACHE_DIR/$key
echo "$1" >$ZAF_CACHE_DIR/$key.info echo "$1" >$ZAF_CACHE_DIR/${key}.info
touch -m -d "$3 seconds" $ZAF_CACHE_DIR/$key.info expiry=$(zaf_date_add "$3")
zaf_trc "Cache: Saving entry $1($key)" zaf_trc "Cache: Saving entry $1[$key,expiry=$expiry]"
touch -m -d "$expiry" $ZAF_CACHE_DIR/${key}.info
} }
# Put object into cache from stdin and copy to stdout # Put object into cache from stdin and copy to stdout
@ -37,16 +58,19 @@ zaf_tocache(){
zaf_tocache_stdin(){ zaf_tocache_stdin(){
! [ -w $ZAF_CACHE_DIR ] && return 1 ! [ -w $ZAF_CACHE_DIR ] && return 1
local key local key
local expiry
key=$(zaf_cache_key "$1") key=$(zaf_cache_key "$1")
rm -f $ZAF_CACHE_DIR/$key $ZAF_CACHE_DIR/${key}.info
cat >$ZAF_CACHE_DIR/$key cat >$ZAF_CACHE_DIR/$key
if [ -s $ZAF_CACHE_DIR/$key ]; then if [ -s $ZAF_CACHE_DIR/$key ]; then
zaf_trc "Cache: Saving entry $1($key)" expiry="$(zaf_date_add $2)"
echo "$1" >$ZAF_CACHE_DIR/$key.info echo "$1 [key=$key,expiry=$expiry]" >$ZAF_CACHE_DIR/${key}.info
touch -m -d "$2 seconds" $ZAF_CACHE_DIR/$key.info zaf_trc "Cache: Saving entry $1[key=$key,expiry=$expiry]"
touch -m -d "$expiry" $ZAF_CACHE_DIR/$key.info
cat $ZAF_CACHE_DIR/$key cat $ZAF_CACHE_DIR/$key
else else
rm $ZAF_CACHE_DIR/$key rm -f "$ZAF_CACHE_DIR/$key"
fi fi
} }
@ -60,6 +84,16 @@ zaf_cache_delentry(){
rm -f "$ZAF_CACHE_DIR/$key*" rm -f "$ZAF_CACHE_DIR/$key*"
} }
# List entries in cache
zaf_cache_list(){
local i
ls $ZAF_CACHE_DIR/*info >/dev/null 2>/dev/null || return 1
local key
for i in $ZAF_CACHE_DIR/*info; do
cat $i
done
}
# Get object from cache # Get object from cache
# $1 key # $1 key
zaf_fromcache(){ zaf_fromcache(){
@ -68,6 +102,7 @@ zaf_fromcache(){
local value local value
key=$(zaf_cache_key "$1") key=$(zaf_cache_key "$1")
if [ -f $ZAF_CACHE_DIR/$key ]; then if [ -f $ZAF_CACHE_DIR/$key ]; then
! [ -f "$ZAF_CACHE_DIR/$key.info" ] && { return 3; }
if [ "$ZAF_CACHE_DIR/$key.info" -nt "$ZAF_CACHE_DIR/$key" ]; then if [ "$ZAF_CACHE_DIR/$key.info" -nt "$ZAF_CACHE_DIR/$key" ]; then
zaf_trc "Cache: serving $1($key) from cache" zaf_trc "Cache: serving $1($key) from cache"
cat $ZAF_CACHE_DIR/$key cat $ZAF_CACHE_DIR/$key

View File

@ -27,7 +27,7 @@ zaf_ctrl_get_extitem_block() {
# Get item body from stdin # Get item body from stdin
# $1 itemname # $1 itemname
zaf_ctrl_get_item_block() { zaf_ctrl_get_item_block() {
grep -v '^#' | awk '/^Item '$1'/ { i=0; grep -vE '^#[a-zA-Z ]' | awk '/^Item '$1'/ { i=0;
while (i==0) { while (i==0) {
getline; getline;
if (/^\/Item/) exit; if (/^\/Item/) exit;
@ -42,7 +42,7 @@ zaf_ctrl_get_item_block() {
# Get global plugin block body from stdin # Get global plugin block body from stdin
# $1 itemname # $1 itemname
zaf_ctrl_get_global_block() { zaf_ctrl_get_global_block() {
grep -v '^#' | awk '{ i=0; print $0; grep -vE '^#[a-zA-Z ]' | awk '{ i=0; print $0;
while (i==0) { while (i==0) {
getline; getline;
if (/^(Item |ExtItem)/) exit; if (/^(Item |ExtItem)/) exit;
@ -156,6 +156,7 @@ zaf_ctrl_sudo() {
pdir="$3" pdir="$3"
plugin=$1 plugin=$1
! [ -d "$ZAF_SUDOERSD" ] && { zaf_wrn "$ZAF_SUDOERSD nonexistent! Skipping sudo install!"; return 1; }
zaf_dbg "Installing sudoers entry $ZAF_SUDOERSD/zaf_$plugin" zaf_dbg "Installing sudoers entry $ZAF_SUDOERSD/zaf_$plugin"
sudo=$(zaf_ctrl_get_global_option $2 "Sudo" | zaf_far '{PLUGINDIR}' "${plugindir}") sudo=$(zaf_ctrl_get_global_option $2 "Sudo" | zaf_far '{PLUGINDIR}' "${plugindir}")
[ -z "$sudo" ] && return # Nothing to install [ -z "$sudo" ] && return # Nothing to install
@ -183,6 +184,7 @@ zaf_ctrl_cron() {
pdir="$3" pdir="$3"
plugin=$1 plugin=$1
! [ -d "$ZAF_CROND" ] && { zaf_wrn "$ZAF_CROND nonexistent! Skipping cron install!"; return 1; }
zaf_dbg "Installing cron entry $ZAF_CROND/zaf_$plugin" zaf_dbg "Installing cron entry $ZAF_CROND/zaf_$plugin"
cron=$(zaf_ctrl_get_global_option $2 "Cron") cron=$(zaf_ctrl_get_global_option $2 "Cron")
[ -z "$cron" ] && return # Nothing to install [ -z "$cron" ] && return # Nothing to install
@ -229,48 +231,62 @@ zaf_ctrl_generate_items_cfg() {
local ikey local ikey
local lock local lock
local cache local cache
local tmpfile
local pname
local pdefault
local pregex
local prest
local zafparms
items=$(zaf_ctrl_get_items <"$1") items=$(zaf_ctrl_get_items <"$1")
tmpfile=$ZAF_TMP_DIR/gencfg$$
(set -e (set -e
for i in $items; do for i in $items; do
iscript=$(zaf_stripctrl $i) iscript=$(zaf_stripctrl $i)
params=$(zaf_ctrl_get_item_option $1 $i "Parameters") zaf_ctrl_get_item_option $1 $i "Parameters" >$tmpfile
if [ -n "$params" ]; then if [ -s "$tmpfile" ]; then
ikey="$2.$i[*]" ikey="$2.$i[*]"
args="" args=""
apos=1; apos=1;
for p in $params; do while read pname pdefault pregex prest; do
zafparams="$zafparams value=\"\$$apos\"; zaf_agentparm $pname $pdefault $pregex; export $pname; "
args="$args \$$apos" args="$args \$$apos"
apos=$(expr $apos + 1) apos=$(expr $apos + 1)
done done <$tmpfile
else else
ikey="$2.$i" ikey="$2.$i"
zafparams=""
args=""
fi fi
env="export ITEM_KEY='$ikey'; export PLUGIN='$2'; export PATH=${ZAF_PLUGINS_DIR}/$2:$ZAF_LIB_DIR:\$PATH; cd ${ZAF_PLUGINS_DIR}/$2; . $ZAF_LIB_DIR/preload.sh; "
lock=$(zaf_ctrl_get_item_option $1 $i "Lock") lock=$(zaf_ctrl_get_item_option $1 $i "Lock")
if [ -n "$lock" ]; then if [ -n "$lock" ]; then
lock="${ZAF_LIB_DIR}/zaflock $lock " lock="${ZAF_LIB_DIR}/zaflock $lock "
fi fi
cache=$(zaf_ctrl_get_item_option $1 $i "Cache") cache=$(zaf_ctrl_get_item_option $1 $i "Cache")
if [ -n "$cache" ]; then if [ -n "$cache" ]; then
cache="_cache '$cache' " cache="${ZAF_LIB_DIR}/zafcache '$cache' "
fi fi
cmd=$(zaf_ctrl_get_item_option $1 $i "Cmd") cmd=$(zaf_ctrl_get_item_option $1 $i "Cmd")
if [ -n "$cmd" ]; then if [ -n "$cmd" ]; then
$(which echo) "UserParameter=$ikey,${ZAF_LIB_DIR}/preload.sh $cache $lock$cmd"; printf "%s" "UserParameter=$ikey,${env}${zafparams}${preload}${cache}${lock}${cmd}"; echo
continue continue
fi fi
cmd=$(zaf_ctrl_get_item_option $1 $i "Script") cmd=$(zaf_ctrl_get_item_option $1 $i "Script")
if [ -n "$cmd" ]; then if [ -n "$cmd" ]; then
zaf_ctrl_get_item_option $1 $i "Script" | \ ( echo "#!/bin/sh"
zaf_far '{INCLUDES}' '. /etc/zaf.conf; . ${ZAF_LIB_DIR}/zaf.lib.sh; . ${ZAF_LIB_DIR}/ctrl.lib.sh; . ${ZAF_LIB_DIR}/zbxapi.lib.sh; . ${ZAF_LIB_DIR}/cache.lib.sh; ' \ echo ". $ZAF_LIB_DIR/preload.sh; "
>${ZAF_TMP_DIR}/${iscript}.sh; zaf_ctrl_get_item_option $1 $i "Script"
zaf_install_bin ${ZAF_TMP_DIR}/${iscript}.sh ${ZAF_PLUGINS_DIR}/$2/ ) >${ZAF_TMP_DIR}/${iscript}.sh;
$(which echo) "UserParameter=$ikey,$cache $lock${ZAF_PLUGINS_DIR}/$2/${iscript}.sh $args"; [ -z "$3" ] && zaf_install_bin ${ZAF_TMP_DIR}/${iscript}.sh ${ZAF_PLUGINS_DIR}/$2/
printf "%s" "UserParameter=$ikey,${env}${preload}${zafparams}${cache}${lock}${ZAF_PLUGINS_DIR}/$2/${iscript}.sh ${args}"; echo
rm -f ${ZAF_TMP_DIR}/${iscript}.sh
continue; continue;
fi fi
zaf_err "Item $i declared in control file but has no Cmd, Function or Script!" zaf_err "Item $i declared in control file but has no Cmd, Function or Script!"
done done
) || zaf_err "Error during zaf_ctrl_generate_items_cfg" ) || zaf_err "Error during zaf_ctrl_generate_items_cfg"
rm -f $tmpfile
} }
# Generates zabbix cfg for external items from control file # Generates zabbix cfg for external items from control file

View File

@ -1,12 +1,15 @@
# Os related functions # Os related functions
zaf_configure_os_openwrt() { zaf_configure_os_openwrt() {
ZAF_AGENT_RESTART="/etc/init.d/zabbix_agentd restart" ZAF_AGENT_RESTART="zaf agent-config ; /etc/init.d/zabbix_agentd restart"
ZAF_AGENT_CONFIGD="/var/run/zabbix_agentd.conf.d/" ZAF_AGENT_CONFIGD="/var/run/zabbix_agentd.conf.d/"
ZAF_AGENT_CONFIG="/etc/zabbix_agentd.conf" ZAF_AGENT_CONFIG="/etc/zabbix_agentd.conf"
ZAF_AGENT_PKG="zabbix-agentd" ZAF_AGENT_PKG="zabbix-agentd"
ZAF_CURL_INSECURE=1 ZAF_CURL_INSECURE=1
} }
zaf_configure_os_beesip() {
zaf_configure_os_openwrt
}
zaf_configure_os_freebsd() { zaf_configure_os_freebsd() {
ZAF_AGENT_PKG="zabbix3-agent" ZAF_AGENT_PKG="zabbix3-agent"
@ -14,9 +17,13 @@ zaf_configure_os_freebsd() {
ZAF_AGENT_CONFIGD="/usr/local/etc/zabbix3/zabbix_agentd.conf.d/" ZAF_AGENT_CONFIGD="/usr/local/etc/zabbix3/zabbix_agentd.conf.d/"
ZAF_AGENT_BIN="/usr/local/sbin/zabbix_agentd" ZAF_AGENT_BIN="/usr/local/sbin/zabbix_agentd"
ZAF_AGENT_RESTART="service zabbix_agentd restart" ZAF_AGENT_RESTART="service zabbix_agentd restart"
ZAF_SUDOERSD="/usr/local/etc/sudoers.d"
} }
zaf_detect_system() { zaf_detect_system() {
ZAF_FILES_UID=zabbix
ZAF_FILES_GID=zabbix
ZAF_FILES_UMASK=0770
if which dpkg >/dev/null; then if which dpkg >/dev/null; then
ZAF_PKG=dpkg ZAF_PKG=dpkg
ZAF_OS=$(lsb_release -is|zaf_tolower) ZAF_OS=$(lsb_release -is|zaf_tolower)

296
lib/plugin.lib.sh Normal file
View File

@ -0,0 +1,296 @@
# Plugin related functions
# Update repo
zaf_update_repo() {
[ "$ZAF_GIT" != 1 ] && { zaf_err "Git is disabled or is not installed. Exiting."; }
if [ -z "${ZAF_REPO_GITURL}" ] || [ -z "${ZAF_REPO_DIR}" ]; then
zaf_err "This system is not configured for git repository."
else
[ ! -d "${ZAF_REPO_DIR}" ] && git clone "${ZAF_REPO_GITURL}" "${ZAF_REPO_DIR}"
(cd ${ZAF_REPO_DIR} && git pull)
fi
}
# Construct url from plugin name
# It can be http[s]://url
# /path (from file)
# name (to try from repo)
zaf_get_plugin_url() {
local url
if echo "$1" | grep -q '/'; then
url="$1" # plugin with path - from directory
else
if echo "$1" | grep -q ^http; then
url="$1" # plugin with http[s] url
else
if [ -d "${ZAF_REPO_DIR}/$1" ]; then
url="${ZAF_REPO_DIR}/$1"
else
if [ -n "${ZAF_PREPACKAGED_DIR}" ] && [ -d "${ZAF_PREPACKAGED_DIR}/$1" ]; then
url="${ZAF_PREPACKAGED_DIR}/$1"
else
if [ -n "${ZAF_REPO_URL}" ]; then
url="${ZAF_REPO_URL}/$1"
else
zaf_err "Cannot find plugin $1"
fi
fi
fi
fi
fi
echo $url
}
# $1 - control
zaf_plugin_info() {
local control="$1"
local items
! [ -f "$control" ] && zaf_err "Control file $control not found."
plugin=$(zaf_ctrl_get_global_block <"${control}" | zaf_block_get_option Plugin)
pdescription=$(zaf_ctrl_get_global_block <"${control}" | zaf_block_get_moption Description)
pmaintainer=$(zaf_ctrl_get_global_block <"${control}" | zaf_block_get_option Maintainer)
pversion=$(zaf_ctrl_get_global_block <"${control}" | zaf_block_get_option Version)
purl=$(zaf_ctrl_get_global_block <"${control}" | zaf_block_get_option Url)
phome=$(zaf_ctrl_get_global_block <"${control}" | zaf_block_get_option Home)
pitems=$(zaf_ctrl_get_items <"${control}")
echo
echo -n "Plugin '$plugin' "; [ -n "$pversion" ] && echo -n "version ${pversion}"; echo ":"
echo "$pdescription"; echo
[ -n "$pmaintainer" ] && echo "Maintainer: $pmaintainer"
[ -n "$purl" ] && echo "Url: $purl"
[ -n "$phome" ] && echo "Home: $phome"
echo
if zaf_is_plugin "$(basename $plugin)"; then
items=$(zaf_list_plugin_items $plugin)
[ -n "$items" ] && echo -n "Defined items: "; echo $items
items=$(zaf_list_plugin_items $plugin test)
[ -n "$items" ] && echo -n "Test items: "; echo $items
items=$(zaf_list_plugin_items $plugin precache)
[ -n "$items" ] && echo -n "Precache items: "; echo $items
else
echo "Items: $pitems"
fi
echo
}
# Prepare plugin into dir
# $1 is url, directory or plugin name (will be searched in default plugin dir).
# $2 is directory to prepare.
zaf_prepare_plugin() {
local url
local plugindir
local control
url=$(zaf_get_plugin_url "$1")/control.zaf || exit $?
plugindir="$2"
control=${plugindir}/control.zaf
zaf_install_dir "$plugindir"
zaf_dbg "Fetching control file from $url ..."
if zaf_fetch_url "$url" >"${control}"; then
zaf_ctrl_check_deps "${control}"
else
zaf_err "prepare_plugin: Cannot fetch or write control file $control from url $url!"
fi
}
zaf_install_plugin() {
local url
local plugin
local plugindir
local control
local version
if zaf_prepare_plugin "$1" "${ZAF_TMP_DIR}/plugin"; then
url=$(zaf_get_plugin_url "$1")
control="${ZAF_TMP_DIR}/plugin/control.zaf"
plugin=$(zaf_ctrl_get_global_option $control Plugin)
version=$(zaf_ctrl_get_global_option $control Version)
plugindir="${ZAF_PLUGINS_DIR}"/$plugin
if [ -n "$plugin" ] && zaf_prepare_plugin "$1" $plugindir; then
zaf_wrn "Installing plugin $plugin version $version"
zaf_dbg "Source url: $url, Destination dir: $plugindir"
control=${plugindir}/control.zaf
[ "$ZAF_DEBUG" -gt 1 ] && zaf_plugin_info "${control}"
zaf_ctrl_check_deps "${control}"
zaf_ctrl_sudo "$plugin" "${control}" "${plugindir}"
zaf_ctrl_cron "$plugin" "${control}" "${plugindir}"
zaf_ctrl_generate_cfg "${control}" "${plugin}" \
| zaf_far '{PLUGINDIR}' "${plugindir}" >${ZAF_AGENT_CONFIGD}/zaf_${plugin}.conf
zaf_dbg "Generated ${ZAF_AGENT_CONFIGD}/zaf_${plugin}.conf"
zaf_ctrl_install "$url" "${control}" "${plugindir}"
else
zaf_err "Cannot install plugin '$plugin' to $plugindir!"
fi
else
zaf_err "Cannot prepare plugin $1"
fi
}
# List installed plugins
# $1 - plugin
zaf_list_plugins() {
local cfile
local plugin
ls -1 ${ZAF_PLUGINS_DIR} | while read p; do
zaf_is_plugin "$(basename $p)" && echo $p
done
}
zaf_is_plugin() {
[ -d "$ZAF_PLUGINS_DIR/$1" ] && [ -f "$ZAF_PLUGINS_DIR/$1/control.zaf" ] && return
false
}
zaf_discovery_plugins() {
zaf_list_plugins | zaf_discovery '{#PLUGIN}'
}
# $1 plugin
# $2 ctrl_option
zaf_plugin_option() {
local plugindir
local cfile
if [ -z "$1" ]; then
zaf_err "Missing plugin name.";
fi
if zaf_is_plugin "$1"; then
plugindir="${ZAF_PLUGINS_DIR}/$1"
cfile="$plugindir/control.zaf"
zaf_ctrl_get_global_option $cfile $2
else
zaf_err "Plugin $1 not installed."
fi
}
zaf_plugin_version() {
zaf_plugin_option "$1" Version
}
zaf_plugin_maintainer() {
zaf_plugin_option "$1" Maintainer
}
zaf_plugin_url() {
zaf_plugin_option "$1" Url
}
zaf_plugin_web() {
zaf_plugin_option "$1" Web
}
zaf_plugin_template_url() {
echo $(zaf_plugin_option "$1" Url)/template.xml
}
# $1 plugin
# $2 test to get test items, precache to get items to precache
zaf_list_plugin_items() {
local items
local i
local p
local key
local testparms
local precache
if ! zaf_is_plugin "$1"; then
zaf_err "Missing plugin name or plugin $1 unknown. ";
fi
plugindir="${ZAF_PLUGINS_DIR}/$1"
cfile="$plugindir/control.zaf"
items=$(zaf_ctrl_get_items <$cfile)
for i in $items; do
p=$(zaf_ctrl_get_item_option $cfile $i "Parameters")
testparms=$(zaf_ctrl_get_item_option $cfile $i "Testparameters")
precache=$(zaf_ctrl_get_item_option $cfile $i "Precache")
case $2 in
test)
for tp in $testparms; do
if [ -n "$p" ]; then
echo -n "$1.$i[$tp] "
else
echo -n "$1.$i "
fi
done
;;
precache)
for tp in $precache; do
echo -n "$1.$i[$tp] "
done
;;
*)
if [ -n "$p" ]; then
echo -n "$1.$i[] "
else
echo -n "$1.$i "
fi
;;
esac
done
echo
}
zaf_item_info() {
local plugin
local item
local param
plugin=$(echo $1 | cut -d '.' -f 1)
item=$(echo $1 | cut -d '.' -f 2-)
if zaf_is_plugin $plugin; then
if zaf_ctrl_get_items <$ZAF_PLUGINS_DIR/$plugin/control.zaf | grep -wq "$item"; then
echo "Item $1:"
echo -n "Cache: "; zaf_ctrl_get_item_option $ZAF_PLUGINS_DIR/$plugin/control.zaf "$item" "Cache"; echo
echo "Parameters:"
zaf_ctrl_get_item_option $ZAF_PLUGINS_DIR/$plugin/control.zaf "$item" "Parameters" ; echo
echo "Testparameters:"
zaf_ctrl_get_item_option $ZAF_PLUGINS_DIR/$plugin/control.zaf "$item" "Testparameters"; echo
echo "Precache:"
zaf_ctrl_get_item_option $ZAF_PLUGINS_DIR/$plugin/control.zaf "$item" "Precache"; echo
grep "UserParameter=$1" $ZAF_AGENT_CONFIGD/zaf_${plugin}.conf
else
zaf_err "No such item $item."
fi
else
zaf_err "No such plugin $plugin."
fi
}
zaf_list_items() {
for p in $(zaf_list_plugins); do
echo $p: $(zaf_list_plugin_items $p)
done
}
zaf_get_item() {
if which zabbix_get >/dev/null; then
zaf_trc zabbix_get -s localhost -k "'$1'"
(zabbix_get -s localhost -k "$1" | tr '\n' ' '; echo) || zaf_wrn "Cannot reach agent on localhost. Please localhost to Server list."
return 11
else
zaf_wrn "Please install zabbix_get binary to check items over network."
return 11
fi
}
zaf_test_item() {
zaf_trc $ZAF_AGENT_BIN -t "'$1'"
if $ZAF_AGENT_BIN -t "$1" | grep ZBX_NOTSUPPORTED; then
return 1
else
$ZAF_AGENT_BIN -t "$1" | tr '\n' ' '
echo
fi
}
zaf_precache_item() {
cmd=$(grep "^UserParameter=$item" $ZAF_AGENT_CONFIGD/zaf*.conf | cut -d ',' -f 2- | sed -e "s/_cache/_nocache/")
zaf_wrn "Precaching item $item[$(echo $*| tr ' ' ',')] ($cmd)"
eval $cmd
}
zaf_remove_plugin() {
! zaf_is_plugin $1 && { zaf_err "Plugin $1 not installed!"; }
zaf_wrn "Removing plugin $1 (version $(zaf_plugin_version $1))"
rm -rf ${ZAF_PLUGINS_DIR}/$1
rm -f ${ZAF_AGENT_CONFIGD}/zaf_$1.conf ${ZAF_CROND}/zaf_$1 ${ZAF_SUDOERSD}/zaf_$1
}

View File

@ -2,36 +2,36 @@
. /etc/zaf.conf . /etc/zaf.conf
[ -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}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}/zaf.lib.sh
. ${ZAF_LIB_DIR}/plugin.lib.sh
. ${ZAF_LIB_DIR}/ctrl.lib.sh . ${ZAF_LIB_DIR}/ctrl.lib.sh
. ${ZAF_LIB_DIR}/os.lib.sh . ${ZAF_LIB_DIR}/os.lib.sh
. ${ZAF_LIB_DIR}/zbxapi.lib.sh . ${ZAF_LIB_DIR}/zbxapi.lib.sh
. ${ZAF_LIB_DIR}/cache.lib.sh . ${ZAF_LIB_DIR}/cache.lib.sh
# Plugin specific functions if exists
[ -f ./functions.sh ] && . ./functions.sh
if ! type zaf_version >/dev/null; then
echo "Problem loading libraries?"
exit 2
fi
zaf_debug_init
zaf_tmp_init
zaf_cache_init
export ZAF_LIB_DIR export ZAF_LIB_DIR
export ZAF_TMP_DIR export ZAF_TMP_DIR
export ZAF_CACHE_DIR
export ZAF_PLUGINS_DIR export ZAF_PLUGINS_DIR
export ZAF_DEBUG
unset ZAF_LOG_STDERR
export PATH
if [ "$1" = "_cache" ] || [ "$1" = "_nocache" ] ; then if [ "$(basename $0)" = "preload.sh" ] && [ -n "$*" ]; then
[ "$1" = "_nocache" ] && export ZAF_NOCACHE=1 tmpf=$(zaf_tmpfile preload)
shift $@ 2>$tmpf
seconds=$1 [ -s $tmpf ] && zaf_wrn <$tmpf
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 fi

View File

@ -11,17 +11,17 @@ zaf_msg() {
echo $@ echo $@
} }
zaf_trc() { zaf_trc() {
[ "$ZAF_DEBUG" -ge "3" ] && logger -s -t zaf -- $@ [ "$ZAF_DEBUG" -ge "3" ] && logger -p user.info ${ZAF_LOG_STDERR} -t zaf-trace -- $@
} }
zaf_dbg() { zaf_dbg() {
[ "$ZAF_DEBUG" -ge "2" ] && logger -s -t zaf -- $@ [ "$ZAF_DEBUG" -ge "2" ] && logger -p user.debug ${ZAF_LOG_STDERR} -t zaf-debug -- $@
} }
zaf_wrn() { zaf_wrn() {
[ "$ZAF_DEBUG" -ge "1" ] && logger -s -t zaf -- $@ [ "$ZAF_DEBUG" -ge "1" ] && logger -p user.warn ${ZAF_LOG_STDERR} -t zaf-warning -- $@
} }
zaf_err() { zaf_err() {
logger -s -t zaf -- $@ logger ${ZAF_LOG_STDERR} -p user.err -t zaf-error -- $@
logger -s -t zaf "Exiting with error!" logger ${ZAF_LOG_STDERR} -p user.err -t zaf-error "Exiting with error!"
exit 1 exit 1
} }
# Help option # Help option
@ -38,11 +38,47 @@ zaf_hlp() {
dl=$(expr $cols - $kl) dl=$(expr $cols - $kl)
printf %-${kl}s%-${dl}s%b "$1" "$2" "\n" printf %-${kl}s%-${dl}s%b "$1" "$2" "\n"
} }
# $1 if nonempty, log to stderr too
zaf_debug_init() {
[ -z "$ZAF_DEBUG" ] && ZAF_DEBUG=1
export ZAF_DEBUG
[ -n "$1" ] && export ZAF_LOG_STDERR="-s"
}
zaf_tmp_init() {
[ -z "$ZAF_TMP_DIR" ] && ZAF_TMP_DIR=/tmp/
! [ -w "$ZAF_TMP_DIR" ] && zaf_err "Tmp dir $ZAF_TMP_DIR is not writable."
}
zaf_version(){ zaf_version(){
echo $ZAF_VERSION echo $ZAF_VERSION
} }
# Add parameter for agent check
# $1 parameter name (will be set to var)
# $2 if nonempty, it is default value. If empty, parameter is mandatory
# $3 if nonempty, regexp to test
zaf_agentparm(){
local name
local default
local regexp
name="$1"
default="$2"
regexp="$3"
[ -z "$value" ] && [ -z "$default" ] && zaf_err "$ITEM_KEY: Missing mandatory parameter $name."
if [ -z "$value" ]; then
value="$default"
else
if [ -n "$regexp" ]; then
echo "$value" | grep -qE "$regexp" || zaf_err "$ITEM_KEY: Bad parameter '$name' value '$value' (not in regexp '$regexp')."
fi
fi
eval $name=$value
zaf_trc "$ITEM_KEY: Param $name set to $value"
}
# Fetch url to stdout # Fetch url to stdout
# $1 url # $1 url
# It supports real file, file:// and other schemes known by curl # It supports real file, file:// and other schemes known by curl
@ -457,10 +493,35 @@ zaf_strunescape() {
sed -e 's#\\\(['"$1"']\)#\1#g' sed -e 's#\\\(['"$1"']\)#\1#g'
} }
# Escape string on stdin # Escape string on stdin
# $1 - list of chars to escape # $1 - list of chars to escape
zaf_strescape() { zaf_strescape() {
sed -e 's#\(['"$1"']\)#\\\1#g' sed -e 's#\(['"$1"']\)#\\\1#g'
} }
# Add seconds to current date and return date in YYYY-MM-DD hh:mm:ss
# $1 seconds
zaf_date_add() {
date -d "$1 seconds" "+%Y-%m-%d %H:%M:%S" 2>/dev/null || date -d "$(expr $(date +%s) + $1)" -D %s "+%Y-%m-%d %H:%M:%S"
}
# Create temp file and return its name
# $1 prefix or empty
zaf_tmpfile() {
echo "$ZAF_TMP_DIR/tmp$1"
}
# return random number
zaf_random() {
hexdump -n 2 -e '/2 "%u"' /dev/urandom
}
# Emulate sudo
zaf_sudo() {
if zaf_is_root || ! which sudo >/dev/null 2>/dev/null; then
$@
else
sudo $@
fi
}

34
lib/zafcache Normal file
View File

@ -0,0 +1,34 @@
#!/bin/sh
. $(dirname $0)/preload.sh
help() {
zaf_err "$0 seconds cmd..."
}
seconds=$1
shift
[ -z "$*" ] && help
zaf_trc "zafcache($seconds): $ITEM_KEY,'$2' '$3' '$4' '$5' '$6' '$7' '$8' '$9'"
if [ -z "$ITEM_KEY" ]; then
key=$(echo $*|tr ' ' '_')
else
key="$(echo ${ITEM_KEY}|cut -d '[' -f 1)[$(shift; echo $*|tr ' ' ',')]"
fi
if ! zaf_fromcache "$key"; then
zaf_fromcache "$key" >/dev/null 2>/dev/null
[ $? -eq 3 ] && { zaf_err "Operation $key already in progress."; }
if which at >/dev/null 2>/dev/null; then
at -M now >/dev/null 2>/dev/null <<EOF
. $(dirname $0)/preload.sh; tmpf=\$(zaf_tmpfile cache); $@ 2>"\$tmpf" | zaf_tocache_stdin "$key" "$seconds" ; [ -s \$tmpf ] && zaf_wrn <\$tmpf
EOF
else
tmpf=$(zaf_tmpfile cache)
$@ 2>"$tmpf" | zaf_tocache_stdin "$key" "$seconds"
[ -s $tmpf ] && zaf_wrn <$tmpf
fi
fi

View File

@ -1,12 +1,9 @@
#!/bin/sh #!/bin/sh
. /etc/zaf.conf . $(dirname $0)/preload.sh
. ${ZAF_LIB_DIR}/zaf.lib.sh
help() { help() {
echo "$0 key cmd" zaf_err "$0 key cmd"
exit 2
} }
lkey="$1" lkey="$1"
@ -16,7 +13,7 @@ shift
[ -z "${ZAF_LOCK_SECONDS}" ] && seconds=5 [ -z "${ZAF_LOCK_SECONDS}" ] && seconds=5
[ -z "${ZAF_LOCK_FORCE}" ] && force=1 [ -z "${ZAF_LOCK_FORCE}" ] && force=1
lockfile="${ZAF_TMP_DIR}/zaflock_${lkey}" lockfile="/tmp/zaflock_${lkey}"
i=0 i=0
while [ -f "$lockfile" ] && [ $i -lt $seconds ]; do while [ -f "$lockfile" ] && [ $i -lt $seconds ]; do
sleep 1 sleep 1
@ -31,7 +28,6 @@ if [ -f "$lockfile" ] && [ -z "$force" ]; then
exit 1 exit 1
fi fi
touch "$lockfile" [ -n "$*" ] && $@ 2>"$lockfile"
[ -n "$*" ] && $@ [ -s "$lockfile" ] && zaf_wrn <"$lockfile"
rm -f "$lockfile"

View File

@ -3,45 +3,56 @@
# $1 - query string # $1 - query string
zaf_zbxapi_do() { zaf_zbxapi_do() {
local result local result
zaf_trc "Zabbix API: $1" local query
result=$(curl -s -f -L -X POST -H 'Content-Type: application/json-rpc' -d "$1" "$ZAF_ZBXAPI_URL") local tmpfile
if [ $? = 0 ] && echo $result | grep -q '"result":'; then
tmpfile=$ZAF_TMP_DIR/zapi$$
query="$1"
zaf_trc "Zabbix API: $query"
curl -s -f -L -X POST -H 'Content-Type: application/json-rpc' -d "$query" "$ZAF_ZBXAPI_URL" >$tmpfile
if [ $? = 0 ] && $ZAF_LIB_DIR/JSON.sh -b <$tmpfile | grep -q '"result"'; then
zaf_trc "API OK" zaf_trc "API OK"
echo $result cat $tmpfile
rm -f $tmpfile
else else
zaf_err "Error processing API request. ($?,$result)" zaf_err "Error processing API request. ($?,$tmpfile)"
fi fi
} }
# Call api function and cache results # Call api function and cache results
# $1 - query string # $1 - query string
zaf_zbxapi_do_cache() { zaf_zbxapi_do_cache() {
local result local result
local tmpfile
local query
query="$(echo $1 | tr '\n' ' ')"
tmpfile=$ZAF_TMP_DIR/zcapi$$
if ! zaf_fromcache "$1"; then if ! zaf_fromcache "$1"; then
result=$(zaf_zbxapi_do "$1") zaf_zbxapi_do "$1" >$tmpfile
[ -n "$result" ] && zaf_tocache "$1" "$result" 60 [ -s "$tmpfile" ] && cat $tmpfile | zaf_tocache_stdin "$query" 60
echo $result rm -f $tmpfile
fi fi
} }
# Extract result from JSON response # Extract one result from JSON response
zaf_zbxapi_getresult() { zaf_zbxapi_getresult() {
sed -e 's/\({"jsonrpc":"2.0","result":\)\(.*\),\("id":.*\)/\2/g' | sed -e 's/^\[\]$//' $ZAF_LIB_DIR/JSON.sh -b | grep '\["result"\]' | tr '\t' ' ' | cut -d ' ' -f 2-
} }
# Extract XML result from JSON response # Extract XML result from JSON response
zaf_zbxapi_getxml() { zaf_zbxapi_getxml() {
zaf_zbxapi_getresult | sed -e 's/{"jsonrpc":"2.0","result":"//' | sed -e 's/","id"\:1}//' | zaf_zbxapi_getstring | zaf_strunescape '<">/' zaf_zbxapi_getstring | zaf_strunescape '</">' | zaf_far '\\n' "\n"
} }
# Extract string from JSON response result # Extract string from JSON response result
zaf_zbxapi_getstring() { zaf_zbxapi_getstring() {
sed -e 's/^"//' -e 's/"$//' -e 's/\\n/'\\n'/g' zaf_zbxapi_getresult | sed -e 's/^"//' -e 's/"$//'
} }
# Extract value from JSON response result # Extract value from JSON response result
# $1 key # $1 key
zaf_zbxapi_getvalue() { zaf_zbxapi_getvalues() {
tr ',' '\n' | grep "\"$1\":" | cut -d '"' -f 4 $ZAF_LIB_DIR/JSON.sh -b | grep '\["result",.*,"'$1'"]' | tr '\t' ' ' | cut -d ' ' -f 2- | sed -e 's/^"//' -e 's/"$//'
} }
# Zabbix API related functions # Zabbix API related functions
@ -68,7 +79,7 @@ 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-) 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 fi
result=$(zaf_zbxapi_do_cache "$authstr") result=$(zaf_zbxapi_do_cache "$authstr")
ZAF_ZBXAPI_AUTH=$(echo $result |zaf_zbxapi_getresult| zaf_zbxapi_getstring) ZAF_ZBXAPI_AUTH=$(echo $result |zaf_zbxapi_getstring)
[ -z "$ZAF_ZBXAPI_AUTH" ] && zaf_err "Cannot login into API" [ -z "$ZAF_ZBXAPI_AUTH" ] && zaf_err "Cannot login into API"
zaf_dbg "Logged into zabbix API ($ZAF_ZBXAPI_AUTH)" zaf_dbg "Logged into zabbix API ($ZAF_ZBXAPI_AUTH)"
} }
@ -102,7 +113,7 @@ zaf_zbxapi_get_object() {
params='"params": {'$filter' "output":"'$output'"}'; params='"params": {'$filter' "output":"'$output'"}';
fi fi
str='{ "method": "'$obj'.get", "jsonrpc": "2.0", "auth": "'$ZAF_ZBXAPI_AUTH'",'$params', "id": "'$id'" }' str='{ "method": "'$obj'.get", "jsonrpc": "2.0", "auth": "'$ZAF_ZBXAPI_AUTH'",'$params', "id": "'$id'" }'
result=$(zaf_zbxapi_do_cache "$str" | zaf_zbxapi_getresult) result=$(zaf_zbxapi_do_cache "$str")
[ -z "$result" ] && zaf_dbg "API call result empty or error! ($str)" [ -z "$result" ] && zaf_dbg "API call result empty or error! ($str)"
echo $result echo $result
} }
@ -113,7 +124,7 @@ zaf_zbxapi_gethostgroupid() {
result=$(zaf_zbxapi_get_object "hostgroup" '"name": ["'$1'"]') result=$(zaf_zbxapi_get_object "hostgroup" '"name": ["'$1'"]')
[ -z "$result" ] && zaf_err "HostGroup $1 not found!" [ -z "$result" ] && zaf_err "HostGroup $1 not found!"
echo $result |zaf_zbxapi_getvalue groupid echo $result |zaf_zbxapi_getvalues groupid
} }
# $1 hostid # $1 hostid
@ -126,7 +137,7 @@ zaf_zbxapi_gethost() {
if [ -z "$2" ]; then if [ -z "$2" ]; then
echo $result echo $result
else else
echo $result |zaf_zbxapi_getvalue $2 echo $result |zaf_zbxapi_getvalues $2
fi fi
} }
@ -136,7 +147,7 @@ zaf_zbxapi_gethostid() {
result=$(zaf_zbxapi_get_object "host" '"host": ["'$1'"]') result=$(zaf_zbxapi_get_object "host" '"host": ["'$1'"]')
[ -z "$result" ] && zaf_err "Host $1 not found!" [ -z "$result" ] && zaf_err "Host $1 not found!"
echo $result |zaf_zbxapi_getvalue hostid echo $result |zaf_zbxapi_getvalues hostid
} }
# $1 hostname # $1 hostname
@ -149,7 +160,7 @@ zaf_zbxapi_gethostinventory() {
if [ -z "$2" ]; then if [ -z "$2" ]; then
echo $result echo $result
else else
echo $result |zaf_zbxapi_getvalue $2 echo $result |zaf_zbxapi_getvalues $2
fi fi
} }
@ -159,7 +170,7 @@ zaf_zbxapi_gettemplateid() {
result=$(zaf_zbxapi_get_object "template" '"host": ["'$1'"]') result=$(zaf_zbxapi_get_object "template" '"host": ["'$1'"]')
[ -z "$result" ] && zaf_err "Template $1 not found!" [ -z "$result" ] && zaf_err "Template $1 not found!"
echo $result |zaf_zbxapi_getvalue templateid echo $result |zaf_zbxapi_getvalues templateid
} }
# $1 templateid # $1 templateid
@ -172,7 +183,7 @@ zaf_zbxapi_gettemplate() {
if [ -z "$2" ]; then if [ -z "$2" ]; then
echo $result echo $result
else else
echo $result |zaf_zbxapi_getvalue $2 echo $result |zaf_zbxapi_getvalues $2
fi fi
} }
@ -182,7 +193,7 @@ zaf_zbxapi_gethostsingroup() {
result=$(zaf_zbxapi_get_object "host" '' '"groupids": ["'$1'"]') result=$(zaf_zbxapi_get_object "host" '' '"groupids": ["'$1'"]')
[ -z "$result" ] && zaf_wrn "No hosts in groupid '$1'" [ -z "$result" ] && zaf_wrn "No hosts in groupid '$1'"
echo $result | zaf_zbxapi_getvalue "hostid" echo $result | zaf_zbxapi_getvalues "hostid"
} }
# Get all hostids in system # Get all hostids in system
@ -190,7 +201,7 @@ zaf_zbxapi_gethostids() {
local result local result
result=$(zaf_zbxapi_get_object "host") result=$(zaf_zbxapi_get_object "host")
echo $result | zaf_zbxapi_getvalue "hostid" echo $result | zaf_zbxapi_getvalues "hostid"
} }
# Get all templateids in system # Get all templateids in system
@ -198,7 +209,7 @@ zaf_zbxapi_gettemplateids() {
local result local result
result=$(zaf_zbxapi_get_object "template") result=$(zaf_zbxapi_get_object "template")
echo $result | zaf_zbxapi_getvalue "templateid" echo $result | zaf_zbxapi_getvalues "templateid"
} }
# $1 hostgroupid # $1 hostgroupid
@ -207,7 +218,7 @@ zaf_zbxapi_gettemplatesingroup() {
result=$(zaf_zbxapi_get_object "template" '' '"groupids": ["'$1'"]') result=$(zaf_zbxapi_get_object "template" '' '"groupids": ["'$1'"]')
[ -z "$result" ] && zaf_wrn "No templates in groupid '$1'" [ -z "$result" ] && zaf_wrn "No templates in groupid '$1'"
echo $result | zaf_zbxapi_getvalue "templateid" echo $result | zaf_zbxapi_getvalues "templateid"
} }
# $1 map or null for all # $1 map or null for all
@ -220,7 +231,7 @@ zaf_zbxapi_getmapid() {
result=$(zaf_zbxapi_get_object "map") result=$(zaf_zbxapi_get_object "map")
fi fi
[ -z "$result" ] && zaf_err "Map $1 not found" [ -z "$result" ] && zaf_err "Map $1 not found"
echo $result | zaf_zbxapi_getvalue "sysmapid" echo $result | zaf_zbxapi_getvalues "sysmapid"
} }
# $1 mapid # $1 mapid
@ -233,7 +244,7 @@ zaf_zbxapi_getmap() {
if [ -z "$2" ]; then if [ -z "$2" ]; then
echo $result echo $result
else else
echo $result |zaf_zbxapi_getvalue $2 echo $result |zaf_zbxapi_getvalues $2
fi fi
} }

116
zaf
View File

@ -25,25 +25,9 @@ ZAF_CFG_FILE="/etc/zaf.conf"
[ -n "$secondstage" ] && exec $0 $params [ -n "$secondstage" ] && exec $0 $params
fi fi
[ -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}c
[ -z "$ZAF_DEBUG" ] && ZAF_DEBUG=1
export ZAF_DEBUG
# If debug is on, do not remove tmp dir
if [ "$ZAF_DEBUG" -le 3 ]; then
trap "rm -rif ${ZAF_TMP_DIR}" EXIT
fi
! [ -d "${ZAF_TMP_DIR}" ] && mkdir "${ZAF_TMP_DIR}"
if ! [ -d "${ZAF_CACHE_DIR}" ]; then
mkdir "${ZAF_CACHE_DIR}"
fi
if [ -f ./lib/zaf.lib.sh ]; then if [ -f ./lib/zaf.lib.sh ]; then
. ./lib/zaf.lib.sh . ./lib/zaf.lib.sh
. ./lib/plugin.lib.sh
. ./lib/os.lib.sh . ./lib/os.lib.sh
. ./lib/ctrl.lib.sh . ./lib/ctrl.lib.sh
. ./lib/cache.lib.sh . ./lib/cache.lib.sh
@ -51,6 +35,7 @@ if [ -f ./lib/zaf.lib.sh ]; then
[ -f ./lib/zaf.${ZAF_OS}.sh ] && . ./lib/zaf.${ZAF_OS}.sh [ -f ./lib/zaf.${ZAF_OS}.sh ] && . ./lib/zaf.${ZAF_OS}.sh
else else
. ${ZAF_LIB_DIR}/zaf.lib.sh . ${ZAF_LIB_DIR}/zaf.lib.sh
. ${ZAF_LIB_DIR}/plugin.lib.sh
. ${ZAF_LIB_DIR}/os.lib.sh . ${ZAF_LIB_DIR}/os.lib.sh
. ${ZAF_LIB_DIR}/ctrl.lib.sh . ${ZAF_LIB_DIR}/ctrl.lib.sh
. ${ZAF_LIB_DIR}/cache.lib.sh . ${ZAF_LIB_DIR}/cache.lib.sh
@ -58,39 +43,46 @@ else
[ -f ${ZAF_LIB_DIR}/zaf.${ZAF_OS}.sh ] && . ${ZAF_LIB_DIR}/zaf.${ZAF_OS}.sh [ -f ${ZAF_LIB_DIR}/zaf.${ZAF_OS}.sh ] && . ${ZAF_LIB_DIR}/zaf.${ZAF_OS}.sh
fi fi
if zaf_is_root; then zaf_debug_init stderr
chgrp zabbix "${ZAF_CACHE_DIR}" zaf_tmp_init
chmod g+w "${ZAF_CACHE_DIR}" zaf_cache_init
fi
case $1 in case $1 in
check-agent-config)
zaf_check_agent_config
;;
cache-clean) cache-clean)
zaf_cache_clean zaf_cache_clean
;; ;;
cache-list)
zaf_cache_list
;;
version)
echo "$ZAF_VERSION<git $ZAF_GITBRANCH>"
[ $ZAF_DEBUG -gt 1 ] && set |grep -E ^ZAF_
;;
###### Agent related commands
userparms) userparms)
for plugin in $(zaf_list_plugins); do for plugin in $(zaf_list_plugins); do
plugindir=$ZAF_PLUGINS_DIR/$plugin plugindir=$ZAF_PLUGINS_DIR/$plugin
control=$plugindir/control.zaf control=$plugindir/control.zaf
zaf_ctrl_generate_cfg "${control}" "${plugin}" \ zaf_ctrl_generate_cfg "${control}" "${plugin}" "noscripts" \
| zaf_far '{PLUGINDIR}' "${plugindir}" | zaf_far '{PLUGINDIR}' "${plugindir}"
done done
;; ;;
agent-config) agent-config)
zaf_wrn "Generating config files in $ZAF_AGENT_CONFIGD ..."
for plugin in $(zaf_list_plugins); do for plugin in $(zaf_list_plugins); do
plugindir=$ZAF_PLUGINS_DIR/$plugin plugindir=$ZAF_PLUGINS_DIR/$plugin
control=$plugindir/control.zaf control=$plugindir/control.zaf
zaf_dbg "Generating ${ZAF_AGENT_CONFIGD}/zaf_${plugin}.conf"
zaf_ctrl_generate_cfg "${control}" "${plugin}" \ zaf_ctrl_generate_cfg "${control}" "${plugin}" \
| zaf_far '{PLUGINDIR}' "${plugindir}" >${ZAF_AGENT_CONFIGD}/zaf_${plugin}.conf | zaf_far '{PLUGINDIR}' "${plugindir}" >${ZAF_AGENT_CONFIGD}/zaf_${plugin}.conf
done done
;; ;;
###### Plugins related commands
update) update)
zaf_wrn "Updating repository ${ZAF_REPO_GITURL}..." zaf_wrn "Updating repository ${ZAF_REPO_GITURL}..."
zaf_update_repo zaf_update_repo
@ -105,23 +97,25 @@ show)
zaf_plugin_info $ZAF_PLUGINS_DIR/$plugin/control.zaf zaf_plugin_info $ZAF_PLUGINS_DIR/$plugin/control.zaf
done done
else else
if zaf_list_plugins | grep -q "^$1"; then if echo $1 | grep -vq "\."; then
[ -f $ZAF_PLUGINS_DIR/$1/control.zaf ] && zaf_plugin_info $ZAF_PLUGINS_DIR/$1/control.zaf || zaf_err "Plugin $1 not installed." if zaf_list_plugins | grep -q "^$1"; then
else zaf_is_plugin $1 && zaf_plugin_info $ZAF_PLUGINS_DIR/$1/control.zaf || zaf_err "Plugin $1 not installed."
if echo $1 |grep -q ^http; then
zaf_prepare_plugin "$1" "$ZAF_TMP_DIR/plugin"
zaf_plugin_info "$ZAF_TMP_DIR/plugin/control.zaf"
else else
zaf_err "Plugin $1 not installed." if echo $1 |grep -q ^http; then
zaf_prepare_plugin "$1" "$ZAF_TMP_DIR/plugin"
zaf_plugin_info "$ZAF_TMP_DIR/plugin/control.zaf"
else
zaf_err "Plugin $1 not installed."
fi
fi fi
else
zaf_item_info "$1"
fi fi
fi fi
;; ;;
plugins) plugins)
zaf_list_plugins zaf_list_plugins
;; ;;
items) items)
shift shift
if [ -z "$1" ]; then if [ -z "$1" ]; then
@ -130,7 +124,6 @@ items)
zaf_list_plugin_items "$1" zaf_list_plugin_items "$1"
fi fi
;; ;;
test) test)
[ "$USER" != "zabbix" ] && zaf_wrn "You are not zabbix user. Test will be run with your privileges and sudo access!" [ "$USER" != "zabbix" ] && zaf_wrn "You are not zabbix user. Test will be run with your privileges and sudo access!"
shift shift
@ -146,7 +139,7 @@ test)
for p in $plugins; do for p in $plugins; do
! zaf_is_plugin $p && zaf_err "Unknown plugin $p" ! zaf_is_plugin $p && zaf_err "Unknown plugin $p"
for i in $(zaf_list_plugin_items $p test); do for i in $(zaf_list_plugin_items $p test); do
echo $i: $(zaf_test_item $i) zaf_test_item $i
echo echo
done done
done done
@ -169,7 +162,6 @@ get)
done done
done done
;; ;;
precache) precache)
shift shift
for i in $*; do for i in $*; do
@ -186,7 +178,6 @@ precache)
fi fi
done done
;; ;;
install) install)
shift shift
[ -z "$1" ] && echo "$0 install plugin [plugin]..." [ -z "$1" ] && echo "$0 install plugin [plugin]..."
@ -200,7 +191,6 @@ install)
done done
[ -n "$installed" ] && zaf_is_root && zaf_restart_agent [ -n "$installed" ] && zaf_is_root && zaf_restart_agent
;; ;;
reinstall) reinstall)
shift shift
[ -z "$1" ] && echo "$0 reinstall plugin [plugin]..." [ -z "$1" ] && echo "$0 reinstall plugin [plugin]..."
@ -214,7 +204,6 @@ reinstall)
done done
[ -n "$reinstalled" ] && zaf_is_root && zaf_restart_agent [ -n "$reinstalled" ] && zaf_is_root && zaf_restart_agent
;; ;;
remove) remove)
shift shift
[ -z "$1" ] && echo "$0 remove plugin [plugin]..." [ -z "$1" ] && echo "$0 remove plugin [plugin]..."
@ -227,11 +216,11 @@ remove)
[ -n "$removed" ] && zaf_is_root && zaf_restart_agent [ -n "$removed" ] && zaf_is_root && zaf_restart_agent
;; ;;
###### Zaf related commands
self-upgrade) self-upgrade)
shift shift
[ -z "$1" ] && auto=auto [ -z "$1" ] && auto=auto
zaf_os_specific zaf_check_deps zaf && zaf_err "Zaf is installed as system package. Cannot self-upgrade." zaf_os_specific zaf_check_deps zaf && zaf_err "Zaf is installed as system package. Cannot self-upgrade."
rm -rf /tmp/zaf-installer && mkdir /tmp/zaf-installer
if ! which curl >/dev/null; if ! which curl >/dev/null;
then then
zaf_err "Curl not found. Cannot continue. Please install it." zaf_err "Curl not found. Cannot continue. Please install it."
@ -239,7 +228,6 @@ self-upgrade)
zaf_fetch_url $ZAF_RAW_URL/$ZAF_GITBRANCH/install.sh | exec sh -s $auto "$@" zaf_fetch_url $ZAF_RAW_URL/$ZAF_GITBRANCH/install.sh | exec sh -s $auto "$@"
exit exit
;; ;;
self-remove) self-remove)
shift shift
zaf_os_specific zaf_check_deps zaf && zaf_err "Zaf is installed as system package. Cannot self-remove." zaf_os_specific zaf_check_deps zaf && zaf_err "Zaf is installed as system package. Cannot self-remove."
@ -256,7 +244,7 @@ self-remove)
echo "To continue, please do $0 self-remove force" echo "To continue, please do $0 self-remove force"
fi fi
;; ;;
###### API related commands
api) api)
zaf_zbxapi_login zaf_zbxapi_login
case $2 in case $2 in
@ -281,8 +269,13 @@ api)
fi fi
;; ;;
get-inventory) get-inventory)
[ -z "$3" ] && zaf_err "$0 $1 <host> [field]" [ -z "$3" ] && zaf_err "$0 $1 field [host]. If host unspecified, use hostname"
zaf_zbxapi_gethostinventory $3 $4 if [ -z "$4" ]; then
host=$(hostname)
else
host="$4"
fi
zaf_zbxapi_gethostinventory $host $3
;; ;;
get-template-ids) get-template-ids)
if [ -n "$3" ]; then if [ -n "$3" ]; then
@ -307,19 +300,19 @@ api)
shift shift
hosts=$(zaf_zbxapi_gethostsingroup $gid) hosts=$(zaf_zbxapi_gethostsingroup $gid)
else else
hosts=$(zaf_zbxapi_gethostid) hosts=$(zaf_zbxapi_gethostids)
fi fi
zaf_wrn "Will backup this hosts: $hosts" zaf_wrn "Will backup this hosts: $hosts"
zaf_wrn "Output dir: $dir" zaf_wrn "Output dir: $dir"
for h in $hosts; do for h in $hosts; do
if zaf_bglimit 5; then if zaf_bglimit 5; then
( (
hn=$(zaf_zbxapi_gethost $h) hn=$(zaf_zbxapi_gethost $h name)
zaf_wrn "Exporting host $hn($h)..." zaf_wrn "Exporting host $hn($h)..."
zaf_zbxapi_export_host $h >"$dir/$hn.xml" zaf_zbxapi_export_host $h >"$dir/$hn.xml"
) & ) &
else else
hn=$(zaf_zbxapi_gethost $h) hn=$(zaf_zbxapi_gethost $h name)
zaf_wrn "Exporting host $hn($h)..." zaf_wrn "Exporting host $hn($h)..."
zaf_zbxapi_export_host $h >"$dir/$hn.xml" zaf_zbxapi_export_host $h >"$dir/$hn.xml"
fi fi
@ -342,18 +335,18 @@ api)
shift; shift shift; shift
[ -z "$1" ] && zaf_err "$0 api export-templates dir" [ -z "$1" ] && zaf_err "$0 api export-templates dir"
dir="$1" dir="$1"
templates=$(zaf_zbxapi_gettemplateid) templates=$(zaf_zbxapi_gettemplateids)
zaf_wrn "Will backup this templates: $templates" zaf_wrn "Will backup this templates: $templates"
zaf_wrn "Output dir: $dir" zaf_wrn "Output dir: $dir"
for t in $templates; do for t in $templates; do
if zaf_bglimit 5; then if zaf_bglimit 5; then
( (
tn=$(zaf_zbxapi_gettemplate $t) tn=$(zaf_zbxapi_gettemplate $t name)
zaf_wrn "Exporting template $tn($t)..." zaf_wrn "Exporting template $tn($t)..."
zaf_zbxapi_export_template $t >"$dir/$tn.xml" zaf_zbxapi_export_template $t >"$dir/$tn.xml"
) & ) &
else else
tn=$(zaf_zbxapi_gettemplate $t) tn=$(zaf_zbxapi_gettemplate $t name)
zaf_wrn "Exporting template $tn($t)..." zaf_wrn "Exporting template $tn($t)..."
zaf_zbxapi_export_template $t >"$dir/$tn.xml" zaf_zbxapi_export_template $t >"$dir/$tn.xml"
fi fi
@ -366,20 +359,20 @@ api)
if [ -f "$ZAF_PLUGINS_DIR/$1/template.xml" ]; then if [ -f "$ZAF_PLUGINS_DIR/$1/template.xml" ]; then
template="$ZAF_PLUGINS_DIR/$1/template.xml" template="$ZAF_PLUGINS_DIR/$1/template.xml"
zaf_wrn "Importing template $template" zaf_wrn "Importing template $template"
zaf_zbxapi_import_template $template || zaf_err "Error importing template" zaf_zbxapi_import_config $template || zaf_err "Error importing template"
else else
url="$(zaf_plugin_option $1 Template)" url="$(zaf_plugin_option $1 Template)"
if [ -n "$url" ]; then if [ -n "$url" ]; then
zaf_fetch_url $url | zaf_zbxapi_import_template || zaf_err "Error importing template" zaf_fetch_url $url | zaf_zbxapi_import_config || zaf_err "Error importing template"
else else
url="$(zaf_plugin_option $1 Url)" url="$(zaf_plugin_option $1 Url)"
zaf_fetch_url $url/template.xml | zaf_zbxapi_import_template || zaf_err "Error importing template" zaf_fetch_url $url/template.xml | zaf_zbxapi_import_config || zaf_err "Error importing template"
fi fi
fi fi
else else
if [ -f $1 ]; then if [ -f $1 ]; then
zaf_wrn "Importing template $1" zaf_wrn "Importing template $1"
zaf_zbxapi_import_template $1 || zaf_err "Error importing template" zaf_zbxapi_import_config $1 || zaf_err "Error importing template"
else else
zaf_err "Unknown plugin $1!" zaf_err "Unknown plugin $1!"
fi fi
@ -391,14 +384,17 @@ api)
zaf_hlp "get-${i}-id $i" "Get $i id" zaf_hlp "get-${i}-id $i" "Get $i id"
zaf_hlp "get-byid-${i} id [property]" "Get $i property from id. Leave empty property for JSON" zaf_hlp "get-byid-${i} id [property]" "Get $i property from id. Leave empty property for JSON"
done done
zaf_hlp "get-inventory host [fields]" "Get inventory fields [or all fields]" zaf_hlp "get-inventory host [fields]" "Get inventory fields [or all fields]"
zaf_hlp "get-host-ids [hg]" "Get all hostids or hostids in group hg"
zaf_hlp "get-template-ids [hg]" "Get all templateids or templateids in group hg"
zaf_hlp "get-map-ids" "Get all mapids"
zaf_hlp "export-hosts dir [hg]" "Backup all hosts [in group hg] (get their config from zabbix and save to dir/hostname.xml)" zaf_hlp "export-hosts dir [hg]" "Backup all hosts [in group hg] (get their config from zabbix and save to dir/hostname.xml)"
zaf_hlp "export-host host" "Backup host (get config from zabbix to stdout)" zaf_hlp "export-host host" "Backup host (get config from zabbix to stdout)"
zaf_hlp "import-template {plugin|file}" "Import template for plugin or from file" zaf_hlp "import-template {plugin|file}" "Import template for plugin or from file"
zaf_hlp "export-template name" "Export template to stdout" zaf_hlp "export-template name" "Export template to stdout"
zaf_hlp "export-templates dir" "Export all template to dir" zaf_hlp "export-templates dir" "Export all template to dir"
echo echo
exit [ -n "$2" ] && zaf_err "Bad API command '$2'!"
;; ;;
esac esac
;; ;;
@ -433,7 +429,9 @@ api)
zaf_hlp "$0 self-upgrade" "To self-upgrade zaf" zaf_hlp "$0 self-upgrade" "To self-upgrade zaf"
zaf_hlp "$0 self-remove" "To self-remove zaf and its config" zaf_hlp "$0 self-remove" "To self-remove zaf and its config"
zaf_hlp "$0 cache-clean" "To remove all entries from cache" zaf_hlp "$0 cache-clean" "To remove all entries from cache"
zaf_hlp "$0 cache-list" "To show all entries in cache"
echo echo
[ -n "$1" ] && zaf_err "Bad command '$1'!"
;; ;;
esac esac