blob: ecb47a2a852a59f1d1e2dc55a4edad918a0d20c6 [file] [log] [blame] [raw]
#!/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-remote | --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