Merge remote-tracking branch 'origin/devel'
[tools/build.git] / build-vm
1 #
2 # VM specific functions for the build script
3 #
4 ################################################################
5 #
6 # Copyright (c) 1995-2014 SUSE Linux Products GmbH
7 #
8 # This program is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License version 2 or 3 as
10 # published by the Free Software Foundation.
11 #
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with this program (see the file COPYING); if not, write to the
19 # Free Software Foundation, Inc.,
20 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
21 #
22 ################################################################
23
24 # defaults for vm_img_mkfs
25 vm_img_mkfs_ext4_options='-O ^has_journal,^huge_file,^resize_inode,sparse_super'
26 vm_img_mkfs_ext4_extra='-E lazy_itable_init,discard'
27 vm_img_mkfs_ext4="mkfs.ext4 -m 0 -q -F $vm_img_mkfs_ext4_options"
28 vm_img_tunefs_ext4='tune2fs -c 0'
29 vm_img_mkfs_ext3='mkfs.ext3 -m 0 -q -F'
30 vm_img_tunefs_ext3='tune2fs -c 0 -o journal_data_writeback'
31 vm_img_mkfs_ext2='mkfs.ext2 -m 0 -q -F'
32 vm_img_tunefs_ext2='tune2fs -c 0'
33 vm_img_mkfs_reiserfs='mkreiserfs -q -f'
34 vm_img_mkfs_btrfs='mkfs.btrfs'
35 vm_img_mkfs_xfs='mkfs.xfs -f'
36
37 # guest visible swap device
38 VM_SWAPDEV=/dev/hda2
39
40 VM_TYPE=
41 VM_IMAGE=
42 VM_SWAP=
43 VM_KERNEL=
44 VM_INITRD=
45 VM_WORKER=
46 VM_SERVER=
47 VM_MEMSIZE=
48 VM_NETOPT=()
49 VM_NETDEVOPT=()
50 VM_DEVICEOPT=()
51 VM_TELNET=
52 VM_CONSOLE_INPUT=
53 VMDISK_ROOTSIZE=4096
54 VMDISK_SWAPSIZE=1024
55 VMDISK_FILESYSTEM=
56 VMDISK_MOUNT_OPTIONS=__default
57 VMDISK_CLEAN=
58
59 # zvm specific?
60 VM_WORKER_NR=
61
62 # kvm specific?
63 HUGETLBFSPATH=
64
65 # emulator specific?
66 EMULATOR_SCRIPT=
67
68 for i in ec2 emulator kvm lxc openstack qemu uml xen zvm docker pvm; do
69     . "$BUILD_DIR/build-vm-$i"
70 done
71
72 VM_WATCHDOG=
73 VM_WATCHDOG_PID=
74
75 # the following functions just call the corresponding vm versions
76 vm_kill() {
77     vm_kill_$VM_TYPE "$@"
78 }
79
80 vm_verify_options() {
81     vm_verify_options_$VM_TYPE "$@"
82 }
83
84 vm_attach_root() {
85     vm_attach_root_$VM_TYPE "$@"
86 }
87
88 vm_attach_swap() {
89     vm_attach_swap_$VM_TYPE "$@"
90 }
91
92 vm_detach_root() {
93     vm_detach_root_$VM_TYPE "$@"
94 }
95
96 vm_detach_swap() {
97     vm_detach_swap_$VM_TYPE "$@"
98 }
99
100 vm_fixup() {
101     vm_fixup_$VM_TYPE "$@"
102 }
103
104 vm_startup() {
105     vm_startup_$VM_TYPE "$@"
106 }
107
108 vm_kill() {
109     vm_kill_$VM_TYPE "$@"
110 }
111
112 vm_cleanup() {
113     kill_watchdog
114     vm_cleanup_$VM_TYPE "$@"
115 }
116
117 vm_parse_options() {
118     case ${PARAM/#--/-} in
119       -vm-emulator-script|-emulator-script)
120         needarg
121         EMULATOR_SCRIPT="$ARG"
122         shift
123       ;;
124       -xen|-kvm|-uml|-qemu|-emulator)
125         VM_TYPE=${PARAM##*-}
126         test -z "$VM_IMAGE" && VM_IMAGE=1
127         if test -n "$ARG" ; then
128             VM_IMAGE="$ARG"
129             shift
130         fi
131       ;;
132       -zvm|-lxc)
133         VM_TYPE=${PARAM##*-}
134         shift
135       ;;
136       -vm-type)
137         needarg
138         VM_TYPE="$ARG"
139         case "$VM_TYPE" in
140             lxc|docker) ;;
141             ec2|xen|kvm|uml|qemu|emulator|openstack|zvm|pvm)
142                 test -z "$VM_IMAGE" && VM_IMAGE=1
143             ;;
144             none|chroot) VM_TYPE= ;;
145             *)
146                 echo "VM '$VM_TYPE' is not supported"
147                 cleanup_and_exit
148             ;;
149         esac
150         shift
151       ;;
152       -vm-worker)
153         needarg
154         VM_WORKER="$ARG"
155         shift
156       ;;
157       -vm-worker-nr|-vm-worker-no)
158         needarg
159         VM_WORKER_NR="$ARG"
160         shift
161       ;;
162       -vm-server|-vm-region)
163         needarg
164         VM_SERVER="$ARG"
165         shift
166       ;;
167       -vm-volumes)
168         needarg
169         VM_VOLUME_NAME="$ARG"
170         shift
171         ARG="$1"
172         test "$ARG" = "${ARG#-}" || ARG=
173         needarg
174         VM_VOLUME_SWAP="$ARG"
175         shift
176       ;;
177       -vm-disk)
178         needarg
179         VM_IMAGE="$ARG"
180         shift
181       ;;
182       -vm-swap|-xenswap|-swap)
183         needarg
184         VM_SWAP="$ARG"
185         shift
186       ;;
187       -vm-memory|-xenmemory|-memory)
188         needarg
189         VM_MEMSIZE="$ARG"
190         shift
191       ;;
192       -vm-kernel)
193         needarg
194         VM_KERNEL="$ARG"
195         shift
196       ;;
197       -vm-initrd)
198         needarg
199         VM_INITRD="$ARG"
200         shift
201       ;;
202       -vm-disk-size|-vmdisk-rootsize)
203         needarg
204         VMDISK_ROOTSIZE="$ARG"
205         shift
206       ;;
207       -vm-swap-size|-vmdisk-swapsize)
208         needarg
209         VMDISK_SWAPSIZE="$ARG"
210         shift
211       ;;
212       -vm-disk-filesystem|-vmdisk-filesystem)
213         needarg
214         VMDISK_FILESYSTEM="$ARG"
215         shift
216       ;;
217       -vm-disk-mount-options|-vmdisk-mount-options)
218        needarg
219        # options needs to be quoted to handle argument which might start with "-o ..."
220        VMDISK_MOUNT_OPTIONS=$(echo $ARG | sed 's/^\"\(.*\)\"$/\1/g')
221        shift
222       ;;
223       -vm-disk-clean|-vmdisk-clean)
224         # delete old root/swap to get rid of the old blocks
225         VMDISK_CLEAN=true
226       ;;
227       -vm-hugetlbfs|-hugetlbfs)
228         needarg
229         HUGETLBFSPATH="$ARG"
230         shift
231       ;;
232       -vm-watchdog)
233         VM_WATCHDOG=true
234       ;;
235       -vm-user)
236         needarg
237         VM_USER="$ARG"
238         shift
239       ;;
240       -vm-enable-console)
241         VM_CONSOLE_INPUT=true
242       ;;
243       -vm-telnet)
244         needarg
245         VM_TELNET="$ARG"
246         shift
247       ;;
248       -vm-net)
249         needarg
250         VM_NETOPT=("${VM_NETOPT[@]}" "$ARG")
251         shift
252       ;;
253       -vm-netdev)
254         needarg
255         VM_NETDEVOPT=("${VM_NETDEVOPT[@]}" "$ARG")
256         shift
257       ;;
258       -vm-device)
259         needarg
260         VM_DEVICEOPT=("${VM_DEVICEOPT[@]}" "$ARG")
261         shift
262       ;;
263       -*)
264         return 1
265       ;;
266     esac
267     nextargs=("$@")
268     return 0
269 }
270
271
272 #
273 # shutdown the system from inside the VM
274 #
275 vm_shutdown() {
276     test -n "$VM_WATCHDOG" && echo "### WATCHDOG MARKER START ###"
277     cd /
278     test -n "$1" || set 1
279     if test -n "$VM_SWAP" -a -e "$VM_SWAP" ; then
280         swapoff "$VM_SWAP" 2>/dev/null
281         echo -n "BUILDSTATUS$1" >"$VM_SWAP"
282     fi
283     exec >&0 2>&0       # so that the logging tee finishes
284     sleep 1             # wait till tee terminates
285     test "$VM_TYPE" = lxc -o "$VM_TYPE" = docker && exit $1
286     kill -9 -1        # goodbye cruel world
287     if ! test -x /sbin/halt ; then
288         test -e /proc/sysrq-trigger || mount -n -tproc none /proc
289         sync
290         sleep 2 # like halt does
291         if test -e /proc/sysrq-trigger; then
292             echo o > /proc/sysrq-trigger
293             sleep 5 # wait for sysrq to take effect
294         else
295             echo "Warning: VM doesn't support sysrq and /sbin/halt not installed"
296         fi
297     else
298         sync    # halt from systemd is not syncing anymore.
299         halt -f -p
300     fi
301     echo "Warning: clean shut down of the VM didn't work"
302     exit $1     # init died...
303 }
304
305 vm_img_create() {
306     local img="$1"
307     local size="$2"
308
309     if test -e "${img}" ; then
310         local origsize=$(cat "${img}.size" 2> /dev/null)
311         if test -z "$origsize" -o "$origsize" != "$size" ; then
312             echo "Resizing $img (${size}M)"
313         fi
314     else
315         echo "Creating $img (${size}M)"
316         rm -f "${img}.size"
317     fi
318
319     mkdir -p "${img%/*}" || cleanup_and_exit 3
320     # truncate file to the desired size
321     dd if=/dev/zero of="$img" bs=1M count=0 seek="$size" || cleanup_and_exit 3
322     echo "$size" > "${img}.size"
323     # allocate blocks
324     if type -p fallocate > /dev/null ; then
325         fallocate -p -l "${size}M" "$img" 2> /dev/null
326         errout=$( fallocate -l "${size}M" "$img" 2>&1 )
327         if test $? != 0; then
328             echo $errout
329             if test "${errout/Operation not supported/}" = "$errout"; then
330                 # Do not fail on not support file systems, eg ext2 or ext3
331                 cleanup_and_exit 3
332             fi
333         fi
334     fi
335 }
336
337 vm_img_mkfs() {
338     local fs="$1"
339     local img="$2"
340     local mkfs tunefs
341     eval "mkfs=\"\$vm_img_mkfs_${fs}\""
342     eval "mkfs_exta_options=\"\$vm_img_mkfs_${fs}_extra\""
343     eval "tunefs=\"\$vm_img_tunefs_${fs}\""
344
345     if test -z "$mkfs"; then
346         echo "filesystem \"$fs\" is not supported"
347         cleanup_and_exit 3
348     fi
349
350     echo "Creating $fs filesystem on $img"
351     export MKE2FS_SYNC=0
352     if ! $mkfs $mkfs_exta_options "$img"; then
353         if test -z "$mkfs_exta_options"; then
354             cleanup_and_exit 3
355         else
356             echo "Format call failed, trying again without extra options..."
357             $mkfs "$img" || cleanup_and_exit 3
358         fi
359     fi
360     if test -n "$tunefs" ; then
361         $tunefs "$img" || cleanup_and_exit 3
362     fi
363 }
364
365 background_monitor_process() {
366     max_disk=0
367     max_mem=0
368     while sleep 5; do
369         test -e /.build/_statistics.exit  && exit 0
370
371         # memory usage
372         if test -e /proc/meminfo ; then
373             memtotal=0
374             while read key value unit; do
375                 case $key in
376                     MemTotal:|SwapTotal:) memtotal=$(( $memtotal + $value )) ;;
377                     MemFree:|SwapFree:|SwapCached:|Cached:|Buffers:) memtotal=$(( $memtotal - $value )) ;;
378                 esac
379             done < /proc/meminfo
380             if test ${memtotal} -gt $max_mem ; then
381                 max_mem="${memtotal}"
382                 echo -n $(( $max_mem / 1024 )) > /.build/_statistics.memory.new && mv /.build/_statistics.memory.new /.build/_statistics.memory
383             fi
384         fi
385
386         # disk storage usage
387         if type -p df >& /dev/null; then
388             c=(`df -m / 2>/dev/null | tail -n 1`)
389
390             if test ${c[2]} -gt $max_disk ; then
391                 max_disk="${c[2]}"
392                 echo -n $max_disk > /.build/_statistics.df.new && mv /.build/_statistics.df.new /.build/_statistics.df
393             fi
394         fi
395     done
396 }
397
398 background_watchdog() {
399     WATCHDOG_START=
400     WATCHDOG_TIMEOUT=300
401     while sleep 5 ; do
402         WATCH=`grep -a "### WATCHDOG MARKER" "$LOGFILE" | tail -n 1`
403         case $WATCH in
404             *WATCHDOG\ MARKER\ START*) test -n "$WATCHDOG_START" || WATCHDOG_START=`date +%s` ;;
405             *WATCHDOG\ MARKER\ END*) WATCHDOG_START= ;;
406         esac
407         if test -n "$WATCHDOG_START" ; then
408             NOW=`date +%s`
409             ELAPSED=$((NOW-WATCHDOG_START))
410             if test $ELAPSED -gt $WATCHDOG_TIMEOUT ; then
411                 # kill the VM
412                  echo "### WATCHDOG TRIGGERED, KILLING VM ###"
413             fuser -k -TERM "$VM_IMAGE"
414             exit 0
415        fi
416     fi
417     done
418 }
419
420 start_watchdog() {
421     local wf=$(mktemp)
422     ( background_watchdog & echo $! > "$wf" )
423     read VM_WATCHDOG_PID < "$wf"
424     rm -f "$wf"
425 }
426
427 kill_watchdog() {
428     test -n "$VM_WATCHDOG_PID" && kill "$VM_WATCHDOG_PID"
429     VM_WATCHDOG_PID=
430 }
431
432 vm_set_personality_syscall() {
433     local archname
434     archname=`perl -V:archname 2>/dev/null`
435     archname="${archname#archname=?}"
436     case "$archname" in
437         x86_64*) PERSONALITY_SYSCALL=135 ;;
438         alpha*) PERSONALITY_SYSCALL=324 ;;
439         sparc*) PERSONALITY_SYSCALL=191 ;;
440         ia64*) PERSONALITY_SYSCALL=1140 ;;
441         i?86*|ppc*|aarch64*|arm*|sh4|cris|m68k*|s390*|unicore32|microblaze)   PERSONALITY_SYSCALL=136 ;;
442         *) echo "Unknown architecture personality: '$archname'"; cleanup_and_exit 1 ;;
443     esac
444 }
445
446 # used before calling kvm or xen
447 linux64() {
448     perl -e 'syscall('$PERSONALITY_SYSCALL', 0); exec(@ARGV) || die("$ARGV[0]: $!\n")' "$@"
449 }
450
451 vm_detect_2nd_stage() {
452     if test ! -e /.build/build.data -o -n "$BUILD_IGNORE_2ND_STAGE" ; then
453         return 1
454     fi
455     . /.build/build.data
456     if test -z "$VM_TYPE" ; then
457         return 1
458     fi
459     if test $$ -eq 1 || test $$ -eq 2 ; then
460         # ignore special init signals if we're init
461         # we're using ' ' instead of '' so that the signal handlers
462         # are reset in the child processes
463         trap ' ' HUP TERM
464         $0 "$@"
465         cleanup_and_exit $?
466     fi
467
468     test -n "$VM_WATCHDOG" -a -z "$PERSONALITY_SET" && echo "### WATCHDOG MARKER END ###"
469     echo "2nd stage started in virtual machine"
470     BUILD_ROOT=/
471     BUILD_DIR=/.build
472     echo "machine type: `uname -m`"
473     if test "$PERSONALITY" != 0 -a -z "$PERSONALITY_SET" ; then
474         export PERSONALITY_SET=true
475         echo "switching personality to $PERSONALITY..."
476         # this is 32bit perl/glibc, thus the 32bit syscall number
477         exec perl -e 'syscall(136, '$PERSONALITY') == -1 && warn("personality: $!\n");exec "/.build/build" || die("/.build/build: $!\n")'
478     fi
479     RUNNING_IN_VM=true
480     test -e /proc/version || mount -orw -n -tproc none /proc
481     if test "$VM_TYPE" != lxc -a "$VM_TYPE" != docker ; then
482         mount -n ${VMDISK_MOUNT_OPTIONS},remount,rw /
483     fi
484     umount /run >/dev/null 2>&1
485     # mount /sys
486     if ! test -e /sys/block; then
487         mkdir -p /sys
488         mount -orw -n -tsysfs sysfs /sys
489         # Docker already has sysfs mounted ro elsewhere,
490         # need to remount rw explicitly.
491         mount -o remount,rw sysfs /sys
492     fi
493 # qemu inside of xen does not work, check again with kvm later before enabling this
494 #    if test -e /dev/kqemu ; then
495 #        # allow abuild user to run qemu
496 #        chmod 0666 /dev/kqemu
497 #    fi
498
499     if test -n "$VM_SWAP" ; then
500         for i in 1 2 3 4 5 6 7 8 9 10 ; do
501             test -e "$VM_SWAP" && break
502             test $i = 1 && echo "waiting for $VM_SWAP to appear"
503             echo -n .
504             sleep 1
505         done
506         test $i = 1 || echo
507         # recreate the swap device manually if it didn't exist for some
508         # reason, hardcoded to hda2 atm
509         if ! test -b "$VM_SWAP" ; then
510             rm -f "$VM_SWAP"
511             umask 027
512             mknod "$VM_SWAP" b 3 2
513             umask 022
514         fi
515         # Do not rely on external system writing the signature, it might differ...
516         mkswap "$VM_SWAP"
517         swapon -v "$VM_SWAP" || exit 1
518     fi
519     HOST="$MYHOSTNAME"
520
521     # repair dracut damage, see bsc#922676
522     test -L /var/run -a ! -e /var/run && rm -f /var/run
523     test -L /var/lock -a ! -e /var/lock && rm -f /var/lock
524
525     # fork a process monitoring max filesystem usage during build
526     if test "$DO_STATISTICS" = 1 ; then
527         rm -f /.build/_statistics.exit
528         ( background_monitor_process & )
529     fi
530
531     if test ! -e /dev/.udev ; then
532         echo "WARNING: udev not running, creating extra device nodes"
533         test -e /dev/fd || ln -sf /proc/self/fd /dev/fd
534         test -e /etc/mtab || ln -sf /proc/mounts /etc/mtab
535     fi
536
537     # set date to build start on broken systems (now < build start)
538     if test $(date '+%s') -lt $(date -r /.build/.date '+%s') ; then
539         echo -n "WARNING: system has a broken clock, setting it to a newer time: "
540         date -s `cat /.build/.date`
541     fi
542
543     return 0
544 }
545
546 vm_set_filesystem_type() {
547     if test -z "$VMDISK_FILESYSTEM" -a -n "$BUILD_DIST" ; then 
548         VMDISK_FILESYSTEM=`queryconfig --dist "$BUILD_DIST" --configdir "$CONFIG_DIR" --archpath "$BUILD_ARCH" buildflags vmfstype`
549     fi   
550     test -n "$VMDISK_FILESYSTEM" || VMDISK_FILESYSTEM=ext3
551 }
552
553 vm_set_mount_options() {
554     if test "$VMDISK_MOUNT_OPTIONS" = __default; then
555         if test "$VMDISK_FILESYSTEM" = reiserfs ; then
556             VMDISK_MOUNT_OPTIONS='-o data=writeback,commit=150,noatime'
557         elif test "$VMDISK_FILESYSTEM" = btrfs ; then
558             VMDISK_MOUNT_OPTIONS='-o nobarrier,noatime'
559         elif test "$VMDISK_FILESYSTEM" = "ext4" ; then
560             VMDISK_MOUNT_OPTIONS='-o noatime'
561         elif test "$VMDISK_FILESYSTEM" = "ext3" ; then
562             VMDISK_MOUNT_OPTIONS='-o data=writeback,nobarrier,commit=150,noatime'
563         elif test "$VMDISK_FILESYSTEM" = "ext2" ; then
564             VMDISK_MOUNT_OPTIONS='-o noacl,noatime'
565         elif test "$VMDISK_FILESYSTEM" = "xfs" ; then
566             VMDISK_MOUNT_OPTIONS='-o noatime'
567         else
568             VMDISK_MOUNT_OPTIONS='-o noatime'
569         fi
570     fi
571 }
572
573 #
574 # create file system and swap space, mount file system to $BUILD_ROOT
575 #
576 vm_setup() {
577     vm_set_filesystem_type
578     vm_set_mount_options
579     if test "$VM_IMAGE" = 1 ; then
580         VM_IMAGE="$BUILD_ROOT.img"
581         if test -z "$VM_SWAP" -a "$VM_TYPE" != emulator; then
582             VM_SWAP="$BUILD_ROOT.swap"
583         fi
584         echo "VM_IMAGE: $VM_IMAGE, VM_SWAP: $VM_SWAP"
585     else
586         echo "VM_IMAGE: $VM_IMAGE, VM_SWAP: $VM_SWAP"
587         vm_attach_root
588     fi
589     # this should not be needed, but sometimes a xen instance got lost
590     test "$VM_TYPE" = xen && vm_purge_xen
591     if test -n "$VMDISK_CLEAN" ; then
592         # delete old root/swap to get rid of the old blocks
593         if test -n "$VM_IMAGE" -a -f "$VM_IMAGE" ; then
594             echo "Deleting old $VM_IMAGE"
595             rm -rf "$VM_IMAGE"
596         fi
597         if test -n "$VM_SWAP" -a -f "$VM_SWAP" ; then
598             echo "Deleting old $VM_SWAP"
599             rm -rf "$VM_SWAP"
600         fi
601     fi
602     test -b "$VM_IMAGE" || vm_img_create "$VM_IMAGE" "$VMDISK_ROOTSIZE"
603     if test -z "$CLEAN_BUILD" ; then
604         vm_img_mkfs "$VMDISK_FILESYSTEM" "$VM_IMAGE"
605     fi
606     if test -n "$VM_SWAP" -a ! -b "$VM_SWAP" ; then
607         vm_img_create "$VM_SWAP" "$VMDISK_SWAPSIZE"
608     fi
609     if test ! -e "$VM_IMAGE" ; then
610         echo "you need to create $VM_IMAGE first"
611         cleanup_and_exit 3
612     fi
613     if test -n "$CLEAN_BUILD" ; then
614         vm_img_mkfs "$VMDISK_FILESYSTEM" "$VM_IMAGE" || cleanup_and_exit 3
615     fi
616     # now mount root/swap
617     mkdir_build_root
618     if test -w /root ; then
619         if test -b $VM_IMAGE ; then
620             # mount device directly
621             mount $VMDISK_MOUNT_OPTIONS $VM_IMAGE $BUILD_ROOT || cleanup_and_exit 3
622         else
623             mount ${VMDISK_MOUNT_OPTIONS},loop $VM_IMAGE $BUILD_ROOT || cleanup_and_exit 3
624         fi
625     else
626         if ! mount $BUILD_ROOT; then
627             echo "mounting the build root failed. An fstab entry is probably missing or incorrect."
628             echo "/etc/fstab should contain an entry like this:"
629             echo "$VM_IMAGE $BUILD_ROOT auto noauto,user,loop 0 0"
630             cleanup_and_exit 3
631         fi
632     fi
633     if test -n "$VM_SWAP" ; then
634         vm_attach_swap
635         dd if=/dev/zero of="$VM_SWAP" bs=1024 count=1 conv=notrunc 2>/dev/null
636         vm_detach_swap
637         # mkswap happens inside of the vm
638     fi
639 }
640
641 vm_update_hostarch() {
642     local kernel="$vm_kernel"
643     local hostarchfile
644     local newhostarch
645     if test -z "$VM_KERNEL" -a -e "$BUILD_ROOT/.build.kernel.$VM_TYPE" ; then
646         kernel="$BUILD_ROOT/.build.kernel.$VM_TYPE"
647         hostarchfile="$BUILD_ROOT/.build.hostarch.$VM_TYPE"
648     elif test -n "$kernel" -a -e "$kernel" -a -e "$kernel.hostarch" ; then
649         hostarchfile="$kernel.hostarch"
650     fi
651     if test -n "$hostarchfile" -a -e "$hostarchfile"; then
652         newhostarch=`cat "$hostarchfile"`
653     elif test -n "$kernel" -a -e "$kernel" ; then
654         case `objdump -f "$kernel" | sed -ne 's/.*file format //p'` in
655             elf64-powerpcle) newhostarch=ppc64le ;;
656             elf64-powerpc) newhostarch=ppc64 ;;
657         esac
658     fi
659     if test -n "$newhostarch" -a "$newhostarch" != "$BUILD_HOST_ARCH" ; then
660         echo "setting hostarch to $newhostarch"
661         BUILD_HOST_ARCH="$newhostarch"
662         # update BUILD_INITVM_ARCH
663         build_host_arch
664     fi
665 }
666
667 #
668 # prepare for vm startup
669 #
670 vm_first_stage() {
671     vm_set_personality_syscall
672     rm -rf "$BUILD_ROOT/.build"
673     mkdir -p "$BUILD_ROOT/.build"
674     TIME_PREINSTALL=
675     if test "$DO_INIT" = true ; then
676         # do first stage of init_buildsystem
677         rm -f $BUILD_ROOT/.build.success
678         set -- init_buildsystem --configdir "$CONFIG_DIR" --cachedir "$CACHE_DIR" --prepare "${definesnstuff[@]}" "${repos[@]}" $CLEAN_BUILD $USEUSEDFORBUILD $RPMLIST "$MYSRCDIR/$RECIPEFILE" $ADDITIONAL_PACKS
679         echo "$* ..."
680         start_time=`date +%s`
681         "$@" || cleanup_and_exit 1
682         check_exit
683         TIME_PREINSTALL=$(( `date +%s` - $start_time ))
684         unset start_time
685         if test ! -w /root ; then
686             # remove setuid bit if files belong to user to make e.g. mount work
687             find $BUILD_ROOT/{bin,sbin,usr/bin,usr/sbin} -type f -uid $UID -perm +4000 -print0 | xargs -0 --no-run-if-empty chmod -s
688         fi
689         copy_oldpackages
690     fi
691
692     # start up VM, rerun ourself
693     cp -a $BUILD_DIR/. $BUILD_ROOT/.build
694     if ! test "$MYSRCDIR" = $BUILD_ROOT/.build-srcdir ; then
695         rm -rf "$BUILD_ROOT/.build-srcdir"
696         mkdir "$BUILD_ROOT/.build-srcdir"
697         if test "$BUILDTYPE" = kiwi ; then
698             cp -pRL "$MYSRCDIR"/* $BUILD_ROOT/.build-srcdir
699         else
700             cp -p "$MYSRCDIR"/* $BUILD_ROOT/.build-srcdir
701         fi
702         MYSRCDIR=$BUILD_ROOT/.build-srcdir
703     else
704         # cwd is at $BUILD_ROOT/.build-srcdir which we want to
705         # umount later so step aside
706         cd "$SRCDIR"
707     fi
708
709     # do vm specific fixups
710     vm_fixup
711
712     # update the hostarch
713     if test -n "$VM_IMAGE" ; then
714         vm_update_hostarch
715     fi
716
717     # the watchdog needs a log file
718     test -n "$LOGFILE" || VM_WATCHDOG=
719     # put our config into .build/build.data
720     Q="'\''"
721     echo "RECIPEFILE='${RECIPEFILE//"'"/$Q}'" > $BUILD_ROOT/.build/build.data
722     echo "BUILD_JOBS='${BUILD_JOBS//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
723     echo "BUILD_ARCH='${BUILD_ARCH//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
724     echo "BUILD_RPMS='${BUILD_RPMS//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
725     case $BUILD_DIST in
726         */*)
727             cp $BUILD_DIST $BUILD_ROOT/.build/build.dist
728             BUILD_DIST=/.build/build.dist
729             ;;
730     esac
731     echo "BUILD_DIST='${BUILD_DIST//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
732     echo "RELEASE='${RELEASE//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
733     echo "BUILD_DEBUG='${BUILD_DEBUG//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
734     echo "SIGNDUMMY='${SIGNDUMMY//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
735     echo "DO_LINT='${DO_LINT//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
736     echo "DO_CHECKS='${DO_CHECKS//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
737     echo "NOROOTFORBUILD='${NOROOTFORBUILD//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
738     echo "CREATE_BASELIBS='$CREATE_BASELIBS'" >> $BUILD_ROOT/.build/build.data
739     echo "REASON='${REASON//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
740     echo "CHANGELOG='${CHANGELOG//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
741     echo "INCARNATION='${INCARNATION//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
742     echo "DISTURL='${DISTURL//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
743     echo "DO_INIT='${DO_INIT//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
744     echo "DO_INIT_TOPDIR='${DO_INIT_TOPDIR//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
745     echo "KIWI_PARAMETERS='${KIWI_PARAMETERS//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
746     echo "VM_TELNET='${VM_TELNET//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
747     echo "VM_WORKER='${VM_WORKER}'" >> $BUILD_ROOT/.build/build.data
748     echo "VM_WORKER_NR='${VM_WORKER_NR}'" >> $BUILD_ROOT/.build/build.data
749     echo "VM_NETDEVOPT='${VM_NETDEVOPT}'" >> $BUILD_ROOT/.build/build.data
750     echo "VM_DEVICEOPT='${VM_DEVICEOPT}'" >> $BUILD_ROOT/.build/build.data
751     echo "VM_CONSOLE_INPUT='${VM_CONSOLE_INPUT//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
752     test -n "$VM_SWAP" && echo "VM_SWAP='${VM_SWAPDEV//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
753     test -n "$VMDISK_MOUNT_OPTIONS" && echo "VMDISK_MOUNT_OPTIONS='${VMDISK_MOUNT_OPTIONS//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
754     PERSONALITY=0
755     test -n "$PERSONALITY_SYSCALL" && PERSONALITY=`perl -e 'print syscall('$PERSONALITY_SYSCALL', 0)."\n"'`
756     test "$PERSONALITY" = -1 && PERSONALITY=0   # syscall failed?
757     case $(uname -m) in
758         ppc|ppcle|s390) PERSONALITY=8 ;;        # ppc/s390 kernel never tells us if a 32bit personality is active, assume we run on 64bit
759         aarch64) test "$BUILD_ARCH" != "${BUILD_ARCH#armv[567]}" && PERSONALITY=8 ;; # workaround, to be removed
760     esac
761     test "$VM_TYPE" = lxc -o "$VM_TYPE" = docker && PERSONALITY=0
762     echo "PERSONALITY='$PERSONALITY'" >> $BUILD_ROOT/.build/build.data
763     echo "MYHOSTNAME='`hostname`'" >> $BUILD_ROOT/.build/build.data
764     echo -n "definesnstuff=(" >> $BUILD_ROOT/.build/build.data
765     shellquote "${definesnstuff[@]}" >> $BUILD_ROOT/.build/build.data
766     echo ")" >> $BUILD_ROOT/.build/build.data
767     echo -n "repos=(" >> $BUILD_ROOT/.build/build.data
768     shellquote "${repos[@]}" >> $BUILD_ROOT/.build/build.data
769     echo ")" >> $BUILD_ROOT/.build/build.data
770     echo "VM_TYPE='$VM_TYPE'" >> $BUILD_ROOT/.build/build.data
771     echo "RUN_SHELL='$RUN_SHELL'" >> $BUILD_ROOT/.build/build.data
772     echo "DO_STATISTICS='$DO_STATISTICS'" >> $BUILD_ROOT/.build/build.data
773     echo "TIME_PREINSTALL='$TIME_PREINSTALL'" >> $BUILD_ROOT/.build/build.data
774     echo "VM_WATCHDOG='$VM_WATCHDOG'" >> $BUILD_ROOT/.build/build.data
775     echo "BUILDENGINE='$BUILDENGINE'" >> $BUILD_ROOT/.build/build.data
776     echo "CCACHE='$CCACHE'" >> $BUILD_ROOT/.build/build.data
777     echo "ABUILD_TARGET='$ABUILD_TARGET'" >> $BUILD_ROOT/.build/build.data
778         # use the rpmbuild --stage option
779      if [ ! -z $BUILD_RPM_BUILD_STAGE ]; then
780                 if [[ "$BUILD_RPM_BUILD_STAGE" =~ ^- ]]; then
781                         echo "BUILD_RPM_BUILD_STAGE='$BUILD_RPM_BUILD_STAGE'" >> $BUILD_ROOT/.build/build.data
782                 else
783                         echo "BUILD_RPM_BUILD_STAGE='-$BUILD_RPM_BUILD_STAGE'" >> $BUILD_ROOT/.build/build.data
784                 fi
785         fi
786
787     # fallback time for broken hosts
788     date '+@%s' > $BUILD_ROOT/.build/.date
789     # we're done with the root file system, unmount
790     umount -n $BUILD_ROOT/proc/sys/fs/binfmt_misc 2> /dev/null || true
791     umount -n $BUILD_ROOT/proc 2> /dev/null || true
792     umount -n $BUILD_ROOT/dev/pts 2> /dev/null || true
793     umount -n $BUILD_ROOT/dev/shm 2> /dev/null || true
794     umount -n $BUILD_ROOT/mnt 2> /dev/null || true
795
796     vm_init_script="/.build/build"
797     if check_use_emulator ; then
798         vm_init_script="/.build/$INITVM_NAME"
799     fi
800     if test -n "$VM_IMAGE" ; then
801         # copy out kernel & initrd (if they exist) during unmounting VM image
802         KERNEL_TEMP_DIR=
803         if test -z "$VM_KERNEL" -a -e "$BUILD_ROOT/.build.kernel.$VM_TYPE" ; then
804             KERNEL_TEMP_DIR=`mktemp -d`
805             cp "$BUILD_ROOT/.build.kernel.$VM_TYPE" "$KERNEL_TEMP_DIR/kernel"
806             if test -e  "$BUILD_ROOT/.build.initrd.$VM_TYPE" ; then
807                 cp "$BUILD_ROOT/.build.initrd.$VM_TYPE" "$KERNEL_TEMP_DIR/initrd"
808             fi
809         fi
810         check_exit
811         # needs to work otherwise we have a corrupted file system
812         if ! umount $BUILD_ROOT; then
813             rm -rf "$KERNEL_TEMP_DIR"
814             cleanup_and_exit 3
815         fi
816         # copy back the kernel and set it for VM
817         if test -n "$KERNEL_TEMP_DIR" ; then
818             mkdir -p "$BUILD_ROOT/boot"
819             mv "$KERNEL_TEMP_DIR/kernel" "$BUILD_ROOT/boot/kernel"
820             vm_kernel="$BUILD_ROOT/boot/kernel"
821             if test -e "$KERNEL_TEMP_DIR/initrd" ; then
822                 mv "$KERNEL_TEMP_DIR/initrd" "$BUILD_ROOT/boot/initrd"
823                 test -z "$VM_INITRD" && vm_initrd="$BUILD_ROOT/boot/initrd"
824             fi
825             rmdir "$KERNEL_TEMP_DIR"
826         fi
827     fi
828     vm_detach_root
829
830     # start watchdog if requested
831     if test -n "$VM_WATCHDOG" ; then
832         start_watchdog
833         echo "### WATCHDOG MARKER START ###"
834     fi
835
836     echo "booting $VM_TYPE..."
837     vm_startup
838
839     # kill watchdog again
840     if test -n "$VM_WATCHDOG" ; then
841         echo "### WATCHDOG MARKER END ###"
842         kill_watchdog
843     fi
844
845     vm_attach_root
846     if test -n "$VM_SWAP" ; then
847         vm_attach_swap
848         BUILDSTATUS=`dd if="$VM_SWAP" bs=12 count=1 2>/dev/null`
849         case $BUILDSTATUS in
850           BUILDSTATUS[02])
851             mkdir -p $BUILD_ROOT/.build.packages
852             cd $BUILD_ROOT/.build.packages || cleanup_and_exit 1
853             echo "build: extracting built packages..."
854             extractbuild --disk "$VM_IMAGE" --input "$VM_SWAP" --skip 512 -v || cleanup_and_exit 3
855             if test "$DO_STATISTICS" = 1 ; then
856                 mkdir -p OTHER
857                 TIME_TOTAL=$(( `date +%s` - $TIME_START_TIME ))
858                 echo "TIME_total: $TIME_TOTAL"  >> OTHER/_statistics
859             fi
860             cleanup_and_exit ${BUILDSTATUS#BUILDSTATUS}
861             ;;
862           BUILDSTATUS*)
863             cleanup_and_exit ${BUILDSTATUS#BUILDSTATUS}
864             ;;
865           *)
866             echo "No buildstatus set, either the base system is broken (kernel/initrd/udev/glibc/bash/perl)"
867             echo "or the build host has a kernel or hardware problem..."
868             cleanup_and_exit 3
869             ;;
870         esac
871         cleanup_and_exit 1
872     fi
873 }
874
875 vm_save_statistics() {
876     echo "... saving statistics"
877     local sys_mounted otherdir
878     otherdir="$BUILD_ROOT$TOPDIR/OTHER"
879     test -n "$TIME_PREINSTALL" && echo "TIME_preinstall: $TIME_PREINSTALL"  >> $otherdir/_statistics
880     test -n "$TIME_INSTALL" && echo "TIME_install: $TIME_INSTALL"  >> $otherdir/_statistics
881     if test -e /.build/_statistics.df ; then
882         echo -n "MAX_mb_used_on_disk: " >> $otherdir/_statistics
883         cat /.build/_statistics.df >> $otherdir/_statistics
884         echo "" >> $otherdir/_statistics
885         rm /.build/_statistics.df
886     fi
887     if test -e /.build/_statistics.memory ; then
888         echo -n "MAX_mb_used_memory: " >> $otherdir/_statistics
889         cat /.build/_statistics.memory >> $otherdir/_statistics
890         echo "" >> $otherdir/_statistics
891         rm /.build/_statistics.memory
892     fi
893     if ! test -e /sys/block; then
894         mkdir -p /sys
895         mount -n sys /sys -t sysfs
896         sys_mounted=1
897     fi
898     device="hda1"
899     test -e /dev/sda && device="sda"
900     test -e /dev/vda && device="vda"
901     test -e /dev/dasda && device="dasda" # in z/VM
902     test -e /dev/nfhd0 && device="nfhd0" # in aranym
903     if test -e /sys/block/${device}/stat ; then
904         disk=(`cat /sys/block/${device}/stat`)
905         test "0${disk[0]}" -gt 0 && echo "IO_requests_read: ${disk[0]}"  >> $otherdir/_statistics
906         test "0${disk[2]}" -gt 0 && echo "IO_sectors_read: ${disk[2]}"   >> $otherdir/_statistics
907         test "0${disk[4]}" -gt 0 && echo "IO_requests_write: ${disk[4]}" >> $otherdir/_statistics
908         test "0${disk[6]}" -gt 0 && echo "IO_sectors_write: ${disk[6]}"  >> $otherdir/_statistics
909     else
910         echo "ERROR: no root disk device found, yet another new device name?"
911         ls -l /sys/block/
912     fi
913     test -n "$sys_mounted" && umount /sys
914 }
915
916 # args: resultdirs
917 vm_wrapup_build() {
918     test "$DO_STATISTICS" = 1 && vm_save_statistics
919     if test -n "$VM_SWAP"; then
920         echo "... saving built packages"
921         swapoff "$VM_SWAP"
922         pushd "$BUILD_ROOT$TOPDIR" >/dev/null
923         find "$@" -print0 | computeblocklists --padstart 512 --padend 512 -v --manifest - -0 > "$VM_SWAP"
924         popd >/dev/null
925     fi
926 }