Skip to content

Commit 1d93f71

Browse files
mahdiyehmrMirsharifi, Maya
authored andcommitted
Support importing preinstallimage as container image
Implement the option to user preinstallimage as base container image for podman and docker build environments. This speeds up the build process since there would be no need to untar the preinstallimage and install the packages inside it. It would only import the preinstallimage if it doesn't already find it implemented in preinstall_container_image(). For finding the package id and HDRMD5 of packages in preinstallimage it prioritizes the preinstallimageinfo and if not found it would fallback to previous method of reading unpacked preinstallimage. Adding randomization for container name in both podman and docker to avoid issues in concurrent builds.
1 parent 8a3bc72 commit 1d93f71

File tree

5 files changed

+177
-33
lines changed

5 files changed

+177
-33
lines changed

build

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ Known Parameters:
346346
347347
--vm-type TYPE
348348
Use virtual machine instead of chroot
349-
TYPE is one of xen|kvm|uml|qemu|lxc|zvm|openstack|ec2|docker|pvm|nspawn
349+
TYPE is one of xen|kvm|uml|qemu|lxc|zvm|openstack|ec2|docker|pvm|nspawn|podman
350350
351351
--vm-args ARGS
352352
Pass extra arguments to virtual machine
@@ -426,6 +426,11 @@ Known Parameters:
426426
Available options are -net, -netdev, -device
427427
(This options in kvm can not guarantee reproducible builds)
428428
429+
--vm-use-container-preinstallimage
430+
Use preinstall container image as base image in containers instead of
431+
using preinstall image tar file. This option is only available when vm-type
432+
is one of podman|docker
433+
429434
--debuginfo
430435
Enable creation of debuginfo packages
431436

build-vm

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ VM_TYPE=
3535
declare -a VM_ARGS
3636
VM_TYPE_PRIVILEGED=
3737
VM_TYPE_CONTAINER=
38+
VM_USE_CONTAINER_PREINSTALLIMAGE=false
39+
VM_CONTAINER_IMAGE=
3840
VM_ROOT=
3941
VM_SWAP=
4042
VM_ROOT_TYPE=
@@ -305,6 +307,13 @@ vm_parse_options() {
305307
VM_OPENSTACK_FLAVOR="$ARG"
306308
shift
307309
;;
310+
-vm-use-container-preinstallimage)
311+
if test "$VM_TYPE" == "docker" -o "$VM_TYPE" == "podman"; then
312+
VM_USE_CONTAINER_PREINSTALLIMAGE=true
313+
else
314+
cleanup_and_exit 1 "Option 'vm-use-container-preinstallimage' is not supported"
315+
fi
316+
;;
308317
-*)
309318
return 1
310319
;;
@@ -990,11 +999,16 @@ vm_first_stage() {
990999
if test "$DO_INIT" = true ; then
9911000
# do first stage of init_buildsystem
9921001
rm -f $BUILD_ROOT/.build.success
993-
set -- init_buildsystem --configdir "$CONFIG_DIR" --cachedir "$CACHE_DIR" --prepare "${initbuildsysstuff[@]}" "${definesnstuff[@]}" "${repos[@]}" $CLEAN_BUILD $USEUSEDFORBUILD $RPMLIST "$RECIPEPATH" $ADDITIONAL_PACKS
1002+
if test "$VM_USE_CONTAINER_PREINSTALLIMAGE" = "true"; then
1003+
set -- init_buildsystem --use-container-preinstallimage "$VM_TYPE" --configdir "$CONFIG_DIR" --cachedir "$CACHE_DIR" --prepare "${initbuildsysstuff[@]}" "${definesnstuff[@]}" "${repos[@]}" $CLEAN_BUILD $USEUSEDFORBUILD $RPMLIST "$RECIPEPATH" $ADDITIONAL_PACKS
1004+
else
1005+
set -- init_buildsystem --configdir "$CONFIG_DIR" --cachedir "$CACHE_DIR" --prepare "${initbuildsysstuff[@]}" "${definesnstuff[@]}" "${repos[@]}" $CLEAN_BUILD $USEUSEDFORBUILD $RPMLIST "$RECIPEPATH" $ADDITIONAL_PACKS
1006+
fi
9941007
echo "$* ..."
9951008
start_time=$SECONDS
9961009
"$@" || cleanup_and_exit 1
9971010
check_exit
1011+
test -f "$BUILD_ROOT/.build/build.data" && source "$BUILD_ROOT/.build/build.data"
9981012
TIME_PREINSTALL=$(( $SECONDS - $start_time ))
9991013
unset start_time
10001014
if test ! -w /root ; then
@@ -1095,6 +1109,9 @@ vm_first_stage() {
10951109
echo ")" >> $BUILD_ROOT/.build/build.data
10961110
echo "VM_TYPE='$VM_TYPE'" >> $BUILD_ROOT/.build/build.data
10971111
echo "VM_TYPE_CONTAINER='$VM_TYPE_CONTAINER'" >> $BUILD_ROOT/.build/build.data
1112+
test -n "$CONTAINER_PREINSTALLIMAGE" && echo "CONTAINER_PREINSTALLIMAGE='$CONTAINER_PREINSTALLIMAGE'" >> $BUILD_ROOT/.build/build.data
1113+
test "$VM_TYPE" = "docker" && echo "CONTAINER_NAME='obsbuild.${BUILD_ROOT##*/}.$(date +%s).${RANDOM}'" >> $BUILD_ROOT/.build/build.data
1114+
test "$VM_TYPE" = "podman" && echo "CONTAINER_NAME='build_${RECIPEFILE//:/-}.$(date +%s).${RANDOM}'" >> $BUILD_ROOT/.build/build.data
10981115
echo "VM_NETWORK='$VM_NETWORK'" >> $BUILD_ROOT/.build/build.data
10991116
echo "RUN_SHELL='$RUN_SHELL'" >> $BUILD_ROOT/.build/build.data
11001117
echo "RUN_SHELL_AFTER_FAIL='$RUN_SHELL_AFTER_FAIL'" >> $BUILD_ROOT/.build/build.data
@@ -1283,6 +1300,11 @@ vm_save_statistics() {
12831300
# args: resultdirs
12841301
vm_wrapup_build() {
12851302
test "$DO_STATISTICS" = 1 && vm_save_statistics
1303+
if test "$BUILDTYPE" = "preinstallimage"; then
1304+
case "$VM_TYPE" in
1305+
docker|podman) preinstallimage_compress "$BUILD_ROOT/$TOPDIR/OTHER" ;;
1306+
esac
1307+
fi
12861308
if test -n "$VM_SWAP"; then
12871309
echo "... saving built packages"
12881310
swapoff "$VM_SWAP"

build-vm-docker

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,24 +28,48 @@ vm_verify_options_docker() {
2828
}
2929

3030
vm_startup_docker() {
31-
local name="obsbuild.${BUILD_ROOT##*/}"
31+
source $BUILD_ROOT/.build/build.data
32+
local name=$CONTAINER_NAME
3233
docker rm "$name" >/dev/null 2>&1 || true
3334
local docker_opts=
35+
local container_root="/mnt"
36+
local build_command=(chroot /mnt "$vm_init_script")
37+
local mounts=("--mount" "type=bind,source=$BUILD_ROOT,destination=/mnt")
3438
test -n "$VM_TYPE_PRIVILEGED" && docker_opts="--privileged --cap-add=SYS_ADMIN --cap-add=MKNOD"
3539
test -n "$RUN_SHELL" -o -n "$RUN_SHELL_AFTER_FAIL" && docker_opts="$docker_opts -it"
40+
local docker_image="busybox"
41+
if test -n "$VM_CONTAINER_IMAGE" ; then
42+
mkdir -p $BUILD_ROOT/home/abuild
43+
# create .build.packages link
44+
rm -rf $BUILD_ROOT/.build.packages
45+
ln -s home/abuild/rpmbuild $BUILD_ROOT/.build.packages
46+
docker_image="$VM_CONTAINER_IMAGE"
47+
container_root=
48+
mounts+=("--mount" "type=bind,source=$BUILD_ROOT/home/abuild,destination=/home/abuild")
49+
local build_command=(bash -c "
50+
# Create symlinks for /mnt hidden directories that include build script and data
51+
for item in /mnt/.[^.]*; do
52+
[ -d \"\$item\" ] && ln -sf \"\$item\" \"/\$(basename \"\$item\")\"
53+
done
54+
$vm_init_script
55+
")
56+
fi
57+
mounts+=(
58+
"--mount" "type=bind,source=/proc,destination=$container_root/proc"
59+
"--mount" "type=bind,source=/dev/pts,destination=$container_root/dev/pts"
60+
"--mount" "type=bind,source=/dev/null,destination=$container_root/dev/null"
61+
)
3662
docker run \
3763
--rm --name "$name" --net=none $docker_opts \
38-
--mount "type=bind,source=$BUILD_ROOT,destination=/mnt" \
39-
--mount "type=bind,source=/proc,destination=/mnt/proc" \
40-
--mount "type=bind,source=/dev/pts,destination=/mnt/dev/pts" \
41-
"$@" busybox chroot /mnt "$vm_init_script"
64+
"${mounts[@]}" "$@" "$docker_image" "${build_command[@]}"
4265
BUILDSTATUS="$?"
4366
test "$BUILDSTATUS" != 255 || BUILDSTATUS=3
4467
cleanup_and_exit "$BUILDSTATUS"
4568
}
4669

4770
vm_kill_docker() {
48-
local name="obsbuild.${BUILD_ROOT##*/}"
71+
source $BUILD_ROOT/.build/build.data
72+
local name=$CONTAINER_NAME
4973
docker stop -t 2 "$name" || true
5074
}
5175

build-vm-podman

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,37 @@ vm_verify_options_podman() {
2828
}
2929

3030
vm_startup_podman() {
31-
local name="build_${RECIPEFILE//:/-}"
31+
source $BUILD_ROOT/.build/build.data
32+
local name=$CONTAINER_NAME
3233
podman rm "$name" >/dev/null 2>&1 || true
3334
local podman_opts=
35+
local container_root="/"
36+
local build_command=("$vm_init_script")
37+
local mounts=()
3438
test -n "$VM_TYPE_PRIVILEGED" && podman_opts="--privileged --cap-add=SYS_ADMIN --cap-add=MKNOD"
3539
test -n "$RUN_SHELL" -o -n "$RUN_SHELL_AFTER_FAIL" && podman_opts="$podman_opts -it"
40+
local podman_image="build-scratch:latest"
41+
if test -n "$VM_CONTAINER_IMAGE" ; then
42+
mkdir -p $BUILD_ROOT/home/abuild
43+
# create .build.packages link
44+
rm -rf $BUILD_ROOT/.build.packages
45+
ln -s home/abuild/rpmbuild $BUILD_ROOT/.build.packages
46+
podman_image="$VM_CONTAINER_IMAGE"
47+
container_root="/mnt"
48+
mounts+=("--mount" "type=bind,source=$BUILD_ROOT/home/abuild,destination=/home/abuild")
49+
local build_command=(bash -c "
50+
# Create symlinks for /mnt hidden directories that include build script and data
51+
for item in /mnt/.[^.]*; do
52+
[ -d \"\$item\" ] && ln -sf \"\$item\" \"/\$(basename \"\$item\")\"
53+
done
54+
$vm_init_script
55+
")
56+
fi
57+
mounts+=("--mount" "type=bind,source=$BUILD_ROOT,destination=$container_root")
3658
podman run \
3759
--runtime=runc \
3860
--rm --name "$name" --net=none $podman_opts \
39-
--mount "type=bind,source=$BUILD_ROOT,destination=/" \
40-
"$@" build-scratch:latest "$vm_init_script"
61+
"${mounts[@]}" "$@" $podman_image "${build_command[@]}"
4162
BUILDSTATUS="$?"
4263
test "$BUILDSTATUS" != 255 || BUILDSTATUS=3
4364
cleanup_and_exit "$BUILDSTATUS"
@@ -49,9 +70,15 @@ vm_kill_podman() {
4970
}
5071

5172
vm_fixup_podman() {
52-
# create a scratch image for our build environment
53-
if ! podman image exists build-scratch:latest ; then
54-
echo "FROM scratch" | podman build -t build-scratch:latest -
73+
if test -n "$VM_CONTAINER_IMAGE"; then
74+
if ! podman image exists "$VM_CONTAINER_IMAGE" ; then
75+
cleanup_and_exit 1 "ERROR: Unable to find container preinstallimage ${VM_CONTAINER_IMAGE}"
76+
fi
77+
else
78+
# create a scratch image for our build environment
79+
if ! podman image exists build-scratch:latest ; then
80+
echo "FROM scratch" | podman build -t build-scratch:latest -
81+
fi
5582
fi
5683
}
5784

@@ -80,7 +107,8 @@ vm_sysrq_podman() {
80107
}
81108

82109
vm_wipe_podman() {
83-
local name="build_${RECIPEFILE//:/-}"
110+
source $BUILD_ROOT/.build/build.data
111+
local name=$CONTAINER_NAME
84112
podman rm "$name" >/dev/null 2>&1 || true
85113

86114
echo "Wiping build root: '$BUILD_ROOT'"

init_buildsystem

Lines changed: 83 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ DLNOSIGNATURE=
6363
CACHE_DIR=
6464
OBSURL=
6565
BUILD_SYSROOT=
66+
CONTAINER=
6667
test -z "$CONFIG_DIR" && CONFIG_DIR="$BUILD_DIR/configs"
6768

6869
# default repository type
@@ -132,6 +133,10 @@ while test -n "$1" ; do
132133
OBSURL="$2"
133134
shift 2
134135
;;
136+
--use-container-preinstallimage)
137+
CONTAINER="$2"
138+
shift 2
139+
;;
135140
*)
136141
break
137142
;;
@@ -226,10 +231,21 @@ unsafe_preinstall_check() {
226231
}
227232

228233
preinstall_image_filter() {
229-
for PKG in "$@" ; do
230-
test -e "$BUILD_ROOT/.preinstall_image/$PKG" && continue
231-
echo $PKG
232-
done
234+
# If we have preinstall image info file, use it to filter packages
235+
if test -n "$PREINSTALL_IMAGE_INFO" -a -f "$PREINSTALL_IMAGE_INFO" ; then
236+
for PKG in "$@" ; do
237+
if grep -q "$PKG$" "$PREINSTALL_IMAGE_INFO" 2>/dev/null ; then
238+
continue
239+
fi
240+
echo $PKG
241+
done
242+
else
243+
# Check unpacked preinstallimage if no info file available
244+
for PKG in "$@" ; do
245+
test -e "$BUILD_ROOT/.preinstall_image/$PKG" && continue
246+
echo $PKG
247+
done
248+
fi
233249
}
234250

235251
# call with cmd [OPTIONS] -- ARGS...
@@ -310,6 +326,27 @@ preinstall_image() {
310326
preinstall_integrate
311327
}
312328

329+
preinstall_container_image() {
330+
check_exit
331+
IMAGE_NAME="${2##*/}"
332+
IMAGE_NAME="${IMAGE_NAME%% \[*}"
333+
IMAGE_TAG=$(echo "$2" | awk -F'[][]' '{print $2}')
334+
echo "Using preinstall image${2:+ $2} as container image"
335+
preinstall_setup
336+
# Check if the image exists
337+
if $CONTAINER images --format "{{.Repository}}:{{.Tag}}" | grep -q "${IMAGE_NAME}:${IMAGE_TAG}"; then
338+
echo "Preinstall container image ${IMAGE_NAME}:${IMAGE_TAG} exists for ${CONTAINER}."
339+
else
340+
echo "Importing preinstall container image ${IMAGE_NAME}:${IMAGE_TAG}"
341+
if ! $CONTAINER import "$BUILD_INIT_CACHE/rpms/$1" "${IMAGE_NAME}:${IMAGE_TAG}"; then
342+
echo "ERROR: failed to import preinstall container image."
343+
cleanup_and_exit 1
344+
fi
345+
fi
346+
export VM_CONTAINER_IMAGE="${IMAGE_NAME}:${IMAGE_TAG}"
347+
echo "VM_CONTAINER_IMAGE='$VM_CONTAINER_IMAGE'" >> $BUILD_ROOT/.build/build.data
348+
}
349+
313350
preinstall() {
314351
local PKG="$1"
315352
check_exit
@@ -758,6 +795,10 @@ else
758795
PREINSTALL_IMAGE_SOURCE="$SRC"
759796
continue
760797
fi
798+
if test "$PKG" = "preinstallimageinfo:" ; then
799+
PREINSTALL_IMAGE_INFO="$SRC"
800+
continue
801+
fi
761802
if test "$PKG" = "runscripts:" ; then
762803
RUNSCRIPTS_SEEN=true
763804
PACKAGES_TO_RUNSCRIPTS=$SRC
@@ -919,29 +960,37 @@ if test ! -e $BUILD_ROOT/installed-pkg -a ! -e $BUILD_ROOT/.build/init_buildsyst
919960
PACKAGES_TO_VMINSTALL_FILTERED="$PACKAGES_TO_VMINSTALL"
920961
rm -f "$BUILD_ROOT/.preinstall_image"/*
921962
if test -n "$PREINSTALL_IMAGE" ; then
922-
preinstall_image "$PREINSTALL_IMAGE" "$PREINSTALL_IMAGE_SOURCE"
963+
if test -n "$CONTAINER"; then
964+
preinstall_container_image "$PREINSTALL_IMAGE" "$PREINSTALL_IMAGE_SOURCE"
965+
else
966+
preinstall_image "$PREINSTALL_IMAGE" "$PREINSTALL_IMAGE_SOURCE"
967+
fi
923968
PACKAGES_TO_PREINSTALL_FILTERED=`preinstall_image_filter $PACKAGES_TO_PREINSTALL_FILTERED`
924969
PACKAGES_TO_VMINSTALL_FILTERED=`preinstall_image_filter $PACKAGES_TO_VMINSTALL_FILTERED`
925970
fi
926971
PACKAGES_TO_PREINSTALL_FILTERED=`reorder $PACKAGES_TO_PREINSTALL_FILTERED`
927972
if test -n "$PREPARE_VM" ; then
928973
PACKAGES_TO_VMINSTALL_FILTERED=`reorder $PACKAGES_TO_VMINSTALL_FILTERED`
929974
fi
930-
progress_setup PACKAGES_TO_PREINSTALL_FILTERED
931-
for PKG in $PACKAGES_TO_PREINSTALL_FILTERED ; do
932-
progress_step PACKAGES_TO_PREINSTALL_FILTERED
933-
preinstall ${PKG##*/}
934-
done
935-
if test -n "$PREPARE_VM" ; then
936-
echo
937-
progress_setup PACKAGES_TO_VMINSTALL_FILTERED
938-
for PKG in $PACKAGES_TO_VMINSTALL_FILTERED ; do
939-
progress_step PACKAGES_TO_VMINSTALL_FILTERED
940-
preinstall ${PKG##*/}
941-
done
975+
# no need to preinstall packages if we are importing them in preinstall container image
976+
if test -z "$VM_CONTAINER_IMAGE"; then
977+
progress_setup PACKAGES_TO_PREINSTALL_FILTERED
978+
for PKG in $PACKAGES_TO_PREINSTALL_FILTERED ; do
979+
progress_step PACKAGES_TO_PREINSTALL_FILTERED
980+
preinstall ${PKG##*/}
981+
done
982+
if test -n "$PREPARE_VM" ; then
983+
echo
984+
progress_setup PACKAGES_TO_VMINSTALL_FILTERED
985+
for PKG in $PACKAGES_TO_VMINSTALL_FILTERED ; do
986+
progress_step PACKAGES_TO_VMINSTALL_FILTERED
987+
preinstall ${PKG##*/}
988+
done
989+
fi
942990
fi
943991
# for reorder
944992
check_exit
993+
mkdir -p "$BUILD_ROOT/etc"
945994
if test -w /root ; then
946995
test -c $BUILD_ROOT/dev/null || create_devs
947996
fi
@@ -962,6 +1011,10 @@ if test ! -e $BUILD_ROOT/installed-pkg -a ! -e $BUILD_ROOT/.build/init_buildsyst
9621011
rm -rf "$BUILD_ROOT/installed-pkg"
9631012
mkdir -p "$BUILD_ROOT/installed-pkg"
9641013
else
1014+
# we still need preinstall image name even if it was already done once
1015+
if test -n "$CONTAINER"; then
1016+
preinstall_container_image "$PREINSTALL_IMAGE" "$PREINSTALL_IMAGE_SOURCE"
1017+
fi
9651018
# preinstall was already done
9661019
if test -z "$PREPARE_VM" ; then
9671020
mount_stuff
@@ -1115,7 +1168,19 @@ for PKG in $MAIN_LIST ; do
11151168
if ! test -e $BUILD_ROOT/.preinstall_image/$PKG ; then
11161169
cleanup_and_exit 1 "Package $PKG is missing from the preinstall image"
11171170
fi
1118-
read PKG_HDRMD5 PKGID < $BUILD_ROOT/.preinstall_image/$PKG
1171+
1172+
# Try to read PKG_HDRMD5 and PKGID from preinstallimage info file first
1173+
if test -n "$PREINSTALL_IMAGE_INFO" -a -f "$PREINSTALL_IMAGE_INFO" ; then
1174+
PKG_INFO=$(grep "$PKG$" "$PREINSTALL_IMAGE_INFO" 2>/dev/null | head -n1)
1175+
if test -n "$PKG_INFO" ; then
1176+
PKG_HDRMD5=$(echo "$PKG_INFO" | awk '{print $1}')
1177+
PKGID=$(echo "$PKG_INFO" | awk '{print $2}')
1178+
fi
1179+
else
1180+
# Fallback to reading from unpacked preinstall image
1181+
read PKG_HDRMD5 PKGID < $BUILD_ROOT/.preinstall_image/$PKG
1182+
fi
1183+
11191184
echo "preinstalled ${PKGID%% *}"
11201185
echo "$PKGID" > $BUILD_ROOT/installed-pkg/$PKG
11211186
continue

0 commit comments

Comments
 (0)