| #!/bin/sh | 
 | #  Copyright (C) 2011-2013, 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 @PKGCONFDIR@/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 | 
 |  | 
 | . @SCRIPTDIR@/vps-functions | 
 | . @PKGCONFDIR@/vz.conf | 
 | test -r @PKGCONFDIR@/download.conf && . @PKGCONFDIR@/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="no"} | 
 | : ${UPDATE_TEMPLATE="yes"} | 
 | : ${IGNORE_ERRORS="no"} | 
 | : ${QUIET="no"} | 
 | unset UPDATE_LIST | 
 | unset WGET_QUIET | 
 |  | 
 | vzcheckvar TEMPLATE | 
 | TCACHEDIR=$TEMPLATE/cache | 
 | SELF=$(basename $0) | 
 |  | 
 | usage() | 
 | { | 
 | 	cat << =EOF= 1>&2 | 
 | Usage: | 
 |   $SELF [option ...] <template> [<template> ...] | 
 |   $SELF [option ...] --update-all | 
 |   $SELF --list-remove | --list-local | --list-all | --list-orphans | 
 |   $SELF --config | --help | 
 | Options: | 
 |   --gpg-check		Check GPG signatures of downloaded files | 
 |   --no-gpg-check	Do not check GPG signatures | 
 |   --ignore-errors	Don't abort if a template can't be downloaded | 
 |   --update		Update templates even if they exist locally | 
 |   --no-update		Do not try to update existing templates | 
 |   --quiet		Be less talkative (shut up wget) | 
 |   --no-quiet		Be more talkative | 
 |   --update-all		Try to update all locally available templates | 
 |   --list-remote		Output list of templates available for download | 
 |   --list-local		Output list of templates available locally | 
 |   --list-all		Output combined list of templates | 
 |   --list-orphans	Output list of local templates NOT available remotely | 
 |   --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 @PKGCONFDIR@/download.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 | 
 | } | 
 |  | 
 | # There's no generic way to ask a web server about list of files | 
 | # in a directory, so we rely on having a .listing file next to templates. | 
 | list_remote() | 
 | { | 
 | 	local url | 
 | 	local cache=/tmp/$SELF-list | 
 |  | 
 | 	umask 0770 | 
 | 	# Cache the result for 1 minute | 
 | 	if test -z "$(find $cache -mmin -1 2>/dev/null)"; then | 
 | 		for url in $TEMPLATE_REPOS; do | 
 | 			wget -q -O - $url/.listing | 
 | 		done > $cache | 
 | 	fi | 
 |  | 
 | 	cat $cache | 
 | } | 
 |  | 
 | list_local() | 
 | { | 
 | 	ls ${TCACHEDIR}/*.tar    ${TCACHEDIR}/*.tar.gz  \ | 
 | 	   ${TCACHEDIR}/*.tar.xz ${TCACHEDIR}/*.tar.bz2	2>/dev/null | | 
 | 		sed -e "s#^${TCACHEDIR}/##" -e 's#\.tar\.*[gbxz2]*$##' | 
 | } | 
 |  | 
 | list_orphans() | 
 | { | 
 | 	local LOCAL=$(list_local) | 
 | 	local REMOTE=$(list_remote) | 
 | 	local t | 
 |  | 
 | 	for t in $LOCAL; do | 
 | 		if ! echo "$REMOTE" | grep -q "^$t$"; then | 
 | 			echo $t | 
 | 		fi | 
 | 	done | sort | uniq | 
 | } | 
 |  | 
 | # Parse arguments | 
 | while echo $1 | grep -q '^-'; do | 
 | 	case $1 in | 
 | 	   --gpg-check) | 
 | 		CHECK_TEMPLATE_SIG=yes | 
 | 		shift | 
 | 		;; | 
 | 	   --no-gpg-check) | 
 | 		CHECK_TEMPLATE_SIG=no | 
 | 		shift | 
 | 		;; | 
 | 	   --ignore-errors) | 
 | 		IGNORE_ERRORS=yes | 
 | 		shift | 
 | 		;; | 
 | 	   --update) | 
 | 		UPDATE_TEMPLATE=yes | 
 | 		shift | 
 | 		;; | 
 | 	   --no-update) | 
 | 		UPDATE_TEMPLATE=no | 
 | 		shift | 
 | 		;; | 
 | 	   --quiet) | 
 | 		QUIET=yes | 
 | 		shift | 
 | 		;; | 
 | 	   --no-quiet) | 
 | 		QUIET=no | 
 | 		shift | 
 | 		;; | 
 | 	   --update-all) | 
 | 		UPDATE_LIST=$(list_local) | 
 | 		UPDATE_TEMPLATE=yes | 
 | 		IGNORE_ERRORS=yes | 
 | 		shift | 
 | 		;; | 
 | 	   --config) | 
 | 		show_config | 
 | 		exit 0 | 
 | 		;; | 
 | 	   --list-all) | 
 | 		(list_local; list_remote) | sort | uniq | 
 | 		exit 0 | 
 | 		;; | 
 | 	   --list-remote) | 
 | 		list_remote | 
 | 		exit 0 | 
 | 		;; | 
 | 	   --list-local) | 
 | 		list_local | 
 | 		exit 0 | 
 | 		;; | 
 | 	   --list-orphans) | 
 | 		list_orphans | 
 | 		exit 0 | 
 | 		;; | 
 | 	   --help) | 
 | 		usage 0 | 
 | 		;; | 
 | 	   -*) | 
 | 		echo "$SELF ERROR: unknown option: $1" 1>&2 | 
 | 		usage 3 | 
 | 		;; | 
 | 	esac | 
 | done | 
 |  | 
 | if [ "$QUIET" = "yes" ]; then | 
 | 	WGET_QUIET="--quiet" | 
 | fi | 
 |  | 
 | if [ -n "$UPDATE_LIST" ]; then | 
 | 	if [ $# -gt 1 ]; then | 
 | 		echo "$SELF ERROR: too many arguments" 1>&2 | 
 | 		usage 3 | 
 | 	fi | 
 | else | 
 | 	if [ $# -lt 1 ]; then | 
 | 		echo "$SELF ERROR: no arguments" 1>&2 | 
 | 		usage 3 | 
 | 	fi | 
 | 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 $WGET_QUIET -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 | 
 |  | 
 | FAILED_TMPL="" | 
 | for TMPL in ${UPDATE_LIST:-$*}; do | 
 | 	download $TMPL | 
 | 	RET=$? | 
 | 	if [ $RET -ne 0 ]; then | 
 | 		if [ "$IGNORE_ERRORS" = "yes" ]; then | 
 | 			FAILED_TMPL="$FAILED_TMPL $TMPL" | 
 | 		else | 
 | 			exit $RET | 
 | 		fi | 
 | 	fi | 
 | done | 
 |  | 
 | if [ ! -z "$FAILED_TMPL" ]; then | 
 | 	echo WARNING: the following templates were not found remotely and can\'t be updated: | 
 | 	for TMPL in $FAILED_TMPL; do | 
 | 		echo " " $TMPL 1>&2 | 
 | 	done | 
 | fi |