Created
January 13, 2025 20:23
-
-
Save hcartiaux/ac9d89b3fe01cda52be9632f907a3d22 to your computer and use it in GitHub Desktop.
Prometheus exporter for PDUs power consumption
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash --posix | |
| # Time-stamp: <Thu 2024-09-26 11:28:19 hcartiaux> | |
| ################################################################################ | |
| # Collect power consumption values using the PDUs in CDC-S02-005 | |
| ################################################################################ | |
| #set -x | |
| COMMAND=$(basename "$0") | |
| SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" | |
| RACKS_LIST="A02 A04 A05 A07-A A07-B A09 A11 A12 A14 B02 B04 B05 B07 B09 B11 B12 B14 C02 C05 C07 C09 C11 C12 C14 D02 D04 D05 D07 D09 D11 D12 D14" | |
| RACK= | |
| ALL= | |
| OUTPUT= | |
| SERVER_ROOM_FILE=/dev/shm/pdu | |
| SERVER_PORT=9100 | |
| echo 0 > $SERVER_ROOM_FILE | |
| ####################### | |
| ### Functions ### | |
| ####################### | |
| error() { echo "*** ERROR *** $1"; } | |
| print_error_and_exit() { | |
| error "$1" | |
| exit 1 | |
| } | |
| print_help() { | |
| less <<EOF | |
| NAME | |
| $COMMAND -- Collect power consumption information in CDC-S02-005 | |
| SYNOPSIS | |
| $COMMAND [-h|--help] | |
| $COMMAND [-r RACK] | |
| $COMMAND [-a] | |
| DESCRIPTION | |
| $COMMAND takes care of collecting power consumption values of the racks in CDC-S02-005 server room | |
| OPTIONS | |
| -h --help | |
| Display a help screen and quit. | |
| -r | --rack RACK | |
| Collect the power consumption on the PDUs of the rack. | |
| RACK values can be: | |
| $RACKS_LIST | |
| -a | --all | |
| Sum the power consumption of all racks in the CDC-S02-005 server room | |
| -q | --quiet | |
| Quiet mode, print only the requested value in kW | |
| -c | --csv | |
| Output CSV, in the format 'rack|server room;Unix timestamp;Power consumption in kW' | |
| -e | --export | |
| Prometheus exporter output, query | |
| -s | --server | |
| Start a HTTP server, implies -e and -a | |
| -p | --port PORT | |
| Choose the server port. Default is 9100 | |
| AUTHOR | |
| Hyacinthe Cartiaux <Hyacinthe.Cartiaux@uni.lu> | |
| COPYRIGHT | |
| This is free software; see the source for copying conditions. There is | |
| NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR | |
| PURPOSE. | |
| EOF | |
| } | |
| print_rack() { | |
| RACK=$1 | |
| if [[ $RACK == "A02" ]] ; then | |
| IP="10.xxx.yyy.zzz 10.xxx.yyy.zzz" | |
| TYPE=AP8481 | |
| elif [[ $RACK == "A04" ]] ; then | |
| IP="10.xxx.yyy.zzz 10.xxx.yyy.zzz 10.xxx.yyy.zzz 10.xxx.yyy.zzz" | |
| TYPE=AP8481 | |
| elif [[ $RACK == "A05" ]] ; then | |
| IP="10.xxx.yyy.zzz 10.xxx.yyy.zzz" | |
| TYPE=AP8481 | |
| elif [[ $RACK == "A07-A" ]] ; then | |
| IP="10.xxx.yyy.zzz 10.xxx.yyy.zzz" | |
| TYPE=AP8481 | |
| elif [[ $RACK == "A07-B" ]] ; then | |
| IP="10.xxx.yyy.zzz 10.xxx.yyy.zzz" | |
| TYPE=PX3-1966-M11V2 | |
| elif [[ $RACK == "A09" ]] ; then | |
| IP="10.xxx.yyy.zzz 10.xxx.yyy.zzz" | |
| TYPE=AP8481 | |
| elif [[ $RACK == "A11" ]] ; then | |
| IP="10.xxx.yyy.zzz 10.xxx.yyy.zzz" | |
| TYPE=AP8481 | |
| elif [[ $RACK == "A12" ]] ; then | |
| IP="10.xxx.yyy.zzz 10.xxx.yyy.zzz" | |
| TYPE=AP8481 | |
| elif [[ $RACK == "A14" ]] ; then | |
| IP="10.xxx.yyy.zzz 10.xxx.yyy.zzz" | |
| TYPE=AP8481 | |
| elif [[ $RACK == "B02" ]] ; then | |
| IP="10.xxx.yyy.zzz 10.xxx.yyy.zzz" | |
| TYPE=AP8886 | |
| elif [[ $RACK == "B04" ]] ; then | |
| IP="10.xxx.yyy.zzz 10.xxx.yyy.zzz" | |
| TYPE=AP8886 | |
| elif [[ $RACK == "B05" ]] ; then | |
| IP="10.xxx.yyy.zzz 10.xxx.yyy.zzz" | |
| TYPE=AP8481 | |
| elif [[ $RACK == "B07" ]] ; then | |
| IP="10.xxx.yyy.zzz 10.xxx.yyy.zzz" | |
| TYPE=AP8481 | |
| elif [[ $RACK == "B09" ]] ; then | |
| IP="10.xxx.yyy.zzz 10.xxx.yyy.zzz" | |
| TYPE=AP8481 | |
| elif [[ $RACK == "B11" ]] ; then | |
| IP="10.xxx.yyy.zzz 10.xxx.yyy.zzz" | |
| TYPE=AP8481 | |
| elif [[ $RACK == "B12" ]] ; then | |
| IP="10.xxx.yyy.zzz 10.xxx.yyy.zzz" | |
| TYPE=AP8481 | |
| elif [[ $RACK == "B14" ]] ; then | |
| IP="10.xxx.yyy.zzz 10.xxx.yyy.zzz" | |
| TYPE=AP8481 | |
| elif [[ $RACK == "C02" ]] ; then | |
| IP="10.xxx.yyy.zzz 10.xxx.yyy.zzz" | |
| TYPE=AP8481 | |
| elif [[ $RACK == "C05" ]] ; then | |
| IP="10.xxx.yyy.zzz 10.xxx.yyy.zzz" | |
| TYPE=AP8481 | |
| elif [[ $RACK == "C07" ]] ; then | |
| IP="10.xxx.yyy.zzz 10.xxx.yyy.zzz 10.xxx.yyy.zzz 10.xxx.yyy.zzz" | |
| TYPE=AP8886 | |
| elif [[ $RACK == "C09" ]] ; then | |
| IP="10.xxx.yyy.zzz 10.xxx.yyy.zzz 10.xxx.yyy.zzz 10.xxx.yyy.zzz" | |
| TYPE=AP8886 | |
| elif [[ $RACK == "C11" ]] ; then | |
| IP="10.xxx.yyy.zzz 10.xxx.yyy.zzz" | |
| TYPE=AP8886 | |
| elif [[ $RACK == "C12" ]] ; then | |
| IP="10.xxx.yyy.zzz 10.xxx.yyy.zzz" | |
| TYPE=AP8886 | |
| elif [[ $RACK == "C14" ]] ; then | |
| IP="10.xxx.yyy.zzz 10.xxx.yyy.zzz" | |
| TYPE=AP8886 | |
| elif [[ $RACK == "D02" ]] ; then | |
| IP="10.xxx.yyy.zzz 10.xxx.yyy.zzz" | |
| TYPE=AP8481 | |
| elif [[ $RACK == "D04" ]] ; then | |
| IP="10.xxx.yyy.zzz 10.xxx.yyy.zzz" | |
| TYPE=AP8481 | |
| elif [[ $RACK == "D05" ]] ; then | |
| IP="10.xxx.yyy.zzz 10.xxx.yyy.zzz 10.xxx.yyy.zzz 10.xxx.yyy.zzz" | |
| TYPE=AP8886 | |
| elif [[ $RACK == "D07" ]] ; then | |
| IP="10.xxx.yyy.zzz 10.xxx.yyy.zzz 10.xxx.yyy.zzz 10.xxx.yyy.zzz" | |
| TYPE=AP8886 | |
| elif [[ $RACK == "D09" ]] ; then | |
| IP="10.xxx.yyy.zzz 10.xxx.yyy.zzz 10.xxx.yyy.zzz 10.xxx.yyy.zzz" | |
| TYPE=AP8886 | |
| elif [[ $RACK == "D11" ]] ; then | |
| IP="10.xxx.yyy.zzz 10.xxx.yyy.zzz 10.xxx.yyy.zzz 10.xxx.yyy.zzz" | |
| TYPE=AP8886 | |
| elif [[ $RACK == "D12" ]] ; then | |
| IP="10.xxx.yyy.zzz 10.xxx.yyy.zzz 10.xxx.yyy.zzz 10.xxx.yyy.zzz" | |
| TYPE=AP8886 | |
| elif [[ $RACK == "D14" ]] ; then | |
| IP="10.xxx.yyy.zzz 10.xxx.yyy.zzz 10.xxx.yyy.zzz 10.xxx.yyy.zzz" | |
| TYPE=AP8886 | |
| fi | |
| if [[ $TYPE == "AP8481" ]] ; then | |
| # OID AP8481 .1.3.6.1.4.1.318.1.1.26.9.4.3.1.6 | |
| # https://cric.grenoble.cnrs.fr/Administrateurs/Outils/MIBS/?oid=1.3.6.1.4.1.318.1.1.26.9.4.3.1.6 | |
| OID=.1.3.6.1.4.1.318.1.1.26.9.4.3.1.6 | |
| elif [[ $TYPE == "AP8886" ]] ; then | |
| # OID AP8886 .1.3.6.1.4.1.318.1.1.26.8.3.1.5 | |
| # https://www.apc.com/us/en/faqs/FA156179/ | |
| # https://cric.grenoble.cnrs.fr/Administrateurs/Outils/MIBS/?oid=.1.3.6.1.4.1.318.1.1.26.8.3.1.5 | |
| OID=.1.3.6.1.4.1.318.1.1.26.8.3.1.5 | |
| elif [[ $TYPE == "PX3-1966-M11V2" ]] ; then | |
| # OID .1.3.6.1.4.1.13742.6.5.2.4.1.4.[1-4].1 | |
| # https://www.raritan.com/product-selector/pdu-detail/PX3-1966-M11V2 | |
| # https://cdn.raritan.com/download/px3/version-3.6.50/MIB_Usage_3.6.50_48059.pdf | |
| OID=".1.3.6.1.4.1.13742.6.5.2.4.1.4.1.1.1.1 .1.3.6.1.4.1.13742.6.5.2.4.1.4.1.1.2.1 .1.3.6.1.4.1.13742.6.5.2.4.1.4.1.1.3.1 .1.3.6.1.4.1.13742.6.5.2.4.1.4.1.1.4.1" | |
| fi | |
| SUM=0 | |
| for i in $IP ; do | |
| for OID_i in $OID ; do | |
| AMP=$(snmpwalk -v1 -c public-HPC "$i" $OID_i 2>/dev/null | grep -o -e '[^:]*$' | xargs | sed 's/ /+/g' | bc) | |
| SUM=$((${AMP:=0} + $SUM)) | |
| done | |
| done | |
| if [[ $TYPE == "AP8481" ]] ; then | |
| KW=$(echo "scale=3;((${SUM}/10)*220)/1000" | bc) # Convert tenth of amps to kW | |
| elif [[ $TYPE == "AP8886" ]] ; then | |
| KW=$(echo "scale=3;((${SUM}/10)*220)/1000" | bc) # Convert tenth of amps to kW | |
| elif [[ $TYPE == "PX3-1966-M11V2" ]] ; then | |
| KW=$(echo "scale=3;((${SUM}/1000)*220)/1000" | bc) # Convert miliamps to kW | |
| fi | |
| if [[ $ALL != '' && $OUTPUT != 'export' ]]; then | |
| SERVER_ROOM_SUM=$(cat "$SERVER_ROOM_FILE") | |
| SERVER_ROOM_SUM=$(echo "$SERVER_ROOM_SUM + $KW" | bc) | |
| echo "$SERVER_ROOM_SUM" > "$SERVER_ROOM_FILE" | |
| fi | |
| [[ $OUTPUT == '' ]] && echo "Rack $RACK power draw: ${KW} kW" | |
| [[ $OUTPUT == 'quiet' && $ALL == '' ]] && echo "${KW}" | |
| [[ $OUTPUT == 'csv' ]] && echo "$RACK;$(date +%s);${KW}" | |
| [[ $OUTPUT == 'export' ]] && echo "cdc_s02_005_rack_power_watt{rack=\"${RACK}\"} $(echo "${KW}*1000/1" | bc)" | |
| } | |
| print_all() { | |
| [[ $OUTPUT == 'export' ]] && echo '# HELP cdc_s02_005_rack_power_watt APC rack global power in watt' | |
| [[ $OUTPUT == 'export' ]] && echo '# TYPE cdc_s02_005_rack_power_watt gauge' | |
| for r in $RACKS_LIST ; do | |
| print_rack "$r" & | |
| done | sort | |
| wait | |
| SERVER_ROOM_SUM=$(cat $SERVER_ROOM_FILE) | |
| [[ $OUTPUT == '' ]] && echo "CDC-S02-005 Total power draw: ${SERVER_ROOM_SUM} kW" | |
| [[ $OUTPUT == 'quiet' ]] && echo "${SERVER_ROOM_SUM}" | |
| [[ $OUTPUT == 'csv' ]] && echo "CDC-S02-005;$(date +%s);${SERVER_ROOM_SUM}" | |
| } | |
| # Check for options | |
| while [ $# -ge 1 ]; do | |
| case $1 in | |
| -h | --help) print_help; exit 0;; | |
| -r | --rack) RACK=$2; shift;; | |
| -q | --quiet) OUTPUT="quiet";; | |
| -c | --csv) OUTPUT="csv";; | |
| -a | --all) ALL=$1;; | |
| -e | --export) ALL=$1; OUTPUT="export";; | |
| -p | --port) SERVER_PORT=$2; shift;; | |
| -s | --server) SERVER=$1;; | |
| *) print_help; exit 1;; | |
| esac | |
| shift | |
| done | |
| ### Let's go | |
| if [[ $SERVER != '' ]] ; then | |
| while true ; do nc -l -p "$SERVER_PORT" -c "echo -e 'HTTP/1.1 200 OK\r\n\r\n' ; $SCRIPT_DIR/$COMMAND -e" ; done | |
| elif [[ $RACK != '' ]]; then | |
| [[ ! $RACKS_LIST =~ $RACK ]] && print_error_and_exit "$RACK does not exist in CDC-S02-005" | |
| print_rack "$RACK" | |
| elif [[ $ALL != '' ]] ; then | |
| print_all | |
| exit 0 | |
| else | |
| print_help | |
| exit 1 | |
| fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment