update to upstream 20150115
[tools/build.git] / build-vm-zvm
1 #
2 # z/VM specific functions
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 # z/VM: use default kernel image from local machine
25 # lets go with the default parameters. However zvm_initrd will be a required parameter
26 #zvm_kernel=/boot/image
27 #zvm_initrd=/boot/initrd_worker
28 zvm_param="root=/dev/disk/by-path/ccw-0.0.0150-part1 hvc_iucv=8 console=hvc0"
29 zvm_mult_pass="THR4ME"
30 zvm_init_script="/.build/build"
31
32 #######################################################################################
33
34 # this once was in zvm_functions
35
36 zvm_fatal() {
37     echo "$1"
38     test -n "$ZVM_CLEANUP" && exit 1
39     cleanup_and_exit 1
40 }
41
42 prevent_detach() {
43     if test "$1" = "150" -o "$1" = "0150"; then
44         zvm_fatal "don't detach local root"
45     fi
46 }
47
48 zvm_memset() {
49     # defining the worker also resets the operating system. Be careful
50     # $1: user name
51     # $2: amount in MB
52     # Note, that this is also limited by the worker definition in the user directory
53     if test -n "$2"; then
54         if ! vmcp send $1 define storage ${2}M ; then
55             zvm_fatal "Could not redefine storage of $1 to ${2}M"
56         fi
57     fi
58 }
59
60 zvm_logon() {
61     # kill machine if it already runs
62     # autolog machine
63     # Needs machine name as $1
64     if test -n "$1" ; then
65         if $(vmcp q "$1" >& /dev/null) ; then
66             vmcp force $1
67             sleep 1
68         fi
69         if ! $(vmcp q "$1" >& /dev/null) ; then
70             if ! $(vmcp xautolog $1 >& /dev/null) ; then
71                 zvm_fatal "Could not start machine $1. Is $1 defined in the user directory?"
72             else
73                 # give the worker a moment to initialize
74                 sleep 2
75                 zvm_memset $1 $VM_MEMSIZE
76                 sleep 2
77             fi
78         fi
79     fi
80 }
81
82 zvm_ipl() {
83     # IPL worker. Needs user as $1 and ipl device as $2.
84     if test -n "$1" -a -n "$2" ; then
85         if ! $(vmcp q "$1" >& /dev/null); then
86             zvm_fatal "User $1 not logged on."
87         else
88             if ! $(vmcp send $1 ipl $2); then
89                  zvm_fatal "Could not send command to $1"
90             fi
91         fi
92     else
93         zvm_fatal "Not enough arguments for ipl. Need user and device number."
94     fi
95 }
96
97
98 zvm_destroy() {
99     # Destroy build. Done by killing the worker machine.
100     # needs user as $1
101     if test -n "$1"; then
102         if ! $(vmcp force $1 ) ; then
103             zvm_fatal "Could not force $1"
104         fi
105     fi
106 }
107
108 zvm_get_local_devnr() {
109     # $1 is base address, either 150 or 250
110     # $2 is worker number
111     # there is room for up to 100 workers for this controlling guest, however in our setup I expect only up to 10 workers.
112     #echo "Debug: zvm_get_local_devnr: arg1: $1 arg2: $2"
113     if test "$2" -ge 100 ; then
114         zvm_fatal "Not more than 100 workers supported by one controlling guest."
115     fi
116     if test "$1" = "0150" -o "$1" = "150" ; then 
117         DEVNR=$((300+$2))
118     else
119         if test "$1" = "0250" -o "$1" = "250" ; then 
120             DEVNR=$((400+$2))
121         else
122             zvm_fatal "The disk devices for root and swap must be 150 and 250 respectively."
123         fi
124     fi
125     echo $DEVNR
126 }
127
128 zvm_volume_link_local() {
129     # attach worker disk to local system as preparation for 
130     # a) prepare worker for build
131     # b) get rpms of the swap disk after build finished
132     # disk must be detached from worker first
133     # The following arguments are needed:
134     # 1. Worker user name
135     # 2. Worker disk device number
136     # 3. Mult password for the disk
137     # 4. Worker number to generate a uniq local device number
138     if test -n "$4"; then
139         DEVNR=$(zvm_get_local_devnr $2 $4)
140         if ! vmcp link $1 $2 $DEVNR MW pass=THR4ME >& /dev/null ; then
141             zvm_fatal "Could not link disk $2 from user $1 to local device $DEVNR."
142         fi
143         dasd_configure 0.0.0$DEVNR 1 0 >& /dev/null
144         udevadm settle
145         DEVICE=$(ls /sys/bus/ccw/devices/0.0.0$DEVNR/block/)
146         if ! test -b /dev/${DEVICE}1 ; then
147             zvm_fatal "The device /sys/bus/ccw/devices/0.0.0$DEVNR has not been setup correctly."
148         fi
149         echo "${DEVICE}1"
150     else
151         zvm_fatal "Not enough arguments given to volume_link_local."
152     fi 
153 }
154
155 zvm_volume_detach_local() {
156     # we need
157     # 1. worker device number
158     # 2. worker number
159     DEVNR=$(zvm_get_local_devnr $1 $2)
160     prevent_detach $DEVNR
161     dasd_configure 0.0.0$DEVNR 0 0
162     if ! vmcp detach $DEVNR >& /dev/null ; then
163         zvm_fatal "Could not locally detach disk number $1 from worker $2"
164     fi
165 }
166
167 zvm_volume_attach() {
168     # link the local disk of the worker 
169     # $1: user name
170     # $2: disk device number
171     # send link * nr nr
172     if ! vmcp send $1 link \* $2 $2 ; then
173         zvm_fatal "Could not link remote worker disk number $2 from user $1"
174     fi 
175 }
176
177 zvm_volume_detach() {
178     # send machine detach nr
179     # $1: user name
180     # $2: disk
181     if ! vmcp send $1 detach $2 ; then
182         zvm_fatal "Could not detach disk $2 on worker $1"
183     fi
184 }
185
186 zvm_worker_init() {
187     # 1. Worker user name
188     # 2. Worker root device number
189     # 3. Worker swap device number
190     # 4. Worker number to generate a uniq local device number
191     # Check for: 
192     # - still mounted dasd
193     # - configured dasd
194     # - linked dasd
195     # - reset worker with force and autolog 
196     DEVNR_ROOT=$(zvm_get_local_devnr $2 $4) 
197     DEVNR_SWAP=$(zvm_get_local_devnr $3 $4)
198     # First, check for mounts:
199     for DEVNR in $DEVNR_ROOT $DEVNR_SWAP ; do
200         if test -d /sys/bus/ccw/devices/0.0.0$DEVNR/block ; then
201             DEV=$(ls /sys/bus/ccw/devices/0.0.0$DEVNR/block/)
202             echo "Found device of worker $1 available at $DEVNR, device is /dev/$DEV."
203             grep "/dev/$DEV" /proc/mounts >& /dev/null && umount /dev/${DEV}1
204         fi
205     done
206     # Second, check if devices are online
207     for DEVNR in $DEVNR_ROOT $DEVNR_SWAP ; do
208         lsdasd $DEVNR | grep $DEVNR && dasd_configure 0.0.0$DEVNR 0 0
209     done
210     # Third, remove stale links
211     for DEVNR in $DEVNR_ROOT $DEVNR_SWAP ; do
212         prevent_detach $DEVNR
213         if vmcp q v $DEVNR 2> /dev/null ; then
214             vmcp detach $DEVNR
215         fi
216     done
217     # Fourth, reset worker
218     zvm_logon $1
219 }
220
221 zvm_cp() {
222     modprobe vmcp || zvm_fatal "Cannod load vmcp module"
223     if test -n "$1" ; then
224         case "$1" in 
225             start)                shift ; zvm_logon "$@"         ;;
226             ipl)                  shift ; zvm_ipl "$@"           ;;
227             destroy)              shift ; zvm_destroy "$@"       ;;
228             volume_attach)        shift ; zvm_volume_attach "$@" ;;
229             volume_detach)        shift ; zvm_volume_detach "$@" ;;
230             volume_link_local)    shift ; zvm_volume_link_local "$@" ;;
231             volume_detach_local)  shift ; zvm_volume_detach_local "$@" ;;
232             memset)               shift ; zvm_memset "$@"        ;;
233             worker_init)          shift ; zvm_worker_init "$@"   ;;
234         esac
235     fi
236 }
237
238 #######################################################################################
239
240 vm_verify_options_zvm() {
241     VM_IMAGE=/dev/dasda1
242     VM_SWAP=/dev/dasdb1
243
244     VM_SWAPDEV=/dev/dasdb1      # in the vm
245
246     if test -z "$VM_VOLUME_ROOT" ; then
247         if test -n "$BUILD_ROOT" -a ${#BUILD_ROOT} -le 4 ; then
248             VM_VOLUME_ROOT="$BUILD_ROOT"
249         else
250             VM_VOLUME_ROOT="0150"
251         fi
252     fi
253     # In z/VM, this is a 4 digit hex number instead of a linux device.
254     # This is the swap disk defined in user direct
255     # This number can be given with the parameter --swap NR.
256     if test -z "$VM_VOLUME_SWAP" ; then
257         if test -n "$VM_SWAP" -a ${#VM_SWAP} -le 4 ; then
258             VM_VOLUME_SWAP="$VM_SWAP"
259         else
260             VM_VOLUME_SWAP="0250"
261         fi
262     fi
263     # z/VM guest name that is already defined in z/VM
264     if test -z "$VM_WORKER" ; then
265         echo "ERROR: No z/VM worker id specified"
266         cleanup_and_exit 3
267     fi
268     if test -z "$VM_WORKER_NR" ; then
269         echo "ERROR: No z/VM worker number specified"
270         cleanup_and_exit 3
271     fi
272     # need the name for a kernel in zvm
273     if test -n "$VM_KERNEL" ; then
274         vm_kernel="$VM_KERNEL"
275     elif test -e "/boot/vmlinux.gz" ; then
276         vm_kernel="/boot/vmlinux.gz"
277     else
278         echo "ERROR: No z/VM kernel specified"
279         cleanup_and_exit 3
280     fi
281     # need the name for an initrd in zvm
282     # this normally will not be the local initrd
283     if test -n "$VM_INITRD" ; then
284         vm_initrd="$VM_INITRD"
285     else
286         echo "ERROR: No z/VM initrd specified"
287         cleanup_and_exit 3
288     fi
289     zvm_cp worker_init $VM_WORKER $VM_VOLUME_ROOT $VM_VOLUME_SWAP $VM_WORKER_NR
290     zvm_cp volume_detach $VM_WORKER $VM_VOLUME_ROOT
291     zvm_cp volume_detach $VM_WORKER $VM_VOLUME_SWAP
292 }
293
294 vm_startup_zvm() {
295     # link root/swap to the worker
296     zvm_cp volume_attach $VM_WORKER $VM_VOLUME_ROOT
297     zvm_cp volume_attach $VM_WORKER $VM_VOLUME_SWAP
298     zvm_cp ipl $VM_WORKER $VM_VOLUME_ROOT
299     # start IUCV Console
300     # IPL needs some time until IPL really starts...
301     sleep 2
302     # start iucv console. This blocks until build process is finished.
303     iucvconn $VM_WORKER lnxhvc0
304     # sleep some time before taking root and swap devices from worker
305     # This might be critical regarding timing (IUCV_CONSOLE down, but machine still running)
306     sleep 5
307     zvm_cp volume_detach $VM_WORKER $VM_VOLUME_ROOT
308     zvm_cp volume_detach $VM_WORKER $VM_VOLUME_SWAP
309 }
310
311 vm_kill_zvm() {
312     if vmcp q "$VM_WORKER" > /dev/null 2>&1 ; then
313         if ! zvm_cp destroy $VM_WORKER ; then
314             echo "could not kill zvm worker $VM_WORKER"
315             cleanup_and_exit 1
316         fi
317     fi
318 }
319
320 vm_fixup_zvm() {
321     # initrd is created in obsstoragesetup.
322     # If it is desired to use a project dependent kernel, use make_guestinitrd from zvm_functions.
323     # have to copy kernel/initrd and run zipl to be able to IPL
324     # have to set init_script before unmounting, thus doing it statically for now.
325     zvm_init_script="/.build/build"
326     mkdir -p $BUILD_ROOT/boot
327     cp $vm_kernel $vm_initrd $BUILD_ROOT/boot
328     mkdir -p $BUILD_ROOT/boot/zipl
329     # finally, install bootloader to the worker disk
330     zipl -t $BUILD_ROOT/boot/zipl -i ${BUILD_ROOT}${vm_kernel} -r ${BUILD_ROOT}${vm_initrd} \
331         --parameters "${zvm_param} init=$zvm_init_script rootfsopts=noatime"
332 }
333
334 vm_attach_root_zvm() {
335     VM_IMAGE=$(ZVM_CLEANUP=1 zvm_cp volume_link_local $VM_WORKER $VM_VOLUME_ROOT $zvm_mult_pass $VM_WORKER_NR )
336     if test "${VM_IMAGE}" = "${VM_IMAGE#dasd}" ; then
337         echo "did not get a real device for VM_IMAGE: $VM_IMAGE"
338         cleanup_and_exit 3
339     fi
340     VM_IMAGE="/dev/$VM_IMAGE"
341 }
342
343 vm_attach_swap_zvm() {
344     VM_SWAP=$(ZVM_CLEANUP=1 zvm_cp volume_link_local $VM_WORKER $VM_VOLUME_SWAP $zvm_mult_pass $VM_WORKER_NR )
345     if test "${VM_SWAP}" = "${VM_SWAP#dasd}" ; then
346         echo "did not get a real device for VM_SWAP: $VM_SWAP"
347         cleanup_and_exit 3
348     fi
349     VM_SWAP="/dev/$VM_SWAP"
350 }
351
352 vm_detach_root_zvm () {
353     zvm_cp volume_detach_local $VM_VOLUME_ROOT $VM_WORKER_NR
354 }
355
356 vm_detach_swap_zvm() {
357     zvm_cp volume_detach_local $VM_VOLUME_SWAP $VM_WORKER_NR
358 }
359
360 vm_cleanup_zvm() {
361     if test -n "$VM_WORKER" -a -n "$VM_WORKER_NR" -a -n "$VM_VOLUME_ROOT" -a -n "$VM_VOLUME_SWAP" ; then
362         ZVM_CLEANUP=1
363         (zvm_cp volume_detach $VM_WORKER $VM_VOLUME_ROOT >/dev/null 2>&1)
364         (zvm_cp volume_detach $VM_WORKER $VM_VOLUME_SWAP >/dev/null 2>&1)
365         (zvm_cp volume_detach_local $VM_VOLUME_ROOT $VM_WORKER_NR >/dev/null 2>&1)
366         (zvm_cp volume_detach_local $VM_VOLUME_SWAP $VM_WORKER_NR >/dev/null 2>&1)
367     fi
368 }
369