#!/bin/bash
# vim: ts=4 sw=4 ai noet
# $Id: cache-os,v 1.18 2006/05/11 14:38:18 kir Exp $
#
# Copyright (C) 2003, 2004, 2005, 2006 by SWsoft. Licensed under GNU GPL.
#
# Creates/updates OS template cache.
#
# All scripts called by this script inherit the following environment variables:
#
# VZCTL
# VZCFG
#
# OS_NAME
# OS_VER
# OS_ARCH
# OS_SET
#
# TEMPLATE_DIR
#
# VEID
# VE_PRIVATE
# VE_ROOT
#
# In addition template scripts inherit the following functions:
#
# find_template_config_file
# get_vz_var
#

test -n "$DEBUG_EXEC" && set -x

TOOLDIR=/usr/share/vzpkg2

. ${TOOLDIR}/functions

export -f find_template_config_file
export -f read_vzpkg_conf
export -f get_vz_var

VZCTL="$VZCTL --quiet --skiplock"
export VZCTL VZCFG VZP_LOGFILE

export -f log log1 log2 log3 log4 log5

log4 Started $0 $*

### Functions

function usage()
{
	echo "Usage: $PROGNAME [-r | -f] <template>"
	exit 0
}

# Kills/umounts/destroys VE.
# Parameters:
#  $1 - VE ID
function cleanup()
{
	local vps=$1
	log4 "Called cleanup($vps)"

	log4 "Calling vzctl stop $vps"
	$VZCTL stop $vps --fast
	log4 "Calling vzctl umount $vps"
	$VZCTL umount $vps
	log4 "Calling vzctl destroy $vps"
	$VZCTL destroy $vps
	log4 "Calling rm -f $VECFGDIR/$vps.*"
	rm -f $VECFGDIR/$vps.*
	unlock_ve $vps
}

if test $# -lt 1; then
	log2 "Wrong number of parameters specified"
	usage
fi

REMOVE=''
FORCE=''
case $1 in
	-r | --remove)
		REMOVE=yes
		shift
		;;
	-f | --force)
		FORCE=yes
		shift
		;;
	-*)
		log2 "Unknown option: $1"
		usage
esac

TEMPLATE=`get_vz_var TEMPLATE`

OST=`ost2full $1` || abort "No such OS template: $1"
set $OST
OS_NAME=$1
OS_VER=$2
OS_SET=$3
OS_ARCH=$4
TEMPLATE_DIR=$5
check_ost_exists $OS_NAME $OS_VER $OS_SET $OS_ARCH || exit 1

OS_TEMPLATE="$OS_NAME-$OS_VER-$OS_ARCH-$OS_SET"

export OS_NAME OS_VER OS_ARCH OS_SET
export TEMPLATE_DIR

CACHE=$OS_TEMPLATE.tar.gz
CACHEDIR=`get_cache_dir`
PACKAGER=`get_packager` || exit $?

if test "$REMOVE" != ""; then
	log3 "Removing OS template cache for $OS_TEMPLATE template"
	log4 "Cache file name: $CACHEDIR/$CACHE"
	test -f "$CACHEDIR/$CACHE" || \
		log2 "Cache file $CACHEDIR/$CACHE is not found!"
	rm -f $CACHEDIR/$CACHE
	# If there is a symlink (for older vzctl) remove it as well
	test -L "$TEMPLATE/$CACHE" && rm -f $TEMPLATE/$CACHE
	exit 0
fi

VEID=`find_lock_nearest_veid 100000` || abort "Can't find free VE ID"
log4 "Using temporary VE $VEID"
VE_PRIVATE=`get_vz_var VE_PRIVATE`
VE_ROOT=`get_vz_var VE_ROOT`
export VEID VE_PRIVATE VE_ROOT

VECFG=$VECFGDIR/$VEID.conf
VECFGSAMPLE=$VECFGDIR/ve-vps.basic.conf-sample
# simple init - for initial VE startup, statically linked
case ${OS_ARCH} in
i?86|x86)		MYINIT=${TOOLDIR}/myinit.i386;;
amd64|x86_64)	MYINIT=${TOOLDIR}/myinit.x86_64;;
ia64)			MYINIT=${TOOLDIR}/myinit.ia64;;
*)				MYINIT=${TOOLDIR}/myinit.i386;;
esac

function terminate()
{
	log4 "Calling cleanup()"
	cleanup $VEID
}
trap terminate EXIT

set -u
cp -f $VECFGSAMPLE $VECFG || abort "Can't copy VE config"
echo "DISK_QUOTA=no" >> $VECFG
echo "OSTEMPLATE=$OS_TEMPLATE" >> $VECFG
mkdir -p $VE_ROOT $VE_PRIVATE || abort "Can't create VE dirs"
log4 Mounting VE private area
$VZCTL mount $VEID || abort "Can't mount VE $VEID"

test -f "$CACHEDIR/$CACHE" && log4 "File $CACHEDIR/$CACHE exists"

# Check if we are going to update cache
if test -f "$CACHEDIR/$CACHE" -a "x$FORCE" = "x"; then
	log3 "Updating cache for $OS_TEMPLATE OS template"
	OPERATION="update"
	log4 "Untarring $CACHEDIR/$CACHE"
	VE_PRVT=$VE_PRIVATE PRIVATE_TEMPLATE=$CACHEDIR/$CACHE $VZLIB_SCRIPTDIR/vps-create || \
		abort "Failed to create a VE based on cache $CACHE"
	# Check if updates are available
	script=$TOOLDIR/$PACKAGER-checkupdate
	test -x "$script" || \
		abort "Failed to find $script script"
	$script
	rc=$?
	if test $rc -eq 0; then
		log3 "No updates are available"
		exit 0
	elif test $rc -eq 1; then
		log3 "Updates may be available - proceeding with update"
	else
		abort "Command $script failed with $rc exit code"
	fi
else
	log3 "Creating cache for $OS_TEMPLATE OS template"
	OPERATION="install"
	# Fake init placed in order for VE to be able to start
	mkdir $VE_ROOT/sbin || abort "Can't create dir $VE_ROOT/sbin"
	cp -f $MYINIT $VE_ROOT/sbin/init || \
		abort "Unable to copy $MYINIT to VE root ($VE_ROOT)"
	mkdir $VE_ROOT/proc || abort "Can't create dir $VE_ROOT/proc"
fi

# Run setup-pre script
call_template_script $OPERATION-pre || \
	abort "Script $OPERATION-pre failed"

# Start VE now
log4 Starting VE
$VZCTL start $VEID || abort "Can't start VE $VEID"

script=$TOOLDIR/$PACKAGER-cache-$OPERATION
test -x "$script" || abort "Failed to find $script script"
$script || \
	abort "Script $script failed"

call_template_script $OPERATION-post || \
	abort "Script $OPERATION-post failed"

# Stop this VE
log4 Stopping VE
$VZCTL stop $VEID --fast
log4 vzctl exit code $?

# Umount VE
log4 Unmounting VE
$VZCTL umount $VEID
log4 vzctl exit code $?

# Create tarball
pushd $VE_PRIVATE > /dev/null
log3 "Packing cache file $CACHE ... "
mkdir -p $CACHEDIR
test -f "$CACHEDIR/$CACHE" && mv $CACHEDIR/$CACHE $CACHEDIR/$CACHE-old
tar --numeric-owner -zcf $CACHEDIR/$CACHE . || {
	rm $CACHEDIR/$CACHE
	test -f $CACHEDIR/$CACHE-old && mv $CACHEDIR/$CACHE-old $CACHEDIR/$CACHE
	abort "tar failed"
}

CACHESIZE=`ls -lh $CACHEDIR/$CACHE | awk '{print $5}'`

log3 "Cache file $CACHE [$CACHESIZE] created."
popd > /dev/null

log4 Destroying VE
$VZCTL destroy $VEID
log4 vzctl exit code $?
log4 rm -f $VECFGDIR/$VEID.*
rm -f $VECFGDIR/$VEID.*
unlock_ve $VEID
