Skip to content

Instantly share code, notes, and snippets.

@hcartiaux
Created January 13, 2025 20:23
Show Gist options
  • Select an option

  • Save hcartiaux/ac9d89b3fe01cda52be9632f907a3d22 to your computer and use it in GitHub Desktop.

Select an option

Save hcartiaux/ac9d89b3fe01cda52be9632f907a3d22 to your computer and use it in GitHub Desktop.
Prometheus exporter for PDUs power consumption
#!/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