-# 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
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
-RESULT=/dev/ttyS1
-MONITOR=/dev/ttyS2
-
-FLOPPY_DEV=/dev/fd0
PROGNAME=$(basename $0)
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
BLOCKDEV=blockdev
REGLOOKUP=reglookup
CHNTPW=chntpw
+SGDISK=sgdisk
+GROWFS_UFS=growfs.ufs
+DUMPFS_UFS=dumpfs.ufs
DATE="date -u" # Time in UTC
EATMYDATA=eatmydata
+MOUNT="mount -n"
CLEANUP=( )
ERRORS=( )
CLEANUP+=("$cmd")
}
+close_fd() {
+ local fd=$1
+
+ exec {fd}>&-
+}
+
+send_result_kvm() {
+ echo "$@" > /dev/ttyS1
+}
+
+send_monitor_message_kvm() {
+ echo "$@" > /dev/ttyS2
+}
+
+send_result_xen() {
+ xenstore-write /local/domain/0/snf-image-helper/$DOMID "$*"
+}
+
+send_monitor_message_xen() {
+ #Broadcast the message
+ echo "$@" | socat "STDIO" "UDP-DATAGRAM:${BROADCAST}:${MONITOR_PORT},broadcast"
+}
+
+prepare_helper() {
+ local cmdline item key val hypervisor domid
+
+ read -a cmdline < /proc/cmdline
+ for item in "${cmdline[@]}"; do
+ key=$(cut -d= -f1 <<< "$item")
+ val=$(cut -d= -f2 <<< "$item")
+ if [ "$key" = "hypervisor" ]; then
+ hypervisor="$val"
+ fi
+ if [ "$key" = "rules_dev" ]; then
+ export RULES_DEV="$val"
+ fi
+ if [ "$key" = "helper_ip" ]; then
+ export IP="$val"
+ export NETWORK="$IP/24"
+ export BROADCAST="${IP%.*}.255"
+ fi
+ if [ "$key" = "monitor_port" ]; then
+ export MONITOR_PORT="$val"
+ fi
+ done
+
+ case "$hypervisor" in
+ kvm)
+ HYPERVISOR=kvm
+ ;;
+ xen-hvm|xen-pvm)
+ if [ -z "$IP" ]; then
+ echo "ERROR: \`helper_ip' not defined or empty" >&2
+ exit 1
+ fi
+ if [ -z "$MONITOR_PORT" ]; then
+ echo "ERROR: \`monitor_port' not defined or empty" >&2
+ exit 1
+ fi
+ $MOUNT -t xenfs xenfs /proc/xen
+ ip addr add "$NETWORK" dev eth0
+ ip link set eth0 up
+ ip route add default dev eth0
+ export DOMID=$(xenstore-read domid)
+ HYPERVISOR=xen
+ ;;
+ *)
+ echo "ERROR: Unknown hypervisor: \`$hypervisor'" >&2
+ exit 1
+ ;;
+ esac
+
+ export HYPERVISOR
+}
+
report_error() {
+ msg=""
if [ ${#ERRORS[*]} -eq 0 ]; then
# No error message. Print stderr
- local lines
- lines=$(tail --lines=${STDERR_LINE_SIZE} "$STDERR_FILE" | wc -l)
- echo -n "STDERR:${lines}:" > "$MONITOR"
- tail --lines=$lines "$STDERR_FILE" > "$MONITOR"
+ local lines stderr
+ stderr="$(tail --lines=${STDERR_LINE_SIZE} "$STDERR_FILE")"
+ lines=$(wc -l <<< "$stderr")
+ msg="STDERR:${lines}:$stderr"
else
for line in "${ERRORS[@]}"; do
- echo "ERROR:$line" > "$MONITOR"
+ msg+="ERROR:$line"$'\n'
done
fi
+
+ send_monitor_message_${HYPERVISOR} "$msg"
}
log_error() {
ERRORS+=("$*")
- echo "ERROR: $@" | tee $RESULT >&2
+
+ send_result_${HYPERVISOR} "ERROR: $@"
# Use return instead of exit. The set -x options will terminate the script
# but will also trigger ERR traps if defined.
warn() {
echo "Warning: $@" >&2
- echo "WARNING:$@" > "$MONITOR"
+ send_monitor_message_${HYPERVISOR} "WARNING: $@"
}
report_task_start() {
- echo "$MSG_TYPE_TASK_START:${PROGNAME:2}" > "$MONITOR"
+ send_monitor_message_${HYPERVISOR} "$MSG_TYPE_TASK_START:${PROGNAME:2}"
}
report_task_end() {
- echo "$MSG_TYPE_TASK_END:${PROGNAME:2}" > "$MONITOR"
+ send_monitor_message_${HYPERVISOR} "$MSG_TYPE_TASK_END:${PROGNAME:2}"
}
system_poweroff() {
echo "gentoo"
elif [ -e "$root_dir/etc/arch-release" ]; then
echo "arch"
+ elif [ -e "$root_dir/etc/freebsd-update.conf" ]; then
+ echo "freebsd"
else
warn "Unknown base distro."
fi
echo "gentoo"
elif [ -e "$root_dir/etc/arch-release" ]; then
echo "arch"
+ elif [ -e "$root_dir/etc/freebsd-update.conf" ]; then
+ echo "freebsd"
else
warn "Unknown distro."
fi
local dev="$1"
local part_num="$2"
- id=$($SFDISK --print-id "$dev" "$part_num")
- if [ "$id" = "5" ]; then
+ id=$($SFDISK --force --print-id "$dev" "$part_num")
+ if [ "$id" = "5" -o "$id" = "f" ]; then
echo "yes"
else
echo "no"
dev="$1"
table=$(get_partition_table "$dev")
+ if [ -z "$table" ]; then
+ return 0
+ fi
if [ $(get_partition_count "$table") -eq 0 ]; then
return 0
extended=$(get_extended_partition "$table")
last_primary=$(get_last_primary_partition "$table")
ext_num=$(cut -d: -f1 <<< "$extended")
- prim_num=$(cut -d: -f1 <<< "$last_primary")
+ last_prim_num=$(cut -d: -f1 <<< "$last_primary")
if [ "$ext_num" != "$last_prim_num" ]; then
echo "$last_prim_num"
local name="${fields[5]}"
local flags="${fields[6]//,/ }"
- $PARTED -s -m -- $device mkpart "$ptype" $fs "$start" "$end"
- for flag in $flags; do
- $PARTED -s -m $device set "$id" "$flag" on
- done
+ if [ "$ptype" = "primary" -o "$ptype" = "logical" -o "$ptype" = "extended" ]; then
+ $PARTED -s -m -- $device mkpart "$ptype" $fs "$start" "$end"
+ for flag in $flags; do
+ $PARTED -s -m $device set "$id" "$flag" on
+ done
+ else
+ # For gpt
+ start=${start:0:${#start}-1} # remove the s at the end
+ end=${end:0:${#end}-1} # remove the s at the end
+ $SGDISK -n "$id":"$start":"$end" -t "$id":"$ptype" "$device"
+ fi
}
enlarge_partition() {
echo "$exists"
}
+umount_all() {
+ local target mpoints
+ target="$1"
+
+ # Unmount file systems mounted under directory `target'
+ mpoints="$({ awk "{ if (match(\$2, \"^$target\")) { print \$2 } }" < /proc/mounts; } | sort -rbd | uniq)"
+
+ for mpoint in $mpoints; do
+ umount $mpoint
+ done
+}
+
+get_ufstype() {
+ local device ufs
+
+ device="$1"
+ ufs="$($DUMPFS_UFS "$device" | head -1 | awk '{ match ($3, /\((.+)\)/, ufs); print ufs[1] }')"
+
+ case "$ufs" in
+ UFS1)
+ echo 44bsd
+ ;;
+ UFS2)
+ echo ufs2
+ ;;
+ *)
+ log_error "Unsupported UFS type: \`$ufs' in device $device"
+ echo ""
+ ;;
+ esac
+}
+
cleanup() {
# if something fails here, it shouldn't call cleanup again...
trap - EXIT
return 0
}
+return_success() {
+ send_result_${HYPERVISOR} "SUCCESS"
+}
+
trap cleanup EXIT
set -o pipefail