Hello World

File build-vm of Package build

#
# VM specific functions for the build script
#
################################################################
#
# Copyright (c) 1995-2014 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################

# Only protecting nonroot from root inside guest -> but anyone can be root inside guest
# so disabling spectre/meltdown mitigations doesn't hurt security and gains performance
vm_linux_kernel_parameter="mitigations=off"
# Make sure that dodgy kernels fail quickly and early
vm_linux_always_append="oops=panic panic=1"

# guest visible devices
VM_ROOTDEV=/dev/hda1
VM_SWAPDEV=/dev/hda2

VM_TYPE=
declare -a VM_ARGS
VM_TYPE_PRIVILEGED=
VM_ROOT=
VM_SWAP=
VM_ROOT_TYPE=
VM_SWAP_TYPE=
VM_KERNEL=
VM_INITRD=
VM_CMDLINE=
VM_WORKER=
VM_SERVER=
# the qemu default size is not able to run our default kernel anymore
VM_MEMSIZE=512
VM_NETWORK=
VM_NETOPT=()
VM_NETDEVOPT=()
VM_DEVICEOPT=()
VM_TELNET=
VM_CONSOLE_INPUT=
VM_USER=
VM_USE_MKFS_COPYIN=
VMDISK_ROOTSIZE=4096
VMDISK_SWAPSIZE=1024
VMDISK_FILESYSTEM=
VMDISK_MOUNT_OPTIONS=__default
VMDISK_CLEAN=
VM_HOSTNAME=

# zvm specific?
VM_WORKER_NO=

# kvm specific?
HUGETLBFSPATH=
VM_CUSTOMOPT=

# emulator specific?
EMULATOR_SCRIPT=

# openstack specific
VM_OPENSTACK_FLAVOR=

for i in ec2 emulator kvm lxc openstack qemu uml xen zvm docker pvm nspawn; do
    . "$BUILD_DIR/build-vm-$i"
done

VM_WATCHDOG=
VM_WATCHDOG_PID=

# the following functions just call the corresponding vm versions
vm_verify_options() {
    vm_verify_options_$VM_TYPE "$@"
}

vm_attach_root() {
    vm_attach_root_$VM_TYPE "$@"
}

vm_attach_swap() {
    vm_attach_swap_$VM_TYPE "$@"
}

vm_detach_root() {
    vm_detach_root_$VM_TYPE "$@"
}

vm_detach_swap() {
    vm_detach_swap_$VM_TYPE "$@"
}

vm_fixup() {
    test -z "$BUILD_VERBOSE_VM" && vm_linux_always_append="$vm_linux_always_append quiet"
    vm_fixup_$VM_TYPE "$@"
}

vm_startup() {
    vm_startup_$VM_TYPE "$@"
}

vm_sysrq() {
    vm_sysrq_$VM_TYPE "$@"
}

vm_kill() {
    vm_kill_$VM_TYPE "$@"
}

vm_cleanup() {
    kill_watchdog
    vm_cleanup_$VM_TYPE "$@"
}

vm_parse_options() {
    case ${PARAM/#--/-} in
      -vm-emulator-script|-emulator-script)
	needarg
	EMULATOR_SCRIPT="$ARG"
	shift
      ;;
      -xen|-kvm|-uml|-qemu|-emulator)
	VM_TYPE=${PARAM##*-}
	test -z "$VM_ROOT" && VM_ROOT=1
	if test -n "$ARG" ; then
	    VM_ROOT="$ARG"
	    shift
	fi
      ;;
      -zvm|-lxc)
        VM_TYPE=${PARAM##*-}
	shift
      ;;
      -vm-type)
	needarg
	VM_TYPE="$ARG"
	case "$VM_TYPE" in
	    docker:privileged|nspawn:privileged)
                VM_TYPE_PRIVILEGED=true
                VM_TYPE=${VM_TYPE%:*}
            ;;
	    lxc|docker|nspawn) ;;
	    ec2|xen|kvm|uml|qemu|emulator|openstack|zvm|pvm)
		test -z "$VM_ROOT" && VM_ROOT=1
	    ;;
	    none|chroot) VM_TYPE= ;;
	    *)
		cleanup_and_exit 1 "VM '$VM_TYPE' is not supported"
	    ;;
	esac
	shift
      ;;
      -vm-args)
	needarg
	eval "VM_ARGS=($ARG)"
        shift
      ;;
      -vm-worker)
        needarg
        VM_WORKER="$ARG"
        shift
      ;;
      -vm-worker-nr|-vm-worker-no)
        needarg
        VM_WORKER_NO="$ARG"
        shift
      ;;
      -vm-server|-vm-region)
	needarg
	VM_SERVER="$ARG"
	shift
      ;;
      -vm-disk)
	needarg
	VM_ROOT="$ARG"
	shift
      ;;
      -vm-swap|-xenswap|-swap)
	needarg
	VM_SWAP="$ARG"
	shift
      ;;
      -vm-use-mkfs-copyin)
	VM_USE_MKFS_COPYIN="true"
      ;;
      -vm-memory|-xenmemory|-memory)
	needarg
	VM_MEMSIZE="$ARG"
	shift
      ;;
      -vm-kernel)
	needarg
	VM_KERNEL="$ARG"
	shift
      ;;
      -vm-initrd)
	needarg
	VM_INITRD="$ARG"
	shift
      ;;
      -vm-cmdline)
	needarg
	VM_CMDLINE="$ARG"
	shift
      ;;
      -vm-disk-size|-vmdisk-rootsize)
	needarg
	VMDISK_ROOTSIZE="$ARG"
	shift
      ;;
      -vm-swap-size|-vmdisk-swapsize)
	needarg
	VMDISK_SWAPSIZE="$ARG"
	shift
      ;;
      -vm-disk-filesystem|-vmdisk-filesystem)
	needarg
	VMDISK_FILESYSTEM="$ARG"
	shift
      ;;
      -vm-disk-filesystem-options|-vmdisk-filesystem-options)
	needarg
	VMDISK_FILESYSTEM_OPTIONS="$ARG"
	shift
      ;;
      -vm-disk-mount-options|-vmdisk-mount-options)
	needarg
	VMDISK_MOUNT_OPTIONS="$ARG"
	# silly code for compat with old bs_worker versions...
	if test "$1" != "----noarg=$PARAM" -a "$ARG" != "${ARG#\"}" -a "$ARG" != "${ARG%\"}" ; then
	    VMDISK_MOUNT_OPTIONS="${VMDISK_MOUNT_OPTIONS#\"}"
	    VMDISK_MOUNT_OPTIONS="${VMDISK_MOUNT_OPTIONS%\"}"
	fi
	shift
      ;;
      -vm-disk-clean|-vmdisk-clean)
	# delete old root/swap to get rid of the old blocks
        VMDISK_CLEAN=true
      ;;
      -vm-hugetlbfs|-hugetlbfs)
	needarg
	HUGETLBFSPATH="$ARG"
	shift
      ;;
      -vm-watchdog)
	VM_WATCHDOG=true
      ;;
      -vm-user)
        needarg
        VM_USER="$ARG"
        shift
      ;;
      -vm-enable-console)
        VM_CONSOLE_INPUT=true
      ;;
      -vm-telnet)
        needarg
        VM_TELNET="$ARG"
        shift
      ;;
      -vm-network)
        VM_NETWORK=true
        VM_NETDEVOPT=("${VM_NETDEVOPT[@]}" user,id=u1,host=10.0.2.2,net=10.0.2.0/24)
        VM_DEVICEOPT=("${VM_DEVICEOPT[@]}" e1000,netdev=u1)
        shift
      ;;
      -vm-net)
        needarg
        VM_NETOPT=("${VM_NETOPT[@]}" "$ARG")
        shift
      ;;
      -vm-netdev)
        needarg
        VM_NETDEVOPT=("${VM_NETDEVOPT[@]}" "$ARG")
        shift
      ;;
      -vm-device)
        needarg
        VM_DEVICEOPT=("${VM_DEVICEOPT[@]}" "$ARG")
        shift
      ;;
      -vm-custom-opt)
        needarg
        VM_CUSTOMOPT="$ARG"
        shift
      ;;
      -vm-openstack-flavor|-openstack-flavor)
        needarg
        VM_OPENSTACK_FLAVOR="$ARG"
        shift
      ;;
      -*)
	return 1
      ;;
    esac
    nextargs=("$@")
    return 0
}

vm_set_buildstatus() {
    if test -n "$VM_ROOT" -a -n "$VM_SWAP" -a "$VM_SWAP_TYPE" != unattached -a -e "$VM_SWAP" ; then
        echo -n "BUILDSTATUS$1" >"$VM_SWAP"
    fi
}

#
# Helper for vm_shutdown() to do the actual system halt
#
vm_shutdown_halt_helper() {
    kill -9 -1        # goodbye cruel world
    if ! mount -o remount,ro / ; then
        echo "Warning: 'remount -o ro /' failed. Triple Syncing.."
        sync ; sync ; sync
    fi
    sync	# halt from systemd is not syncing anymore.
    if ! test -x /sbin/poweroff ; then
	test -e /proc/sysrq-trigger || mount -n -tproc none /proc
	echo o > /proc/sysrq-trigger
	sleep 5 # wait for sysrq to take effect
	echo "Warning: VM doesn't support sysrq and /sbin/poweroff not installed"
    else
	poweroff -f
    fi
    exit $1
}

vm_shutdown_halt() {
    # get rid of the exit handler
    trap EXIT
    test "$VM_TYPE" = lxc -o "$VM_TYPE" = docker -o "$VM_TYPE" = nspawn && exit $1
    # shutdown from fresh shell to close out deleted inodes
    exec -a "build: halt" -- $BASH -c "$(declare -f vm_shutdown_halt_helper); vm_shutdown_halt_helper $1"
    echo "Warning: clean shut down of the VM didn't work"
    exit $1
}

#
# shutdown the system from inside the VM
#
vm_shutdown() {
    test -n "$VM_WATCHDOG" && echo "### VM INTERACTION START ###"
    exec >&0 2>&0	# so that the logging tee finishes
    cd /
    test -n "$1" || set 1
    if test -n "$VM_SWAP" -a -e "$VM_SWAP" ; then
	swapoff "$VM_SWAP" 2>/dev/null
	echo -n "BUILDSTATUS$1" >"$VM_SWAP"
    fi

    # Wait for logging tee to finish
    LOGGING_TEE_PID=
    test -f "$LOGFILE.pid" -a ! -L "$LOGFILE.pid" && read LOGGING_TEE_PID < "$LOGFILE.pid"
    if test -n "$LOGGING_TEE_PID"; then
        while kill -0 "$LOGGING_TEE_PID" 2>/dev/null; do
            sleep 0.1
        done
    fi
    # if VM_EXTRA_FORK is set we were called from vm_detect_2nd_stage, so just exit and
    # let the parent process to the shutdown call
    test -n "$VM_EXTRA_FORK" && exit $1
    vm_shutdown_halt $1
}

vm_img_create() {
    local img="$1"
    local size="$2"

    if test -e "${img}" ; then
	local origsize=$(cat "${img}.size" 2> /dev/null)
	if test -z "$origsize" -o "$origsize" != "$size" ; then
	    echo "Resizing $img (${size}M)"
	fi
    else
	echo "Creating $img (${size}M)"
	rm -f "${img}.size"
    fi

    mkdir -p "${img%/*}" || cleanup_and_exit 4
    # truncate file to the desired size
    dd if=/dev/zero of="$img" bs=1M count=0 seek="$size" status=none || cleanup_and_exit 4
    echo "$size" > "${img}.size"

    # allocate blocks
    if type -p fallocate > /dev/null ; then
        fallocate -p -l "${size}M" "$img" 2> /dev/null
        errout=$( fallocate -l "${size}M" "$img" 2>&1 )
        if test $? != 0; then
            echo $errout
            if test "${errout/Operation not supported/}" = "$errout"; then
                # Do not fail on not support file systems, eg ext2 or ext3
                cleanup_and_exit 4
            fi
        fi
    fi
}

vm_img_wipe() {
    vm_wipe_$VM_TYPE "$@"

    if test -n "$VM_ROOT" -a "$VM_ROOT_TYPE" = file ; then
       rm -f "$VM_ROOT"
    fi
    if test -n "$VM_SWAP" -a "$VM_SWAP_TYPE" = file ; then
       rm -f "$VM_SWAP"
    fi
}

vm_img_mkfs() {
    local fs="$1"
    local img="$2"
    local options="$3"
    local populate="$4"
    local mkfs tunefs

    case "$fs" in
	ext[234]|xfs|btrfs|reiserfs) ;;
	*) cleanup_and_exit 1 "filesystem \"$fs\" is not supported" ;;
    esac

    # defaults for creating the filesystem
    vm_img_mkfs_ext4_options='-O ^has_journal,^huge_file,^resize_inode,sparse_super,^metadata_csum'
    vm_img_mkfs_ext4_extra='-E lazy_itable_init,discard'
    vm_img_mkfs_ext4="mkfs.ext4 -m 0 -q -F $vm_img_mkfs_ext4_options"
    vm_img_mkfs_ext3='mkfs.ext3 -m 0 -q -F'
    vm_img_mkfs_ext2='mkfs.ext2 -m 0 -q -F'
    vm_img_mkfs_reiserfs='mkreiserfs -q -f'
    vm_img_mkfs_btrfs='mkfs.btrfs'
    vm_img_mkfs_xfs='mkfs.xfs -f'
    # defaults for tuning the filesystem
    vm_img_tunefs_ext4='tune2fs -c 0'
    vm_img_tunefs_ext3='tune2fs -c 0 -o journal_data_writeback'
    vm_img_tunefs_ext2='tune2fs -c 0'

    var="vm_img_mkfs_${fs}"; mkfs="${!var}"
    var="vm_img_mkfs_extra_options_${fs}"; mkfs_extra_options="${!var}"
    var="vm_img_tunefs_${fs}"; vm_img_tunefs="${!var}"

    local labelopt=
    test "$VM_ROOTDEV" != "${VM_ROOTDEV#LABEL=}" && labelopt="-L ${VM_ROOTDEV#LABEL=}"

    # extend options if wanted, multiple -O are fine
    if test "$options" = "nodirindex" && test "$fs" = "ext2" -o "$fs" = "ext3" -o "$fs" = "ext4"; then
        mkfs_extra_options="$mkfs_extra_options -O ^dir_index"
    fi
    if test -n "$populate"; then
      if test "$fs" = "ext2" -o "$fs" = "ext3" -o "$fs" = "ext4"; then
        mkfs_extra_options="$mkfs_extra_options -d $populate"
        # mkfs needs to see the files it copies into the fs as owned by root.
        # Otherwise the whole fs tree would be owned by the calling user.
        # Doesn't matter too much when setting up the build root initially as
        # rpm is called inside anway to fix everything. However, when reusing
        # an image suddenly all ownerships would change.
        [ -x "/usr/bin/unshare" ] && mkfs="unshare --user --map-root-user $mkfs"
      else
        print "ERROR: populating filesystem is only supported with ext file systems"
        cleanup_and_exit 1
      fi
    fi

    if test -z "$mkfs"; then
	cleanup_and_exit 1 "filesystem \"$fs\" is not supported"
    fi

    echo "Creating $fs filesystem on $img"
    export MKE2FS_SYNC=0
    if ! $mkfs $labelopt $mkfs_extra_options "$img" ; then
        if test -z "$mkfs_extra_options" ; then
            cleanup_and_exit 3
        else
            echo "Filesystem creation failed, trying again without extra options..."
            $mkfs $labelopt "$img" || cleanup_and_exit 4
        fi
    fi
    if test -n "$tunefs" ; then
	$tunefs "$img" || cleanup_and_exit 4
    fi
}

background_monitor_process() {
    max_disk=0
    max_mem=0
    while sleep 5; do
	test -e /.build/_statistics.exit  && exit 0

	# memory usage
	if test -e /proc/meminfo ; then
	    memtotal=0
	    while read key value unit; do
		case $key in
		    MemTotal:|SwapTotal:) memtotal=$(( $memtotal + $value )) ;;
		    MemFree:|SwapFree:|SwapCached:|Cached:|Buffers:) memtotal=$(( $memtotal - $value )) ;;
		esac
	    done < /proc/meminfo
	    if test ${memtotal} -gt $max_mem ; then
		max_mem="${memtotal}"
		echo -n $(( $max_mem / 1024 )) > /.build/_statistics.memory.new && mv /.build/_statistics.memory.new /.build/_statistics.memory
	    fi
	fi

	# disk storage usage
	if type -p df >& /dev/null; then
	    c=(`df -m / 2>/dev/null | tail -n 1`)

	    if test ${c[2]} -gt $max_disk ; then
		max_disk="${c[2]}"
		echo -n $max_disk > /.build/_statistics.df.new && mv /.build/_statistics.df.new /.build/_statistics.df
	    fi
	fi
    done
}

background_watchdog() {
    WATCHDOG_START=
    WATCHDOG_TIMEOUT=300
    BUILD_OPTIONS_PARSED=
    while sleep 5 ; do
	WATCH=$(grep -a "### VM INTERACTION" "$LOGFILE" | tr '\0' a | tail -n 1)
	case $WATCH in
	    *VM\ INTERACTION\ START*) test -n "$WATCHDOG_START" || WATCHDOG_START=$SECONDS ;;
	    *VM\ INTERACTION\ END*) WATCHDOG_START= ;;
	esac
	if test -n "$WATCHDOG_START" ; then
	    ELAPSED=$(( $SECONDS - $WATCHDOG_START ))
	    if test $ELAPSED -gt $WATCHDOG_TIMEOUT ; then
		# kill the VM
		echo
		echo "### WATCHDOG TRIGGERED, KILLING VM ###"
		vm_kill
	        exit 0
            fi
        fi
    done
}

start_watchdog() {
    local wf=$(mktemp)
    ( background_watchdog & echo $! > "$wf" )
    read VM_WATCHDOG_PID < "$wf"
    rm -f "$wf"
}

kill_watchdog() {
    test -n "$VM_WATCHDOG_PID" && kill "$VM_WATCHDOG_PID"
    VM_WATCHDOG_PID=
}

vm_set_personality_syscall() {
    local archname
    archname=`perl -V:archname 2>/dev/null`
    archname="${archname#archname=?}"
    case "$archname" in
	x86_64*) PERSONALITY_SYSCALL=135 ;;
	alpha*) PERSONALITY_SYSCALL=324 ;;
	sparc*) PERSONALITY_SYSCALL=191 ;;
	ia64*) PERSONALITY_SYSCALL=1140 ;;
	aarch64*) PERSONALITY_SYSCALL=92 ;;
	i?86*|ppc*|arm*|sh4|cris|m68k*|s390*|unicore32|microblaze|riscv*)   PERSONALITY_SYSCALL=136 ;;
	*) cleanup_and_exit 1 "Unknown architecture personality: '$archname'" ;;
    esac
}

# used before calling kvm or xen
linux64() {
    perl -e 'syscall('$PERSONALITY_SYSCALL', 0); exec(@ARGV) || die("$ARGV[0]: $!\n")' "$@"
}

vm_start_statistics() {
    if test "$DO_STATISTICS" = 1 ; then
	rm -f /.build/_statistics.exit
        ( background_monitor_process & )
    fi
}

vm_exit_statistics() {
    if test "$DO_STATISTICS" = 1 ; then
	rm -f /.build/_statistics.exit
    fi
}

vm_detect_2nd_stage() {
    if test ! -e /.build/build.data -o -n "$BUILD_IGNORE_2ND_STAGE" ; then
	return 1
    fi
    . /.build/build.data
    if test -z "$VM_TYPE" ; then
	return 1
    fi
    BUILD_OPTIONS_PARSED=true
    if test $$ -le 2 ; then
	# ignore special init signals if we're init
	# we're using ' ' instead of '' so that the signal handlers
	# are reset in the child processes
	test $$ -eq 1 && trap ' ' HUP TERM
	export VM_EXTRA_FORK=true
	$0 "$@"
	vm_shutdown_halt $?
    fi

    test -n "$VM_WATCHDOG" -a -z "$PERSONALITY_SET" && echo "### VM INTERACTION END ###"
    echo "2nd stage started in virtual machine"
    # fedora packages sometimes do not have the needed links
    ldconfig
    BUILD_ROOT=/
    BUILD_DIR=/.build
    echo "machine type: `uname -m`"
    echo "Linux version: `uname -rv`"
    echo "Increasing log level from now on..."
    echo 4 > /proc/sysrq-trigger
    echo "Enable sysrq operations"
    echo 1 > /proc/sys/kernel/sysrq
    if test "$PERSONALITY" != 0 -a -z "$PERSONALITY_SET" ; then
	export PERSONALITY_SET=true
	echo "switching personality to $PERSONALITY..."
	# this is 32bit perl/glibc, thus the 32bit syscall number
	exec perl -e 'syscall(136, '$PERSONALITY') == -1 && warn("personality: $!\n");exec "/.build/build" || die("/.build/build: $!\n")'
    fi
    RUNNING_IN_VM=true
    test -e /proc/version || mount -orw -n -tproc none /proc
    if test "$VM_TYPE" != lxc -a "$VM_TYPE" != docker -a "$VM_TYPE" != nspawn ; then
	mount -n ${VMDISK_MOUNT_OPTIONS},remount,rw /
    fi
    umount /run >/dev/null 2>&1
    # mount /sys
    if ! test -e /sys/block; then
	mkdir -p /sys
	mount -orw -n -tsysfs sysfs /sys
        # Docker already has sysfs mounted ro elsewhere,
        # need to remount rw explicitly.
        mount -o remount,rw sysfs /sys
    fi
    # mount selinuxfs
    if ! test -e /sys/fs/selinux/status; then
        mount -orw -n -tselinuxfs selinuxfs /sys/fs/selinux 2>/dev/null || :
    fi

    # mount securityfs
    if ! test -e /sys/kernel/security/lsm; then
        mount -orw -n -t securityfs securityfs /sys/kernel/security 2>/dev/null || :
    fi

# qemu inside of xen does not work, check again with kvm later before enabling this
#    if test -e /dev/kqemu ; then
#        # allow abuild user to run qemu
#        chmod 0666 /dev/kqemu
#    fi
    test -d /dev/shm || rm -f /dev/shm
    mkdir -p /dev/pts
    mkdir -p /dev/shm
    mount -n -tdevpts -omode=0620,ptmxmode=0666,gid=5 none /dev/pts
    mount -n -ttmpfs none /dev/shm

    if test -n "$VM_SWAP" ; then
	if test "$VM_SWAP" != "${VM_SWAP#LABEL=}" ; then
	    i=$(blkid -l -o device -t "$VM_SWAP")
	    if test "$i" = "${i#/}" ; then
		cleanup_and_exit 1 "could not find swap device with $VM_SWAP"
	    fi
	    echo "resolved swap device $VM_SWAP to $i"
	    VM_SWAP=$i
	fi
	for i in 1 2 3 4 5 6 7 8 9 10 ; do
	    test -e "$VM_SWAP" && break
	    test $i = 1 && echo "waiting for $VM_SWAP to appear"
	    echo -n .
	    sleep 1
	done
	test $i = 1 || echo
	# recreate the swap device manually if it didn't exist for some
	# reason, hardcoded to hda2 atm
	if ! test -b "$VM_SWAP" ; then
	    rm -f "$VM_SWAP"
	    umask 027
	    mknod "$VM_SWAP" b 3 2
	    umask 022
	fi
	# Do not rely on external system writing the signature, it might differ...
	mkswap "$VM_SWAP"
	swapon -v "$VM_SWAP" || exit 1
    fi
    HOST="$VM_HOSTNAME"

    # repair dracut damage, see bsc#922676
    test -L /var/run -a ! -e /var/run && rm -f /var/run
    test -L /var/lock -a ! -e /var/lock && rm -f /var/lock

    # start a process monitoring max filesystem usage during build
    vm_start_statistics

    if test ! -e /dev/.udev ; then
        echo "WARNING: udev not running, creating extra device nodes"
        test -e /dev/fd || ln -sf /proc/self/fd /dev/fd
        test -e /etc/mtab || ln -sf /proc/mounts /etc/mtab
    fi

    # set date to build start on broken systems (now < build start)
    if test $(date '+%s') -lt $(date -r /.build/.date '+%s') ; then
        echo -n "WARNING: system has a broken clock, setting it to a newer time: "
        date -s $(</.build/.date)
    fi

    # Enable Core dump generation
    mkdir -p "$BUILD_ROOT/.build/cores"
    echo "/.build/cores/%p" > /proc/sys/kernel/core_pattern

    # Load selinux policy (if a preinstall image is used)
    if test -s /etc/selinux/config -a -x /usr/sbin/load_policy -a -e /sys/fs/selinux/status -a -e /installed-pkg ; then
	echo "loading selinux policy"
	/usr/sbin/load_policy
    fi
    return 0
}

vm_set_filesystem_type() {
    local vmfstype
    local vmfsoptions
    if test -n "$BUILD_DIST" ; then 
        # testing for build specific filesystem, which are more important then worker defaults
        vmfstype=`queryconfig --dist "$BUILD_DIST" --configdir "$CONFIG_DIR" --archpath "$BUILD_ARCH" buildflags vmfstype`
        vmfsoptions=`queryconfig --dist "$BUILD_DIST" --configdir "$CONFIG_DIR" --archpath "$BUILD_ARCH" buildflags vmfsoptions`
    fi
    test -n "$vmfstype" && VMDISK_FILESYSTEM="$vmfstype"
    test -n "$vmfsoptions" && VMDISK_FILESYSTEM_OPTIONS="$vmfsoptions"
    # use either commandline specified fs or ext3 as fallback
    test -n "$VMDISK_FILESYSTEM" || VMDISK_FILESYSTEM=ext3
    if test -n "$VM_USE_MKFS_COPYIN"; then
       test "${VMDISK_FILESYSTEM:0:3}" == "ext" || cleanup_and_exit 4 "mkfs copyin works only with ext filesystems"
       /sbin/mkfs.ext3 -d /var/lib/empty -V >& /dev/null || cleanup_and_exit 4 "mkfs is missing the -d option needed for copyin files"
    fi
}

vm_set_mount_options() {
    if test "$VMDISK_MOUNT_OPTIONS" = __default; then
	if test "$VMDISK_FILESYSTEM" = reiserfs ; then
	    VMDISK_MOUNT_OPTIONS='-o data=writeback,commit=150,noatime'
	elif test "$VMDISK_FILESYSTEM" = btrfs ; then
	    VMDISK_MOUNT_OPTIONS='-o nobarrier,noatime,nodatacow'
	elif test "$VMDISK_FILESYSTEM" = "ext4" ; then
	    VMDISK_MOUNT_OPTIONS='-o noatime'
	elif test "$VMDISK_FILESYSTEM" = "ext3" ; then
	    VMDISK_MOUNT_OPTIONS='-o data=writeback,nobarrier,commit=150,noatime'
	elif test "$VMDISK_FILESYSTEM" = "ext2" ; then
	    VMDISK_MOUNT_OPTIONS='-o noacl,noatime'
	elif test "$VMDISK_FILESYSTEM" = "xfs" ; then
	    VMDISK_MOUNT_OPTIONS='-o noatime'
	else
	    VMDISK_MOUNT_OPTIONS='-o noatime'
	fi
    fi
}

vm_set_defaults() {
    # setup root/swap defaults and type, called after option verification
    if test "$VM_ROOT" = 1 ; then
	VM_ROOT="$BUILD_ROOT.img"
	if test -z "$VM_SWAP" -a "$VM_TYPE" != emulator ; then
	    VM_SWAP="$BUILD_ROOT.swap"
	fi
    fi
    if test -n "$VM_ROOT" -a -z "$VM_ROOT_TYPE" ; then
	VM_ROOT_TYPE=file
	test -b "$VM_ROOT" && VM_ROOT_TYPE=device
    fi
    if test -n "$VM_SWAP" -a -z "$VM_SWAP_TYPE" ; then
	VM_SWAP_TYPE=file
	test -b "$VM_SWAP" && VM_SWAP_TYPE=device
    fi
    test $UID != 0 && VM_USE_MKFS_COPYIN="true"
}

#
# create swap space
#
vm_setup_swap() {
    if test -n "$VMDISK_CLEAN" ; then
	# delete old swap to get rid of the old blocks
	if test -n "$VM_SWAP" -a "$VM_SWAP_TYPE" = file -a -f "$VM_SWAP" ; then
	    echo "Deleting old $VM_SWAP"
        rm -f "$VM_SWAP"
	fi
    fi
    if test -n "$VM_SWAP" -a "$VM_SWAP_TYPE" = file ; then
	vm_img_create "$VM_SWAP" "$VMDISK_SWAPSIZE"
    fi
    if test -n "$VM_SWAP" ; then
	vm_attach_swap
	dd if=/dev/zero of="$VM_SWAP" bs=1024 count=1 conv=notrunc status=none || cleanup_and_exit 4
	if test "$VM_SWAPDEV" != "${VM_SWAPDEV#LABEL=}"; then
	    # call mkswap to set a label
	    mkswap -L "${VM_SWAPDEV#LABEL=}" "$VM_SWAP" || cleanup_and_exit 4
	fi
	vm_detach_swap
        # mkswap happens inside of the vm
    fi
}

#
# create file system, mount file system to $BUILD_ROOT
#
vm_setup() {
    vm_set_filesystem_type
    vm_set_mount_options
    echo "VM_ROOT: $VM_ROOT, VM_SWAP: $VM_SWAP"

    vm_attach_root
    vm_setup_swap
    # this should not be needed, but sometimes a xen instance got lost
    test "$VM_TYPE" = xen && vm_purge_xen
    if test -n "$VMDISK_CLEAN" ; then
	# delete old root to get rid of the old blocks
	if test -n "$VM_ROOT" -a "$VM_ROOT_TYPE" = file -a -f "$VM_ROOT" ; then
	    echo "Deleting old $VM_ROOT"
	    rm -f "$VM_ROOT"
	fi
    fi
    # Check for populating filesystem during mkfs
    if test -n "$VM_USE_MKFS_COPYIN" ; then
	echo "Using mkfs copyin mode to populate the root filesystem"
	mkdir_build_root
	if test ! -w /root ; then
	    find "$BUILD_ROOT" -type d -not -perm /200 -print0 | xargs -0 --no-run-if-empty chmod +w
	fi
	rm -rf "$BUILD_ROOT"/* "$BUILD_ROOT"/.[^.]*
        if test -z "$CLEAN_BUILD" -a -e "$VM_ROOT" ; then
           echo "Recovering former build root"
           debugfs -f <(echo rdump / "$BUILD_ROOT") "$VM_ROOT" 2>/dev/null
        fi
    fi
    local clean_build="$CLEAN_BUILD"
    if test "$VM_ROOT_TYPE" = file ; then
	if test -z "$clean_build" ; then
	    local origrootsize
	    test -e "$VM_ROOT" -a -e "${VM_ROOT}.size" && origrootsize=$(cat "${VM_ROOT}.size" 2>/dev/null)
	    if test -z "$origrootsize" -o "$origrootsize" != "$VMDISK_ROOTSIZE" ; then
		# the size has changed, re-create file system
		clean_build=true
	    fi
	fi
	if test -n "$clean_build" ; then
	    vm_img_create "$VM_ROOT" "$VMDISK_ROOTSIZE"
	fi
    fi
    if test ! -e "$VM_ROOT" ; then
	cleanup_and_exit 4 "you need to create $VM_ROOT first"
    fi
    if test -n "$VM_USE_MKFS_COPYIN" ; then
        return
    fi
    if test -n "$clean_build" ; then
	vm_img_mkfs "$VMDISK_FILESYSTEM" "$VM_ROOT" "$VMDISK_FILESYSTEM_OPTIONS" || cleanup_and_exit 4
    fi
    # now mount root/swap
    mkdir_build_root
    if test -w /root ; then
	if test -b $VM_ROOT ; then
	    # mount device directly
	    mount $VMDISK_MOUNT_OPTIONS $VM_ROOT $BUILD_ROOT || cleanup_and_exit 4
	else
	    mount ${VMDISK_MOUNT_OPTIONS},loop $VM_ROOT $BUILD_ROOT || cleanup_and_exit 4
	fi
    else
	if ! mount $BUILD_ROOT; then
	    echo "mounting the build root failed. An fstab entry is probably missing or incorrect."
	    echo "/etc/fstab should contain an entry like this:"
	    echo "$VM_ROOT $BUILD_ROOT auto noauto,user,loop 0 0"
	    cleanup_and_exit 4
	fi
    fi
}

vm_update_hostarch() {
    local kernel="$vm_kernel"
    local hostarchfile
    local newhostarch
    local vm_type="$VM_TYPE"
    test "$vm_type" = "qemu" && vm_type=kvm
    if test -z "$VM_KERNEL" -a -f "$BUILD_ROOT/.build.kernel.$vm_type" -a ! -L "$BUILD_ROOT/.build.kernel.$vm_type" ; then
	kernel="$BUILD_ROOT/.build.kernel.$vm_type"
	if test -f "$BUILD_ROOT/.build.hostarch.$vm_type" -a ! -L "$BUILD_ROOT/.build.hostarch.$vm_type" ; then
	    hostarchfile="$BUILD_ROOT/.build.hostarch.$vm_type"
	fi
    elif test -n "$kernel" -a -f "$kernel" -a -f "$kernel.hostarch" ; then
	hostarchfile="$kernel.hostarch"
    fi
    if test -n "$hostarchfile" -a -f "$hostarchfile" ; then
	local dummy
	read newhostarch dummy < "$hostarchfile"
    elif test -n "$kernel" -a -f "$kernel" ; then
	case `objdump -f "$kernel" 2>/dev/null | sed -ne 's/.*file format //p'` in
	    elf64-powerpcle) newhostarch=ppc64le ;;
	    elf64-powerpc) newhostarch=ppc64 ;;
	esac
    fi
    if test -n "$newhostarch" -a "$newhostarch" != "$BUILD_HOST_ARCH" ; then
	echo "setting hostarch to $newhostarch"
	BUILD_HOST_ARCH="$newhostarch"
	# update BUILD_INITVM_ARCH
	build_host_arch
    fi
}

#
# prepare for vm startup
#
vm_first_stage() {
    vm_set_personality_syscall
    rm -rf "$BUILD_ROOT/.build"
    mkdir -p "$BUILD_ROOT/.build"
    TIME_PREINSTALL=
    if test "$DO_INIT" = true ; then
	# do first stage of init_buildsystem
	rm -f $BUILD_ROOT/.build.success
	set -- init_buildsystem --configdir "$CONFIG_DIR" --cachedir "$CACHE_DIR" --prepare "${initbuildsysstuff[@]}" "${definesnstuff[@]}" "${repos[@]}" $CLEAN_BUILD $USEUSEDFORBUILD $RPMLIST "$RECIPEPATH" $ADDITIONAL_PACKS
	echo "$* ..."
	start_time=$SECONDS
	"$@" || cleanup_and_exit 1
	check_exit
	TIME_PREINSTALL=$(( $SECONDS - $start_time ))
	unset start_time
	if test ! -w /root ; then
	    # remove setuid bit if files belong to user to make e.g. mount work
	    find $BUILD_ROOT/{bin,sbin,usr/bin,usr/sbin} -type f -uid $UID -perm /4000 -print0 | xargs -0 --no-run-if-empty chmod -s
	fi
	copy_oldpackages
    fi

    # start up VM, rerun ourself
    cp -a $BUILD_DIR/. $BUILD_ROOT/.build
    if ! test "$MYSRCDIR" = $BUILD_ROOT/.build-srcdir ; then
	rm -rf "$BUILD_ROOT/.build-srcdir"
	mkdir "$BUILD_ROOT/.build-srcdir" || cleanup_and_exit 1
	copy_sources "$MYSRCDIR" "$BUILD_ROOT/.build-srcdir"
	MYSRCDIR=$BUILD_ROOT/.build-srcdir
    else
	# cwd is at $BUILD_ROOT/.build-srcdir which we want to
	# umount later so step aside
	cd "$SRCDIR"
    fi
    # do the conversion now because a yaml reader may be missing in the vm
    if test -n "$MODULEMDFILE" -a "${MODULEMDFILE##*/}" != _modulemd.pst ; then
	$BUILD_DIR/writemodulemd --converttopst "$MODULEMDFILE" > "$MYSRCDIR/_modulemd.pst"
    fi

    # some time has passed copying files, lets make sure we should not exit
    check_exit

    # update the hostarch
    if test -n "$VM_ROOT" ; then
	vm_update_hostarch
    fi

    # do vm specific fixups
    vm_fixup

    # copy ccache archive
    if test -n "$CCACHE" -a -n "$CCACHE_ARCHIVE" -a "$CCACHE_ARCHIVE" = "${CCACHE_ARCHIVE#redis://}"; then
	mkdir -p "$BUILD_ROOT/.build.oldpackages"
	if ! test "$BUILD_ROOT/.build.oldpackages/_ccache.tar" -ef "$CCACHE_ARCHIVE" ; then
	    cp --remove-destination -a "$CCACHE_ARCHIVE" "$BUILD_ROOT/.build.oldpackages/_ccache.tar"
	fi
	CCACHE_ARCHIVE="/.build.oldpackages/_ccache.tar"
    fi

    # the watchdog needs a log file
    test -n "$LOGFILE" || VM_WATCHDOG=
    # put our config into .build/build.data
    rm -rf $BUILD_ROOT/.build/build.data
    Q="'\''"
    echo "RECIPEFILE='${RECIPEFILE//"'"/$Q}'" > $BUILD_ROOT/.build/build.data
    echo "BUILD_JOBS='${BUILD_JOBS//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
    echo "BUILD_ARCH='${BUILD_ARCH//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
    echo "BUILD_RPMS='${BUILD_RPMS//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
    case $BUILD_DIST in
	*/*)
	    cp $BUILD_DIST $BUILD_ROOT/.build/build.dist
	    BUILD_DIST=/.build/build.dist
	    ;;
    esac
    echo "BUILD_DIST='${BUILD_DIST//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
    echo "RELEASE='${RELEASE//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
    echo "BUILD_DEBUG='${BUILD_DEBUG//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
    echo "SIGNDUMMY='${SIGNDUMMY//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
    echo "DO_LINT='${DO_LINT//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
    echo "DO_CHECKS='${DO_CHECKS//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
    echo "NOROOTFORBUILD='${NOROOTFORBUILD//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
    echo "CREATE_BASELIBS='$CREATE_BASELIBS'" >> $BUILD_ROOT/.build/build.data
    echo "REASON='${REASON//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
    echo "CHANGELOG='${CHANGELOG//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
    echo "INCARNATION='${INCARNATION//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
    echo "DISTURL='${DISTURL//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
    echo "DO_INIT='${DO_INIT//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
    echo "DO_INIT_TOPDIR='${DO_INIT_TOPDIR//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
    echo "KIWI_PARAMETERS='${KIWI_PARAMETERS//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
    echo "VM_TELNET='${VM_TELNET//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
    echo "VM_CONSOLE_INPUT='${VM_CONSOLE_INPUT//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
    test -n "$VM_SWAP" && echo "VM_SWAP='${VM_SWAPDEV//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
    test -n "$VMDISK_MOUNT_OPTIONS" && echo "VMDISK_MOUNT_OPTIONS='${VMDISK_MOUNT_OPTIONS//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
    PERSONALITY=0
    test -n "$PERSONALITY_SYSCALL" && PERSONALITY=`perl -e 'print syscall('$PERSONALITY_SYSCALL', 0)."\n"'`
    test "$PERSONALITY" = -1 && PERSONALITY=0	# syscall failed?
    case $(uname -m) in
	ppc|ppcle|s390) PERSONALITY=8 ;;	# ppc/s390 kernel never tells us if a 32bit personality is active, assume we run on 64bit
	aarch64) test "$BUILD_ARCH" != "${BUILD_ARCH#armv[567]}" && PERSONALITY=8 ;; # workaround, to be removed
    esac
    test "$VM_TYPE" = lxc -o "$VM_TYPE" = docker -o "$VM_TYPE" = nspawn && PERSONALITY=0
    echo "PERSONALITY='$PERSONALITY'" >> $BUILD_ROOT/.build/build.data
    echo "VM_HOSTNAME='$HOST'" >> $BUILD_ROOT/.build/build.data
    echo -n "definesnstuff=(" >> $BUILD_ROOT/.build/build.data
    shellquote "${definesnstuff[@]}" >> $BUILD_ROOT/.build/build.data
    echo ")" >> $BUILD_ROOT/.build/build.data
    echo -n "repos=(" >> $BUILD_ROOT/.build/build.data
    shellquote "${repos[@]}" >> $BUILD_ROOT/.build/build.data
    echo ")" >> $BUILD_ROOT/.build/build.data
    echo "VM_TYPE='$VM_TYPE'" >> $BUILD_ROOT/.build/build.data
    echo "VM_NETWORK='$VM_NETWORK'" >> $BUILD_ROOT/.build/build.data
    echo "RUN_SHELL='$RUN_SHELL'" >> $BUILD_ROOT/.build/build.data
    echo "RUN_SHELL_AFTER_FAIL='$RUN_SHELL_AFTER_FAIL'" >> $BUILD_ROOT/.build/build.data
    echo "RUN_SHELL_CMD='$RUN_SHELL_CMD'" >> $BUILD_ROOT/.build/build.data
    echo "DO_STATISTICS='$DO_STATISTICS'" >> $BUILD_ROOT/.build/build.data
    echo "TIME_PREINSTALL='$TIME_PREINSTALL'" >> $BUILD_ROOT/.build/build.data
    echo "VM_WATCHDOG='$VM_WATCHDOG'" >> $BUILD_ROOT/.build/build.data
    echo "BUILDENGINE='$BUILDENGINE'" >> $BUILD_ROOT/.build/build.data
    echo "CCACHE='$CCACHE'" >> $BUILD_ROOT/.build/build.data
    echo "CCACHE_TYPE='$CCACHE_TYPE'" >> $BUILD_ROOT/.build/build.data
    echo "CCACHE_ARCHIVE='$CCACHE_ARCHIVE'" >> $BUILD_ROOT/.build/build.data
    echo "CCACHE_CREATE_ARCHIVE='$CCACHE_CREATE_ARCHIVE'" >> $BUILD_ROOT/.build/build.data
    echo "CCACHE_CLEAN='$CCACHE_CLEAN'" >> $BUILD_ROOT/.build/build.data
    echo "ABUILD_TARGET='$ABUILD_TARGET'" >> $BUILD_ROOT/.build/build.data
    echo "BUILD_FLAVOR='$BUILD_FLAVOR'" >> $BUILD_ROOT/.build/build.data
    echo "OBS_PACKAGE='$OBS_PACKAGE'" >> $BUILD_ROOT/.build/build.data
    echo "BUILD_SKIP_BUNDLE='$BUILD_SKIP_BUNDLE'" >> $BUILD_ROOT/.build/build.data
    echo "BUILD_RPM_BUILD_STAGE='$BUILD_RPM_BUILD_STAGE'" >> $BUILD_ROOT/.build/build.data
    echo "RPM_BUILD_IN_PLACE='$RPM_BUILD_IN_PLACE'" >> $BUILD_ROOT/.build/build.data
    echo "RPM_NOPREP='$RPM_NOPREP'" >> $BUILD_ROOT/.build/build.data
    # fallback time for broken hosts
    rm -rf $BUILD_ROOT/.build/.date
    date '+@%s' > $BUILD_ROOT/.build/.date

    # we're done with the root file system, unmount
    buildroot_umount /proc/sys/fs/binfmt_misc
    buildroot_umount /proc
    buildroot_umount /sys
    buildroot_umount /dev/pts
    buildroot_umount /dev/shm
    buildroot_umount /mnt

    vm_init_script="/.build/build"
    if set_initvm_name_for_emulator_in "$BUILD_ROOT/.build" ; then
        vm_init_script="/.build/$INITVM_NAME"
    fi

    if test -n "$VM_ROOT" ; then
	# copy out kernel & initrd (if they exist) during unmounting VM image
	KERNEL_TEMP_DIR=
        local vm_type="$VM_TYPE"
        test "$vm_type" = "qemu" && vm_type=kvm
	if test -z "$VM_KERNEL" -a -f "$BUILD_ROOT/.build.kernel.$vm_type" -a ! -L "$BUILD_ROOT/.build.kernel.$vm_type" ; then
	    KERNEL_TEMP_DIR=`mktemp -d`
	    cp "$BUILD_ROOT/.build.kernel.$vm_type" "$KERNEL_TEMP_DIR/kernel"
	    if test -f "$BUILD_ROOT/.build.initrd.$vm_type" -a ! -L "$BUILD_ROOT/.build.initrd.$vm_type" ; then
	        cp "$BUILD_ROOT/.build.initrd.$vm_type" "$KERNEL_TEMP_DIR/initrd"
	    fi
	    if test -f "$BUILD_ROOT/.build.cmdline.$vm_type" -a ! -L "$BUILD_ROOT/.build.cmdline.$vm_type" ; then
	        vm_cmdline="$(cat $BUILD_ROOT/.build.cmdline.$vm_type)"
	    fi
	fi
	check_exit
	if test -n "$VM_USE_MKFS_COPYIN" ; then
	    vm_img_mkfs "$VMDISK_FILESYSTEM" "$VM_ROOT" "$VMDISK_FILESYSTEM_OPTIONS" "$BUILD_ROOT" || cleanup_and_exit 4
        else
	    # needs to work otherwise we have a corrupted file system
	    if ! umount $BUILD_ROOT; then
		test -n "$KERNEL_TEMP_DIR" && rm -rf "$KERNEL_TEMP_DIR"
		cleanup_and_exit 4
	    fi
	fi
	# copy back the kernel and set it for VM
	if test -n "$KERNEL_TEMP_DIR" ; then
	    rm -rf "$BUILD_ROOT/boot"
	    mkdir -p "$BUILD_ROOT/boot"
	    mv "$KERNEL_TEMP_DIR/kernel" "$BUILD_ROOT/boot/kernel"
	    vm_kernel="$BUILD_ROOT/boot/kernel"
	    if test -e "$KERNEL_TEMP_DIR/initrd" ; then
	        mv "$KERNEL_TEMP_DIR/initrd" "$BUILD_ROOT/boot/initrd"
	        test -z "$VM_INITRD" && vm_initrd="$BUILD_ROOT/boot/initrd"
	    fi
	    rmdir "$KERNEL_TEMP_DIR"
	fi
    fi
    vm_detach_root

    echo "booting $VM_TYPE..."
    unset VM_EXTRA_FORK

    # start watchdog if requested
    if test -n "$VM_WATCHDOG" ; then
	start_watchdog
	echo "### VM INTERACTION START ###"
    fi

    vm_startup "${VM_ARGS[@]}"

    # kill watchdog again
    if test -n "$VM_WATCHDOG" ; then
	echo "### VM INTERACTION END ###"
	kill_watchdog
    fi

    vm_attach_root
    if test -n "$VM_SWAP" -a -z "$RUN_SHELL" ; then
	vm_attach_swap
	BUILDSTATUS=$(dd if="$VM_SWAP" bs=12 count=1 status=none | tr '\0' a)
	case $BUILDSTATUS in
	  BUILDSTATUS[029])
	    mkdir -p $BUILD_ROOT/.build.packages
	    cd $BUILD_ROOT/.build.packages || cleanup_and_exit 1
	    echo "build: extracting built packages..."
	    extractbuild --disk "$VM_ROOT" --input "$VM_SWAP" --skip 512 -v || cleanup_and_exit 3
            if test "$BUILDTYPE" = "preinstallimage" ; then
                preinstallimage_compress OTHER
            fi
	    if test "$DO_STATISTICS" = 1 ; then
		mkdir -p OTHER
		TIME_TOTAL=$(( $SECONDS - $TIME_START_TIME ))
		echo "TIME_total: $TIME_TOTAL"  >> OTHER/_statistics
	    fi
	    cleanup_and_exit ${BUILDSTATUS#BUILDSTATUS}
	    ;;
	  BUILDSTATUS*)
	    cleanup_and_exit ${BUILDSTATUS#BUILDSTATUS}
	    ;;
	  *)
	    echo "No buildstatus set, either the base system is broken (kernel/initrd/udev/glibc/bash/perl)"
	    echo "or the build host has a kernel or hardware problem..."
	    cleanup_and_exit 3
	    ;;
	esac
	cleanup_and_exit 1
    fi
}

vm_save_statistics() {
    echo "... saving statistics"
    local sys_mounted otherdir
    otherdir="$BUILD_ROOT$TOPDIR/OTHER"
    test -n "$TIME_PREINSTALL" && echo "TIME_preinstall: $TIME_PREINSTALL"  >> $otherdir/_statistics
    test -n "$TIME_INSTALL" && echo "TIME_install: $TIME_INSTALL"  >> $otherdir/_statistics
    test -n "$TIME_POSTCHECKS" && echo "TIME_postchecks: $TIME_POSTCHECKS"  >> $otherdir/_statistics
    test -n "$TIME_RPMLINT" && echo "TIME_rpmlint: $TIME_RPMLINT"  >> $otherdir/_statistics
    test -n "$TIME_BUILDCMP" && echo "TIME_buildcmp: $TIME_BUILDCMP"  >> $otherdir/_statistics
    test -n "$TIME_DELTARPMS" && echo "TIME_deltarpms: $TIME_DELTARPMS"  >> $otherdir/_statistics
    local cpustat=($(head -n 1 /proc/stat))
    test "${cpustat[8]}" -gt 0 && echo "TIME_cpusteal: $(( ${cpustat[8]} / 100 ))" >> $otherdir/_statistics
    if test -e /.build/_statistics.df ; then
	echo -n "MAX_mb_used_on_disk: " >> $otherdir/_statistics
	cat /.build/_statistics.df >> $otherdir/_statistics
	echo "" >> $otherdir/_statistics
	rm /.build/_statistics.df
    fi
    if test -e /.build/_statistics.memory ; then
	echo -n "MAX_mb_used_memory: " >> $otherdir/_statistics
	cat /.build/_statistics.memory >> $otherdir/_statistics
	echo "" >> $otherdir/_statistics
	rm /.build/_statistics.memory
    fi
    if ! test -e /sys/block; then
	mkdir -p /sys
	mount -n sys /sys -t sysfs
	sys_mounted=1
    fi
    device="hda1"
    test -e /dev/sda && device="sda"
    test -e /dev/vda && device="vda"
    test -e /dev/xvda && device="xvda"   # in newer XEN setups
    test -e /dev/dasda && device="dasda" # in z/VM
    test -e /dev/nfhd0 && device="nfhd0" # in aranym
    if test -e /sys/block/${device}/stat ; then
	disk=(`cat /sys/block/${device}/stat`)
	test "0${disk[0]}" -gt 0 && echo "IO_requests_read: ${disk[0]}"  >> $otherdir/_statistics
	test "0${disk[2]}" -gt 0 && echo "IO_sectors_read: ${disk[2]}"   >> $otherdir/_statistics
	test "0${disk[4]}" -gt 0 && echo "IO_requests_write: ${disk[4]}" >> $otherdir/_statistics
	test "0${disk[6]}" -gt 0 && echo "IO_sectors_write: ${disk[6]}"  >> $otherdir/_statistics
    else
	echo "ERROR: no root disk device found, yet another new device name?"
	ls -l /sys/block/
    fi
    test -n "$sys_mounted" && umount /sys
}

# args: resultdirs
vm_wrapup_build() {
    test "$DO_STATISTICS" = 1 && vm_save_statistics
    if test -n "$VM_SWAP"; then
        echo "... saving built packages"
        swapoff "$VM_SWAP"
	pushd "$BUILD_ROOT$TOPDIR" >/dev/null
	find "$@" -print0 | computeblocklists --padstart 512 --padend 512 -v --manifest - -0 > "$VM_SWAP" || cleanup_and_exit 1
	popd >/dev/null
    fi
}

vm_setup_network() {
    if test -x /sbin/ip ; then
	ip addr add 127.0.0.1/8 dev lo
	ip addr add ::1/128 dev lo
	ip link set lo up
    elif test -x /sbin/ifconfig ; then
        ifconfig lo 127.0.0.1 up
        ifconfig lo add ::1/128
    fi
    . /.build/build.data
    if test -n "$VM_NETWORK"; then
       echo "Network setup"
       NETDEV=eth0
       # these IPs are the built-in adresses in qemu
       echo nameserver 10.0.2.3 >> /etc/resolv.conf
       if test -x /sbin/ip ; then
           ip addr add 10.0.2.15/24 dev ${NETDEV}
           ip addr add ::1/24 dev ${NETDEV}
           ip link set ${NETDEV} up
           ip route add default via 10.0.2.2
       elif test -x /sbin/ifconfig ; then
           ifconfig ${NETDEV} 10.0.2.15 netmask 255.255.255.0 up
           ifconfig ${NETDEV} add ::1/24
           route add default gw 10.0.2.2
       else
           dhclient eth0
       fi
       ip a
    fi
    if test -n "$VM_TELNET"; then 
	VM_TELNET_DEVICE=$( cd /sys/class/net/; echo * )
	VM_TELNET_DEVICE=${VM_TELNET_DEVICE#lo }
	VM_TELNET_DEVICE=${VM_TELNET_DEVICE%% *}
	if test -z "$VM_TELNET_DEVICE" ; then 
	    cleanup_and_exit 1 "ERROR: no network device found for telnet server"
	fi
	if test -x /sbin/ip ; then 
	    # these IPs are the built-in adresses in qemu
	    ip addr add 10.0.2.15/8 dev ${VM_TELNET_DEVICE}
	    ip addr add ::1/24 dev ${VM_TELNET_DEVICE}
	    ip link set ${VM_TELNET_DEVICE} up
	elif test -x /sbin/ifconfig ; then 
	    ifconfig ${VM_TELNET_DEVICE} 10.0.2.15 up
	    ifconfig ${VM_TELNET_DEVICE} add ::1/24
	else
	    cleanup_and_exit 1 "ERROR: neither /sbin/ifconfig nor /sbin/ip is installed, please specify correct package via -x option"
	fi
    fi
    if test -n "$VM_HOSTNAME" ; then 
	if test -e /bin/hostname -o -e /usr/bin/hostname -o -e /sbin/hostname -o -e /usr/sbin/hostname ; then
	    hostname "$VM_HOSTNAME"
	elif test -e /proc/sys/kernel/hostname ; then
	    echo "$VM_HOSTNAME" > /proc/sys/kernel/hostname
	fi
    fi
    if test -n "$VM_TELNET"; then 
	echo WARNING: telnet option used, setting up telnet server ${VM_TELNET_DEVICE}
	if test -x /usr/sbin/in.telnetd; then 
	    ( /usr/sbin/in.telnetd -L /.build/telnet_login_wrapper -debug 23 & )
	else
	    cleanup_and_exit 1 "ERROR: /usr/sbin/in.telnetd is not installed, please specify correct package via -x option"
	fi
    fi
}