ansible-roles/kvm-host/files/kvmstats.sh
Alexis Ben Miloud--Josselin 058753bcfe
All checks were successful
gitea/ansible-roles/pipeline/head This commit looks good
kvmstats: Utiliser domstats pour récupérer infos
Remplacer les multiples commandes virsh par une seule commande
virsh domstats. La sortie est filtrée par une commande awk.

Certains hyperviseurs ne savent pas lister les informations d’un
volume RBD (Ceph) avec domblkinfo. Il semble que domstats
fonctionne mieux pour ça et peut donner toutes les informations
de toute façon.
2023-03-10 10:07:00 +01:00

224 lines
4.7 KiB
Bash
Executable file

#!/bin/sh
VERSION="21.10"
PROGNAME=$(basename "$0")
show_version() {
cat <<END
${PROGNAME} version ${VERSION}
Copyright 2018-2021 Evolix <info@evolix.fr>,
Alexis Ben Miloud--Josselin <abenmiloud@evolix.fr>,
Jérémy Lecour <jlecour@evolix.fr>
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 <<END
${PROGNAME} print stats about configured virtal servers
END
show_usage
}
show_usage() {
cat <<END
Usage: ${PROGNAME} --all
or ${PROGNAME} --output <human|html|csv>
or ${PROGNAME} --units <k|m|g>
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]+\.physical/ {
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 "<html><body>\n<table>"
}
{
printf "<tr>"
for(i = 1; i <= NF; i++)
printf "<td>%s</td>", $i
print "</tr>"
}
END {
print "</table>\n</body></html>"
}'
;;
'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