#!/usr/bin/bash
#
# Report collector launcher.
#
# Copyright (c) 2020-2021 Virtuozzo International GmbH. All rights reserved.
#
# This file is part of vzreport. It's free software; you can redistribute
# it and/or modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the License,
# or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
#
# Our contact details: Virtuozzo International GmbH, Vordergasse 59, 8200
# Schaffhausen, Switzerland.
#

# Parse options.
# We always dump report into file, but preserve -d option for backward compatibility
do_send=0
do_dump=1
do_help=0
do_full=0
REPORTFILE=
PROXY=
VE_ID=
VM_INFO_CMDS="domblkstat iothreadinfo schedinfo domjobinfo domfsinfo domhostname domtime dominfo 
              cpu-stats perf emulatorpin dommemstat vcpucount vcpuinfo vcpupin guestinfo domblkerror domstats"

CT_INFO_CMDS="schedinfo domjobinfo dominfo domstats"


TEMP=`getopt -o sdfh --long proxy:,full,send,dump,help,sendfile: -n '$0' -- "$@"`

if [ $? != 0 ]; then
	echo "Error parsing options..." >&2
	exit 1
fi

eval set -- "$TEMP"

while true; do
  case "$1" in
    -h | --help ) do_help=1; shift ;;
    -d | --dump ) do_dump=1; shift ;;
    -s | --send ) do_send=1; shift ;;
    -f | --full ) do_full=1; shift ;;
    --sendfile ) REPORTFILE="$2"; shift 2 ;;
    --proxy ) PROXY="$2"; shift 2 ;;
    '--') shift; break ;;
    * ) break ;;
  esac
done

if (( do_help )) ; then
	echo "Usage: $0 [-f|--full] [-s|--send|-d|--dump|--sendfile FILENAME|-h] [--proxy user[:password]@proxyhost[:port]] [ve_id]"
	echo "  ve_id               - create problem report for the given VE"
	echo "  -d, --dump          - dump problem report (default behavior)"
	echo "  -s, --send          - send problem report to the Vz server"
	echo "  -f, --full          - include more logs that would be omitted otherwise - such as rotated storage logs"
	echo "  --sendfile FILENAME - send preliminary collected report to the Vz server"
	echo "  --proxy [protocol://][user:password]@proxyhost[:port] "
	echo "                      - use proxy for report sending. Vzreport uses curl so you can also set the proxy "
	echo "                        in the curlrc file or via the https_proxy environment variable"
	echo "  -h, --help          - print this help and exit"
	exit 0
fi

for arg; do
	if [[ ! -z $VE_ID ]]; then
		echo "Can't generate report for multiple VEs at once"
		exit 1
	fi
	VE_ID=$arg
done

# If --sendfile is chosen, just send the file and exit
if [[ ! -z $REPORTFILE ]]; then
	if [[ ! -z $VE_ID ]]; then
		echo "Can't combine --sendfile with ve_id argument"
		exit 1
	fi
	if [[ ! -f $REPORTFILE ]]; then
		echo "Can't access $REPORTFILE"
		exit 1
	fi
	TMPREP_DIR=`dirname "${REPORTFILE}"`
	curl $PROXY -D- -s -F name=@${REPORTFILE} https://report.virtuozzo.com/post > ${TMPREP_DIR}/result.txt 2>&1
	if [[ $? == 0 ]]; then
		id=`grep status ${TMPREP_DIR}/result.txt | cut -d';' -f 2`
		echo "The problem report was successfully sent with id: $id"
		exit 0
	else
		echo "Failed to send the report":
		cat ${TMPREP_DIR}/result.txt
		exit 1
	fi
fi

if [ -z "$REPORT_DIR" ]; then
	TMPREP_DIR=`mktemp -d /tmp/vzreport.auto.XXXXXX`
	if [ $? -ne 0 ]; then
		exit 1
	fi

	DT=`date +%Y.%m.%d-%H.%M.%S.%N`
	REPORT_DIR="$TMPREP_DIR/PrlProblemReport-${DT}"
	mkdir $REPORT_DIR
	if [ $? -ne 0 ]; then
		exit 1;
	fi
else
	TMPREP_DIR=`dirname $REPORT_DIR`
fi

if [ ! -d $REPORT_DIR ]; then
	echo "$0: No output dir" >&2
	exit 2
fi
echo "Collecting report in $TMPREP_DIR/report.tar.gz"

function write_report()
{
	cd $REPORT_DIR/..
	echo "tar -zchf report.tar.gz `basename $REPORT_DIR`"
	tar -zchf report.tar.gz `basename $REPORT_DIR` 2>&1 |grep -vE 'Removing leading|No such file or directory'
	rm -rf $REPORT_DIR

	if [ -n "$TMPREP_DIR" ]; then
		echo "Report was collected in $TMPREP_DIR/report.tar.gz"
	fi
}

function alert()
{
	write_report
	# exit with zero because otherwise report will not be attached
	exit 0
}

# Emulate dispatcher behavior - 3 minutes timeout for vzreport collector
VZREPORT_COLLECTOR_TIMEOUT=180
mkdir $REPORT_DIR/vzreport

if (( do_full )) ; then
	export FULL_REPORT=1
fi

find /usr/libexec/vzreport -type f -executable | grep -v list_services | while read f; do
	if [ -f /etc/vz/vzreport.ignore ]; then
		grep -q -x $f /etc/vz/vzreport.ignore && continue
	fi

	if [[ ! -z $SKIP_LOG ]]; then
		skip=0
		for w in $SKIP_LOG; do
			grep -q "w"<<< "$a" && skip=1 && break
		done
		(( skip )) && continue
	fi

	if [[ $f =~ 'vzreport_collector' ]]; then
		"$f" "$REPORT_DIR/vzreport"
	else
		timeout ${VZREPORT_COLLECTOR_TIMEOUT}s "$f" "$REPORT_DIR"
	fi
done

# Populate some files directly from here
rpm -qa > $REPORT_DIR/InstalledSoftware.txt
# Historically, this is not xml despite of extension
uname -a > $REPORT_DIR/MoreHostInfo.xml
[ -f /etc/vz/vz.conf ] && cp /etc/vz/vz.conf $REPORT_DIR/VzConfig.txt
echo "======= ps auxf =======" > $REPORT_DIR/AllProcesses.txt
ps auxf >> $REPORT_DIR/AllProcesses.txt

if [[ ! -z $VE_ID ]]; then
	CONN=''
	vzlist $VE_ID >/dev/null 2>&1 && CONN='-c vzct:///system'
	virsh $CONN dominfo $VE_ID || exit 1
	virsh $CONN dumpxml $VE_ID > $REPORT_DIR/CurrentVmDomain.xml
	CMDS=$CT_INFO_CMDS
	[[ -z "$CONN" ]] && CMDS=$VM_INFO_CMDS
	for c in $CMDS; do
		virsh $CONN $c $VE_ID > $REPORT_DIR/CurrentVm_${c}.txt
	done
	[[ -z "$CONN" ]] && virsh $CONN screenshot --file $REPORT_DIR/screenshot.png $VE_ID || :
	echo '<snapshots>' >  $REPORT_DIR/VmSnapshots.xml
	virsh $CONN snapshot-list $VE_ID | grep -v 'Name\|---' | awk '{ print $1; }' | grep -v '^[[:space:]]*$' | while read s; do
		virsh $CONN snapshot-dumpxml $VE_ID "$s" >> $REPORT_DIR/VmSnapshots.xml
	done
	echo '<snapshots>' >> $REPORT_DIR/VmSnapshots.xml
fi

# Create archive
write_report

if (( do_send )) ; then
	curl $PROXY -D- -s -F name=@${TMPREP_DIR}/report.tar.gz https://report.virtuozzo.com/post > ${TMPREP_DIR}/result.txt 2>&1
	if [[ $? == 0 ]]; then
		id=`grep status ${TMPREP_DIR}/result.txt | cut -d';' -f 2`
		echo "The problem report was successfully sent with id: $id"
	else
		echo "Failed to send the report":
		cat ${TMPREP_DIR}/result.txt
	fi
fi
