#!/bin/sh

export LANG="C"
export LC_ALL="C"

# Here you can define checking routines list for every mode
brief_list="
    get_sysinfo
    get_common_info
    get_common_logs
    get_ipconfig
    get_mounts_info
    get_last
    get_selinux_info
    get_pkglist
    get_components
    get_system_users
    get_system_services
    get_ai_log
    get_apache_info
    get_nginx_info
    get_cpserver_info
    get_php_info
    get_psa_conf
"
middle_list="
    $brief_list
    get_db_misc
    get_db_eventhandlers
    get_maillog
    get_mail_handlers_list
    get_vhost_conf
    get_php_conf
    get_pmm_info
    get_webmail_conf
"

full_list="
    $middle_list
    get_db_dumps
"

# common options
curdir="`dirname $0`"
tmp_d="/usr/local/psa/var"
infodir="$tmp_d/collect"
info_plesk="$infodir/plesk"
info_system="$infodir/system"
info_db="$infodir/db"

my_access="-uadmin -p`cat /etc/psa/.psa.shadow`"

# global options
pkgtype=''  # defined in get_sysinfo
os_descr='' # defined in get_sysinfo
root_d=''   # defined in get_sysinfo

# Common functions
# ---------------------------------------------------------------------------------------
help()
{
    echo "USAGE: $progname [--mode=[brief|middlefull]]"
    echo "       $progname [--mode=[brief|middlefull]]"
    echo "       $progname --help"
    echo ""
    echo "OPTIONS:"
    echo "     --mode  Set required verbosity level. See MODES section"
    echo "             to get an additional info."
    echo "     --help  Show this message"
    echo ""
    echo "MODES:"
    echo "     brief    Short basic info."
    echo "     middle   Detailed info about system and product."
    echo "     full     Includes detailed info, product logs and database dumps"
}

parse_options()
{
    local count="$#"

    progname="$0"

    for i in `seq $count`; do
        eval arg=\$$i
        param="`echo $arg | awk -F '=' '{print $1}' | sed -e 's|--||'`"
        val="`echo $arg | awk -F '=' '{print $2}'`"

        case $param in
            mode)
                eval $param="$val"
                ;;
            help)
                help && exit 0
                ;;
            *)
                echo "Command not found: '--$param'"
                help && exit 1
                ;;
        esac
    done
}

ok()
{
    echo "ok"
}

info()
{
    echo "$*"
}

try()
{
    echo -n "Trying to $*... "
}

fail()
{
    echo "failed"
}

die()
{
    echo "ERROR: $*.. exiting..."
    exit 1
}

is_function()
{
        local type_output="`type \"$1\" 2>/dev/null | head -n1 | awk '{print $NF}'`"
        test "X${type_output}" = "Xfunction"
}

cleanup()
{
    rm -rf $infodir >/dev/null 2>&1
    rm -f $tmp_d/collect.zip
}

db_do()
{
    local query="$*"

    echo "$query" | mysql -n -N $my_access psa
}

db_dump()
{
    local database="$1"
    local table="$2"

    my_opts="--skip-extended-insert --skip-quick --skip-lock-tables"
    mysqldump $my_access $my_opts $database $table
}

collect()
{
    local functions="$1"

    for func in $functions; do
        if is_function $func; then
            $func
            continue
        fi
        echo "Internal error: Unable to find a function '$func'. Skipping..."
    done
}

pack()
{
    try "pack gathered info"

    local zip_bin
    zip_bin="`which zip 2>/dev/null`"
    [ -z "$zip_bin" ] && die "ZIP archiver didn't find"

    cd $tmp_d
    find collect > $tmp_d/pack_list.txt
    $zip_bin -b . collect -xi `cat $tmp_d/pack_list.txt` > /dev/null 2>&1
    rm -f $tmp_d/pack_list.txt
    rm -rf $infodir

    ok
}

# Routines
# ---------------------------------------------------------------------------------------

get_sysinfo()
{
    try "collect system info"

    res="`/bin/uname -m`"
    [ "$res" = "amd64" -o "$res" = "x86_64" ] && arch="x86_64" || arch="i386"

    found_file=""
    for f in redhat-release SuSE-release lsb-release debian_version; do
            [ -f "/etc/$f" ] && found_file="$f" && break
    done

    case $found_file in
        redhat-release)
            pkgtype="rpm"
            os_descr="`cat /etc/$found_file` $arch"
            root_d="/usr/local/psa"
        ;;
        SuSE-release)
            pkgtype="rpm"
            os_descr="`cat /etc/$found_file | head -n 1` $arch"
            root_d="/usr/local/psa"
        ;;
        lsb-release)
            pkgtype="deb"
            os_descr="`awk -F '=' '/DISTRIB_DESCRIPTION/ {print $2}' < /etc/$found_file | tr -d '"'` $arch"
            root_d="/opt/psa"
        ;;
        debian_version)
            pkgtype="deb"
            os_descr="Debian `cat /etc/$found_file` $arch"
            root_d="/opt/psa"
        ;;
        *)
            fail
            die "Unsupported os has been detected"
        ;;
    esac

    ok
}

get_ipconfig()
{
    try "collect IP configuration"
    mkdir -p $info_system
    ifconfig > $info_system/ipconfig.txt 2>&1
    ok
}

get_mounts_info()
{
    try "get mountpoints and volumes info"
    mkdir -p $info_system
    mount > $info_system/mounts.txt
    echo "" >> $info_system/mounts.txt
    df -h >> $info_system/mounts.txt
    ok
}

get_last()
{
    try "get last events"
    mkdir -p $info_system
    last > $info_system/last.txt
    ok
}

get_db_misc()
{
    try "collect info from psa.misc database table"
    mkdir -p $info_db
    db_dump "psa" "misc" > $info_db/misc.sql
    ok
}

get_db_eventhandlers()
{
    try "collect info from psa.event_handlers"
    mkdir -p $info_db
    db_dump "psa" "event_handlers" > $info_db/event_handlers.sql
    ok
}

get_selinux_info()
{
    try "get selinux status"
    
    enforced="`getenforce 2>/dev/null`"

    [ "$pkgtype" != "rpm" -o -z "$enforced" ] \
        && info "not installed" \
        && return

    mkdir -p $info_system
    echo -e "SELinux mode:\n    $enforced" >  $info_system/selinux.txt

    ok
}

get_common_info()
{
    try "collect Plesk common info"

    [ ! -f "$root_d/version" ] && fail && return || info="`cat $root_d/version`"

    mufile="/root/.autoinstaller/microupdates.xml"
    if [ "$mufile" ]; then
        mustring="`awk '/patch / { \
            for (i=1; i <= NF; i++) { \
                if ($i ~ /version/ || $i ~ /installed-at/) { \
                    split($i, arr, "="); \
                    print arr[1]" "arr[2]; \
                } \
            }}' < $mufile | tr -d '"' | xargs echo -n`"
    fi

    up_hist="`db_do "select * from upgrade_history"`"

    domains="`db_do "select count(*) from domains"`"

    case $pkgtype in
        rpm) nginx_str="`head -1 /etc/sysconfig/nginx`" ;;
        deb) nginx_str="`head -1 /etc/default/nginx`" ;;
        *) die "Unsupported OS" ;;
    esac
    nginx_status="`echo $nginx_str | awk -F '=' '{print $2}' | tr -d '"'`"

    vz_env_id="`awk '/envID/ {print $2}' /proc/self/status`"
    if [ -z "$vz_env_id" -o "$vz_env_id" = "0" ]; then
        vz_status="Nope. Is not VZ."
        counters="Not found."
    else
        vz_status="Yep. Is VZ."
        counters="`cat /proc/user_beancounters`"
    fi

    mkdir -p $infodir
    out="$infodir/common_info.txt"

    echo "OS:" > $out
    echo "    $os_descr" >> $out
    echo "" >> $out

    echo "Is virtuozzo container?:" >> $out
    echo "    $vz_status" >> $out
    echo "" >> $out

    echo "Product:" >> $out
    echo "    $info" >> $out
    echo "" >> $out

    echo "Microupdate:" >> $out
    echo "    $mustring" >> $out
    echo "" >> $out

    echo "Upgrade history:" >> $out
    if [ -z "$up_hist" ]; then
        echo "    Clean installation." >> $out
    else
        IFS_OLD="$IFS"
        IFS=$'\n'
        for str in $up_hist; do
            echo "    $str" >> $out
        done
        IFS="$IFS_OLD"
    fi
    echo "" >> $out

    echo "Count of domains:" >> $out
    echo "    $domains" >> $out
    echo "" >> $out

    echo "Nginx enabled:" >> $out
    echo "    $nginx_status" >> $out
    echo "" >> $out

    echo "Collected info date:" >> $out
    echo "    `date +%s` (`date -u`)" >> $out
    echo "" >> $out

    echo "User been counters:" >> $out
    echo "    $counters" >> $out
    echo "" >> $out

    cp -f /etc/sw/keys/registry.xml $infodir/

    ok
}

get_common_logs()
{
    try "collect common system logs"
    dstdir="$info_system/var_log"
    mkdir -p $dstdir
    for entry in cron mail.info syslog maillog messages mysqld.log secure yum.log audit dmesg; do
        [ -e "/var/log/$entry" ] && cp -fR /var/log/$entry $dstdir/
    done
    ok
}

get_pkglist()
{
    try "get packages list"

    mkdir -p $info_system
    case $pkgtype in
        rpm)
                rpm -qa >$info_system/pkglist.txt 2>&1
        ;;
        deb)
                dpkg --list > $info_system/pkglist.txt 2>&1
        ;;
        *)
            die "Unknown packages type."
        ;;
    esac

    ok
}

get_components()
{
    try "get Plesk components list"
    mkdir -p $info_plesk
    $root_d/admin/sbin/packagemng --list > $info_plesk/components.txt 2>&1
    ok
}

get_system_users()
{
    try "get system users and groups"
    mkdir -p $info_system
    cp -f /etc/passwd $info_system/sysusers.txt
    cp -f /etc/group  $info_system/sysgroups.txt
    ok
}

get_system_services()
{
    try "get system active services list"
    mkdir -p $info_system
    case "$pkgtype" in
        rpm)
            chkconfig --list > $info_system/services.txt
        ;;
        deb)
        ;;
        *)
            die "Unknown packages type."
        ;;
    esac

    top -b -n 1 > $info_system/top.txt 2>&1
    ps auxwww > $info_system/ps.txt 2>&1
    ok
}

get_ai_log()
{
    try "get autoinstaller logs"
    mkdir -p $info_plesk
    cp /tmp/autoinstaller3.log $info_plesk/
    ok
}

get_mail_handlers_list()
{
    try "get mail handlers info"
    mkdir -p $info_plesk
    $root_d/admin/sbin/mail_handlers_control --list > $info_plesk/mhandlers.txt
    echo "" >> $info_plesk/mhandlers.txt
    $root_d/admin/sbin/mail_handlers_control --list --extent >> $info_plesk/mhandlers.txt
    ok
}

get_apache_info()
{
    try "collect customer's web server configuration"

    local cmd
    local out
    local subdir

    mkdir -p $info_plesk/apache
    out="$info_plesk/apache/common.txt"

    cmd="`which httpd 2>/dev/null`"
    [ -z "$cmd" ] && cmd="`which apache 2>/dev/null`"
    [ -z "$cmd" ] && cmd="`which apache2 2>/dev/null`"
    [ -z "$cmd" ] && echo "apache not found.. " && fail && return

    [ "$pkgtype" = "rpm" ] && cmd_bin="$cmd" || cmd_bin="apachectl"

    $cmd_bin -t >> $out 2>&1
    echo "" >> $out
    $cmd_bin -V >> $out 2>&1
    echo "" >> $out
    $cmd_bin -M >> $out 2>&1
    echo "" >> $out

    $cmd_bin -S > $info_plesk/apache/vhosts.txt 2>&1

    subdir="`basename $cmd`"

    cp -fR /var/log/$subdir $info_plesk/apache/logs
    cp -fR /etc/$subdir $info_plesk/apache/conf
    
    ok
}

get_nginx_info()
{
    try "collect nginx web server info"
    mkdir -p $info_plesk/nginx
    cp -fR /etc/nginx/* $info_plesk/nginx/
    ok
}

get_cpserver_info()
{
    try "collect cp-server info"
    dstdir="$info_plesk/cp-server"

    mkdir -p $dstdir/etc/conf $dstdir/var_logs
    cp -fR /etc/sw-cp-server/* $dstdir/etc/
    cp -fR /var/log/sw-cp-server/* $dstdir/var_logs/

    mkdir -p $dstdir/admin
    cp -fR $root_d/admin/conf $dstdir/admin/
    cp -fR $root_d/admin/logs $dstdir/admin/
    ok
}

get_php_info()
{
    try "collect info about installed php"
    mkdir -p $info_plesk
    php -r "@phpinfo();" > $info_plesk/phpinfo.txt
    ok
}

get_psa_conf()
{
    try "get psa common configuration"
    mkdir -p $info_plesk/etc_psa
    cp -fR /etc/psa/* $info_plesk/etc_psa/
    ok
}

get_webmail_conf()
{
    try "get webmails configuration"
    mkdir -p $info_plesk/webmails
    cp -fR /etc/psa-webmail/* $info_plesk/webmails/
    ok
}

get_maillog()
{
    try "collect mail logs"
    mkdir -p $info_plesk
    cp -fR $root_d/var/log $info_plesk/maillog
    ok
}

get_vhost_conf()
{
    try "collect info from virtual domains"
    local vhosts_d
    vhosts_d="`awk '/^HTTPD_VHOSTS_D/ {print $2}' /etc/psa/psa.conf`"
    is_new_vhost="`which plesk 2>/dev/null`"
    count=0
    for domain in `db_do "select name from domains"`; do
        [ $count -eq 100 ] && echo -n "." && count=0
        [ -n "$is_new_vhost" ] \
            && srcdir="$vhosts_d/system/$domain" \
            || srcdir="$vhosts_d/$domain"
            
        mkdir -p $info_plesk/vhosts/$domain
        cp -fR $srcdir/logs $info_plesk/vhosts/$domain/ 2>/dev/null
        cp -fR $srcdir/conf $info_plesk/vhosts/$domain/ 2>/dev/null
        count=$(expr $count + 1)
    done
    echo -n " "
    ok
}

get_php_conf()
{
    try "collect php configs"
    mkdir -p $info_plesk/php
    find /etc -maxdepth 1 -name "*php*" -exec cp -fR {} $info_plesk/php/ \;
    ok
}

get_plesk_perms()
{
    try "collect plesk permissions"
    mkdir -p $info_plesk
    find $root_d -type d -exec ls -ld {} \; \
        | awk '{print $1" "$3" "$4" "$5" "$6" "$7" "$8" "$9" "$10" "$11}' \
        > $info_plesk/permissions.txt
    ok
}

get_pmm_info()
{
    try "collect backup/migration logs"

    local dstdir
    local srcdir

    dstdir="$info_plesk/PMM"
    mkdir -p $dstdir

    for dir in sessions rsessions msessions logs; do
        [ -d "$root_d/PMM/$dir" ] || continue
        cp -fR $root_d/PMM/$dir $dstdir/
    done

    ok
}

get_db_dumps()
{
    mkdir -p $info_db

    try "get psa database dump"
    db_dump psa > $info_db/psa.sql
    ok

    try "get apsc database dump"
    db_dump apsc > $info_db/apsc.sql
    ok
}

# --------------------------------------------------------------------------------------------

parse_options $*

[ -z "$mode" ] && mode="middle"

case $mode in
    brief)
        cleanup
        collect "$brief_list"
        ;;
    middle)
        cleanup
        collect "$middle_list"
        ;;
    full)
        cleanup
        collect "$full_list"
        ;;
    *)
        help && exit 1
        ;;
esac

pack
