From 22787955c0ec02102664860cc43a5150859b4b9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20Sch=C3=A4fer?= Date: Sun, 2 Nov 2025 19:27:09 +0100 Subject: [PATCH 1/5] Add rd.kiwi.install.retain_past deployment option As a less strict method to retain_last, now also the retain_past deployment option exists. In the retain_past mode the partition to preserve must not be part of the initial image. It can retain the content of any last partition if its start address is past the OS image. However, a gap in the partition table between the OS end and the start of the retained partition can occur for which this commit does not provide a resize method yet. --- .../modules.d/55kiwi-dump/kiwi-dump-image.sh | 59 +++++++++++++++++-- 1 file changed, 54 insertions(+), 5 deletions(-) diff --git a/dracut/modules.d/55kiwi-dump/kiwi-dump-image.sh b/dracut/modules.d/55kiwi-dump/kiwi-dump-image.sh index c60e43b0a18..620d3a6f091 100755 --- a/dracut/modules.d/55kiwi-dump/kiwi-dump-image.sh +++ b/dracut/modules.d/55kiwi-dump/kiwi-dump-image.sh @@ -346,8 +346,15 @@ function dump_image { dump=dump_local_image fi + # preserve pre-dump partition table + if getargbool 0 rd.kiwi.install.retain_past; then + fetch_local_partition_table "${image_target}" /tmp/parttable_pre + fi + # setup blocks and blocksize to retain last - if getargbool 0 rd.kiwi.install.retain_last; then + if getargbool 0 rd.kiwi.install.retain_last || \ + getargbool 0 rd.kiwi.install.retain_past + then if [ -n "${image_from_remote}" ];then image_size=$((blocks * blocksize)) parttable=$( @@ -409,15 +416,49 @@ function dump_image { report_and_quit "Failed to install image" fi fi + + # recreate last partition from pre-dump table + if getargbool 0 rd.kiwi.install.retain_past; then + recreate_last_partition "${image_target}" + fi } function fetch_local_partition_table { local image_source=$1 - local parttable=/tmp/parttable + local parttable=$2 + if [ -z "${parttable}" ];then + parttable=/tmp/parttable + fi sfdisk -d "${image_source}" > "${parttable}" 2>/dev/null echo "${parttable}" } +function recreate_last_partition { + # recreate last partition as it existed prior dump + local image_target=$1 + local table_type + table_type=$(get_partition_table_type "${image_target}") + if [ "${table_type}" = "gpt" ];then + relocate_gpt_at_end_of_disk "${image_target}" + fi + # parttable after image dump, the OS + sfdisk -d "${image_target}" > /tmp/parttable_1 2>/dev/null + # last partition of table as it existed prior dump + tail -n 1 /tmp/parttable_pre > /tmp/parttable_2 + # combine table snippets. Please note there can now be a gap + # between the end of the OS table and the start of the last + # partition of the table prior dump. Please also note, if the + # table prior dump had more partitions than only the last + # one to retain, this table concat will not retain those. + # and the OS dump might have overwritten them. A more + # sophisticated concat procedure would be needed to support + # this case here in this code and also in the + # compatible_to_retain() method + cat /tmp/parttable_1 /tmp/parttable_2 > /tmp/parttable + set_device_lock "${image_target}" \ + sfdisk -f "${image_target}" < /tmp/parttable +} + function fetch_remote_partition_table { local image_source=$1 local image_size=$2 @@ -452,8 +493,14 @@ function compatible_to_retain { touch /tmp/retain_not_applicable return 1 fi - if [ ! "${source_start}" = "${target_start}" ];then - report_and_quit "Cannot retain partition, start address mismatch" + if getargbool 0 rd.kiwi.install.retain_last; then + if [ ! "${source_start}" = "${target_start}" ];then + report_and_quit "Cannot retain partition, start address mismatch" + fi + elif getargbool 0 rd.kiwi.install.retain_past; then + if [ "${source_start}" -gt "${target_start}" ];then + report_and_quit "Cannot retain partition, image overlaps" + fi fi return 0 } @@ -550,7 +597,9 @@ function check_image_integrity { # no verification wanted return fi - if getargbool 0 rd.kiwi.install.retain_last; then + if getargbool 0 rd.kiwi.install.retain_last || \ + getargbool 0 rd.kiwi.install.retain_past + then if [ ! -e /tmp/retain_not_applicable ];then # no verification possible as only a portion of # the image got deployed intentionally From cc7e4111e9b871d36cd44daab7fabaf005342bb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20Sch=C3=A4fer?= Date: Mon, 1 Dec 2025 16:25:29 +0100 Subject: [PATCH 2/5] Update retain feature integration test Add RetainPast profile to build image for testing custom partition table changes not provided by the image --- .../tumbleweed/test-image-disk/appliance.kiwi | 28 +++++++++++++++++-- .../x86/tumbleweed/test-image-disk/config.sh | 2 +- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/build-tests/x86/tumbleweed/test-image-disk/appliance.kiwi b/build-tests/x86/tumbleweed/test-image-disk/appliance.kiwi index c00882d6560..9f8abf2da1a 100644 --- a/build-tests/x86/tumbleweed/test-image-disk/appliance.kiwi +++ b/build-tests/x86/tumbleweed/test-image-disk/appliance.kiwi @@ -8,7 +8,8 @@ - + + 1.42.1 @@ -35,7 +36,7 @@ - + @@ -54,8 +55,27 @@ 3 + + + + + true + true + 512 + false + + false + + + + + 3 + + + + @@ -88,11 +108,13 @@ - + + + diff --git a/build-tests/x86/tumbleweed/test-image-disk/config.sh b/build-tests/x86/tumbleweed/test-image-disk/config.sh index 3551376a6d8..c17447b3ae8 100644 --- a/build-tests/x86/tumbleweed/test-image-disk/config.sh +++ b/build-tests/x86/tumbleweed/test-image-disk/config.sh @@ -13,7 +13,7 @@ systemctl enable dracut_hostonly # Just in case the kiwi resizer is disabled in the system and # gets dropped from the initrd by the customer for some reason for profile in ${kiwi_profiles//,/ }; do - if [ "${profile}" = "Retain" ]; then + if [ "${profile}" = "RetainLast" ]; then cat > /etc/fstab.script <<-EOF sed -ie "s@/home ext4 defaults@/home ext4 x-systemd.growfs,defaults@" /etc/fstab rm /etc/fstabe From 2d7b59ea7682648876cb9510b0737842ed317f6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20Sch=C3=A4fer?= Date: Mon, 1 Dec 2025 16:45:59 +0100 Subject: [PATCH 3/5] Fixes... --- .../modules.d/55kiwi-dump/kiwi-dump-image.sh | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/dracut/modules.d/55kiwi-dump/kiwi-dump-image.sh b/dracut/modules.d/55kiwi-dump/kiwi-dump-image.sh index 620d3a6f091..04945aa7a07 100755 --- a/dracut/modules.d/55kiwi-dump/kiwi-dump-image.sh +++ b/dracut/modules.d/55kiwi-dump/kiwi-dump-image.sh @@ -366,7 +366,15 @@ function dump_image { ) fi if compatible_to_retain "${parttable}" "${image_target}"; then - count=$(get_disk_offset_retain_last_partition "${parttable}") + if getargbool 0 rd.kiwi.install.retain_last; then + count=$(get_disk_offset_retain_last_partition "${parttable}") + else + # retain_past always dumps the complete image + # the compatible_to_retain check for this image blob + # has been done and the deployment can happen for + # all blocks + count=0 + fi fi if [ "${count}" -gt 0 ];then block_size=$(get_sector_size_from_table_dump "${parttable}") @@ -391,8 +399,7 @@ function dump_image { # deploy echo "${load_text} [${image_target}]..." - if command -v pv &>/dev/null && [ "${kiwi_oemsilentinstall}" = "false" ] - then + if with_progress && [ "${kiwi_oemsilentinstall}" = "false" ]; then # dump with dialog based progress information setup_progress_fifo ${progress} eval \ @@ -418,11 +425,20 @@ function dump_image { fi # recreate last partition from pre-dump table - if getargbool 0 rd.kiwi.install.retain_past; then + if getargbool 0 rd.kiwi.install.retain_past && \ + [ ! -e /tmp/retain_not_applicable ] + then recreate_last_partition "${image_target}" fi } +function with_progress { + if getargbool 0 rd.debug || ! command -v pv &>/dev/null; then + return 1 + fi + return 0 +} + function fetch_local_partition_table { local image_source=$1 local parttable=$2 @@ -597,17 +613,14 @@ function check_image_integrity { # no verification wanted return fi - if getargbool 0 rd.kiwi.install.retain_last || \ - getargbool 0 rd.kiwi.install.retain_past - then + if getargbool 0 rd.kiwi.install.retain_last; then if [ ! -e /tmp/retain_not_applicable ];then # no verification possible as only a portion of # the image got deployed intentionally return fi fi - if command -v pv &>/dev/null && [ "${kiwi_oemsilentverify}" = "false" ] - then + if with_progress && [ "${kiwi_oemsilentverify}" = "false" ]; then # verify with dialog based progress information setup_progress_fifo ${progress} ( From 2b9011d402ce795311746e0ea8fc21ac33ebbd83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20Sch=C3=A4fer?= Date: Mon, 1 Dec 2025 16:54:03 +0100 Subject: [PATCH 4/5] Fixes... --- dracut/modules.d/55kiwi-dump/kiwi-dump-image.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dracut/modules.d/55kiwi-dump/kiwi-dump-image.sh b/dracut/modules.d/55kiwi-dump/kiwi-dump-image.sh index 04945aa7a07..8110ce85e76 100755 --- a/dracut/modules.d/55kiwi-dump/kiwi-dump-image.sh +++ b/dracut/modules.d/55kiwi-dump/kiwi-dump-image.sh @@ -613,7 +613,9 @@ function check_image_integrity { # no verification wanted return fi - if getargbool 0 rd.kiwi.install.retain_last; then + if getargbool 0 rd.kiwi.install.retain_last || \ + getargbool 0 rd.kiwi.install.retain_past + then if [ ! -e /tmp/retain_not_applicable ];then # no verification possible as only a portion of # the image got deployed intentionally From d9f4751ca1ce09350fe9ac4229e4a6ca2e223292 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20Sch=C3=A4fer?= Date: Mon, 1 Dec 2025 16:55:22 +0100 Subject: [PATCH 5/5] Fixes... --- dracut/modules.d/55kiwi-dump/kiwi-dump-image.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dracut/modules.d/55kiwi-dump/kiwi-dump-image.sh b/dracut/modules.d/55kiwi-dump/kiwi-dump-image.sh index 8110ce85e76..29c0120b8a7 100755 --- a/dracut/modules.d/55kiwi-dump/kiwi-dump-image.sh +++ b/dracut/modules.d/55kiwi-dump/kiwi-dump-image.sh @@ -618,7 +618,9 @@ function check_image_integrity { then if [ ! -e /tmp/retain_not_applicable ];then # no verification possible as only a portion of - # the image got deployed intentionally + # the image got deployed intentionally (retain_last) + # or parts of the former partition table got + # restored (retain_past) return fi fi