summaryrefslogtreecommitdiffstats
path: root/lib/adei
diff options
context:
space:
mode:
Diffstat (limited to 'lib/adei')
-rw-r--r--lib/adei/adei.sh287
-rw-r--r--lib/adei/adei_error.sh74
-rw-r--r--lib/adei/adei_print.sh25
-rw-r--r--lib/adei/adei_version.sh51
4 files changed, 437 insertions, 0 deletions
diff --git a/lib/adei/adei.sh b/lib/adei/adei.sh
new file mode 100644
index 0000000..3a0aeb6
--- /dev/null
+++ b/lib/adei/adei.sh
@@ -0,0 +1,287 @@
+cd $(dirname $0)
+
+MAX_SOURCE_OFFSET=3600
+MAX_MASTER_OFFSET=300
+MAX_SLAVE_OFFSET=300
+
+adei_default_timeout=${default_timeout:-120}
+
+. lib/adei/adei_version.sh
+. lib/adei/adei_print.sh
+. lib/adei/adei_error.sh
+. lib/nagios/nagios.sh
+
+shopt -s nocasematch;
+
+# Auth with redirect (-L/--location-trusted) not working. Credentials are lost on hops.
+function adei_query {
+ local resp
+ local timeout=${3:-$adei_default_timeout}
+
+ local err=0
+ if [ "$2" == "ecode" ]; then
+ url="$1&mysql=master"
+# resp=$(curl --proxy "" -f -m "$timeout" "$url" 2>&1 | grep "returned error")
+ resp=$(curl --proxy "" --location-trusted -sf -m "$timeout" -w "%{http_code}" -o /dev/null "$url" 2>&1);
+ [ -z "$resp" -o "$resp" = "000" ] && resp="10" # error code 1
+ elif [ "$2" == "emsg" ]; then
+ url="$1&mysql=master"
+ resp=$(curl --proxy "" --location-trusted -f -m "$timeout" "$url" 2>&1 | grep -o "curl.*")
+ [ -z "$resp" ] && resp="No response from"
+ else
+ if [ "$2" == "slave" ]; then
+ url="$1&mysql=slave"
+ else
+ url="$1&mysql=master"
+ fi
+
+
+ resp=$(curl --proxy "" --location-trusted -sf -m "$timeout" "$url"); err=$?
+ if [ $err -ne 0 ]; then
+ resp=$(adei_query "$1" "ecode" "$timeout")
+ err=$(($(($resp / 10)) + $(($resp % 10))))
+
+ resp=$(adei_query "$1" "emsg" "$timeout")
+
+ [ -n "$debug" ] && echo "$(date) $timeout Failed $url" >> /tmp/adei.log
+ else
+ [ -n "$debug" ] && echo "$(date) $timeout OK $url" >> /tmp/adei.log
+ fi
+ fi
+
+ echo -n $resp
+ return $err
+}
+
+function adei_format_query {
+ local with_auth="${1:-1}"
+ local query="$2"
+ local timeout=${3:-$adei_default_timeout}
+ local source=${4:-"$adei_source"}
+ local url="${5:-$adei_url}"
+
+ auth=""
+ [ $with_auth -gt 0 ] && auth="$adei_auth"
+ if [[ "$query" =~ \? ]]; then
+ echo "http://${auth}${url}/${query}${source}"
+ else
+ echo "http://${auth}${url}/${query}?xxxxx${source}"
+ fi
+}
+
+function adei_simple_query {
+ local req=$(adei_format_query 1 "$@")
+ adei_query "$req" "master" "$timeout"; err=$?
+ return $err
+}
+
+function adei_text_query {
+ local out # Local on the same string breaks error reporting
+ out="$(adei_simple_query "$@")"; local err=$?
+
+ if [ $err -gt 0 -o -z "$out" ]; then
+# echo "Error sending ADEI request: $(adei_format_query 0 "$@")"
+ [ $err -eq 0 ] && local err=1
+ [ -n "$out" ] && echo -n "$out"
+ return $err
+ elif [[ "$out" =~ "Error:" ]]; then
+ echo -n "$out"
+ return 7
+ else
+ echo -n "$out"
+ return 0
+ fi
+}
+
+function adei_xml_query {
+ local out # Local on the same string breaks error reporting
+ out="$(adei_simple_query "$@")"; local err=$?
+
+ if [ $err -ne 0 -o -z "$out" ]; then
+# echo "Error sending ADEI request: $(adei_format_query 0 '$@')"
+ [ $err -eq 0 ] && err=1
+ [ -n "$out" ] && echo "$out"
+ return $err
+ fi
+
+ local xml="$(echo "$out" | xmllint --format - 2>/dev/null)"
+ if [ $err -ne 0 -o -z "$out" ]; then
+ echo "$out"
+ if [[ "$out" =~ "Error:" ]]; then
+ return 7
+ else
+ return 4
+ fi
+ fi
+
+ error=$(echo "$xml" | grep "<Error>")
+ if [ -n "$error" ]; then
+ echo $error | sed -e "s|</\?Error>||g"
+ return 7
+ fi
+
+ echo "$xml"
+ return $err
+}
+
+function adei_value_query {
+ local out # Local on the same string breaks error reporting
+ out="$(adei_xml_query "$@")"; local err=$?
+ [ $err -ne 0 ] && { echo "$out"; return $err; }
+
+ local values
+ values="$(echo "$out" | grep "Value")"; err=$?
+ [ $err -ne 0 ] && return 6
+
+ echo "$values"
+}
+
+
+function adei_get_databases {
+ local out
+ out="$(adei_xml_query "list.php?target=databases" "$@")"
+ [ $err -gt 0 ] && { echo -n "$out"; return $err; }
+ echo "$out" | grep "Value" | sed -e "s/^.*db_name=\"\([^\"]*\)\".*$/\\1/" | sed -e "s/ /::space::/"
+}
+
+function adei_query_version {
+ local version # Local on the same string breaks error reporting
+
+ version="$(adei_text_query "info.php?target=version&encoding=text" "$@")"; local err=$?
+ [ $err -gt 0 ] && { echo "$version"; return $err; }
+
+ adei_version="$version"
+
+ adei_revision=$(echo $adei_version | cut -d '-' -f 1)
+ if [ "$adei_revision" == "$adei_version" ]; then
+ adei_date=""
+ else
+ adei_date=$(echo $adei_version | cut -d '-' -f 2)
+ fi
+}
+
+function adei_resolve_id {
+ fn="$1"
+ id="$2"
+ host="$3"
+ setup="$4"
+
+ local var=$(cat "$fn" | grep "^$id" | awk '{ print $2 }')
+ [ -z "$var" -a -n "$host" ] && var=$(cat "$fn" | grep "^$host" | awk '{ print $2 }')
+ [ -z "$var" -a -n "$setup" ] && var=$(cat "$fn" | grep "^$setup" | awk '{ print $2 }')
+
+ [ -n "$debug" ] && echo "$(date) resolved ($var) from $fn (id=$id, host=$host, setup=$setup) pwd ($(pwd))" >> /tmp/resolv.log
+ echo "$var"
+}
+
+function adei_init_ {
+ local id="$1" && shift # Either URL or [setup]@[host]
+# local url="$1" && shift
+ local server="$1" && shift
+ local database="$1" && [[ ! "$server" =~ \&|= ]] && shift
+ adei_args=( "$@" )
+
+ [ -z "$id" ] && { echo "ADEI ID is not specified" && exit 8 ; }
+
+
+ local url
+ local host
+ local setup
+ if [[ $id =~ http.*:// ]]; then # url
+ url="$id"
+ host="$(echo ${url#http*://} | cut -d '/' -f 1)" # parse port, maybe
+
+ unset $setup
+ elif [[ $id =~ : ]]; then # [setup@]host
+ local seho
+ IFS='@' read -ra seho <<< "$id" && shift
+ host="${seho[1]:-${seho[0]}}" # parse port, for sure
+ setup="${seho[1]:+${seho[0]}}"
+
+ unset $url
+ else # [setup]@[host] or both, no port
+ local seho
+ IFS='@' read -ra seho <<< "$id" && shift # techincally we can try to resolve to decide which is which
+
+ host="${seho[1]:-${seho[0]}}" # This could be mixed up, but it is either not important, or correct, or misconfigured anyway
+ setup="${seho[1]:+${seho[0]}}" # Only error if only setup is provided. But we handle it in resolution code which agnostic and treats them as ids
+
+ url=$(adei_resolve_id "setup/adei.txt" "$id" "$host" "$setup")
+
+ if [ -n "$url" ]; then # Get URL, now we can determine host correctly and ignore the ids.
+ host="$(echo ${url#http*://} | cut -d '/' -f 1)"
+ unset $setup
+ else # only 'setup' is not allowed if URL is not configured, so it should be host (or error in configuration)
+ unset $url # so either we have both (correctly) or only host (correctly)
+ fi
+ fi
+
+ local hopo
+ IFS=':' read -ra hopo <<< "$host" && shift
+ host="${hopo[0]}" # only non fqdn if also url not set
+ port=":${hopo[1]:-80}"
+ [ $port = ":80" ] && port=""
+
+ local fqdn
+ if [ -z "$url" ]; then
+ url=$(adei_resolve_id "setup/adei.txt" "$id" "$host" "$setup")
+ if [ -n "$url" ]; then
+ fqdn="$(echo ${url#http*://} | cut -d '/' -f 1)"
+
+ IFS=':' read -ra hopo <<< "$fqdn" && shift
+ host="${hopo[0]}" # again fqdn
+ port=":${hopo[1]:-80}"
+ [ $port = ":80" ] && port=""
+ else
+ fqdn=$(resolve_fqdn "$host") # this may be not fqdn
+ [ -n "$fqdn" ] && host="$fqdn"
+ url="${host}${port}/adei"
+ fi
+ fi
+
+ # In some case we miss here "setup", but surely then the password is resolved host-based
+ adei_auth=$(adei_resolve_id "security/adei.txt" "$id" "$host" "$setup")
+ [ -n "$adei_auth" ] && adei_auth="$adei_auth@"
+
+ # Now check port
+ adei_online=$(scripts/ping.pl "$host" "$port")
+ [ $adei_online -ne 1 ] && return 2
+
+ # Now build ADEI url
+
+ adei_setup="$setup"
+ adei_host="$host"
+ adei_port="$port"
+ adei_url="${url#http*://}/services"
+
+
+ adei_query_version; local err=$?
+ [ $err -gt 0 ] && return $err
+
+
+ if [[ "$server" =~ \&|= ]]; then
+ adei_source="&$server"
+ else
+ adei_source=""
+ [ -n "$adei_setup" -a "$adei_setup" != "*" ] && adei_source+="&setup=$adei_setup"
+ [ -n "$server" -a "$server" != "-" ] && adei_source+="&db_server=$server"
+
+ if [ "$database" == "#1" ]; then
+ databases="$(adei_get_databases)"; err=$?
+ [ $err -gt 0 ] && { echo "Failed to query ADEI databases: $databases"; return $err; }
+ [ -z "$databases" ] && { echo "No databases reported by ADEI"; return 6; }
+ database=$(echo "$databases" | head -n 1)
+ fi
+
+ [ -n "$database" -a "$database" != "-" ] && adei_source+="&db_name=$database"
+ fi
+
+ return 0
+}
+
+function adei_init {
+ adei_init_ "$@"; local code=$?
+
+ adei_healthy=$(($code == 0))
+ adei_process_error "$code" "" "*" "$(adei_print_status "$0" $adei_online $adei_healthy)"
+}
diff --git a/lib/adei/adei_error.sh b/lib/adei/adei_error.sh
new file mode 100644
index 0000000..9de4795
--- /dev/null
+++ b/lib/adei/adei_error.sh
@@ -0,0 +1,74 @@
+# Error codes: 1 - unknown network, 2 - unreachable, 3 - timeout, 4 - invalid XML/JSON, 5 - parsing error, 6 - set is empty, 7 - service reported error, 8 - parameter error, 9 - unknown, 10-59 - HTTP errors
+# http code (xyz) is converted to error code (xz), e.g. 404 -> 44
+
+function adei_format_http_error {
+ err=$1
+ echo -n "$(($err / 10))0$(($err % 10))"
+}
+
+# Returns 1 if printing text is recommended
+function adei_print_error {
+ local ret=0
+ local code=${1:-0}
+ local text="$2"
+
+ local service="${3#\*}"
+ service="${service:-ADEI}"
+
+ local msg
+ if [ $code -ge 30 -a $code -lt 60 ]; then
+ msg="HTTP Error: $(adei_format_http_error $code)"
+ [ $code -eq 41 ] && msg+=" (Authentication Requested)"
+ [ $code -eq 43 ] && msg+=" (Access Denied)"
+ elif [ $code -ge 20 -a $code -lt 30 ]; then
+ msg="HTTP Status: $(adei_format_http_error $code)"
+ ret=1
+ elif [ $code -eq 1 ]; then
+ msg="Error communicating with $service"
+ ret=1
+ elif [ $code -eq 2 ]; then
+ msg="ADEI host ($adei_host:$adei_port) unreachable"
+ elif [ $code -eq 3 ]; then
+ msg="Timeout waiting for $service"
+ elif [ $code -eq 4 ]; then
+ msg="Non-XML response from $service"
+ ret=1
+ elif [ $code -eq 5 ]; then
+ msg="Error parsing response from $service"
+ ret=1
+ elif [ $code -eq 6 ]; then
+ msg="Empty response from $service"
+ ret=1
+ elif [ $code -eq 7 ]; then
+ rep="$(echo "$text" | head -n 1 | sed 's/Error:\?[[:space:]]\+//i')"
+ if [ ${#rep} -lt 40 ]; then
+ msg="$service Error: $rep"
+ else
+ msg="$service returned a error"
+ ret=1
+ fi
+ elif [ $code -eq 8 ]; then
+ msg="Invalid parameter"
+ else
+ msg="Unknown Error $code while accessing $service"
+ fi
+
+ echo -n "$msg"
+ return $ret
+}
+
+function adei_process_error {
+ local code=${1:-0}; shift
+ local text="$1"; shift
+ local service="$1"; shift
+ local status="${1:-0}"
+
+ if [ $code -ne 0 ]; then
+ local msg # local on the same line break error reporting
+ msg="$(adei_print_error $code "$text" "$service")"
+ [ $? -eq 1 ] && echo "$text"
+ echo "$status $msg"
+ exit
+ fi
+}
+
diff --git a/lib/adei/adei_print.sh b/lib/adei/adei_print.sh
new file mode 100644
index 0000000..aca7735
--- /dev/null
+++ b/lib/adei/adei_print.sh
@@ -0,0 +1,25 @@
+function adei_print_status {
+ cmd="$1"
+ online="$2"
+ healthy="$3"
+
+ if [[ "$cmd" =~ check_adei_ ]]; then
+ echo "$healthy"
+ else
+ echo "$online $healthy"
+ fi
+}
+
+function format_time {
+ offset=$1
+ if [ $offset -ge 86400 ]; then
+ echo "$((offset / 86400))d"
+ elif [ $offset -ge 3600 ]; then
+ echo "$((offset / 3600))h"
+ elif [ $offset -ge 60 ]; then
+ echo "$((offset / 60))m"
+ else
+ echo "${offset}s"
+ fi
+}
+
diff --git a/lib/adei/adei_version.sh b/lib/adei/adei_version.sh
new file mode 100644
index 0000000..b71b1e1
--- /dev/null
+++ b/lib/adei/adei_version.sh
@@ -0,0 +1,51 @@
+vercomp() {
+ if [[ $1 == $2 ]]
+ then
+ return 0
+ fi
+ local IFS=.
+ local i ver1=($1) ver2=($2)
+ # fill empty fields in ver1 with zeros
+ for ((i=${#ver1[@]}; i<${#ver2[@]}; i++))
+ do
+ ver1[i]=0
+ done
+ for ((i=0; i<${#ver1[@]}; i++))
+ do
+ if [[ -z ${ver2[i]} ]]
+ then
+ # fill empty fields in ver2 with zeros
+ ver2[i]=0
+ fi
+ if ((10#${ver1[i]} > 10#${ver2[i]}))
+ then
+ return 1
+ fi
+ if ((10#${ver1[i]} < 10#${ver2[i]}))
+ then
+ return 2
+ fi
+ done
+ return 0
+}
+
+adei_version_check() {
+ vercomp $adei_revision $1
+ res=$?
+ if [ $res -eq 1 ]; then
+ return 0
+ elif [ $res -eq 2 ]; then
+ return 1;
+ fi
+
+ if [ -z "$2" -o -z "$adei_date" ]; then
+ return 0
+ fi
+
+ if [ $adei_date -ge $2 ]; then
+ return 0
+ fi
+
+ return 1
+}
+