pull/1/head
Lukas Macura 2016-04-14 21:38:22 +02:00
commit 93ab7c3c65
17 changed files with 1598 additions and 245 deletions

2
.gitignore vendored
View File

@ -1,2 +1,4 @@
*~
plugins/
out/
tmp/

91
Makefile Normal file
View File

@ -0,0 +1,91 @@
# 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=$(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
endif
ifeq ($(IPLUGINS),)
IPLUGINS = zaf
endif
all: help
help:
@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: $(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)
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_GITBRANCH" = "master" ] && master=master; \
zaf_far '{ZAF_VERSION}' "$${ZAF_VERSION}$$master" <files/control.template | zaf_far '{ZAF_DEPENDS}' "$$DEPENDS" >$(DEBIAN_CTRL)/control
deb-scripts:
@. lib/zaf.lib.sh; \
. lib/ctrl.lib.sh; \
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
deb-cp:
@mkdir -p $(DEBIAN_DIR)
@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 \
plugin=$$(zaf_ctrl_get_global_option $$p/control.zaf 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
@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
endif
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

167
README.md
View File

@ -5,57 +5,162 @@ 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 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
* 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.
* 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 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; 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 [...]
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. 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. 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 \
Z_Server=zabbix.server.local \
Z_ServerActive=zabbix.server.local \
Z_HostnameItem=system.hostname Z_RefreshActiveChecks=60 \
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 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.2master.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.
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
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
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
```
### 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 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.
## 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
## 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.
```
## Zaf control file
Control files are similar to Debian Control files
```
will be explained
```

5
files/changelog.template Normal file
View File

@ -0,0 +1,5 @@
PACKAGE (1.0) zaf; urgency=medium
* Initial release.
-- Lukas Macura <lukas@macura.cz> Wed, 06 Apr 2016 13:56:25 +0200

11
files/control.template Normal file
View File

@ -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 <lukas@macura.cz>
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.

17
files/postinst.template Normal file
View File

@ -0,0 +1,17 @@
#!/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
[ -n "{PLUGINS}" ] && zaf reinstall {PLUGINS} {IPLUGINS}
fi
;;
esac
true

10
files/preinst.template Normal file
View File

@ -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

7
files/prerm.template Normal file
View File

@ -0,0 +1,7 @@
#!/bin/sh
case $1 in
remove)
rm -rf /usr/lib/zaf/plugins /usr/lib/zaf/repo
;;
esac

View File

@ -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'

View File

@ -1,21 +1,48 @@
#!/bin/sh
if ! [ "$(basename $0)" = "install.sh" ]; then
[ -z "$ZAF_DEBUG" ] && ZAF_DEBUG=1
if [ -z "$ZAF_URL" ]; then
# Runing as standalone install.sh. We have to download rest of files first.
ZAF_URL="https://github.com/limosek/zaf/"
fi
[ -z "$ZAF_GITBRANCH" ] && ZAF_GITBRANCH=master
# 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_GITBRANCH.tar.gz | tar -f - -C /tmp -zx && mv /tmp/zaf-$ZAF_GITBRANCH /tmp/zaf-installer
}
if ! [ -f README.md ]; then
# We are runing from stdin
url="https://raw.githubusercontent.com/limosek/zaf/master/"
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 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
. lib/cache.lib.sh
. lib/zbxapi.lib.sh
fi
# Read options as config for ZAF
@ -24,17 +51,11 @@ 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.
@ -81,32 +102,61 @@ 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
}
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
zaf_agent_set_option() {
zaf_set_agent_option() {
local option="$1"
local value="$2"
if grep ^$option\= $ZAF_AGENT_CONFIG; then
zaf_wrn "Moving option $option to zaf config part."
sed -i "s/$option=/#$option=/" $ZAF_AGENT_CONFIG
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
else
zaf_move_agent_option "$1" "$2"
fi
echo "$option=$value" >> "$ZAF_AGENT_CONFIGD/zaf_options.conf"
}
# 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
}
# 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 -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
[ -n "$value" ] && echo "$option=$value" >> "$ZAF_AGENT_CONFIGD/zaf_options.conf"
}
# Automaticaly configure agent if supported
@ -115,31 +165,45 @@ zaf_configure_agent() {
local pair
local option
local value
local options
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"
! [ -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)
value=$(echo $pair|cut -d '=' -f 2-)
zaf_agent_set_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_preconfigure(){
zaf_detect_system
zaf_os_specific zaf_configure_os
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_configure(){
zaf_detect_system
zaf_os_specific zaf_configure_os
if ! zaf_is_root; then
[ -z "$INSTALL_PREFIX" ] && zaf_err "We are not root. Use INSTALL_PREFIX or become root."
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_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
@ -147,24 +211,31 @@ zaf_configure(){
if which git >/dev/null; then
ZAF_GIT=1
else
ZAF_GIT=""
ZAF_GIT=0
fi
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}" -eq 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"
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."
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_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"
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
[ -n "$INSTALL_PREFIX" ] && zaf_install_dir "/etc"
@ -182,87 +253,143 @@ 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}" -eq 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"
ZAF_TMP_DIR="${ZAF_TMP_BASE}-${USER}-$$"
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"
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
zaf_configure_agent $ZAF_AGENT_OPTIONS "$@"
zaf_add_agent_option "Include" "$ZAF_AGENT_CONFIGD"
fi
}
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
zaf_configure_agent "$@"
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 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_err "Error installing $i"
done
zaf_install_dir ${ZAF_BIN_DIR}
for i in zaf; do
zaf_install_bin $i ${ZAF_BIN_DIR}/ || zaf_err "Error installing $i"
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
if zaf_is_root; then
[ "${ZAF_GIT}" -eq 1 ] && ${INSTALL_PREFIX}/${ZAF_BIN_DIR}/zaf update
}
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_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."
echo "Does ${ZAF_AGENT_RESTART} work?"
exit 1
fi
else
[ "${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."
true
}
if [ -f "${ZAF_CFG_FILE}" ]; then
. "${ZAF_CFG_FILE}"
fi
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
INSTALL_MODE=interactive
zaf_preconfigure
zaf_configure "$@"
zaf_install_all
zaf_postconfigure
;;
auto)
shift
INSTALL_MODE=auto
zaf_preconfigure
zaf_configure "$@"
zaf_install_all
zaf_postconfigure
;;
debug-auto)
shift;
ZAF_DEBUG=4
INSTALL_MODE=auto
zaf_preconfigure
zaf_configure "$@"
zaf_install_all
zaf_postconfigure
;;
debug-interactive)
shift;
ZAF_DEBUG=4
INSTALL_MODE=interactive
zaf_preconfigure
zaf_configure "$@"
zaf_install_all
zaf_postconfigure
;;
debug)
shift;
ZAF_DEBUG=4
INSTALL_MODE=auto
zaf_preconfigure
zaf_configure "$@"
zaf_install_all
zaf_postconfigure
;;
reconf)
shift;
rm -f $ZAF_CFG_FILE
INSTALL_MODE=auto
zaf_preconfigure reconf
zaf_configure "$@"
zaf_postconfigure
;;
install)
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)'

84
lib/cache.lib.sh Normal file
View File

@ -0,0 +1,84 @@
# Zaf cache related functions
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_cache_key(){
echo "$1" | md5sum - | cut -d ' ' -f 1
}
# Put object into cache
# $1 key
# $2 value
# $3 lifetime in seconds
zaf_tocache(){
! [ -w $ZAF_CACHE_DIR ] && return 1
local key
local value
key=$(zaf_cache_key "$1")
echo "$2" >$ZAF_CACHE_DIR/$key
echo "$1" >$ZAF_CACHE_DIR/$key.info
touch -m -d "$3 seconds" $ZAF_CACHE_DIR/$key.info
zaf_trc "Cache: Saving entry $1($key)"
}
# Put object into cache from stdin and copy to stdout
# $1 key
# $2 lifetime in seconds
zaf_tocache_stdin(){
! [ -w $ZAF_CACHE_DIR ] && return 1
local key
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.info
touch -m -d "$2 seconds" $ZAF_CACHE_DIR/$key.info
cat $ZAF_CACHE_DIR/$key
else
rm $ZAF_CACHE_DIR/$key
fi
}
# 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"
rm -f "$ZAF_CACHE_DIR/$key*"
}
# 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.info" -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
}

View File

@ -55,33 +55,100 @@ 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 ctrlvar
local ctrlopt
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" \
|| 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 ctrlvar
local ctrlopt
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" \
|| zaf_ctrl_get_item_block <$1 "$2" | zaf_block_get_option "$3"
fi
}
# Check dependencies based on control file
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
}
# Install binaries from control
# Install sudo config from control
# $1 plugin
# $2 control
# $3 plugindir
zaf_ctrl_sudo() {
local pdir
local plugin
local sudo
local cmd
local parms
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 || zaf_err "Error during zaf_ctrl_sudo"
chmod 0440 $ZAF_SUDOERSD/zaf_$plugin
else
zaf_err "Cannot find binary '$cmd' to put into sudoers."
fi
}
# Install crontab config from control
# $1 plugin
# $2 control
# $3 plugindir
zaf_ctrl_cron() {
local pdir
local plugin
local cron
pdir="$3"
plugin=$1
zaf_dbg "Installing cron entry $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 files defined to be installed in control to plugun directory
# $1 pluginurl
# $2 control
# $3 plugindir
@ -89,18 +156,26 @@ zaf_ctrl_install() {
local binaries
local pdir
local script
local cmd
local files
local f
local b
pdir="$3"
binaries=$(zaf_ctrl_get_global_block <$2 | zaf_block_get_option "Install-bin")
(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
script=$(zaf_ctrl_get_global_block <$2 | zaf_block_get_moption "Install-script")
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_block <$2 | zaf_block_get_option "Install-cmd")
[ -n "$cmd" ] && $cmd
true
) || zaf_err "Error during zaf_ctrl_install"
}
# Generates zabbix cfg from control file
@ -112,13 +187,21 @@ zaf_ctrl_generate_cfg() {
local iscript
local ikey
local lock
local cache
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[*]"
args=""
apos=1;
for p in $params; do
args="$args \$$apos"
apos=$(expr $apos + 1)
done
else
ikey="$2.$i"
fi
@ -126,25 +209,30 @@ 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
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
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}/${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 $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!"
done
) || zaf_err "Error during zaf_ctrl_generate_cfg"
}

View File

@ -8,26 +8,39 @@ 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_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"
ZAF_OS="freebsd"
ZAF_OS_CODENAME="$(freebsd-version|cut -d '-' -f 1)"
return
else
ZAF_PKG="unknown"
@ -35,6 +48,7 @@ zaf_detect_system() {
ZAF_OS_CODENAME="unknown"
ZAF_AGENT_PKG=""
return
fi
fi
fi
fi
@ -101,22 +115,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
@ -124,7 +147,16 @@ 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
}
# 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:' || { return 1; }
done
}

View File

@ -4,18 +4,34 @@
[ -z "$ZAF_TMP_BASE" ] && ZAF_TMP_BASE=/tmp/zaf
ZAF_TMP_DIR="${ZAF_TMP_BASE}-${USER}"
[ -z "$ZAF_CACHE_DIR" ] && ZAF_CACHE_DIR=${ZAF_TMP_BASE}c
trap "rm -rif ${ZAF_TMP_DIR}" EXIT
! [ -d "${ZAF_TMP_DIR}" ] && mkdir "${ZAF_TMP_DIR}"
! [ -d "${ZAF_CACHE_DIR}" ] && mkdir "${ZAF_CACHE_DIR}"
[ -z "$ZAF_DEBUG" ] && ZAF_DEBUG=1
. ${ZAF_LIB_DIR}/zaf.lib.sh
. ${ZAF_LIB_DIR}/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
[ -n "$*" ] && $@
if [ "$1" = "_cache" ] || [ "$1" = "_nocache" ] ; then
[ "$1" = "_nocache" ] && export ZAF_NOCACHE=1
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

View File

@ -1,21 +1,26 @@
# Hardcoded variables
ZAF_VERSION="trunk"
ZAF_URL="https://raw.githubusercontent.com/limosek/zaf/master/"
ZAF_VERSION="1.2"
ZAF_GITBRANCH="master"
ZAF_URL="https://github.com/limosek/zaf"
ZAF_RAW_URL="https://raw.githubusercontent.com/limosek/zaf"
############################################ Common routines
zaf_msg() {
echo $@
}
zaf_trc() {
[ "$ZAF_DEBUG" -ge "3" ] && logger -s -t zaf -- $@
}
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
}
@ -31,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
@ -39,9 +48,10 @@ 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_msg curl $insecure -f -s -L -o - "$1"
curl $insecure -f -s -L -o - "$1"
zaf_dbg curl $insecure -f -s -L -o - $1
curl $insecure -f -s -L -o - "$1" | zaf_tocache_stdin "$1" 120
;;
esac
}
@ -63,6 +73,28 @@ zaf_far(){
eval $sedcmd
}
# Limit concurrent processes or continue
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
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 <<EOF
@ -131,7 +163,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
@ -142,11 +174,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
}
@ -157,6 +189,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 +199,15 @@ 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
if [ -n "${ZAF_REPO_URL}" ]; then
url="${ZAF_REPO_URL}/$1"
else
zaf_err "Cannot find plugin $1"
fi
fi
fi
fi
fi
@ -177,6 +218,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)
@ -190,8 +232,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
}
@ -199,7 +247,11 @@ 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() {
url=$(zaf_get_plugin_url "$1")/control.zaf
local url
local plugindir
local control
url=$(zaf_get_plugin_url "$1")/control.zaf || exit $?
plugindir="$2"
control=${plugindir}/control.zaf
zaf_install_dir "$plugindir"
@ -207,23 +259,33 @@ 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
}
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
[ "$ZAF_DEBUG" -gt 0 ] && zaf_plugin_info "${control}"
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 1 ] && zaf_plugin_info "${control}"
zaf_ctrl_check_deps "${control}"
zaf_ctrl_install "$1" "${control}" "${plugindir}"
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"
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"
@ -249,25 +311,49 @@ zaf_discovery_plugins() {
zaf_list_plugins | zaf_discovery '{#PLUGIN}'
}
zaf_plugin_version() {
# $1 plugin
# $2 ctrl_option
zaf_plugin_option() {
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 $2
else
echo "Plugin $1 not installed"
zaf_err "Plugin $1 not installed."
fi
}
zaf_plugin_version() {
zaf_plugin_option "$1" Version
}
zaf_plugin_maintainer() {
zaf_plugin_option "$1" Maintainer
}
zaf_plugin_url() {
zaf_plugin_option "$1" Url
}
zaf_plugin_web() {
zaf_plugin_option "$1" Web
}
zaf_plugin_template_url() {
echo $(zaf_plugin_option "$1" Url)/template.xml
}
# $1 plugin
# $2 test to get test items, precache to get items to precache
zaf_list_plugin_items() {
local items
local i
local p
local key
local testparms
local precache
if ! zaf_is_plugin "$1"; then
zaf_err "Missing plugin name or plugin $1 unknown. ";
@ -277,12 +363,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
}
@ -293,15 +392,57 @@ 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() {
$ZAF_AGENT_BIN -t "$1"
}
zaf_precache_item() {
cmd=$(grep "^UserParameter=$item" $ZAF_AGENT_CONFIGD/zaf*.conf | cut -d ',' -f 2- | sed -e "s/_cache/_nocache/")
zaf_wrn "Precaching item $item[$(echo $*| tr ' ' ',')] ($cmd)"
eval $cmd
}
zaf_remove_plugin() {
! [ -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() {
tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'
}
zaf_toupper() {
tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
}
# Return simplified key with discarded special chars.
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'
}

360
lib/zbxapi.lib.sh Normal file
View File

@ -0,0 +1,360 @@
# 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
result=$(zaf_zbxapi_do "$1")
[ -n "$result" ] && 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}//' | zaf_zbxapi_getstring | zaf_strunescape '<">/'
}
# 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_*
# returns auth on stdout or false
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"
}'
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_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)"
}
# $1 hostgroup name
zaf_zbxapi_gethostgroupid() {
local hstr
local filter
local gfilter
local result
hstr='{
"method": "hostgroup.get",
"jsonrpc": "2.0",
"auth": "'$ZAF_ZBXAPI_AUTH'",
"params": {
"filter": {
"name": ["'$1'"]
},
"output": "shorten"
},
"id": 1
}'
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
zaf_zbxapi_gethostid() {
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": "host.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 "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
zaf_zbxapi_gethost() {
local hstr
local host
local groupid
local filter
local gfilter
local result
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
}'
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
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_cache "$hstr" | zaf_zbxapi_getresult | tr ',' '\n' | cut -d '"' -f 4
}
# Object backup
# $1 object
# $2 id
zaf_zbxapi_export_object(){
local bkpstr
local obj
local id
obj="$1"
id="$2"
bkpstr='
{
"method": "configuration.export",
"jsonrpc": "2.0",
"params": {
"options": {
"'$obj'": [
"'$id'"
]
},
"format": "xml"
},
"auth": "'$ZAF_ZBXAPI_AUTH'",
"id": 1
}'
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(){
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_config(){
local xmlstr
local impstr
if [ -z "$1" ]; then
xmlstr=$(zaf_strescape '"')
else
! [ -f "$1" ] && return 1
xmlstr=$(zaf_strescape '"\n\r' <$1)
fi
impstr='
{
"method": "configuration.import",
"jsonrpc": "2.0",
"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
},
"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": "'$xmlstr'"
},
"auth": "'$ZAF_ZBXAPI_AUTH'",
"id": 3
}'
zaf_zbxapi_do "$impstr" | zaf_zbxapi_getresult | grep -q true
}

319
zaf
View File

@ -1,55 +1,118 @@
#!/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
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
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}"
trap "rm -rif ${ZAF_TMP_DIR}" EXIT
! [ -d "${ZAF_TMP_DIR}" ] && mkdir "${ZAF_TMP_DIR}"
[ -z "$ZAF_CACHE_DIR" ] && ZAF_CACHE_DIR=${ZAF_TMP_BASE}c
[ -z "$ZAF_DEBUG" ] && ZAF_DEBUG=1
export ZAF_DEBUG
# If debug is on, do not remove tmp dir
if [ "$ZAF_DEBUG" -le 3 ]; then
trap "rm -rif ${ZAF_TMP_DIR}" EXIT
fi
! [ -d "${ZAF_TMP_DIR}" ] && mkdir "${ZAF_TMP_DIR}"
if ! [ -d "${ZAF_CACHE_DIR}" ]; then
mkdir "${ZAF_CACHE_DIR}"
fi
if [ -f ./lib/zaf.lib.sh ]; then
. ./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
if zaf_is_root; then
chgrp zabbix "${ZAF_CACHE_DIR}"
chmod g+w "${ZAF_CACHE_DIR}"
fi
case $1 in
check-agent-config)
zaf_check_agent_config
;;
update)
zaf_update_repo
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
;;
upgrade)
ZAF_DEBUG=$ZAF_DEBUG $0 reinstall $(zaf_list_plugins)
;;
show)
if [ -z "$2" ]; then
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
@ -60,33 +123,76 @@ plugins)
;;
items)
if [ -z "$2" ]; then
shift
if [ -z "$1" ]; then
zaf_list_items
else
zaf_list_plugin_items "$2"
zaf_list_plugin_items "$1"
fi
;;
test)
if [ -n "$2" ]; then
shift
[ "$USER" != "zabbix" ] && zaf_wrn "You are not zabbix user. Test will be run with your privileges and sudo access!"
shift
if echo $1|grep -q '\.'; then
zaf_test_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
! zaf_is_plugin $p && zaf_err "Unknown plugin $p"
for i in $(zaf_list_plugin_items $p test); do
echo $i: $(zaf_test_item $i)
echo
done
done
;;
get)
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 test); do
echo $i: $(zaf_get_item $i)
echo
done
done
;;
precache)
shift
for i in $*; do
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
;;
install)
shift;
[ -z "$@" ] && echo "$0 install plugin [plugin]..."
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"
@ -96,8 +202,8 @@ install)
;;
reinstall)
shift;
[ -z "$@" ] && echo "$0 reinstall plugin [plugin]..."
shift
[ -z "$1" ] && echo "$0 reinstall plugin [plugin]..."
for p in $@; do
if zaf_is_plugin "$p"; then
zaf_remove_plugin "$(basename $p)"
@ -110,8 +216,8 @@ reinstall)
;;
remove)
shift;
[ -z "$@" ] && echo "$0 remove plugin [plugin]..."
shift
[ -z "$1" ] && echo "$0 remove plugin [plugin]..."
for p in $@; do
if zaf_is_plugin "$p"; then
zaf_remove_plugin "$p"
@ -122,17 +228,23 @@ remove)
;;
self-upgrade)
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 zaf_fetch_url $ZAF_URL/install.sh >/tmp/zaf-installer/install.sh; then
cd /tmp/zaf-installer && ./install.sh
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
zaf_fetch_url $ZAF_RAW_URL/$ZAF_GITBRANCH/install.sh | exec sh -s $auto "$@"
exit
;;
self-remove)
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
@ -143,18 +255,151 @@ 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") || exit 1
zaf_zbxapi_gethostsingroup $gid
;;
export-hosts)
shift; shift
[ -z "$1" ] && zaf_err "$0 api export-hosts dir [hostgroup]"
dir="$1"
shift
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
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
;;
export-host)
shift; shift
hostid=$(zaf_zbxapi_gethostid "$1") || exit 1
zaf_wrn "Exporting host $3($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
[ -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"
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]"
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 "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
exit
;;
esac
;;
*)
echo "$0 update To update repo"
echo "$0 Version ${ZAF_VERSION}. Please use some of this commands:"
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"
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 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."
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
;;
esac