Commit bad5ca1f authored by Nikos Skalkotos's avatar Nikos Skalkotos
Browse files

Mass cleanup and some bug fixing

 * Make all "local" variables lowercase.
 * Move HELPER_EXTRA_PKGS from snf-image-update-helper to common.sh
 * Protect all variables from spaces and other special chars
 * Remove extra X's from mktemp template names (only 6 are supported).
 * Make sure pipelines fail if any command (not only the rightmost)
   fails
parent c36351f5
......@@ -38,6 +38,12 @@ RESIZE2FS=resize2fs
CLEANUP=( )
add_cleanup() {
local cmd=""
for arg; do cmd+=$(printf "%q " "$arg"); done
CLEANUP+=("$cmd")
}
log_error() {
echo "ERROR: $@" | tee $RESULT >&2
exit 1
......
......@@ -32,31 +32,32 @@
. @commondir@/common.sh
set -e
set -o pipefail
# terminate helper vm when the script exits
CLEANUP+=("telinit 0")
add_cleanup telinit 0
if [ ! -b $FLOPPY_DEV ]; then
if [ ! -b "$FLOPPY_DEV" ]; then
log_error "Floppy device is not present!"
fi
floppy=$(mktemp -d --tmpdir floppy.XXXXXXXX)
CLEANUP+=("rmdir $floppy")
floppy=$(mktemp -d --tmpdir floppy.XXXXXX)
add_cleanup rmdir "$floppy"
mount $FLOPPY_DEV $floppy
CLEANUP+=("umount $floppy")
add_cleanup umount "$floppy"
if [ -f $floppy/rules ]; then
source $floppy/rules
if [ -f "$floppy/rules" ]; then
source "$floppy/rules"
else
log_error "Floppy does not contain \`rules\' file"
fi
# Image mount point...
target=$(mktemp -d --tmpdir target.XXXXXXXX)
CLEANUP+=("rmdir $target")
target=$(mktemp -d --tmpdir target.XXXXXX)
add_cleanup rmdir "$target"
export SNF_IMAGE_TARGET=$target
export SNF_IMAGE_TARGET="$target"
if [ ! -d "@tasksdir@" ]; then
log_error "snf-image/tasks directory is missing"
......@@ -69,7 +70,7 @@ fi
# If something goes wrong with the tasks, try to umount the target filesystem
# in case it is left mounted...
trap '{ umount $target; }' ERR
trap '{ umount "$target"; }' ERR
echo "Execute all snf-image tasks...."
$RUN_PARTS -v --exit-on-error "@tasksdir@"
......@@ -77,7 +78,7 @@ $RUN_PARTS -v --exit-on-error "@tasksdir@"
# Disable the trap. If code reaches here, the filesystem is unmounted.
trap - ERR
echo "SUCCESS" > $RESULT
echo "SUCCESS" > "$RESULT"
cleanup
trap - EXIT
......
......@@ -7,7 +7,7 @@
### END TAST INFO
set -e
. @commondir@/common.sh
. "@commondir@/common.sh"
if [ ! -b "$SNF_IMAGE_DEV" ]; then
log_error "Device file:\`${SNF_IMAGE_DEV}' is not a block device"
......@@ -18,7 +18,7 @@ if [ -z "$SNF_IMAGE_TYPE" ]; then
fi
if [ "$SNF_IMAGE_TYPE" = "extdump" ]; then
$RESIZE2FS $SNF_IMAGE_DEV
"$RESIZE2FS" "$SNF_IMAGE_DEV"
fi
exit 0
......
......@@ -7,7 +7,7 @@
### END TAST INFO
set -e
. @commondir@/common.sh
. "@commondir@/common.sh"
if [ ! -d "$SNF_IMAGE_TARGET" ]; then
log_error "Target dir:\`$SNF_IMAGE_TARGET' is missing"
......@@ -17,7 +17,7 @@ if [ ! -b "$SNF_IMAGE_DEV" ]; then
log_error "Device file:\`$SNF_IMAGE_DEV' is not a block device"
fi
mount $SNF_IMAGE_DEV $SNF_IMAGE_TARGET
mount "$SNF_IMAGE_DEV" "$SNF_IMAGE_TARGET"
exit 0
......
......@@ -8,7 +8,7 @@
### END TAST INFO
set -e
. @commondir@/common.sh
. "@commondir@/common.sh"
if [ ! -d "$SNF_IMAGE_TARGET" ]; then
log_error "Target dir: \`$SNF_IMAGE_TARGET' is missing"
......
......@@ -7,7 +7,7 @@
### END TAST INFO
set -e
. @commondir@/common.sh
. "@commondir@/common.sh"
if [ ! -d "$SNF_IMAGE_TARGET" ]; then
log_error "Target dir: \`$SNF_IMAGE_TARGET' is missing."
......@@ -19,8 +19,8 @@ if [ "$SNF_IMAGE_TYPE" = "extdump" ]; then
DSA_KEY="/etc/ssh/ssh_host_dsa_key"
for key in $HOST_KEY $RSA_KEY $DSA_KEY ; do
if [ -f "${SNF_IMAGE_TARGET}/${key}" ] ; then
rm -f ${SNF_IMAGE_TARGET}/${key}*
if [ -f "$SNF_IMAGE_TARGET/$key" ] ; then
rm -f "$SNF_IMAGE_TARGET"/$key*
fi
done
fi
......
......@@ -8,7 +8,7 @@
### END TAST INFO
set -e
. @commondir@/common.sh
. "@commondir@/common.sh"
if [ -z "$SNF_IMAGE_TARGET" ]; then
log_error "Target dir: \`$SNF_IMAGE_TARGET' is missing"
......@@ -18,8 +18,8 @@ if [ "$SNF_IMAGE_TYPE" != "ntfsdump" ]; then
exit 0
fi
if [ -f @commondir@/unattend.xml ]; then
cat @commondir@/unattend.xml > $SNF_IMAGE_TARGET/Unattend.xml
if [ -f "@commondir@/unattend.xml" ]; then
cat "@commondir@/unattend.xml" > "$SNF_IMAGE_TARGET/Unattend.xml"
else
log_error "File \`@commondir@/unattend.xml' is missing."
fi
......
......@@ -8,7 +8,7 @@
### END TAST INFO
set -e
. @commondir@/common.sh
. "@commondir@/common.sh"
if [ ! -d "$SNF_IMAGE_TARGET" ]; then
log_error "Target directory \`$SNF_IMAGE_TARGET' is missing"
......
......@@ -8,7 +8,7 @@
### END TAST INFO
set -e
. @commondir@/common.sh
. "@commondir@/common.sh"
if [ ! -d "$SNF_IMAGE_TARGET" ]; then
log_error "Target dir: \`$SNF_IMAGE_TARGET' is missing"
......@@ -21,7 +21,7 @@ if [ "$SNF_IMAGE_TYPE" = "extdump" ]; then
# we have to force a filesystem relabeling for SELinux after messing
# around with the filesystem in redhat derived OSs
echo "Enforce an automatic relabeling in the initial boot process..."
touch $SNF_IMAGE_TARGET/.autorelabel
touch "$SNF_IMAGE_TARGET/.autorelabel"
fi
fi
......
......@@ -8,50 +8,50 @@
### END TAST INFO
set -e
. @commondir@/common.sh
. "@commondir@/common.sh"
windows_hostname() {
local target=$1
local password=$2
local target="$1"
local password="$2"
local tmp_unattend=`mktemp` || exit 1
CLEANUP+=("rm $tmp_unattend")
add_cleanup rm "$tmp_unattend"
echo -n "Assigning new computer name..."
local namespace="urn:schemas-microsoft-com:unattend"
$XMLSTARLET ed -N x=$namespace -u "/x:unattend/x:settings/x:component/x:ComputerName" -v $password "$target/Unattend.xml" > $tmp_unattend
"$XMLSTARLET" ed -N x=$namespace -u "/x:unattend/x:settings/x:component/x:ComputerName" -v "$password" "$target/Unattend.xml" > "$tmp_unattend"
cat $tmp_unattend > "$target/Unattend.xml"
cat "$tmp_unattend" > "$target/Unattend.xml"
echo done
}
linux_hostname() {
local target=$1
local hostname=$2
local target="$1"
local hostname="$2"
local distro=$(get_base_distro $target)
local distro=$(get_base_distro "$target")
case "$distro" in
debian)
echo "$hostname" > $target/etc/hostname;;
echo "$hostname" > "$target/etc/hostname";;
redhat)
sed -ie "s/HOSTNAME=.*$/HOSTNAME=$hostname/g" $target/etc/sysconfig/network;;
sed -ie "s/HOSTNAME=.*$/HOSTNAME=$hostname/g" "$target/etc/sysconfig/network";;
slackware|suse)
#local domain=$(sed -e 's/^[^\.]*//g' < /etc/HOSTNAME)
# In slackware hostname and domain name are joined together. For now I
# will not retain the domain name.
echo $hostname > ${target}/etc/HOSTNAME;;
echo "$hostname" > "${target}/etc/HOSTNAME";;
gentoo)
sed -ie "s/\(\(HOSTNAME\)\|\(hostname\)\)=.*$/\1=\"$hostname\"/" $target/etc/conf.d/hostname;;
sed -ie "s/\(\(HOSTNAME\)\|\(hostname\)\)=.*$/\1=\"$hostname\"/" "$target/etc/conf.d/hostname";;
esac
# Some Linux distributions assign the hostname to 127.0.1.1 in order to be
# resolvable to an IP address. Lets replace this if found in /etc/hosts
sed -ie "s/^[[:blank:]]*127\.0\.1\.1[[:blank:]].\+$/127.0.1.1\t$hostname/" $target/etc/hosts
sed -ie "s/^[[:blank:]]*127\.0\.1\.1[[:blank:]].\+$/127.0.1.1\t$hostname/" "$target/etc/hosts"
}
if [ ! -d "$SNF_IMAGE_TARGET" ]; then
......@@ -63,9 +63,9 @@ if [ -z "$SNF_IMAGE_HOSTNAME" ]; then
fi
if [ "$SNF_IMAGE_TYPE" = "ntfsdump" ]; then
windows_hostname $SNF_IMAGE_TARGET $SNF_IMAGE_HOSTNAME
windows_hostname "$SNF_IMAGE_TARGET" "$SNF_IMAGE_HOSTNAME"
elif [ "$SNF_IMAGE_TYPE" = "extdump" ]; then
linux_hostname $SNF_IMAGE_TARGET $SNF_IMAGE_HOSTNAME
linux_hostname "$SNF_IMAGE_TARGET" "$SNF_IMAGE_HOSTNAME"
fi
cleanup
......
......@@ -8,31 +8,31 @@
### END TAST INFO
set -e
. @commondir@/common.sh
. "@commondir@/common.sh"
windows_password() {
local target=$1
local password=$2
local target="$1"
local password="$2"
local tmp_unattend=`mktemp` || exit 1
CLEANUP+=("rm $tmp_unattend")
local tmp_unattend="$(mktemp)"
add_cleanup rm "$tmp_unattend"
echo -n "Installing new admin password..."
local namespace="urn:schemas-microsoft-com:unattend"
$XMLSTARLET ed -N x=$namespace -u "/x:unattend/x:settings/x:component/x:UserAccounts/x:AdministratorPassword/x:Value" -v $password "$target/Unattend.xml" > $tmp_unattend
"$XMLSTARLET" ed -N x=$namespace -u "/x:unattend/x:settings/x:component/x:UserAccounts/x:AdministratorPassword/x:Value" -v "$password" "$target/Unattend.xml" > "$tmp_unattend"
cat $tmp_unattend > "$target/Unattend.xml"
cat "$tmp_unattend" > "$target/Unattend.xml"
echo done
}
linux_password() {
local target=$1
local password=$2
local target="$1"
local password="$2"
local hash=$(@scriptsdir@/snf-passtohash.py $password)
if [ ! -e ${target}/etc/shadow ]; then
local hash=$("@scriptsdir@/snf-passtohash.py" "$password")
if [ ! -e "$target/etc/shadow" ]; then
log_error "No /etc/shadow found!"
fi
......@@ -46,14 +46,14 @@ linux_password() {
fi
for i in $(seq 0 1 $((${#users[@]}-1))); do
local tmp_shadow=$(mktemp)
CLEANUP+=("rm $tmp_shadow")
local tmp_shadow="$(mktemp)"
add_cleanup rm "$tmp_shadow"
echo -n "Setting ${users[$i]} password..."
echo "${users[$i]}:$hash:15103:0:99999:7:::" > $tmp_shadow
grep -v "${users[$i]}" ${TARGET}/etc/shadow >> $tmp_shadow
cat $tmp_shadow > ${target}/etc/shadow
echo "${users[$i]}:$hash:15103:0:99999:7:::" > "$tmp_shadow"
grep -v "${users[$i]}" "$target/etc/shadow" >> "$tmp_shadow"
cat "$tmp_shadow" > "$target/etc/shadow"
echo "done"
done
}
......@@ -67,9 +67,9 @@ if [ -z "$SNF_IMAGE_PASSWORD" ]; then
fi
if [ "$SNF_IMAGE_TYPE" = "ntfsdump" ]; then
windows_password $SNF_IMAGE_TARGET $SNF_IMAGE_PASSWORD
windows_password "$SNF_IMAGE_TARGET" "$SNF_IMAGE_PASSWORD"
elif [ "$SNF_IMAGE_TYPE" = "extdump" ]; then
linux_password $SNF_IMAGE_TARGET $SNF_IMAGE_PASSWORD
linux_password "$SNF_IMAGE_TARGET" "$SNF_IMAGE_PASSWORD"
fi
echo "done"
......
......@@ -8,13 +8,13 @@
### END TAST INFO
set -e
. @commondir@/common.sh
. "@commondir@/common.sh"
if [ ! -d "$SNF_IMAGE_TARGET" ]; then
log_error "Target dir:\`$SNF_IMAGE_TARGET' is missing"
fi
umount $SNF_IMAGE_TARGET
umount "$SNF_IMAGE_TARGET"
cleanup
trap - EXIT
......
......@@ -40,6 +40,12 @@ progress_monitor_support="@progress_monitor_support@"
CLEANUP=( )
add_cleanup() {
local cmd=""
for arg; do cmd+=$(printf "%q " "$arg"); done
CLEANUP+=("$cmd")
}
log_error() {
echo "$@" >&2
}
......@@ -139,7 +145,7 @@ map_disk0() {
log_error "Cannot interpret kpartx output and get partition mapping"
exit 1
fi
$KPARTX -a -p- $blockdev > /dev/null
$KPARTX -a -p- "$blockdev" > /dev/null
filesystem_dev="/dev/mapper/${filesystem_dev_base/%-1/}"
if [ ! -b "/dev/mapper/$filesystem_dev_base" ]; then
log_error "Can't find kpartx mapped partition:" \
......@@ -150,7 +156,7 @@ map_disk0() {
}
unmap_disk0() {
$KPARTX -d -p- $1
$KPARTX -d -p- "$1"
}
format_disk0() {
......@@ -171,17 +177,17 @@ EOF
create_floppy() {
local img=$1
local target=$(mktemp -d) || exit 1
CLEANUP+=("rmdir $target")
local target=$(mktemp -d)
add_cleanup rmdir "$target"
dd bs=512 count=2880 if=/dev/zero of=$img
mkfs.ext2 -F $img > /dev/null
mount $img $target -o loop
dd bs=512 count=2880 if=/dev/zero of="$img"
mkfs.ext2 -F "$img" > /dev/null
mount "$img" "$target" -o loop
set | egrep ^snf_export_\\w+=|sed -e 's/^snf_export_/SNF_IMAGE_/' | \
while read line; do
echo "export $line" >> $target/rules
echo "export $line" >> "$target/rules"
done
umount $target
umount "$target"
}
# this one is only to be called by create
......@@ -275,9 +281,12 @@ fi
: ${HELPER_KERNEL:="@HELPER_KERNEL@"}
: ${HELPER_INITRD:="@HELPER_INITRD@"}
: ${HELPER_PKG:="@HELPER_DIR@/snf-image-helper.deb"}
: ${HELPER_SOFT_TIMEOUT=15}
: ${HELPER_HARD_TIMEOUT=5}
: ${HELPER_USER="nobody"}
: ${HELPER_SOFT_TIMEOUT:=15}
: ${HELPER_HARD_TIMEOUT:=5}
: ${HELPER_USER:="nobody"}
: ${HELPER_CACHE_FILE:="@HELPER_DIR@/cache.tar"}
: ${HELPER_EXTRA_PKGS:="linux-image-amd64,e2fsprogs,ntfs-3g,ntfsprogs,xmlstarlet,python"}
SCRIPT_NAME=$(basename $0)
......
......@@ -30,6 +30,7 @@
# policies, either expressed or implied, of GRNET S.A.
set -e
set -o pipefail
. common.sh
......@@ -37,37 +38,38 @@ ganeti_os_main
case "$IMAGE_TYPE" in
extdump)
IMAGE_FILE="${IMAGE_DIR}/${IMAGE_NAME}-${ARCH}.extdump";;
image_file="$IMAGE_DIR/$IMAGE_NAME-$ARCH.extdump";;
ntfsdump)
IMAGE_FILE="${IMAGE_DIR}/${IMAGE_NAME}-${ARCH}.ntfsdump";;
image_file="$IMAGE_DIR/$IMAGE_NAME-$ARCH.ntfsdump";;
*)
log_error "Unknown image type: \`$IMAGE_TYPE'.";
exit 1
esac
if [ ! -e "$IMAGE_FILE" ]; then
log_error "Image file \`$IMAGE_FILE' does not exit."
if [ ! -e "$image_file" ]; then
log_error "Image file \`$image_file' does not exit."
exit 1
fi
MONITOR="" #Empty if progress monitor support is disabled
monitor="" #Empty if progress monitor support is disabled
if [ "$progress_monitor_support" = "yes" ]; then
IMAGE_SIZE="$(stat -L -c %s ${IMAGE_FILE})"
MONITOR="$PROGRESS_MONITOR -i ${INSTANCE_NAME} -r ${IMAGE_SIZE}"
image_size="$(stat -L -c %s "$IMAGE_FILE")"
monitor="$(printf "%q" "$PROGRESS_MONITOR") \
-i $(printf "%q" "$INSTANCE_NAME") -r $image_size"
fi
# If the target device is not a real block device we'll first losetup it.
# This is needed for file disks.
if [ ! -b $blockdev ]; then
ORIGINAL_BLOCKDEV=$blockdev
blockdev=$($LOSETUP -sf $blockdev)
CLEANUP+=("$LOSETUP -d $blockdev")
if [ ! -b "$blockdev" ]; then
original_blockdev="$blockdev"
blockdev=$("$LOSETUP" -sf "$blockdev")
add_cleanup "$LOSETUP" -d "$blockdev"
fi
format_disk0 $blockdev ${IMAGE_TYPE}
format_disk0 "$blockdev" "$IMAGE_TYPE"
filesystem_dev=$(map_disk0 $blockdev)
CLEANUP+=("unmap_disk0 $blockdev")
filesystem_dev=$(map_disk0 "$blockdev")
add_cleanup unmap_disk0 "$blockdev"
root_dev="${filesystem_dev}-1"
......@@ -75,37 +77,37 @@ root_dev="${filesystem_dev}-1"
# Deploying an image file on a target block device is a streaming
# copy operation. Enable the direct I/O flag on the output fd to
# avoid polluting the host cache with useless data.
$MONITOR dd bs=4M if=$IMAGE_FILE of=$root_dev oflag=direct
$monitor dd bs=4M if="$IMAGE_FILE" of="$root_dev" oflag=direct
# Create a floppy image
floppy=$(mktemp --tmpdir floppy.XXXXXXXX)
CLEANUP+=("rm -f $floppy")
floppy=$(mktemp --tmpdir floppy.XXXXXX)
add_cleanup rm "$floppy"
snf_export_DEV=/dev/vda
snf_export_TYPE=${IMG_FORMAT}
snf_export_PASSWORD=${IMG_PASSWD}
snf_export_HOSTNAME=${instance}
snf_export_TYPE="$IMG_FORMAT"
snf_export_PASSWORD="$IMG_PASSWD"
snf_export_HOSTNAME="$instance"
if [ -n "$IMG_PERSONALITY" ]; then
snf_export_PERSONALITY=${IMG_PERSONALITY}
snf_export_PERSONALITY="$IMG_PERSONALITY"
fi
create_floppy $floppy
create_floppy "$floppy"
# Invoke the helper vm to do the dirty job...
result_file=$(mktemp --tmpdir result.XXXXXXXX)
CLEANUP+=("rm -f $result_file")
result_file=$(mktemp --tmpdir result.XXXXXX)
add_cleanup rm "$result_file"
image_file=$(mktemp --tmpdir helperXXXXXXXX.img)
CLEANUP+=("rm -f $image_file")
snapshot=$(mktemp --tmpdir helperXXXXXX.img)
add_cleanup rm "$snapshot"
$QEMU_IMG create -f qcow2 -b ${HELPER_IMG} $image_file
"$QEMU_IMG" create -f qcow2 -b "$HELPER_IMG" "$snapshot"
$TIMELIMIT -t $HELPER_SOFT_TIMEOUT -T $HELPER_HARD_TIMEOUT \
kvm -runas $HELPER_USER -drive file=${image_file} \
-drive file=$root_dev,format=raw,if=virtio,cache=none \
-boot c -serial stdio -serial file:$result_file -fda $floppy \
-vga none -nographic -parallel none -monitor null -nographic \
-kernel ${HELPER_KERNEL} -initrd ${HELPER_INITRD} \
"$TIMELIMIT" -t "$HELPER_SOFT_TIMEOUT" -T "$HELPER_HARD_TIMEOUT" \
kvm -runas "$HELPER_USER" -drive file="$snapshot" \
-drive file="$root_dev",format=raw,if=virtio,cache=none \
-boot c -serial stdio -serial file:"$result_file" \
-fda "$floppy" -vga none -nographic -parallel none -monitor null \
-kernel "$HELPER_KERNEL" -initrd "$HELPER_INITRD" \
-append "quiet ro root=/dev/sda1 console=ttyS0,9600n8" \
2>&1 | sed 's|^|HELPER: |g'
......@@ -117,7 +119,7 @@ if [ $? -ne 0 ]; then
fi
# Read the first line. This will remove \r and \n chars
result=$(sed 's|\r||g' $result_file | xargs echo)
result=$(sed 's|\r||g' "$result_file" | xargs echo)
if [ "x$result" != "xSUCCESS" ]; then
log_error "Helper VM returned error"
......@@ -125,7 +127,7 @@ if [ "x$result" != "xSUCCESS" ]; then
fi
# Install a new MBR
$INSTALL_MBR -p 1 -i n ${blockdev}
"$INSTALL_MBR" -p 1 -i n "$blockdev"
# Execute cleanups
cleanup
......
......@@ -43,6 +43,14 @@
# user the helper vm should run as is specifies by HELPER_USR variable.
# HELPER_USER="nobody"
# HELPER_CACHE_FILE: Cache file update-helper script uses to avoid running
# `debootstrap' all the time.
# HELPER_CACHE_FILE=$(HELPER_DIR)/cache.tar
# HELPER_EXTRA_PKGS: Extra packages that will need to be supplied to de supplied
# to debootstrap to make the resulting helper image workable
# HELPER_EXTRA_PKGS="linux-image-amd64,e2fsprogs,ntfs-3g,ntfsprogs,xmlstarlet,python"
# Paths for needed programs. Uncommend and change the variables below, if you
# don't want to use the default one.
# LOSETUP="losetup"
......
#!/bin/bash
set -e
set -o pipefail
. @osdir@/common.sh
CACHE_FILE="$HELPER_DIR/cache.tar"
ARCH=amd64
EXTRA_PKGS="linux-image-amd64,e2fsprogs,ntfs-3g,ntfsprogs,xmlstarlet,python"
if [ ! -e "$HELPER_PKG" ]; then
log_error "Helper package \`$HELPER_PKG' not found."
log_error "You need to provide this for the script to work"
exit 1
fi
cat >&1 <<EOF
This program will overwrite the following files:
\`$HELPER_DIR/initrd'
......@@ -33,56 +31,56 @@ done
rm -f "$HELPER_DIR/initrd" "$HELPER_DIR/kernel" "$HELPER_DIR/image"
echo -n "Allocating space for helper disk image..."
helper_img=$(mktemp $HELPER_DIR/image.XXXXXXXX)
helper_img=$(mktemp "$HELPER_DIR/image.XXXXXX")
dd if=/dev/zero of=$helper_img bs=1k count=400000 &> /dev/null
dd if=/dev/zero of="$helper_img" bs=1k count=400000 &> /dev/null
echo "done"
echo "Creating partitions..."
blockdev=$(losetup -sf $helper_img)
CLEANUP+=("losetup -d $blockdev")