#!/bin/sh
#  Copyright (C) 2011, Parallels, Inc. All rights reserved.
#
#  This program is 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
#
# Download a precreated container tarball (a template cache).
# Usage: please see usage() below.
# There are some built-in defaults in this script, those can be changed
# by editing /etc/vz/download.conf
#
# Exit codes:
#  0 -- template downloaded successfully
#  1 -- download error
#  2 -- local template file already present, not updating
#  3 -- error in usage (no argument provided)
#  4 -- wget binary not found
#  5 -- GPG signature check failed
#
# If you want this script to do automatic GPG signature checking, you need
# to have gpg binary installed, and OpenVZ public key to be in your keyring.
# The latter can be achieved by running the following command as root:
#   gpg --search-keys security@openvz.org
# For more details, see gpg(1) man page and the following link:
#   http://wiki.openvz.org/Package_signatures#Importing_the_public_key


# Wget is required for this script to function
wget -V >/dev/null || exit 4

. /usr/lib64/vzctl/scripts/vps-functions
. /etc/vz/vz.conf
test -r /etc/vz/download.conf && . /etc/vz/download.conf

# Prefix to template cache repository URL
: ${TMPL_REPO_PREFIX="http://download.openvz.org/template/precreated"}
# What directories to use
: ${TEMPLATE_REPOS="${TMPL_REPO_PREFIX}"}
# Uncomment this to enable 'beta' (new) templates
#TEMPLATE_REPOS="${TEMPLATE_REPOS} ${TMPL_REPO_PREFIX}/beta/"
# Uncomment this to enable 'unsupported' (old) templates
#TEMPLATE_REPOS="${TEMPLATE_REPOS} ${TMPL_REPO_PREFIX}/unsupported"

: ${TMPL_SUFFIXES="tar.gz"}
: ${GPG_KEY="security@openvz.org"}
: ${CHECK_TEMPLATE_SIG="yes"}
: ${UPDATE_TEMPLATE="yes"}

vzcheckvar TEMPLATE
TCACHEDIR=$TEMPLATE/cache
SELF=$(basename $0)

usage()
{
	cat << -EOF- 1>&2
Usage:
  $SELF [option ...] template [template ...]
  $SELF --config | --help
Options:
  --no-gpg-check	Do not check GPG signatures
  --no-update		Do not try to update existing templates
  --config		Output current configuration
  --help		Print this help
Arguments:
  template		An OS template name (like centos-6-x86_64)
-EOF-
	exit $1
}

gpg_working()
{
	test "x$CHECK_TEMPLATE_SIG" != "xyes" && return 0

	# Check if gpg is installed
	if ! gpg --version >/dev/null; then
		CHECK_TEMPLATE_SIG=no
		echo "$SELF WARNING: gpg binary not found," \
			"signature check disabled" 1>&2
		return 1
	fi

	# ... and our key is there
	if ! gpg -k "$GPG_KEY" >/dev/null 2>&1; then
		CHECK_TEMPLATE_SIG=no
		cat << -EOF- 1>&2

$SELF WARNING: no public gpg key $GPG_KEY found,
disabling signature check. To import the public key, see
http://wiki.openvz.org/Package_signatures#Importing_the_public_key

-EOF-
		return 2
	fi
}

show_config()
{
	local url

	gpg_working

	cat << -EOF-
Current $SELF configuration is below. Defaults are built-in and can be
overwritten by setting an appropriate variables in /etc/vz/vz.conf

* Try to update template files (\$UPDATE_TEMPLATE): $UPDATE_TEMPLATE
* Check template signatures (\$CHECK_TEMPLATE_SIG): $CHECK_TEMPLATE_SIG
* GPG public key name to check (\$GPG_KEY):         $GPG_KEY
* List of template suffixes (\$TMPL_SUFFIXES):      $TMPL_SUFFIXES
* Prefix to template cache repository URL (\$TMPL_REPO_PREFIX):
  $TMPL_REPO_PREFIX
* List of template URLs to try (\$TEMPLATE_REPOS):
-EOF-

	for url in $TEMPLATE_REPOS; do
		echo "  ${url}"
	done
}

# Parse arguments
while echo $1 | grep -q '^-'; do
	case $1 in
	   --no-gpg-check)
		CHECK_TEMPLATE_SIG=no
		shift
		;;
	   --no-update)
		UPDATE_TEMPLATE=no
		shift
		;;
	   --config)
		show_config
		exit 0
		;;
	   --help)
		usage 0
		;;
	   -*)
		echo "$SELF ERROR: unknown option: $1" 1>&2
		usage 3
		;;
	esac
done

if [ $# -lt 1 ]; then
	echo "$SELF ERROR: no arguments" 1>&2
	usage 3
fi

check_sig()
{
	test "x${CHECK_TEMPLATE_SIG}" = "xyes" || return 0

	local sig=$1.asc
	local file=$2
	local ret

	echo "Checking template signature..."

	wget -q $sig || return 1
	sig=$(basename $sig)

	gpg --verify $sig $file
	ret=$?
	rm -f $sig

	if test "$ret" != "0"; then
		echo "$SELF ERROR: signature check failed!" 1>&2
		return 5
	else
		echo "Signature check passed."
		return 0
	fi
}

do_download()
{
	local src=$1
	local dst=$2
	local ret

	trap "rm -f ${dst}" INT TERM
	wget -P $(dirname ${dst}) -N ${src}
	ret=$?
	trap - INT TERM
	if test $ret -eq 0; then
		check_sig $src $dst
		return
	else
		echo "$SELF ERROR: failed to download ${src}!" 1>&2
		rm -f $dst
		return 1
	fi
}

download()
{
	local prefix suffix src dst
	local tmpl=$1

	for prefix in $TEMPLATE_REPOS; do
		for suffix in $TMPL_SUFFIXES; do
			src=${prefix}/${tmpl}.${suffix}
			dst=$TCACHEDIR/${tmpl}.${suffix}
			# Check for local copy
			if test -f $dst -a "$UPDATE_TEMPLATE" = "no"; then
				echo "$SELF ERROR: file $dst is present," \
					"not updating." 1>&2
				return 2
			fi
			# Check if the file is there
			if wget -q --spider -P $(dirname ${dst}) ${src}; then
				# Download it
				do_download "$src" "$dst"
				return
			fi
		done
	done
	echo "$SELF ERROR: template $tmpl not found!" 1>&2
	return 1
}

gpg_working

for TMPL in $*; do
	download $TMPL
	RET=$?
	test $RET -eq 0 || exit $RET
done
