#!/bin/sh VERSION="21.10" PROGNAME=$(basename "$0") show_version() { cat <, Alexis Ben Miloud--Josselin , Jérémy Lecour and others. ${PROGNAME} comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions. See the GNU General Public Licence for details. END } show_help() { cat < or ${PROGNAME} --units END } error () { echo "$0": "$@" >&2 exit 1 } main() { for VM in $(virsh list --name --all | sed '/^$/d' | sort) do printf '%s ' "${VM}" virsh domstats "${VM}" | awk ' BEGIN { FS = "=" } /vcpu\.current/ { vcpu = $2 } /balloon\.current/ { mem = $2 } /balloon\.maximum/ { if (!mem) mem = $2 } /block\.[0-9]+\.capacity/ { disksize += $2 } /state\.state/ { if ($2 == 1) running = "yes" else running = "no" } END { print vcpu, mem / 1024 ^ 2, disksize / 1024 ^ 3, running }' done | { echo vm vcpu ram disk running awk '{ print } /yes$/ { vcpu += $2; ram += $3; disk += $4; running++ } END { print "TOTAL(running)", vcpu, ram, disk, running }' test "$SHOW_AVAIL" && { nproc awk '/^MemTotal:/ { print int($2 / '$((POW / 1024))' ) }' /proc/meminfo } | xargs -r printf 'AVAILABLE %s %s %s %s\n' } | case "$FMT" in 'human') column -t ;; 'html') awk ' BEGIN { print "\n" } { printf "" for(i = 1; i <= NF; i++) printf "", $i print "" } END { print "
%s
\n" }' ;; 'csv') tr ' ' ',' ;; esac } parse_units() { case "$1" in 'k') POW="$(echo '1024 ^ 1' | bc)" ;; 'm') POW="$(echo '1024 ^ 2' | bc)" ;; 'g') POW="$(echo '1024 ^ 3' | bc)" ;; *) printf 'ERROR: Unknown unit value: %s. Possible values: %s\n' "$1" "k, m, g" >&2 echo "" >&2 show_usage >&2 exit 1 ;; esac } parse_output() { case "$1" in 'csv'|'html'|'human') FMT="$1" ;; *) printf 'ERROR: Unknown output value : %s. Possible values: %s\n' "$1" "csv, html, human" >&2 echo "" >&2 show_usage >&2 exit 1 ;; esac } # Check dependencies for DEP in bc virsh do command -v "$DEP" > /dev/null || error "$DEP" 'command not found' done # default values POW="$(echo '1024 ^ 3' | bc)" FMT='human' # Parse options # based on https://gist.github.com/deshion/10d3cb5f88a21671e17a while :; do case $1 in -h|-\?|--help) show_help exit 0 ;; -V|--version) show_version exit 0 ;; -a|--all) SHOW_AVAIL='y' ;; -u|--units) # with value separated by space if [ -n "$2" ]; then parse_units "$2" shift else printf 'ERROR: "-u|--units" requires a non-empty option argument.\n' >&2 exit 1 fi ;; --units=?*) # with value speparated by = parse_units ${1#*=} ;; --units=) # without value printf 'ERROR: "--units" requires a non-empty option argument.\n' >&2 exit 1 ;; -o|--output) # with value separated by space if [ -n "$2" ]; then parse_output "$2" shift else printf 'ERROR: "-o|--output" requires a non-empty option argument.\n' >&2 exit 1 fi ;; --output=?*) # with value speparated by = parse_output ${1#*=} ;; --output=) # without value printf 'ERROR: "--output" requires a non-empty option argument.\n' >&2 exit 1 ;; --) # End of all options. shift break ;; -?*|[[:alnum:]]*) # ignore unknown options printf 'ERROR: Unknown option : %s\n' "$1" >&2 echo "" >&2 show_usage >&2 exit 1 ;; *) # Default case: If no more options then break out of the loop. break ;; esac shift done main