|  | #!/bin/sh | 
|  | #  Copyright (C) 2011-2012, 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="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 | --list | 
|  | Options: | 
|  | --no-gpg-check	Do not check GPG signatures | 
|  | --no-update		Do not try to update existing templates | 
|  | --config		Output current configuration | 
|  | --list		Output list of templates available for download | 
|  | --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@/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 | 
|  | } | 
|  |  | 
|  | # 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() | 
|  | { | 
|  | 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 | 
|  | } | 
|  |  | 
|  | # 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 | 
|  | ;; | 
|  | --list) | 
|  | list | 
|  | 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 |