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