From 2977958dd58e58bd93566da9f4e9387b2d2bcd36 Mon Sep 17 00:00:00 2001 From: Lukas Macura Date: Mon, 30 Jan 2017 10:32:29 +0100 Subject: [PATCH] Support for plugin subcommands --- install.sh | 24 ++++++++++++-- lib/ctrl.lib.sh | 4 +-- lib/plugin.lib.sh | 53 ++++++++++++++++++++++++++++++- lib/zaf.lib.sh | 53 +++++++++++++++++++++++++++++++ zaf | 80 ++++++++++++++++++++++++++++++++++++++++++----- 5 files changed, 200 insertions(+), 14 deletions(-) diff --git a/install.sh b/install.sh index 25b6bb0..cfb40da 100755 --- a/install.sh +++ b/install.sh @@ -111,7 +111,7 @@ zaf_set_zabbix_option() { local option="$2" local value="$3" if grep -q ^$option\= $cfgfile; then - zaf_dbg "Setting option $option in $cfgfile to $3." + zaf_dbg "Setting Zabbix agent option $option in $cfgfile to $3." sed -i "s/$option=\(.*\)/$option=$value/" $cfgfile else zaf_move_zabbix_option "$1" "$2" "$3" @@ -179,11 +179,23 @@ zaf_configure_agent() { local value local options local changes + local aparams 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 + if [ -n "$ZAF_ZBXSRV_HOST" ]; then + aparms="Z_Server=$ZAF_ZBXSRV_HOST,localhost Z_ServerActive=$ZAF_ZBXSRV_HOST" + else + aparms="" + fi + if [ -n "$ZAF_HOSTNAME" ]; then + aparms="$aparms Z_Hostname=$ZAF_HOSTNAME" + else + aparms="$aparms Z_HostnameItem=system.hostname Z_Hostname=" + zaf_dbg "Using hostname as Hostname item for Zabbix" + fi + for pair in $aparms "$@"; 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-) @@ -192,7 +204,7 @@ zaf_configure_agent() { else zaf_unset_zabbix_option "$ZAF_AGENT_CONFIG" "$option" fi - options="$options Z_$option=$value" + echo $options |grep -vq "Z_$option=" && options="$options Z_$option=$value" changes=1 done zaf_set_option ZAF_AGENT_OPTIONS "${options}" @@ -275,11 +287,14 @@ 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_ZBXSRV_HOST "Zabbix server hostname" "zabbix" "$INSTALL_MODE" + zaf_get_option ZAF_ZBXSRV_PORT "Zabbix server port" "10051" "$INSTALL_MODE" zaf_get_option ZAF_SERVER_CONFIG "Zabbix server config" "/etc/zabbix/zabbix_server.conf" "$INSTALL_MODE" [ -z "${ZAF_SERVER_CONFIGD}" ] && ! [ -d "${ZAF_SERVER_CONFIGD}" ] && [ -d "/etc/zabbix/zabbix_server.d" ] && ZAF_SERVER_CONFIGD="/etc/zabbix/zabbix_server.d" zaf_get_option ZAF_SERVER_CONFIGD "Zabbix server config.d" "/etc/zabbix/zabbix_server.conf.d/" "$INSTALL_MODE" zaf_get_option ZAF_SERVER_BIN "Zabbix server binary" "/usr/sbin/zabbix_server" "$INSTALL_MODE" + zaf_get_option ZAF_HOSTNAME "Hostname of this machine" "" "$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" @@ -320,6 +335,9 @@ zaf_configure(){ zaf_set_option ZAF_FILES_GID "$ZAF_FILES_GID" zaf_set_option ZAF_FILES_UMASK "$ZAF_FILES_UMASK" zaf_set_option ZAF_AGENT_RESTART "$ZAF_AGENT_RESTART" + zaf_set_option ZAF_ZBXSRV_HOST "$ZAF_ZBXSRV_HOST" + zaf_set_option ZAF_ZBXSRV_PORT "$ZAF_ZBXSRV_PORT" + zaf_set_option ZAF_HOSTNAME "$ZAF_HOSTNAME" if [ -x "$ZAF_SERVER_BIN" ]; then zaf_set_option ZAF_SERVER_CONFIG "$ZAF_SERVER_CONFIG" zaf_set_option ZAF_SERVER_CONFIGD "$ZAF_SERVER_CONFIGD" diff --git a/lib/ctrl.lib.sh b/lib/ctrl.lib.sh index b64bbc3..4ab0a25 100644 --- a/lib/ctrl.lib.sh +++ b/lib/ctrl.lib.sh @@ -195,7 +195,7 @@ zaf_ctrl_cron() { 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 +# Install files defined to be installed in control to plugin directory # $1 pluginurl # $2 control # $3 plugindir @@ -209,7 +209,7 @@ zaf_ctrl_install() { pdir="$3" (set -e - binaries=$(zaf_ctrl_get_global_option $2 "Install-bin") + binaries=$(zaf_ctrl_get_global_option $2 "Install-bin")" "$(zaf_ctrl_get_global_option $2 "Install-cmd") for b in $binaries; do zaf_fetch_url "$1/$b" >"${ZAF_TMP_DIR}/$b" zaf_install_bin "${ZAF_TMP_DIR}/$b" "$pdir" diff --git a/lib/plugin.lib.sh b/lib/plugin.lib.sh index 3f6ac7c..a419b38 100644 --- a/lib/plugin.lib.sh +++ b/lib/plugin.lib.sh @@ -223,7 +223,7 @@ zaf_is_item() { local item plugin=$(echo $1|cut -d '.' -f 1) - item=$(echo $1|cut -d '.' -f 2) + item=$(echo $1|cut -d '.' -f 2- | cut -d '[' -f 1) [ -z "$plugin" ] || [ -z "$item" ] && return 1 zaf_is_plugin "$plugin" && zaf_list_plugin_items "$plugin" | grep -qE "\.(${item}\$|${item}\[)" } @@ -314,6 +314,48 @@ zaf_list_plugin_items() { echo } +zaf_list_plugin_commands() { + local plugindir + local commands + + if ! zaf_is_plugin "$1"; then + zaf_err "Missing plugin name or plugin $1 unknown. "; + fi + plugindir="${ZAF_PLUGINS_DIR}/$1" + commands=$(zaf_ctrl_get_global_option "${plugindir}/control.zaf" Install-cmd) + if [ -n "$commands" ]; then + echo $commands; + else + zaf_wrn "Plugin $1 has no commands." + fi +} + +# $1 plugin +# $2 cmd +# $3...$9 arguments +zaf_plugin_run_command() { + local plugin + local cmd + local args + + plugin=$1 + cmd=$2 + args="$3 $4 $5 $6 $7 $8 $9" + if ! zaf_is_plugin "$plugin"; then + zaf_err "Missing plugin name or plugin $olugin unknown. "; + fi + plugindir="${ZAF_PLUGINS_DIR}/$plugin" + commands=$(zaf_ctrl_get_global_option "${plugindir}/control.zaf" Install-cmd) + if echo $commands |grep -q $cmd; then + export PATH=$plugindir:$PATH + cd $plugindir + [ -f functions.sh ] && source functions.sh + exec $cmd $args; + else + zaf_err "Plugin $1 has no command $cmd" + fi +} + zaf_item_info() { local plugin local item @@ -375,6 +417,15 @@ zaf_test_item() { fi } +zaf_run_item() { + local item + item=$(echo $1| cut -d '[' -f 1) + params=$(echo $1| cut -d '[' -f 2- | tr ',' ' '| tr -d ']') + cmd=$(grep "^UserParameter=$item" $ZAF_AGENT_CONFIGD/zaf*.conf | cut -d ',' -f 2-) + echo $cmd >/tmp/a + sh /tmp/a $params +} + 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)" diff --git a/lib/zaf.lib.sh b/lib/zaf.lib.sh index a67f282..3eba19c 100644 --- a/lib/zaf.lib.sh +++ b/lib/zaf.lib.sh @@ -301,3 +301,56 @@ zaf_sudo() { fi } +# Get item name from plugin.item[parms] +zaf_get_plugin_name() { + echo $1|cut -d '.' -f 1 +} + +# Get item name from plugin.item[parms] +zaf_get_item_name() { + echo $1|cut -d '.' -f 2-|cut -d '[' -f 1 +} + +# Get item params from plugin.item[parms] +zaf_get_item_params() { + echo $1|cut -d '[' -f 2|cut -d ']' -f 1 +} + +# Convert Zabbix style parameters [param1,param2,..] into $1 $2 $3 +zaf_paramstosh() { + local parms + local IFS + parms=$(echo $*|cut -d '[' -f 2 | cut -d ']' -f 1| tr ',' ':') + IFS=:; for i in $parms; do + if [ -n "$i" ]; then + printf "$i " + else + printf "'' " + fi + done +} + +#Returns either actual hostname or configured one +zaf_hostname() { + if [ -z "$ZAF_HOSTNAME" ]; then + hostname + else + echo $ZAF_HOSTNAME + fi +} + +# Send active agent query (used for auto registration of host) +# $1 hostname +# $2 metadata +zaf_register() { + local query + local result + zaf_dbg "zaf_register $1 $2" + query="{\"host\": \"$1\", \"host_metadata\": \"$2\", \"request\": \"active checks\"}" + result="$(echo $query| nc -q1 $ZAF_ZBXSRV_HOST $ZAF_ZBXSRV_PORT | tail -c +14)" + if echo $result |grep -q failed; then + zaf_wrn $result + fi +} + + diff --git a/zaf b/zaf index 7ea8ad2..19cbc6b 100755 --- a/zaf +++ b/zaf @@ -25,6 +25,8 @@ ZAF_CFG_FILE="/etc/zaf.conf" [ -n "$secondstage" ] && exec $0 $params fi +export ZAF_BIN=$(realpath $0) + if [ -n "$ZAF_PROXY" ]; then export ALL_PROXY="$ZAF_PROXY" export http_proxy="$ZAF_PROXY" @@ -175,21 +177,35 @@ test) done done ;; -itemsh) +itemsh) shift if zaf_is_item "$1"; then - plugin=$(echo $1|cut -d '.' -f 1) - item=$(echo $1|cut -d '.' -f 2) - script=$(zaf_ctrl_generate_items_cfg "${ZAF_PLUGINS_DIR}/${plugin}/control.zaf" "${plugin}" "" "sh -i #"| grep "UserParameter=$1" | cut -d ',' -f 2-) - eval $script - exit + plugin=$(zaf_get_plugin_name "$1") + item=$(zaf_get_item_name "$1") + params=$(zaf_get_item_params "$1") + params2=$(zaf_paramstosh "[$params]") + script=$(zaf_ctrl_generate_items_cfg "${ZAF_PLUGINS_DIR}/${plugin}/control.zaf" "${plugin}" "" "sh -i #"| grep "UserParameter=$plugin.$item" | cut -d ',' -f 2-) + exec sh -c "$script" dummy $params2 + else + zaf_err "No such plugin/item $1" + fi + ;; +run) + shift + if zaf_is_item "$1"; then + plugin=$(zaf_get_plugin_name "$1") + item=$(zaf_get_item_name "$1") + params=$(zaf_get_item_params "$1") + params2=$(zaf_paramstosh "[$params]") + script=$(zaf_ctrl_generate_items_cfg "${ZAF_PLUGINS_DIR}/${plugin}/control.zaf" "${plugin}" | grep "UserParameter=$plugin.$item" | cut -d ',' -f 2-) + exec sh -c "$script" dummy $params2 else zaf_err "No such plugin/item $1" fi ;; get) shift - if echo $1|grep -q '\.'; then + if zaf_is_item "$1"; then zaf_get_item "$1" exit fi @@ -205,6 +221,39 @@ get) done done ;; +send) + shift + if zaf_is_item "$1"; then + plugin=$(zaf_get_plugin_name "$1") + item=$(zaf_get_item_name "$1") + zscmd="zabbix_sender -z '$ZAF_ZBXSRV_HOST' -p '$ZAF_ZBXSRV_PORT' -s '$(zaf_hostname)' -k '$plugin.$item' -o '$(zaf_run_item $1)'" + zaf_dbg $zscmd + eval $zscmd + exit + else + zaf_wrn "Waiting for data on stdin (host item value) per line" + zscmd="zabbix_sender -z '$ZAF_ZBXSRV_HOST' -p '$ZAF_ZBXSRV_PORT' -i -" + zaf_dbg $zscmd + eval $zscmd + exit + fi + ;; +register) + shift + if [ -z "$1" ]; then + hostname=$(zaf_hostname) + else + hostname="$1" + if [ -z "$2" ]; then + metadata="ZAF" + else + metadata="$2" + fi + + fi + zaf_register "$hostname" "$metadata" + exit; + ;; precache) shift for i in $*; do @@ -306,7 +355,8 @@ self-remove) echo echo "To continue, please do $0 self-remove force" fi - ;; + ;; + ###### API related commands api) zaf_zbxapi_login @@ -463,6 +513,14 @@ api) ;; *) + if zaf_is_plugin "$1"; then + if [ -z "$2" ]; then + zaf_list_plugin_commands "$1" + else + zaf_plugin_run_command "$@" + fi + exit + fi 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 "Plugin manipulation commands:" @@ -479,12 +537,18 @@ api) echo "Plugin diagnostic commands:" zaf_hlp "$0 test [plugin[.item]]" "To test [all] suported items by zabbix_agentd [for plugin]" zaf_hlp "$0 get [plugin[.item]]" "To test [all] suported items by zabbix_get [for plugin]" + zaf_hlp "$0 run [plugin[.item]]" "To test [all] suported items by directly runing command [for plugin]" zaf_hlp "$0 precache [plugin[.item]]" "To precache [all] suported items" zaf_hlp "$0 itemsh plugin.item" "To spawn interactive shell in item context (same as UserParameter)." echo echo "Zabbix API commands:" zaf_hlp "$0 api" "To zabbix API functions. See $0 api for more info." echo + echo "Zabbix trapper commands:" + zaf_hlp "$0 send plugin.item" "To send result of agent param directly to Zabbix server by zabbix_server." + echo "Zabbix agent registration:" + zaf_hlp "$0 register [hostname] [metadata]" "To register hostname on Zabbix server (autoregistration)." + echo echo "Agent config info commands:" zaf_hlp "$0 userparms" "See userparms generated from zaf on stdout" zaf_hlp "$0 agent-config [force]" "Reconfigure zabbix userparms in $ZAF_AGENT_CONFIGD"