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

Cleanup Xen code

Make it comply with the rest of the software. Some things are not
ready yet.
parent aa185eca
# Copyright (C) 2011 GRNET S.A.
# Copyright (C) 2011, 2012, 2013 GRNET S.A.
# Copyright (C) 2007, 2008, 2009 Google Inc.
#
# This program is free software; you can redistribute it and/or modify
......@@ -41,86 +41,88 @@ MSG_TYPE_TASK_END="TASK_END"
STDERR_LINE_SIZE=10
add_cleanup() {
local cmd=""
for arg; do cmd+=$(printf "%q " "$arg"); done
CLEANUP+=("$cmd")
}
# hypervisor param is passed in /proc/cmdline
case "$hypervisor" in
kvm)
FLOPPY_DEV=/dev/fd0
IMG_DEV=/dev/vda
RESULT=/dev/ttyS1
MONITOR=/dev/ttyS2
;;
xen-hvm|xen-pvm)
FLOPPY_DEV=/dev/xvdc1
IMG_DEV=/dev/xvdb
;;
esac
to_monitor() {
case $hypervisor in
kvm)
echo "HELPER_MONITOR_$@" > "$MONITOR"
;;
xen-pvm|xen-hvm)
echo "HELPER_MONITOR_$@" | socat STDIO INTERFACE:eth0
;;
esac
close_fd() {
local fd=$1
exec {fd}>&-
}
to_result() {
prepare_helper() {
local cmdline item key val hypervisor domid
case $hypervisor in
kvm)
echo "HELPER_RESULT_$@" > "$RESULT"
read -a cmdline < /proc/cmdline
for item in "${cmdline[@]}"; do
key=$(cut -d= -f1 <<< "$item")
if [ "$key" = "hypervisor" ]; then
val=$(cut -d= -f2 <<< "$item")
hypervisor="$val"
fi
done
case "$hypervisor" in
kvm)
FLOPPY_DEV=/dev/fd0
exec {RESULT_FD}> /dev/ttyS1
add_cleanup close_fd ${RESULT_FD}
exec {MONITOR_FD}> /dev/ttyS2
add_cleanup close_fd ${MONITOR_FD}
;;
xen-pvm|xen-hvm)
xen-hvm|xen-pvm)
mount -t xenfs xenfs /proc/xen
iptables -P OUTPUT DROP
ip6tables -P OUTPUT DROP
ip link set eth0 up
FLOPPY_DEV=/dev/xvdc
domid=$(xenstore-read domid)
xenstore-write /local/domain/0/helper/$domid "HELPER_RESULT_$@"
exec {RESULT_FD}> >(xargs -l1 xenstore-write /local/domain/0/snf-image-helper/$domid)
add_cleanup close_fd ${RESULT_FD}
exec {MONITOR_FD}> >(socat STDIN INTERFACE:eth0)
add_cleanup close_fd ${MONITOR_FD}
;;
*)
echo "ERROR: Unknown hypervisor: \`$hypervisor'" >&2
exit 1
;;
esac
}
add_cleanup() {
local cmd=""
for arg; do cmd+=$(printf "%q " "$arg"); done
CLEANUP+=("$cmd")
export RESULT_FD MONITOR_FD
}
log_error() {
ERRORS+=("$@")
echo "ERROR: $@" >&2
to_result "ERROR: $@"
echo "ERROR: $@" >&${MONITOR_FD}
exit 1
}
warn() {
echo "Warning: $@" >&2
to_monitor "WARNING: $@"
echo "WARNING: $@" >&${MONITOR_FD}
}
report_task_start() {
to_monitor "$MSG_TYPE_TASK_START:${PROGNAME:2}"
echo "$MSG_TYPE_TASK_START:${PROGNAME:2}" >&${MONITOR_FD}
}
report_task_end() {
to_monitor "$MSG_TYPE_TASK_END:${PROGNAME:2}"
echo "$MSG_TYPE_TASK_END:${PROGNAME:2}" >&${MONITOR_FD}
}
report_error() {
if [ ${#ERRORS[*]} -eq 0 ]; then
# No error message. Print stderr
lines="$(tail --lines=${STDERR_LINE_SIZE} "$STDERR_FILE")"
cnt=$(echo $lines | wc -l)
for line in lines; do
to_monitor "$STDERR:$cnt: $line"
let cnt--
done
local lines=$(tail --lines=${STDERR_LINE_SIZE} "$STDERR_FILE" | wc -l)
echo -n "STDERR:${lines}:" >&${MONITOR_FD}
tail --lines=$lines "$STDERR_FILE" >&${MONITOR_FD}
else
for line in "${ERRORS[@]}"; do
to_monitor "ERROR: $line"
echo "ERROR:$line" >&${MONITOR_FD}
done
fi
}
......@@ -432,9 +434,7 @@ check_if_excluded() {
return_success() {
to_result SUCCESS
echo SUCCESS >&${RESULT_FD}
}
trap cleanup EXIT
......
......@@ -30,6 +30,8 @@ fi
# terminate helper vm when the script exits
add_cleanup telinit 0
prepare_helper
if [ ! -b "$FLOPPY_DEV" ]; then
log_error "Floppy device is not present!"
fi
......
......@@ -141,57 +141,11 @@ if [ -n "$IMG_PERSONALITY" ]; then
snf_export_PERSONALITY="$IMG_PERSONALITY"
fi
create_floppy "$floppy"
# Invoke the helper vm to do the dirty job...
jail=$(mktemp -d --tmpdir tmpfsXXXXXXX)
add_cleanup rmdir "$jail"
mount tmpfs -t tmpfs "$jail" -o size=1G
add_cleanup umount -l "$jail"
result_file=$(mktemp --tmpdir="$jail" result.XXXXXX)
add_cleanup rm "$result_file"
snapshot=$(mktemp --tmpdir="$jail" helperXXXXXX.img)
add_cleanup rm "$snapshot"
mk_snapshot
echo -n "$(date +%Y:%m:%d-%H:%M:%S.%N) " >&2
log_info "Starting customization VM..."
set +e
snf_export_DEV=$(get_img_dev)
launch_helper
rc=$?
set -e
if [ $rc -ne 0 ]; then
if [ $rc -eq 124 ]; then
log_error "Image customization was terminated. Did not finish on time."
elif [ $rc -eq 137 ]; then # (128 + SIGKILL)
log_error "Image customization was killed. Did not finish on time."
elif [ $rc -eq 141 ]; then # (128 + SIGPIPE)
log_error "Image customization was terminated by a SIGPIPE."
log_error "Maybe progress monitor has died unexpectedly."
elif [ $rc -eq 125 ]; then
log_error "Internal Error. Image customization could not start."
log_error "timeout did not manage to run."
else
log_error "Image customization died unexpectedly (return code $rc)."
fi
exit 1
else
echo -n "$(date +%Y:%m:%d-%H:%M:%S.%N)" >&2
log_info "Customization VM finished."
fi
get_helper_result
create_floppy "$floppy"
if [ "x$result" != "xHELPER_RESULT_SUCCESS" ]; then
log_error "Image customization failed."
exit 1
fi
launch_helper "$blockdev" "$floppy"
log_info "Image customization finished successfully."
......
snf_export_DEV=/dev/vda
mk_snapshot() {
get_img_dev() {
echo /dev/vda
}
launch_helper() {
local jail result_file result snapshot rc floppy blockdev
blockdev="$1"
floppy="$2"
# Invoke the helper vm to do the dirty job...
jail=$(mktemp -d --tmpdir tmpfsXXXXXXX)
add_cleanup rmdir "$jail"
mount tmpfs -t tmpfs "$jail" -o size=1G
add_cleanup umount -l "$jail"
result_file=$(mktemp --tmpdir="$jail" result.XXXXXX)
add_cleanup rm "$result_file"
snapshot=$(mktemp --tmpdir="$jail" helperXXXXXX.img)
add_cleanup rm "$snapshot"
"$QEMU_IMG" create -f qcow2 -b "$HELPER_IMG" "$snapshot"
}
echo -n "$(date +%Y:%m:%d-%H:%M:%S.%N) " >&2
log_info "Starting customization VM..."
launch_helper() {
set +e
$TIMEOUT -k "$HELPER_HARD_TIMEOUT" "$HELPER_SOFT_TIMEOUT" \
kvm -runas "$HELPER_USER" -drive file="$snapshot" \
-drive file="$blockdev",format=raw,if=virtio,cache=none \
-boot c -serial stdio -serial "file:$(printf "%q" "$result_file")" \
-serial file:>(./helper-monitor.py ${MONITOR_FD}) \
-fda "$floppy" -vga none -nographic -parallel none -monitor null \
-kernel "$HELPER_KERNEL" -initrd "$HELPER_INITRD" \
-append "quiet ro root=/dev/sda1 console=ttyS0,9600n8 \
hypervisor=$HYPERVISOR snf_image_activate_helper" \
2>&1 | sed -u 's|^|HELPER: |g'
$TIMEOUT -k "$HELPER_HARD_TIMEOUT" "$HELPER_SOFT_TIMEOUT" \
kvm -runas "$HELPER_USER" -drive file="$snapshot" \
-drive file="$blockdev",format=raw,if=virtio,cache=none \
-boot c -serial stdio -serial "file:$(printf "%q" "$result_file")" \
-serial file:>(./helper-monitor.py ${MONITOR_FD}) \
-fda "$floppy" -vga none -nographic -parallel none -monitor null \
-kernel "$HELPER_KERNEL" -initrd "$HELPER_INITRD" \
-append "quiet ro root=/dev/sda1 console=ttyS0,9600n8 \
hypervisor=$HYPERVISOR snf_image_activate_helper \
rules_dev=/dev/fd0" \
2>&1 | sed -u 's|^|HELPER: |g'
}
rc=$?
set -e
get_helper_result() {
if [ $rc -ne 0 ]; then
if [ $rc -eq 124 ]; then
log_error "Image customization was terminated. Did not finish on time."
elif [ $rc -eq 137 ]; then # (128 + SIGKILL)
log_error "Image customization was killed. Did not finish on time."
elif [ $rc -eq 141 ]; then # (128 + SIGPIPE)
log_error "Image customization was terminated by a SIGPIPE."
log_error "Maybe progress monitor has died unexpectedly."
elif [ $rc -eq 125 ]; then
log_error "Internal Error. Image customization could not start."
log_error "timeout did not manage to run."
else
log_error "Image customization died unexpectedly (return code $rc)."
fi
exit 1
else
echo -n "$(date +%Y:%m:%d-%H:%M:%S.%N)" >&2
log_info "Customization VM finished."
fi
result=$(sed 's|\r||g' "$result_file" | head -1)
report_info "Checking customization status..."
# Read the first line. This will remove \r and \n chars
result=$(sed 's|\r||g' "$result_file" | head -1)
if [ "x$result" != "xHELPER_RESULT_SUCCESS" ]; then
log_error "Image customization failed."
exit 1
fi
}
# vim: set sta sts=4 shiftwidth=4 sw=4 et ai :
......@@ -123,7 +123,7 @@ 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.XXXXXX")
dd if=/dev/zero of="$helper_img" bs=1k count=800000 &> /dev/null
dd if=/dev/zero of="$helper_img" bs=1k count=400000 &> /dev/null
echo "done"
echo "Creating partitions..."
......@@ -142,7 +142,7 @@ mkfs.ext3 "$root_dev" 2>&1 | sed -e 's/^/MKFS.EXT3: /g'
# The helper vm should never do filesystem checks...
tune2fs -i 0 -c 0 "$root_dev" 2>&1 | sed -e 's/^/TUNE2FS: /g'
blkid=$(blkid -s UUID -o value $root_dev)
root_uuid=$(blkid -s UUID -o value "$root_dev")
target=$(mktemp -d)
add_cleanup rmdir "$target"
......@@ -212,52 +212,32 @@ cat > "$target/etc/fstab" <<EOF
# /etc/fstab: static file system information.
#
# <file system> <mount point> <type> <options> <dump> <pass>
UUID=$blkid / ext3 defaults 0 1
UUID=$root_uuid / ext3 defaults 0 1
proc /proc proc defaults 0 0
EOF
echo "done"
echo -n "Extracting kernel..."
if [ ! -L "$target/vmlinuz" -o ! -L "$target/vmlinuz" ]; then
echo -e "\033[1;31mfailed\033[0m"
log_error "vmlinuz or initrd.img link in root is missing."
log_error "I don't know how to find a usable kernel/initrd pair."
exit 1
fi
echo "done"
kernel=$(readlink -en "$target/vmlinuz")
initrd=$(readlink -en "$target/initrd.img")
echo "Moving $(basename "$kernel") and $(basename "$initrd") to \`$HELPER_DIR'"
mv "$kernel" "$initrd" "$HELPER_DIR"
setup_image() {
# setup_image pkg suffix
echo "Getting linux image $1"
chroot "$target" apt-get install -y --force-yes -qq "$1" &>/dev/null
echo -n "Extracting kernel..."
if [ ! -L "$target/vmlinuz" -o ! -L "$target/vmlinuz" ]; then
echo -e "\033[1;31mfailed\033[0m"
log_error "vmlinuz or initrd.img link in root is missing."
log_error "I don't know how to find a usable kernel/initrd pair."
exit 1
fi
echo "done"
kernel=$(readlink -en "$target/vmlinuz")
initrd=$(readlink -en "$target/initrd.img")
echo "Moving $(basename "$kernel") and $(basename "$initrd") to \`$HELPER_DIR'"
mv "$kernel" "$initrd" "$HELPER_DIR"
kernel=$(basename "$kernel")
initrd=$(basename "$initrd")
(
cd "$HELPER_DIR";
ln -fs "$kernel" kernel$2;
ln -fs "$initrd" initrd$2;
)
rm "$target/vmlinuz" "$target/initrd.img"
}
kernel=$(basename "$kernel")
initrd=$(basename "$initrd")
setup_image $HELPER_LINUX_IMAGE_PKG ""
setup_image $HELPER_LINUX_IMAGE_XEN_PKG "-xen"
(cd "$HELPER_DIR"; ln -fs "$kernel" kernel; ln -fs "$initrd" initrd)
rm "$target/vmlinuz" "$target/initrd.img"
echo "Installing snf-image-helper pkg in the new image..."
cp "$HELPER_PKG" "$target/tmp/"
......@@ -283,20 +263,6 @@ if ! grep -q snf_image_activate_helper /proc/cmdline; then
echo "WARNING: NOT calling snf-image-helper, add snf_image_activate_helper"
echo "to the kernel command line if you want to do so."
else
for x in \$(cat /proc/cmdline); do
case x in
hypervisor*) eval \$x
;;
esac
done
case \$hypervisor in
xen-pvm|xen-hvm)
mount -t xenfs xenfs /proc/xen
iptables -P OUTPUT DROP
ip6tables -P OUTPUT DROP
ip link set eth0 up
;;
esac
/usr/bin/snf-image-helper --force
fi
......
snf_export_DEV=/dev/xvdb
HELPER_KERNEL=${HELPER_KERNEL}-xen
HELPER_INITRD=${HELPER_INITRD}-xen
mk_snapshot() {
cp "$HELPER_IMG" "$snapshot"
get_img_dev() {
echo /dev/xvdb
}
launch_helper() {
local name helperid rc blockdev floppy
helper_name=helper$$
blockdev="$1"
floppy="$2"
name=$(uuid)
xm create /dev/null \
kernel="$HELPER_KERNEL" ramdisk="$HELPER_INITRD" \
extra="console=hvc0 hypervisor=$HYPERVISOR snf_image_activate_helper" \
disk="file:$snapshot,xvda,w" \
disk="phy:$blockdev,xvdb,w" \
disk="file:$floppy,xvdc1,w" \
vif="mac=aa:00:00:00:00:11,bridge=$XEN_BRIDGE" \
memory="256" root="/dev/xvda1 quiet ro boot=local" boot="c" vcpus=1 \
name="$helper_name"
if [ ! $(xenstore-exists helper) ]; then
xenstore-write helper ""
kernel="$HELPER_KERNEL" ramdisk="$HELPER_INITRD" root="/dev/xvda1" \
extra="console=hvc0 hypervisor=$HYPERVISOR snf_image_activate_helper quiet ro boot=local" \
disk="file:${HELPER_IMG},xvda,w" disk="phy:$blockdev,xvdb,w" \
disk="file:$floppy,xvdc,r" vif="mac=aa:00:00:00:00:11,bridge=$XEN_BRIDGE" \
memory="256" boot="c" vcpus=1 name="$name"
if ! xenstore-exists snf-image-helper; then
xenstore-write snf-image-helper ""
#add_cleanup xenstore-rm snf-image-helper
fi
helperid=$(xm domid $helper_name)
xenstore-write helper/$helperid ""
xenstore-chmod helper/$helperid r0 w$helperid
brctl delif xenbr vif$helperid.0
helperid=$(xm domid "$name")
xenstore-write snf-image-helper/${helperid} ""
add_cleanup xenstore-rm snf-image-helper/${helperid}
xenstore-chmod snf-image-helper/${helperid} r0 w${helperid}
brctl delif xenbr "vif${helperid}.0"
socat EXEC:"./helper-monitor.py ${MONITOR_FD}" INTERFACE:vif$helperid.0 &
socat EXEC:"./helper-monitor.py ${MONITOR_FD}" INTERFACE:vif${helperid}.0 &
set +e
$TIMEOUT -k $HELPER_HARD_TIMEOUT $HELPER_SOFT_TIMEOUT \
socat EXEC:"xm console $helper_name",pty STDOUT \
| sed -u 's|^|HELPER: |g'
socat EXEC:"xm console $name",pty STDOUT | sed -u 's|^|HELPER: |g'
}
rc=$?
set -e
if [ $rc -ne 0 ]; then
if [ $rc -eq 124 ]; then
log_error "Image customization was terminated. Did not finish on time."
elif [ $rc -eq 137 ]; then # (128 + SIGKILL)
log_error "Image customization was killed. Did not finish on time."
elif [ $rc -eq 141 ]; then # (128 + SIGPIPE)
log_error "Image customization was terminated by a SIGPIPE."
log_error "Maybe progress monitor has died unexpectedly."
elif [ $rc -eq 125 ]; then
log_error "Internal Error. Image customization could not start."
log_error "timeout did not manage to run."
else
log_error "Image customization died unexpectedly (return code $rc)."
fi
exit 1
else
echo -n "$(date +%Y:%m:%d-%H:%M:%S.%N)" >&2
log_info "Customization VM finished."
fi
get_helper_result() {
result=$(xenstore-read snf-image-helper/$helperid)
result=$(xenstore-read helper/$helperid)
xenstore-rm helper/$helperid
if [ "x$result" != "xSUCCESS" ]; then
log_error "Image customization failed."
exit 1
fi
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment