#!/bin/sh

# srowe@coraid.com
# robin@coraid.com
# nate@coraid.com

VERSION=1338578127
MODE=file
EXTENDED=0
GRABMSGS=0

now=$(date +%s)

tmpdir=/tmp/coraid-$(hostname)-${now}
outfile=/tmp/coraid-$(hostname)-${now}.txt


while getopts ehmtv flag
do
    case $flag in
        e)
            EXTENDED=1
            echo "Please be patient. Extended diagnostics may take several minutes to collect."
            ;;
        h)
            echo Usage:
            echo -e "${0} [-h] | [-e] [-m] [-t]"
            echo -e "\t-h : show this help and exit"
            echo -e "\t-e : capture extended diagnostics"
            echo -e "\t-m : capture a copy of OS's messages file"
            echo -e "\t-t : capture diagnostics in tarball format"
            exit 0
            ;;
        m)
            GRABMSGS=1
            ;;
        t)
            MODE=tar
            mkdir -p ${tmpdir}
            cd ${tmpdir}
            ;;
        v)
            echo Version: ${VERSION}
            exit 0
            ;;
    esac
done

if test "`whoami`" != "root"; then
    echo "$me: please run $me as root" 1>&2
    exit 1
fi

cleanup(){
    cd /tmp
    [ "${MODE}" = "tar" ] && rm -rf ${tmpdir}
}
trap "cleanup" EXIT
sepuku(){
    cleanup
    exit
}
trap "sepuku" INT

have(){
    unset -v have;
    type $1 > /dev/null 2>&1 && have='yes'
}

run(){
    run=$1
    label=$2
    printf .
    if [ "${MODE}" = "tar" ] ; then
        eval ${run} > ${label} 2>&1
    else
        echo          >> ${outfile}
        echo ========================================== >> ${outfile}
        echo ${label} >> ${outfile}
        echo ========================================== >> ${outfile}
        eval ${run}   >> ${outfile} 2>&1
    fi
}

grab(){
    if [ "${MODE}" = "tar" ] ; then
        cat ${1} > $(basename ${1})
    else
        echo >> ${outfile}
        echo ========================================== >> ${outfile}
        echo ${1} >> ${outfile}
        echo ========================================== >> ${outfile}
        cat  ${1} >> ${outfile}
    fi
}

columnt(){
    python -c 'import sys;a=[x.strip().split() for x in sys.stdin.readlines()];sys.exit(0) if len(a) == 0 else None;z=[[row[i] for row in a] for i in range(len(a[0]))];l=[len(max(x, key=len))+2 for x in z]; o=[[ v.ljust(l[i]) for i,v in enumerate(x)] for x in a]; print "\n".join(["".join(y) for y in o]);'
}

have column && unset -f columnt
have column && alias columnt='column -t'

driver(){
    printf .
    if [ "${MODE}" = "tar" ] ; then
        mkdir driver
        cd driver
    fi
    DRVLOC=uninstalled
    if [ -e /proc/scsi/ethdrv ] ; then
        DRVLOC= "/proc/scsi/ethdrv/ethdrv."
        loopdriver $DRVLOC
    fi
    if [ -e /proc/ethdrv ] ; then
        DRVLOC=/proc/ethdrv/
        loopdriver $DRVLOC
    fi
    if [ -e /dev/ethdrv ] ; then
        DRVLOC=/dev/ethdrv/
        loopdriver $DRVLOC
    fi
    if [ -e /proc/ethdrv.release ] ; then
        DRVLOC="/proc/ethdrv."
        loopdriver $DRVLOC
    fi
    if [ ! -e ${DRVLOC} -o "${DRVLOC}" = "uninstalled" ] ; then
        echo
        echo "HBA Driver either too old or not installed."
        echo
    fi
    [ "${MODE}" = "tar" ] && cd ${tmpdir}
}

loopdriver(){
    DRVLOC=${1}
    for f in ${DRVLOC}* ; do
        if [ "${f}" = ${DRVLOC}ifstats -o ${f} = ${DRVLOC}corestats -o ${f} = ${DRVLOC}config ] ; then
            grab ${f}
        else
            DHEADERS=''
            if [ "${f}" = ${DRVLOC}acbs ] ; then
                DHEADERS='ln 4 s.s cwrk mxwn cscsi caoe cmds rtx unre'
            fi
            if [ "${f}" = ${DRVLOC}ca ] ; then
                DHEADERS='ln s.s cwrk clamp mxwn ssthresh rttavg rttdelt'
            fi
            if [ "${MODE}" = tar ] ; then
                DDEST=$(basename ${f})-t
                cat ${f} > $(basename ${f})
            else
                echo ========================================== >> ${outfile}
                echo ${f} >> ${outfile}
                echo ========================================== >> ${outfile}
                DDEST=${outfile}
            fi
            if [ ! -z "${DHEADERS}" ] ; then
                (echo ${DHEADERS} ; cat ${f}) | columnt >> ${DDEST}
            else
                cat ${f} | columnt >> ${DDEST}
            fi
        fi
    done
}

#esx
esxversion(){
    run "vmware -v" vmware-v
}

esxmpath(){
    run "esxcfg-mpath -l" esxcfg-mpath-l
}

esxmodinfo(){
    run "esxcfg-module -i ethdrv" esxcfg-module-i-ethdrv
}

esxvolume(){
    run "esxcfg-volume -l" esxcfg-volume-l
}

esxscsidevs(){
    run "esxcfg-scsidevs -m" esxcfg-scsidevs-m
}

lsvms(){
    run 'vim-cmd vmsvc/getallvms' vim-cmd-vmsvc-getallvms
}
mapnaatoctd(){
    esxcfg-mpath -L | sort | awk '{print $1 " " $3}' |  awk " BEGIN { n=1; while (getline < \"${DRVLOC}devices\" > 0){ target[\$1] = n; aoe[n] = \$2; n++; } } { if (target[\$1]){ mtarget=\$1; mnaa=\$2; print mtarget \" \" aoe[target[mtarget]] \" \" mnaa }else{ ignore } }" | sort -k2 | columnt
}
wrapmap(){
    run mapnaatoctd "naa-map"
}
#end ESX
#solaris
whatsol(){
    run 'uname -a' uname-a
}
cscanpci(){
    run 'scanpci | grep -v ^$' scanpci
}

iostatXEN(){
    run 'iostat -xen' iostat-xen
}

cvmstat(){
    run 'vmstat -s' vmstat
}

cprtdiag(){
    run 'prtdiag -v' prtdiag
}

cfmdump(){
    run 'fmdump -meV -t 1d' fmdump
}

csig(){
    run 'machinesig' machinesig
}

csvcs(){
    run 'svcs -xv' svcs-xv
}

zpoolstatus(){
    run 'zpool status' zpool-status
}

zpoollistH(){
    run 'zpool list -H' zpool-list-H
}

zpoolgetall(){
    for zpool in $(zpool list -H |egrep -v 'rpool|syspool' |awk '{print $1}'); do
        run "zpool get all ${zpool} | sort -k2" zpool-get-all-${zpool}
        for zvol in $(zfs list -Hr |grep ^${zpool} |awk '{print $1}' | sort) ; do
            run "zfs get all ${zvol} | sort -k2" zfs-get-all-${zvol}
        done
        run "zpool history -i ${zpool}" zpool-history-i-${zpool}
    done
}

solmapdevices(){
    python -c 'import os;devs=[y.split()[0] for y in open("/dev/ethdrv/devices").readlines()];x=[y.split()[0] for y in os.popen("iostat -x").readlines()];xn=[y.split()[-1] for y in os.popen("iostat -xn")];c=dict(zip(x,xn)); print "\n".join(["%s = %s" % (y,c.get(y)) for y in devs])'
}

solnetwork(){
    run 'dladm show-phys |grep -v ^LINK |sort' dladm-show-phys
    run 'dladm show-link |grep -v ^LINK |sort' dladm-show-link
    run "for net in $(dladm show-link |sort |grep -v ^LINK |awk '{print $1}') ; do ifconfig \${net} ; done" ifconfig
    run 'dladm show-aggr' dladm-show-aggr
    run "for aggr in $(dladm show-aggr |sort |grep -v ^LINK |awk '{print $1}') ; do dladm show-aggr -L ${aggr} ; done" dladm-show-aggr-L
    run 'dladm show-vlan' dladm-show-vlan
    run 'ipmpstat -i' ipmpstat-i
    run 'netstat -nr' netstat-nr
    #kstat -c net
    [ -f /etc/hosts ] && grab /etc/hosts
    [ -f /etc/netmasks ] && grab /etc/netmasks
}
solcluster() {
    if [ -d /usr/cluster/bin ] ; then
        run 'cluster show' cluster-show
        run 'clrg status' clrg-status
        run 'clrs status' clrs-status
        run 'clq status'  clq-status
        run 'clinterconnect show -v' clinterconnect-show-v
        run 'solmapdevices' solmapdevices
        grab /etc/cluster/ccr/global/infrastructure
        #clrg show
        #clrs show
        #cldevice list -v
    fi
}
#end solaris
#begin linux
whatlinux(){
    run "uname -a" uname-a
    run 'grep . /etc/*release* /etc/*version* | sed 50q' version
}
linmodinfo(){
    run "find /sys/module/aoe -name version | xargs cat" module-name
}
linmounts(){
    grab /proc/mounts
}
linaoe(){
    have aoe-version && run aoe-version aoe-version
    have aoe-stat    && run aoe-stat aoe-stat
}
linmdstat(){
    grab /proc/mdstat
}
linpvs(){
    have pvs && run pvs pvs
}
linnetwork(){
    run 'ifconfig -a' ifconfig-a
    linethtool
}
linfree(){
    run free free
}
lindmesg(){
    run 'dmesg | tail -n 100' dmesg
}
linethtool(){
    for i in $(aoe-interfaces); do
        run "ethtool -S ${i};ethtool -i ${i}; ethtool -k ${i}" ethtool-${i}
    done
}
linsysctl(){
    run "sysctl -a |sort" sysctl-asort
}
aoeinterfaces(){
    have aoe-interfaces && run aoe-interfaces aoe-interfaces
}
aoeversion(){
    run aoe-version aoe-version
}
aoedebugfiles(){
    for f in /sys/block/etherd*/debug ; do
        name=$(echo ${f}|sed -e 's/.*\!//' -e 's!/!-!')
        if [ "${MODE}" = "tar" ] ; then
            cat ${1} > ${name}
        else
            echo >> ${outfile}
            echo ========================================== >> ${outfile}
            echo ${name} >> ${outfile}
            echo ========================================== >> ${outfile}
            cat  ${f} >> ${outfile}
        fi
    done
}
cdmidecode(){
    have dmidecode && run dmidecode dmidecode
}
#end linux

clspci(){
    run lspci lspci
}

lintop(){
    run 'top -b -n1' top
}

soltop(){
    # replace 'top' with 'prstat'
    # thus portable to nexenta
    #run 'top -b' top
    # the following 'cat' is required. thanks, solaris.
    run 'prstat -av -n 999999 0 1 |cat' top
}

cuptime(){
    run uptime uptime
}

grablog(){
    printf .
    if [ -e /var/log/vmkernel.log ] ; then
        grab /var/log/vmkernel.log
    fi
    if [ -f /var/log/messages ] ; then
        grab /var/log/messages
    fi
    if [ -f /var/adm/messages ] ; then
        grab /var/adm/messages
    fi
    if [ "${OS}" = "esx" ] ; then
        run "ls -l /var/log/" "ls-l-var-log"
    fi
}

package(){
    echo Complete.
    if [ "${MODE}" = "tar" ] ; then
        cd /tmp
        b=$(basename ${tmpdir})
        tar cf ${b}.tar ${b}
        echo Output file is /tmp/${b}.tar
    else
        echo Output file is ${outfile}
    fi
}

stamp(){
    run "date" date
    run "echo 'Coraid SOS Version: ${VERSION}' ; echo" coraid-version
}

esxdiags(){
    esxversion
    cuptime
    driver
    esxvolume
    esxmpath
    if [ ${EXTENDED} -eq 1 ] ; then
        wrapmap
        esxscsidevs
        lsvms
        clspci
        esxmodinfo
    fi
}

soldiags(){
    whatsol
    have machinesig && csig
    cuptime
    driver
    zpoollistH
    zpoolstatus
    zpoolgetall
    if [ ${EXTENDED} -eq 1 ] ; then
        cvmstat
        soltop
        iostatXEN
        csvcs
        solnetwork
        solcluster
        have scanpci && cscanpci
        have lspci && clspci
        cprtdiag
        cfmdump
    fi
}

lindiags(){
    whatlinux
    cuptime
    if [ -e /proc/ethdrv ] ; then
        driver
    fi
    aoeinterfaces
    linpvs
    linmodinfo
    linaoe
    linnetwork
    aoedebugfiles
    if [ ${EXTENDED} -eq 1 ] ; then
        linsysctl
    fi
    linmounts
    linmdstat
    if [ ${EXTENDED} -eq 1 ] ; then
        lintop
        cvmstat
        clspci
        cdmidecode
    fi
}

me=$(uname)

[ -e "/bin/vmware" -o -e "/usr/bin/vmware" ] && me="VMkernel"

stamp

case ${me} in
    VMkernel)
        OS=esx
        esxdiags
        ;;
    SunOS)
        OS=solaris
        PATH=/usr/cluster/bin:/usr/bin:/usr/sbin:/bin:/sbin
        soldiags
        ;;
    Linux)
        OS=linux
        lindiags
        ;;
esac

if [ ${GRABMSGS} -eq 1 ] ; then
    grablog
fi

package
