#!/bin/bash
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
source "$(dirname "$0")/lib/ulib/ulib" || exit 1
urequire DEFAULTS

function display_help() {
    uecho "$scriptname: afficher des informations sur une machine virtuelle OpenVZ

USAGE
    $scriptname [options] [params...]d

OPTIONS
    -b  Afficher les informations de /proc/user_beancounters
    -f  N'afficher que les valeurs pour lesquelles failcnt > 0.
        Implique -b
    -z coef
        Afficher les instructions à utiliser pour augmenter de coef% les
        valeurs pour lesquelles failcnt > 0. Implique -f
    -c config|veid
        Afficher les informations du fichier de configuration plutôt que les
        beancounters"
}

default=1
bc=
show_failed=
coef=
conf=
parse_opts "${PRETTYOPTS[@]}" \
    --help '$exit_with display_help' \
    -b '$bc=1;default=' \
    -f '$show_failed=1;default=' \
    -z: '$set@ coef;default=' \
    -c: '$set@ conf;default=' \
    @ args -- "$@" && set -- "${args[@]}" || die "$args"

[ -n "$default" ] && bc=1
[ -n "$coef" ] && show_failed=1
[ -n "$show_failed" ] && bc=1

is_root || run_as_root ${bc:+-b} ${show_failed:+-f} ${coef:+-z "$coef"}${conf:+-c "$conf"} "$@"

# Faire la fonction de filtre
params=
count=0
for param in "$@"; do
    params="${params:+$params\\|}$param"
    count=$(($count + 1))
done
if [ $count -gt 1 ]; then
    params="\\($params\\)"
fi
function nocomments() {
    grep -v "^#" | grep -v "^$"
}
if [ -n "$show_failed" ]; then
    function show_failed_maybe() {
        awk '$6 > 0 { print }'
    }
else
    function show_failed_maybe() {
        cat
    }
fi
if [ -n "$params" ]; then
    function filter() {
        nocomments | grep -i "$params"
    }
else
    function filter() {
        nocomments
    }
fi

# Fonctions awk partagées
awk_functions=\
'function pad(s, size) {
    while (length(s) < size) {
        s = s " "
    }
    return s
}
function sizeOrInf(size, mult) {
    if (mult == null) mult = 1

    if (size == "2147483647") return "+INF"
    else return size * mult
}
function format_size(size, unit) {
    if (size == "+INF") return size

    if (size == 0) unit = null
    while (size > 1023) {
        if (unit == "G") break
        if (size > 10239) size = int(size / 1024)
        else size = int(size / 1024 * 10) / 10
        if (unit == null) unit = "k"
        else if (unit == "k") unit = "M"
        else if (unit == "M" ) unit = "G"
    }
    return size unit
}
function format(r, count) {
    r = tolower(r)
    if (r ~ /pages$/) return format_size(sizeOrInf(count, 4), "k")
    if (r ~ /size$/) return format_size(sizeOrInf(count))
    if (r == "diskspace") return format_size(sizeOrInf(count), "k")
    if (r ~ /buf$/) return format_size(sizeOrInf(count))
    return sizeOrInf(count)
}'

# Parser un fichier de config
if [ -n "$conf" ]; then
    function show_conf() { awk "$awk_functions"'
BEGIN {
    print "resource\tbarrier\tlimit"
}
{
    if ($0 ~ /[A-Z]*="[0-9]*:[0-9]*"/) {
        match($0, /^[A-Z]*/)
        r = substr($0, RSTART, RLENGTH);
        match($0, /"[0-9]*/)
        barrier = substr($0, RSTART + 1, RLENGTH - 1)
        match($0, /:[0-9]*/)
        limit = substr($0, RSTART + 1, RLENGTH - 1)

        print pad(r, 10) "\t" format(r, barrier) "\t" format(r, limit)
    }
}
'
    }

    vzdir=/etc/vz
    confdir="$vzdir/conf"
    namedir="$vzdir/names"
    if [ ! -f "$conf" ]; then
        if [ -f "$confdir/$conf" ]; then
            conf="$confdir/$conf"
        elif [ -f "$confdir/$conf.conf" ]; then
            conf="$confdir/$conf.conf"
        elif [ -f "$confdir/ve-$conf.conf-sample" ]; then
            conf="$confdir/ve-$conf.conf-sample"
        elif [ -f "$namedir/$conf" ]; then
            conf="$namedir/$conf"
        else
            die "Configuration non trouvée: $conf"
        fi
    fi

    cat "$conf" |
    filter |
    show_conf
fi

# Parser les bean counters
if [ -n "$bc" ]; then
    [ -f /proc/user_beancounters ] || die "Pas de fichier /proc/user_beancounters (OpenVZ est-il installé?)"

    function show_beancounters() { awk "$awk_functions"'
BEGIN {
    print "resource\theld\tmaxheld\tbarrier\tlimit\tfailcnt"
}
{
    r = $1
    held = $2
    maxheld = $3
    barrier = $4
    limit = $5
    failcnt = $6
    print pad(r, 10) "\t" format(r, held) "\t" format(r, maxheld) "\t" format(r, barrier) "\t" format(r, limit) "\t" failcnt
}
'
    }
    function show_ctls() { awkrun coef="$1" "$awk_functions"'
{
    r = $1
    barrier = sizeOrInf($4)
    limit = sizeOrInf($5)

    print "# Actuellement,   " r "=" barrier ":" limit ", soit " format(r, barrier) ":" format(r, limit)

    if (barrier != "+INF") barrier = int(barrier * (100 + coef) / 100)
    if (limit != "+INF" ) limit = int(limit * (100 + coef) / 100)
    print "# Nous voulons    " r "=" barrier ":" limit ", soit " format(r, barrier) ":" format(r, limit)

    print "vzctl $VEID set --" r "=" barrier ":" limit " --save"
}
'
    }

    ac_set_tmpfile tmpfile
    cat /proc/user_beancounters |
    sed '/^Version:/d; /[ ]*uid[ ]*resource[ ]*held[ ]*maxheld[ ]*barrier[ ]*limit[ ]*failcnt/d; s/[0-9]*://g' |
    filter |
    show_failed_maybe >"$tmpfile"

    show_beancounters <"$tmpfile"

    if [ -n "$coef" ]; then
        etitle -s "Augmenter les resources"
        enote "Pour augmenter les resources de $coef %, configuration sur l'hôte:"
        show_ctls "$coef" <"$tmpfile"
        eend
    fi
fi
