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. # Copyright (C) 2007, 2008, 2009 Google Inc.
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
...@@ -41,86 +41,88 @@ MSG_TYPE_TASK_END="TASK_END" ...@@ -41,86 +41,88 @@ MSG_TYPE_TASK_END="TASK_END"
STDERR_LINE_SIZE=10 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 close_fd() {
case "$hypervisor" in local fd=$1
kvm)
FLOPPY_DEV=/dev/fd0 exec {fd}>&-
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
} }
to_result() { prepare_helper() {
local cmdline item key val hypervisor domid
case $hypervisor in read -a cmdline < /proc/cmdline
kvm) for item in "${cmdline[@]}"; do
echo "HELPER_RESULT_$@" > "$RESULT" 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) 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 esac
} export RESULT_FD MONITOR_FD
add_cleanup() {
local cmd=""
for arg; do cmd+=$(printf "%q " "$arg"); done
CLEANUP+=("$cmd")
} }
log_error() { log_error() {
ERRORS+=("$@") ERRORS+=("$@")
echo "ERROR: $@" >&2 echo "ERROR: $@" >&2
to_result "ERROR: $@" echo "ERROR: $@" >&${MONITOR_FD}
exit 1 exit 1
} }
warn() { warn() {
echo "Warning: $@" >&2 echo "Warning: $@" >&2
to_monitor "WARNING: $@" echo "WARNING: $@" >&${MONITOR_FD}
} }
report_task_start() { report_task_start() {
to_monitor "$MSG_TYPE_TASK_START:${PROGNAME:2}" echo "$MSG_TYPE_TASK_START:${PROGNAME:2}" >&${MONITOR_FD}
} }
report_task_end() { report_task_end() {
to_monitor "$MSG_TYPE_TASK_END:${PROGNAME:2}" echo "$MSG_TYPE_TASK_END:${PROGNAME:2}" >&${MONITOR_FD}
} }
report_error() { report_error() {
if [ ${#ERRORS[*]} -eq 0 ]; then if [ ${#ERRORS[*]} -eq 0 ]; then
# No error message. Print stderr # No error message. Print stderr
lines="$(tail --lines=${STDERR_LINE_SIZE} "$STDERR_FILE")" local lines=$(tail --lines=${STDERR_LINE_SIZE} "$STDERR_FILE" | wc -l)
cnt=$(echo $lines | wc -l) echo -n "STDERR:${lines}:" >&${MONITOR_FD}
for line in lines; do tail --lines=$lines "$STDERR_FILE" >&${MONITOR_FD}
to_monitor "$STDERR:$cnt: $line"
let cnt--
done
else else
for line in "${ERRORS[@]}"; do for line in "${ERRORS[@]}"; do
to_monitor "ERROR: $line" echo "ERROR:$line" >&${MONITOR_FD}
done done
fi fi
} }
...@@ -432,9 +434,7 @@ check_if_excluded() { ...@@ -432,9 +434,7 @@ check_if_excluded() {
return_success() { return_success() {
echo SUCCESS >&${RESULT_FD}
to_result SUCCESS
} }
trap cleanup EXIT trap cleanup EXIT
......
...@@ -30,6 +30,8 @@ fi ...@@ -30,6 +30,8 @@ fi
# terminate helper vm when the script exits # terminate helper vm when the script exits
add_cleanup telinit 0 add_cleanup telinit 0
prepare_helper
if [ ! -b "$FLOPPY_DEV" ]; then if [ ! -b "$FLOPPY_DEV" ]; then
log_error "Floppy device is not present!" log_error "Floppy device is not present!"
fi fi
......
...@@ -141,57 +141,11 @@ if [ -n "$IMG_PERSONALITY" ]; then ...@@ -141,57 +141,11 @@ if [ -n "$IMG_PERSONALITY" ]; then
snf_export_PERSONALITY="$IMG_PERSONALITY" snf_export_PERSONALITY="$IMG_PERSONALITY"
fi fi
create_floppy "$floppy" snf_export_DEV=$(get_img_dev)
# 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
launch_helper create_floppy "$floppy"
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
if [ "x$result" != "xHELPER_RESULT_SUCCESS" ]; then launch_helper "$blockdev" "$floppy"
log_error "Image customization failed."
exit 1
fi
log_info "Image customization finished successfully." 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" "$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" \ $TIMEOUT -k "$HELPER_HARD_TIMEOUT" "$HELPER_SOFT_TIMEOUT" \
kvm -runas "$HELPER_USER" -drive file="$snapshot" \ kvm -runas "$HELPER_USER" -drive file="$snapshot" \
-drive file="$blockdev",format=raw,if=virtio,cache=none \ -drive file="$blockdev",format=raw,if=virtio,cache=none \
-boot c -serial stdio -serial "file:$(printf "%q" "$result_file")" \ -boot c -serial stdio -serial "file:$(printf "%q" "$result_file")" \
-serial file:>(./helper-monitor.py ${MONITOR_FD}) \ -serial file:>(./helper-monitor.py ${MONITOR_FD}) \
-fda "$floppy" -vga none -nographic -parallel none -monitor null \ -fda "$floppy" -vga none -nographic -parallel none -monitor null \
-kernel "$HELPER_KERNEL" -initrd "$HELPER_INITRD" \ -kernel "$HELPER_KERNEL" -initrd "$HELPER_INITRD" \
-append "quiet ro root=/dev/sda1 console=ttyS0,9600n8 \ -append "quiet ro root=/dev/sda1 console=ttyS0,9600n8 \
hypervisor=$HYPERVISOR snf_image_activate_helper" \ hypervisor=$HYPERVISOR snf_image_activate_helper \
2>&1 | sed -u 's|^|HELPER: |g' 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" ...@@ -123,7 +123,7 @@ rm -f "$HELPER_DIR/initrd" "$HELPER_DIR/kernel" "$HELPER_DIR/image"
echo -n "Allocating space for helper disk image..." echo -n "Allocating space for helper disk image..."
helper_img=$(mktemp "$HELPER_DIR/image.XXXXXX") 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 "done"
echo "Creating partitions..." echo "Creating partitions..."
...@@ -142,7 +142,7 @@ mkfs.ext3 "$root_dev" 2>&1 | sed -e 's/^/MKFS.EXT3: /g' ...@@ -142,7 +142,7 @@ mkfs.ext3 "$root_dev" 2>&1 | sed -e 's/^/MKFS.EXT3: /g'
# The helper vm should never do filesystem checks... # The helper vm should never do filesystem checks...
tune2fs -i 0 -c 0 "$root_dev" 2>&1 | sed -e 's/^/TUNE2FS: /g' 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) target=$(mktemp -d)
add_cleanup rmdir "$target" add_cleanup rmdir "$target"
...@@ -212,52 +212,32 @@ cat > "$target/etc/fstab" <<EOF ...@@ -212,52 +212,32 @@ cat > "$target/etc/fstab" <<EOF
# /etc/fstab: static file system information. # /etc/fstab: static file system information.
# #
# <file system> <mount point> <type> <options> <dump> <pass> # <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 proc /proc proc defaults 0 0
EOF EOF
echo "done" 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() { kernel=$(basename "$kernel")
# setup_image pkg suffix initrd=$(basename "$initrd")
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"
}
setup_image $HELPER_LINUX_IMAGE_PKG "" (cd "$HELPER_DIR"; ln -fs "$kernel" kernel; ln -fs "$initrd" initrd)
setup_image $HELPER_LINUX_IMAGE_XEN_PKG "-xen"
rm "$target/vmlinuz" "$target/initrd.img"
echo "Installing snf-image-helper pkg in the new image..." echo "Installing snf-image-helper pkg in the new image..."
cp "$HELPER_PKG" "$target/tmp/" cp "$HELPER_PKG" "$target/tmp/"
...@@ -283,20 +263,6 @@ if ! grep -q snf_image_activate_helper /proc/cmdline; then ...@@ -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 "WARNING: NOT calling snf-image-helper, add snf_image_activate_helper"
echo "to the kernel command line if you want to do so." echo "to the kernel command line if you want to do so."
else 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 /usr/bin/snf-image-helper --force
fi fi
......
snf_export_DEV=/dev/xvdb get_img_dev() {
HELPER_KERNEL=${HELPER_KERNEL}-xen echo /dev/xvdb
HELPER_INITRD=${HELPER_INITRD}-xen
mk_snapshot() {
cp "$HELPER_IMG" "$snapshot"
} }
launch_helper() { launch_helper() {
local name helperid rc blockdev floppy
helper_name=helper$$ blockdev="$1"
floppy="$2"
name=$(uuid)
xm create /dev/null \ xm create /dev/null \
kernel="$HELPER_KERNEL" ramdisk="$HELPER_INITRD" \ kernel="$HELPER_KERNEL" ramdisk="$HELPER_INITRD" root="/dev/xvda1" \
extra="console=hvc0 hypervisor=$HYPERVISOR snf_image_activate_helper" \ extra="console=hvc0 hypervisor=$HYPERVISOR snf_image_activate_helper quiet ro boot=local" \
disk="file:$snapshot,xvda,w" \ disk="file:${HELPER_IMG},xvda,w" disk="phy:$blockdev,xvdb,w" \
disk="phy:$blockdev,xvdb,w" \ disk="file:$floppy,xvdc,r" vif="mac=aa:00:00:00:00:11,bridge=$XEN_BRIDGE" \
disk="file:$floppy,xvdc1,w" \ memory="256" boot="c" vcpus=1 name="$name"
vif="mac=aa:00:00:00:00:11,bridge=$XEN_BRIDGE" \
memory="256" root="/dev/xvda1 quiet ro boot=local" boot="c" vcpus=1 \ if ! xenstore-exists snf-image-helper; then
name="$helper_name" xenstore-write snf-image-helper ""
#add_cleanup xenstore-rm snf-image-helper
if [ ! $(xenstore-exists helper) ]; then
xenstore-write helper ""
fi 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 \ $TIMEOUT -k $HELPER_HARD_TIMEOUT $HELPER_SOFT_TIMEOUT \
socat EXEC:"xm console $helper_name",pty STDOUT \ socat EXEC:"xm console $name",pty STDOUT | sed -u 's|^|HELPER: |g'
| 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) if [ "x$result" != "xSUCCESS" ]; then
xenstore-rm helper/$helperid 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