diff --git a/build-tests/x86/tumbleweed/test-image-disk/appliance.kiwi b/build-tests/x86/tumbleweed/test-image-disk/appliance.kiwi
index 0c9c1759f21..27e82cdf346 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,12 +108,14 @@
-
+
+
+
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
diff --git a/doc/source/concept_and_workflow/customize_the_boot_process.rst b/doc/source/concept_and_workflow/customize_the_boot_process.rst
index 43648bc2d01..765b81acdc8 100644
--- a/doc/source/concept_and_workflow/customize_the_boot_process.rst
+++ b/doc/source/concept_and_workflow/customize_the_boot_process.rst
@@ -230,8 +230,29 @@ the available kernel boot parameters for these modules:
the type setup of the image description. The implementation
also checks if the start address of the last partition on the
target disk matches the start address of the image to be
- deployed. Only if they match can the data on the last partition
- be retained.
+ deployed. Only if they match the data on the last partition
+ can be retained.
+
+``rd.kiwi.install.retain_past``
+ Instructs an OEM installation to retain the contents of the
+ last partition on the target disk in a less strict mode than
+ it is the case with `rd.kiwi.install.retain_last`. 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.
+
+ .. note:: Retain Past Mode Limitations
+
+ There are no sanity checks for the partition to retain in this mode.
+ From an implementation perspective {kiwi-ng} simply takes the last
+ partition prior dump as reported by sfdisk and rebuilds this partition
+ after the OS image is deployed. This can lead to a gap in the partition
+ table between the OS end and the start of the retained partition. There
+ is also no sanity checking when there are multiple partitions after the
+ OS image. In this case, the last partition is retained, and all other
+ partitions are removed. In constrast to `rd.kiwi.install.retain_last`,
+ there is no tight coupling to the OS image partition table layout and
+ as such `rd.kiwi.install.retain_last` should be used with caution.
``rd.kiwi.oem.luks.reencrypt``
For OEM LUKS2-encrypted disk images. If set, it re-encrypts the disk
diff --git a/dracut/modules.d/55kiwi-dump/kiwi-dump-image.sh b/dracut/modules.d/55kiwi-dump/kiwi-dump-image.sh
index 926703feae5..8ab56b2a826 100755
--- a/dracut/modules.d/55kiwi-dump/kiwi-dump-image.sh
+++ b/dracut/modules.d/55kiwi-dump/kiwi-dump-image.sh
@@ -374,8 +374,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=$(
@@ -387,7 +394,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}")
@@ -412,8 +427,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 \
@@ -437,15 +451,58 @@ 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 && \
+ [ ! -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=/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
@@ -480,8 +537,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
}
@@ -583,15 +646,18 @@ 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
+ # the image got deployed intentionally (retain_last)
+ # or parts of the former partition table got
+ # restored (retain_past)
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}
(