From 8188fdba937e2b2de5fed0cddbd7287cb5d1ab83 Mon Sep 17 00:00:00 2001 From: Lukas Macura Date: Mon, 4 Apr 2016 10:27:25 +0200 Subject: [PATCH 01/33] Repaired zabbix auto installation --- install.sh | 15 ++++++++++++--- lib/os.lib.sh | 19 ++++++++++++++----- lib/zaf.lib.sh | 8 ++++---- 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/install.sh b/install.sh index 341b88d..839fa93 100755 --- a/install.sh +++ b/install.sh @@ -99,9 +99,17 @@ zaf_getrest(){ # Set config option in zabbix agent # $1 option # $2 value -zaf_agent_set_option() { +# $3 if nonempty, do not remove opion from config, just add to the end +zaf_set_agent_option() { local option="$1" local value="$2" + if [ -n "$3" ]; then + if ! grep -q "^$1=$2" $ZAF_AGENT_CONFIG; then + zaf_dbg "Adding option $option to $ZAF_AGENT_CONFIG." + echo "$option=$value" >>$ZAF_AGENT_CONFIG + fi + return + fi if grep ^$option\= $ZAF_AGENT_CONFIG; then zaf_wrn "Moving option $option to zaf config part." sed -i "s/$option=/#$option=/" $ZAF_AGENT_CONFIG @@ -122,7 +130,7 @@ zaf_configure_agent() { echo $pair | grep -q '^Z\_' || continue # Skip non Z_ vars option=$(echo $pair|cut -d '=' -f 1|cut -d '_' -f 2) value=$(echo $pair|cut -d '=' -f 2-) - zaf_agent_set_option "$option" "$value" + zaf_set_agent_option "$option" "$value" done } @@ -228,6 +236,7 @@ reconf) install) zaf_configure auto zaf_configure_agent "$@" + zaf_set_agent_option "Include" "$ZAF_AGENT_CONFIGD" append rm -rif ${ZAF_TMP_DIR} mkdir -p ${ZAF_TMP_DIR} zaf_install_dir ${ZAF_LIB_DIR} @@ -245,7 +254,7 @@ install) if zaf_is_root; then [ "${ZAF_GIT}" -eq 1 ] && ${INSTALL_PREFIX}/${ZAF_BIN_DIR}/zaf update ${INSTALL_PREFIX}/${ZAF_BIN_DIR}/zaf reinstall zaf || zaf_err "Error installing zaf plugin." - if zaf_is_root && ! zaf_check_agent_config; then + if zaf_is_root && ! zaf_test_item zaf.framework_version; then echo "Something is wrong with zabbix agent config." echo "Ensure that zabbix_agentd reads ${ZAF_AGENT_CONFIG}" echo "and there is Include=${ZAF_AGENT_CONFIGD} directive inside." diff --git a/lib/os.lib.sh b/lib/os.lib.sh index fdb59f4..7433fe8 100644 --- a/lib/os.lib.sh +++ b/lib/os.lib.sh @@ -101,22 +101,31 @@ zaf_uninstall(){ # Automaticaly install agent on debian # For another os, create similar function (install_zabbix_centos) zaf_install_agent_debian() { - zaf_fetch_url "http://repo.zabbix.com/zabbix/3.0/debian/pool/main/z/zabbix-release/zabbix-release_3.0-1+${ZAF_CODENAME}_all.deb" >"/tmp/zaf-installer/zabbix-release_3.0-1+${ZAF_CODENAME}_all.deb" \ - && dpkg -i "/tmp/zaf-installer/zabbix-release_3.0-1+${ZAF_CODENAME}_all.deb" \ + zaf_fetch_url "http://repo.zabbix.com/zabbix/3.0/debian/pool/main/z/zabbix-release/zabbix-release_3.0-1+${ZAF_OS_CODENAME}_all.deb" >"/tmp/zaf-installer/zabbix-release_3.0-1+${ZAF_OS_CODENAME}_all.deb" \ + && dpkg -i "/tmp/zaf-installer/zabbix-release_3.0-1+${ZAF_OS_CODENAME}_all.deb" \ && apt-get update \ - && apt-get install $ZAF_AGENT_PKG + && apt-get install -y -q $ZAF_AGENT_PKG +} + +zaf_install_agent_opkg() { + opkg update && \ + opkg install $ZAF_AGENT_PKG } # Check if dpkg dependency is met # $* - packages zaf_check_deps_dpkg() { - dpkg-query -f '${Package}\n' -W $* >/dev/null + for i in $*; do + dpkg-query -f '${Status},${Package}\n' -W $* 2>/dev/null | grep -q "^install ok" + done } # Check if dpkg dependency is met # $* - packages zaf_check_deps_rpm() { - rpm --quiet -qi $* + for i in $*; do + rpm --quiet -qi $i | grep -q $i + done } # Check if dpkg dependency is met diff --git a/lib/zaf.lib.sh b/lib/zaf.lib.sh index 5b8d0ce..1100358 100644 --- a/lib/zaf.lib.sh +++ b/lib/zaf.lib.sh @@ -9,13 +9,13 @@ zaf_msg() { echo $@ } zaf_dbg() { - [ "$ZAF_DEBUG" -ge "2" ] && logger -s -t zaf $@ + [ "$ZAF_DEBUG" -ge "2" ] && logger -s -t zaf -- $@ } zaf_wrn() { - [ "$ZAF_DEBUG" -ge "1" ] && logger -s -t zaf $@ + [ "$ZAF_DEBUG" -ge "1" ] && logger -s -t zaf -- $@ } zaf_err() { - logger -s -t zaf $@ + logger -s -t zaf -- $@ logger -s -t zaf "Exiting with error!" exit 1 } @@ -40,7 +40,7 @@ zaf_fetch_url() { case $scheme in http|https|ftp|file) [ "${ZAF_CURL_INSECURE}" = "1" ] && insecure="-k" - zaf_msg curl $insecure -f -s -L -o - "$1" + zaf_dbg curl $insecure -f -s -L -o - $1 curl $insecure -f -s -L -o - "$1" ;; esac From f0988cf5ee50abdedbeb8c1f72fc7d69f7f5e056 Mon Sep 17 00:00:00 2001 From: Lukas Macura Date: Mon, 4 Apr 2016 14:00:44 +0200 Subject: [PATCH 02/33] Repaired bugs --- install.sh | 6 +++--- lib/ctrl.lib.sh | 14 ++++++++++---- lib/preload.sh | 3 ++- lib/zaf.lib.sh | 13 ++++++++++++- zaf | 9 +++++---- 5 files changed, 32 insertions(+), 13 deletions(-) diff --git a/install.sh b/install.sh index 839fa93..8ebced0 100755 --- a/install.sh +++ b/install.sh @@ -162,7 +162,7 @@ zaf_configure(){ zaf_get_option ZAF_LIB_DIR "Libraries directory" "/usr/lib/zaf" "$1" zaf_get_option ZAF_BIN_DIR "Directory to put binaries" "/usr/bin" "$1" zaf_get_option ZAF_PLUGINS_DIR "Plugins directory" "${ZAF_LIB_DIR}/plugins" "$1" - [ "${ZAF_GIT}" -eq 1 ] && zaf_get_option ZAF_PLUGINS_GITURL "Git plugins repository" "https://github.com/limosek/zaf-plugins.git" "$1" + [ "${ZAF_GIT}" = 1 ] && zaf_get_option ZAF_PLUGINS_GITURL "Git plugins repository" "https://github.com/limosek/zaf-plugins.git" "$1" zaf_get_option ZAF_PLUGINS_URL "Plugins http[s] repository" "https://raw.githubusercontent.com/limosek/zaf-plugins/master/" "$1" zaf_get_option ZAF_REPO_DIR "Plugins directory" "${ZAF_LIB_DIR}/repo" "$1" zaf_get_option ZAF_AGENT_CONFIG "Zabbix agent config" "/etc/zabbix/zabbix_agentd.conf" "$1" @@ -191,7 +191,7 @@ zaf_configure(){ zaf_set_option ZAF_BIN_DIR "$ZAF_BIN_DIR" zaf_set_option ZAF_PLUGINS_DIR "$ZAF_PLUGINS_DIR" zaf_set_option ZAF_PLUGINS_URL "$ZAF_PLUGINS_URL" - [ "${ZAF_GIT}" -eq 1 ] && zaf_set_option ZAF_PLUGINS_GITURL "$ZAF_PLUGINS_GITURL" + [ "${ZAF_GIT}" = 1 ] && zaf_set_option ZAF_PLUGINS_GITURL "$ZAF_PLUGINS_GITURL" zaf_set_option ZAF_REPO_DIR "$ZAF_REPO_DIR" zaf_set_option ZAF_AGENT_CONFIG "$ZAF_AGENT_CONFIG" zaf_set_option ZAF_AGENT_CONFIGD "$ZAF_AGENT_CONFIGD" @@ -252,7 +252,7 @@ install) zaf_install_bin $(zaf_getrest zaf) ${ZAF_BIN_DIR} export INSTALL_PREFIX ZAF_CFG_FILE if zaf_is_root; then - [ "${ZAF_GIT}" -eq 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." if zaf_is_root && ! zaf_test_item zaf.framework_version; then echo "Something is wrong with zabbix agent config." diff --git a/lib/ctrl.lib.sh b/lib/ctrl.lib.sh index c6b615c..1f05abd 100644 --- a/lib/ctrl.lib.sh +++ b/lib/ctrl.lib.sh @@ -119,6 +119,12 @@ zaf_ctrl_generate_cfg() { params=$(zaf_ctrl_get_item_option $1 $i "Parameters") if [ -n "$params" ]; then ikey="$2.$i[*]" + args="" + apos=1; + for p in $params; do + args="$args \$$apos" + apos=$(expr $apos + 1) + done else ikey="$2.$i" fi @@ -128,19 +134,19 @@ zaf_ctrl_generate_cfg() { fi cmd=$(zaf_ctrl_get_item_option $1 $i "Cmd") if [ -n "$cmd" ]; then - echo "UserParameter=$ikey,${ZAF_LIB_DIR}/preload.sh $lock$cmd"; + $(which echo) "UserParameter=$ikey,${ZAF_LIB_DIR}/preload.sh $lock$cmd $args"; continue fi cmd=$(zaf_ctrl_get_item_option $1 $i "Function") if [ -n "$cmd" ]; then - echo "UserParameter=$ikey,${ZAF_LIB_DIR}/preload.sh $lock$cmd"; + $(which echo) -E "UserParameter=$ikey,${ZAF_LIB_DIR}/preload.sh $lock$cmd $args"; 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}/${ikey}.sh ${ZAF_PLUGINS_DIR}/$2/ - echo "UserParameter=$ikey,${ZAF_LIB_DIR}/preload.sh $lock${ZAF_PLUGINS_DIR}/$2/${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"; 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 5f43a36..641616a 100644 --- a/lib/preload.sh +++ b/lib/preload.sh @@ -16,6 +16,7 @@ export ZAF_LIB_DIR export ZAF_TMP_DIR export ZAF_PLUGINS_DIR -[ -n "$*" ] && $@ +[ "$(basename $0)" = "preload.sh" ] && [ -n "$*" ] && $@ + diff --git a/lib/zaf.lib.sh b/lib/zaf.lib.sh index 1100358..5429e4c 100644 --- a/lib/zaf.lib.sh +++ b/lib/zaf.lib.sh @@ -199,6 +199,10 @@ zaf_plugin_info() { # $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 plugindir="$2" control=${plugindir}/control.zaf @@ -212,13 +216,20 @@ zaf_prepare_plugin() { } zaf_install_plugin() { + local url + local plugin + local plugindir + local control + if zaf_prepare_plugin "$1" "${ZAF_TMP_DIR}/plugin"; then + url=$(zaf_get_plugin_url "$1") plugin=$(zaf_ctrl_get_global_block <"${ZAF_TMP_DIR}/plugin/control.zaf" | zaf_block_get_option Plugin) plugindir="${ZAF_PLUGINS_DIR}"/$plugin if zaf_prepare_plugin "$1" $plugindir; then + control=${plugindir}/control.zaf [ "$ZAF_DEBUG" -gt 0 ] && zaf_plugin_info "${control}" zaf_ctrl_check_deps "${control}" - zaf_ctrl_install "$1" "${control}" "${plugindir}" + zaf_ctrl_install "$url" "${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" diff --git a/zaf b/zaf index 8fc1a9b..5b41af8 100755 --- a/zaf +++ b/zaf @@ -83,7 +83,7 @@ test) install) shift; - [ -z "$@" ] && echo "$0 install plugin [plugin]..." + [ -z "$1" ] && echo "$0 install plugin [plugin]..." for p in $@; do if zaf_is_plugin "$p"; then zaf_wrn "Plugin $p already installed. Skipping installation." @@ -97,7 +97,7 @@ install) reinstall) shift; - [ -z "$@" ] && echo "$0 reinstall plugin [plugin]..." + [ -z "$1" ] && echo "$0 reinstall plugin [plugin]..." for p in $@; do if zaf_is_plugin "$p"; then zaf_remove_plugin "$(basename $p)" @@ -111,7 +111,7 @@ reinstall) remove) shift; - [ -z "$@" ] && echo "$0 remove plugin [plugin]..." + [ -z "$1" ] && echo "$0 remove plugin [plugin]..." for p in $@; do if zaf_is_plugin "$p"; then zaf_remove_plugin "$p" @@ -124,7 +124,7 @@ remove) self-upgrade) rm -rf /tmp/zaf-installer && mkdir /tmp/zaf-installer if zaf_fetch_url $ZAF_URL/install.sh >/tmp/zaf-installer/install.sh; then - cd /tmp/zaf-installer && ./install.sh + cd /tmp/zaf-installer && exec ./install.sh else echo "Cannot fetch uri $ZAF_URL/install.sh!"; fi @@ -146,6 +146,7 @@ self-remove) ;; *) + echo "$0 Version ${ZAF_VERSION}. Please use some of this commands:" echo "$0 update To update repo" echo "$0 plugins To list installed plugins" echo "$0 show [plugin] To show installed plugins or plugin info" From 6a868ae3f17aca5ff163da9ba76a90b748fe1c37 Mon Sep 17 00:00:00 2001 From: Lukas Macura Date: Mon, 4 Apr 2016 14:49:38 +0200 Subject: [PATCH 03/33] Minor changes to install --- install.sh | 2 +- zaf | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/install.sh b/install.sh index 8ebced0..28c087c 100755 --- a/install.sh +++ b/install.sh @@ -12,7 +12,7 @@ if ! [ "$(basename $0)" = "install.sh" ]; then set -e mkdir -p /tmp/zaf-installer \ && cd /tmp/zaf-installer \ - && (for i in lib/zaf.lib.sh lib/os.lib.sh lib/ctrl.lib.sh install.sh ; do curl -f -k -s -L -o - "$url/$i"; done) >install.sh \ + && (for i in lib/zaf.lib.sh lib/os.lib.sh lib/ctrl.lib.sh install.sh ; do echo curl -f -k -s -L -o - "$url/$i" >&2; curl -f -k -s -L -o - "$url/$i"; done) >install.sh \ && chmod +x install.sh \ && exec ./install.sh $auto "$@" exit diff --git a/zaf b/zaf index 5b41af8..d4f78a4 100755 --- a/zaf +++ b/zaf @@ -68,6 +68,10 @@ items) ;; test) + if echo $2|grep -q '\.'; then + zaf_test_item "$2" + exit + fi if [ -n "$2" ]; then shift plugins="$@" @@ -151,7 +155,7 @@ self-remove) echo "$0 plugins To list installed plugins" echo "$0 show [plugin] To show installed plugins or plugin info" echo "$0 items [plugin] To list all suported items [for plugin]" - echo "$0 test [plugin] To test all suported items [for plugin]" + echo "$0 test [plugin[.item]] To test all suported items [for plugin]" echo "$0 install plugin To install plugin" echo "$0 remove plugin To remove plugin" echo "$0 self-upgrade To self-upgrade zaf" From c0bbe2e30eea1000e918431be5f79ef66fb1bdd2 Mon Sep 17 00:00:00 2001 From: Lukas Macura Date: Mon, 4 Apr 2016 14:53:34 +0200 Subject: [PATCH 04/33] Repaired self-upgrade --- zaf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zaf b/zaf index d4f78a4..cba4c38 100755 --- a/zaf +++ b/zaf @@ -128,7 +128,7 @@ remove) self-upgrade) rm -rf /tmp/zaf-installer && mkdir /tmp/zaf-installer if zaf_fetch_url $ZAF_URL/install.sh >/tmp/zaf-installer/install.sh; then - cd /tmp/zaf-installer && exec ./install.sh + cd /tmp/zaf-installer && chmod +x ./install.sh && exec ./install.sh else echo "Cannot fetch uri $ZAF_URL/install.sh!"; fi From 4964988b365b4976a3a5ac5ed28a64486ce4a11e Mon Sep 17 00:00:00 2001 From: Lukas Macura Date: Mon, 4 Apr 2016 15:05:18 +0200 Subject: [PATCH 05/33] Repaired function plugin_version --- lib/zaf.lib.sh | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/zaf.lib.sh b/lib/zaf.lib.sh index 5429e4c..3c4300c 100644 --- a/lib/zaf.lib.sh +++ b/lib/zaf.lib.sh @@ -261,16 +261,18 @@ zaf_discovery_plugins() { } zaf_plugin_version() { + local plugindir + local cfile + if [ -z "$1" ]; then - echo "Missing plugin name"; - exit 1 + zaf_err "Missing plugin name."; fi - plugindir="${ZAF_PLUGINS_DIR}/$1" - cfile="$plugindir/control" - if [ -d "$plugindir" ] ; then - zaf_ctrl_get_option "$cfile" Version + if zaf_is_plugin "$1"; then + plugindir="${ZAF_PLUGINS_DIR}/$1" + cfile="$plugindir/control.zaf" + zaf_ctrl_get_global_option $cfile Version else - echo "Plugin $1 not installed" + zaf_err "Plugin $1 not installed." fi } From 1c274a512ba099eb076651d85a9693e0f14914dd Mon Sep 17 00:00:00 2001 From: Lukas Macura Date: Mon, 4 Apr 2016 15:06:12 +0200 Subject: [PATCH 06/33] One more bug fix on self-upgrade --- zaf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zaf b/zaf index cba4c38..1b39456 100755 --- a/zaf +++ b/zaf @@ -128,7 +128,7 @@ remove) self-upgrade) rm -rf /tmp/zaf-installer && mkdir /tmp/zaf-installer if zaf_fetch_url $ZAF_URL/install.sh >/tmp/zaf-installer/install.sh; then - cd /tmp/zaf-installer && chmod +x ./install.sh && exec ./install.sh + cd /tmp/zaf-installer && chmod +x ./install.sh && exec ./install.sh auto else echo "Cannot fetch uri $ZAF_URL/install.sh!"; fi From 5c3338fdb9bdd3df35450d1cb374d5af9755281e Mon Sep 17 00:00:00 2001 From: Lukas Macura Date: Mon, 4 Apr 2016 15:10:38 +0200 Subject: [PATCH 07/33] Neverending self-upgrade bug --- zaf | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/zaf b/zaf index 1b39456..e3a7c41 100755 --- a/zaf +++ b/zaf @@ -127,11 +127,18 @@ remove) self-upgrade) rm -rf /tmp/zaf-installer && mkdir /tmp/zaf-installer - if zaf_fetch_url $ZAF_URL/install.sh >/tmp/zaf-installer/install.sh; then - cd /tmp/zaf-installer && chmod +x ./install.sh && exec ./install.sh auto - else - echo "Cannot fetch uri $ZAF_URL/install.sh!"; + if ! which curl >/dev/null; + then + zaf_err "Curl not found. Cannot continue. Please install it." fi + [ -z "$2" ] && auto=auto + set -e + mkdir -p /tmp/zaf-installer \ + && cd /tmp/zaf-installer \ + && (for i in lib/zaf.lib.sh lib/os.lib.sh lib/ctrl.lib.sh install.sh ; do echo curl -f -k -s -L -o - "$ZAF_URL/$i" >&2; curl -f -k -s -L -o - "$ZAF_URL/$i"; done) >install.sh \ + && chmod +x install.sh \ + && exec ./install.sh $auto "$@" + exit ;; self-remove) From 604c2477771359aa86f6cd32152559ef27277d0a Mon Sep 17 00:00:00 2001 From: Lukas Macura Date: Mon, 4 Apr 2016 16:08:07 +0200 Subject: [PATCH 08/33] Rewrited readme --- README.md | 105 ++++++++++++++++++++++++++++++++++++----------------- install.sh | 6 +-- zaf | 1 + 3 files changed, 76 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index cb2e082..fa28658 100644 --- a/README.md +++ b/README.md @@ -5,57 +5,96 @@ But there is problem with installation, update and centralised management. This 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. +## Motivation + +Did you install lot of zabbix agents? 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? +So zaf is here for you :) + ## Features * Minimal dependencies. At this time, only sh, sed, awk and curl +* Minimal code (less than 50kb of code) * Minimal runtime version to fit on different systems (openwrt, debian, ubuntu, ...) * Modular. Zaf module can be maintained externaly from this framework * Sharing code. Many zabbix external checks share common shell functions. +* Simplification of userparameter functions (does not have to be one-line long code) * 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. -* OS packaging support. +* OS packaging support (in future). +* Zabbix agent autoinstallation and autoconfiguration suitable to use in puppet or another tool ## 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 command should be used on most systems: -``` -curl https://raw.githubusercontent.com/limosek/zaf/master/install.sh | sh -``` -but in openwrt, you should use this: +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: ``` curl -k https://raw.githubusercontent.com/limosek/zaf/master/install.sh | sh ``` -## Example -Best way how to explain everything is example. Supposing we are working on debian-like system. +### Install options and autoconfiguration +General parameters for install.sh on any system (simplest way how to install) ``` -curl https://raw.githubusercontent.com/limosek/zaf/master/install.sh | sudo sh -sudo zaf install process-info -sudo zaf install http://other.check.domain/check/ -zaf make-deb -zaf make-opkg -zaf make-rpm -zaf self-upgrade +curl -k https://raw.githubusercontent.com/limosek/zaf/master/install.sh | sh -s {auto|interactive|debug-auto|debug-interactive} [Agent-Options] [Zaf-Options] +``` +or use git version: +``` +git clone https://github.com/limosek/zaf.git +./install.sh {auto|interactive|debug-auto|debug-interactive} [Agent-Options] [Zaf-Options] + Agent-Options: A_Option=value [...] + Zaf-Options: ZAF_OPT=value [...] +``` + +So you can pass ANY configuration of your zabbix agent directly to installer. Installer will try to autoguess suitable config options for your system. +Now everything was tested on Debian and OpenWrt. If somebody is interrested in, you can help and test with some rpm specific functions. + +### Example +Suppose you want to autoinstall agent on clean system. You need only curl installed. Everything else is one-cmd process. +This command will install zaf, install zabbix-agent if necessary and sets zabbix variables on agent to reach server. This command can be automatized by puppet or another deploying system. +``` +curl -k https://raw.githubusercontent.com/limosek/zaf/master/install.sh | sh -s Z_Server=zabbix.server.local Z_ServerActive=zabbix.server.local Z_HostnameItem=system.hostname Z_RefreshActiveChecks=60 ZAF_PLUGINS_GITURL="git://gitserver.local" ``` ## Zaf plugin -Zaf plugin is set of configuration options and binaries which are needed for specific checks. For example, to monitor postfix, we need some cron job which is automaticaly run and next ti this, some external items which has to be configured. +Zaf plugin is set of configuration options and binaries which are needed for specific checks. For example, to monitor postfix, we need some cron job which is automaticaly run and next ti this, some external items which has to be configured. Do not mix zaf plugin and zabbix plugin. While zaf plugin is set of scripts or binaries external to zabbix agent, zabbix plugin is internal zabbix lodadable module. + +## Zaf utility +Zaf binary can be installed on any system from openwrt to big system. It has minimal dependencies and is shell based. Is has minimal size (up to 50kb of code). It can be used for installing, removing and testing zaf plugin items. Zaf should be run as root. +``` +zaf +/usr/bin/zaf Version trunk. Please use some of this commands: +/usr/bin/zaf update To update repo +/usr/bin/zaf plugins To list installed plugins +/usr/bin/zaf show [plugin] To show installed plugins or plugin info +/usr/bin/zaf items [plugin] To list all suported items [for plugin] +/usr/bin/zaf test [plugin[.item]] To test all suported items [for plugin] +/usr/bin/zaf install plugin To install plugin +/usr/bin/zaf remove plugin To remove plugin +/usr/bin/zaf self-upgrade To self-upgrade zaf +/usr/bin/zaf self-remove To self-remove zaf and its config + +``` + +### Installing plugin +To install plugin from common repository. If git is available, local git repo is tried first. If not, remote https repo is tried second. +``` +zaf install zaf +``` +To install plugin from external source, external plugin has to be "zafable". This means that its maitainer will create control.zaf file located at http://some.project/plugin/control.zaf. Nothing else. +``` +zaf install http://some.project/plugin +``` +To install plugin from local directory: +``` +zaf install /some/plugin +``` +Installer will look into control file, run setup task defined there, fetch binaries and scripts needed for specific plugin and test system dependencies for that plugin. If everything is OK, zaf_plugin.conf is created in zabbix_agentd.d conf directory and userparameters are automaticaly added. ## How it works -There is central zaf reposirory on github. There are basic checks and zaf code itself. Next to this, each project can have its own zaf structure. Adding url of plugin to zaf will make it useable and updatable. - -## Zaf plugin structure -Each zaf plugin url MUST have this items: -``` -/plugin/README.md # Documentation -/plugin/control # Control file -/plugin/template.xml # Template for Zabbix - -``` - -## Zaf control file -Control files are similar to Debian Control files -``` -will be explained - -``` +Zaf installer will do most of actions needed to monitor some specific plugin items. Configuration of plugin is very simple and text readable. Anybody can write its own plugin or make its plugin "zafable". It is enough to create *control.zaf" file. For example, look into https://github.com/limosek/zaf-plugins repository. This is default repository for zaf. + + +## I want to make my own plugin! +Great! Look into https://github.com/limosek/zaf-plugins repository, look to control files and try to create your own. It is easy! You can contact me for help. + +## I want to help with zaf! +Great! I have no time for testing on systems and writing system specific hacks. Next to this, templates should be optimized and tested for basic plugins. + diff --git a/install.sh b/install.sh index 28c087c..37dcf8f 100755 --- a/install.sh +++ b/install.sh @@ -171,8 +171,8 @@ zaf_configure(){ zaf_get_option ZAF_AGENT_BIN "Zabbix agent binary" "/usr/sbin/zabbix_agentd" "$1" zaf_get_option ZAF_AGENT_RESTART "Zabbix agent restart cmd" "service zabbix-agent restart" "$1" - if zaf_is_root && ! which $ZAF_AGENT_BIN >/dev/null; then - zaf_err "Zabbix agent not installed? Use ZAF_ZABBIX_AGENT_BIN env variable to specify location. Exiting." + if zaf_is_root && ! [ -x $ZAF_AGENT_BIN ]; then + zaf_err "Zabbix agent ($ZAF_AGENT_BIN) not installed? Use ZAF_AGENT_BIN env variable to specify location. Exiting." fi [ -n "$INSTALL_PREFIX" ] && zaf_install_dir "/etc" @@ -250,7 +250,7 @@ install) zaf_install_dir ${ZAF_PLUGINS_DIR} zaf_install_dir ${ZAF_BIN_DIR} zaf_install_bin $(zaf_getrest zaf) ${ZAF_BIN_DIR} - export INSTALL_PREFIX ZAF_CFG_FILE + export INSTALL_PREFIX ZAF_CFG_FILE ZAF_DEBUG if zaf_is_root; then [ "${ZAF_GIT}" = 1 ] && ${INSTALL_PREFIX}/${ZAF_BIN_DIR}/zaf update ${INSTALL_PREFIX}/${ZAF_BIN_DIR}/zaf reinstall zaf || zaf_err "Error installing zaf plugin." diff --git a/zaf b/zaf index e3a7c41..aebb793 100755 --- a/zaf +++ b/zaf @@ -33,6 +33,7 @@ check-agent-config) ;; update) + zaf_wrn "Updating repository ${ZAF_PLUGINS_GITURL}..." zaf_update_repo ;; From 88bd1a57e575bc88ae1badb0dc88f9519224681b Mon Sep 17 00:00:00 2001 From: Lukas Macura Date: Mon, 4 Apr 2016 16:13:49 +0200 Subject: [PATCH 09/33] More typos in readme --- README.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index fa28658..63a0d49 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,8 @@ curl -k https://raw.githubusercontent.com/limosek/zaf/master/install.sh | sh ### Install options and autoconfiguration General parameters for install.sh on any system (simplest way how to install) ``` -curl -k https://raw.githubusercontent.com/limosek/zaf/master/install.sh | sh -s {auto|interactive|debug-auto|debug-interactive} [Agent-Options] [Zaf-Options] +curl -k https://raw.githubusercontent.com/limosek/zaf/master/install.sh | \ + sh -s {auto|interactive|debug-auto|debug-interactive} [Agent-Options] [Zaf-Options] ``` or use git version: ``` @@ -41,14 +42,20 @@ git clone https://github.com/limosek/zaf.git Zaf-Options: ZAF_OPT=value [...] ``` -So you can pass ANY configuration of your zabbix agent directly to installer. Installer will try to autoguess suitable config options for your system. +So you can pass ANY configuration of your zabbix agent directly to installer prefixing it with *Z_*. Please note that options are *Case Sensitive*! +Next to this, you can pass ANY zaf config options by *ZAF_* prefix. Yes, we need some more documentation of ZAF options. Please look at least here: https://github.com/limosek/zaf/blob/master/install.sh#L160 +Installer will try to autoguess suitable config options for your system. Now everything was tested on Debian and OpenWrt. If somebody is interrested in, you can help and test with some rpm specific functions. ### Example Suppose you want to autoinstall agent on clean system. You need only curl installed. Everything else is one-cmd process. This command will install zaf, install zabbix-agent if necessary and sets zabbix variables on agent to reach server. This command can be automatized by puppet or another deploying system. ``` -curl -k https://raw.githubusercontent.com/limosek/zaf/master/install.sh | sh -s Z_Server=zabbix.server.local Z_ServerActive=zabbix.server.local Z_HostnameItem=system.hostname Z_RefreshActiveChecks=60 ZAF_PLUGINS_GITURL="git://gitserver.local" +curl -k https://raw.githubusercontent.com/limosek/zaf/master/install.sh | sh -s \ + Z_Server=zabbix.server.local \ + Z_ServerActive=zabbix.server.local \ + Z_HostnameItem=system.hostname Z_RefreshActiveChecks=60 \ + ZAF_PLUGINS_GITURL="git://gitserver.local" ``` ## Zaf plugin From ce4559feaa0225f6a09e0ff15adda7e584e60a51 Mon Sep 17 00:00:00 2001 From: Lukas Macura Date: Mon, 4 Apr 2016 16:43:58 +0200 Subject: [PATCH 10/33] Missed auto word --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 63a0d49..5e327f4 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ Now everything was tested on Debian and OpenWrt. If somebody is interrested in, Suppose you want to autoinstall agent on clean system. You need only curl installed. Everything else is one-cmd process. This command will install zaf, install zabbix-agent if necessary and sets zabbix variables on agent to reach server. This command can be automatized by puppet or another deploying system. ``` -curl -k https://raw.githubusercontent.com/limosek/zaf/master/install.sh | sh -s \ +curl -k https://raw.githubusercontent.com/limosek/zaf/master/install.sh | sh -s auto \ Z_Server=zabbix.server.local \ Z_ServerActive=zabbix.server.local \ Z_HostnameItem=system.hostname Z_RefreshActiveChecks=60 \ From ee06971e3a1f17427c1022b2ec1f09e2dfe655b2 Mon Sep 17 00:00:00 2001 From: Lukas Macura Date: Mon, 4 Apr 2016 16:52:23 +0200 Subject: [PATCH 11/33] Set parameter of zabbix only if not empty --- install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install.sh b/install.sh index 37dcf8f..903353e 100755 --- a/install.sh +++ b/install.sh @@ -114,7 +114,7 @@ zaf_set_agent_option() { zaf_wrn "Moving option $option to zaf config part." sed -i "s/$option=/#$option=/" $ZAF_AGENT_CONFIG fi - echo "$option=$value" >> "$ZAF_AGENT_CONFIGD/zaf_options.conf" + [ -n "$2" ] && echo "$option=$value" >> "$ZAF_AGENT_CONFIGD/zaf_options.conf" } # Automaticaly configure agent if supported From 83eae36198247ef2e6e7f38e96fae4f64b041c10 Mon Sep 17 00:00:00 2001 From: Lukas Macura Date: Mon, 4 Apr 2016 16:58:39 +0200 Subject: [PATCH 12/33] zaf_options are always generated on install, not added --- install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install.sh b/install.sh index 903353e..a57551c 100755 --- a/install.sh +++ b/install.sh @@ -125,7 +125,7 @@ zaf_configure_agent() { local value zaf_install_dir "$ZAF_AGENT_CONFIGD" - zaf_touch "$ZAF_AGENT_CONFIGD/zaf_options.conf" || zaf_err "Cannot access $ZAF_AGENT_CONFIGD/zaf_options.conf" + echo -n >"$ZAF_AGENT_CONFIGD/zaf_options.conf" || zaf_err "Cannot access $ZAF_AGENT_CONFIGD/zaf_options.conf" for pair in "$@"; do echo $pair | grep -q '^Z\_' || continue # Skip non Z_ vars option=$(echo $pair|cut -d '=' -f 1|cut -d '_' -f 2) From 63feeb1b1d41e3c7b2675e2349ee8607500a04c1 Mon Sep 17 00:00:00 2001 From: Lukas Macura Date: Tue, 5 Apr 2016 13:00:35 +0200 Subject: [PATCH 13/33] Repaired args in script usage --- lib/ctrl.lib.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ctrl.lib.sh b/lib/ctrl.lib.sh index 1f05abd..e3e8ff5 100644 --- a/lib/ctrl.lib.sh +++ b/lib/ctrl.lib.sh @@ -134,12 +134,12 @@ zaf_ctrl_generate_cfg() { 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 $args"; + $(which echo) "UserParameter=$ikey,${ZAF_LIB_DIR}/preload.sh $lock$cmd"; continue fi cmd=$(zaf_ctrl_get_item_option $1 $i "Function") if [ -n "$cmd" ]; then - $(which echo) -E "UserParameter=$ikey,${ZAF_LIB_DIR}/preload.sh $lock$cmd $args"; + $(which echo) -E "UserParameter=$ikey,${ZAF_LIB_DIR}/preload.sh $lock$cmd"; continue; fi cmd=$(zaf_ctrl_get_item_option $1 $i "Script") From 7eea6896e17e449946f80b906811163904262c60 Mon Sep 17 00:00:00 2001 From: Lukas Macura Date: Tue, 5 Apr 2016 13:14:45 +0200 Subject: [PATCH 14/33] Self-upgrade now remebers zabbix options entered during first install --- install.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/install.sh b/install.sh index a57551c..9060fe5 100755 --- a/install.sh +++ b/install.sh @@ -123,6 +123,7 @@ zaf_configure_agent() { local pair local option local value + local options zaf_install_dir "$ZAF_AGENT_CONFIGD" echo -n >"$ZAF_AGENT_CONFIGD/zaf_options.conf" || zaf_err "Cannot access $ZAF_AGENT_CONFIGD/zaf_options.conf" @@ -131,7 +132,9 @@ zaf_configure_agent() { option=$(echo $pair|cut -d '=' -f 1|cut -d '_' -f 2) value=$(echo $pair|cut -d '=' -f 2-) zaf_set_agent_option "$option" "$value" + options="$options Z_$option='$value'" done + zaf_set_option ZAF_AGENT_OPTIONS "${options}" } zaf_configure(){ @@ -145,6 +148,7 @@ zaf_configure(){ zaf_get_option ZAF_OS "Operating system to use" "$ZAF_OS" "$1" zaf_get_option ZAF_OS_CODENAME "Operating system codename" "$ZAF_OS_CODENAME" "$1" zaf_get_option ZAF_AGENT_PKG "Zabbix agent package" "$ZAF_AGENT_PKG" "$1" + zaf_get_option ZAF_AGENT_OPTIONS "Zabbix options to set in cfg" "$ZAF_AGENT_OPTIONS" "$1" if zaf_is_root && [ -n "$ZAF_AGENT_PKG" ]; then if ! zaf_os_specific zaf_check_deps "$ZAF_AGENT_PKG"; then if [ "$1" = "auto" ]; then @@ -235,7 +239,7 @@ reconf) ;; install) zaf_configure auto - zaf_configure_agent "$@" + zaf_configure_agent $ZAF_AGENT_OPTIONS "$@" zaf_set_agent_option "Include" "$ZAF_AGENT_CONFIGD" append rm -rif ${ZAF_TMP_DIR} mkdir -p ${ZAF_TMP_DIR} From 081ac01e6b32ccd8efc6f2331810a4c326fcc3cb Mon Sep 17 00:00:00 2001 From: Lukas Macura Date: Wed, 6 Apr 2016 14:25:10 +0200 Subject: [PATCH 15/33] Added makefile for debian package --- .gitignore | 2 ++ Makefile | 68 +++++++++++++++++++++++++++++++++++++ files/changelog.template | 5 +++ files/control.template | 11 ++++++ files/zaf.conf-deb.template | 12 +++++++ install.sh | 7 ++-- lib/ctrl.lib.sh | 6 ++-- lib/os.lib.sh | 21 ++++++++++++ 8 files changed, 127 insertions(+), 5 deletions(-) create mode 100644 Makefile create mode 100644 files/changelog.template create mode 100644 files/control.template create mode 100644 files/zaf.conf-deb.template diff --git a/.gitignore b/.gitignore index 47f6dfc..e46087e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ *~ plugins/ +out/ +tmp/ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..10fa93f --- /dev/null +++ b/Makefile @@ -0,0 +1,68 @@ +# Zabbix agent framework makefile + +CONTROLFILES=$(foreach p,$(PLUGINS),$(p)/control.zaf) +ZAF_EXPORT_OPTS=$(foreach o,$(ZAF_OPTIONS),$(shell echo $(o)|cut -d '=' -f 1)) +DEBIAN_DIR=tmp/deb +DEBIAN_CTRL=$(DEBIAN_DIR)/DEBIAN +DEBIAN_PKG=out/zaf.deb + +all: help + +help: + @echo make '{deb|ipk|rpm}' '[PLUGINS="/dir/plg1 /dir/plg2] [ZAF_OPTIONS="ZAF_cfg=val ..."] [AGENT_OPTIONS="Z_Server=host ..."]' + +deb: deb-clean deb-init deb-deps deb-control deb-postinst deb-cp deb-changelog deb-package + +deb-clean: + rm -rf $(DEBIAN_DIR) $(DEBIAN_PKG) + +deb-init: + @mkdir -p tmp out $(DEBIAN_DIR) + +deb-deps: $(CONTROLFILES) + @which dpkg >/dev/null && which dpkg-buildpackage >/dev/null && which dch >/dev/null || { echo "You need essential debian developer tools. Please install them:\nsudo apt-get install build-essential devscripts debhelper"; exit 2; } + +deb-control: + @mkdir -p $(DEBIAN_CTRL) + @. lib/zaf.lib.sh; \ + . lib/ctrl.lib.sh; \ + for p in $(PLUGINS); do \ + DEPENDS="$$DEPENDS,$$(zaf_ctrl_get_global_option $$p/control.zaf Depends-dpkg | tr ' ' ',')"; \ + done; \ + zaf_far '{ZAF_VERSION}' "0.1" $(DEBIAN_CTRL)/control + +deb-postinst: +ifneq ($(PLUGINS),) + @echo -n "#!/bin/sh\nzaf install " >$(DEBIAN_CTRL)/postinst + @. lib/zaf.lib.sh; \ + . lib/ctrl.lib.sh; \ + for p in $(PLUGINS); do \ + echo -n " "$$(zaf_ctrl_get_global_option $$p/control.zaf Plugin) ; \ + done >>$(DEBIAN_CTRL)/postinst + @echo >>$(DEBIAN_CTRL)/postinst + @chmod +x $(DEBIAN_CTRL)/postinst +endif + +deb-cp: + @mkdir -p $(DEBIAN_DIR) + INSTALL_PREFIX=$(DEBIAN_DIR) ZAF_DEBUG=0 ./install.sh auto $(ZAF_OPTIONS) $(AGENT_OPTIONS) + @. lib/zaf.lib.sh; \ + . lib/ctrl.lib.sh; \ + for p in $(PLUGINS); do \ + plugin=$$(zaf_ctrl_get_global_option $$p/control.zaf Plugin) ; \ + mkdir -p $(DEBIAN_DIR)/usr/lib/zaf/plugins/$$plugin/; \ + cp -R $$p/* $(DEBIAN_DIR)/usr/lib/zaf/plugins/$$plugin/; \ + done + @rm -rf $(DEBIAN_DIR)/tmp + @cp $(DEBIAN_DIR)/etc/zaf.conf tmp/zaf.conf + grep -E "$$(echo $(ZAF_EXPORT_OPTS) | tr ' ' '|')=" tmp/zaf.conf >$(DEBIAN_DIR)/etc/zaf.conf +ifneq ($(AGENT_OPTIONS),) + echo "ZAF_AGENT_OPTIONS=\"$(AGENT_OPTIONS)\"" >>$(DEBIAN_DIR)/etc/zaf.conf +endif + +deb-changelog: + @cp files/changelog.template debian/changelog + +deb-package: + dpkg-deb -b $(DEBIAN_DIR) $(DEBIAN_PKG) + diff --git a/files/changelog.template b/files/changelog.template new file mode 100644 index 0000000..98bcb73 --- /dev/null +++ b/files/changelog.template @@ -0,0 +1,5 @@ +PACKAGE (0.1) zaf; urgency=medium + + * Initial release. + + -- Lukas Macura Wed, 06 Apr 2016 13:56:25 +0200 diff --git a/files/control.template b/files/control.template new file mode 100644 index 0000000..2d281ac --- /dev/null +++ b/files/control.template @@ -0,0 +1,11 @@ +Package: zaf +Version: {ZAF_VERSION} +Homepage: https://github.com/limosek/zaf +Section: admin +Priority: optional +Architecture: all +Depends: dash, awk, sed, grep, coreutils {ZAF_DEPENDS} +Maintainer: Lukas Macura +Description: Zabbix agent framework package + This tool is used to maintain external zabbix checks in one place. 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. + diff --git a/files/zaf.conf-deb.template b/files/zaf.conf-deb.template new file mode 100644 index 0000000..d6a8345 --- /dev/null +++ b/files/zaf.conf-deb.template @@ -0,0 +1,12 @@ +ZAF_PKG='dpkg' +ZAF_AGENT_PKG='zabbix-agent' +ZAF_TMP_BASE='/tmp/zaf' +ZAF_LIB_DIR='/usr/lib/zaf' +ZAF_BIN_DIR='/usr/bin' +ZAF_PLUGINS_DIR='/usr/lib/zaf/plugins' +ZAF_PLUGINS_URL='https://raw.githubusercontent.com/limosek/zaf-plugins/master/' +ZAF_PLUGINS_GITURL='https://github.com/limosek/zaf-plugins.git' +ZAF_REPO_DIR='/usr/lib/zaf/repo' +ZAF_AGENT_CONFIGD='/etc/zabbix/zabbix_agentd.d' +ZAF_AGENT_BIN='/usr/sbin/zabbix_agentd' +ZAF_AGENT_RESTART='service zabbix-agent restart' diff --git a/install.sh b/install.sh index 9060fe5..fea45a5 100755 --- a/install.sh +++ b/install.sh @@ -127,6 +127,7 @@ zaf_configure_agent() { zaf_install_dir "$ZAF_AGENT_CONFIGD" echo -n >"$ZAF_AGENT_CONFIGD/zaf_options.conf" || zaf_err "Cannot access $ZAF_AGENT_CONFIGD/zaf_options.conf" + ! [ -f "$ZAF_AGENT_CONFIG" ] && zaf_install "$ZAF_AGENT_CONFIG" for pair in "$@"; do echo $pair | grep -q '^Z\_' || continue # Skip non Z_ vars option=$(echo $pair|cut -d '=' -f 1|cut -d '_' -f 2) @@ -239,10 +240,12 @@ reconf) ;; install) zaf_configure auto - zaf_configure_agent $ZAF_AGENT_OPTIONS "$@" - zaf_set_agent_option "Include" "$ZAF_AGENT_CONFIGD" append rm -rif ${ZAF_TMP_DIR} mkdir -p ${ZAF_TMP_DIR} + if zaf_is_root; then + zaf_configure_agent $ZAF_AGENT_OPTIONS "$@" + zaf_set_agent_option "Include" "$ZAF_AGENT_CONFIGD" append + fi zaf_install_dir ${ZAF_LIB_DIR} zaf_install_dir ${ZAF_PLUGINS_DIR} zaf_install $(zaf_getrest lib/zaf.lib.sh) ${ZAF_LIB_DIR} diff --git a/lib/ctrl.lib.sh b/lib/ctrl.lib.sh index e3e8ff5..028404d 100644 --- a/lib/ctrl.lib.sh +++ b/lib/ctrl.lib.sh @@ -92,14 +92,14 @@ zaf_ctrl_install() { local cmd pdir="$3" - binaries=$(zaf_ctrl_get_global_block <$2 | zaf_block_get_option "Install-bin") + binaries=$(zaf_ctrl_get_global_option $2 "Install-bin") for b in $binaries; do zaf_fetch_url "$1/$b" >"${ZAF_TMP_DIR}/$b" zaf_install_bin "${ZAF_TMP_DIR}/$b" "$pdir" done - script=$(zaf_ctrl_get_global_block <$2 | zaf_block_get_moption "Install-script") + script=$(zaf_ctrl_get_global_option $2 "Install-script") [ -n "$script" ] && eval "$script" - cmd=$(zaf_ctrl_get_global_block <$2 | zaf_block_get_option "Install-cmd") + cmd=$(zaf_ctrl_get_global_option $2 "Install-cmd") [ -n "$cmd" ] && $cmd } diff --git a/lib/os.lib.sh b/lib/os.lib.sh index 7433fe8..cb5c0ff 100644 --- a/lib/os.lib.sh +++ b/lib/os.lib.sh @@ -8,6 +8,12 @@ zaf_configure_os_openwrt() { ZAF_CURL_INSECURE=1 } +zaf_configure_os_freebsd() { + ZAF_AGENT_PKG="zabbix3-agent" + ZAF_AGENT_CONFIG="/usr/local/etc/zabbix3/zabbix_agentd.conf" + ZAF_AGENT_CONFIGD="/usr/local/etc/zabbix3/zabbix_agentd.conf.d/" +} + zaf_detect_system() { if which dpkg >/dev/null; then ZAF_PKG=dpkg @@ -29,12 +35,18 @@ zaf_detect_system() { ZAF_OS="$(echo $DISTRIB_ID|tr '[:upper:]' '[:lower:]')" ZAF_OS_CODENAME="$(echo $DISTRIB_CODENAME|tr '[:upper:]' '[:lower:]')" return + else if which pkg >/dev/null; then + ZAF_PKG="pkg" + ZAF_OS="freebsd" + ZAF_OS_CODENAME="$(freebsd-version|cut -d '-' -f 1)" + return else ZAF_PKG="unknown" ZAF_OS="unknown" ZAF_OS_CODENAME="unknown" ZAF_AGENT_PKG="" return + fi fi fi fi @@ -137,4 +149,13 @@ zaf_check_deps_opkg() { done } +# Check if pkg dependency is met +# $* - packages +zaf_check_deps_pkg() { + local p + for p in $*; do + pkg query -x "Package: %n" $p| grep -q 'Package:' || { echo "Missing package $p" >&2; return 1; } + done +} + From ea6bf3d83a1196ed9dd59f60483aa75507f13bcc Mon Sep 17 00:00:00 2001 From: Lukas Macura Date: Thu, 7 Apr 2016 13:14:53 +0200 Subject: [PATCH 16/33] Added debian package creation --- Makefile | 34 ++++--- files/postinst.template | 16 +++ files/preinst.template | 10 ++ files/prerm.template | 7 ++ install.sh | 210 ++++++++++++++++++++++++---------------- lib/zaf.lib.sh | 14 ++- zaf | 10 ++ 7 files changed, 200 insertions(+), 101 deletions(-) create mode 100644 files/postinst.template create mode 100644 files/preinst.template create mode 100644 files/prerm.template diff --git a/Makefile b/Makefile index 10fa93f..072b824 100644 --- a/Makefile +++ b/Makefile @@ -11,10 +11,10 @@ all: help help: @echo make '{deb|ipk|rpm}' '[PLUGINS="/dir/plg1 /dir/plg2] [ZAF_OPTIONS="ZAF_cfg=val ..."] [AGENT_OPTIONS="Z_Server=host ..."]' -deb: deb-clean deb-init deb-deps deb-control deb-postinst deb-cp deb-changelog deb-package +deb: deb-clean deb-init deb-deps deb-control deb-scripts deb-cp deb-package deb-clean: - rm -rf $(DEBIAN_DIR) $(DEBIAN_PKG) + @rm -rf $(DEBIAN_DIR) $(DEBIAN_PKG) deb-init: @mkdir -p tmp out $(DEBIAN_DIR) @@ -31,38 +31,44 @@ deb-control: done; \ zaf_far '{ZAF_VERSION}' "0.1" $(DEBIAN_CTRL)/control -deb-postinst: +deb-scripts: ifneq ($(PLUGINS),) - @echo -n "#!/bin/sh\nzaf install " >$(DEBIAN_CTRL)/postinst @. lib/zaf.lib.sh; \ . lib/ctrl.lib.sh; \ for p in $(PLUGINS); do \ - echo -n " "$$(zaf_ctrl_get_global_option $$p/control.zaf Plugin) ; \ - done >>$(DEBIAN_CTRL)/postinst - @echo >>$(DEBIAN_CTRL)/postinst + plugins="$$plugins "$$(zaf_ctrl_get_global_option $$p/control.zaf Plugin) ; \ + done; \ + cat files/postinst.template | zaf_far '{PLUGINS}' "$$plugins" | zaf_far '{ZAF_LIB_DIR}' "/usr/lib/zaf" >$(DEBIAN_CTRL)/postinst @chmod +x $(DEBIAN_CTRL)/postinst + @cp files/preinst.template $(DEBIAN_CTRL)/preinst + @chmod +x $(DEBIAN_CTRL)/preinst + @cp files/prerm.template $(DEBIAN_CTRL)/prerm + @chmod +x $(DEBIAN_CTRL)/prerm endif deb-cp: @mkdir -p $(DEBIAN_DIR) - INSTALL_PREFIX=$(DEBIAN_DIR) ZAF_DEBUG=0 ./install.sh auto $(ZAF_OPTIONS) $(AGENT_OPTIONS) + @set -e; INSTALL_PREFIX=$(DEBIAN_DIR) ZAF_DEBUG=0 ./install.sh auto $(ZAF_OPTIONS) $(AGENT_OPTIONS) @. lib/zaf.lib.sh; \ . lib/ctrl.lib.sh; \ for p in $(PLUGINS); do \ plugin=$$(zaf_ctrl_get_global_option $$p/control.zaf Plugin) ; \ - mkdir -p $(DEBIAN_DIR)/usr/lib/zaf/plugins/$$plugin/; \ - cp -R $$p/* $(DEBIAN_DIR)/usr/lib/zaf/plugins/$$plugin/; \ + mkdir -p $(DEBIAN_DIR)/usr/lib/zaf/prepackaged/$$plugin/; \ + cp -R $$p/* $(DEBIAN_DIR)/usr/lib/zaf/prepackaged/$$plugin/; \ done + @cat lib/*lib.sh install.sh >$(DEBIAN_DIR)/usr/lib/zaf/install.sh + @chmod +x $(DEBIAN_DIR)/usr/lib/zaf/install.sh @rm -rf $(DEBIAN_DIR)/tmp @cp $(DEBIAN_DIR)/etc/zaf.conf tmp/zaf.conf - grep -E "$$(echo $(ZAF_EXPORT_OPTS) | tr ' ' '|')=" tmp/zaf.conf >$(DEBIAN_DIR)/etc/zaf.conf + @grep -E "$$(echo $(ZAF_EXPORT_OPTS) | tr ' ' '|')=" tmp/zaf.conf >$(DEBIAN_DIR)/etc/zaf.conf + @echo "ZAF_PREPACKAGED_DIR=\"/usr/lib/zaf/prepackaged\"" >>$(DEBIAN_DIR)/etc/zaf.conf ifneq ($(AGENT_OPTIONS),) - echo "ZAF_AGENT_OPTIONS=\"$(AGENT_OPTIONS)\"" >>$(DEBIAN_DIR)/etc/zaf.conf + @echo "ZAF_AGENT_OPTIONS=\"$(AGENT_OPTIONS)\"" >>$(DEBIAN_DIR)/etc/zaf.conf endif deb-changelog: - @cp files/changelog.template debian/changelog + @cp files/changelog.template $(DEBIAN_CTRL)/changelog deb-package: - dpkg-deb -b $(DEBIAN_DIR) $(DEBIAN_PKG) + @dpkg-deb -b $(DEBIAN_DIR) $(DEBIAN_PKG) diff --git a/files/postinst.template b/files/postinst.template new file mode 100644 index 0000000..45e6060 --- /dev/null +++ b/files/postinst.template @@ -0,0 +1,16 @@ +#!/bin/sh + +case $1 in +configure) + if [ -f /usr/lib/zaf/install.sh ] && [ -f /etc/zaf.conf ] && [ -f /usr/lib/zaf/zaf.lib.sh ] && which zaf >/dev/null; then + . /etc/zaf.conf + . /usr/lib/zaf/zaf.lib.sh + . /usr/lib/zaf/os.lib.sh + . /usr/lib/zaf/ctrl.lib.sh + cd /usr/lib/zaf && /usr/lib/zaf/install.sh reconf + zaf reinstall {PLUGINS} + fi +;; +esac + + diff --git a/files/preinst.template b/files/preinst.template new file mode 100644 index 0000000..0a3971d --- /dev/null +++ b/files/preinst.template @@ -0,0 +1,10 @@ +#!/bin/sh + +case $1 in +install) + if [ -d /usr/lib/zaf ]; then + echo "Do zaf self-remove first! Cannot mix packaged and non-packaged version!" + exit 2 + fi + ;; +esac diff --git a/files/prerm.template b/files/prerm.template new file mode 100644 index 0000000..ea97185 --- /dev/null +++ b/files/prerm.template @@ -0,0 +1,7 @@ +#!/bin/sh + +case $1 in +remove) + rm -rf /usr/lib/zaf/plugins /usr/lib/zaf/repo + ;; +esac diff --git a/install.sh b/install.sh index fea45a5..c02c64c 100755 --- a/install.sh +++ b/install.sh @@ -1,21 +1,44 @@ #!/bin/sh -if ! [ "$(basename $0)" = "install.sh" ]; then - # We are runing from stdin - url="https://raw.githubusercontent.com/limosek/zaf/master/" +if [ -z "$ZAF_URL" ]; then + # Runing as standalone install.sh. We have to download rest of files first. + [ -z "$ZAF_VERSION" ] && ZAF_VERSION=master + ZAF_URL="https://github.com/limosek/zaf/" +fi + +# Lite version of zaf_fetch_url, full version will be loaded later +zaf_fetch_url(){ + if [ -z "$ZAF_OFFLINE" ]; then + echo curl -f -k -s -L -o - "$1" >&2; 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 +zaf_download_files() { + rm -rf /tmp/zaf-installer + zaf_fetch_url $ZAF_URL/archive/$ZAF_VERSION.tar.gz | tar -C /tmp -zx && mv /tmp/zaf-$ZAF_VERSION /tmp/zaf-installer +} + +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 - set -e - mkdir -p /tmp/zaf-installer \ - && cd /tmp/zaf-installer \ - && (for i in lib/zaf.lib.sh lib/os.lib.sh lib/ctrl.lib.sh install.sh ; do echo curl -f -k -s -L -o - "$url/$i" >&2; curl -f -k -s -L -o - "$url/$i"; done) >install.sh \ - && chmod +x install.sh \ - && exec ./install.sh $auto "$@" - exit + 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 fi # Read options as config for ZAF @@ -24,18 +47,13 @@ for pair in "$@"; do 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 [ -z "$ZAF_DEBUG" ] && ZAF_DEBUG=1 -if [ -f $(dirname $0)/lib/zaf.lib.sh ]; then - . $(dirname $0)/lib/zaf.lib.sh - . $(dirname $0)/lib/os.lib.sh - . $(dirname $0)/lib/ctrl.lib.sh -fi - # 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. # $1 - option name @@ -87,34 +105,41 @@ zaf_set_option(){ fi } -zaf_getrest(){ - if [ -f "$(dirname $0)/$1" ]; then - echo "$(dirname $0)/$1" - else - curl -f -k -s -L -o - https://raw.githubusercontent.com/limosek/zaf/master/$1 >${ZAF_TMP_DIR}/$(basename $1) - echo ${ZAF_TMP_DIR}/$(basename $1) - fi -} - -# Set config option in zabbix agent +# Set config option in zabbix agent config file # $1 option # $2 value -# $3 if nonempty, do not remove opion from config, just add to the end zaf_set_agent_option() { local option="$1" local value="$2" - if [ -n "$3" ]; then - if ! grep -q "^$1=$2" $ZAF_AGENT_CONFIG; then - zaf_dbg "Adding option $option to $ZAF_AGENT_CONFIG." - echo "$option=$value" >>$ZAF_AGENT_CONFIG - fi - return - fi if grep ^$option\= $ZAF_AGENT_CONFIG; then - zaf_wrn "Moving option $option to zaf config part." - sed -i "s/$option=/#$option=/" $ZAF_AGENT_CONFIG + zaf_dbg "Setting option $option in $ZAF_AGENT_CONFIG." + sed -i "s/$option=(.*)/$option=$2/" $ZAF_AGENT_CONFIG fi - [ -n "$2" ] && echo "$option=$value" >> "$ZAF_AGENT_CONFIGD/zaf_options.conf" +} + +# Add config option in zabbix agent config file +# $1 option +# $2 value +zaf_add_agent_option() { + local option="$1" + local value="$2" + if ! grep -q "^$1=$2" $ZAF_AGENT_CONFIG; then + zaf_dbg "Adding option $option to $ZAF_AGENT_CONFIG." + echo "$option=$value" >>$ZAF_AGENT_CONFIG + fi +} + +# Move config option fron zabbix agent config file to zaf options file and set value +# $1 option +# $2 value +zaf_move_agent_option() { + local option="$1" + local value="$2" + if grep ^$option\= $ZAF_AGENT_CONFIG; then + zaf_dbg "Moving option $option from $ZAF_AGENT_CONFIG to ." + sed -i "s/$option=(.*)/$option=$2/" $ZAF_AGENT_CONFIG + fi + [ -n "$value" ] && echo "$option=$value" >> "$ZAF_AGENT_CONFIGD/zaf_options.conf" } # Automaticaly configure agent if supported @@ -160,8 +185,9 @@ zaf_configure(){ if which git >/dev/null; then ZAF_GIT=1 else - ZAF_GIT="" + ZAF_GIT=0 fi + zaf_get_option ZAF_GIT "Git is installed" "$ZAF_GIT" "$1" zaf_get_option ZAF_CURL_INSECURE "Insecure curl (accept all certificates)" "1" "$1" zaf_get_option ZAF_TMP_BASE "Tmp directory prefix (\$USER will be added)" "/tmp/zaf" "$1" zaf_get_option ZAF_LIB_DIR "Libraries directory" "/usr/lib/zaf" "$1" @@ -202,61 +228,33 @@ 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" + [ -n "$ZAF_PREPACKAGED_DIR" ] && zaf_set_option ZAF_PREPACKAGED_DIR "$ZAF_PREPACKAGED_DIR" ZAF_TMP_DIR="${ZAF_TMP_BASE}-${USER}-$$" -} -if [ -f "${ZAF_CFG_FILE}" ]; then - . "${ZAF_CFG_FILE}" -fi -ZAF_TMP_DIR="${ZAF_TMP_BASE-/tmp/zaf}-${USER}-$$" - -case $1 in -interactive) - shift - zaf_configure interactive - $0 install "$@" - ;; -auto) - shift - zaf_configure auto - $0 install "$@" - ;; -debug-auto) - shift; - ZAF_DEBUG=3 $0 auto "$@" - ;; -debug-interactive) - shift; - ZAF_DEBUG=3 $0 interactive "$@" - ;; -debug) - shift; - ZAF_DEBUG=3 $0 install "$@" - ;; -reconf) - shift; - rm -f $ZAF_CFG_FILE - $0 install "$@" - ;; -install) - zaf_configure auto - rm -rif ${ZAF_TMP_DIR} - mkdir -p ${ZAF_TMP_DIR} if zaf_is_root; then zaf_configure_agent $ZAF_AGENT_OPTIONS "$@" - zaf_set_agent_option "Include" "$ZAF_AGENT_CONFIGD" append + zaf_add_agent_option "Include" "$ZAF_AGENT_CONFIGD" fi +} + +zaf_install_all() { + rm -rif ${ZAF_TMP_DIR} + mkdir -p ${ZAF_TMP_DIR} zaf_install_dir ${ZAF_LIB_DIR} + for i in lib/zaf.lib.sh lib/os.lib.sh lib/ctrl.lib.sh README.md; do + zaf_install $i ${ZAF_LIB_DIR}/ + done + for i in lib/zaflock lib/preload.sh; do + zaf_install_bin $i ${ZAF_LIB_DIR}/ + done + zaf_install_dir ${ZAF_BIN_DIR} + for i in zaf; do + zaf_install_bin $i ${ZAF_BIN_DIR}/ + done zaf_install_dir ${ZAF_PLUGINS_DIR} - zaf_install $(zaf_getrest lib/zaf.lib.sh) ${ZAF_LIB_DIR} - zaf_install $(zaf_getrest lib/os.lib.sh) ${ZAF_LIB_DIR} - zaf_install $(zaf_getrest lib/ctrl.lib.sh) ${ZAF_LIB_DIR} - zaf_install_bin $(zaf_getrest lib/zaflock) ${ZAF_LIB_DIR} - zaf_install_bin $(zaf_getrest lib/preload.sh) ${ZAF_LIB_DIR} zaf_install_dir ${ZAF_TMP_DIR}/p/zaf zaf_install_dir ${ZAF_PLUGINS_DIR} zaf_install_dir ${ZAF_BIN_DIR} - zaf_install_bin $(zaf_getrest zaf) ${ZAF_BIN_DIR} export INSTALL_PREFIX ZAF_CFG_FILE ZAF_DEBUG if zaf_is_root; then [ "${ZAF_GIT}" = 1 ] && ${INSTALL_PREFIX}/${ZAF_BIN_DIR}/zaf update @@ -268,9 +266,55 @@ install) echo "Does ${ZAF_AGENT_RESTART} work?" exit 1 fi + else + [ "${ZAF_GIT}" = 1 ] && [ -n "${INSTALL_PREFIX}" ] && git clone "${ZAF_PLUGINS_GITURL}" "${INSTALL_PREFIX}/${ZAF_REPO_DIR}" fi rm -rif ${ZAF_TMP_DIR} echo "Install OK. Use 'zaf' without parameters to continue." +} + +if [ -f "${ZAF_CFG_FILE}" ]; then + . "${ZAF_CFG_FILE}" +fi +ZAF_TMP_DIR="${ZAF_TMP_BASE-/tmp/zaf}-${USER}-$$" + +case $1 in +interactive) + shift + zaf_configure interactive + zaf_install_all + ;; +auto) + shift + zaf_configure auto + zaf_install_all + ;; +debug-auto) + shift; + ZAF_DEBUG=4 + zaf_configure auto + zaf_install_all + ;; +debug-interactive) + shift; + ZAF_DEBUG=4 + zaf_configure interactive + zaf_install_all + ;; +debug) + shift; + ZAF_DEBUG=4 + zaf_configure auto + zaf_install_all + ;; +reconf) + shift; + rm -f $ZAF_CFG_FILE + zaf_configure auto + ;; +install) + zaf_configure auto + zaf_install_all ;; *) echo diff --git a/lib/zaf.lib.sh b/lib/zaf.lib.sh index 3c4300c..e08a539 100644 --- a/lib/zaf.lib.sh +++ b/lib/zaf.lib.sh @@ -1,7 +1,7 @@ # Hardcoded variables -ZAF_VERSION="trunk" -ZAF_URL="https://raw.githubusercontent.com/limosek/zaf/master/" +ZAF_VERSION="master" +ZAF_URL="https://github.com/limosek/zaf" ############################################ Common routines @@ -39,6 +39,7 @@ zaf_fetch_url() { fi case $scheme in http|https|ftp|file) + [ "$scheme" != "file" ] && [ -n "$ZAF_OFFLINE" ] && zaf_err "Cannot download $1 in offline mode!" [ "${ZAF_CURL_INSECURE}" = "1" ] && insecure="-k" zaf_dbg curl $insecure -f -s -L -o - $1 curl $insecure -f -s -L -o - "$1" @@ -131,7 +132,7 @@ zaf_discovery(){ # Restart zabbix agent zaf_restart_agent() { zaf_wrn "Restarting agent (${ZAF_AGENT_RESTART})" - ${ZAF_AGENT_RESTART} || zaf_err "Cannot restart Zabbix agent (${ZAF_AGENT_RESTART})!" + ${ZAF_AGENT_RESTART} || zaf_err "Cannot restart Zabbix agent (${ZAF_AGENT_RESTART}). Try $ZAF_AGENT_BIN -f !"; } # Check if zaf.version item is populated @@ -157,6 +158,7 @@ zaf_update_repo() { # 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 @@ -166,7 +168,11 @@ zaf_get_plugin_url() { if [ -d "${ZAF_REPO_DIR}/$1" ]; then url="${ZAF_REPO_DIR}/$1" else - url="${ZAF_PLUGINS_URL}/$1"; + if [ -n "${ZAF_PREPACKAGED_DIR}" ] && [ -d "${ZAF_PREPACKAGED_DIR}/$1" ]; then + url="${ZAF_PREPACKAGED_DIR}/$1" + else + zaf_err "Plugin $1 not found." + fi fi fi fi diff --git a/zaf b/zaf index aebb793..1e2fd88 100755 --- a/zaf +++ b/zaf @@ -8,6 +8,14 @@ else exit 2 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 "${option}='$value'" +done + [ -z "$ZAF_TMP_BASE" ] && ZAF_TMP_BASE=/tmp/zaf ZAF_TMP_DIR="${ZAF_TMP_BASE}-${USER}" trap "rm -rif ${ZAF_TMP_DIR}" EXIT @@ -127,6 +135,7 @@ remove) ;; 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; then @@ -143,6 +152,7 @@ self-upgrade) ;; self-remove) + zaf_os_specific zaf_check_deps zaf && zaf_err "Zaf is installed as system package. Cannot self-remove." . /etc/zaf.conf if [ "$2" = "force" ]; then rm -rf /etc/zaf.conf ${ZAF_PLUGINS_DIR} ${ZAF_REPO_DIR} ${ZAF_LIB_DIR} \ From 9b190e57ea41579120e66dbd726faa902081dcce Mon Sep 17 00:00:00 2001 From: Lukas Macura Date: Thu, 7 Apr 2016 13:20:55 +0200 Subject: [PATCH 17/33] Minor changes --- Makefile | 4 ++++ install.sh | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 072b824..3209a61 100644 --- a/Makefile +++ b/Makefile @@ -71,4 +71,8 @@ deb-changelog: deb-package: @dpkg-deb -b $(DEBIAN_DIR) $(DEBIAN_PKG) + @echo "\nCheck configuration:" + @cat $(DEBIAN_DIR)/etc/zaf.conf + @echo + diff --git a/install.sh b/install.sh index c02c64c..51269c9 100755 --- a/install.sh +++ b/install.sh @@ -111,7 +111,7 @@ zaf_set_option(){ zaf_set_agent_option() { local option="$1" local value="$2" - if grep ^$option\= $ZAF_AGENT_CONFIG; then + if grep -q ^$option\= $ZAF_AGENT_CONFIG; then zaf_dbg "Setting option $option in $ZAF_AGENT_CONFIG." sed -i "s/$option=(.*)/$option=$2/" $ZAF_AGENT_CONFIG fi @@ -135,7 +135,7 @@ zaf_add_agent_option() { zaf_move_agent_option() { local option="$1" local value="$2" - if grep ^$option\= $ZAF_AGENT_CONFIG; then + if grep -q ^$option\= $ZAF_AGENT_CONFIG; then zaf_dbg "Moving option $option from $ZAF_AGENT_CONFIG to ." sed -i "s/$option=(.*)/$option=$2/" $ZAF_AGENT_CONFIG fi From 531b3c31f684a1e56fef687de785cb0214dfa4a4 Mon Sep 17 00:00:00 2001 From: Lukas Macura Date: Tue, 12 Apr 2016 10:36:17 +0200 Subject: [PATCH 18/33] Switched working flow to trunk --- Makefile | 35 ++++++---- README.md | 100 +++++++++++++++++++++------ files/changelog.template | 2 +- files/postinst.template | 2 +- install.sh | 146 ++++++++++++++++++++++++++------------- lib/ctrl.lib.sh | 9 +-- lib/os.lib.sh | 18 ++--- lib/zaf.lib.sh | 62 ++++++++++++++--- zaf | 123 ++++++++++++++++++++++++--------- 9 files changed, 361 insertions(+), 136 deletions(-) diff --git a/Makefile b/Makefile index 3209a61..cadc4f4 100644 --- a/Makefile +++ b/Makefile @@ -4,14 +4,29 @@ CONTROLFILES=$(foreach p,$(PLUGINS),$(p)/control.zaf) ZAF_EXPORT_OPTS=$(foreach o,$(ZAF_OPTIONS),$(shell echo $(o)|cut -d '=' -f 1)) DEBIAN_DIR=tmp/deb DEBIAN_CTRL=$(DEBIAN_DIR)/DEBIAN -DEBIAN_PKG=out/zaf.deb +DEBIAN_PKG=$(shell . lib/zaf.lib.sh; echo out/zaf-$$ZAF_VERSION.deb) + +ifeq ($(ZAF_OPTIONS),) + ZAF_OPTIONS = ZAF_GIT=0 +endif +ifeq ($(IPLUGINS),) + IPLUGINS = zaf +endif all: help help: - @echo make '{deb|ipk|rpm}' '[PLUGINS="/dir/plg1 /dir/plg2] [ZAF_OPTIONS="ZAF_cfg=val ..."] [AGENT_OPTIONS="Z_Server=host ..."]' + @echo make '{deb|ipk|rpm}' '[PLUGINS="/dir/plg1 [/dir2]...] [IPLUGINS="plg1 [plg2]..."] [ZAF_OPTIONS="ZAF_cfg=val ..."] [AGENT_OPTIONS="Z_Server=host ..."]' + @echo PLUGINS are embedded into package. Has to be local directories accessible during build. + @echo IPLUGINS will be downloaded and installed after package is installed. Can be name or url accessible after package installation. + @echo -deb: deb-clean deb-init deb-deps deb-control deb-scripts deb-cp deb-package +deb: $(DEBIAN_PKG) + +$(DEBIAN_PKG): deb-clean deb-init deb-deps deb-control deb-scripts deb-cp deb-package + +clean: + @rm -rf tmp/* out/* deb-clean: @rm -rf $(DEBIAN_DIR) $(DEBIAN_PKG) @@ -29,22 +44,17 @@ deb-control: for p in $(PLUGINS); do \ DEPENDS="$$DEPENDS,$$(zaf_ctrl_get_global_option $$p/control.zaf Depends-dpkg | tr ' ' ',')"; \ done; \ - zaf_far '{ZAF_VERSION}' "0.1" $(DEBIAN_CTRL)/control + zaf_far '{ZAF_VERSION}' "$$ZAF_VERSION" $(DEBIAN_CTRL)/control deb-scripts: -ifneq ($(PLUGINS),) @. lib/zaf.lib.sh; \ . lib/ctrl.lib.sh; \ - for p in $(PLUGINS); do \ - plugins="$$plugins "$$(zaf_ctrl_get_global_option $$p/control.zaf Plugin) ; \ - done; \ - cat files/postinst.template | zaf_far '{PLUGINS}' "$$plugins" | zaf_far '{ZAF_LIB_DIR}' "/usr/lib/zaf" >$(DEBIAN_CTRL)/postinst + cat files/postinst.template | zaf_far '{PLUGINS}' "$(PLUGINS)" | zaf_far "{IPLUGINS}" "$(IPLUGINS)" | zaf_far '{ZAF_LIB_DIR}' "/usr/lib/zaf" >$(DEBIAN_CTRL)/postinst @chmod +x $(DEBIAN_CTRL)/postinst @cp files/preinst.template $(DEBIAN_CTRL)/preinst @chmod +x $(DEBIAN_CTRL)/preinst @cp files/prerm.template $(DEBIAN_CTRL)/prerm @chmod +x $(DEBIAN_CTRL)/prerm -endif deb-cp: @mkdir -p $(DEBIAN_DIR) @@ -66,13 +76,12 @@ ifneq ($(AGENT_OPTIONS),) @echo "ZAF_AGENT_OPTIONS=\"$(AGENT_OPTIONS)\"" >>$(DEBIAN_DIR)/etc/zaf.conf endif -deb-changelog: - @cp files/changelog.template $(DEBIAN_CTRL)/changelog - deb-package: @dpkg-deb -b $(DEBIAN_DIR) $(DEBIAN_PKG) @echo "\nCheck configuration:" @cat $(DEBIAN_DIR)/etc/zaf.conf + @echo PLUGINS embedded: $(PLUGINS) + @echo PLUGINS in postinst: $(IPLUGINS) @echo diff --git a/README.md b/README.md index 5e327f4..0b786eb 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ If you are maintainer of some external check, it is enough to create zaf file in ## Motivation -Did you install lot of zabbix agents? 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? So zaf is here for you :) ## Features @@ -21,60 +21,121 @@ 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. * OS packaging support (in future). * Zabbix agent autoinstallation and autoconfiguration suitable to use in puppet or another tool +* OS packaging support ## 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: ``` -curl -k https://raw.githubusercontent.com/limosek/zaf/master/install.sh | sh +curl -k https://raw.githubusercontent.com/limosek/zaf/1.0/install.sh | sh ``` ### Install options and autoconfiguration General parameters for install.sh on any system (simplest way how to install) ``` -curl -k https://raw.githubusercontent.com/limosek/zaf/master/install.sh | \ +curl -k https://raw.githubusercontent.com/limosek/zaf/1.0/install.sh | \ sh -s {auto|interactive|debug-auto|debug-interactive} [Agent-Options] [Zaf-Options] ``` or use git version: ``` -git clone https://github.com/limosek/zaf.git +git clone https://github.com/limosek/zaf.git; cd zaf; git checkout 1.0 ./install.sh {auto|interactive|debug-auto|debug-interactive} [Agent-Options] [Zaf-Options] - Agent-Options: A_Option=value [...] + Agent-Options: Z_Option=value [...] Zaf-Options: ZAF_OPT=value [...] + To unset Agent-Option use Z_Option='' ``` So you can pass ANY configuration of your zabbix agent directly to installer prefixing it with *Z_*. Please note that options are *Case Sensitive*! -Next to this, you can pass ANY zaf config options by *ZAF_* prefix. Yes, we need some more documentation of ZAF options. Please look at least here: https://github.com/limosek/zaf/blob/master/install.sh#L160 +Next to this, you can pass ANY zaf config options by *ZAF_* prefix. Interresting ZAF options: +``` + # If we want to use GIT and local GIT repository + ZAF_GIT='1'# Default + + # Git repository. Can be your local version + ZAF_REPO_GITURL='https://github.com/limosek/zaf-plugins.git' + + # Where to install plugins + ZAF_PLUGINS_DIR='/usr/lib/zaf/plugins' + + # Plugins can be downloaded from http[s] too + ZAF_REPO_URL='https://raw.githubusercontent.com/limosek/zaf-plugins/master/' + +``` + Installer will try to autoguess suitable config options for your system. -Now everything was tested on Debian and OpenWrt. If somebody is interrested in, you can help and test with some rpm specific functions. +Now everything was tested on Debian and OpenWrt. If somebody is interrested in, you can help and test with some rpm specific functions. Remember that on some systems, default zabbix agent config is empty so you *need to* enter essential config options as parameters. ### Example Suppose you want to autoinstall agent on clean system. You need only curl installed. Everything else is one-cmd process. This command will install zaf, install zabbix-agent if necessary and sets zabbix variables on agent to reach server. This command can be automatized by puppet or another deploying system. ``` -curl -k https://raw.githubusercontent.com/limosek/zaf/master/install.sh | sh -s auto \ +curl -k https://raw.githubusercontent.com/limosek/zaf/1.0/install.sh | sh -s auto \ Z_Server=zabbix.server.local \ Z_ServerActive=zabbix.server.local \ Z_HostnameItem=system.hostname Z_RefreshActiveChecks=60 \ - ZAF_PLUGINS_GITURL="git://gitserver.local" + ZAF_REPO_GITURL="git://gitserver.local" +``` + +### Packaged version +You can make your own deb package with preconfigured option. It is up to you to put it to right APT repository and install. +``` +git clone https://github.com/limosek/zaf.git \ + && cd zaf \ + && git checkout 1.0 \ + && git clone https://github.com/limosek/zaf-plugins.git \ + && make deb PLUGINS="./zaf-plugins/fsx" IPLUGINS="zaf" ZAF_OPTIONS="ZAF_GIT=0" AGENT_OPTIONS="Z_Server=zabbix.server Z_ServerActive=zabbix.server Z_StartAgents=8" +sudo dpkg -i out/zaf-1.0.deb +``` +General usage: +``` +make {deb|ipk|rpm} [PLUGINS="/dir/plg1 [/dir2]...] [IPLUGINS="plg1 [plg2]..."] [ZAF_OPTIONS="ZAF_cfg=val ..."] [AGENT_OPTIONS="Z_Server=host ..."] +PLUGINS are embedded into package. Has to be local directories accessible during build. +IPLUGINS will be downloaded and installed after package is installed. Can be name or url accessible after package installation. ``` ## Zaf plugin Zaf plugin is set of configuration options and binaries which are needed for specific checks. For example, to monitor postfix, we need some cron job which is automaticaly run and next ti this, some external items which has to be configured. Do not mix zaf plugin and zabbix plugin. While zaf plugin is set of scripts or binaries external to zabbix agent, zabbix plugin is internal zabbix lodadable module. +### Control file +Control file is main part of zaf plugin. It describes how to install plugin and defines all checks. In fact, simple control file can be enough to create zaf plugin because scripts can be embeded within. There are two kind of options: global and per item. Each option can be singleline: +``` +Plugin: pluginname +``` +or multiline: +``` +Description:: + Zaf plugin for monitoring fail2ban with LLD + Credits + 2014 dron, jiri.slezka@slu.cz + 2016 limo, lukas.macura@slu.cz +:: +``` +Items are enclosed like this: +``` +Item some_item: +Description:: + Returns number of currently banned IPs for jail +:: +Parameters: jail +Cmd: sudo fail2ban-client status $1 | grep "Currently banned:" | grep -o -E "[0-9]*" +/Item +``` +During plugin installation, zaf will check all dependencies, do install binaries and generates apropriate zabbix.conf.d entries. Look into https://github.com/limosek/zaf-plugins repository for more examples. + ## Zaf utility Zaf binary can be installed on any system from openwrt to big system. It has minimal dependencies and is shell based. Is has minimal size (up to 50kb of code). It can be used for installing, removing and testing zaf plugin items. Zaf should be run as root. ``` zaf -/usr/bin/zaf Version trunk. Please use some of this commands: -/usr/bin/zaf update To update repo -/usr/bin/zaf plugins To list installed plugins -/usr/bin/zaf show [plugin] To show installed plugins or plugin info -/usr/bin/zaf items [plugin] To list all suported items [for plugin] -/usr/bin/zaf test [plugin[.item]] To test all suported items [for plugin] -/usr/bin/zaf install plugin To install plugin -/usr/bin/zaf remove plugin To remove plugin -/usr/bin/zaf self-upgrade To self-upgrade zaf -/usr/bin/zaf self-remove To self-remove zaf and its config +zaf Version 1.0. Please use some of this commands: +zaf update To update repo +zaf plugins To list installed plugins +zaf show [plugin] To show installed plugins or plugin info +zaf items [plugin] To list all suported items [for plugin] +zaf test [plugin[.item]] To test [all] suported items by zabbix_agentd [for plugin] +zaf get [plugin[.item]] To test [all] suported items by zabbix_get [for plugin] +zaf install plugin To install plugin +zaf remove plugin To remove plugin +zaf self-upgrade To self-upgrade zaf +zaf self-remove To self-remove zaf and its config ``` @@ -96,7 +157,6 @@ Installer will look into control file, run setup task defined there, fetch binar ## How it works Zaf installer will do most of actions needed to monitor some specific plugin items. Configuration of plugin is very simple and text readable. Anybody can write its own plugin or make its plugin "zafable". It is enough to create *control.zaf" file. For example, look into https://github.com/limosek/zaf-plugins repository. This is default repository for zaf. - ## I want to make my own plugin! Great! Look into https://github.com/limosek/zaf-plugins repository, look to control files and try to create your own. It is easy! You can contact me for help. diff --git a/files/changelog.template b/files/changelog.template index 98bcb73..8057848 100644 --- a/files/changelog.template +++ b/files/changelog.template @@ -1,4 +1,4 @@ -PACKAGE (0.1) zaf; urgency=medium +PACKAGE (1.0) zaf; urgency=medium * Initial release. diff --git a/files/postinst.template b/files/postinst.template index 45e6060..e5abaf1 100644 --- a/files/postinst.template +++ b/files/postinst.template @@ -8,7 +8,7 @@ configure) . /usr/lib/zaf/os.lib.sh . /usr/lib/zaf/ctrl.lib.sh cd /usr/lib/zaf && /usr/lib/zaf/install.sh reconf - zaf reinstall {PLUGINS} + zaf reinstall {PLUGINS} {IPLUGINS} fi ;; esac diff --git a/install.sh b/install.sh index 51269c9..369efb9 100755 --- a/install.sh +++ b/install.sh @@ -1,8 +1,9 @@ #!/bin/sh +[ -z "$ZAF_DEBUG" ] && ZAF_DEBUG=1 if [ -z "$ZAF_URL" ]; then # Runing as standalone install.sh. We have to download rest of files first. - [ -z "$ZAF_VERSION" ] && ZAF_VERSION=master + [ -z "$ZAF_VERSION" ] && ZAF_VERSION=1.0 ZAF_URL="https://github.com/limosek/zaf/" fi @@ -19,7 +20,7 @@ zaf_fetch_url(){ # Download tgz and extract to /tmp/zaf-installer zaf_download_files() { rm -rf /tmp/zaf-installer - zaf_fetch_url $ZAF_URL/archive/$ZAF_VERSION.tar.gz | tar -C /tmp -zx && mv /tmp/zaf-$ZAF_VERSION /tmp/zaf-installer + zaf_fetch_url $ZAF_URL/archive/$ZAF_VERSION.tar.gz | tar -f - -C /tmp -zx && mv /tmp/zaf-$ZAF_VERSION /tmp/zaf-installer } if ! [ -f README.md ]; then @@ -52,7 +53,6 @@ done [ -z "$ZAF_CFG_FILE" ] && ZAF_CFG_FILE=$INSTALL_PREFIX/etc/zaf.conf [ -n "$C_ZAF_DEBUG" ] && ZAF_DEBUG=$C_ZAF_DEBUG -[ -z "$ZAF_DEBUG" ] && ZAF_DEBUG=1 # 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. @@ -99,9 +99,10 @@ zaf_set_option(){ local description if ! grep -q "^$1=" ${ZAF_CFG_FILE}; then echo "$1='$2'" >>${ZAF_CFG_FILE} - zaf_dbg "Saving $1 to $2 in ${ZAF_CFG_FILE}" >&2 + zaf_dbg "Saving $1 to $2 in ${ZAF_CFG_FILE}" else - zaf_wrn "Preserving $1 to $2 in ${ZAF_CFG_FILE}" >&2 + sed -i "s#^$1=\(.*\)#$1='$2'#" ${ZAF_CFG_FILE} + zaf_dbg "Changing $1 to $2 in ${ZAF_CFG_FILE}" fi } @@ -113,7 +114,20 @@ zaf_set_agent_option() { local value="$2" if grep -q ^$option\= $ZAF_AGENT_CONFIG; then zaf_dbg "Setting option $option in $ZAF_AGENT_CONFIG." - sed -i "s/$option=(.*)/$option=$2/" $ZAF_AGENT_CONFIG + sed -i "s/$option=\(.*\)/$option=$2/" $ZAF_AGENT_CONFIG + else + zaf_move_agent_option "$1" "$2" + fi +} + +# Unset config option in zabbix agent config file +# $1 option +zaf_unset_agent_option() { + local option="$1" + local value="$2" + if grep -q ^$option\= $ZAF_AGENT_CONFIG; then + zaf_dbg "Unsetting option $option in $ZAF_AGENT_CONFIG." + sed -i "s/$option=\(.*\)/#$option=$2/" $ZAF_AGENT_CONFIG fi } @@ -157,27 +171,36 @@ zaf_configure_agent() { echo $pair | grep -q '^Z\_' || continue # Skip non Z_ vars option=$(echo $pair|cut -d '=' -f 1|cut -d '_' -f 2) value=$(echo $pair|cut -d '=' -f 2-) - zaf_set_agent_option "$option" "$value" + if [ -n "$value" ]; then + zaf_set_agent_option "$option" "$value" + else + zaf_unset_agent_option "$option" + fi options="$options Z_$option='$value'" done zaf_set_option ZAF_AGENT_OPTIONS "${options}" } -zaf_configure(){ - +zaf_preconfigure(){ zaf_detect_system zaf_os_specific zaf_configure_os - if ! zaf_is_root; then + if ! zaf_is_root; then [ -z "$INSTALL_PREFIX" ] && zaf_err "We are not root. Use INSTALL_PREFIX or become root." + else + [ "$1" != "reconf" ] && zaf_os_specific zaf_check_deps zaf && zaf_err "Zaf is installed as system package. Cannot install." fi - zaf_get_option ZAF_PKG "Packaging system to use" "$ZAF_PKG" "$1" - zaf_get_option ZAF_OS "Operating system to use" "$ZAF_OS" "$1" - zaf_get_option ZAF_OS_CODENAME "Operating system codename" "$ZAF_OS_CODENAME" "$1" - zaf_get_option ZAF_AGENT_PKG "Zabbix agent package" "$ZAF_AGENT_PKG" "$1" - zaf_get_option ZAF_AGENT_OPTIONS "Zabbix options to set in cfg" "$ZAF_AGENT_OPTIONS" "$1" +} + +zaf_configure(){ + + zaf_get_option ZAF_PKG "Packaging system to use" "$ZAF_PKG" "$INSTALL_MODE" + zaf_get_option ZAF_OS "Operating system to use" "$ZAF_OS" "$INSTALL_MODE" + zaf_get_option ZAF_OS_CODENAME "Operating system codename" "$ZAF_OS_CODENAME" "$INSTALL_MODE" + zaf_get_option ZAF_AGENT_PKG "Zabbix agent package" "$ZAF_AGENT_PKG" "$INSTALL_MODE" + zaf_get_option ZAF_AGENT_OPTIONS "Zabbix options to set in cfg" "$ZAF_AGENT_OPTIONS" "$INSTALL_MODE" if zaf_is_root && [ -n "$ZAF_AGENT_PKG" ]; then if ! zaf_os_specific zaf_check_deps "$ZAF_AGENT_PKG"; then - if [ "$1" = "auto" ]; then + if [ "$INSTALL_MODE" = "auto" ]; then zaf_os_specific zaf_install_agent fi fi @@ -187,20 +210,20 @@ zaf_configure(){ else ZAF_GIT=0 fi - zaf_get_option ZAF_GIT "Git is installed" "$ZAF_GIT" "$1" - zaf_get_option ZAF_CURL_INSECURE "Insecure curl (accept all certificates)" "1" "$1" - zaf_get_option ZAF_TMP_BASE "Tmp directory prefix (\$USER will be added)" "/tmp/zaf" "$1" - zaf_get_option ZAF_LIB_DIR "Libraries directory" "/usr/lib/zaf" "$1" - zaf_get_option ZAF_BIN_DIR "Directory to put binaries" "/usr/bin" "$1" - zaf_get_option ZAF_PLUGINS_DIR "Plugins directory" "${ZAF_LIB_DIR}/plugins" "$1" - [ "${ZAF_GIT}" = 1 ] && zaf_get_option ZAF_PLUGINS_GITURL "Git plugins repository" "https://github.com/limosek/zaf-plugins.git" "$1" - zaf_get_option ZAF_PLUGINS_URL "Plugins http[s] repository" "https://raw.githubusercontent.com/limosek/zaf-plugins/master/" "$1" - zaf_get_option ZAF_REPO_DIR "Plugins directory" "${ZAF_LIB_DIR}/repo" "$1" - zaf_get_option ZAF_AGENT_CONFIG "Zabbix agent config" "/etc/zabbix/zabbix_agentd.conf" "$1" + 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_TMP_BASE "Tmp directory prefix (\$USER will be added)" "/tmp/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_PLUGINS_DIR "Plugins directory" "${ZAF_LIB_DIR}/plugins" "$INSTALL_MODE" + [ "${ZAF_GIT}" = 1 ] && zaf_get_option ZAF_REPO_GITURL "Git plugins repository" "https://github.com/limosek/zaf-plugins.git" "$INSTALL_MODE" + zaf_get_option ZAF_REPO_URL "Plugins http[s] repository" "https://raw.githubusercontent.com/limosek/zaf-plugins/master/" "$INSTALL_MODE" + zaf_get_option ZAF_REPO_DIR "Plugins directory" "${ZAF_LIB_DIR}/repo" "$INSTALL_MODE" + zaf_get_option ZAF_AGENT_CONFIG "Zabbix agent config" "/etc/zabbix/zabbix_agentd.conf" "$INSTALL_MODE" ! [ -d "${ZAF_AGENT_CONFIGD}" ] && [ -d "/etc/zabbix/zabbix_agentd.d" ] && ZAF_AGENT_CONFIGD="/etc/zabbix/zabbix_agentd.d" - zaf_get_option ZAF_AGENT_CONFIGD "Zabbix agent config.d" "/etc/zabbix/zabbix_agentd.conf.d/" "$1" - zaf_get_option ZAF_AGENT_BIN "Zabbix agent binary" "/usr/sbin/zabbix_agentd" "$1" - zaf_get_option ZAF_AGENT_RESTART "Zabbix agent restart cmd" "service zabbix-agent restart" "$1" + 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" if zaf_is_root && ! [ -x $ZAF_AGENT_BIN ]; then zaf_err "Zabbix agent ($ZAF_AGENT_BIN) not installed? Use ZAF_AGENT_BIN env variable to specify location. Exiting." @@ -221,15 +244,14 @@ zaf_configure(){ zaf_set_option ZAF_LIB_DIR "$ZAF_LIB_DIR" zaf_set_option ZAF_BIN_DIR "$ZAF_BIN_DIR" zaf_set_option ZAF_PLUGINS_DIR "$ZAF_PLUGINS_DIR" - zaf_set_option ZAF_PLUGINS_URL "$ZAF_PLUGINS_URL" - [ "${ZAF_GIT}" = 1 ] && zaf_set_option ZAF_PLUGINS_GITURL "$ZAF_PLUGINS_GITURL" + zaf_set_option ZAF_REPO_URL "$ZAF_REPO_URL" + [ "${ZAF_GIT}" = 1 ] && zaf_set_option ZAF_REPO_GITURL "$ZAF_REPO_GITURL" zaf_set_option ZAF_REPO_DIR "$ZAF_REPO_DIR" zaf_set_option ZAF_AGENT_CONFIG "$ZAF_AGENT_CONFIG" 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" [ -n "$ZAF_PREPACKAGED_DIR" ] && zaf_set_option ZAF_PREPACKAGED_DIR "$ZAF_PREPACKAGED_DIR" - ZAF_TMP_DIR="${ZAF_TMP_BASE}-${USER}-$$" if zaf_is_root; then zaf_configure_agent $ZAF_AGENT_OPTIONS "$@" @@ -252,11 +274,12 @@ zaf_install_all() { zaf_install_bin $i ${ZAF_BIN_DIR}/ done zaf_install_dir ${ZAF_PLUGINS_DIR} - zaf_install_dir ${ZAF_TMP_DIR}/p/zaf zaf_install_dir ${ZAF_PLUGINS_DIR} zaf_install_dir ${ZAF_BIN_DIR} - export INSTALL_PREFIX ZAF_CFG_FILE ZAF_DEBUG - if zaf_is_root; then +} + +zaf_postconfigure() { + if zaf_is_root; then [ "${ZAF_GIT}" = 1 ] && ${INSTALL_PREFIX}/${ZAF_BIN_DIR}/zaf update ${INSTALL_PREFIX}/${ZAF_BIN_DIR}/zaf reinstall zaf || zaf_err "Error installing zaf plugin." if zaf_is_root && ! zaf_test_item zaf.framework_version; then @@ -267,62 +290,91 @@ zaf_install_all() { exit 1 fi else - [ "${ZAF_GIT}" = 1 ] && [ -n "${INSTALL_PREFIX}" ] && git clone "${ZAF_PLUGINS_GITURL}" "${INSTALL_PREFIX}/${ZAF_REPO_DIR}" + [ "${ZAF_GIT}" = 1 ] && [ -n "${INSTALL_PREFIX}" ] && git clone "${ZAF_REPO_GITURL}" "${INSTALL_PREFIX}/${ZAF_REPO_DIR}" fi - rm -rif ${ZAF_TMP_DIR} - echo "Install OK. Use 'zaf' without parameters to continue." + zaf_wrn "Install done. Use 'zaf' to get started. Do not forget to do 'zaf upgrade' to upgrade plugins too!" + true } if [ -f "${ZAF_CFG_FILE}" ]; then . "${ZAF_CFG_FILE}" fi -ZAF_TMP_DIR="${ZAF_TMP_BASE-/tmp/zaf}-${USER}-$$" +ZAF_TMP_DIR="/tmp/zaf-installer-tmp/" + +# If debug is on, do not remove tmp dir +if [ "$ZAF_DEBUG" -le 3 ]; then + trap "rm -rif ${ZAF_TMP_DIR}" EXIT + trap "rm -rif /tmp/zaf-installer" EXIT +fi +! [ -d "${ZAF_TMP_DIR}" ] && mkdir "${ZAF_TMP_DIR}" case $1 in interactive) shift - zaf_configure interactive + INSTALL_MODE=interactive + zaf_preconfigure + zaf_configure "$@" zaf_install_all + zaf_postconfigure ;; auto) shift - zaf_configure auto + INSTALL_MODE=auto + zaf_preconfigure + zaf_configure "$@" zaf_install_all + zaf_postconfigure ;; debug-auto) shift; ZAF_DEBUG=4 - zaf_configure auto + INSTALL_MODE=auto + zaf_preconfigure + zaf_configure "$@" zaf_install_all + zaf_postconfigure ;; debug-interactive) shift; ZAF_DEBUG=4 - zaf_configure interactive + INSTALL_MODE=interactive + zaf_preconfigure + zaf_configure "$@" zaf_install_all + zaf_postconfigure ;; debug) shift; ZAF_DEBUG=4 - zaf_configure auto + INSTALL_MODE=auto + zaf_preconfigure + zaf_configure "$@" zaf_install_all + zaf_postconfigure ;; reconf) shift; rm -f $ZAF_CFG_FILE - zaf_configure auto + INSTALL_MODE=auto + zaf_preconfigure reconf + zaf_configure "$@" + zaf_postconfigure ;; install) - zaf_configure auto + INSTALL_MODE=auto + zaf_preconfigure nor + zaf_configure "$@" zaf_install_all + zaf_postconfigure ;; *) echo echo "Please specify how to install." echo "install.sh {auto|interactive|debug-auto|debug-interactive|reconf} [Agent-Options] [Zaf-Options]" echo "scratch means that config file will be created from scratch" - echo " Agent-Options: A_Option=value [...]" + echo " Agent-Options: Z_Option=value [...]" echo " Zaf-Options: ZAF_OPT=value [...]" + echo " To unset Agent-Option use Z_Option=''" echo echo "Example 1 (default install): install.sh auto" echo 'Example 2 (preconfigure agent options): install.sh auto A_Server=zabbix.server A_ServerActive=zabbix.server A_Hostname=$(hostname)' diff --git a/lib/ctrl.lib.sh b/lib/ctrl.lib.sh index 028404d..05f9b12 100644 --- a/lib/ctrl.lib.sh +++ b/lib/ctrl.lib.sh @@ -71,12 +71,13 @@ zaf_ctrl_get_item_option() { zaf_ctrl_check_deps() { local deps deps=$(zaf_ctrl_get_global_block <$1 | zaf_block_get_option "Depends-${ZAF_PKG}" ) - zaf_os_specific zaf_check_deps $deps + if ! zaf_os_specific zaf_check_deps $deps; then + zaf_err "Missing one of dependend system packages: $deps" + fi deps=$(zaf_ctrl_get_global_block <$1 | zaf_block_get_option "Depends-bin" ) for cmd in $deps; do if ! which $cmd >/dev/null; then - zaf_wrn "Missing binary dependency $cmd. Please install it first." - return 1 + zaf_err "Missing binary dependency $cmd. Please install it first." fi done } @@ -139,7 +140,7 @@ zaf_ctrl_generate_cfg() { fi cmd=$(zaf_ctrl_get_item_option $1 $i "Function") if [ -n "$cmd" ]; then - $(which echo) -E "UserParameter=$ikey,${ZAF_LIB_DIR}/preload.sh $lock$cmd"; + $(which echo) "UserParameter=$ikey,${ZAF_LIB_DIR}/preload.sh $lock$cmd"; continue; fi cmd=$(zaf_ctrl_get_item_option $1 $i "Script") diff --git a/lib/os.lib.sh b/lib/os.lib.sh index cb5c0ff..48ea6a5 100644 --- a/lib/os.lib.sh +++ b/lib/os.lib.sh @@ -12,28 +12,30 @@ zaf_configure_os_freebsd() { ZAF_AGENT_PKG="zabbix3-agent" ZAF_AGENT_CONFIG="/usr/local/etc/zabbix3/zabbix_agentd.conf" ZAF_AGENT_CONFIGD="/usr/local/etc/zabbix3/zabbix_agentd.conf.d/" + ZAF_AGENT_BIN="/usr/local/sbin/zabbix_agentd" + ZAF_AGENT_RESTART="service zabbix_agentd restart" } zaf_detect_system() { if which dpkg >/dev/null; then ZAF_PKG=dpkg - ZAF_OS=$(lsb_release -is|tr '[:upper:]' '[:lower:]') - ZAF_OS_CODENAME=$(lsb_release -cs|tr '[:upper:]' '[:lower:]') + ZAF_OS=$(lsb_release -is|zaf_tolower) + ZAF_OS_CODENAME=$(lsb_release -cs|zaf_tolower) ZAF_CURL_INSECURE=0 ZAF_AGENT_PKG="zabbix-agent" return else if which rpm >/dev/null; then ZAF_PKG="rpm" - ZAF_OS=$(lsb_release -is|tr '[:upper:]' '[:lower:]') - ZAF_OS_CODENAME=$(lsb_release -cs|tr '[:upper:]' '[:lower:]') + ZAF_OS=$(lsb_release -is|zaf_tolower) + ZAF_OS_CODENAME=$(lsb_release -cs|zaf_tolower) ZAF_CURL_INSECURE=0 ZAF_AGENT_PKG="zabbix-agent" return else if which opkg >/dev/null; then ZAF_PKG="opkg" . /etc/openwrt_release - ZAF_OS="$(echo $DISTRIB_ID|tr '[:upper:]' '[:lower:]')" - ZAF_OS_CODENAME="$(echo $DISTRIB_CODENAME|tr '[:upper:]' '[:lower:]')" + ZAF_OS="$(echo $DISTRIB_ID|zaf_tolower)" + ZAF_OS_CODENAME="$(echo $DISTRIB_CODENAME|zaf_tolower)" return else if which pkg >/dev/null; then ZAF_PKG="pkg" @@ -145,7 +147,7 @@ zaf_check_deps_rpm() { zaf_check_deps_opkg() { local p for p in $*; do - opkg info $p | grep -q 'Package:' || { echo "Missing package $p" >&2; return 1; } + opkg info $p | grep -q 'Package:' || { return 1; } done } @@ -154,7 +156,7 @@ zaf_check_deps_opkg() { zaf_check_deps_pkg() { local p for p in $*; do - pkg query -x "Package: %n" $p| grep -q 'Package:' || { echo "Missing package $p" >&2; return 1; } + pkg query -x "Package: %n" $p| grep -q 'Package:' || { return 1; } done } diff --git a/lib/zaf.lib.sh b/lib/zaf.lib.sh index e08a539..c45716b 100644 --- a/lib/zaf.lib.sh +++ b/lib/zaf.lib.sh @@ -2,6 +2,7 @@ # Hardcoded variables ZAF_VERSION="master" ZAF_URL="https://github.com/limosek/zaf" +ZAF_RAW_URL="https://raw.githubusercontent.com/limosek/zaf" ############################################ Common routines @@ -143,11 +144,11 @@ zaf_check_agent_config() { # Update repo zaf_update_repo() { - [ "$ZAF_GIT" != 1 ] && { zaf_err "Git is not installed. Exiting."; } - if [ -z "${ZAF_PLUGINS_GITURL}" ] || [ -z "${ZAF_REPO_DIR}" ]; then + [ "$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_PLUGINS_GITURL}" "${ZAF_REPO_DIR}" + [ ! -d "${ZAF_REPO_DIR}" ] && git clone "${ZAF_REPO_GITURL}" "${ZAF_REPO_DIR}" (cd ${ZAF_REPO_DIR} && git pull) fi } @@ -171,7 +172,11 @@ zaf_get_plugin_url() { if [ -n "${ZAF_PREPACKAGED_DIR}" ] && [ -d "${ZAF_PREPACKAGED_DIR}/$1" ]; then url="${ZAF_PREPACKAGED_DIR}/$1" else - zaf_err "Plugin $1 not found." + if [ -n "${ZAF_REPO_URL}" ]; then + url="${ZAF_REPO_URL}/$1" + else + zaf_err "Cannot find plugin $1" + fi fi fi fi @@ -183,6 +188,7 @@ zaf_get_plugin_url() { zaf_plugin_info() { local control="$1" + ! [ -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) @@ -209,7 +215,7 @@ zaf_prepare_plugin() { local plugindir local control - url=$(zaf_get_plugin_url "$1")/control.zaf + url=$(zaf_get_plugin_url "$1")/control.zaf || exit $? plugindir="$2" control=${plugindir}/control.zaf zaf_install_dir "$plugindir" @@ -217,7 +223,7 @@ zaf_prepare_plugin() { if zaf_fetch_url "$url" >"${control}"; then zaf_ctrl_check_deps "${control}" else - zaf_err "Cannot fetch or write control file!" + zaf_err "prepare_plugin: Cannot fetch or write control file $control from url $url!" fi } @@ -231,7 +237,7 @@ zaf_install_plugin() { url=$(zaf_get_plugin_url "$1") plugin=$(zaf_ctrl_get_global_block <"${ZAF_TMP_DIR}/plugin/control.zaf" | zaf_block_get_option Plugin) plugindir="${ZAF_PLUGINS_DIR}"/$plugin - if zaf_prepare_plugin "$1" $plugindir; then + if [ -n "$plugin" ] && zaf_prepare_plugin "$1" $plugindir; then control=${plugindir}/control.zaf [ "$ZAF_DEBUG" -gt 0 ] && zaf_plugin_info "${control}" zaf_ctrl_check_deps "${control}" @@ -240,7 +246,7 @@ zaf_install_plugin() { | zaf_far '{PLUGINDIR}' "${plugindir}" >${ZAF_AGENT_CONFIGD}/zaf_${plugin}.conf zaf_dbg "Generated ${ZAF_AGENT_CONFIGD}/zaf_${plugin}.conf" else - zaf_err "Cannot install plugin $plugin to $plugindir!" + zaf_err "Cannot install plugin '$plugin' to $plugindir!" fi else zaf_err "Cannot prepare plugin $1" @@ -266,7 +272,9 @@ zaf_discovery_plugins() { zaf_list_plugins | zaf_discovery '{#PLUGIN}' } -zaf_plugin_version() { +# $1 plugin +# $2 ctrl_option +zaf_plugin_option() { local plugindir local cfile @@ -276,12 +284,28 @@ zaf_plugin_version() { if zaf_is_plugin "$1"; then plugindir="${ZAF_PLUGINS_DIR}/$1" cfile="$plugindir/control.zaf" - zaf_ctrl_get_global_option $cfile Version + 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 +} + zaf_list_plugin_items() { local items local i @@ -312,7 +336,18 @@ zaf_list_items() { done } +zaf_get_item() { + if which zabbix_get >/dev/null; then + zabbix_get -s localhost -k "$1" || 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() { + [ "$USER" != "zabbix" ] && zaf_wrn "You are not zabbix user. Test will be run with your privileges and sudo access!" $ZAF_AGENT_BIN -t "$1" } @@ -323,4 +358,11 @@ zaf_remove_plugin() { rm -f ${ZAF_AGENT_CONFIGD}/zaf_${plugin}.conf } +zaf_tolower() { + tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' +} + +zaf_toupper() { + tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +} diff --git a/zaf b/zaf index 1e2fd88..6c70dda 100755 --- a/zaf +++ b/zaf @@ -18,9 +18,15 @@ done [ -z "$ZAF_TMP_BASE" ] && ZAF_TMP_BASE=/tmp/zaf ZAF_TMP_DIR="${ZAF_TMP_BASE}-${USER}" -trap "rm -rif ${ZAF_TMP_DIR}" EXIT -! [ -d "${ZAF_TMP_DIR}" ] && mkdir "${ZAF_TMP_DIR}" [ -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 [ -f ./lib/zaf.lib.sh ]; then . ./lib/zaf.lib.sh @@ -34,6 +40,25 @@ else [ -f ${ZAF_LIB_DIR}/zaf.${ZAF_OS}.sh ] && . ${ZAF_LIB_DIR}/zaf.${ZAF_OS}.sh fi +zaf_shift(){ + local s + + if echo $1 |grep -q "="; then + if echo $2 |grep -q "="; then + if echo $3 |grep -q "="; then + s=3 + else + s=2 + fi + else + s=1 + fi + else + s=0 + fi + echo $s +} + case $1 in check-agent-config) @@ -41,24 +66,30 @@ check-agent-config) ;; update) - zaf_wrn "Updating repository ${ZAF_PLUGINS_GITURL}..." + zaf_wrn "Updating repository ${ZAF_REPO_GITURL}..." zaf_update_repo ;; - +upgrade) + zaf_list_plugins | while read plugin; do + ZAF_DEBUG=$ZAF_DEBUG $0 reinstall $plugin || zaf_err "Error upgrading $plugin" + done + ;; show) - if [ -z "$2" ]; then + shift; + shift $(zaf_shift "$@") + if [ -z "$1" ]; then zaf_list_plugins | while read plugin; do zaf_plugin_info $ZAF_PLUGINS_DIR/$plugin/control.zaf done - else - if zaf_list_plugins | grep -q "^$2"; then - zaf_plugin_info $ZAF_PLUGINS_DIR/$2/control.zaf + else + if zaf_list_plugins | grep -q "^$1"; then + [ -f $ZAF_PLUGINS_DIR/$1/control.zaf ] && zaf_plugin_info $ZAF_PLUGINS_DIR/$1/control.zaf || zaf_err "Plugin $1 not installed." else - if echo $2 |grep -q ^http; then - zaf_prepare_plugin "$2" "$ZAF_TMP_DIR/plugin" + 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 $2 not installed." + zaf_err "Plugin $1 not installed." fi fi fi @@ -69,33 +100,55 @@ plugins) ;; items) - if [ -z "$2" ]; then + shift + shift $(zaf_shift "$@") + if [ -z "$1" ]; then zaf_list_items else - zaf_list_plugin_items "$2" + zaf_list_plugin_items "$1" fi ;; test) - if echo $2|grep -q '\.'; then - zaf_test_item "$2" + shift + shift $(zaf_shift "$@") + if echo $1|grep -q '\.'; then + zaf_test_item "$1" exit fi - if [ -n "$2" ]; then - shift + if [ -n "$1" ]; then + plugins="$@" + else + plugins="$(zaf_list_plugins)" + fi + for p in $plugins; do + ! zaf_is_plugin $p && zaf_err "Unknown plugin $p" + for i in $(zaf_list_plugin_items $p); do + echo $i: $(zaf_test_item $i) + done + done + ;; +get) + shift + shift $(zaf_shift "$@") + if echo $1|grep -q '\.'; then + zaf_get_item "$1" + exit + fi + if [ -n "$1" ]; then plugins="$@" else plugins="$(zaf_list_plugins)" fi for p in $plugins; do for i in $(zaf_list_plugin_items $p); do - echo $i: $(zaf_test_item $i) + echo $i: $(zaf_get_item $i) done done ;; - install) - shift; + shift + shift $(zaf_shift "$@") [ -z "$1" ] && echo "$0 install plugin [plugin]..." for p in $@; do if zaf_is_plugin "$p"; then @@ -109,7 +162,8 @@ install) ;; reinstall) - shift; + shift + shift $(zaf_shift "$@") [ -z "$1" ] && echo "$0 reinstall plugin [plugin]..." for p in $@; do if zaf_is_plugin "$p"; then @@ -123,7 +177,8 @@ reinstall) ;; remove) - shift; + shift + shift $(zaf_shift "$@") [ -z "$1" ] && echo "$0 remove plugin [plugin]..." for p in $@; do if zaf_is_plugin "$p"; then @@ -135,26 +190,25 @@ remove) ;; self-upgrade) + shift + shift $(zaf_shift "$@") + [ -z "$1" ] && auto=auto 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; then zaf_err "Curl not found. Cannot continue. Please install it." fi - [ -z "$2" ] && auto=auto - set -e - mkdir -p /tmp/zaf-installer \ - && cd /tmp/zaf-installer \ - && (for i in lib/zaf.lib.sh lib/os.lib.sh lib/ctrl.lib.sh install.sh ; do echo curl -f -k -s -L -o - "$ZAF_URL/$i" >&2; curl -f -k -s -L -o - "$ZAF_URL/$i"; done) >install.sh \ - && chmod +x install.sh \ - && exec ./install.sh $auto "$@" + zaf_fetch_url $ZAF_RAW_URL/$ZAF_VERSION/install.sh | exec sh -s $auto "$@" exit ;; self-remove) + shift + shift $(zaf_shift "$@") zaf_os_specific zaf_check_deps zaf && zaf_err "Zaf is installed as system package. Cannot self-remove." . /etc/zaf.conf - if [ "$2" = "force" ]; then + if [ "$1" = "force" ]; then rm -rf /etc/zaf.conf ${ZAF_PLUGINS_DIR} ${ZAF_REPO_DIR} ${ZAF_LIB_DIR} \ ${ZAF_BIN_DIR}/zaf ${ZAF_AGENT_CONFIGD}/zaf_* else @@ -169,15 +223,20 @@ self-remove) *) echo "$0 Version ${ZAF_VERSION}. Please use some of this commands:" - echo "$0 update To update repo" + echo "$0 Cmd [ZAF_OPTION=value] ..." + echo "Commands:" + echo "$0 update To update repo (not plugins, similar to apt-get update)" + echo "$0 upgrade To upgrade installed plugins from repo" echo "$0 plugins To list installed plugins" echo "$0 show [plugin] To show installed plugins or plugin info" echo "$0 items [plugin] To list all suported items [for plugin]" - echo "$0 test [plugin[.item]] To test all suported items [for plugin]" + echo "$0 test [plugin[.item]] To test [all] suported items by zabbix_agentd [for plugin]" + echo "$0 get [plugin[.item]] To test [all] suported items by zabbix_get [for plugin]" echo "$0 install plugin To install plugin" echo "$0 remove plugin To remove plugin" echo "$0 self-upgrade To self-upgrade zaf" echo "$0 self-remove To self-remove zaf and its config" + echo ;; esac From c2864f8d4c9516b8dbb0f8c7dc91b7852c6ea609 Mon Sep 17 00:00:00 2001 From: Lukas Macura Date: Tue, 12 Apr 2016 10:36:39 +0200 Subject: [PATCH 19/33] Added zabbix API functions --- lib/zbxapi.lib.sh | 74 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100755 lib/zbxapi.lib.sh diff --git a/lib/zbxapi.lib.sh b/lib/zbxapi.lib.sh new file mode 100755 index 0000000..52a53c8 --- /dev/null +++ b/lib/zbxapi.lib.sh @@ -0,0 +1,74 @@ +#!/bin/sh + +# Zabbix API related functions +# Parameters in global variables ZAF_ZBX_API_* +# returns auth on stdout or false +zaf_zbxapi_login(){ + local authstr + local user + local pass + + [ -z "$ZAF_ZBXAPI_URL" ] || [ -z "$ZAF_ZBXAPI_USER" ] || [ -z "$ZAF_ZBXAPI_PASS" ] && zaf_err "Zabbix Api parameters not set!" + authstr='{ + "params" : { + "password" : "'$ZAF_ZBXAPI_PASS'", + "user" : "'$ZAF_ZBXAPI_USER'" + }, + "id" : 0, + "jsonrpc" : "2.0", + "method" : "user.login" + }' + zaf_dbg "Zabbix API login: $authstr" + ZAF_ZBXAPI_AUTH=$(curl -s -f -L -X POST -H 'Content-Type: application/json-rpc' -d "$authstr" "$ZAF_ZBXAPI_URL" | json_pp | grep result | cut -d ':' -f 2 | tr -d '", ') || { zaf_err "Bad zabbix API parameters, cannot login."; } + zaf_dbg "Logged into zabbix API ($ZAF_ZBXAPI_AUTH)" +} + +zaf_zbxapi_getxml() { + sed -e 's/\({"jsonrpc":"2.0","result":\)"\(.*\)",\("id":.*\)/\n\2\n/g' | sed -r 's/\\([/"])/\1/g' +} + +# $1 host group or empty +zaf_zbxapi_gethosts() { + local hstr + local hgroup + local filter + + hgroup="$1" + [ -n "$hgroup" ] && filter='"filter": { "hostgroup": [ "'$hgroup'" ] },' + hstr='{ + "jsonrpc": "2.0", + "method": "host.get", + "auth": "'$ZAF_ZBXAPI_AUTH'", + '$filter' + "id": 2 + }' + zaf_dbg "Zabbix Get hosts: $hstr" + curl -s -f -L -X POST -H 'Content-Type: application/json-rpc' -d "$hstr" "$ZAF_ZBXAPI_URL" | tr ',' '\n' | grep hostid | cut -d '"' -f 4 +} + +# Host backup +# $1 hostid +zaf_zbxapi_backuphost(){ + local bkpstr + + host="$1" + bkpstr=' + { + "jsonrpc": "2.0", + "method": "configuration.export", + "params": { + "options": { + "hosts": [ + "'$host'" + ] + }, + "format": "xml" + }, + "auth": "'$ZAF_ZBXAPI_AUTH'", + "id": 1 +}' + zaf_dbg "Zabbix API backup host: $bkpstr" + curl -s -f -L -X POST -H 'Content-Type: application/json-rpc' -d "$bkpstr" "$ZAF_ZBXAPI_URL" | zaf_zbxapi_getxml +} + + From 3cbd3a370224955c898055ac8a692a0a36803a39 Mon Sep 17 00:00:00 2001 From: Lukas Macura Date: Tue, 12 Apr 2016 15:28:29 +0200 Subject: [PATCH 20/33] Working on 1.1 version Added cache support Added Zabbix API calls --- Makefile | 8 ++- files/postinst.template | 3 +- install.sh | 24 +++++-- lib/cache.lib.sh | 59 ++++++++++++++++ lib/zaf.lib.sh | 15 +++- lib/zbxapi.lib.sh | 151 ++++++++++++++++++++++++++++++++++------ zaf | 57 +++++++++++++-- 7 files changed, 280 insertions(+), 37 deletions(-) create mode 100644 lib/cache.lib.sh mode change 100755 => 100644 lib/zbxapi.lib.sh diff --git a/Makefile b/Makefile index cadc4f4..c06c9ab 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,9 @@ ZAF_EXPORT_OPTS=$(foreach o,$(ZAF_OPTIONS),$(shell echo $(o)|cut -d '=' -f 1)) DEBIAN_DIR=tmp/deb DEBIAN_CTRL=$(DEBIAN_DIR)/DEBIAN DEBIAN_PKG=$(shell . lib/zaf.lib.sh; echo out/zaf-$$ZAF_VERSION.deb) +ifeq ($(ZAF_DEBUG),) + ZAF_DEBUG=0 +endif ifeq ($(ZAF_OPTIONS),) ZAF_OPTIONS = ZAF_GIT=0 @@ -44,7 +47,8 @@ deb-control: for p in $(PLUGINS); do \ DEPENDS="$$DEPENDS,$$(zaf_ctrl_get_global_option $$p/control.zaf Depends-dpkg | tr ' ' ',')"; \ done; \ - zaf_far '{ZAF_VERSION}' "$$ZAF_VERSION" $(DEBIAN_CTRL)/control + [ "$$ZAF_GITBRANCH" = "master" ] && master=master; \ + zaf_far '{ZAF_VERSION}' "$${ZAF_VERSION}$$master" $(DEBIAN_CTRL)/control deb-scripts: @. lib/zaf.lib.sh; \ @@ -58,7 +62,7 @@ deb-scripts: deb-cp: @mkdir -p $(DEBIAN_DIR) - @set -e; INSTALL_PREFIX=$(DEBIAN_DIR) ZAF_DEBUG=0 ./install.sh auto $(ZAF_OPTIONS) $(AGENT_OPTIONS) + @set -e; INSTALL_PREFIX=$(DEBIAN_DIR) ZAF_DEBUG=$(ZAF_DEBUG) ./install.sh auto $(ZAF_OPTIONS) $(AGENT_OPTIONS) @. lib/zaf.lib.sh; \ . lib/ctrl.lib.sh; \ for p in $(PLUGINS); do \ diff --git a/files/postinst.template b/files/postinst.template index e5abaf1..6c95d4b 100644 --- a/files/postinst.template +++ b/files/postinst.template @@ -8,9 +8,10 @@ configure) . /usr/lib/zaf/os.lib.sh . /usr/lib/zaf/ctrl.lib.sh cd /usr/lib/zaf && /usr/lib/zaf/install.sh reconf - zaf reinstall {PLUGINS} {IPLUGINS} + [ -n "{PLUGINS}" ] && zaf reinstall {PLUGINS} {IPLUGINS} fi ;; esac +true diff --git a/install.sh b/install.sh index 369efb9..efb620c 100755 --- a/install.sh +++ b/install.sh @@ -3,7 +3,7 @@ [ -z "$ZAF_DEBUG" ] && ZAF_DEBUG=1 if [ -z "$ZAF_URL" ]; then # Runing as standalone install.sh. We have to download rest of files first. - [ -z "$ZAF_VERSION" ] && ZAF_VERSION=1.0 + [ -z "$ZAF_GITBRANCH" ] && ZAF_GITBRANCH=master ZAF_URL="https://github.com/limosek/zaf/" fi @@ -20,7 +20,7 @@ zaf_fetch_url(){ # Download tgz and extract to /tmp/zaf-installer zaf_download_files() { rm -rf /tmp/zaf-installer - zaf_fetch_url $ZAF_URL/archive/$ZAF_VERSION.tar.gz | tar -f - -C /tmp -zx && mv /tmp/zaf-$ZAF_VERSION /tmp/zaf-installer + zaf_fetch_url $ZAF_URL/archive/$ZAF_GITBRANCH.tar.gz | tar -f - -C /tmp -zx && mv /tmp/zaf-$ZAF_VERSION /tmp/zaf-installer } if ! [ -f README.md ]; then @@ -224,7 +224,12 @@ 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_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" + zaf_get_option ZAF_ZBXAPI_AUTHTYPE "Zabbix API authentication type" "internal" "$INSTALL_MODE" + if zaf_is_root && ! [ -x $ZAF_AGENT_BIN ]; then zaf_err "Zabbix agent ($ZAF_AGENT_BIN) not installed? Use ZAF_AGENT_BIN env variable to specify location. Exiting." fi @@ -251,6 +256,11 @@ 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_ZBXAPI_URL "$ZAF_ZBXAPI_URL" + zaf_set_option ZAF_ZBXAPI_USER "$ZAF_ZBXAPI_USER" + zaf_set_option ZAF_ZBXAPI_PASS "$ZAF_ZBXAPI_PASS" + zaf_set_option ZAF_ZBXAPI_AUTHTYPE "$ZAF_ZBXAPI_AUTHTYPE" [ -n "$ZAF_PREPACKAGED_DIR" ] && zaf_set_option ZAF_PREPACKAGED_DIR "$ZAF_PREPACKAGED_DIR" if zaf_is_root; then @@ -263,15 +273,15 @@ zaf_install_all() { rm -rif ${ZAF_TMP_DIR} mkdir -p ${ZAF_TMP_DIR} zaf_install_dir ${ZAF_LIB_DIR} - for i in lib/zaf.lib.sh lib/os.lib.sh lib/ctrl.lib.sh README.md; do - zaf_install $i ${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 + zaf_install $i ${ZAF_LIB_DIR}/ || zaf_err "Error installing $i" done for i in lib/zaflock lib/preload.sh; do - zaf_install_bin $i ${ZAF_LIB_DIR}/ + zaf_install_bin $i ${ZAF_LIB_DIR}/ || zaf_err "Error installing $i" done zaf_install_dir ${ZAF_BIN_DIR} for i in zaf; do - zaf_install_bin $i ${ZAF_BIN_DIR}/ + zaf_install_bin $i ${ZAF_BIN_DIR}/ || zaf_err "Error installing $i" done zaf_install_dir ${ZAF_PLUGINS_DIR} zaf_install_dir ${ZAF_PLUGINS_DIR} diff --git a/lib/cache.lib.sh b/lib/cache.lib.sh new file mode 100644 index 0000000..bc665f8 --- /dev/null +++ b/lib/cache.lib.sh @@ -0,0 +1,59 @@ +# Zaf cache related functions + +zaf_cache_init(){ + [ -n "$ZAF_CACHE_DIR" ] && rm -rf "$ZAF_CACHE_DIR" + mkdir -p "$ZAF_CACHE_DIR" +} + +# Get cache key from requested param +zaf_cachekey(){ + echo "$1" | md5sum - | cut -d ' ' -f 1 +} + +# Put object into cache +# $1 key +# $2 value +# $3 lifetime in seconds +zaf_tocache(){ + local key + local value + local lifetime + key=$(zaf_cachekey "$1") + echo "$2" >$ZAF_CACHE_DIR/$key + touch -m -d "$3 seconds" $ZAF_CACHE_DIR/$key.tme +} + +# Put object into cache from stdin and copy to stdout +# $1 key +# $2 lifetime in seconds +zaf_tocache_stdin(){ + local key + local lifetime + + key=$(zaf_cachekey "$1") + cat >$ZAF_CACHE_DIR/$key + touch -m -d "$3 seconds" $ZAF_CACHE_DIR/$key.tme + cat $ZAF_CACHE_DIR/$key +} + +# Get object from cache +# $1 key +zaf_fromcache(){ + local key + local value + 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" + cat $ZAF_CACHE_DIR/$key + else + zaf_trc "Cache: removing old entry $1" + rm -f "$ZAF_CACHE_DIR/$key*" + return 2 + fi + else + zaf_trc "Cache: missing entry $1($key)" + return 1 + fi +} + diff --git a/lib/zaf.lib.sh b/lib/zaf.lib.sh index c45716b..acf7a4d 100644 --- a/lib/zaf.lib.sh +++ b/lib/zaf.lib.sh @@ -1,6 +1,7 @@ # Hardcoded variables -ZAF_VERSION="master" +ZAF_VERSION="1.1" +ZAF_GITBRANCH="master" ZAF_URL="https://github.com/limosek/zaf" ZAF_RAW_URL="https://raw.githubusercontent.com/limosek/zaf" @@ -9,6 +10,9 @@ ZAF_RAW_URL="https://raw.githubusercontent.com/limosek/zaf" zaf_msg() { echo $@ } +zaf_trc() { + [ "$ZAF_DEBUG" -ge "3" ] && logger -s -t zaf -- $@ +} zaf_dbg() { [ "$ZAF_DEBUG" -ge "2" ] && logger -s -t zaf -- $@ } @@ -32,7 +36,11 @@ zaf_fetch_url() { local scheme local uri local insecure + local out + if zaf_fromcache "$1"; then + return + fi scheme=$(echo $1|cut -d ':' -f 1) uri=$(echo $1|cut -d '/' -f 3-) if [ "$1" = "$scheme" ]; then @@ -43,7 +51,7 @@ zaf_fetch_url() { [ "$scheme" != "file" ] && [ -n "$ZAF_OFFLINE" ] && zaf_err "Cannot download $1 in offline mode!" [ "${ZAF_CURL_INSECURE}" = "1" ] && insecure="-k" zaf_dbg curl $insecure -f -s -L -o - $1 - curl $insecure -f -s -L -o - "$1" + curl $insecure -f -s -L -o - "$1" | zaf_tocache_stdin "$1" 120 ;; esac } @@ -238,8 +246,9 @@ zaf_install_plugin() { plugin=$(zaf_ctrl_get_global_block <"${ZAF_TMP_DIR}/plugin/control.zaf" | zaf_block_get_option Plugin) plugindir="${ZAF_PLUGINS_DIR}"/$plugin if [ -n "$plugin" ] && zaf_prepare_plugin "$1" $plugindir; then + zaf_wrn "Installing plugin $plugin from $url to $plugindir" control=${plugindir}/control.zaf - [ "$ZAF_DEBUG" -gt 0 ] && zaf_plugin_info "${control}" + [ "$ZAF_DEBUG" -gt 1 ] && zaf_plugin_info "${control}" zaf_ctrl_check_deps "${control}" zaf_ctrl_install "$url" "${control}" "${plugindir}" zaf_ctrl_generate_cfg "${control}" "${plugin}" \ diff --git a/lib/zbxapi.lib.sh b/lib/zbxapi.lib.sh old mode 100755 new mode 100644 index 52a53c8..be30bbb --- a/lib/zbxapi.lib.sh +++ b/lib/zbxapi.lib.sh @@ -1,4 +1,35 @@ -#!/bin/sh +# Call api function +# $1 - query string +zaf_zbxapi_do() { + local result + if ! zaf_fromcache "$1"; then + zaf_dbg "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 + fi +} + +# Extract result from JSON response +zaf_zbxapi_getresult() { + sed -e 's/\({"jsonrpc":"2.0","result":\)\(.*\),\("id":.*\)/\2/g' | sed -e 's/^\[\]$//' +} + +# Extract XML result from JSON response +zaf_zbxapi_getxml() { + zaf_zbxapi_getresult | sed -e 's/{"jsonrpc":"2.0","result":"//' | sed -e 's/","id"\:1}//' | sed -e 's#\\\([<">/]\)#\1#g' +} + +# Extract string from JSON response result +zaf_zbxapi_getstring() { + sed -e 's/^"//' -e 's/"$//' -e 's/\\n/'\\n'/g' +} + +# Extract value from JSON response result +# $1 key +zaf_zbxapi_getvalue() { + tr ',' '\n' | grep "\"$1\":" | cut -d '"' -f 4 +} # Zabbix API related functions # Parameters in global variables ZAF_ZBX_API_* @@ -7,43 +38,124 @@ zaf_zbxapi_login(){ local authstr local user local pass + local result [ -z "$ZAF_ZBXAPI_URL" ] || [ -z "$ZAF_ZBXAPI_USER" ] || [ -z "$ZAF_ZBXAPI_PASS" ] && zaf_err "Zabbix Api parameters not set!" authstr='{ + "method" : "user.login", "params" : { "password" : "'$ZAF_ZBXAPI_PASS'", "user" : "'$ZAF_ZBXAPI_USER'" }, "id" : 0, - "jsonrpc" : "2.0", - "method" : "user.login" + "jsonrpc" : "2.0" }' - zaf_dbg "Zabbix API login: $authstr" - ZAF_ZBXAPI_AUTH=$(curl -s -f -L -X POST -H 'Content-Type: application/json-rpc' -d "$authstr" "$ZAF_ZBXAPI_URL" | json_pp | grep result | cut -d ':' -f 2 | tr -d '", ') || { zaf_err "Bad zabbix API parameters, cannot login."; } + + if [ "$ZAF_ZBXAPI_AUTHTYPE" = "http" ] ; then + 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)" } -zaf_zbxapi_getxml() { - sed -e 's/\({"jsonrpc":"2.0","result":\)"\(.*\)",\("id":.*\)/\n\2\n/g' | sed -r 's/\\([/"])/\1/g' +# $1 hostgroup name +zaf_zbxapi_gethostgroupid() { + local hstr + local filter + local gfilter + + hstr='{ + "method": "hostgroup.get", + "jsonrpc": "2.0", + "auth": "'$ZAF_ZBXAPI_AUTH'", + "params": { + "filter": { + "name": ["'$1'"] + }, + "output": "shorten" + }, + "id": 1 + }' + zaf_zbxapi_do "$hstr" | zaf_zbxapi_getresult | tr ',' '\n' | cut -d '"' -f 4 } -# $1 host group or empty -zaf_zbxapi_gethosts() { +# $1 hostname +zaf_zbxapi_gethostid() { local hstr - local hgroup + local host + local groupid local filter + local gfilter - hgroup="$1" - [ -n "$hgroup" ] && filter='"filter": { "hostgroup": [ "'$hgroup'" ] },' + host="$1" + if [ -n "$host" ] ; then + filter='"filter": { "host": [ "'$host'" ] },' + fi hstr='{ - "jsonrpc": "2.0", "method": "host.get", + "jsonrpc": "2.0", "auth": "'$ZAF_ZBXAPI_AUTH'", - '$filter' - "id": 2 + "params": { + '$filter' + "output": "shorten" + }, + "id": 1 }' - zaf_dbg "Zabbix Get hosts: $hstr" - curl -s -f -L -X POST -H 'Content-Type: application/json-rpc' -d "$hstr" "$ZAF_ZBXAPI_URL" | tr ',' '\n' | grep hostid | cut -d '"' -f 4 + zaf_zbxapi_do "$hstr" | zaf_zbxapi_getresult | tr ',' '\n' | cut -d '"' -f 4 +} + +# $1 hostid +zaf_zbxapi_gethost() { + local hstr + local host + local groupid + local filter + local gfilter + + hostid="$1" + if [ -n "$hostid" ] ; then + filter='"hostids": [ "'$hostid'" ],' + fi + hstr='{ + "method": "host.get", + "jsonrpc": "2.0", + "auth": "'$ZAF_ZBXAPI_AUTH'", + "params": { + '$filter' + "output": "extend" + }, + "id": 1 + }' + zaf_zbxapi_do "$hstr" | zaf_zbxapi_getresult | zaf_zbxapi_getvalue host +} + +# $1 hostgroupid +zaf_zbxapi_gethostsingroup() { + local hstr + local host + local groupid + local filter + local gfilter + + groupid="$1" + if [ -n "$groupid" ]; then + gfilter='"groupids": [ "'$groupid'" ],' + fi + + hstr='{ + "method": "host.get", + "jsonrpc": "2.0", + "auth": "'$ZAF_ZBXAPI_AUTH'", + "params": { + '$gfilter' + '$filter' + "output": "shorten" + }, + "id": 1 + }' + zaf_zbxapi_do "$hstr" | zaf_zbxapi_getresult | tr ',' '\n' | cut -d '"' -f 4 } # Host backup @@ -54,8 +166,8 @@ zaf_zbxapi_backuphost(){ host="$1" bkpstr=' { - "jsonrpc": "2.0", "method": "configuration.export", + "jsonrpc": "2.0", "params": { "options": { "hosts": [ @@ -67,8 +179,7 @@ zaf_zbxapi_backuphost(){ "auth": "'$ZAF_ZBXAPI_AUTH'", "id": 1 }' - zaf_dbg "Zabbix API backup host: $bkpstr" - curl -s -f -L -X POST -H 'Content-Type: application/json-rpc' -d "$bkpstr" "$ZAF_ZBXAPI_URL" | zaf_zbxapi_getxml + zaf_zbxapi_do "$bkpstr" | zaf_zbxapi_getxml } diff --git a/zaf b/zaf index 6c70dda..3ea1a22 100755 --- a/zaf +++ b/zaf @@ -27,16 +27,21 @@ if [ "$ZAF_DEBUG" -le 3 ]; then fi ! [ -d "${ZAF_TMP_DIR}" ] && mkdir "${ZAF_TMP_DIR}" +! [ -d "${ZAF_CACHE_DIR}" ] && mkdir "${ZAF_CACHE_DIR}" if [ -f ./lib/zaf.lib.sh ]; then . ./lib/zaf.lib.sh . ./lib/os.lib.sh . ./lib/ctrl.lib.sh +. ./lib/cache.lib.sh +. ./lib/zbxapi.lib.sh [ -f ./lib/zaf.${ZAF_OS}.sh ] && . ./lib/zaf.${ZAF_OS}.sh else . ${ZAF_LIB_DIR}/zaf.lib.sh . ${ZAF_LIB_DIR}/os.lib.sh . ${ZAF_LIB_DIR}/ctrl.lib.sh +. ${ZAF_LIB_DIR}/cache.lib.sh +. ${ZAF_LIB_DIR}/zbxapi.lib.sh [ -f ${ZAF_LIB_DIR}/zaf.${ZAF_OS}.sh ] && . ${ZAF_LIB_DIR}/zaf.${ZAF_OS}.sh fi @@ -70,9 +75,7 @@ update) zaf_update_repo ;; upgrade) - zaf_list_plugins | while read plugin; do - ZAF_DEBUG=$ZAF_DEBUG $0 reinstall $plugin || zaf_err "Error upgrading $plugin" - done + ZAF_DEBUG=$ZAF_DEBUG $0 reinstall $(zaf_list_plugins) ;; show) shift; @@ -219,7 +222,52 @@ self-remove) echo echo "To continue, please do $0 self-remove force" fi - ;; + ;; + +api) + zaf_zbxapi_login + case $2 in + hostid) + zaf_zbxapi_gethostid "$3" + ;; + host) + zaf_zbxapi_gethost "$3" + ;; + hostgroupid) + zaf_zbxapi_gethostgroupid "$3" + ;; + hosts) + gid=$(zaf_zbxapi_gethostgroupid "$3") + zaf_zbxapi_gethostsingroup $gid + ;; + backup-group) + gid=$(zaf_zbxapi_gethostgroupid "$3") + hosts=$(zaf_zbxapi_gethostsingroup $gid) + zaf_wrn "Will backup this hosts: $hosts" + for h in $hosts; do + hn=$(zaf_zbxapi_gethost $h) + zaf_wrn "Exporting host $hn($h)..." + zaf_zbxapi_backuphost $h >$hn.xml + done + ;; + backup-host) + hostid=$(zaf_zbxapi_gethostid "$3") + zaf_wrn "Exporting host $3($hostid)..." + zaf_zbxapi_backuphost $hostid + ;; + *) + echo "$0 api command [parameters]" + echo "hostid 'host' Get hostid from hostname" + echo "host 'hostid' Get hostname from hostid" + echo "hostgroupid 'hostgroup' Get hostgroup id from hostgroup" + echo "hosts 'hostgroup' Get hosts in group" + echo "backup-group 'hostgroup' [dir] Backup all hosts in group (get their config from zabbix and save to dir/hostname.xml)" + echo "backup-host 'host' Backup host (get config from zabbix to stdout)" + echo + exit + ;; + esac + ;; *) echo "$0 Version ${ZAF_VERSION}. Please use some of this commands:" @@ -234,6 +282,7 @@ self-remove) echo "$0 get [plugin[.item]] To test [all] suported items by zabbix_get [for plugin]" 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 self-upgrade To self-upgrade zaf" echo "$0 self-remove To self-remove zaf and its config" echo From 86b921dad256a3ca7dc5301c9d9b5f14efa8b874 Mon Sep 17 00:00:00 2001 From: Lukas Macura Date: Tue, 12 Apr 2016 15:37:28 +0200 Subject: [PATCH 21/33] Added default version strings --- install.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/install.sh b/install.sh index efb620c..34faafa 100755 --- a/install.sh +++ b/install.sh @@ -3,10 +3,12 @@ [ -z "$ZAF_DEBUG" ] && ZAF_DEBUG=1 if [ -z "$ZAF_URL" ]; then # Runing as standalone install.sh. We have to download rest of files first. - [ -z "$ZAF_GITBRANCH" ] && ZAF_GITBRANCH=master ZAF_URL="https://github.com/limosek/zaf/" fi +[ -z "$ZAF_GITBRANCH" ] && ZAF_GITBRANCH=master +[ -z "$ZAF_VERSION" ] && ZAF_VERSION=1.1master + # Lite version of zaf_fetch_url, full version will be loaded later zaf_fetch_url(){ if [ -z "$ZAF_OFFLINE" ]; then From 6bf7c16b7d0131b30e4ecfef9f1ee9bde780c96a Mon Sep 17 00:00:00 2001 From: Lukas Macura Date: Tue, 12 Apr 2016 15:42:09 +0200 Subject: [PATCH 22/33] One more version repair --- install.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/install.sh b/install.sh index 34faafa..9b616e2 100755 --- a/install.sh +++ b/install.sh @@ -7,7 +7,6 @@ if [ -z "$ZAF_URL" ]; then fi [ -z "$ZAF_GITBRANCH" ] && ZAF_GITBRANCH=master -[ -z "$ZAF_VERSION" ] && ZAF_VERSION=1.1master # Lite version of zaf_fetch_url, full version will be loaded later zaf_fetch_url(){ @@ -22,7 +21,7 @@ zaf_fetch_url(){ # Download tgz and extract to /tmp/zaf-installer zaf_download_files() { rm -rf /tmp/zaf-installer - zaf_fetch_url $ZAF_URL/archive/$ZAF_GITBRANCH.tar.gz | tar -f - -C /tmp -zx && mv /tmp/zaf-$ZAF_VERSION /tmp/zaf-installer + zaf_fetch_url $ZAF_URL/archive/$ZAF_GITBRANCH.tar.gz | tar -f - -C /tmp -zx && mv /tmp/zaf-$ZAF_GITBRANCH /tmp/zaf-installer } if ! [ -f README.md ]; then From cf90b8bc2c2fe843c90bbadba9b757e0b71a503a Mon Sep 17 00:00:00 2001 From: Lukas Macura Date: Tue, 12 Apr 2016 18:38:19 +0200 Subject: [PATCH 23/33] Added support for cached items. Sudo setup is supported --- install.sh | 4 ++-- lib/cache.lib.sh | 19 +++++++++++++------ lib/ctrl.lib.sh | 32 +++++++++++++++++++++++++++---- lib/preload.sh | 20 +++++++++++++++++--- lib/zaf.lib.sh | 22 ++++++++++++++++++++++ lib/zbxapi.lib.sh | 11 +++++++---- zaf | 48 +++++++++++++++++++++++++++++++++++++++++++---- 7 files changed, 133 insertions(+), 23 deletions(-) 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 ;; From a99c9b828058e07887d2e840a7b15cd2f82dc306 Mon Sep 17 00:00:00 2001 From: Lukas Macura Date: Tue, 12 Apr 2016 19:31:06 +0200 Subject: [PATCH 24/33] Added cron support Added precache support --- install.sh | 2 ++ lib/cache.lib.sh | 2 ++ lib/ctrl.lib.sh | 17 ++++++++++++++++- lib/preload.sh | 4 ++-- lib/zaf.lib.sh | 5 +++++ zaf | 22 ++++++++++++++++++++-- 6 files changed, 47 insertions(+), 5 deletions(-) diff --git a/install.sh b/install.sh index f1e1e24..a09132b 100755 --- a/install.sh +++ b/install.sh @@ -226,6 +226,7 @@ zaf_configure(){ 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_SUDOERSD "Sudo sudoers.d directory" "/etc/sudoers.d" "$INSTALL_MODE" + zaf_get_option ZAF_CROND "Cron.d directory" "/etc/cron.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" @@ -258,6 +259,7 @@ zaf_configure(){ zaf_set_option ZAF_AGENT_BIN "$ZAF_AGENT_BIN" zaf_set_option ZAF_AGENT_RESTART "$ZAF_AGENT_RESTART" zaf_set_option ZAF_SUDOERSD "$ZAF_SUDOERSD" + zaf_set_option ZAF_CROND "$ZAF_CROND" 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 93d8695..54884b4 100644 --- a/lib/cache.lib.sh +++ b/lib/cache.lib.sh @@ -25,6 +25,7 @@ zaf_tocache(){ local lifetime key=$(zaf_cachekey $1) echo "$2" >$ZAF_CACHE_DIR/$key + echo "$1" >$ZAF_CACHE_DIR/$key.key touch -m -d "$3 seconds" $ZAF_CACHE_DIR/$key.tme zaf_trc "Cache: Saving entry $1($key)" } @@ -38,6 +39,7 @@ zaf_tocache_stdin(){ key=$(zaf_cachekey $1) cat >$ZAF_CACHE_DIR/$key + echo "$1" >$ZAF_CACHE_DIR/$key.key touch -m -d "$3 seconds" $ZAF_CACHE_DIR/$key.tme zaf_trc "Cache: Saving entry $1($key)" cat $ZAF_CACHE_DIR/$key diff --git a/lib/ctrl.lib.sh b/lib/ctrl.lib.sh index 35612dc..8d79499 100644 --- a/lib/ctrl.lib.sh +++ b/lib/ctrl.lib.sh @@ -95,11 +95,26 @@ zaf_ctrl_sudo() { fi pdir="$3" plugin=$1 - (echo -n "zabbix ALL=NOPASSWD: " + zaf_dbg "Installing sudoers entry $ZAF_SUDOERSD/zaf_$plugin" + (echo -n "zabbix ALL=NOPASSWD:SETENV: " zaf_ctrl_get_global_option $2 "Sudo" | zaf_far '{PLUGINDIR}' "${plugindir}"; echo ) >$ZAF_SUDOERSD/zaf_$plugin } +# Install crontab config from control +# $1 plugin +# $2 control +# $3 plugindir +zaf_ctrl_cron() { + local pdir + local plugin + + pdir="$3" + plugin=$1 + zaf_dbg "Installing cron entry $ZAF_CROND/zaf_$plugin" + zaf_ctrl_get_global_option $2 "Cron" | zaf_far '{PLUGINDIR}' "${plugindir}" >$ZAF_CROND/zaf_$plugin +} + # Install sudo options from control # $1 pluginurl # $2 control diff --git a/lib/preload.sh b/lib/preload.sh index fefde66..c2cbc50 100644 --- a/lib/preload.sh +++ b/lib/preload.sh @@ -4,9 +4,9 @@ [ -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_CACHE_DIR" ] && ZAF_CACHE_DIR=${ZAF_TMP_BASE}c -#trap "rm -rif ${ZAF_TMP_DIR}" EXIT +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 diff --git a/lib/zaf.lib.sh b/lib/zaf.lib.sh index 5294cc0..093dfdc 100644 --- a/lib/zaf.lib.sh +++ b/lib/zaf.lib.sh @@ -382,6 +382,11 @@ zaf_test_item() { $ZAF_AGENT_BIN -t "$1" } +zaf_precache_item() { + cmd=$(grep "^UserParameter=$item" $ZAF_AGENT_CONFIGD/zaf*.conf | cut -d ',' -f 2-) + eval $cmd +} + zaf_remove_plugin() { ! [ -d ${ZAF_PLUGINS_DIR}/$1 ] && { zaf_err "Plugin $1 not installed!"; } zaf_wrn "Removing plugin $1" diff --git a/zaf b/zaf index 11c289f..275a413 100755 --- a/zaf +++ b/zaf @@ -18,7 +18,7 @@ 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_CACHE_DIR" ] && ZAF_CACHE_DIR=${ZAF_TMP_BASE}c [ -z "$ZAF_DEBUG" ] && ZAF_DEBUG=1 export ZAF_DEBUG @@ -29,7 +29,9 @@ if [ "$ZAF_DEBUG" -le 3 ]; then fi ! [ -d "${ZAF_TMP_DIR}" ] && mkdir "${ZAF_TMP_DIR}" -! [ -d "${ZAF_CACHE_DIR}" ] && mkdir "${ZAF_CACHE_DIR}" +if ! [ -d "${ZAF_CACHE_DIR}" ]; then + mkdir "${ZAF_CACHE_DIR}" +fi if [ -f ./lib/zaf.lib.sh ]; then . ./lib/zaf.lib.sh @@ -47,6 +49,11 @@ else [ -f ${ZAF_LIB_DIR}/zaf.${ZAF_OS}.sh ] && . ${ZAF_LIB_DIR}/zaf.${ZAF_OS}.sh fi +if zaf_is_root; then + chgrp zabbix "${ZAF_CACHE_DIR}" + chmod g+w "${ZAF_CACHE_DIR}" +fi + zaf_shift(){ local s @@ -173,6 +180,17 @@ get) done done ;; + +precache) + shift + shift $(zaf_shift "$@") + for i in $*; do + item=$(echo $i | cut -d '[' -f 1) + params=$(echo $i | cut -d '[' -f 2 | cut -d ']' -f 1 | tr ',' ' ') + zaf_precache_item $params + done + ;; + install) shift shift $(zaf_shift "$@") From 9ed9e990eddcc2fe92c5f60f1b6582314c9015cc Mon Sep 17 00:00:00 2001 From: Lukas Macura Date: Tue, 12 Apr 2016 19:40:17 +0200 Subject: [PATCH 25/33] Missed quotes --- lib/cache.lib.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/cache.lib.sh b/lib/cache.lib.sh index 54884b4..82018bc 100644 --- a/lib/cache.lib.sh +++ b/lib/cache.lib.sh @@ -12,7 +12,7 @@ zaf_cache_clean(){ # 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 @@ -23,7 +23,7 @@ zaf_tocache(){ local key local value local lifetime - key=$(zaf_cachekey $1) + key=$(zaf_cachekey "$1") echo "$2" >$ZAF_CACHE_DIR/$key echo "$1" >$ZAF_CACHE_DIR/$key.key touch -m -d "$3 seconds" $ZAF_CACHE_DIR/$key.tme @@ -37,7 +37,7 @@ zaf_tocache_stdin(){ local key local lifetime - key=$(zaf_cachekey $1) + key=$(zaf_cachekey "$1") cat >$ZAF_CACHE_DIR/$key echo "$1" >$ZAF_CACHE_DIR/$key.key touch -m -d "$3 seconds" $ZAF_CACHE_DIR/$key.tme @@ -50,7 +50,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" From ce4df86f4610c3d33c45908c1aa9441ed1cf1f71 Mon Sep 17 00:00:00 2001 From: Lukas Macura Date: Wed, 13 Apr 2016 12:42:12 +0200 Subject: [PATCH 26/33] Repaired docs, added cron --- README.md | 15 +++++++-------- lib/cache.lib.sh | 30 +++++++++++++++++++++--------- lib/ctrl.lib.sh | 14 +++++++++++--- lib/zaf.lib.sh | 5 +++-- 4 files changed, 42 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 0b786eb..e9a366b 100644 --- a/README.md +++ b/README.md @@ -19,25 +19,24 @@ So zaf is here for you :) * Sharing code. Many zabbix external checks share common shell functions. * Simplification of userparameter functions (does not have to be one-line long code) * 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. -* OS packaging support (in future). * Zabbix agent autoinstallation and autoconfiguration suitable to use in puppet or another tool * OS packaging support ## 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: ``` -curl -k https://raw.githubusercontent.com/limosek/zaf/1.0/install.sh | sh +curl -k https://raw.githubusercontent.com/limosek/zaf/master/install.sh | sh ``` ### Install options and autoconfiguration General parameters for install.sh on any system (simplest way how to install) ``` -curl -k https://raw.githubusercontent.com/limosek/zaf/1.0/install.sh | \ +curl -k https://raw.githubusercontent.com/limosek/zaf/master/install.sh | \ sh -s {auto|interactive|debug-auto|debug-interactive} [Agent-Options] [Zaf-Options] ``` or use git version: ``` -git clone https://github.com/limosek/zaf.git; cd zaf; git checkout 1.0 +git clone https://github.com/limosek/zaf.git; cd zaf; git checkout master ./install.sh {auto|interactive|debug-auto|debug-interactive} [Agent-Options] [Zaf-Options] Agent-Options: Z_Option=value [...] Zaf-Options: ZAF_OPT=value [...] @@ -68,7 +67,7 @@ Now everything was tested on Debian and OpenWrt. If somebody is interrested in, Suppose you want to autoinstall agent on clean system. You need only curl installed. Everything else is one-cmd process. This command will install zaf, install zabbix-agent if necessary and sets zabbix variables on agent to reach server. This command can be automatized by puppet or another deploying system. ``` -curl -k https://raw.githubusercontent.com/limosek/zaf/1.0/install.sh | sh -s auto \ +curl -k https://raw.githubusercontent.com/limosek/zaf/master/install.sh | sh -s auto \ Z_Server=zabbix.server.local \ Z_ServerActive=zabbix.server.local \ Z_HostnameItem=system.hostname Z_RefreshActiveChecks=60 \ @@ -80,10 +79,10 @@ You can make your own deb package with preconfigured option. It is up to you to ``` git clone https://github.com/limosek/zaf.git \ && cd zaf \ - && git checkout 1.0 \ + && git checkout master \ && git clone https://github.com/limosek/zaf-plugins.git \ && make deb PLUGINS="./zaf-plugins/fsx" IPLUGINS="zaf" ZAF_OPTIONS="ZAF_GIT=0" AGENT_OPTIONS="Z_Server=zabbix.server Z_ServerActive=zabbix.server Z_StartAgents=8" -sudo dpkg -i out/zaf-1.0.deb +sudo dpkg -i out/zaf-1.1master.deb ``` General usage: ``` @@ -125,7 +124,7 @@ During plugin installation, zaf will check all dependencies, do install binaries Zaf binary can be installed on any system from openwrt to big system. It has minimal dependencies and is shell based. Is has minimal size (up to 50kb of code). It can be used for installing, removing and testing zaf plugin items. Zaf should be run as root. ``` zaf -zaf Version 1.0. Please use some of this commands: +zaf Version 1.1master. Please use some of this commands: zaf update To update repo zaf plugins To list installed plugins zaf show [plugin] To show installed plugins or plugin info diff --git a/lib/cache.lib.sh b/lib/cache.lib.sh index 82018bc..d5512c7 100644 --- a/lib/cache.lib.sh +++ b/lib/cache.lib.sh @@ -11,7 +11,7 @@ zaf_cache_clean(){ } # Get cache key from requested param -zaf_cachekey(){ +zaf_cache_key(){ echo "$1" | md5sum - | cut -d ' ' -f 1 } @@ -23,7 +23,7 @@ zaf_tocache(){ local key local value local lifetime - key=$(zaf_cachekey "$1") + key=$(zaf_cache_key "$1") echo "$2" >$ZAF_CACHE_DIR/$key echo "$1" >$ZAF_CACHE_DIR/$key.key touch -m -d "$3 seconds" $ZAF_CACHE_DIR/$key.tme @@ -36,13 +36,25 @@ zaf_tocache(){ zaf_tocache_stdin(){ local key local lifetime - - key=$(zaf_cachekey "$1") + key=$(zaf_cache_key "$1") cat >$ZAF_CACHE_DIR/$key - echo "$1" >$ZAF_CACHE_DIR/$key.key - touch -m -d "$3 seconds" $ZAF_CACHE_DIR/$key.tme - zaf_trc "Cache: Saving entry $1($key)" - cat $ZAF_CACHE_DIR/$key + if [ -s $ZAF_CACHE_DIR/$key ]; then + zaf_trc "Cache: Saving entry $1($key)" + echo "$1" >$ZAF_CACHE_DIR/$key.key + touch -m -d "$3 seconds" $ZAF_CACHE_DIR/$key.tme + cat $ZAF_CACHE_DIR/$key + else + rm $ZAF_CACHE_DIR/$key + fi +} + +# Remove entry from cache +# $1 key +zaf_cache_delentry(){ + local key + key=$(zaf_cache_key "$1") + zaf_trc "Cache: removing $1($key) from cache" + rm -f "$ZAF_CACHE_DIR/$key*" } # Get object from cache @@ -50,7 +62,7 @@ zaf_tocache_stdin(){ zaf_fromcache(){ local key local value - key=$(zaf_cachekey "$1") + key=$(zaf_cache_key "$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 8d79499..e8179d2 100644 --- a/lib/ctrl.lib.sh +++ b/lib/ctrl.lib.sh @@ -89,6 +89,9 @@ zaf_ctrl_check_deps() { zaf_ctrl_sudo() { local pdir local plugin + local sudo + local cmd + local parms if ! which sudo >/dev/null; then zaf_wrn "Sudo needed bud not installed?" @@ -96,9 +99,14 @@ zaf_ctrl_sudo() { pdir="$3" plugin=$1 zaf_dbg "Installing sudoers entry $ZAF_SUDOERSD/zaf_$plugin" - (echo -n "zabbix ALL=NOPASSWD:SETENV: " - zaf_ctrl_get_global_option $2 "Sudo" | zaf_far '{PLUGINDIR}' "${plugindir}"; - echo ) >$ZAF_SUDOERSD/zaf_$plugin + sudo=$(zaf_ctrl_get_global_option $2 "Sudo" | zaf_far '{PLUGINDIR}' "${plugindir}") + cmd=$(echo $sudo | cut -d ' ' -f 1) + parms=$(echo $sudo | cut -d ' ' -f 2-) + if which $cmd >/dev/null ; then + (echo "zabbix ALL=NOPASSWD:SETENV: $(which $cmd) $(echo $parms | tr '%' '*')";echo) >$ZAF_SUDOERSD/zaf_$plugin + else + zaf_wrn "Cannot find binary $cmd for sudo. Ignoring sudo." + fi } # Install crontab config from control diff --git a/lib/zaf.lib.sh b/lib/zaf.lib.sh index 093dfdc..9b73a39 100644 --- a/lib/zaf.lib.sh +++ b/lib/zaf.lib.sh @@ -273,6 +273,7 @@ zaf_install_plugin() { zaf_ctrl_check_deps "${control}" zaf_ctrl_install "$url" "${control}" "${plugindir}" 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" @@ -388,10 +389,10 @@ zaf_precache_item() { } zaf_remove_plugin() { - ! [ -d ${ZAF_PLUGINS_DIR}/$1 ] && { zaf_err "Plugin $1 not installed!"; } + ! zaf_is_plugin $1 && { zaf_err "Plugin $1 not installed!"; } zaf_wrn "Removing plugin $1" rm -rf ${ZAF_PLUGINS_DIR}/$1 - rm -f ${ZAF_AGENT_CONFIGD}/zaf_${plugin}.conf + rm -f ${ZAF_AGENT_CONFIGD}/zaf_$1.conf ${ZAF_CROND}/zaf_$1 ${ZAF_SUDOERSD}/zaf_$1 } zaf_tolower() { From 2a0d6848a7e4107b3a5f207ec834ca8149a02ea5 Mon Sep 17 00:00:00 2001 From: Lukas Macura Date: Wed, 13 Apr 2016 16:04:00 +0200 Subject: [PATCH 27/33] Repaired caching Added testparameters and precacheparameters --- lib/cache.lib.sh | 18 +++++++++++------- lib/preload.sh | 3 ++- lib/zaf.lib.sh | 35 +++++++++++++++++++++++++++++------ zaf | 26 +++++++++++++++++++------- 4 files changed, 61 insertions(+), 21 deletions(-) diff --git a/lib/cache.lib.sh b/lib/cache.lib.sh index d5512c7..ebd02f5 100644 --- a/lib/cache.lib.sh +++ b/lib/cache.lib.sh @@ -20,13 +20,14 @@ zaf_cache_key(){ # $2 value # $3 lifetime in seconds zaf_tocache(){ + ! [ -w $ZAF_CACHE_DIR ] && return 1 local key local value - local lifetime + key=$(zaf_cache_key "$1") echo "$2" >$ZAF_CACHE_DIR/$key - echo "$1" >$ZAF_CACHE_DIR/$key.key - touch -m -d "$3 seconds" $ZAF_CACHE_DIR/$key.tme + echo "$1" >$ZAF_CACHE_DIR/$key.info + touch -m -d "$3 seconds" $ZAF_CACHE_DIR/$key.info zaf_trc "Cache: Saving entry $1($key)" } @@ -34,14 +35,15 @@ zaf_tocache(){ # $1 key # $2 lifetime in seconds zaf_tocache_stdin(){ + ! [ -w $ZAF_CACHE_DIR ] && return 1 local key - local lifetime + key=$(zaf_cache_key "$1") cat >$ZAF_CACHE_DIR/$key if [ -s $ZAF_CACHE_DIR/$key ]; then zaf_trc "Cache: Saving entry $1($key)" - echo "$1" >$ZAF_CACHE_DIR/$key.key - touch -m -d "$3 seconds" $ZAF_CACHE_DIR/$key.tme + echo "$1" >$ZAF_CACHE_DIR/$key.info + touch -m -d "$2 seconds" $ZAF_CACHE_DIR/$key.info cat $ZAF_CACHE_DIR/$key else rm $ZAF_CACHE_DIR/$key @@ -51,6 +53,7 @@ zaf_tocache_stdin(){ # Remove entry from cache # $1 key zaf_cache_delentry(){ + ! [ -w $ZAF_CACHE_DIR ] && return 1 local key key=$(zaf_cache_key "$1") zaf_trc "Cache: removing $1($key) from cache" @@ -60,11 +63,12 @@ zaf_cache_delentry(){ # Get object from cache # $1 key zaf_fromcache(){ + ! [ -r $ZAF_CACHE_DIR ] || [ -n "$ZAF_NOCACHE" ] && return 1 local key local value key=$(zaf_cache_key "$1") if [ -f $ZAF_CACHE_DIR/$key ]; then - if [ "$ZAF_CACHE_DIR/$key.tme" -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" cat $ZAF_CACHE_DIR/$key else diff --git a/lib/preload.sh b/lib/preload.sh index c2cbc50..46a8881 100644 --- a/lib/preload.sh +++ b/lib/preload.sh @@ -21,7 +21,8 @@ export ZAF_LIB_DIR export ZAF_TMP_DIR export ZAF_PLUGINS_DIR -if [ "$1" = "_cache" ]; then +if [ "$1" = "_cache" ] || [ "$1" = "_nocache" ] ; then + [ "$1" = "_nocache" ] && export ZAF_NOCACHE=1 shift seconds=$1 shift diff --git a/lib/zaf.lib.sh b/lib/zaf.lib.sh index 9b73a39..db71851 100644 --- a/lib/zaf.lib.sh +++ b/lib/zaf.lib.sh @@ -231,8 +231,14 @@ zaf_plugin_info() { [ -n "$pmaintainer" ] && echo "Maintainer: $pmaintainer" [ -n "$purl" ] && echo "Url: $purl" [ -n "$phome" ] && echo "Home: $phome" - echo - echo "Items: $pitems" + echo + if zaf_is_plugin "$(basename $plugin)"; then + echo -n "Defined items: "; zaf_list_plugin_items $plugin + echo -n "Test items: "; zaf_list_plugin_items $plugin test + echo -n "Precache items: "; zaf_list_plugin_items $plugin precache + else + echo "Items: $pitems" + fi echo } @@ -338,11 +344,15 @@ 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. "; @@ -352,12 +362,25 @@ zaf_list_plugin_items() { 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") if [ -n "$p" ]; then - key="$1.$i[]" + if [ -n "$testparms" ] && [ "$2" = "test" ]; then + for tp in $testparms; do + echo -n "$1.$i[$tp] " + done + else + if [ -n "$precache" ] && [ "$2" = "precache" ]; then + for tp in $precache; do + echo -n "$1.$i[$tp] " + done + fi + [ "$2" != "test" ] && key="$1.$i[]" + fi else key="$1.$i" fi - echo -n "$key " + [ "$2" != "precache" ] && echo -n "$key " done echo } @@ -379,12 +402,12 @@ zaf_get_item() { } zaf_test_item() { - [ "$USER" != "zabbix" ] && zaf_wrn "You are not zabbix user. Test will be run with your privileges and sudo access!" $ZAF_AGENT_BIN -t "$1" } zaf_precache_item() { - cmd=$(grep "^UserParameter=$item" $ZAF_AGENT_CONFIGD/zaf*.conf | cut -d ',' -f 2-) + 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 } diff --git a/zaf b/zaf index 275a413..3a9834d 100755 --- a/zaf +++ b/zaf @@ -144,6 +144,7 @@ items) ;; test) + [ "$USER" != "zabbix" ] && zaf_wrn "You are not zabbix user. Test will be run with your privileges and sudo access!" shift shift $(zaf_shift "$@") if echo $1|grep -q '\.'; then @@ -157,8 +158,9 @@ test) fi for p in $plugins; do ! zaf_is_plugin $p && zaf_err "Unknown plugin $p" - for i in $(zaf_list_plugin_items $p); do + for i in $(zaf_list_plugin_items $p test); do echo $i: $(zaf_test_item $i) + echo done done ;; @@ -175,8 +177,9 @@ get) plugins="$(zaf_list_plugins)" fi for p in $plugins; do - for i in $(zaf_list_plugin_items $p); do + for i in $(zaf_list_plugin_items $p test); do echo $i: $(zaf_get_item $i) + echo done done ;; @@ -185,9 +188,17 @@ precache) shift shift $(zaf_shift "$@") for i in $*; do - item=$(echo $i | cut -d '[' -f 1) - params=$(echo $i | cut -d '[' -f 2 | cut -d ']' -f 1 | tr ',' ' ') - zaf_precache_item $params + if zaf_is_plugin $i; then + for j in $(zaf_list_plugin_items $i precache); do + item=$(echo $j | cut -d '[' -f 1) + params=$(echo $j | cut -d '[' -f 2 | cut -d ']' -f 1 | tr ',' ' ') + zaf_precache_item $params >/dev/null + done + else + item=$(echo $i | cut -d '[' -f 1) + params=$(echo $i | cut -d '[' -f 2 | cut -d ']' -f 1 | tr ',' ' ') + zaf_precache_item $params >/dev/null + fi done ;; @@ -196,8 +207,8 @@ install) shift $(zaf_shift "$@") [ -z "$1" ] && echo "$0 install plugin [plugin]..." for p in $@; do - if zaf_is_plugin "$p"; then - zaf_wrn "Plugin $p already installed. Skipping installation." + if zaf_is_plugin "$(basename $p)"; then + zaf_wrn "Plugin $(basename $p) already installed. Skipping installation." continue fi zaf_install_plugin "$p" @@ -334,6 +345,7 @@ api) echo "$0 items [plugin] To list all suported items [for plugin]" echo "$0 test [plugin[.item]] To test [all] suported items by zabbix_agentd [for plugin]" echo "$0 get [plugin[.item]] To test [all] suported items by zabbix_get [for plugin]" + echo "$0 precache [plugin[.item]] To precache [all] suported items" 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." From 781f1f0bc0bc238000a9e2301c04f04b87da66dc Mon Sep 17 00:00:00 2001 From: Lukas Macura Date: Thu, 14 Apr 2016 09:57:59 +0200 Subject: [PATCH 28/33] Reworked parameters parsing Repaired install libraries loading Repaired installation error handling --- install.sh | 6 +++-- lib/ctrl.lib.sh | 60 +++++++++++++++++++++++++++++++----------- zaf | 70 ++++++++++++++++--------------------------------- 3 files changed, 72 insertions(+), 64 deletions(-) diff --git a/install.sh b/install.sh index a09132b..08e207e 100755 --- a/install.sh +++ b/install.sh @@ -25,7 +25,7 @@ zaf_download_files() { } if ! [ -f README.md ]; then - # We are runing from stdin + # We are runing from stdin if ! which curl >/dev/null; then zaf_err "Curl not found. Cannot continue. Please install it." @@ -41,6 +41,8 @@ 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 @@ -305,7 +307,7 @@ zaf_postconfigure() { else [ "${ZAF_GIT}" = 1 ] && [ -n "${INSTALL_PREFIX}" ] && git clone "${ZAF_REPO_GITURL}" "${INSTALL_PREFIX}/${ZAF_REPO_DIR}" fi - zaf_wrn "Install done. Use 'zaf' to get started. Do not forget to do 'zaf upgrade' to upgrade plugins too!" + zaf_wrn "Install done. Use 'zaf' to get started." true } diff --git a/lib/ctrl.lib.sh b/lib/ctrl.lib.sh index e8179d2..975f6e4 100644 --- a/lib/ctrl.lib.sh +++ b/lib/ctrl.lib.sh @@ -55,16 +55,32 @@ zaf_block_get_option() { # $1 - control file # $2 - option name zaf_ctrl_get_global_option() { - zaf_ctrl_get_global_block <$1 | zaf_block_get_moption "$2" \ - || zaf_ctrl_get_global_block <$1 | zaf_block_get_option "$2" + local ctrlopt + + eval ctrlopt=\$ZAF_CTRL_$(echo $2| tr '-' '_') + if [ -n "$ctrlopt" ]; then + zaf_wrn "Overriding $2 from env" + echo $ctrlopt + else + zaf_ctrl_get_global_block <$1 | zaf_block_get_moption "$2" \ + || zaf_ctrl_get_global_block <$1 | zaf_block_get_option "$2" + fi } # Get item specific option (single or multiline) # $1 - control file # $2 - item name # $3 - option name zaf_ctrl_get_item_option() { - zaf_ctrl_get_item_block <$1 "$2" | zaf_block_get_moption "$3" \ - || zaf_ctrl_get_item_block <$1 "$2" | zaf_block_get_option "$3" + local ctrlopt + + eval ctrlopt=\$ZAF_CTRL_$2_$(echo $3| tr '-' '_') + if [ -n "$ctrlopt" ]; then + zaf_wrn "Overriding item $2 option $3 from env" + echo $ctrlopt + else + zaf_ctrl_get_item_block <$1 "$2" | zaf_block_get_moption "$3" \ + || zaf_ctrl_get_item_block <$1 "$2" | zaf_block_get_option "$3" + fi } # Check dependencies based on control file @@ -93,19 +109,21 @@ zaf_ctrl_sudo() { local cmd local parms - if ! which sudo >/dev/null; then - zaf_wrn "Sudo needed bud not installed?" - fi pdir="$3" plugin=$1 zaf_dbg "Installing sudoers entry $ZAF_SUDOERSD/zaf_$plugin" sudo=$(zaf_ctrl_get_global_option $2 "Sudo" | zaf_far '{PLUGINDIR}' "${plugindir}") + [ -z "$sudo" ] && return # Nothing to install + if ! which sudo >/dev/null; then + zaf_wrn "Sudo needed bud not installed?" + fi cmd=$(echo $sudo | cut -d ' ' -f 1) parms=$(echo $sudo | cut -d ' ' -f 2-) if which $cmd >/dev/null ; then - (echo "zabbix ALL=NOPASSWD:SETENV: $(which $cmd) $(echo $parms | tr '%' '*')";echo) >$ZAF_SUDOERSD/zaf_$plugin + (echo "zabbix ALL=NOPASSWD:SETENV: $(which $cmd) $(echo $parms | tr '%' '*')";echo) >$ZAF_SUDOERSD/zaf_$plugin || zaf_err "Error during zaf_ctrl_sudo" + chmod 0440 $ZAF_SUDOERSD/zaf_$plugin else - zaf_wrn "Cannot find binary $cmd for sudo. Ignoring sudo." + zaf_err "Cannot find binary '$cmd' to put into sudoers." fi } @@ -116,14 +134,17 @@ zaf_ctrl_sudo() { zaf_ctrl_cron() { local pdir local plugin + local cron pdir="$3" plugin=$1 zaf_dbg "Installing cron entry $ZAF_CROND/zaf_$plugin" - zaf_ctrl_get_global_option $2 "Cron" | zaf_far '{PLUGINDIR}' "${plugindir}" >$ZAF_CROND/zaf_$plugin + cron=$(zaf_ctrl_get_global_option $2 "Cron") + [ -z "$cron" ] && return # Nothing to install + zaf_ctrl_get_global_option $2 "Cron" | zaf_far '{PLUGINDIR}' "${plugindir}" >$ZAF_CROND/zaf_$plugin || zaf_err "Error during zaf_ctrl_cron" } -# Install sudo options from control +# Install files defined to be installed in control to plugun directory # $1 pluginurl # $2 control # $3 plugindir @@ -131,21 +152,28 @@ zaf_ctrl_install() { local binaries local pdir local script - local cmd + local files + local f + local b pdir="$3" + (set -e binaries=$(zaf_ctrl_get_global_option $2 "Install-bin") for b in $binaries; do zaf_fetch_url "$1/$b" >"${ZAF_TMP_DIR}/$b" zaf_install_bin "${ZAF_TMP_DIR}/$b" "$pdir" done + files=$(zaf_ctrl_get_global_option $2 "Install-files") + for f in $files; do + zaf_fetch_url "$1/$b" >"${ZAF_TMP_DIR}/$b" + zaf_install "${ZAF_TMP_DIR}/$b" "$pdir" + done script=$(zaf_ctrl_get_global_option $2 "Install-script") [ -n "$script" ] && eval "$script" - cmd=$(zaf_ctrl_get_global_option $2 "Install-cmd") - [ -n "$cmd" ] && $cmd + true + ) || zaf_err "Error during zaf_ctrl_install" } - # Generates zabbix cfg from control file # $1 control # $2 pluginname @@ -158,6 +186,7 @@ zaf_ctrl_generate_cfg() { local cache items=$(zaf_ctrl_get_items <"$1") + (set -e for i in $items; do iscript=$(echo $i | tr -d '[]*&;:') params=$(zaf_ctrl_get_item_option $1 $i "Parameters") @@ -199,6 +228,7 @@ zaf_ctrl_generate_cfg() { fi zaf_err "Item $i declared in control file but has no Cmd, Function or Script!" done + ) || zaf_err "Error during zaf_ctrl_generate_cfg" } diff --git a/zaf b/zaf index 3a9834d..533830d 100755 --- a/zaf +++ b/zaf @@ -1,20 +1,29 @@ #!/bin/sh +if [ -z "$secondstage" ]; then ZAF_CFG_FILE="/etc/zaf.conf" -if [ -f $ZAF_CFG_FILE ]; then - . $ZAF_CFG_FILE -else - echo "Missing config file $ZAF_CFG_FILE! Exiting." - exit 2 -fi + if [ -f $ZAF_CFG_FILE ]; then + . $ZAF_CFG_FILE + else + echo "Missing config file $ZAF_CFG_FILE! Exiting." + exit 2 + 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 "${option}='$value'" -done + # Read options as config for ZAF + for pair in "$@"; do + if echo $pair | grep -qE '^ZAF\_(.*)='; then + option=$(echo $pair|cut -d '=' -f 1) + value=$(echo $pair|cut -d '=' -f 2-) + eval "${option}='$value'" + export secondstage=1 + else + params="$params $pair" + fi + done + export $(set |grep ^ZAF_ | cut -d '=' -f 1) + # If some variables in cmd were stripped, rerun only with right arguments and exported variables + [ -n "$secondstage" ] && exec $0 $params +fi [ -z "$ZAF_TMP_BASE" ] && ZAF_TMP_BASE=/tmp/zaf ZAF_TMP_DIR="${ZAF_TMP_BASE}-${USER}" @@ -54,25 +63,6 @@ if zaf_is_root; then chmod g+w "${ZAF_CACHE_DIR}" fi -zaf_shift(){ - local s - - if echo $1 |grep -q "="; then - if echo $2 |grep -q "="; then - if echo $3 |grep -q "="; then - s=3 - else - s=2 - fi - else - s=1 - fi - else - s=0 - fi - echo $s -} - case $1 in check-agent-config) @@ -110,7 +100,6 @@ upgrade) ;; show) shift; - shift $(zaf_shift "$@") if [ -z "$1" ]; then zaf_list_plugins | while read plugin; do zaf_plugin_info $ZAF_PLUGINS_DIR/$plugin/control.zaf @@ -135,7 +124,6 @@ plugins) items) shift - shift $(zaf_shift "$@") if [ -z "$1" ]; then zaf_list_items else @@ -146,7 +134,6 @@ items) test) [ "$USER" != "zabbix" ] && zaf_wrn "You are not zabbix user. Test will be run with your privileges and sudo access!" shift - shift $(zaf_shift "$@") if echo $1|grep -q '\.'; then zaf_test_item "$1" exit @@ -166,7 +153,6 @@ test) ;; get) shift - shift $(zaf_shift "$@") if echo $1|grep -q '\.'; then zaf_get_item "$1" exit @@ -186,7 +172,6 @@ get) precache) shift - shift $(zaf_shift "$@") for i in $*; do if zaf_is_plugin $i; then for j in $(zaf_list_plugin_items $i precache); do @@ -204,7 +189,6 @@ precache) install) shift - shift $(zaf_shift "$@") [ -z "$1" ] && echo "$0 install plugin [plugin]..." for p in $@; do if zaf_is_plugin "$(basename $p)"; then @@ -219,7 +203,6 @@ install) reinstall) shift - shift $(zaf_shift "$@") [ -z "$1" ] && echo "$0 reinstall plugin [plugin]..." for p in $@; do if zaf_is_plugin "$p"; then @@ -234,7 +217,6 @@ reinstall) remove) shift - shift $(zaf_shift "$@") [ -z "$1" ] && echo "$0 remove plugin [plugin]..." for p in $@; do if zaf_is_plugin "$p"; then @@ -247,7 +229,6 @@ remove) self-upgrade) shift - shift $(zaf_shift "$@") [ -z "$1" ] && auto=auto 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 @@ -261,7 +242,6 @@ self-upgrade) self-remove) shift - shift $(zaf_shift "$@") zaf_os_specific zaf_check_deps zaf && zaf_err "Zaf is installed as system package. Cannot self-remove." . /etc/zaf.conf if [ "$1" = "force" ]; then @@ -294,11 +274,8 @@ api) zaf_zbxapi_gethostsingroup $gid ;; backup-group) - set -e - shift $(zaf_shift) shift; shift gid=$(zaf_zbxapi_gethostgroupid "$1") - shift $(zaf_shift) shift hosts=$(zaf_zbxapi_gethostsingroup $gid) dir="." @@ -314,7 +291,6 @@ api) wait ;; backup-host) - shift $(zaf_shift) shift; shift hostid=$(zaf_zbxapi_gethostid "$1") zaf_wrn "Exporting host $3($hostid)..." @@ -336,7 +312,7 @@ api) *) echo "$0 Version ${ZAF_VERSION}. Please use some of this commands:" - echo "$0 Cmd [ZAF_OPTION=value] ..." + echo "$0 Cmd [ZAF_OPTION=value] [ZAF_CTRL_Option=value] ..." echo "Commands:" echo "$0 update To update repo (not plugins, similar to apt-get update)" echo "$0 upgrade To upgrade installed plugins from repo" From df7c5f56dd05299c68d3e042728883740901e0d4 Mon Sep 17 00:00:00 2001 From: Lukas Macura Date: Thu, 14 Apr 2016 10:04:45 +0200 Subject: [PATCH 29/33] Repaired self-upgrade --- zaf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zaf b/zaf index 533830d..9388cbd 100755 --- a/zaf +++ b/zaf @@ -236,7 +236,7 @@ self-upgrade) then zaf_err "Curl not found. Cannot continue. Please install it." fi - zaf_fetch_url $ZAF_RAW_URL/$ZAF_VERSION/install.sh | exec sh -s $auto "$@" + zaf_fetch_url $ZAF_RAW_URL/$ZAF_GITBRANCH/install.sh | exec sh -s $auto "$@" exit ;; From fef2bf5ac0c455dc74dc0c8563a4567a05006474 Mon Sep 17 00:00:00 2001 From: Lukas Macura Date: Thu, 14 Apr 2016 10:44:50 +0200 Subject: [PATCH 30/33] Sync master branch --- README.md | 4 ++-- lib/ctrl.lib.sh | 18 +++++++++++------- lib/zaf.lib.sh | 8 +++++++- zaf | 2 +- 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index e9a366b..9f4228e 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,7 @@ git clone https://github.com/limosek/zaf.git \ && git checkout master \ && git clone https://github.com/limosek/zaf-plugins.git \ && make deb PLUGINS="./zaf-plugins/fsx" IPLUGINS="zaf" ZAF_OPTIONS="ZAF_GIT=0" AGENT_OPTIONS="Z_Server=zabbix.server Z_ServerActive=zabbix.server Z_StartAgents=8" -sudo dpkg -i out/zaf-1.1master.deb +sudo dpkg -i out/zaf-1.2master.deb ``` General usage: ``` @@ -124,7 +124,7 @@ During plugin installation, zaf will check all dependencies, do install binaries Zaf binary can be installed on any system from openwrt to big system. It has minimal dependencies and is shell based. Is has minimal size (up to 50kb of code). It can be used for installing, removing and testing zaf plugin items. Zaf should be run as root. ``` zaf -zaf Version 1.1master. Please use some of this commands: +zaf Version 1.2master. Please use some of this commands: zaf update To update repo zaf plugins To list installed plugins zaf show [plugin] To show installed plugins or plugin info diff --git a/lib/ctrl.lib.sh b/lib/ctrl.lib.sh index 975f6e4..e5ee3f6 100644 --- a/lib/ctrl.lib.sh +++ b/lib/ctrl.lib.sh @@ -55,11 +55,13 @@ zaf_block_get_option() { # $1 - control file # $2 - option name zaf_ctrl_get_global_option() { + local ctrlvar local ctrlopt - eval ctrlopt=\$ZAF_CTRL_$(echo $2| tr '-' '_') - if [ -n "$ctrlopt" ]; then - zaf_wrn "Overriding $2 from env" + ctrlopt="ZAF_CTRL_$(zaf_stripctrl $2)" + eval ctrlvar=\$$ctrlopt + if [ -n "$ctrlvar" ]; then + zaf_dbg "Overriding control field $2 from env $ctrlopt($ctrlvar)" echo $ctrlopt else zaf_ctrl_get_global_block <$1 | zaf_block_get_moption "$2" \ @@ -71,11 +73,13 @@ zaf_ctrl_get_global_option() { # $2 - item name # $3 - option name zaf_ctrl_get_item_option() { + local ctrlvar local ctrlopt - eval ctrlopt=\$ZAF_CTRL_$2_$(echo $3| tr '-' '_') - if [ -n "$ctrlopt" ]; then - zaf_wrn "Overriding item $2 option $3 from env" + ctrlopt="ZAF_CTRLI_$(zaf_stripctrl $2)_$(zaf_stripctrl $3)" + eval ctrlvar=\$$ctrlopt + if [ -n "$ctrlvar" ]; then + zaf_dbg "Overriding item control field $2/$3 from env $ctrlopt($ctrlvar)" echo $ctrlopt else zaf_ctrl_get_item_block <$1 "$2" | zaf_block_get_moption "$3" \ @@ -188,7 +192,7 @@ zaf_ctrl_generate_cfg() { items=$(zaf_ctrl_get_items <"$1") (set -e for i in $items; do - iscript=$(echo $i | tr -d '[]*&;:') + iscript=$(zaf_stripctrl $i) params=$(zaf_ctrl_get_item_option $1 $i "Parameters") if [ -n "$params" ]; then ikey="$2.$i[*]" diff --git a/lib/zaf.lib.sh b/lib/zaf.lib.sh index db71851..ab51cc0 100644 --- a/lib/zaf.lib.sh +++ b/lib/zaf.lib.sh @@ -1,6 +1,6 @@ # Hardcoded variables -ZAF_VERSION="1.1" +ZAF_VERSION="1.2" ZAF_GITBRANCH="master" ZAF_URL="https://github.com/limosek/zaf" ZAF_RAW_URL="https://raw.githubusercontent.com/limosek/zaf" @@ -426,3 +426,9 @@ zaf_toupper() { tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' } +# Return simplified key with discarded special chars. +zaf_stripctrl() { + echo $1 | tr '[]*&;:.-' '________' +} + + diff --git a/zaf b/zaf index 9388cbd..d03009c 100755 --- a/zaf +++ b/zaf @@ -312,7 +312,7 @@ api) *) echo "$0 Version ${ZAF_VERSION}. Please use some of this commands:" - echo "$0 Cmd [ZAF_OPTION=value] [ZAF_CTRL_Option=value] ..." + echo "$0 Cmd [ZAF_OPTION=value] [ZAF_CTRL_Option=value] [ZAF_CTRLI_Item_Option=value] ..." echo "Commands:" echo "$0 update To update repo (not plugins, similar to apt-get update)" echo "$0 upgrade To upgrade installed plugins from repo" From ac0a75b9349efd49ffa83c14b722067ab0e91a3d Mon Sep 17 00:00:00 2001 From: Lukas Macura Date: Thu, 14 Apr 2016 14:31:01 +0200 Subject: [PATCH 31/33] Added template import/export Added host export --- lib/zaf.lib.sh | 14 ++++ lib/zbxapi.lib.sh | 174 +++++++++++++++++++++++++++++++++++++++++----- zaf | 87 +++++++++++++++++++---- 3 files changed, 246 insertions(+), 29 deletions(-) diff --git a/lib/zaf.lib.sh b/lib/zaf.lib.sh index ab51cc0..1af6899 100644 --- a/lib/zaf.lib.sh +++ b/lib/zaf.lib.sh @@ -78,6 +78,7 @@ zaf_bglimit(){ local maxbg local maxnumber local cnumber + [ -z "$BASH_VERSION" ] && { zaf_dbg "Job server not available. Use bash!"; return 1; } if [ $# -eq 0 ] ; then maxbg=5 else @@ -431,4 +432,17 @@ zaf_stripctrl() { echo $1 | tr '[]*&;:.-' '________' } +# Unescape string on stdin +# $1 - list of chars to unescape +zaf_strunescape() { + sed -e 's#\\\(['"$1"']\)#\1#g' +} + + +# Escape string on stdin +# $1 - list of chars to escape +zaf_strescape() { + sed -e 's#\(['"$1"']\)#\\\1#g' +} + diff --git a/lib/zbxapi.lib.sh b/lib/zbxapi.lib.sh index 24a6b5e..694283f 100644 --- a/lib/zbxapi.lib.sh +++ b/lib/zbxapi.lib.sh @@ -1,16 +1,25 @@ -# Call api function + +# Call api function and use cache # $1 - query string zaf_zbxapi_do() { + local result + zaf_trc "Zabbix API: $1" + result=$(curl -s -f -L -X POST -H 'Content-Type: application/json-rpc' -d "$1" "$ZAF_ZBXAPI_URL") + if [ $? = 0 ] && echo $result | grep -q '"result":'; then + zaf_trc "API OK" + echo $result + else + zaf_err "Error processing API request. ($?,$result)" + fi +} +# Call api function and cache results +# $1 - query string +zaf_zbxapi_do_cache() { local result if ! zaf_fromcache "$1"; then - zaf_trc "Zabbix API: $1" - result=$(curl -s -f -L -X POST -H 'Content-Type: application/json-rpc' -d "$1" "$ZAF_ZBXAPI_URL") - if [ $? = 0 ] && echo $result | grep -q '"result":'; then - zaf_tocache "$1" "$result" 60 - echo $result - else - zaf_err "Error processing API request. ($?,$result)" - fi + result=$(zaf_zbxapi_do "$1") + [ -n "$result" ] && zaf_tocache "$1" "$result" 60 + echo $result fi } @@ -21,7 +30,7 @@ zaf_zbxapi_getresult() { # Extract XML result from JSON response zaf_zbxapi_getxml() { - zaf_zbxapi_getresult | sed -e 's/{"jsonrpc":"2.0","result":"//' | sed -e 's/","id"\:1}//' | sed -e 's#\\\([<">/]\)#\1#g' + zaf_zbxapi_getresult | sed -e 's/{"jsonrpc":"2.0","result":"//' | sed -e 's/","id"\:1}//' | zaf_zbxapi_getstring | zaf_strunescape '<">/' } # Extract string from JSON response result @@ -58,8 +67,9 @@ zaf_zbxapi_login(){ if [ "$ZAF_ZBXAPI_AUTHTYPE" = "http" ] ; then 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") + result=$(zaf_zbxapi_do_cache "$authstr") ZAF_ZBXAPI_AUTH=$(echo $result |zaf_zbxapi_getresult| zaf_zbxapi_getstring) + [ -z "$ZAF_ZBXAPI_AUTH" ] && zaf_err "Cannot login into API" zaf_dbg "Logged into zabbix API ($ZAF_ZBXAPI_AUTH)" } @@ -68,6 +78,7 @@ zaf_zbxapi_gethostgroupid() { local hstr local filter local gfilter + local result hstr='{ "method": "hostgroup.get", @@ -81,7 +92,9 @@ zaf_zbxapi_gethostgroupid() { }, "id": 1 }' - zaf_zbxapi_do "$hstr" | zaf_zbxapi_getresult | tr ',' '\n' | cut -d '"' -f 4 + result=$(zaf_zbxapi_do_cache "$hstr" | zaf_zbxapi_getresult | tr ',' '\n' | cut -d '"' -f 4) + [ -z "$result" ] && zaf_err "HostGroup $1 not found!" + echo $result } # $1 hostname @@ -91,6 +104,7 @@ zaf_zbxapi_gethostid() { local groupid local filter local gfilter + local result host="$1" if [ -n "$host" ] ; then @@ -106,7 +120,37 @@ zaf_zbxapi_gethostid() { }, "id": 1 }' - zaf_zbxapi_do "$hstr" | zaf_zbxapi_getresult | tr ',' '\n' | cut -d '"' -f 4 + result=$(zaf_zbxapi_do_cache "$hstr" | zaf_zbxapi_getresult | tr ',' '\n' | cut -d '"' -f 4) + [ -z "$result" ] && zaf_err "Host $1 not found!" + echo $result +} + +# $1 hostname +zaf_zbxapi_gettemplateid() { + local hstr + local host + local groupid + local filter + local gfilter + local result + + host="$1" + if [ -n "$host" ] ; then + filter='"filter": { "host": [ "'$host'" ] },' + fi + hstr='{ + "method": "template.get", + "jsonrpc": "2.0", + "auth": "'$ZAF_ZBXAPI_AUTH'", + "params": { + '$filter' + "output": "shorten" + }, + "id": 1 + }' + result=$(zaf_zbxapi_do_cache "$hstr" | zaf_zbxapi_getresult | tr ',' '\n' | cut -d '"' -f 4) + [ -z "$result" ] && zaf_err "Template $1 not found!" + echo $result } # $1 hostid @@ -116,6 +160,7 @@ zaf_zbxapi_gethost() { local groupid local filter local gfilter + local result hostid="$1" if [ -n "$hostid" ] ; then @@ -131,9 +176,40 @@ zaf_zbxapi_gethost() { }, "id": 1 }' - zaf_zbxapi_do "$hstr" | zaf_zbxapi_getresult | zaf_zbxapi_getvalue host + result=$(zaf_zbxapi_do_cache "$hstr" | zaf_zbxapi_getresult | zaf_zbxapi_getvalue host) + [ -z "$result" ] && zaf_err "Hostid $1 not found!" + echo $result } +# $1 templateid +zaf_zbxapi_gettemplate() { + local hstr + local host + local groupid + local filter + local gfilter + local result + + hostid="$1" + if [ -n "$hostid" ] ; then + filter='"templateids": [ "'$hostid'" ],' + fi + hstr='{ + "method": "template.get", + "jsonrpc": "2.0", + "auth": "'$ZAF_ZBXAPI_AUTH'", + "params": { + '$filter' + "output": "extend" + }, + "id": 1 + }' + result=$(zaf_zbxapi_do_cache "$hstr" | zaf_zbxapi_getresult | zaf_zbxapi_getvalue host) + [ -z "$result" ] && zaf_err "Templateid $1 not found!" + echo $result +} + + # $1 hostgroupid zaf_zbxapi_gethostsingroup() { local hstr @@ -158,13 +234,14 @@ zaf_zbxapi_gethostsingroup() { }, "id": 1 }' - zaf_zbxapi_do "$hstr" | zaf_zbxapi_getresult | tr ',' '\n' | cut -d '"' -f 4 + zaf_zbxapi_do_cache "$hstr" | zaf_zbxapi_getresult | tr ',' '\n' | cut -d '"' -f 4 } # Host backup # $1 hostid -zaf_zbxapi_backuphost(){ +zaf_zbxapi_export_host(){ local bkpstr + local host host="$1" bkpstr=' @@ -182,7 +259,70 @@ zaf_zbxapi_backuphost(){ "auth": "'$ZAF_ZBXAPI_AUTH'", "id": 1 }' - zaf_zbxapi_do "$bkpstr" | zaf_zbxapi_getxml + zaf_zbxapi_do_cache "$bkpstr" | zaf_zbxapi_getxml +} + +# Template backup +# $1 templateid +zaf_zbxapi_export_template(){ + local bkpstr + local host + + host="$1" + bkpstr=' + { + "method": "configuration.export", + "jsonrpc": "2.0", + "params": { + "options": { + "templates": [ + "'$host'" + ] + }, + "format": "xml" + }, + "auth": "'$ZAF_ZBXAPI_AUTH'", + "id": 1 +}' + zaf_zbxapi_do_cache "$bkpstr" | zaf_zbxapi_getxml +} + +# Import template into zabbix +# $1 template file or stdin +zaf_zbxapi_import_template(){ + local tmplstr + local impstr + + if [ -z "$1" ]; then + tmplstr=$(zaf_strescape '"') + else + ! [ -f "$1" ] && return 1 + tmplstr=$(zaf_strescape '"\n\r' <$1) + fi + impstr=' + { + "method": "configuration.import", + "jsonrpc": "2.0", + "params": { + "format": "xml", + "rules": { + "hosts": { + "createMissing": true, + "updateExisting": true + }, + "items": { + "createMissing": true, + "updateExisting": true, + "deleteMissing": true + } + }, + "source": "'$tmplstr'" + }, + "auth": "'$ZAF_ZBXAPI_AUTH'", + "id": 3 +}' + echo "$impstr";exit + zaf_zbxapi_do "$impstr" | zaf_zbxapi_getresult | grep -q true } diff --git a/zaf b/zaf index d03009c..ba46e20 100755 --- a/zaf +++ b/zaf @@ -270,12 +270,12 @@ api) zaf_zbxapi_gethostgroupid "$3" ;; hosts) - gid=$(zaf_zbxapi_gethostgroupid "$3") + gid=$(zaf_zbxapi_gethostgroupid "$3") || exit 1 zaf_zbxapi_gethostsingroup $gid ;; - backup-group) + export-hosts-in-group) shift; shift - gid=$(zaf_zbxapi_gethostgroupid "$1") + gid=$(zaf_zbxapi_gethostgroupid "$1") || exit 1 shift hosts=$(zaf_zbxapi_gethostsingroup $gid) dir="." @@ -283,18 +283,78 @@ api) zaf_wrn "Will backup this hosts: $hosts" zaf_wrn "Output dir: $dir" for h in $hosts; do - zaf_bglimit 5 - (hn=$(zaf_zbxapi_gethost $h) - zaf_wrn "Exporting host $hn($h)..." - zaf_zbxapi_backuphost $h >$dir/$hn.xml ) + if zaf_bglimit 5; then + ( + hn=$(zaf_zbxapi_gethost $h) + zaf_wrn "Exporting host $hn($h)..." + zaf_zbxapi_export_host $h >"$dir/$hn.xml" + ) & + else + hn=$(zaf_zbxapi_gethost $h) + zaf_wrn "Exporting host $hn($h)..." + zaf_zbxapi_export_host $h >"$dir/$hn.xml" + fi done wait ;; - backup-host) + export-host) shift; shift - hostid=$(zaf_zbxapi_gethostid "$1") + hostid=$(zaf_zbxapi_gethostid "$1") || exit 1 zaf_wrn "Exporting host $3($hostid)..." - zaf_zbxapi_backuphost $hostid + zaf_zbxapi_export_host $hostid + ;; + export-template) + shift; shift + templateid=$(zaf_zbxapi_gettemplateid "$1") || exit 1 + zaf_wrn "Exporting template $3($hostid)..." + zaf_zbxapi_export_template $templateid + ;; + export-templates) + shift; shift + dir="." + [ -n "$1" ] && dir="$1" + templates=$(zaf_zbxapi_gettemplateid) + zaf_wrn "Will backup this templates: $templates" + zaf_wrn "Output dir: $dir" + for t in $templates; do + if zaf_bglimit 5; then + ( + tn=$(zaf_zbxapi_gettemplate $t) + zaf_wrn "Exporting template $tn($t)..." + zaf_zbxapi_export_template $t >"$dir/$tn.xml" + ) & + else + tn=$(zaf_zbxapi_gettemplate $t) + zaf_wrn "Exporting template $tn($t)..." + zaf_zbxapi_export_template $t >"$dir/$tn.xml" + fi + done + wait + ;; + import-template) + shift; shift + if zaf_is_plugin $1; then + if [ -f "$ZAF_PLUGINS_DIR/$1/template.xml" ]; then + template="$ZAF_PLUGINS_DIR/$1/template.xml" + zaf_wrn "Importing template $template" + zaf_zbxapi_import_template $template || zaf_err "Error importing template" + else + url="$(zaf_plugin_option $1 Template)" + if [ -n "$url" ]; then + zaf_fetch_url $url | zaf_zbxapi_import_template || zaf_err "Error importing template" + else + url="$(zaf_plugin_option $1 Url)" + zaf_fetch_url $url/template.xml | zaf_zbxapi_import_template || zaf_err "Error importing template" + fi + fi + else + if [ -f $1 ]; then + zaf_wrn "Importing template $1" + zaf_zbxapi_import_template $1 || zaf_err "Error importing template" + else + zaf_err "Unknown plugin $1!" + fi + fi ;; *) echo "$0 api command [parameters]" @@ -302,8 +362,11 @@ api) echo "host 'hostid' Get hostname from hostid" echo "hostgroupid 'hostgroup' Get hostgroup id from hostgroup" echo "hosts 'hostgroup' Get hosts in group" - echo "backup-group 'hostgroup' [dir] Backup all hosts in group (get their config from zabbix and save to dir/hostname.xml)" - echo "backup-host 'host' Backup host (get config from zabbix to stdout)" + echo "export-hosts-in-group 'hostgroup' [dir] Backup all hosts in group (get their config from zabbix and save to dir/hostname.xml)" + echo "export-host 'host' Backup host (get config from zabbix to stdout)" + echo "import-template {plugin|file} Import template for plugin or from file" + echo "export-template 'name' Export template to stdout" + echo "export-templates [dir] Export all template to dir" echo exit ;; From 9c6cd711eed964437fe377a993a2393e17400b2c Mon Sep 17 00:00:00 2001 From: Lukas Macura Date: Thu, 14 Apr 2016 14:46:29 +0200 Subject: [PATCH 32/33] Changed parameters to export --- zaf | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/zaf b/zaf index ba46e20..7c488f3 100755 --- a/zaf +++ b/zaf @@ -273,13 +273,18 @@ api) gid=$(zaf_zbxapi_gethostgroupid "$3") || exit 1 zaf_zbxapi_gethostsingroup $gid ;; - export-hosts-in-group) + export-hosts) shift; shift - gid=$(zaf_zbxapi_gethostgroupid "$1") || exit 1 + [ -z "$1" ] && zaf_err "$0 api export-hosts dir [hostgroup]" + dir="$1" shift - hosts=$(zaf_zbxapi_gethostsingroup $gid) - dir="." - [ -n "$1" ] && dir="$1" + if [ -n "$1" ]; then + gid=$(zaf_zbxapi_gethostgroupid "$1") || exit 1 + shift + hosts=$(zaf_zbxapi_gethostsingroup $gid) + else + hosts=$(zaf_zbxapi_gethostid) + fi zaf_wrn "Will backup this hosts: $hosts" zaf_wrn "Output dir: $dir" for h in $hosts; do @@ -311,8 +316,8 @@ api) ;; export-templates) shift; shift - dir="." - [ -n "$1" ] && dir="$1" + [ -z "$1" ] && zaf_err "$0 api export-templates dir" + dir="$1" templates=$(zaf_zbxapi_gettemplateid) zaf_wrn "Will backup this templates: $templates" zaf_wrn "Output dir: $dir" @@ -362,11 +367,11 @@ api) echo "host 'hostid' Get hostname from hostid" echo "hostgroupid 'hostgroup' Get hostgroup id from hostgroup" echo "hosts 'hostgroup' Get hosts in group" - echo "export-hosts-in-group 'hostgroup' [dir] Backup all hosts in group (get their config from zabbix and save to dir/hostname.xml)" + echo "export-hosts dir [hostgroup] Backup all hosts [in group] (get their config from zabbix and save to dir/hostname.xml)" echo "export-host 'host' Backup host (get config from zabbix to stdout)" echo "import-template {plugin|file} Import template for plugin or from file" echo "export-template 'name' Export template to stdout" - echo "export-templates [dir] Export all template to dir" + echo "export-templates dir Export all template to dir" echo exit ;; From 844193fd23bd887ab9ffcba6f4e484e3e5ab6c77 Mon Sep 17 00:00:00 2001 From: Lukas Macura Date: Thu, 14 Apr 2016 15:10:42 +0200 Subject: [PATCH 33/33] Added more objects to import/export --- lib/zbxapi.lib.sh | 102 ++++++++++++++++++++++++++++++---------------- 1 file changed, 67 insertions(+), 35 deletions(-) diff --git a/lib/zbxapi.lib.sh b/lib/zbxapi.lib.sh index 694283f..dd570ce 100644 --- a/lib/zbxapi.lib.sh +++ b/lib/zbxapi.lib.sh @@ -237,21 +237,25 @@ zaf_zbxapi_gethostsingroup() { zaf_zbxapi_do_cache "$hstr" | zaf_zbxapi_getresult | tr ',' '\n' | cut -d '"' -f 4 } -# Host backup -# $1 hostid -zaf_zbxapi_export_host(){ +# Object backup +# $1 object +# $2 id +zaf_zbxapi_export_object(){ local bkpstr - local host + local obj + local id - host="$1" + obj="$1" + id="$2" + bkpstr=' { "method": "configuration.export", "jsonrpc": "2.0", "params": { "options": { - "hosts": [ - "'$host'" + "'$obj'": [ + "'$id'" ] }, "format": "xml" @@ -262,42 +266,36 @@ zaf_zbxapi_export_host(){ zaf_zbxapi_do_cache "$bkpstr" | zaf_zbxapi_getxml } + +# Host backup +# $1 hostid +zaf_zbxapi_export_host(){ + zaf_zbxapi_export_object hosts "$1" +} + # Template backup # $1 templateid zaf_zbxapi_export_template(){ - local bkpstr - local host - - host="$1" - bkpstr=' - { - "method": "configuration.export", - "jsonrpc": "2.0", - "params": { - "options": { - "templates": [ - "'$host'" - ] - }, - "format": "xml" - }, - "auth": "'$ZAF_ZBXAPI_AUTH'", - "id": 1 -}' - zaf_zbxapi_do_cache "$bkpstr" | zaf_zbxapi_getxml + zaf_zbxapi_export_object templates "$1" +} + +# Map backup +# $1 mapid +zaf_zbxapi_export_map(){ + zaf_zbxapi_export_object maps "$1" } # Import template into zabbix # $1 template file or stdin -zaf_zbxapi_import_template(){ - local tmplstr +zaf_zbxapi_import_config(){ + local xmlstr local impstr if [ -z "$1" ]; then - tmplstr=$(zaf_strescape '"') + xmlstr=$(zaf_strescape '"') else ! [ -f "$1" ] && return 1 - tmplstr=$(zaf_strescape '"\n\r' <$1) + xmlstr=$(zaf_strescape '"\n\r' <$1) fi impstr=' { @@ -306,22 +304,56 @@ zaf_zbxapi_import_template(){ "params": { "format": "xml", "rules": { + "applications": { + "createMissing": true, + "updateExisting": true + }, + "discoveryRules": { + "createMissing": true, + "updateExisting": true + }, + "graphs": { + "createMissing": true, + "updateExisting": true + }, "hosts": { "createMissing": true, "updateExisting": true }, "items": { "createMissing": true, - "updateExisting": true, - "deleteMissing": true + "updateExisting": true + }, + "templates": { + "createMissing": true, + "updateExisting": true + }, + "triggers": { + "createMissing": true, + "updateExisting": true + }, + "maps": { + "createMissing": true, + "updateExisting": true + }, + "screens": { + "createMissing": true, + "updateExisting": true + }, + "items": { + "createMissing": true, + "updateExisting": true + }, + "valueMaps": { + "createMissing": true, + "updateExisting": true } }, - "source": "'$tmplstr'" + "source": "'$xmlstr'" }, "auth": "'$ZAF_ZBXAPI_AUTH'", "id": 3 }' - echo "$impstr";exit zaf_zbxapi_do "$impstr" | zaf_zbxapi_getresult | grep -q true }