rebase to new upstream version

Resolves: RHEL-72557
This commit is contained in:
Lukáš Zaoral 2025-02-04 15:16:14 +01:00 committed by Pavel Cahyna
parent 789f48ba6b
commit d340c35cc1
28 changed files with 42 additions and 5697 deletions

View File

@ -1,3 +0,0 @@
rear-%-clean.tar.gz: rear-%.tar.gz
set -o pipefail; gunzip -c $< | tar --delete "rear-"$*"/doc/rear-release-notes.txt" -f - | gzip -c - > $@.tmp
mv $@.tmp $@

View File

@ -1,32 +0,0 @@
From 89b61793d80bc2cb2abe47a7d0549466fb087d16 Mon Sep 17 00:00:00 2001
From: Johannes Meixner <jsmeix@suse.com>
Date: Fri, 12 Jan 2024 08:04:40 +0100
Subject: [PATCH] Make initrd accessible only by root (#3123)
In pack/GNU/Linux/900_create_initramfs.sh call
chmod 0600 "$TMP_DIR/$REAR_INITRD_FILENAME"
to let only 'root' access the ReaR initrd because
the ReaR recovery system in the initrd can contain secrets
(not by default but when certain things are explicitly
configured by the user like SSH keys without passphrase)
see https://github.com/rear/rear/issues/3122
and https://bugzilla.opensuse.org/show_bug.cgi?id=1218728
---
usr/share/rear/pack/GNU/Linux/900_create_initramfs.sh | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/usr/share/rear/pack/GNU/Linux/900_create_initramfs.sh b/usr/share/rear/pack/GNU/Linux/900_create_initramfs.sh
index 1e0c11039..12be718ed 100644
--- a/usr/share/rear/pack/GNU/Linux/900_create_initramfs.sh
+++ b/usr/share/rear/pack/GNU/Linux/900_create_initramfs.sh
@@ -125,4 +125,10 @@ case "$REAR_INITRD_COMPRESSION" in
fi
;;
esac
+
+# Only root should be allowed to access the initrd
+# because the ReaR recovery system can contain secrets
+# cf. https://github.com/rear/rear/issues/3122
+test -s "$TMP_DIR/$REAR_INITRD_FILENAME" && chmod 0600 "$TMP_DIR/$REAR_INITRD_FILENAME"
+
popd >/dev/null

View File

@ -1,15 +0,0 @@
diff --git a/usr/share/rear/output/ISO/Linux-i386/249_check_rhel_grub2_efi_package.sh b/usr/share/rear/output/ISO/Linux-i386/249_check_rhel_grub2_efi_package.sh
new file mode 100644
index 00000000..4c4ded08
--- /dev/null
+++ b/usr/share/rear/output/ISO/Linux-i386/249_check_rhel_grub2_efi_package.sh
@@ -0,0 +1,9 @@
+# 249_check_rhel_grub2_efi_package.sh
+
+is_true $USING_UEFI_BOOTLOADER || return # empty or 0 means NO UEFI
+
+(
+ VERBOSE=1
+ test -r /usr/lib/grub/x86_64-efi/moddep.lst
+ PrintIfError "WARNING: /usr/lib/grub/x86_64-efi/moddep.lst not found, grub2-mkimage will likely fail. Please install the grub2-efi-x64-modules package to fix this."
+)

View File

@ -1,76 +0,0 @@
From 29e739ae7c0651f8f77c60846bfbe2b6c91baa29 Mon Sep 17 00:00:00 2001
From: Pavel Cahyna <pcahyna@redhat.com>
Date: Sat, 31 Dec 2022 17:40:39 +0100
Subject: [PATCH] Protect against colons in pvdisplay output
LVM can be configured to show device names under /dev/disk/by-path
in command output. These names often contain colons that separate fields
like channel and target (for example /dev/disk/by-path/pci-*-scsi-0:0:1:0-*,
similarly the pci-* part, which contains colon-separated PCI bus and
device numbers). Since the "pvdisplay -c" output also uses colons as
field separators and does not escape embedded colons in any way,
embedded colons break parsing of this output.
As a fix, use the pipe character '|' as the field separator in pvdisplay
output. (This would break if a PV device has a '|' in its name, but this
is very much less likely than having a ':' .)
Also, configure explicitly what fields to output - "pvdisplay -c"
prints many fields, but I have not found documentation about what fields
is it using exactly, so one had to guess what the output means. Using
"pvdisplay -C" and selecting the fields explicitly is much clearer.
This also changes the PV size field to match documentation, the comment
says that size is in bytes, but it actually was not in bytes. As nothing
is actually using the PV size field, this inconsistency has not caused
any problem in practice, and no code needs adjusting for the change.
---
.../layout/save/GNU/Linux/220_lvm_layout.sh | 24 ++++++++++++-------
1 file changed, 15 insertions(+), 9 deletions(-)
diff --git a/usr/share/rear/layout/save/GNU/Linux/220_lvm_layout.sh b/usr/share/rear/layout/save/GNU/Linux/220_lvm_layout.sh
index e01dbf465..7400c586e 100644
--- a/usr/share/rear/layout/save/GNU/Linux/220_lvm_layout.sh
+++ b/usr/share/rear/layout/save/GNU/Linux/220_lvm_layout.sh
@@ -70,14 +70,20 @@ local lvs_exit_code
# Get physical_device configuration.
# Format: lvmdev <volume_group> <device> [<uuid>] [<size(bytes)>]
header_printed="no"
- # Example output of "lvm pvdisplay -c":
- # /dev/sda1:system:41940992:-1:8:8:-1:4096:5119:2:5117:7wwpcO-KmNN-qsTE-7sp7-JBJS-vBdC-Zyt1W7
+ # Set pvdisplay separator to '|' to prevent issues with a colon in the path under /dev/disk/by-path
+ # that contains a ':' in the SCSI slot name.
+ # Example output of "lvm pvdisplay -C --separator '|' --noheadings --nosuffix --units=b -o pv_name,vg_name,pv_size,pv_uuid"
+ # on a system where LVM is configured to show the /dev/disk/by-path device names instead of the usual
+ # /dev/sda etc. (by using a setting like
+ # filter = [ "r|/dev/disk/by-path/.*-usb-|", "a|/dev/disk/by-path/pci-.*-nvme-|", "a|/dev/disk/by-path/pci-.*-scsi-|", "a|/dev/disk/by-path/pci-.*-ata-|", "a|/dev/disk/by-path/pci-.*-sas-|", "a|loop|", "r|.*|" ]
+ # in /etc/lvm/lvm.conf):
+ # /dev/disk/by-path/pci-0000:03:00.0-scsi-0:0:1:0-part1|system|107340627968|7wwpcO-KmNN-qsTE-7sp7-JBJS-vBdC-Zyt1W7
# There are two leading blanks in the output (at least on SLES12-SP4 with LVM 2.02.180).
- lvm pvdisplay -c | while read line ; do
+ lvm pvdisplay -C --separator '|' --noheadings --nosuffix --units=b -o pv_name,vg_name,pv_size,pv_uuid | while read line ; do
- # With the above example pdev=/dev/sda1
+ # With the above example pdev=/dev/disk/by-path/pci-0000:03:00.0-scsi-0:0:1:0-part1
# (the "echo $line" makes the leading blanks disappear)
- pdev=$( echo $line | cut -d ":" -f "1" )
+ pdev=$( echo $line | cut -d "|" -f "1" )
# Skip lines that are not describing physical devices
# i.e. lines where pdev does not start with a leading / character:
@@ -91,11 +97,11 @@ local lvs_exit_code
fi
# With the above example vgrp=system
- vgrp=$( echo $line | cut -d ":" -f "2" )
- # With the above example size=41940992
- size=$( echo $line | cut -d ":" -f "3" )
+ vgrp=$( echo $line | cut -d "|" -f "2" )
+ # With the above example size=107340627968
+ size=$( echo $line | cut -d "|" -f "3" )
# With the above example uuid=7wwpcO-KmNN-qsTE-7sp7-JBJS-vBdC-Zyt1W7
- uuid=$( echo $line | cut -d ":" -f "12" )
+ uuid=$( echo $line | cut -d "|" -f "4" )
# Translate pdev through diskbyid_mappings file:
pdev=$( get_device_mapping $pdev )

View File

@ -1,60 +0,0 @@
commit bca0e7a92af16cb7fb82ef04401cdb3286068081
Merge: d2d2300b f36bfe9b
Author: pcahyna <pcahyna@users.noreply.github.com>
Date: Thu Jul 28 12:11:04 2022 +0200
Merge pull request #2839 from pcahyna/lvm-y
Pass -y to lvcreate instead of piping the output of yes
diff --git a/usr/share/rear/conf/GNU/Linux.conf b/usr/share/rear/conf/GNU/Linux.conf
index 82007719..7e47b912 100644
--- a/usr/share/rear/conf/GNU/Linux.conf
+++ b/usr/share/rear/conf/GNU/Linux.conf
@@ -5,7 +5,7 @@ ip
less
parted
readlink
-# For noninteractive confirmation in lvm commands during layout recreation
+# For noninteractive confirmation in commands
yes
)
diff --git a/usr/share/rear/layout/prepare/GNU/Linux/110_include_lvm_code.sh b/usr/share/rear/layout/prepare/GNU/Linux/110_include_lvm_code.sh
index 0bd863ac..6089cc09 100644
--- a/usr/share/rear/layout/prepare/GNU/Linux/110_include_lvm_code.sh
+++ b/usr/share/rear/layout/prepare/GNU/Linux/110_include_lvm_code.sh
@@ -287,28 +287,16 @@ create_lvmvol() {
# so e.g. 'lvcreate -L 123456b -n LV VG' becomes 'lvcreate -l 100%FREE -n LV VG'
fallbacklvopts="$( sed -e 's/-L [0-9b]*/-l 100%FREE/' <<< "$lvopts" )"
- # In SLES11 "man lvcreate" does not show '-y' or '--yes'
- # so we cannot use "lvm lvcreate -y ..."
- # see https://github.com/rear/rear/issues/2820#issuecomment-1161934013
- # instead we input as many 'y' as asked for by "lvm lvcreate"
- # see https://github.com/rear/rear/issues/513
- # and https://github.com/rear/rear/issues/2820
- # plus be safe against possible 'set -o pipefail' non-zero exit code of 'yes' via '( yes || true ) | ...'
- # see https://github.com/rear/rear/issues/2820#issuecomment-1162804476
- # because 'yes' may get terminated by SIGPIPE when plain 'yes | ...' is used
- # see https://github.com/rear/rear/issues/2820#issuecomment-1162772415
- # and suppress needless "yes: standard output: Broken pipe" stderr messages
- # that appear at least with newer 'yes' in coreutils-8.32 in openSUSE Leap 15.3
cat >> "$LAYOUT_CODE" <<EOF
$ifline
LogPrint "Creating LVM volume '$vg/$lvname' (some properties may not be preserved)"
$warnraidline
- if ! ( yes 2>/dev/null || true ) | lvm lvcreate $lvopts $vg ; then
- LogPrintError "Failed to create LVM volume '$vg/$lvname' with lvcreate $lvopts $vg"
- if ( yes 2>/dev/null || true ) | lvm lvcreate $fallbacklvopts $vg ; then
- LogPrintError "Created LVM volume '$vg/$lvname' using fallback options lvcreate $fallbacklvopts $vg"
+ if ! lvm lvcreate -y $lvopts $vg ; then
+ LogPrintError "Failed to create LVM volume '$vg/$lvname' with lvcreate -y $lvopts $vg"
+ if lvm lvcreate -y $fallbacklvopts $vg ; then
+ LogPrintError "Created LVM volume '$vg/$lvname' using fallback options lvcreate -y $fallbacklvopts $vg"
else
- LogPrintError "Also failed to create LVM volume '$vg/$lvname' with lvcreate $fallbacklvopts $vg"
+ LogPrintError "Also failed to create LVM volume '$vg/$lvname' with lvcreate -y $fallbacklvopts $vg"
# Explicit 'false' is needed to let the whole 'if then else fi' command exit with non zero exit state
# to let diskrestore.sh abort here as usual when a command fails (diskrestore.sh runs with 'set -e'):
false

View File

@ -1,39 +0,0 @@
diff --git a/usr/share/rear/build/default/490_fix_broken_links.sh b/usr/share/rear/build/default/490_fix_broken_links.sh
index 5bace664..cf960be8 100644
--- a/usr/share/rear/build/default/490_fix_broken_links.sh
+++ b/usr/share/rear/build/default/490_fix_broken_links.sh
@@ -7,6 +7,23 @@
# see https://github.com/rear/rear/issues/1638
# and https://github.com/rear/rear/pull/1734
+# Some broken symlinks are expected. The 'build' and 'source' symlinks in kernel modules point to kernel sources
+# and are broken until one installs the kernel-debug-devel or kernel-devel packages (on Fedora) and even then
+# the targets are not included in the rescue system by default.
+# Do not warn about those, it is just noise.
+local irrelevant_symlinks=( '*/lib/modules/*/build' '*/lib/modules/*/source' )
+function symlink_is_irrelevant () {
+ for i in "${irrelevant_symlinks[@]}"; do
+ # do not quote $i, it is a glob pattern, matching will be performed by [[ ... == ... ]]
+ # quoting inside [[ ]] prevents pattern matching
+ if [[ "$1" == $i ]]; then
+ return 0
+ fi
+ done
+ return 1
+}
+
+
# FIXME: The following code fails if symlinks or their targets contain characters from IFS (e.g. blanks),
# cf. the same kind of comments in build/default/990_verify_rootfs.sh
# and layout/prepare/GNU/Linux/130_include_mount_subvolumes_code.sh
@@ -38,6 +55,10 @@ pushd $ROOTFS_DIR
local broken_symlink=''
local link_target=''
for broken_symlink in $broken_symlinks ; do
+ if symlink_is_irrelevant "$broken_symlink" ; then
+ DebugPrint "Ignoring irrelevant broken symlink $broken_symlink"
+ continue
+ fi
# For each broken symlink absolute path inside ROOTFS_DIR
# we call "readlink -e" in the original system to get its link target there.
# If in the original system there was a chain of symbolic links like

View File

@ -2,8 +2,8 @@ diff --git a/usr/share/rear/conf/default.conf b/usr/share/rear/conf/default.conf
index b14525da..23a83b71 100644
--- a/usr/share/rear/conf/default.conf
+++ b/usr/share/rear/conf/default.conf
@@ -1841,10 +1841,10 @@ OBDR_BLOCKSIZE=2048
# BACKUP=NBU stuff (Symantec/Veritas NetBackup)
@@ -2483,10 +2483,10 @@ OBDR_BLOCKSIZE=2048
# BACKUP=NBU (Symantec/Veritas NetBackup)
##
#
-COPY_AS_IS_NBU=( /usr/openv/bin/vnetd /usr/openv/bin/vopied /usr/openv/lib /usr/openv/netbackup /usr/openv/var/auth/[mn]*.txt /opt/VRTSpbx /etc/vx/VxICS /etc/vx/vrtslog.conf )
@ -14,5 +14,5 @@ index b14525da..23a83b71 100644
-NBU_LD_LIBRARY_PATH="/usr/openv/lib:/usr/openv/netbackup/sec/at/lib/"
+NBU_LD_LIBRARY_PATH="/usr/openv/lib:/usr/openv/netbackup/sec/at/lib/:/usr/openv/lib/boost"
PROGS_NBU=( )
####
##

View File

@ -1,41 +0,0 @@
From 6d1e5ab96213a0d79489c4296cd1f5a4be645597 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Zaoral?= <lzaoral@redhat.com>
Date: Thu, 29 Sep 2022 15:32:22 +0200
Subject: [PATCH] Fix initrd regeneration on s390x and Fedora/RHEL
For some reason, the 550_rebuild_initramfs.sh script was not included
for s390x on Fedora/RHEL so the initrd was not regenerated after backup
restore on this architecture.
Since all other architectures were actually using the same script,
let's just move it one level up to fix this bug and to also simplify
the directory structure a bit.
---
.../rear/finalize/Fedora/{i386 => }/550_rebuild_initramfs.sh | 0
usr/share/rear/finalize/Fedora/ppc64/550_rebuild_initramfs.sh | 1 -
usr/share/rear/finalize/Fedora/ppc64le/550_rebuild_initramfs.sh | 1 -
3 files changed, 2 deletions(-)
rename usr/share/rear/finalize/Fedora/{i386 => }/550_rebuild_initramfs.sh (100%)
delete mode 120000 usr/share/rear/finalize/Fedora/ppc64/550_rebuild_initramfs.sh
delete mode 120000 usr/share/rear/finalize/Fedora/ppc64le/550_rebuild_initramfs.sh
diff --git a/usr/share/rear/finalize/Fedora/i386/550_rebuild_initramfs.sh b/usr/share/rear/finalize/Fedora/550_rebuild_initramfs.sh
similarity index 100%
rename from usr/share/rear/finalize/Fedora/i386/550_rebuild_initramfs.sh
rename to usr/share/rear/finalize/Fedora/550_rebuild_initramfs.sh
diff --git a/usr/share/rear/finalize/Fedora/ppc64/550_rebuild_initramfs.sh b/usr/share/rear/finalize/Fedora/ppc64/550_rebuild_initramfs.sh
deleted file mode 120000
index 22eede59d..000000000
--- a/usr/share/rear/finalize/Fedora/ppc64/550_rebuild_initramfs.sh
+++ /dev/null
@@ -1 +0,0 @@
-../i386/550_rebuild_initramfs.sh
\ No newline at end of file
diff --git a/usr/share/rear/finalize/Fedora/ppc64le/550_rebuild_initramfs.sh b/usr/share/rear/finalize/Fedora/ppc64le/550_rebuild_initramfs.sh
deleted file mode 120000
index 22eede59d..000000000
--- a/usr/share/rear/finalize/Fedora/ppc64le/550_rebuild_initramfs.sh
+++ /dev/null
@@ -1 +0,0 @@
-../i386/550_rebuild_initramfs.sh
\ No newline at end of file

View File

@ -45,257 +45,6 @@ index 00000000..f7423e0a
+unset -f get_unit_path
+unset -f get_unit_dropin_paths
+unset -f unit_is_enabled
diff --git a/usr/share/rear/skel/default/etc/scripts/run-automatic-rear b/usr/share/rear/skel/default/etc/scripts/run-automatic-rear
new file mode 100755
index 00000000..6edc657a
--- /dev/null
+++ b/usr/share/rear/skel/default/etc/scripts/run-automatic-rear
@@ -0,0 +1,82 @@
+#!/bin/bash
+
+source /etc/scripts/system-setup-functions.sh
+
+# In debug mode run the automated 'rear recover' also with debug options.
+# Because the kernel command line option 'debug' means 'set -x' for the system setup scripts
+# it also means '-D' (i.e. 'set -x') for the automated 'rear recover' run:
+if rear_debug ; then
+ rear_debug_options='-D'
+else
+ rear_debug_options=''
+fi
+
+# Launch rear recover automatically:
+if automatic_recovery ; then
+ choices=( "View Relax-and-Recover log file(s)"
+ "Go to Relax-and-Recover shell"
+ )
+ echo -e "\nLaunching 'rear recover' automatically\n"
+ if rear $rear_debug_options recover ; then
+ echo -e "\n'rear recover' finished successfully\n"
+ choices+=( "Reboot" )
+ else
+ echo -e "\n'rear recover' failed, check the Relax-and-Recover log file(s)\n"
+ fi
+ PS3="Select what to do "
+ select choice in "${choices[@]}" ; do
+ case "$REPLY" in
+ (1)
+ # Do not assume the ReaR log file is named rear-$HOSTNAME.log
+ # the user can have specified any name as LOGFILE:
+ less /var/log/rear/*
+ ;;
+ (2)
+ echo "" > /etc/issue
+ echo "" > /etc/motd
+ break
+ ;;
+ (3)
+ reboot
+ ;;
+ esac
+ for (( i=1 ; i <= ${#choices[@]} ; i++ )) ; do
+ echo "$i) ${choices[$i-1]}"
+ done
+ done 2>&1
+fi
+
+# Launch rear recover automatically in unattended mode
+# i.e. with automated reboot after successful 'rear recover':
+if unattended_recovery ; then
+ choices=( "View Relax-and-Recover log file(s)"
+ "Go to Relax-and-Recover shell"
+ )
+ echo -e "\nLaunching 'rear recover' automatically in unattended mode\n"
+ if rear $rear_debug_options recover ; then
+ echo -e "\n'rear recover' finished successfully\n"
+ echo -e "\nRebooting in 30 seconds (Ctrl-C to interrupt)\n"
+ sleep 30
+ reboot
+ else
+ echo -e "\n'rear recover' failed, check the Relax-and-Recover log file(s)\n"
+ PS3="Select what to do "
+ select choice in "${choices[@]}" ; do
+ case "$REPLY" in
+ (1)
+ # Do not assume the ReaR log file is named rear-$HOSTNAME.log
+ # the user can have specified any name as LOGFILE:
+ less /var/log/rear/*
+ ;;
+ (2)
+ echo "" > /etc/issue
+ echo "" > /etc/motd
+ break
+ ;;
+ esac
+ for (( i=1 ; i <= ${#choices[@]} ; i++ )) ; do
+ echo "$i) ${choices[$i-1]}"
+ done
+ done 2>&1
+ fi
+fi
diff --git a/usr/share/rear/skel/default/etc/scripts/system-setup b/usr/share/rear/skel/default/etc/scripts/system-setup
index 1dc7f1e8..17487ac7 100755
--- a/usr/share/rear/skel/default/etc/scripts/system-setup
+++ b/usr/share/rear/skel/default/etc/scripts/system-setup
@@ -9,36 +9,7 @@
# (e.g. "ls foo*bar" becomes plain "ls" without "foo*bar: No such file or directory" error).
shopt -s nullglob
-# Use an artificial array to get the kernel command line parameters as array elements
-kernel_command_line=( $( cat /proc/cmdline ) )
-
-function rear_debug() {
- for kernel_command_line_parameter in "${kernel_command_line[@]}" ; do
- test "debug" = "$kernel_command_line_parameter" && return 0
- done
- return 1
-}
-
-function unattended_recovery() {
- for kernel_command_line_parameter in "${kernel_command_line[@]}" ; do
- test "unattended" = "$kernel_command_line_parameter" && return 0
- done
- return 1
-}
-
-function automatic_recovery() {
- # The unattended recovery mode implies automatic recovery (see the implementations below)
- # so that in unattended mode the automatic recovery code below must not be run
- # otherwise first the automatic recovery code and then the unattended recovery code
- # get run automatically one after the other where the unattended recovery fails
- # because for two subsequent 'rear recover' the second one fails:
- unattended_recovery && return 1
- for kernel_command_line_parameter in "${kernel_command_line[@]}" ; do
- test "auto_recover" = "$kernel_command_line_parameter" && return 0
- test "automatic" = "$kernel_command_line_parameter" && return 0
- done
- return 1
-}
+source /etc/scripts/system-setup-functions.sh
# The 'sleep 1' is used as workaround to avoid whatever inexplicable actual reason
# that at least on SLES12 some initial output lines of this script would get lost
@@ -135,84 +106,3 @@ echo -e "\nRelax-and-Recover rescue system is ready\n"
# Wait two seconds so that the user can read the 'Relax-and-Recover rescue system is ready' message
# on his screen before the screen gets cleared and replaced by the login screen:
sleep 2
-
-# In debug mode run the automated 'rear recover' also with debug options.
-# Because the kernel command line option 'debug' means 'set -x' for the system setup scripts
-# it also means '-D' (i.e. 'set -x') for the automated 'rear recover' run:
-if rear_debug ; then
- rear_debug_options='-D'
-else
- rear_debug_options=''
-fi
-
-# Launch rear recover automatically:
-if automatic_recovery ; then
- choices=( "View Relax-and-Recover log file(s)"
- "Go to Relax-and-Recover shell"
- )
- echo -e "\nLaunching 'rear recover' automatically\n"
- # The recover workflow is always verbose (see usr/sbin/rear):
- if rear $rear_debug_options recover ; then
- echo -e "\n'rear recover' finished successfully\n"
- choices+=( "Reboot" )
- else
- echo -e "\n'rear recover' failed, check the Relax-and-Recover log file(s)\n"
- fi
- PS3="Select what to do "
- select choice in "${choices[@]}" ; do
- case "$REPLY" in
- (1)
- # Do not assume the ReaR log file is named rear-$HOSTNAME.log
- # the user can have specified any name as LOGFILE:
- less /var/log/rear/*
- ;;
- (2)
- echo "" > /etc/issue
- echo "" > /etc/motd
- break
- ;;
- (3)
- reboot
- ;;
- esac
- for (( i=1 ; i <= ${#choices[@]} ; i++ )) ; do
- echo "$i) ${choices[$i-1]}"
- done
- done 2>&1
-fi
-
-# Launch rear recover automatically in unattended mode
-# i.e. with automated reboot after successful 'rear recover':
-if unattended_recovery ; then
- choices=( "View Relax-and-Recover log file(s)"
- "Go to Relax-and-Recover shell"
- )
- echo -e "\nLaunching 'rear recover' automatically in unattended mode\n"
- # The recover workflow is always verbose (see usr/sbin/rear):
- if rear $rear_debug_options recover ; then
- echo -e "\n'rear recover' finished successfully\n"
- echo -e "\nRebooting in 30 seconds (Ctrl-C to interrupt)\n"
- sleep 30
- reboot
- else
- echo -e "\n'rear recover' failed, check the Relax-and-Recover log file(s)\n"
- PS3="Select what to do "
- select choice in "${choices[@]}" ; do
- case "$REPLY" in
- (1)
- # Do not assume the ReaR log file is named rear-$HOSTNAME.log
- # the user can have specified any name as LOGFILE:
- less /var/log/rear/*
- ;;
- (2)
- echo "" > /etc/issue
- echo "" > /etc/motd
- break
- ;;
- esac
- for (( i=1 ; i <= ${#choices[@]} ; i++ )) ; do
- echo "$i) ${choices[$i-1]}"
- done
- done 2>&1
- fi
-fi
diff --git a/usr/share/rear/skel/default/etc/scripts/system-setup-functions.sh b/usr/share/rear/skel/default/etc/scripts/system-setup-functions.sh
new file mode 100644
index 00000000..c320cf88
--- /dev/null
+++ b/usr/share/rear/skel/default/etc/scripts/system-setup-functions.sh
@@ -0,0 +1,30 @@
+# Use an artificial array to get the kernel command line parameters as array elements
+kernel_command_line=( $( cat /proc/cmdline ) )
+
+function rear_debug() {
+ for kernel_command_line_parameter in "${kernel_command_line[@]}" ; do
+ test "debug" = "$kernel_command_line_parameter" && return 0
+ done
+ return 1
+}
+
+function unattended_recovery() {
+ for kernel_command_line_parameter in "${kernel_command_line[@]}" ; do
+ test "unattended" = "$kernel_command_line_parameter" && return 0
+ done
+ return 1
+}
+
+function automatic_recovery() {
+ # The unattended recovery mode implies automatic recovery (see the implementations below)
+ # so that in unattended mode the automatic recovery code below must not be run
+ # otherwise first the automatic recovery code and then the unattended recovery code
+ # get run automatically one after the other where the unattended recovery fails
+ # because for two subsequent 'rear recover' the second one fails:
+ unattended_recovery && return 1
+ for kernel_command_line_parameter in "${kernel_command_line[@]}" ; do
+ test "auto_recover" = "$kernel_command_line_parameter" && return 0
+ test "automatic" = "$kernel_command_line_parameter" && return 0
+ done
+ return 1
+}
diff --git a/usr/share/rear/skel/default/etc/systemd/system/default.target.wants/.gitignore b/usr/share/rear/skel/default/etc/systemd/system/default.target.wants/.gitignore
new file mode 100644
index 00000000..d6b7ef32
@ -304,137 +53,3 @@ index 00000000..d6b7ef32
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/usr/share/rear/skel/default/usr/lib/systemd/system/automatic-rear.service b/usr/share/rear/skel/default/usr/lib/systemd/system/automatic-rear.service
new file mode 100644
index 00000000..ee3187a8
--- /dev/null
+++ b/usr/share/rear/skel/default/usr/lib/systemd/system/automatic-rear.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=Run Relax-and-Recover recovery automatically if requested
+Wants=network-online.target
+After=network-online.target
+
+[Service]
+Type=oneshot
+ExecStart=/etc/scripts/run-automatic-rear
+StandardInput=tty
+RemainAfterExit=yes
+
+[Install]
+WantedBy=multi-user.target
diff --git a/usr/share/rear/skel/default/usr/lib/systemd/system/getty@.service b/usr/share/rear/skel/default/usr/lib/systemd/system/getty@.service
index bf858ca8..abafd8b5 100644
--- a/usr/share/rear/skel/default/usr/lib/systemd/system/getty@.service
+++ b/usr/share/rear/skel/default/usr/lib/systemd/system/getty@.service
@@ -6,6 +6,8 @@ Description=Getty on %I
Documentation=man:agetty(8)
After=systemd-user-sessions.service plymouth-quit-wait.service
After=sysinit.service
+# Automatic ReaR uses the system console
+After=automatic-rear.service
# If additional gettys are spawned during boot then we should make
# sure that this is synchronized before getty.target, even though
diff --git a/usr/share/rear/skel/default/usr/lib/systemd/system/multi-user.target b/usr/share/rear/skel/default/usr/lib/systemd/system/multi-user.target
index c5ea1cca..a88e219f 100644
--- a/usr/share/rear/skel/default/usr/lib/systemd/system/multi-user.target
+++ b/usr/share/rear/skel/default/usr/lib/systemd/system/multi-user.target
@@ -4,7 +4,7 @@
[Unit]
Description=Multi-User
-Requires=sysinit.target
+Requires=sysinit.target basic.target
AllowIsolate=yes
[Install]
diff --git a/usr/share/rear/skel/default/usr/lib/systemd/system/multi-user.target.wants/automatic-rear.service b/usr/share/rear/skel/default/usr/lib/systemd/system/multi-user.target.wants/automatic-rear.service
new file mode 120000
index 00000000..3e8a4161
--- /dev/null
+++ b/usr/share/rear/skel/default/usr/lib/systemd/system/multi-user.target.wants/automatic-rear.service
@@ -0,0 +1 @@
+../automatic-rear.service
\ No newline at end of file
diff --git a/usr/share/rear/skel/default/usr/lib/systemd/system/network-online.target b/usr/share/rear/skel/default/usr/lib/systemd/system/network-online.target
new file mode 100644
index 00000000..c3edfeb4
--- /dev/null
+++ b/usr/share/rear/skel/default/usr/lib/systemd/system/network-online.target
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+#
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+[Unit]
+Description=Network is Online
+Documentation=man:systemd.special(7)
+Documentation=https://www.freedesktop.org/wiki/Software/systemd/NetworkTarget
+After=network.target
diff --git a/usr/share/rear/skel/default/usr/lib/systemd/system/network-online.target.wants/sysinit.service b/usr/share/rear/skel/default/usr/lib/systemd/system/network-online.target.wants/sysinit.service
new file mode 120000
index 00000000..ed660a10
--- /dev/null
+++ b/usr/share/rear/skel/default/usr/lib/systemd/system/network-online.target.wants/sysinit.service
@@ -0,0 +1 @@
+../sysinit.service
\ No newline at end of file
diff --git a/usr/share/rear/skel/default/usr/lib/systemd/system/rsyslog.service b/usr/share/rear/skel/default/usr/lib/systemd/system/rsyslog.service
index ac171e0f..18fa17b5 100644
--- a/usr/share/rear/skel/default/usr/lib/systemd/system/rsyslog.service
+++ b/usr/share/rear/skel/default/usr/lib/systemd/system/rsyslog.service
@@ -1,6 +1,5 @@
[Unit]
Description=Relax-and-Recover run-syslog script
-DefaultDependencies=no
[Service]
Type=simple
diff --git a/usr/share/rear/skel/default/usr/lib/systemd/system/sysinit.service b/usr/share/rear/skel/default/usr/lib/systemd/system/sysinit.service
index ee22fafc..b34b2fe8 100644
--- a/usr/share/rear/skel/default/usr/lib/systemd/system/sysinit.service
+++ b/usr/share/rear/skel/default/usr/lib/systemd/system/sysinit.service
@@ -1,9 +1,14 @@
[Unit]
Description=Initialize Rescue System
-After=systemd-udevd.service
+DefaultDependencies=no
+After=systemd-udevd.service rear-boot-helper.service
+Before=network-online.target
[Service]
Type=oneshot
ExecStart=/etc/scripts/system-setup
StandardInput=tty
RemainAfterExit=yes
+
+[Install]
+WantedBy=network-online.target
diff --git a/usr/share/rear/skel/default/usr/lib/systemd/system/sysinit.target b/usr/share/rear/skel/default/usr/lib/systemd/system/sysinit.target
index 4187ef67..2a16369b 100644
--- a/usr/share/rear/skel/default/usr/lib/systemd/system/sysinit.target
+++ b/usr/share/rear/skel/default/usr/lib/systemd/system/sysinit.target
@@ -4,3 +4,5 @@
[Unit]
Description=System Initialization
+Wants=sysinit.service rear-boot-helper.service
+After=sysinit.service rear-boot-helper.service
diff --git a/usr/share/rear/skel/default/usr/lib/systemd/system/syslog.socket b/usr/share/rear/skel/default/usr/lib/systemd/system/syslog.socket
index 9a0064c0..3fb02344 100644
--- a/usr/share/rear/skel/default/usr/lib/systemd/system/syslog.socket
+++ b/usr/share/rear/skel/default/usr/lib/systemd/system/syslog.socket
@@ -4,7 +4,6 @@
[Unit]
Description=Syslog Socket
-DefaultDependencies=no
Before=sockets.target syslog.target
[Socket]

View File

@ -1,587 +0,0 @@
commit 88f11d19d748fff3f36357ef1471ee75fbfacabb
Merge: bca0e7a9 4b4efc58
Author: Johannes Meixner <jsmeix@suse.com>
Date: Wed Aug 3 15:04:20 2022 +0200
Merge pull request #2844 from rear/jsmeix-overhauled-290_kernel_cmdline
Overhauled rescue/GNU/Linux/290_kernel_cmdline.sh
in particular to make it possible to add several already existing
kernel options by this script with same kernel option keyword
for example when /proc/cmdline contains
... console=ttyS0,9600 ... console=tty0 ...
then via COPY_KERNEL_PARAMETERS+=( console )
cf. https://github.com/rear/rear/pull/2749#issuecomment-1197843273
Cherry-picked-by: Lukáš Zaoral <lzaoral@redhat.com>
diff --git a/usr/share/rear/rescue/GNU/Linux/290_kernel_cmdline.sh b/usr/share/rear/rescue/GNU/Linux/290_kernel_cmdline.sh
index 0e11204b..eb6c45de 100644
--- a/usr/share/rear/rescue/GNU/Linux/290_kernel_cmdline.sh
+++ b/usr/share/rear/rescue/GNU/Linux/290_kernel_cmdline.sh
@@ -1,8 +1,15 @@
-# purpose of the script is to detect some important KERNEL CMDLINE options on the current system
-# we should also use in rescue mode (automatically update KERNEL_CMDLINE array variable).
+# Purpose of the script is to get the COPY_KERNEL_PARAMETERS on the current system
+# to be used in the rescue/recovery system via automated update of KERNEL_CMDLINE.
-# Scanning current kernel cmdline to look for important option ($COPY_KERNEL_PARAMETERS) to include in KERNEL_CMDLINE
-for current_kernel_option in $( cat /proc/cmdline ); do
+# Also protect the rescue/recovery system by removing net.ifnames=0 from KERNEL_CMDLINE
+# if net.ifnames=0 is in KERNEL_CMDLINE but persistent network interface naming is used:
+local persistent_naming='no'
+is_persistent_ethernet_name $( ip route | awk '$2 == "dev" && $8 == "src" { print $3 }' | sort -u | head -n1 ) && persistent_naming='yes'
+
+# Scan current kernel cmdline for options in COPY_KERNEL_PARAMETERS to be included in KERNEL_CMDLINE:
+local current_kernel_option
+local new_kernel_options_to_add=()
+for current_kernel_option in $( cat /proc/cmdline ) ; do
# Get the current kernel option name (part before leftmost "=") and
# add the whole option (with value) to new_kernel_options_to_add array
# if the option name is part of COPY_KERNEL_PARAMETERS array:
@@ -11,41 +18,45 @@ for current_kernel_option in $( cat /proc/cmdline ); do
fi
done
-# Verify if the kernel option we want to add to KERNEL_CMDLINE are not already set/force by the user in the rear configuration.
-# If yes, the parameter set in the configuration file have the priority and superseed the current kernel option.
+# Check if the kernel options we want to add to KERNEL_CMDLINE are already set by the user in KERNEL_CMDLINE.
+# If yes, the user setting has priority and superseds the kernel option from the current system.
+# For the check use the existing KERNEL_CMDLINE when this script is started
+# and not the modified KERNEL_CMDLINE with already added kernel options
+# to make it possible to add several kernel options by this script
+# with same kernel option keyword like console=ttyS0,9600 console=tty0
+# see https://github.com/rear/rear/pull/2749#issuecomment-1197843273
+# and https://github.com/rear/rear/pull/2844
+local existing_kernel_cmdline="$KERNEL_CMDLINE"
+local existing_kernel_option new_kernel_option new_kernel_option_keyword
for new_kernel_option in "${new_kernel_options_to_add[@]}" ; do
new_kernel_option_keyword="${new_kernel_option%%=*}"
-
- for rear_kernel_option in $KERNEL_CMDLINE ; do
- # Check if a kernel option key without value parameter (everything before =) is not already present in rear KERNEL_CMDLINE array.
- if test "$new_kernel_option_keyword" = "${rear_kernel_option%%=*}" ; then
- Log "Current kernel option [$new_kernel_option] supperseeded by [$rear_kernel_option] in your rear configuration: (KERNEL_CMDLINE)"
+ for existing_kernel_option in $existing_kernel_cmdline ; do
+ if test "$new_kernel_option_keyword" = "${existing_kernel_option%%=*}" ; then
+ LogPrint "Not adding '$new_kernel_option' (superseded by existing '$existing_kernel_option' in KERNEL_CMDLINE)"
# Continue with the next new_kernel_option (i.e. continue the outer 'for' loop):
continue 2
fi
done
-
+ # If we are using persistent naming do not add net.ifnames to KERNEL_CMDLINE
+ # see https://github.com/rear/rear/pull/1874
+ # and continue with the next new_kernel_option:
if test "net.ifnames" = "$new_kernel_option_keyword" ; then
- # If we are using persistent naming do not add net.ifnames to KERNEL_CMDLINE
- # see https://github.com/rear/rear/pull/1874
- # and continue with the next new_kernel_option:
- is_persistent_ethernet_name $( ip r | awk '$2 == "dev" && $8 == "src" { print $3 }' | sort -u | head -1 ) && continue
+ if is_true $persistent_naming ; then
+ LogPrint "Not adding '$new_kernel_option' (persistent network interface naming is used)"
+ continue
+ fi
fi
-
- LogPrint "Adding $new_kernel_option to KERNEL_CMDLINE"
- KERNEL_CMDLINE="$KERNEL_CMDLINE $new_kernel_option"
+ LogPrint "Adding '$new_kernel_option' to KERNEL_CMDLINE"
+ KERNEL_CMDLINE+=" $new_kernel_option"
done
-# In case we added 'KERNEL_CMDLINE="$KERNEL_CMDLINE net.ifnames=0"' to /etc/rear/local.conf, but we have no idea if we
-# are using persistent naming or not then we should protect the rescue image from doing stupid things and remove
-# the keyword (and value) in a preventive way in case "persistent naming is in use".
-# And, to be clear the /proc/cmdline did not contain the keyword net.ifnames
-
-if is_persistent_ethernet_name $( ip r | awk '$2 == "dev" && $8 == "src" { print $3 }' | sort -u | head -1 ) ; then
- # persistent naming is in use
- # When the KERNEL_CMDLINE does NOT contain net.ifnames=0 silently return
- echo $KERNEL_CMDLINE | grep -q 'net.ifnames=0' || return
- # Remove net.ifnames=0 from KERNEL_CMDLINE
- KERNEL_CMDLINE=$( echo $KERNEL_CMDLINE | sed -e 's/net.ifnames=0//' )
- LogPrint "Removing net.ifnames=0 from KERNEL_CMDLINE"
+# The user may have added 'net.ifnames=0' to KERNEL_CMDLINE in /etc/rear/local.conf
+# but he may not know whether or not persistent naming is used.
+# So we should protect the rescue/recovery system from doing "stupid things"
+# and remove 'net.ifnames=0' in a preventive way when persistent naming is used:
+if is_true $persistent_naming ; then
+ if echo $KERNEL_CMDLINE | grep -q 'net.ifnames=0' ; then
+ KERNEL_CMDLINE=$( echo $KERNEL_CMDLINE | sed -e 's/net.ifnames=0//' )
+ LogPrint "Removed 'net.ifnames=0' from KERNEL_CMDLINE (persistent network interface naming is used)"
+ fi
fi
commit 42e04f36f5f8eea0017915bb35e56ee285b394d7
Merge: 7c6296db 940fede7
Author: Johannes Meixner <jsmeix@suse.com>
Date: Tue Jan 31 13:13:56 2023 +0100
Merge pull request #2915 from rear/jsmeix-serial-devs-fail-safe
In lib/serial-functions.sh make the
get_serial_console_devices() function
fail-safe if no serial device node exists, see
https://github.com/rear/rear/issues/2914
diff --git a/usr/share/rear/lib/serial-functions.sh b/usr/share/rear/lib/serial-functions.sh
index aac5dc88..3d421b52 100644
--- a/usr/share/rear/lib/serial-functions.sh
+++ b/usr/share/rear/lib/serial-functions.sh
@@ -1,13 +1,24 @@
# Get available serial devices:
function get_serial_console_devices () {
- test "$SERIAL_CONSOLE_DEVICES" && echo $SERIAL_CONSOLE_DEVICES || ls /dev/ttyS[0-9]* /dev/hvsi[0-9]* | sort
+ # Via SERIAL_CONSOLE_DEVICES the user specifies which ones to use (and no others):
+ if test "$SERIAL_CONSOLE_DEVICES" ; then
+ echo $SERIAL_CONSOLE_DEVICES
+ return 0
+ fi
+ # Test if there is /dev/ttyS[0-9]* or /dev/hvsi[0-9]*
+ # because when there is neither /dev/ttyS[0-9]* nor /dev/hvsi[0-9]*
+ # the ls command below would become plain 'ls' because of 'nullglob'
+ # cf. "Beware of the emptiness" in https://github.com/rear/rear/wiki/Coding-Style
+ # see https://github.com/rear/rear/issues/2914#issuecomment-1396659184
+ # and return 0 because it is no error when no serial device node exists
+ test "$( echo -n /dev/ttyS[0-9]* /dev/hvsi[0-9]* )" || return 0
# Use plain 'sort' which results /dev/ttyS0 /dev/ttyS1 /dev/ttyS10 ... /dev/ttyS19 /dev/ttyS2 /dev/ttyS20 ...
# to get at least /dev/ttyS0 and /dev/ttyS1 before the other /dev/ttyS* devices because
# we cannot use "sort -V" which would result /dev/ttyS0 /dev/ttyS1 ... /dev/ttyS9 /dev/ttyS10 ...
# because in older Linux distributions 'sort' does not support '-V' e.g. SLES10 with GNU coreutils 5.93
# (SLES11 with GNU coreutils 8.12 supports 'sort -V') but if 'sort' fails there is no output at all
- # cf. "Maintain backward compatibility" at https://github.com/rear/rear/wiki/Coding-Style
+ # cf. "Maintain backward compatibility" in https://github.com/rear/rear/wiki/Coding-Style
# Furthermore 'sort' results that /dev/hvsi* devices appear before /dev/ttyS* devices
# so the create_grub2_serial_entry function in lib/bootloader-functions.sh
# which uses by default the first one and skips the rest will result that
@@ -16,7 +27,8 @@ function get_serial_console_devices () {
# that have the HVSI driver loaded (a console driver for IBM's p5 servers)
# cf. https://lwn.net/Articles/98442/
# and it seems right that when special console drivers are loaded
- # then their devices should be preferred by default.
+ # then their devices should be preferred by default:
+ ls /dev/ttyS[0-9]* /dev/hvsi[0-9]* | sort
}
# Get the serial device speed for those device nodes that belong to actual serial devices.
commit 07da02143b5597b202e66c187e53103561018255
Merge: 91942f63 75a23e79
Author: Johannes Meixner <jsmeix@suse.com>
Date: Fri Oct 20 14:45:23 2023 +0200
Merge pull request #2961 from rear/jsmeix-copy-serial-console
For the automated serial console setup for the recovery system
use only the 'console=...' kernel arguments from the original system
which fixes https://github.com/rear/rear/issues/2843
and it means that no longer all "real serial devices" get
auto-enabled as serial consoles in the recovery system, see
https://github.com/rear/rear/pull/2749#issuecomment-1196650631
That new default behaviour is described in default.conf.
In particular prep/GNU/Linux/200_include_serial_console.sh
and lib/serial-functions.sh were overhauled which results
that rescue/GNU/Linux/400_use_serial_console.sh is obsolete.
Cherry-picked-by: Lukáš Zaoral <lzaoral@redhat.com>
diff --git a/usr/share/rear/conf/default.conf b/usr/share/rear/conf/default.conf
index ec1691b6..76355fb8 100644
--- a/usr/share/rear/conf/default.conf
+++ b/usr/share/rear/conf/default.conf
@@ -3320,39 +3320,90 @@ SIMPLIFY_TEAMING=no
SIMPLIFY_TEAMING=no
# Serial console support for the ReaR rescue/recovery system:
-# By default serial consoles get enabled if serial devices are found and
-# then matching kernel command line parameters like 'console=ttyS0,9600 console=ttyS1,9600'
-# are set when booting the rescue/recovery system (see KERNEL_CMDLINE above).
# IA64 platforms require it and people need it when no VGA console is available.
-# Specify 'yes' or 'no' or leave it empty to use ReaR's automatism:
+# By default there is serial console support in the ReaR recovery system
+# when 'getty' or 'agetty' and 'stty' can be found,
+# otherwise USE_SERIAL_CONSOLE is automatically set to 'no'.
+# When 'getty' or 'agetty' and 'stty' can be found
+# and there is a 'console=...' option in /proc/cmdline,
+# then USE_SERIAL_CONSOLE is automatically set to 'yes'.
+# With USE_SERIAL_CONSOLE="no" no serial console gets set up,
+# neither for the recovery system kernel nor for the recovery system bootloader.
+# With USE_SERIAL_CONSOLE="yes" plus appropriate SERIAL_CONSOLE_DEVICE... settings
+# serial consoles can be specified for the recovery system kernel and bootloader
+# for example when there is no 'console=...' option in /proc/cmdline
+# or when serial consoles for the recovery system kernel and bootloader
+# should differ from what 'console=...' options in /proc/cmdline tell.
+# By default (when empty) the automatism further described below is used:
USE_SERIAL_CONSOLE=
-# If you do not want to use all serial devices found as console you can specify the ones to use
-# e.g. SERIAL_CONSOLE_DEVICES="/dev/ttyS0 /dev/ttyS1" provided USE_SERIAL_CONSOLE is turned on.
-# By default (when empty) all serial devices found are used:
+#
+# Devices to be used in general for serial console setup
+# unless explicitly specified via SERIAL_CONSOLE_DEVICES_KERNEL
+# or SERIAL_CONSOLE_DEVICE_SYSLINUX or SERIAL_CONSOLE_DEVICE_GRUB:
+# E.g. SERIAL_CONSOLE_DEVICES="/dev/ttyS0 /dev/ttyS1"
SERIAL_CONSOLE_DEVICES=
-# Serial consoles for the kernel of the recovery system:
+#
+# Serial consoles for the kernel of the recovery system
+# provided USE_SERIAL_CONSOLE is not 'no':
# SERIAL_CONSOLE_DEVICES_KERNEL can be device nodes like "/dev/ttyS0 /dev/ttyS1"
# or 'console=...' kernel parameters like "console=ttyS1,9600 console=tty0" or both like
# SERIAL_CONSOLE_DEVICES_KERNEL="/dev/ttyS0 console=ttyS1,9600 console=tty0"
-# provided USE_SERIAL_CONSOLE is turned on.
-# By default (when empty) the SERIAL_CONSOLE_DEVICES are used for the kernel:
+# When SERIAL_CONSOLE_DEVICES_KERNEL is empty but SERIAL_CONSOLE_DEVICES is specified
+# then the specified SERIAL_CONSOLE_DEVICES are used for the kernel.
+# By default (when SERIAL_CONSOLE_DEVICES_KERNEL and SERIAL_CONSOLE_DEVICES are empty)
+# serial consoles get enabled for the recovery system kernel via COPY_KERNEL_PARAMETERS
+# for all 'console=...' options that are found in /proc/cmdline.
SERIAL_CONSOLE_DEVICES_KERNEL=
-# Serial console for SYSLINUX/EXTLINUX when it is used as bootloader for the recovery system:
+#
+# Serial console for SYSLINUX/EXTLINUX when it is used as bootloader for the recovery system
+# provided USE_SERIAL_CONSOLE is 'yes' (automatically with 'console=...' in /proc/cmdline):
# SYSLINUX supports only one serial device (because the last SYSLINUX 'serial' directive wins).
# The right /dev/ttyS* can be specified like SERIAL_CONSOLE_DEVICE_SYSLINUX="/dev/ttyS0"
# or a whole SYSLINUX 'serial' directive can be specified e.g. for /dev/ttyS1 like
# SERIAL_CONSOLE_DEVICE_SYSLINUX="serial 1 9600"
-# provided USE_SERIAL_CONSOLE is turned on.
-# By default (when empty) the first one of SERIAL_CONSOLE_DEVICES is used for SYSLINUX:
+# When SERIAL_CONSOLE_DEVICE_SYSLINUX is empty but SERIAL_CONSOLE_DEVICES is specified
+# then the first one of SERIAL_CONSOLE_DEVICES is used for SYSLINUX.
+# By default (when SERIAL_CONSOLE_DEVICE_SYSLINUX and SERIAL_CONSOLE_DEVICES are empty)
+# the devices of the 'console=...' options in /proc/cmdline
+# that exist as /dev/ttyS* or /dev/hvsi* character device nodes are used
+# (which excludes /dev/tty0 when there is 'console=tty0' in /proc/cmdline).
SERIAL_CONSOLE_DEVICE_SYSLINUX=
-# Serial console for GRUB when it is used as bootloader for the recovery system:
+#
+# Serial console for GRUB when it is used as bootloader for the recovery system
+# provided USE_SERIAL_CONSOLE is 'yes' (automatically with 'console=...' in /proc/cmdline):
# GRUB supports only one serial device (because the last GRUB 'serial' command wins).
# The right /dev/ttyS* can be specified like SERIAL_CONSOLE_DEVICE_GRUB="/dev/ttyS0"
# or a whole GRUB 'serial' command can be specified e.g. for /dev/ttyS1 like
# SERIAL_CONSOLE_DEVICE_GRUB="serial --unit=1 --speed=9600"
-# provided USE_SERIAL_CONSOLE is turned on.
-# By default (when empty) the first one of SERIAL_CONSOLE_DEVICES is used for GRUB:
+# When SERIAL_CONSOLE_DEVICE_GRUB is empty but SERIAL_CONSOLE_DEVICES is specified
+# then the first one of SERIAL_CONSOLE_DEVICES is used for GRUB.
+# By default (when SERIAL_CONSOLE_DEVICE_GRUB and SERIAL_CONSOLE_DEVICES are empty)
+# the devices of the 'console=...' options in /proc/cmdline
+# that exist as /dev/ttyS* or /dev/hvsi* character device nodes are used
+# (which excludes /dev/tty0 when there is 'console=tty0' in /proc/cmdline).
SERIAL_CONSOLE_DEVICE_GRUB=
+#
+# Examples
+# (provided USE_SERIAL_CONSOLE is not 'no'
+# and 'getty' or 'agetty' and 'stty' can be found):
+#
+# Default behaviour
+# when there is no 'console=...' option in /proc/cmdline
+# then no serial console is set up for the recovery system.
+#
+# Default behaviour when there are for example
+# 'console=ttyS0,9600' and 'console=tty0' in /proc/cmdline
+# then 'console=ttyS0,9600' and 'console=tty0'
+# are used for the recovery system kernel
+# and only /dev/ttyS0 is used as serial console
+# for the recovery system bootloader (SYSLINUX or GRUB).
+#
+# On a headless machine without VGA card but with serial device /dev/ttyS0
+# the kernel would choose /dev/ttyS0 as its console automatically
+# so no 'console=...' kernel option needs to be used and then the automatism described above
+# would not set up a console for the recovery system (in particular not for the bootloader).
+# In this case USE_SERIAL_CONSOLE="yes" and appropriate SERIAL_CONSOLE_DEVICE... settings
+# are needed to manually specify the right console setup for the recovery system.
# Say "y", "Yes", etc, to enable or "n", "No" etc. to disable the DHCP client protocol or leave empty to autodetect.
# When enabled, lets the rescue/recovery system run dhclient to get an IP address
# instead of using the same IP address as the original system:
diff --git a/usr/share/rear/lib/serial-functions.sh b/usr/share/rear/lib/serial-functions.sh
index 3d421b52..a586d357 100644
--- a/usr/share/rear/lib/serial-functions.sh
+++ b/usr/share/rear/lib/serial-functions.sh
@@ -6,29 +6,34 @@ function get_serial_console_devices () {
echo $SERIAL_CONSOLE_DEVICES
return 0
fi
- # Test if there is /dev/ttyS[0-9]* or /dev/hvsi[0-9]*
- # because when there is neither /dev/ttyS[0-9]* nor /dev/hvsi[0-9]*
- # the ls command below would become plain 'ls' because of 'nullglob'
- # cf. "Beware of the emptiness" in https://github.com/rear/rear/wiki/Coding-Style
- # see https://github.com/rear/rear/issues/2914#issuecomment-1396659184
- # and return 0 because it is no error when no serial device node exists
- test "$( echo -n /dev/ttyS[0-9]* /dev/hvsi[0-9]* )" || return 0
- # Use plain 'sort' which results /dev/ttyS0 /dev/ttyS1 /dev/ttyS10 ... /dev/ttyS19 /dev/ttyS2 /dev/ttyS20 ...
- # to get at least /dev/ttyS0 and /dev/ttyS1 before the other /dev/ttyS* devices because
- # we cannot use "sort -V" which would result /dev/ttyS0 /dev/ttyS1 ... /dev/ttyS9 /dev/ttyS10 ...
- # because in older Linux distributions 'sort' does not support '-V' e.g. SLES10 with GNU coreutils 5.93
- # (SLES11 with GNU coreutils 8.12 supports 'sort -V') but if 'sort' fails there is no output at all
- # cf. "Maintain backward compatibility" in https://github.com/rear/rear/wiki/Coding-Style
- # Furthermore 'sort' results that /dev/hvsi* devices appear before /dev/ttyS* devices
- # so the create_grub2_serial_entry function in lib/bootloader-functions.sh
- # which uses by default the first one and skips the rest will result that
- # the first /dev/hvsi* device becomes used for the GRUB serial console by default
- # which looks right because /dev/hvsi* devices should exist only on systems
- # that have the HVSI driver loaded (a console driver for IBM's p5 servers)
- # cf. https://lwn.net/Articles/98442/
- # and it seems right that when special console drivers are loaded
- # then their devices should be preferred by default:
- ls /dev/ttyS[0-9]* /dev/hvsi[0-9]* | sort
+ # Scan the kernel command line of the currently running original system
+ # for 'console=<device>[,<options>]' settings e.g. 'console=ttyS1,9600n8 ... console=ttyS3 ... console=tty0'
+ # and extract the specified serial device nodes e.g. ttyS1 -> /dev/ttyS1 ... ttyS3 -> /dev/ttyS3
+ local kernel_option console_option_value console_option_device
+ for kernel_option in $( cat /proc/cmdline ) ; do
+ # Continue with next kernel option when the option name (part before leftmost "=") is not 'console':
+ test "${kernel_option%%=*}" = "console" || continue
+ # Get the console option value (part after leftmost "=") e.g. 'ttyS1,9600n8' 'ttyS3' 'tty0'
+ console_option_value="${kernel_option#*=}"
+ # Get the console option device (part before leftmost optional ',' separator) e.g. 'ttyS1' 'ttyS3' 'tty0'
+ console_option_device="${console_option_value%%,*}"
+ # Continue with next kernel option when the current console option device is no serial device (exclude 'tty0').
+ # The special /dev/hvsi* devices should exist only on systems that have the HVSI driver loaded
+ # (a console driver for IBM's p5 servers) cf. https://lwn.net/Articles/98442/
+ [[ $console_option_device == ttyS* ]] || [[ $console_option_device == hvsi* ]] || continue
+ # Test that the matching serial device node e.g. ttyS1 -> /dev/ttyS1 and ttyS3 -> /dev/ttyS3' exists
+ # to avoid that this automated serial console setup may not work in the ReaR recovery system
+ # when serial device nodes get specified for the recovery system that do not exist
+ # in the currently running original system because the default assumption is
+ # that the replacement system has same hardware as the original system,
+ # cf. https://github.com/rear/rear/pull/2749#issuecomment-1196650631
+ # (if needed the user can specify what he wants via SERIAL_CONSOLE_DEVICES, see above):
+ if ! test -c "/dev/$console_option_device" ; then
+ LogPrintError "Found '$kernel_option' in /proc/cmdline but '/dev/$console_option_device' is no character device"
+ continue
+ fi
+ echo /dev/$console_option_device
+ done
}
# Get the serial device speed for those device nodes that belong to actual serial devices.
@@ -39,64 +44,15 @@ function get_serial_device_speed () {
# Run it in a subshell so that 'set -o pipefail' does not affect the current shell and
# it can run in a subshell because the caller of this function only needs its stdout
# cf. the function get_root_disk_UUID in lib/bootloader-functions.sh
- # so when stty fails the get_serial_device_speed return code is the stty exit code and not the awk exit code
- # therefore one can call get_serial_device_speed with error checking for example like
+ # so when stty fails the get_serial_device_speed return code is the stty exit code and not the awk exit code.
+ # Therefore one can call get_serial_device_speed with error checking for example like
# speed=$( get_serial_device_speed $serial_device ) && COMMAND_WITH_speed || COMMAND_WITHOUT_speed
- # because the return code of variable=$( PIPE ) is the return code of the pipe,
- # cf. how get_serial_device_speed is called in cmdline_add_console below.
+ # because the return code of variable=$( PIPE ) is the return code of the pipe
+ # cf. how get_serial_device_speed is called in lib/bootloader-functions.sh
+ # and output/USB/Linux-i386/300_create_extlinux.sh
# Suppress stty stderr output because for most /dev/ttyS* device nodes the result is
# stty: /dev/ttyS...: Input/output error
# when the device node does not belong to an actual serial device (i.e. to real serial hardware)
# so get_serial_device_speed is also used to get those device nodes that belong to real serial devices:
( set -o pipefail ; stty -F $devnode 2>/dev/null | awk '/^speed / { print $2 }' )
}
-
-# Add serial console to kernel cmdline:
-function cmdline_add_console {
- # Nothing to do when using serial console is not wanted:
- is_true "$USE_SERIAL_CONSOLE" || return 0
-
- # Strip existing 'console=...' kernel cmd parameters:
- local param cmdline=""
- for param in $KERNEL_CMDLINE ; do
- case "$param" in
- (console=*) ;;
- (*) cmdline+=" $param";;
- esac
- done
-
- # Add serial console config to kernel cmd line:
- local devnode speed=""
- if test "$SERIAL_CONSOLE_DEVICES_KERNEL" ; then
- # When the user has specified SERIAL_CONSOLE_DEVICES_KERNEL use only that (no automatisms):
- for devnode in $SERIAL_CONSOLE_DEVICES_KERNEL ; do
- # devnode can be a character device node like "/dev/ttyS0" or "/dev/lp0" or "/dev/ttyUSB0"
- # cf. https://www.kernel.org/doc/html/latest/admin-guide/serial-console.html
- # or devnode can be a 'console=...' kernel cmd parameter like "console=ttyS1,9600"
- if test -c "$devnode" ; then
- if speed=$( get_serial_device_speed $devnode ) ; then
- cmdline+=" console=${devnode##/dev/},$speed"
- else
- cmdline+=" console=${devnode##/dev/}"
- fi
- else
- # When devnode is a 'console=...' kernel cmd parameter use it as specified:
- cmdline+=" $devnode"
- fi
- done
- else
- local real_consoles=""
- for devnode in $( get_serial_console_devices ) ; do
- # Only add for those device nodes that belong to actual serial devices:
- speed=$( get_serial_device_speed $devnode ) && real_consoles+=" console=${devnode##/dev/},$speed"
- done
- cmdline+=" $real_consoles"
-
- # Add fallback console if no real serial device was found:
- test "$real_consoles" || cmdline+=" console=tty0"
- fi
-
- # Have a trailing space to be on the safe side
- # so that more kernel cmd parameters could be "just appended" by other scripts:
- echo "$cmdline "
-}
diff --git a/usr/share/rear/prep/GNU/Linux/200_include_serial_console.sh b/usr/share/rear/prep/GNU/Linux/200_include_serial_console.sh
index 214af3c4..14ec113e 100644
--- a/usr/share/rear/prep/GNU/Linux/200_include_serial_console.sh
+++ b/usr/share/rear/prep/GNU/Linux/200_include_serial_console.sh
@@ -1,31 +1,115 @@
-# If possible auto-enable serial console when not specified:
-if [[ -z "$USE_SERIAL_CONSOLE" ]] ; then
- local devnode speed=""
- for devnode in $( get_serial_console_devices ) ; do
- # Enable serial console when there is at least one real serial device:
- if speed=$( get_serial_device_speed $devnode ) ; then
- USE_SERIAL_CONSOLE="yes"
- break
- fi
- done
-fi
+# This script prep/GNU/Linux/200_include_serial_console.sh
+# is the first ...console... script that is run for "rear mkrescue/mkbackup".
+#
+# When USE_SERIAL_CONSOLE is empty then this script decides
+# if USE_SERIAL_CONSOLE is kept empty
+# or (provided there is sufficient reason)
+# it sets USE_SERIAL_CONSOLE to 'no' or 'yes'.
+# It sets USE_SERIAL_CONSOLE to 'no'
+# when serial consoles cannot work in the recovery system.
+# It sets USE_SERIAL_CONSOLE to 'yes'
+# when a serial console will be set up for the recovery system kernel.
+# Only when a serial console will be actually set up for the recovery system kernel,
+# then it makes sense to also set up a serial console for the recovery system bootloader.
+# So serial console setup for the recovery system bootloader is only done if USE_SERIAL_CONSOLE="yes"
+# because an empty USE_SERIAL_CONSOLE must not result serial console setup for the recovery system bootloader
+# (without actual serial console setup for the recovery system kernel).
-# Always include getty or agetty as we don't know in advance whether they are needed
+# Always try to include getty or agetty as we do not know in advance whether they are needed
# (the user may boot the recovery system with manually specified kernel options
# to get serial console support in his recovery system).
-# For serial support we need to include the agetty binary,
-# but Debian distro's use getty instead of agetty:
-local getty_binary=""
+# For serial console support we need to include 'getty' or 'agetty'.
+# Debian distributions (in particular Ubuntu) use 'getty'.
+# Fedora, RHEL, SLES,... use 'agetty'.
if has_binary getty ; then
- # Debian, Ubuntu,...
- getty_binary="getty"
+ PROGS+=( getty )
elif has_binary agetty ; then
- # Fedora, RHEL, SLES,...
- getty_binary="agetty"
+ PROGS+=( agetty )
+else
+ is_true "$USE_SERIAL_CONSOLE" && Error "Failed to find 'getty' or 'agetty' (USE_SERIAL_CONSOLE is 'true')"
+ LogPrintError "No serial console support (failed to find 'getty' or 'agetty')"
+ USE_SERIAL_CONSOLE="no"
+fi
+
+# Also try to include 'stty' which is (currently) only needed for serial console support
+# in skel/default/etc/scripts/system-setup.d/45-serial-console.sh
+# and lib/serial-functions.sh
+if has_binary stty ; then
+ PROGS+=( stty )
else
- # The user must have the programs in REQUIRED_PROGS installed on his system:
- Error "Failed to find 'getty' or 'agetty' for serial console"
+ is_true "$USE_SERIAL_CONSOLE" && Error "Failed to find 'stty' (USE_SERIAL_CONSOLE is 'true')"
+ LogPrintError "No serial console support (failed to find 'stty')"
+ USE_SERIAL_CONSOLE="no"
fi
-REQUIRED_PROGS+=( "$getty_binary" stty )
+# Auto-enable serial console support for the recovery system
+# provided console support is not impossible because there is no getty or agetty and stty
+# and unless the user specified to not have serial console support:
+is_false "$USE_SERIAL_CONSOLE" && return 0
+
+# When the user has specified SERIAL_CONSOLE_DEVICES_KERNEL use only that,
+# otherwise use SERIAL_CONSOLE_DEVICES if the user has specified it:
+local serial_console_devices=""
+test "$SERIAL_CONSOLE_DEVICES" && serial_console_devices="$SERIAL_CONSOLE_DEVICES"
+test "$SERIAL_CONSOLE_DEVICES_KERNEL" && serial_console_devices="$SERIAL_CONSOLE_DEVICES_KERNEL"
+if test "$serial_console_devices" ; then
+ local serial_console speed="" cmdline_add_console=""
+ for serial_console in $serial_console_devices ; do
+ # serial_console can be a character device node like "/dev/ttyS0" or "/dev/lp0" or "/dev/ttyUSB0"
+ # cf. https://www.kernel.org/doc/html/latest/admin-guide/serial-console.html
+ # or serial_console can be a 'console=...' kernel cmd parameter like "console=ttyS1,9600"
+ if test -c "$serial_console" ; then
+ if speed=$( get_serial_device_speed $serial_console ) ; then
+ cmdline_add_console+=" console=${serial_console##/dev/},$speed"
+ else
+ cmdline_add_console+=" console=${serial_console##/dev/}"
+ fi
+ else
+ # When serial_console is not a character device
+ # it should be a 'console=...' kernel cmd parameter
+ # that is used as specified ("final power to the user"):
+ cmdline_add_console+=" $serial_console"
+ fi
+ done
+ if test "$cmdline_add_console" ; then
+ KERNEL_CMDLINE+="$cmdline_add_console"
+ DebugPrint "Appended '$cmdline_add_console' to KERNEL_CMDLINE"
+ USE_SERIAL_CONSOLE="yes"
+ # No further automatisms when a 'console=...' kernel cmd parameter was set
+ # via SERIAL_CONSOLE_DEVICES_KERNEL or SERIAL_CONSOLE_DEVICES:
+ return
+ fi
+ LogPrintError "SERIAL_CONSOLE_DEVICES_KERNEL or SERIAL_CONSOLE_DEVICES specified but none is a character device"
+fi
+
+# Auto-enable serial console support for the recovery system kernel:
+# The below auto-enable serial console support for the recovery system kernel
+# does not auto-enable serial console support for the recovery system bootloader.
+# Currently auto-enable serial console support for the recovery system bootloader
+# happens for the first real serial device from get_serial_console_devices()
+# in lib/bootloader-functions.sh in make_syslinux_config() and create_grub2_cfg()
+# and in output/USB/Linux-i386/300_create_extlinux.sh
+# The auto-enable serial console support for the recovery system bootloader should be
+# auto-aligned with the auto-enable serial console support for the recovery system kernel.
+# Things are auto-aligned when the first 'console=...' device in /proc/cmdline
+# is also the first real serial device from get_serial_console_devices().
+# When current auto-alignment does not result what the user needs, what is needed can be specified
+# via SERIAL_CONSOLE_DEVICES_KERNEL and SERIAL_CONSOLE_DEVICE_SYSLINUX or SERIAL_CONSOLE_DEVICE_GRUB.
+
+# Scan the kernel command line of the currently running original system
+# and auto-enable serial console for the recovery system kernel
+# only if there is at least one 'console=...' option:
+local kernel_option
+for kernel_option in $( cat /proc/cmdline ) ; do
+ # Get the kernel option name (part before leftmost "="):
+ if test "${kernel_option%%=*}" = "console" ; then
+ USE_SERIAL_CONSOLE="yes"
+ # Get all 'console=...' kernel command line options
+ # copied from the currently running original system
+ # via rescue/GNU/Linux/290_kernel_cmdline.sh that runs later:
+ COPY_KERNEL_PARAMETERS+=( console )
+ return
+ fi
+done
+DebugPrint "No 'console=...' setting for recovery system kernel (none in /proc/cmdline)"
diff --git a/usr/share/rear/rescue/GNU/Linux/400_use_serial_console.sh b/usr/share/rear/rescue/GNU/Linux/400_use_serial_console.sh
deleted file mode 100644
index fc935844..00000000
--- a/usr/share/rear/rescue/GNU/Linux/400_use_serial_console.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-
-# Nothing to do when using serial console is not wanted:
-is_true "$USE_SERIAL_CONSOLE" || return 0
-
-KERNEL_CMDLINE=$( cmdline_add_console )
-Log "Modified kernel commandline to: '$KERNEL_CMDLINE'"

View File

@ -1,33 +0,0 @@
commit 41c2d9b1fbcece4b0890ab92e9f5817621917ad3 (from 23977a19101b6e6eaeebbe8ce013332ddf9ea517)
Merge: 23977a19 686012cb
Author: Johannes Meixner <jsmeix@suse.com>
Date: Thu Jul 20 15:11:52 2023 +0200
Merge pull request #3027 from rmetrich/shrinking_file
In build/GNU/Linux/100_copy_as_is.sh
ensure to really get all COPY_AS_IS files copied by using
'tar ... -i' when extracting to avoid a false regular exit of 'tar'
in particular when padding zeroes get added when a file being read shrinks
because for 'tar' (without '-i') two consecutive 512-blocks of zeroes mean EOF,
cf. https://github.com/rear/rear/pull/3027
diff --git a/usr/share/rear/build/GNU/Linux/100_copy_as_is.sh b/usr/share/rear/build/GNU/Linux/100_copy_as_is.sh
index e8f2be20..2169efaa 100644
--- a/usr/share/rear/build/GNU/Linux/100_copy_as_is.sh
+++ b/usr/share/rear/build/GNU/Linux/100_copy_as_is.sh
@@ -110,9 +110,13 @@ done >$copy_as_is_exclude_file
# COPY_AS_IS+=( /path/to/directory/* )
# which are used in our scripts and by users in their etc/rear/local.conf
# cf. https://github.com/rear/rear/pull/2405#issuecomment-633512932
+# Using '-i' when extracting is necessary to avoid a false regular exit of 'tar'
+# in particular when padding zeroes get added when a file being read shrinks
+# because for 'tar' (without '-i') two consecutive 512-blocks of zeroes mean EOF,
+# cf. https://github.com/rear/rear/pull/3027
# FIXME: The following code fails if file names contain characters from IFS (e.g. blanks),
# cf. https://github.com/rear/rear/issues/1372
-if ! tar -v -X $copy_as_is_exclude_file -P -C / -c ${COPY_AS_IS[*]} 2>$copy_as_is_filelist_file | tar $v -C $ROOTFS_DIR/ -x 1>/dev/null ; then
+if ! tar -v -X $copy_as_is_exclude_file -P -C / -c ${COPY_AS_IS[*]} 2>$copy_as_is_filelist_file | tar $v -C $ROOTFS_DIR/ -x -i 1>/dev/null ; then
Error "Failed to copy files and directories in COPY_AS_IS minus COPY_AS_IS_EXCLUDE"
fi
Log "Finished copying files and directories in COPY_AS_IS minus COPY_AS_IS_EXCLUDE"

View File

@ -1,321 +0,0 @@
commit ec9080664303165799a215cef062826b65f6a6f8
Author: Johannes Meixner <jsmeix@suse.com>
Date: Fri Apr 12 15:25:28 2024 +0200
New unique_unsorted() function (#3177)
In lib/global-functions.sh added a
new unique_unsorted() function
that outputs lines in a file or from STDIN
without subsequent duplicate lines
which keeps the ordering of the lines, see
https://github.com/rear/rear/pull/3177
In backup/NETFS/default/500_make_backup.sh use
unique_unsorted $TMP_DIR/backup-include.txt
to ignore duplicate arguments provided
to 'tar' and 'rsync' what should be archived
to avoid that 'tar' and 'rsync' archive
exact same things multiple times
which needlessly increases backup time and
in case of 'tar' the backup archive size and
storage space and backup restore time, cf.
https://github.com/rear/rear/pull/3175#issuecomment-1985306750
Cherry-picked-by: Lukáš Zaoral <lzaoral@redhat.com>
diff --git a/usr/share/rear/backup/NETFS/default/500_make_backup.sh b/usr/share/rear/backup/NETFS/default/500_make_backup.sh
index feb4d322..fba03338 100644
--- a/usr/share/rear/backup/NETFS/default/500_make_backup.sh
+++ b/usr/share/rear/backup/NETFS/default/500_make_backup.sh
@@ -42,10 +42,10 @@ fi
# Log what is included in the backup and what is excluded from the backup
# cf. backup/NETFS/default/400_create_include_exclude_files.sh
-Log "Backup include list (backup-include.txt contents):"
+Log "Backup include list (backup-include.txt contents without subsequent duplicates):"
while read -r backup_include_item ; do
test "$backup_include_item" && Log " $backup_include_item"
-done < $TMP_DIR/backup-include.txt
+done < <( unique_unsorted $TMP_DIR/backup-include.txt )
Log "Backup exclude list (backup-exclude.txt contents):"
while read -r backup_exclude_item ; do
test "$backup_exclude_item" && Log " $backup_exclude_item"
@@ -127,7 +127,7 @@ case "$(basename ${BACKUP_PROG})" in
$BACKUP_PROG_CREATE_NEWER_OPTIONS \
${BACKUP_PROG_BLOCKS:+-b $BACKUP_PROG_BLOCKS} "${BACKUP_PROG_COMPRESS_OPTIONS[@]}" \
-X $TMP_DIR/backup-exclude.txt -C / -c -f - \
- $(cat $TMP_DIR/backup-include.txt) $RUNTIME_LOGFILE \| $BACKUP_PROG_CRYPT_OPTIONS BACKUP_PROG_CRYPT_KEY \| $SPLIT_COMMAND
+ $(unique_unsorted $TMP_DIR/backup-include.txt) $RUNTIME_LOGFILE \| $BACKUP_PROG_CRYPT_OPTIONS BACKUP_PROG_CRYPT_KEY \| $SPLIT_COMMAND
else
Log $BACKUP_PROG $TAR_OPTIONS --sparse --block-number --totals --verbose \
--no-wildcards-match-slash --one-file-system \
@@ -135,7 +135,7 @@ case "$(basename ${BACKUP_PROG})" in
$BACKUP_PROG_CREATE_NEWER_OPTIONS \
${BACKUP_PROG_BLOCKS:+-b $BACKUP_PROG_BLOCKS} "${BACKUP_PROG_COMPRESS_OPTIONS[@]}" \
-X $TMP_DIR/backup-exclude.txt -C / -c -f - \
- $(cat $TMP_DIR/backup-include.txt) $RUNTIME_LOGFILE \| $SPLIT_COMMAND
+ $(unique_unsorted $TMP_DIR/backup-include.txt) $RUNTIME_LOGFILE \| $SPLIT_COMMAND
fi
if is_true "$BACKUP_PROG_CRYPT_ENABLED" ; then
@@ -151,7 +151,7 @@ case "$(basename ${BACKUP_PROG})" in
${BACKUP_PROG_BLOCKS:+-b $BACKUP_PROG_BLOCKS} \
"${BACKUP_PROG_COMPRESS_OPTIONS[@]}" \
-X $TMP_DIR/backup-exclude.txt -C / -c -f - \
- $(cat $TMP_DIR/backup-include.txt) $RUNTIME_LOGFILE | \
+ $(unique_unsorted $TMP_DIR/backup-include.txt) $RUNTIME_LOGFILE | \
{ $BACKUP_PROG_CRYPT_OPTIONS "$BACKUP_PROG_CRYPT_KEY" ; } 2>/dev/null | \
$SPLIT_COMMAND
pipes_rc=( ${PIPESTATUS[@]} )
@@ -160,14 +160,14 @@ case "$(basename ${BACKUP_PROG})" in
"$(basename $(echo "$BACKUP_PROG" | awk '{ print $1 }'))"
"$(basename $(echo "$SPLIT_COMMAND" | awk '{ print $1 }'))"
)
- $BACKUP_PROG $TAR_OPTIONS --sparse --block-number --totals --verbose \
- --no-wildcards-match-slash --one-file-system \
- --ignore-failed-read "${BACKUP_PROG_OPTIONS[@]}" \
- $BACKUP_PROG_CREATE_NEWER_OPTIONS \
- ${BACKUP_PROG_BLOCKS:+-b $BACKUP_PROG_BLOCKS} \
- "${BACKUP_PROG_COMPRESS_OPTIONS[@]}" \
- -X $TMP_DIR/backup-exclude.txt -C / -c -f - \
- $(cat $TMP_DIR/backup-include.txt) $RUNTIME_LOGFILE | \
+ $BACKUP_PROG $TAR_OPTIONS --sparse --block-number --totals --verbose \
+ --no-wildcards-match-slash --one-file-system \
+ --ignore-failed-read "${BACKUP_PROG_OPTIONS[@]}" \
+ $BACKUP_PROG_CREATE_NEWER_OPTIONS \
+ ${BACKUP_PROG_BLOCKS:+-b $BACKUP_PROG_BLOCKS} \
+ "${BACKUP_PROG_COMPRESS_OPTIONS[@]}" \
+ -X $TMP_DIR/backup-exclude.txt -C / -c -f - \
+ $(unique_unsorted $TMP_DIR/backup-include.txt) $RUNTIME_LOGFILE | \
$SPLIT_COMMAND
pipes_rc=( ${PIPESTATUS[@]} )
fi
@@ -213,21 +213,21 @@ case "$(basename ${BACKUP_PROG})" in
mkdir -p $v "$backuparchive" >&2
Log $BACKUP_PROG --verbose "${BACKUP_RSYNC_OPTIONS[@]}" --one-file-system --delete \
--exclude-from=$TMP_DIR/backup-exclude.txt --delete-excluded \
- $(cat $TMP_DIR/backup-include.txt) "$backuparchive"
+ $(unique_unsorted $TMP_DIR/backup-include.txt) "$backuparchive"
$BACKUP_PROG --verbose "${BACKUP_RSYNC_OPTIONS[@]}" --one-file-system --delete \
--exclude-from=$TMP_DIR/backup-exclude.txt --delete-excluded \
- $(cat $TMP_DIR/backup-include.txt) "$backuparchive" >&2
+ $(unique_unsorted $TMP_DIR/backup-include.txt) "$backuparchive" >&2
;;
(*)
Log "Using unsupported backup program '$BACKUP_PROG'"
Log $BACKUP_PROG "${BACKUP_PROG_COMPRESS_OPTIONS[@]}" \
$BACKUP_PROG_OPTIONS_CREATE_ARCHIVE $TMP_DIR/backup-exclude.txt \
"${BACKUP_PROG_OPTIONS[@]}" "$backuparchive" \
- $(cat $TMP_DIR/backup-include.txt) $RUNTIME_LOGFILE > "$backuparchive"
+ $(unique_unsorted $TMP_DIR/backup-include.txt) $RUNTIME_LOGFILE > "$backuparchive"
$BACKUP_PROG "${BACKUP_PROG_COMPRESS_OPTIONS[@]}" \
$BACKUP_PROG_OPTIONS_CREATE_ARCHIVE $TMP_DIR/backup-exclude.txt \
"${BACKUP_PROG_OPTIONS[@]}" "$backuparchive" \
- $(cat $TMP_DIR/backup-include.txt) $RUNTIME_LOGFILE > "$backuparchive"
+ $(unique_unsorted $TMP_DIR/backup-include.txt) $RUNTIME_LOGFILE > "$backuparchive"
;;
esac 2> "${TMP_DIR}/${BACKUP_PROG_ARCHIVE}.log"
# For the rsync and default case the backup prog is the last in the case entry
diff --git a/usr/share/rear/lib/global-functions.sh b/usr/share/rear/lib/global-functions.sh
index 77263cb1..1fc083b4 100644
--- a/usr/share/rear/lib/global-functions.sh
+++ b/usr/share/rear/lib/global-functions.sh
@@ -14,6 +14,35 @@ function read_and_strip_file () {
sed -e '/^[[:space:]]/d;/^$/d;/^#/d' "$filename"
}
+# Output lines in STDIN or in a file without subsequent duplicate lines
+# i.e. for each line that was seen (and output) do not output subsequent duplicates of that line.
+# This keeps the ordering of the lines so the input
+# one
+# two
+# one
+# three
+# two
+# one
+# gets output as
+# one
+# two
+# three
+# To remove duplicate lines and keep the ordering one could use ... | cat -n | sort -uk2 | sort -nk1 | cut -f2-
+# cf. https://stackoverflow.com/questions/11532157/remove-duplicate-lines-without-sorting/11532197#11532197
+# that also explains an awk command that prints each line provided the line was not seen before.
+# The awk variable $0 holds an entire line and square brackets is associative array access in awk.
+# For each line the node of the associative array 'seen' is incremented and the line is printed
+# if the content of that node was not '!' previously set (i.e. if the line was not previously seen)
+# cf. https://www.thegeekstuff.com/2010/03/awk-arrays-explained-with-5-practical-examples/
+function unique_unsorted () {
+ local filename="$1"
+ if test "$filename" ; then
+ test -r "$filename" && awk '!seen[$0]++' "$filename"
+ else
+ awk '!seen[$0]++'
+ fi
+}
+
# Three functions to test
# if the argument is an integer
# if the argument is a positive integer (i.e. test for '> 0')
commit 2da70f54936e5c558c9f607b1526b9b17f6501b1
Author: Lukáš Zaoral <lzaoral@redhat.com>
Date: Fri Jul 12 10:44:04 2024 +0200
Automatically include mounted btrfs subvolumes in NETFS backups (#3175)
* automatically exclude btrfs snapshot subvolumes from 'btrfsmountedsubvol'
Related: https://github.com/rear/rear/pull/3175#issuecomment-1983498175
* automatically include mounted btrfs subvolumes in NETFS backups
... unless they are explicitly excluded.
Resolves: https://github.com/rear/rear/issues/2928
* always add the excluded component in RESTORE_EXCLUDE_FILE
Otherwise, the component itself would not be included if it had any child
components of the `fs` type.
* automatically exclude btrfs subvolume children of excluded components
Cherry-picked-by: Lukáš Zaoral <lzaoral@redhat.com>
diff --git a/usr/share/rear/layout/prepare/default/610_exclude_from_restore.sh b/usr/share/rear/layout/prepare/default/610_exclude_from_restore.sh
index 0a902041..1e7522b2 100644
--- a/usr/share/rear/layout/prepare/default/610_exclude_from_restore.sh
+++ b/usr/share/rear/layout/prepare/default/610_exclude_from_restore.sh
@@ -7,24 +7,33 @@ RESTORE_EXCLUDE_FILE="$TMP_DIR/restore-exclude-list.txt"
: >"$RESTORE_EXCLUDE_FILE"
+local component
+
for component in "${EXCLUDE_RECREATE[@]}" ; do
if ! IsInArray "$component" "${EXCLUDE_RESTORE[@]}" ; then
EXCLUDE_RESTORE+=( "$component" )
fi
done
+local comp_type children child
+local comp_types=( "btrfsmountedsubvol" "fs" )
+
for component in "${EXCLUDE_RESTORE[@]}" ; do
- fs_children=$(get_child_components "$component" "fs" | sort -u)
- if [ -n "$fs_children" ] ; then
- for child in $fs_children ; do
- child=${child#fs:}
- echo "${child#/}" >> "$RESTORE_EXCLUDE_FILE"
- echo "${child#/}/*" >> "$RESTORE_EXCLUDE_FILE"
- done
- else
- # if there are no fs deps, assume it is a wildcard path
- component=${component#fs:}
- echo "${component#/}" >> "$RESTORE_EXCLUDE_FILE"
- echo "${component#/}/*" >> "$RESTORE_EXCLUDE_FILE"
- fi
+ for comp_type in "${comp_types[@]}"; do
+ children=$(get_child_components "$component" "$comp_type" | sort -u)
+ if [ -n "$children" ] ; then
+ for child in $children ; do
+ child=${child#$comp_type:}
+ echo "${child#/}" >> "$RESTORE_EXCLUDE_FILE"
+ echo "${child#/}/*" >> "$RESTORE_EXCLUDE_FILE"
+ done
+ fi
+ done
+
+ # exclude the component itself
+ for comp_type in "${comp_types[@]}"; do
+ component=${component#$comp_type:}
+ done
+ echo "${component#/}" >> "$RESTORE_EXCLUDE_FILE"
+ echo "${component#/}/*" >> "$RESTORE_EXCLUDE_FILE"
done
diff --git a/usr/share/rear/layout/save/GNU/Linux/230_filesystem_layout.sh b/usr/share/rear/layout/save/GNU/Linux/230_filesystem_layout.sh
index 7990c055..166b9cd2 100644
--- a/usr/share/rear/layout/save/GNU/Linux/230_filesystem_layout.sh
+++ b/usr/share/rear/layout/save/GNU/Linux/230_filesystem_layout.sh
@@ -434,6 +434,7 @@ fi
# Output header only once:
btrfsmountedsubvol_entry_exists="yes"
echo "# All mounted btrfs subvolumes (including mounted btrfs default subvolumes and mounted btrfs snapshot subvolumes)."
+ echo "# Mounted btrfs snapshot subvolumes are autoexcluded."
if test "$findmnt_FSROOT_works" ; then
echo "# Determined by the findmnt command that shows the mounted btrfs_subvolume_path."
echo "# Format: btrfsmountedsubvol <device> <subvolume_mountpoint> <mount_options> <btrfs_subvolume_path>"
@@ -469,7 +470,10 @@ fi
# Finally, test whether the btrfs subvolume listed as mounted actually exists. A running docker
# daemon apparently can convince the system to list a non-existing btrfs volume as mounted.
# See https://github.com/rear/rear/issues/1496
- if btrfs_subvolume_exists "$subvolume_mountpoint" "$btrfs_subvolume_path"; then
+ if btrfs_snapshot_subvolume_exists "$subvolume_mountpoint" "$btrfs_subvolume_path"; then
+ # Exclude mounted snapshot subvolumes
+ echo "#btrfsmountedsubvol $device $subvolume_mountpoint $mount_options $btrfs_subvolume_path"
+ elif btrfs_subvolume_exists "$subvolume_mountpoint" "$btrfs_subvolume_path"; then
echo "btrfsmountedsubvol $device $subvolume_mountpoint $mount_options $btrfs_subvolume_path"
else
LogPrintError "Ignoring non-existing btrfs subvolume listed as mounted: $subvolume_mountpoint"
diff --git a/usr/share/rear/layout/save/default/340_generate_mountpoint_device.sh b/usr/share/rear/layout/save/default/340_generate_mountpoint_device.sh
index 2b58922b..fb358ccf 100644
--- a/usr/share/rear/layout/save/default/340_generate_mountpoint_device.sh
+++ b/usr/share/rear/layout/save/default/340_generate_mountpoint_device.sh
@@ -7,15 +7,15 @@
# EXCLUDE_RECREATE is handled automatically (commented out in LAYOUT_FILE)
excluded_mountpoints=()
while read fs device mountpoint junk ; do
- if IsInArray "fs:$mountpoint" "${EXCLUDE_BACKUP[@]}" ; then
+ if IsInArray "$fs:$mountpoint" "${EXCLUDE_BACKUP[@]}" ; then
excluded_mountpoints+=( $mountpoint )
fi
- for component in $(get_parent_components "fs:$mountpoint" | sort -u) ; do
+ for component in $(get_parent_components "$fs:$mountpoint" | sort -u) ; do
if IsInArray "$component" "${EXCLUDE_BACKUP[@]}" ; then
excluded_mountpoints+=( $mountpoint )
fi
done
-done < <(grep ^fs $LAYOUT_FILE)
+done < <(grep -E '^(fs|btrfsmountedsubvol)' $LAYOUT_FILE)
# Generate the list of mountpoints and devices to exclude from backup
while read fs device mountpoint junk ; do
@@ -25,4 +25,4 @@ while read fs device mountpoint junk ; do
continue
fi
echo "$mountpoint $device"
-done < <(grep '^fs' $LAYOUT_FILE) > $VAR_DIR/recovery/mountpoint_device
+done < <(grep -E '^(fs|btrfsmountedsubvol)' $LAYOUT_FILE) | unique_unsorted > $VAR_DIR/recovery/mountpoint_device
diff --git a/usr/share/rear/lib/filesystems-functions.sh b/usr/share/rear/lib/filesystems-functions.sh
index f0547706..826571be 100644
--- a/usr/share/rear/lib/filesystems-functions.sh
+++ b/usr/share/rear/lib/filesystems-functions.sh
@@ -3,16 +3,27 @@
#
# File system support functions
+function btrfs_snapshot_subvolume_exists() {
+ # returns true if the btrfs snapshot subvolume ($2) exists in the Btrfs
+ # file system at the mount point ($1).
+
+ # Use -s so that btrfs subvolume list considers snapshots only
+ btrfs_subvolume_exists "$1" "$2" "-s"
+}
+
function btrfs_subvolume_exists() {
# returns true if the btrfs subvolume ($2) exists in the Btrfs file system at the mount point ($1).
local subvolume_mountpoint="$1" btrfs_subvolume_path="$2"
+ # extra options for the btrfs subvolume list command ($3)
+ local btrfs_extra_opts="$3"
+
# A root subvolume can be assumed to always exist
[ "$btrfs_subvolume_path" == "/" ] && return 0
# A non-root subvolume exists if the btrfs subvolume list contains its complete path at the end of one line.
# This code deliberately uses a plain string comparison rather than a regexp.
- btrfs subvolume list -a "$subvolume_mountpoint" | sed -e 's; path <FS_TREE>/; path ;' |
+ btrfs subvolume list -a $btrfs_extra_opts "$subvolume_mountpoint" | sed -e 's; path <FS_TREE>/; path ;' |
awk -v path="$btrfs_subvolume_path" '
BEGIN {
match_string = " path " path;

View File

@ -1,54 +0,0 @@
From 060fef89b6968f0c8f254e6f612eff839b83c057 Mon Sep 17 00:00:00 2001
From: Pavel Cahyna <pcahyna@redhat.com>
Date: Mon, 13 Nov 2023 18:54:41 +0100
Subject: [PATCH] Do not mount /sys if already mounted
Newer versions of systemd (starting with Fedora 39) seem to mount /sys
themselves. Mounting it again leads to errors on the recovery system
startup (startup scripts failing with status=219/CGROUP ), see
https://github.com/rear/rear/issues/3017.
Check if /sys is already mounted using the `mountpoint` tool and mount it
only if it is not.
Do the same for the other system mountpoints like /proc, /dev, /dev/pts.
Not sure if they suffer from the same problem, but they probably could.
N.B. the `mountpoint` command is already among REQUIRED_PROGS.
---
usr/share/rear/skel/default/etc/scripts/boot | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/usr/share/rear/skel/default/etc/scripts/boot b/usr/share/rear/skel/default/etc/scripts/boot
index 0f221af3e4..f06e759620 100755
--- a/usr/share/rear/skel/default/etc/scripts/boot
+++ b/usr/share/rear/skel/default/etc/scripts/boot
@@ -4,8 +4,8 @@
dmesg -n1
# basic mounts
-mount -t proc -n none /proc
-mount -t sysfs none /sys
+mountpoint /proc || mount -t proc -n none /proc
+mountpoint /sys || mount -t sysfs none /sys
if type udevd &>/dev/null && ! type udevinfo &>/dev/null; then
### we use udevinfo to filter out old udev versions (<106) that don't
@@ -13,7 +13,7 @@ if type udevd &>/dev/null && ! type udevinfo &>/dev/null; then
udev_version=$(udevd --version)
if [[ "$udev_version" -gt 175 ]]; then
### udev > 175 needs devtmpfs
- mount -t devtmpfs none /dev
+ mountpoint /dev || mount -t devtmpfs none /dev
fi
fi
@@ -26,7 +26,7 @@ if [[ ! -L /dev/fd ]] ; then
ln -s /proc/self/fd /dev/fd
fi
-mount -t devpts -o gid=5,mode=620 none /dev/pts
+mountpoint /dev/pts || mount -t devpts -o gid=5,mode=620 none /dev/pts
cat /proc/mounts >/etc/mtab 2>/dev/null

File diff suppressed because it is too large Load Diff

View File

@ -1,110 +0,0 @@
commit eb574592a21c7ca986393c4563fe5484b9f01454
Author: Johannes Meixner <jsmeix@suse.com>
Date: Tue Jun 18 13:47:27 2024 +0200
In 990_verify_rootfs.sh fix issue #3021 (#3250)
In build/default/990_verify_rootfs.sh
for each 'not found' shared object
(i.e. a shared object that was 'not found' by 'ldd')
check whether or not the shared object
may exist nevertheless in the recovery system
and if yes, we may sufficiently safely assume
things are OK in the ReaR recovery system
so we do not report it as missing to the user
(for debugging we have all in the log), see
https://github.com/rear/rear/issues/3021#issuecomment-2165453757
Additionally in 990_verify_rootfs.sh
more consistent level when messages are shown,
i.e. now only LogPrint and LogPrintError
to show nothing (except errors) when not in verbose mode
and all messages when in verbose mode
to make the messages as a whole
better understandable by the user.
Cherry-picked-by: Lukáš Zaoral <lzaoral@redhat.com>
diff --git a/usr/share/rear/build/default/990_verify_rootfs.sh b/usr/share/rear/build/default/990_verify_rootfs.sh
index 3d203cca..dce42701 100644
--- a/usr/share/rear/build/default/990_verify_rootfs.sh
+++ b/usr/share/rear/build/default/990_verify_rootfs.sh
@@ -70,9 +70,13 @@ DebugPrint "Testing each binary with 'ldd' and look for 'not found' libraries wi
local backup_tool_LD_LIBRARY_PATH=""
local binary=""
local broken_binary_LD_LIBRARY_PATH=""
-local broken_binaries="no"
local fatal_missing_library="no"
local ldd_output=""
+local not_found_output=""
+local not_found_library=""
+local junk=""
+local actually_found_library=""
+local actually_missing_libraries="no"
# Third-party backup tools may use LD_LIBRARY_PATH to find their libraries
# so that for testing such third-party backup tools we must also use their special LD_LIBRARY_PATH here:
if test "$BACKUP" = "TSM" ; then
@@ -159,9 +163,8 @@ for binary in $( find $ROOTFS_DIR -type f \( -executable -o -name '*.so' -o -nam
broken_binary_LD_LIBRARY_PATH=$backup_tool_LD_LIBRARY_PATH
Log "$binary requires additional libraries with backup tool specific LD_LIBRARY_PATH=$backup_tool_LD_LIBRARY_PATH"
fi
- # All tests had a 'not found' shared object dependency so the binary requires additional libraries
- # without LD_LIBRARY_PATH and with LD_LIBRARY_PATH and with backup tool specific LD_LIBRARY_PATH:
- broken_binaries="yes"
+ # At this point all tests had a 'not found' shared object dependency so the binary requires additional libraries
+ # without LD_LIBRARY_PATH and with LD_LIBRARY_PATH and with backup tool specific LD_LIBRARY_PATH.
# Only for programs (i.e. files in a .../bin/... or .../sbin/... directory) treat a missing library as fatal
# unless specified when a 'not found' reported library is not fatal (when the 'ldd' test was false alarm):
if grep -q '/[s]*bin/' <<<"$binary" ; then
@@ -169,17 +172,17 @@ for binary in $( find $ROOTFS_DIR -type f \( -executable -o -name '*.so' -o -nam
if test "$NON_FATAL_BINARIES_WITH_MISSING_LIBRARY" ; then
# A program with missing library is treated as fatal when it does not match the pattern:
if grep -E -q "$NON_FATAL_BINARIES_WITH_MISSING_LIBRARY" <<<"$binary" ; then
- LogPrintError "$binary requires additional libraries (specified as non-fatal)"
+ LogPrint "$binary requires libraries were 'ldd' shows 'not found' (specified as non-fatal)"
else
- LogPrintError "$binary requires additional libraries (fatal error)"
+ LogPrint "$binary requires libraries were 'ldd' shows 'not found' (fatal error)"
fatal_missing_library="yes"
fi
else
- LogPrintError "$binary requires additional libraries (fatal error)"
+ LogPrint "$binary requires libraries were 'ldd' shows 'not found' (fatal by default)"
fatal_missing_library="yes"
fi
else
- LogPrintError "$binary requires additional libraries"
+ LogPrint "$binary requires libraries were 'ldd' shows 'not found'"
fi
# Run the same ldd call as above but now keep its whole stdout output.
# The ldd call that results the final 'not found' shared object is the last of the above ldd calls that was run.
@@ -191,10 +194,27 @@ for binary in $( find $ROOTFS_DIR -type f \( -executable -o -name '*.so' -o -nam
fi
# Have the whole ldd output only in the log:
Log "$ldd_output"
- # Show only the missing libraries to the user to not flood his screen with tons of other ldd output lines:
- PrintError "$( grep 'not found' <<<"$ldd_output" )"
+ # For each 'not found' shared object (i.e. a shared object that was 'not found' by 'ldd')
+ # check whether or not the shared object may exist nevertheless in the ReaR recovery system
+ # and if yes, we may sufficiently safely assume things are OK in the ReaR recovery system
+ # so we do not report it as missing to the user (for debugging we have all in the log)
+ # cf. https://github.com/rear/rear/issues/3021#issuecomment-2165453757
+ not_found_output="$( grep 'not found' <<<"$ldd_output" )"
+ # not_found_output is a string of multiple lines (separated by \n) that look e.g. like
+ # libsystemd-shared-255.4-1.fc40.so => not found
+ # /path/to/library => not found
+ while read not_found_library junk ; do
+ # We prefer a simple 'grep -q' pipe over dealing with find -name versus -path options:
+ if actually_found_library="$( find $ROOTFS_DIR -xdev | grep "$not_found_library" )" ; then
+ LogPrint "$binary requires $not_found_library which was not found by 'ldd' but exists as $actually_found_library"
+ else
+ actually_missing_libraries="yes"
+ # Show only the missing libraries to the user to not flood his screen with tons of other ldd output lines:
+ LogPrintError "$binary requires $not_found_library which could not be found in the ReaR recovery system"
+ fi
+ done <<<"$not_found_output"
done
-is_true $broken_binaries && LogPrintError "ReaR recovery system in '$ROOTFS_DIR' needs additional libraries, check $RUNTIME_LOGFILE for details"
+is_true $actually_missing_libraries && LogPrintError "ReaR recovery system in '$ROOTFS_DIR' needs additional libraries, check $RUNTIME_LOGFILE for details"
is_true $fatal_missing_library && keep_build_dir
# Testing that each program in the PROGS array can be found as executable command within the recovery system

View File

@ -2,8 +2,8 @@ diff --git a/usr/share/rear/conf/default.conf b/usr/share/rear/conf/default.conf
index 17a764cba..a944114b3 100644
--- a/usr/share/rear/conf/default.conf
+++ b/usr/share/rear/conf/default.conf
@@ -1866,7 +1866,7 @@ OBDR_BLOCKSIZE=2048
# BACKUP=NBU stuff (Symantec/Veritas NetBackup)
@@ -2483,7 +2483,7 @@ OBDR_BLOCKSIZE=2048
# BACKUP=NBU (Symantec/Veritas NetBackup)
##
#
-COPY_AS_IS_NBU=( /usr/openv/bin/vnetd /usr/openv/bin/vopied /usr/openv/lib /usr/openv/netbackup /usr/openv/var/auth/[mn]*.txt /usr/openv/var/vxss /usr/openv/var/webtruststore /usr/openv/resources/nbpxyhelper /opt/VRTSpbx /etc/vx/VxICS /etc/vx/vrtslog.conf /var/log/VRTSpbx )

View File

@ -1,50 +0,0 @@
From 5a8c5086bf3fc28236436ff3ef27196509f0375d Mon Sep 17 00:00:00 2001
From: Pavel Cahyna <pcahyna@redhat.com>
Date: Thu, 24 Aug 2023 11:41:25 +0200
Subject: [PATCH] Remove the lvmdevices file at the end of recovery
The file /etc/lvm/devices/system.devices restricts LVM to disks with
given (hardware) IDs (serial numbers, WWNs). See lvmdevices(8).
Unfortunately, when restoring to different disks than in the original
system, it will mean that LVM is broken in the recovered system (it
won't find any disks). Therefore it is safer to remove the file to
force the old behavior where LVM scans all disks. This used to be the
LVM default (use_devicesfile=0).
---
.../GNU/Linux/230_remove_lvmdevices.sh | 25 +++++++++++++++++++
1 file changed, 25 insertions(+)
create mode 100644 usr/share/rear/finalize/GNU/Linux/230_remove_lvmdevices.sh
diff --git a/usr/share/rear/finalize/GNU/Linux/230_remove_lvmdevices.sh b/usr/share/rear/finalize/GNU/Linux/230_remove_lvmdevices.sh
new file mode 100644
index 0000000000..9392c9f52f
--- /dev/null
+++ b/usr/share/rear/finalize/GNU/Linux/230_remove_lvmdevices.sh
@@ -0,0 +1,25 @@
+# Adapted from 260_rename_diskbyid.sh
+
+# Remove /etc/lvm/devices/system.devices
+# The file restricts LVM to disks with given (hardware) IDs (serial
+# numbers, WWNs). See lvmdevices(8).
+# Unfortunately, when restoring to different disks than in the original
+# system, it will mean that LVM is broken in the recovered system (it
+# won't find any disks). Therefore it is safer to remove the file to
+# force the old behavior where LVM scans all disks. This used to be the
+# LVM default (use_devicesfile=0).
+
+# There may be other files under /etc/lvm/devices, but they are not used
+# by default
+
+local file=/etc/lvm/devices/system.devices
+local realfile
+
+realfile="$TARGET_FS_ROOT/$file"
+# OK if file not found
+test -f "$realfile" || return 0
+mv $v "$realfile" "$realfile.rearbak"
+LogPrint "Renamed LVM devices file $realfile to $realfile.rearbak
+to prevent LVM problems in the recovered system, verify that the file
+is correct after booting the recovered system and move it back, or
+regenerate it using vgimportdevices."

View File

@ -1,30 +0,0 @@
commit 9f859c13f5ba285cd1d5983c9b595975c21888d3
Merge: 01f503ed 4434da63
Author: pcahyna <pcahyna@users.noreply.github.com>
Date: Tue Nov 14 14:33:56 2023 +0100
Merge pull request #3073 from pcahyna/resolve-libraries-for-symlinks-in-COPY_AS_IS
Resolve libs for executable links in COPY_AS_IS
diff --git a/usr/share/rear/build/GNU/Linux/100_copy_as_is.sh b/usr/share/rear/build/GNU/Linux/100_copy_as_is.sh
index 2169efaa..2e991145 100644
--- a/usr/share/rear/build/GNU/Linux/100_copy_as_is.sh
+++ b/usr/share/rear/build/GNU/Linux/100_copy_as_is.sh
@@ -135,10 +135,13 @@ local copy_as_is_file=""
# cf. https://github.com/rear/rear/pull/2378
# It is crucial to append to /dev/$DISPENSABLE_OUTPUT_DEV (cf. 'Print' in lib/_input-output-functions.sh):
while read -r copy_as_is_file ; do
- # Skip non-regular files like directories, device files, and 'tar' error messages (e.g. in case of non-existent files, see above):
+ # Skip non-regular files like directories, device files, and 'tar' error messages (e.g. in case of non-existent files, see above)
+ # but do not skip symbolic links. Their targets will be copied later by build/default/490_fix_broken_links.sh.
+ # We thus need library dependencies for symlinked executables just like for normal executables
+ # and build/default/490_fix_broken_links.sh does not perform library dependency scan.
+ # See GitHub PR https://github.com/rear/rear/pull/3073
+ # and issue https://github.com/rear/rear/issues/3064 for details.
test -f "$copy_as_is_file" || continue
- # Skip symbolic links (only care about symbolic link targets):
- test -L "$copy_as_is_file" && continue
# Remember actual regular files that are executable:
test -x "$copy_as_is_file" && copy_as_is_executables+=( "$copy_as_is_file" )
done < <( sort -u $copy_as_is_filelist_file ) 2>>/dev/$DISPENSABLE_OUTPUT_DEV

View File

@ -1,589 +0,0 @@
commit 096bfde5e234f5a803bae74f24e3821798022c7c
Merge: 625775fc 1df15b03
Author: pcahyna <pcahyna@users.noreply.github.com>
Date: Tue Feb 6 18:37:52 2024 +0100
Merge pull request #3136 from pcahyna/no-recovery-bootdisk
Include GRUB tools unconditionally and don't create $VAR_DIR/recovery/bootdisk in prep
diff --git a/usr/share/rear/prep/GNU/Linux/300_include_grub_tools.sh b/usr/share/rear/prep/GNU/Linux/300_include_grub_tools.sh
index fcf0a5ff..7d494281 100644
--- a/usr/share/rear/prep/GNU/Linux/300_include_grub_tools.sh
+++ b/usr/share/rear/prep/GNU/Linux/300_include_grub_tools.sh
@@ -1,8 +1,6 @@
#
# GRUB2 has much more commands than the legacy grub command, including modules
-test -d $VAR_DIR/recovery || mkdir -p $VAR_DIR/recovery
-
# cf. https://github.com/rear/rear/issues/2137
# s390 zlinux does not use grub
# *********************************************************************************
@@ -11,19 +9,8 @@ test -d $VAR_DIR/recovery || mkdir -p $VAR_DIR/recovery
# *********************************************************************************
[ "$ARCH" == "Linux-s390" ] && return 0
-# Because usr/sbin/rear sets 'shopt -s nullglob' the 'echo -n' command
-# outputs nothing if nothing matches the bash globbing pattern '/boot/grub*'
-local grubdir="$( echo -n /boot/grub* )"
-# Use '/boot/grub' as fallback if nothing matches '/boot/grub*'
-test -d "$grubdir" || grubdir='/boot/grub'
-
-# Check if we're using grub or grub2 before doing something.
-if has_binary grub-probe ; then
- grub-probe -t device $grubdir >$VAR_DIR/recovery/bootdisk 2>/dev/null || return 0
-elif has_binary grub2-probe ; then
- grub2-probe -t device $grubdir >$VAR_DIR/recovery/bootdisk 2>/dev/null || return 0
-fi
-
+# It is safe to assume that we are using GRUB and try to add these files to the rescue image
+# even if the assumption is wrong.
# Missing programs in the PROGS array are ignored:
PROGS+=( grub-bios-setup grub2-bios-setup
grub-install grub2-install
diff --git a/usr/share/rear/prep/Linux-s390/305_include_s390_tools.sh b/usr/share/rear/prep/Linux-s390/305_include_s390_tools.sh
index b4ab3786..4451f53d 100644
--- a/usr/share/rear/prep/Linux-s390/305_include_s390_tools.sh
+++ b/usr/share/rear/prep/Linux-s390/305_include_s390_tools.sh
@@ -1,8 +1,6 @@
#
# s390 zIPL boot loader and grubby for configuring boot loader`
-test -d $VAR_DIR/recovery || mkdir -p $VAR_DIR/recovery
-
# See the code in prep/GNU/Linux/300_include_grub_tools.sh
# that sets grubdir via
# local grubdir="$( echo -n /boot/grub* )"
@@ -21,7 +19,7 @@ local bootdir="/boot/"
# findmnt returns --> /dev/dasda3[/@/.snapshots/1/snapshot]
# use 300_include_grub_tools.sh instead of this file (grub2-probe)
if has_binary findmnt ; then
- findmnt -no SOURCE --target $bootdir >$VAR_DIR/recovery/bootdisk || return 0
+ findmnt -no SOURCE --target $bootdir > /dev/null || return 0
fi
# Missing programs in the PROGS array are ignored:
diff --git a/usr/share/rear/prep/default/320_include_uefi_env.sh b/usr/share/rear/prep/default/320_include_uefi_env.sh
index ea86af4c..93e59eae 100644
--- a/usr/share/rear/prep/default/320_include_uefi_env.sh
+++ b/usr/share/rear/prep/default/320_include_uefi_env.sh
@@ -87,7 +87,3 @@ fi
DebugPrint "Found EFI system partition ${esp_proc_mounts_line[0]} on ${esp_proc_mounts_line[1]} type ${esp_proc_mounts_line[2]}"
USING_UEFI_BOOTLOADER=1
LogPrint "Using UEFI Boot Loader for Linux (USING_UEFI_BOOTLOADER=1)"
-
-# Remember the ESP device node in VAR_DIR/recovery/bootdisk:
-echo "${esp_proc_mounts_line[0]}" >$VAR_DIR/recovery/bootdisk
-
commit ca99d855579cfcab37f985e2547a3187e0f0aeeb
Merge: 8c59415c 40b883c0
Author: pcahyna <pcahyna@users.noreply.github.com>
Date: Fri Feb 16 11:40:04 2024 +0100
Merge pull request #3145 from rear/restore-hybrid-bootloader
Support saving and restoring hybrid BIOS/UEFI bootloader setup and clean up bootloader detection
Cherry-picked-by: Lukáš Zaoral <lzaoral@redhat.com>
diff --git a/usr/share/rear/finalize/Linux-i386/630_install_grub.sh b/usr/share/rear/finalize/Linux-i386/630_install_grub.sh
index f3d9a820..a0e87e1d 100644
--- a/usr/share/rear/finalize/Linux-i386/630_install_grub.sh
+++ b/usr/share/rear/finalize/Linux-i386/630_install_grub.sh
@@ -1,22 +1,18 @@
# This script is an improvement over the default grub-install '(hd0)'
#
-# However the following issues still exist:
+# However the following issue still exists:
#
# * We don't know what the first disk will be, so we cannot be sure the MBR
-# is written to the correct disk(s). That's why we make all disks bootable.
-#
-# * There is no guarantee that GRUB was the boot loader used originally.
-# One possible attempt would be to save and restore the MBR for each disk,
-# but this does not guarantee a correct boot order,
-# or even a working boot loader config
-# (eg. GRUB stage2 might not be at the exact same location).
+# is written to the correct disk(s). That's why we make all suitable disks bootable.
# Skip if another boot loader is already installed
# (then $NOBOOTLOADER is not a true value cf. finalize/default/010_prepare_checks.sh):
is_true $NOBOOTLOADER || return 0
-# For UEFI systems with grub legacy with should use efibootmgr instead:
-is_true $USING_UEFI_BOOTLOADER && return
+# For UEFI systems with grub legacy with should use efibootmgr instead,
+# but if BOOTLOADER is explicitly set to GRUB, we are on a hybrid (BIOS/UEFI)
+# boot system and we need to install GRUB to MBR as well.
+# Therefore, we don't test $USING_UEFI_BOOTLOADER.
# If the BOOTLOADER variable (read by finalize/default/010_prepare_checks.sh)
# is not "GRUB" (which means GRUB Legacy) skip this script (which is only for GRUB Legacy)
@@ -25,31 +21,27 @@ is_true $USING_UEFI_BOOTLOADER && return
test "GRUB" = "$BOOTLOADER" || return 0
# If the BOOTLOADER variable is "GRUB" (which means GRUB Legacy)
-# do not unconditionally trust that because https://github.com/rear/rear/pull/589
-# reads (excerpt):
-# Problems found:
-# The ..._install_grub.sh checked for GRUB2 which is not part
-# of the first 2048 bytes of a disk - only GRUB was present -
-# thus the check for grub-probe/grub2-probe
-# and https://github.com/rear/rear/commit/079de45b3ad8edcf0e3df54ded53fe955abded3b
-# reads (excerpt):
-# replace grub-install by grub-probe
-# as grub-install also exist in legacy grub
-# so that it seems there are cases where actually GRUB 2 is used
-# but wrongly detected as "GRUB" so that another test is needed
-# to detected if actually GRUB 2 is used and that test is to
-# check if grub-probe or grub2-probe is installed because
-# grub-probe or grub2-probe is only installed in case of GRUB 2
-# and when GRUB 2 is installed we assume GRUB 2 is used as boot loader
-# so that then we skip this script (which is only for GRUB Legacy)
-# because finalize/Linux-i386/660_install_grub2.sh is for installing GRUB 2:
-if type -p grub-probe >&2 || type -p grub2-probe >&2 ; then
- LogPrint "Skip installing GRUB Legacy boot loader because GRUB 2 is installed (grub-probe or grub2-probe exist)."
+# we could in principle trust that and continue because
+# layout/save/default/445_guess_bootloader.sh (where the value has been set)
+# is now able to distinguish between GRUB Legacy and GRUB 2.
+# But, as this code used to support the value "GRUB" for GRUB 2,
+# the user can have BOOTLOADER=GRUB set explicitly in the configuration file
+# and then it overrides the autodetection in layout/save/default/445_guess_bootloader.sh .
+# The user expects this setting to work with GRUB 2, thus for backward compatibility
+# we need to take into accout the possibility that GRUB actually means GRUB 2.
+if is_grub2_installed ; then
+ LogPrint "Skip installing GRUB Legacy boot loader because GRUB 2 is installed."
+ # We have the ErrorIfDeprecated function, but it aborts ReaR by default,
+ # which is not a good thing to do during recovery.
+ # Therefore it better to log a warning and continue.
+ LogPrintError "WARNING: setting BOOTLOADER=GRUB for GRUB 2 is deprecated, set BOOTLOADER=GRUB2 if setting BOOTLOADER explicitly"
return
fi
# The actual work:
LogPrint "Installing GRUB Legacy boot loader:"
+# See above for the reasoning why not to use ErrorIfDeprecated
+LogPrintError "WARNING: support for GRUB Legacy is deprecated"
# Installing GRUB Legacy boot loader requires an executable "grub":
type -p grub >&2 || Error "Cannot install GRUB Legacy boot loader because there is no 'grub' program."
@@ -79,8 +71,10 @@ if [[ -r "$LAYOUT_FILE" && -r "$LAYOUT_DEPS" ]] ; then
for disk in $disks ; do
# Installing grub on an LVM PV will wipe the metadata so we skip those
- # function is_disk_a_pv returns with 1 if disk is a PV
- is_disk_a_pv "$disk" || continue
+ # function is_disk_a_pv returns true if disk is a PV
+ is_disk_a_pv "$disk" && continue
+ # Is the disk suitable for GRUB installation at all?
+ is_disk_grub_candidate "$disk" || continue
# Use first boot partition by default
part=$( echo $bootparts | cut -d' ' -f1 )
diff --git a/usr/share/rear/finalize/Linux-i386/660_install_grub2.sh b/usr/share/rear/finalize/Linux-i386/660_install_grub2.sh
index d1c36bd3..5bf9144c 100644
--- a/usr/share/rear/finalize/Linux-i386/660_install_grub2.sh
+++ b/usr/share/rear/finalize/Linux-i386/660_install_grub2.sh
@@ -36,7 +36,9 @@
# This script does not check BOOTLOADER because it is also used as fallback
# to install the nowadays most often used bootloader GRUB2
# unless the BOOTLOADER variable tells to install another bootloader
-# (other bootloader install scripts check the BOOTLOADER variable).
+# (other bootloader install scripts check the BOOTLOADER variable)
+# and unless we are using UEFI (BOOTLOADER then indicates the BIOS bootloader
+# in a a hybrid boot setup).
#
# This script does not error out because at this late state of "rear recover"
# (i.e. after the backup was restored) I <jsmeix@suse.de> consider it too hard
@@ -45,6 +47,37 @@
# so that after "rear recover" finished he can manually install the bootloader
# as appropriate for his particular system.
+local grub_name
+local grub2_install_failed grub2_install_device
+local source_disk target_disk junk
+local grub2_installed_disks
+local part bootparts
+local disk disks bootdisk
+
+function bios_grub_install ()
+{
+ local grub2_install_device="$1"
+
+ if is_true $USING_UEFI_BOOTLOADER ; then
+ # If running under UEFI, we need to specify the target explicitly, otherwise grub-install thinks
+ # that we are installing the EFI bootloader.
+ if ! chroot $TARGET_FS_ROOT /bin/bash --login -c "$grub_name-install --target=i386-pc $grub2_install_device" ; then
+ LogPrintError "Failed to install GRUB2 for BIOS boot (target i386-pc) on $bootdisk"
+ # purely informational test that may help to explain the reason for the error
+ if ! test -d "$TARGET_FS_ROOT/boot/$grub_name/i386-pc" ; then
+ LogPrintError "GRUB2 module dir for BIOS boot (boot/$grub_name/i386-pc in $TARGET_FS_ROOT) does not exist, is GRUB2 for BIOS (target i386-pc) installed?"
+ fi
+ return 1
+ fi
+ else
+ if ! chroot $TARGET_FS_ROOT /bin/bash --login -c "$grub_name-install $grub2_install_device" ; then
+ LogPrintError "Failed to install GRUB2 on $grub2_install_device"
+ return 1
+ fi
+ fi
+ return 0
+}
+
# Skip if another bootloader was already installed:
# In this case NOBOOTLOADER is not true,
# cf. finalize/default/050_prepare_checks.sh
@@ -52,12 +85,16 @@ is_true $NOBOOTLOADER || return 0
# For UEFI systems with grub2 we should use efibootmgr instead,
# cf. finalize/Linux-i386/670_run_efibootmgr.sh
-is_true $USING_UEFI_BOOTLOADER && return
+# but if BOOTLOADER is explicitly set to GRUB2, we are on a hybrid (BIOS/UEFI)
+# boot system and we need to install GRUB to MBR as well
+if is_true $USING_UEFI_BOOTLOADER && [ "GRUB2" != "$BOOTLOADER" ] ; then
+ return 0
+fi
# Only for GRUB2 - GRUB Legacy will be handled by its own script.
# GRUB2 is detected by testing for grub-probe or grub2-probe which does not exist in GRUB Legacy.
# If neither grub-probe nor grub2-probe is there assume GRUB2 is not there:
-type -p grub-probe || type -p grub2-probe || return 0
+is_grub2_installed || return 0
LogPrint "Installing GRUB2 boot loader..."
@@ -101,7 +138,7 @@ if test "$GRUB2_INSTALL_DEVICES" ; then
else
LogPrint "Installing GRUB2 on $grub2_install_device (specified in GRUB2_INSTALL_DEVICES)"
fi
- if ! chroot $TARGET_FS_ROOT /bin/bash --login -c "$grub_name-install $grub2_install_device" ; then
+ if ! bios_grub_install "$grub2_install_device" ; then
LogPrintError "Failed to install GRUB2 on $grub2_install_device"
grub2_install_failed="yes"
fi
@@ -145,8 +182,8 @@ fi
grub2_installed_disks=()
for disk in $disks ; do
# Installing GRUB2 on an LVM PV will wipe the metadata so we skip those:
- # function is_disk_a_pv returns with 1 if disk is a PV
- is_disk_a_pv "$disk" || continue
+ # function is_disk_a_pv returns true if disk is a PV
+ is_disk_a_pv "$disk" && continue
# Use first boot partition by default:
part=$( echo $bootparts | cut -d' ' -f1 )
@@ -165,6 +202,8 @@ for disk in $disks ; do
# Install GRUB2 on the boot disk if one was found:
if test "$bootdisk" ; then
+ # Is the disk suitable for GRUB installation at all?
+ is_disk_grub_candidate "$bootdisk" || continue
# Continue with the next possible boot disk when GRUB2 was already installed on the current one.
# When there are more disks like /dev/sda and /dev/sdb it can happen that
# for /dev/sda bootdisk=/dev/sda and GRUB2 gets installed on /dev/sda and
@@ -172,7 +211,7 @@ for disk in $disks ; do
# so we avoid that GRUB2 gets needlessly installed two times on the same device:
IsInArray "$bootdisk" "${grub2_installed_disks[@]}" && continue
LogPrint "Found possible boot disk $bootdisk - installing GRUB2 there"
- if chroot $TARGET_FS_ROOT /bin/bash --login -c "$grub_name-install $bootdisk" ; then
+ if bios_grub_install "$bootdisk" ; then
grub2_installed_disks+=( "$bootdisk" )
# In contrast to the above behaviour when GRUB2_INSTALL_DEVICES is specified
# consider it here as a successful bootloader installation when GRUB2
@@ -181,11 +220,14 @@ for disk in $disks ; do
# Continue with the next possible boot disk:
continue
fi
- LogPrintError "Failed to install GRUB2 on possible boot disk $bootdisk"
fi
done
is_true $NOBOOTLOADER || return 0
-LogPrintError "Failed to install GRUB2 - you may have to manually install it"
+if is_true $USING_UEFI_BOOTLOADER ; then
+ LogPrintError "Failed to install GRUB2 for BIOS boot - you may have to manually install it to preserve the hybrid BIOS/UEFI boot support, otherwise only UEFI boot will work"
+else
+ LogPrintError "Failed to install GRUB2 - you may have to manually install it"
+fi
return 1
diff --git a/usr/share/rear/finalize/default/050_prepare_checks.sh b/usr/share/rear/finalize/default/050_prepare_checks.sh
index 1679c9a4..57b44bca 100644
--- a/usr/share/rear/finalize/default/050_prepare_checks.sh
+++ b/usr/share/rear/finalize/default/050_prepare_checks.sh
@@ -10,10 +10,18 @@
NOBOOTLOADER=1
# Try to read the BOOTLOADER value if /var/lib/rear/recovery/bootloader is not empty.
-# Currently (June 2016) the used BOOTLOADER values (grep for '$BOOTLOADER') are:
+# Currently (February 2024) the used BOOTLOADER values (grep for '$BOOTLOADER') are:
# GRUB for GRUB Legacy
# GRUB2 for GRUB 2
# ELILO for elilo
+# LILO for lilo
+# GRUB2-EFI for GRUB 2, EFI version
+# EFI for any EFI bootloader, dummy value
+# ARM for ARM devices, dummy value
+# ARM-ALLWINNER for Allwinner devices
+# ZIPL for zIPL, on IBM Z (s390x)
+# PPC for any bootloader in the PReP boot partition (can be LILO, YABOOT, GRUB2)
+
local bootloader_file="$VAR_DIR/recovery/bootloader"
# The output is stored in an artificial bash array so that $BOOTLOADER is the first word:
test -s $bootloader_file && BOOTLOADER=( $( grep -v '^[[:space:]]*#' $bootloader_file ) )
diff --git a/usr/share/rear/layout/save/default/445_guess_bootloader.sh b/usr/share/rear/layout/save/default/445_guess_bootloader.sh
index 06de7648..374a706f 100644
--- a/usr/share/rear/layout/save/default/445_guess_bootloader.sh
+++ b/usr/share/rear/layout/save/default/445_guess_bootloader.sh
@@ -1,10 +1,26 @@
# Determine or guess the used bootloader if not specified by the user
# and save this information into /var/lib/rear/recovery/bootloader
-bootloader_file="$VAR_DIR/recovery/bootloader"
+local bootloader_file="$VAR_DIR/recovery/bootloader"
+
+local sysconfig_bootloader
+local block_device
+local blockd
+local disk_device
+local bootloader_area_strings_file
+local block_size
+local known_bootloader
# When BOOTLOADER is specified use that:
if test "$BOOTLOADER" ; then
+ # case-insensitive match, as later we conver all to uppercase
+ if [[ "$BOOTLOADER" == [Gg][Rr][Uu][Bb] ]] ; then
+ if is_grub2_installed ; then
+ LogPrintError "BOOTLOADER=GRUB used to mean GRUB 2 if GRUB 2 is installed and GRUB Legacy if not"
+ Error "BOOTLOADER set to '$BOOTLOADER', set it to 'GRUB2' explicitly to avoid the ambiguity"
+ fi
+ # we should add an ErrorIfDeprecated call here or later for GRUB Legacy deprecation
+ fi
LogPrint "Using specified bootloader '$BOOTLOADER' for 'rear recover'"
echo "$BOOTLOADER" | tr '[a-z]' '[A-Z]' >$bootloader_file
return
@@ -57,39 +73,31 @@ for block_device in /sys/block/* ; do
# Continue guessing the used bootloader by inspecting the first bytes on the next disk:
continue
fi
- # 'Hah!IdontNeedEFI' is the ASCII representation of the official GUID number
- # for a GPT BIOS boot partition which is 21686148-6449-6E6F-744E-656564454649
- # see https://en.wikipedia.org/wiki/BIOS_boot_partition (issue #1752).
- # Use single quotes for 'Hah!IdontNeedEFI' to be on the safe side
- # because with double quotes the ! would cause history expansion if that is enabled
- # (non-interactive shells do not perform history expansion by default but better safe than sorry):
- if grep -q 'Hah!IdontNeedEFI' $bootloader_area_strings_file ; then
- # Because 'Hah!IdontNeedEFI' contains the known bootloader 'EFI'
- # the default code below would falsely guess that 'EFI' is used
- # but actually another non-EFI bootloader is used here
- # cf. https://github.com/rear/rear/issues/1752#issue-303856221
- # so that in the 'Hah!IdontNeedEFI' case only non-EFI bootloaders are tested.
- # IBM Z (s390) uses zipl boot loader for RHEL and Ubuntu
- # cf. https://github.com/rear/rear/issues/2137
- for known_bootloader in GRUB2 GRUB ELILO LILO ZIPL ; do
- if grep -q -i "$known_bootloader" $bootloader_area_strings_file ; then
- LogPrint "Using guessed bootloader '$known_bootloader' for 'rear recover' (found in first bytes on $disk_device with GPT BIOS boot partition)"
- echo "$known_bootloader" >$bootloader_file
- return
- fi
- done
- # When in the 'Hah!IdontNeedEFI' case no known non-EFI bootloader is found
- # continue guessing the used bootloader by inspecting the first bytes on the next disk
- # because otherwise the default code below would falsely guess that 'EFI' is used
- # cf. https://github.com/rear/rear/pull/1754#issuecomment-383531597
- continue
- fi
# Check the default cases of known bootloaders.
# IBM Z (s390) uses zipl boot loader for RHEL and Ubuntu
# cf. https://github.com/rear/rear/issues/2137
- for known_bootloader in GRUB2-EFI EFI GRUB2 GRUB ELILO LILO ZIPL ; do
+ for known_bootloader in GRUB2 GRUB LILO ZIPL ; do
if grep -q -i "$known_bootloader" $bootloader_area_strings_file ; then
- LogPrint "Using guessed bootloader '$known_bootloader' for 'rear recover' (found in first bytes on $disk_device)"
+ # If we find "GRUB" (which means GRUB Legacy)
+ # do not unconditionally trust that because https://github.com/rear/rear/pull/589
+ # reads (excerpt):
+ # Problems found:
+ # The ..._install_grub.sh checked for GRUB2 which is not part
+ # of the first 2048 bytes of a disk - only GRUB was present -
+ # thus the check for grub-probe/grub2-probe
+ # and https://github.com/rear/rear/commit/079de45b3ad8edcf0e3df54ded53fe955abded3b
+ # reads (excerpt):
+ # replace grub-install by grub-probe
+ # as grub-install also exist in legacy grub
+ # so that if actually GRUB 2 is used, the string in the bootloader area
+ # is "GRUB" so that another test is needed to detect if actually GRUB 2 is used.
+ # When GRUB 2 is installed we assume GRUB 2 is used as boot loader.
+ if [ "$known_bootloader" = "GRUB" ] && is_grub2_installed ; then
+ known_bootloader=GRUB2
+ LogPrint "GRUB found in first bytes on $disk_device and GRUB 2 is installed, using GRUB2 as a guessed bootloader for 'rear recover'"
+ else
+ LogPrint "Using guessed bootloader '$known_bootloader' for 'rear recover' (found in first bytes on $disk_device)"
+ fi
echo "$known_bootloader" >$bootloader_file
return
fi
@@ -103,6 +111,26 @@ for block_device in /sys/block/* ; do
Log "End of strings in the first bytes on $disk_device"
done
+# No bootloader detected, but we are using UEFI - there is probably an EFI bootloader
+if is_true $USING_UEFI_BOOTLOADER ; then
+ if is_grub2_installed ; then
+ echo "GRUB2-EFI" >$bootloader_file
+ elif test -f /sbin/elilo ; then
+ echo "ELILO" >$bootloader_file
+ else
+ # There is an EFI bootloader, we don't know which one exactly.
+ # The value "EFI" is a bit redundant with USING_UEFI_BOOTLOADER=1,
+ # which already indicates that there is an EFI bootloader. We use it as a placeholder
+ # to not leave $bootloader_file empty.
+ # Note that it is legal to have USING_UEFI_BOOTLOADER=1 and e.g. known_bootloader=GRUB2
+ # (i.e. a non=EFI bootloader). This will happen in BIOS/UEFI hybrid boot scenarios.
+ # known_bootloader=GRUB2 indicates that there is a BIOS bootloader and USING_UEFI_BOOTLOADER=1
+ # indicates that there is also an EFI bootloader. Only the EFI one is being used at this
+ # time, but both will need to be restored.
+ echo "EFI" >$bootloader_file
+ fi
+ return 0
+fi
# Error out when no bootloader was specified or could be autodetected:
Error "Cannot autodetect what is used as bootloader, see default.conf about 'BOOTLOADER'"
diff --git a/usr/share/rear/lib/bootloader-functions.sh b/usr/share/rear/lib/bootloader-functions.sh
index a7363c4c..3dade874 100644
--- a/usr/share/rear/lib/bootloader-functions.sh
+++ b/usr/share/rear/lib/bootloader-functions.sh
@@ -529,6 +529,53 @@ function get_root_disk_UUID {
( set -o pipefail ; mount | grep ' on / ' | awk '{print $1}' | xargs blkid -s UUID -o value || Error "Failed to get root disk UUID" )
}
+# Detect whether actually GRUB 2 is installed and that test is to
+# check if grub-probe or grub2-probe is installed because
+# grub-probe or grub2-probe is only installed in case of GRUB 2.
+# Needed because one can't tell the GRUB version by looking at the MBR
+# (both GRUB 2 and GRUB Legacy have the string "GRUB" in their MBR).
+function is_grub2_installed () {
+ if type -p grub-probe >&2 || type -p grub2-probe >&2 ; then
+ Log "GRUB 2 is installed (grub-probe or grub2-probe exist)."
+ return 0
+ else
+ return 1
+ fi
+}
+
+# Determine whether a disk is worth detecting or installing GRUB on
+function is_disk_grub_candidate () {
+ local disk="$1"
+ local disk_partitions part
+ local label flags
+
+ # ToDo : validate $disk (does it even exist? Isn't it write-protected?)
+
+ # Installing grub on an LVM PV will wipe the metadata so we skip those
+ is_disk_a_pv "$disk" && return 1
+
+ label="$( get_disklabel_type "$disk" )" || return 1
+ # We don't care about the SUSE-specific 'gpt_sync_mbr' partition scheme
+ # anymore: https://github.com/rear/rear/pull/3145#discussion_r1481388431
+ if [ "$label" == gpt ] ; then
+ # GPT needs a special BIOS boot partition to store GRUB (BIOS version).
+ # Let's try to find it. It can be recognized as having the bios_grub flag.
+ disk_partitions=( $( get_child_components "$disk" "part" ) )
+ for part in "${disk_partitions[@]}" ; do
+ flags=( $( get_partition_flags "$part" ) )
+ IsInArray bios_grub "${flags[@]}" && return 0 # found!
+ done
+ # If a given GPT-partitioned disk does not contain a BIOS boot partition,
+ # GRUB for BIOS booting can not be installed into its MBR (grub-install errors out).
+ return 1
+ else
+ # Other disklabel types don't need anything special to install GRUB.
+ # The test for the PReP boot partition (finalize/Linux-ppc64le/660_install_grub2.sh)
+ # is a bit similar, but operates on the partition itself, not on the uderlying disk.
+ return 0
+ fi
+}
+
# Output GRUB2 configuration on stdout:
# $1 is the kernel file with appropriate path for GRUB2 to load the kernel from within GRUB2's root filesystem
# $2 is the initrd file with appropriate path for GRUB2 to load the initrd from within GRUB2's root filesystem
diff --git a/usr/share/rear/lib/layout-functions.sh b/usr/share/rear/lib/layout-functions.sh
index 69f38b47..ee651b2a 100644
--- a/usr/share/rear/lib/layout-functions.sh
+++ b/usr/share/rear/lib/layout-functions.sh
@@ -532,6 +532,33 @@ get_component_type() {
grep -E "^[^ ]+ $1 " $LAYOUT_TODO | cut -d " " -f 3
}
+# Get the disklabel (partition table) type of the disk $1 from the layout file
+# (NOT from the actual disk, so layout file must exist before calling this,
+# and it is useful during recovery even before the disk layout has been recreated)
+function get_disklabel_type () {
+ # from create_disk() in layout/prepare/GNU/Linux/100_include_partition_code.sh
+ local component disk size label junk
+
+ disk=''
+
+ read component disk size label junk < <(grep "^disk $1 " "$LAYOUT_FILE")
+ test $disk || return 1
+
+ echo $label
+}
+
+# Get partition flags from layout (space-separated) of partition given as $1
+function get_partition_flags () {
+ local part disk size pstart name flags partition junk
+
+ while read part disk size pstart name flags partition junk; do
+ if [ "$partition" == "$1" ] ; then
+ echo "$flags" | tr ',' ' '
+ return 0
+ fi
+ done < <(grep "^part " $LAYOUT_FILE)
+}
+
# Function returns 0 when v1 is greater or equal than v2
version_newer() {
local v1list=( ${1//[-.]/ } )
@@ -806,17 +833,17 @@ blkid_label_of_device() {
echo "$label"
}
-# Returns 1 if the device is an LVM physical volume
-# Returns 0 otherwise or if the device doesn't exists
+# Returns true if the device is an LVM physical volume
+# Returns false otherwise or if the device doesn't exist
is_disk_a_pv() {
disk=$1
# Using awk, select the 'lvmdev' line for which $disk is the device (column 3),
# cf. https://github.com/rear/rear/pull/1897
# If exit == 1, then there is such line (so $disk is a PV),
- # otherwise exit with default value '0', which falls through to 'return 0' below.
- awk "\$1 == \"lvmdev\" && \$3 == \"${disk}\" { exit 1 }" "$LAYOUT_FILE" >/dev/null || return 1
- return 0
+ # otherwise exit with default value '0', which falls through to 'return 1' below.
+ awk "\$1 == \"lvmdev\" && \$3 == \"${disk}\" { exit 1 }" "$LAYOUT_FILE" >/dev/null || return 0
+ return 1
}
function is_multipath_used {
diff --git a/usr/share/rear/lib/savelayout-workflow.sh b/usr/share/rear/lib/savelayout-workflow.sh
index 69cda58e..27bb0a1a 100644
--- a/usr/share/rear/lib/savelayout-workflow.sh
+++ b/usr/share/rear/lib/savelayout-workflow.sh
@@ -10,6 +10,10 @@ if [[ "$VERBOSE" ]]; then
fi
WORKFLOWS+=( savelayout )
WORKFLOW_savelayout () {
+ # layout code needs to know whether we are using UEFI (USING_UEFI_BOOTLOADER)
+ # as it also detects the bootloader in use ( layout/save/default/445_guess_bootloader.sh )
+ Source $SHARE_DIR/prep/default/320_include_uefi_env.sh
+
#DISKLAYOUT_FILE=$VAR_DIR/layout/disklayout.conf # defined in default.conf now (issue #678)
SourceStage "layout/save"
}

View File

@ -1,112 +0,0 @@
commit f6af518baf3b5a4dc06bf8cfea262e627eee3e07
Merge: ed4c78d5 75a86fc3
Author: pcahyna <pcahyna@users.noreply.github.com>
Date: Wed Nov 1 12:53:33 2023 +0100
Merge pull request #3061 from pcahyna/save-lvm-poolmetadatasize
Save LVM pool metadata volume size in disk layout
diff --git a/usr/share/rear/layout/save/GNU/Linux/220_lvm_layout.sh b/usr/share/rear/layout/save/GNU/Linux/220_lvm_layout.sh
index 7400c586..b12cff1f 100644
--- a/usr/share/rear/layout/save/GNU/Linux/220_lvm_layout.sh
+++ b/usr/share/rear/layout/save/GNU/Linux/220_lvm_layout.sh
@@ -18,7 +18,7 @@ local already_processed_lvs=()
local lv_layout_supported lvs_fields
local origin lv vg
local layout modules
-local thinpool chunksize stripes stripesize segmentsize
+local thinpool chunksize stripes stripesize segmentsize poolmetadatasize
local kval infokval
local lvs_exit_code
@@ -130,7 +130,7 @@ local lvs_exit_code
echo "# Skipping PV $pdev that is not part of a valid VG (VG '$vgrp' empty or more than one word):"
contains_visible_char "$vgrp" || vgrp='<missing_VG>'
echo "# lvmdev /dev/$vgrp $pdev $uuid $size"
- # Continue with the next line in the output of "lvm pvdisplay -c"
+ # Continue with the next line in the output of "lvm pvdisplay -C"
continue
fi
# With the above example the output is:
@@ -138,10 +138,10 @@ local lvs_exit_code
echo "lvmdev /dev/$vgrp $pdev $uuid $size"
done
- # Check the exit code of "lvm pvdisplay -c"
- # in the "lvm pvdisplay -c | while read line ; do ... done" pipe:
+ # Check the exit code of "lvm pvdisplay -C"
+ # in the "lvm pvdisplay -C ... | while read line ; do ... done" pipe:
pvdisplay_exit_code=${PIPESTATUS[0]}
- test $pvdisplay_exit_code -eq 0 || Error "LVM command 'lvm pvdisplay -c' failed with exit code $pvdisplay_exit_code"
+ test $pvdisplay_exit_code -eq 0 || Error "LVM command 'lvm pvdisplay -C ... -o pv_name,vg_name,pv_size,pv_uuid' failed with exit code $pvdisplay_exit_code"
# Get the volume group configuration:
# Format: lvmgrp <volume_group> <extentsize> [<size(extents)>] [<size(bytes)>]
@@ -200,18 +200,18 @@ local lvs_exit_code
# Specify the fields for the lvs command depending on whether or not the 'lv_layout' field is supported:
if is_true $lv_layout_supported ; then
- lvs_fields="origin,lv_name,vg_name,lv_size,lv_layout,pool_lv,chunk_size,stripes,stripe_size,seg_size"
+ lvs_fields="origin,lv_name,vg_name,lv_size,lv_layout,pool_lv,chunk_size,stripes,stripe_size,seg_size,lv_metadata_size"
else
# Use the 'modules' field as fallback replacement when the 'lv_layout' field is not supported:
- lvs_fields="origin,lv_name,vg_name,lv_size,modules,pool_lv,chunk_size,stripes,stripe_size,seg_size"
+ lvs_fields="origin,lv_name,vg_name,lv_size,modules,pool_lv,chunk_size,stripes,stripe_size,seg_size,lv_metadata_size"
fi
# Example output of "lvs --separator=':' --noheadings --units b --nosuffix -o $lvs_fields"
- # with lvs_fields="origin,lv_name,vg_name,lv_size,lv_layout,pool_lv,chunk_size,stripes,stripe_size,seg_size"
+ # with lvs_fields="origin,lv_name,vg_name,lv_size,lv_layout,pool_lv,chunk_size,stripes,stripe_size,seg_size,lv_metadata_size"
# i.e. when the 'lv_layout' field is supported:
- # :home:system:6148849664:linear::0:1:0:6148849664
- # :root:system:14050918400:linear::0:1:0:14050918400
- # :swap:system:1262485504:linear::0:1:0:1262485504
+ # :home:system:6148849664:linear::0:1:0:6148849664:
+ # :root:system:14050918400:linear::0:1:0:14050918400:
+ # :swap:system:1262485504:linear::0:1:0:1262485504:
# There are two leading blanks in the output (at least on SLES12-SP4 with LVM 2.02.180 and SLES15-SP3 with LVM 2.03.05).
# The 'lvs' output lines ordering does not match the ordering of the LVs kernel device nodes /dev/dm-N
# # lsblk -ipbo NAME,KNAME,TYPE,FSTYPE,SIZE,MOUNTPOINT /dev/sda2
@@ -251,9 +251,9 @@ local lvs_exit_code
# that the recreated system did not boot (boot screen showed GRUB but there it hung with constant 100% CPU usage)
# so automatically shrinking only the biggest LVs avoids that a relatively small 'swap' LV gets shrinked.
# With 'sort -n -t ':' -k 4' the above 'lvs' output lines become
- # :swap:system:1262485504:linear::0:1:0:1262485504
- # :home:system:6148849664:linear::0:1:0:6148849664
- # :root:system:14050918400:linear::0:1:0:14050918400
+ # :swap:system:1262485504:linear::0:1:0:1262485504:
+ # :home:system:6148849664:linear::0:1:0:6148849664:
+ # :root:system:14050918400:linear::0:1:0:14050918400:
# so only the 'root' LV may get automatically shrinked if needed.
lvm lvs --separator=':' --noheadings --units b --nosuffix -o $lvs_fields | sort -n -t ':' -k 4 | while read line ; do
@@ -304,14 +304,23 @@ local lvs_exit_code
# With the above example segmentsize=19927138304 and segmentsize=1535115264
segmentsize="$( echo "$line" | awk -F ':' '{ print $10 }' )"
- # TODO: Explain what that code is meant to do.
- # In particular a more explanatory variable name than 'kval' might help.
- # In 110_include_lvm_code.sh there is a comment what 'kval' means there
- # # kval: "key:value" pairs, separated by spaces
- # so probably 'kval' means the same here, but what is 'infokval'?
+ # With the above example poolmetadatasize=""
+ poolmetadatasize="$( echo "$line" | awk -F ':' '{ print $11 }' )"
+
+ # kval is a string of space-separated key:value pairs. Key names are chosen to represent
+ # long options to lvcreate, and value will be the parameter for each long option.
+ # e.g. "chunksize:${chunksize}b" will eventually become a --chunksize=${chunksize}b
+ # argument to lvcreate.
+ # This way 110_include_lvm_code.sh which constructs the arguments to lvcreate
+ # can be kept generic and does not need to be updated every time an argument is added,
+ # as long as the argument can follow this generic scheme.
+ # infokval are key:value pairs that are not used when restoring the layout
+ # and are kept in disklayout.conf only as comments for information
+ # (because the setting is not easy or desirable to preserve).
kval=""
infokval=""
[ -z "$thinpool" ] || kval="${kval:+$kval }thinpool:$thinpool"
+ [ -z "$poolmetadatasize" ] || kval="${kval:+$kval }poolmetadatasize:${poolmetadatasize}b"
[ $chunksize -eq 0 ] || kval="${kval:+$kval }chunksize:${chunksize}b"
[ $stripesize -eq 0 ] || kval="${kval:+$kval }stripesize:${stripesize}b"
[ $segmentsize -eq $size ] || infokval="${infokval:+$infokval }segmentsize:${segmentsize}b"

View File

@ -1,62 +0,0 @@
From c8409e1f2972e9cd87d9390ca0b52b908d1a872a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Zaoral?= <lzaoral@redhat.com>
Date: Wed, 20 Mar 2024 12:22:46 +0100
Subject: [PATCH] skip btrfs subvolumes when detecting ESP partitions
The idea is to find all direct partitions that contain the ESP
mount point and to skip all other transitive `fs:` dependencies.
The `diskdeps.conf` file contains following entries on default Fedora
installations (the list was shortened to only the relevant ones):
```
/dev/vda1 /dev/vda
/dev/vda4 /dev/vda
/dev/vda5 /dev/vda
fs:/boot/efi /dev/vda1
fs:/boot/efi fs:/boot
fs:/boot/efi fs:/
fs:/boot/efi btrfsmountedsubvol:/
fs:/boot /dev/vda4
fs:/boot fs:/
fs:/boot btrfsmountedsubvol:/
fs:/ /dev/vda5
btrfsmountedsubvol:/ /dev/vda5
```
The ESP partition is only on `/dev/vda1`. However, the `find_partition` call
was not taking into account the need to skip mounted btrfs subvolumes as well.
Therefore, `/dev/vda5` was listed as an ESP partition as well.
This change makes sure that only direct ESP partitions are listed and
fixes a bug where ReaR would create broken BootXXXX entries which point to
completely unrelated partitions.
Relevant excerpts from logs:
```
++ efibootmgr --create --gpt --disk /dev/vda --part 1 --write-signature --label 'RedHatEnterpriseServer 41' --loader '\EFI\fedora\grubx64.efi'
...
++ efibootmgr --create --gpt --disk /dev/vda --part 5 --write-signature --label 'RedHatEnterpriseServer 41' --loader '\EFI\fedora\grubx64.efi'
```
---
usr/share/rear/finalize/Linux-i386/670_run_efibootmgr.sh | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/usr/share/rear/finalize/Linux-i386/670_run_efibootmgr.sh b/usr/share/rear/finalize/Linux-i386/670_run_efibootmgr.sh
index 33d87767..8b658618 100644
--- a/usr/share/rear/finalize/Linux-i386/670_run_efibootmgr.sh
+++ b/usr/share/rear/finalize/Linux-i386/670_run_efibootmgr.sh
@@ -47,7 +47,10 @@ fi
# accounting for possible trailing slashes in TARGET_FS_ROOT
esp_mountpoint_inside="${esp_mountpoint#${TARGET_FS_ROOT%%*(/)}}"
-boot_efi_parts=$( find_partition "fs:$esp_mountpoint_inside" fs )
+# Find all partitions with the ESP mount point and skip all other transitive
+# 'fs' and 'btrfsmountedsubvol' components in LAYOUT_DEPS (var/lib/rear/layout/diskdeps.conf)
+# to support ESP on software RAID (cf. https://github.com/rear/rear/pull/2608).
+boot_efi_parts=$( find_partition "fs:$esp_mountpoint_inside" 'btrfsmountedsubvol fs' )
if ! test "$boot_efi_parts" ; then
LogPrint "Unable to find ESP $esp_mountpoint_inside in layout"
LogPrint "Trying to determine device currently mounted at $esp_mountpoint as fallback"
--
2.44.0

View File

@ -1,90 +0,0 @@
commit c08658d5a0260c3242bb817e77b9c6dadecd14f6
Merge: 879e173f db191aaf
Author: pcahyna <pcahyna@users.noreply.github.com>
Date: Wed Sep 13 12:46:54 2023 +0200
Merge pull request #3047 from pcahyna/skip-invalid-drives
Skip invalid disk drives (zero sized, no media) when saving layout
Cherry-picked-by: Lukáš Zaoral <lzaoral@redhat.com>
diff --git a/usr/share/rear/layout/save/GNU/Linux/200_partition_layout.sh b/usr/share/rear/layout/save/GNU/Linux/200_partition_layout.sh
index 9d6e0bc6..b2dc743a 100644
--- a/usr/share/rear/layout/save/GNU/Linux/200_partition_layout.sh
+++ b/usr/share/rear/layout/save/GNU/Linux/200_partition_layout.sh
@@ -413,17 +413,21 @@ Log "Saving disks and their partitions"
elif [[ ! ($blockd = *rpmb || $blockd = *[0-9]boot[0-9]) ]]; then # Silently skip Replay Protected Memory Blocks and others
devname=$(get_device_name $disk)
devsize=$(get_disk_size ${disk#/sys/block/})
- disktype=$(parted -s $devname print | grep -E "Partition Table|Disk label" | cut -d ":" -f "2" | tr -d " ")
# Ensure syntactically correct 'disk' entries:
# Each value must exist and each value must be a single non-blank word so we 'test' without quoting the value:
test $devname || Error "Invalid 'disk' entry (no disk device name for '$disk')"
test $devsize || Error "Invalid 'disk $devname' entry (no device size for '$devname')"
- # We do not error out when there is no partition label type value because
- # "rear recover" works in a special case without partition label type value when there is
- # only a 'disk' entry but nothing else for this disk exists in disklayout.conf
- # which can happen when /dev/sdX is an empty SD card slot without medium,
- # see https://github.com/rear/rear/issues/2810
- test $disktype || LogPrintError "No partition label type for 'disk $devname' (may cause 'rear recover' failure)"
+ # Validation error can happen when /dev/sdX is an empty SD card slot without medium,
+ # see https://github.com/rear/rear/issues/2810 https://github.com/rear/rear/issues/2958
+ # this is normal, but such device must be skipped and not be added to the layout
+ # - it does not contain any data anyway.
+ # See https://github.com/rear/rear/pull/3047
+ if ! validation_error=$(is_disk_valid $devname) ; then
+ LogPrintError "Ignoring $blockd: $validation_error"
+ continue
+ fi
+ disktype=$(parted -s $devname print | grep -E "Partition Table|Disk label" | cut -d ":" -f "2" | tr -d " ")
+ test $disktype || Error "Invalid 'disk $devname' entry (no partition table type for '$devname')"
if [ "$disktype" != "dasd" ]; then
echo "# Disk $devname"
echo "# Format: disk <devname> <size(bytes)> <partition label type>"
diff --git a/usr/share/rear/lib/layout-functions.sh b/usr/share/rear/lib/layout-functions.sh
index 6dd43313..e46478d6 100644
--- a/usr/share/rear/lib/layout-functions.sh
+++ b/usr/share/rear/lib/layout-functions.sh
@@ -819,6 +819,41 @@ is_disk_a_pv() {
return 1
}
+# Check whether disk is suitable for being added to layout
+# Can be used to skip obviously unsuitable/broken devices
+# (missing device node, zero size, device can't be opened).
+# Should not be used to skip potential mapping targets before layout restoration
+# - an invalid disk may become valid later, for example if it is a DASD that needs
+# low-level formatting (see 090_include_dasd_code.sh and 360_generate_dasd_format_code.sh),
+# unformatted DASDs show zero size.
+# Returns 0 if the device is ok
+# Returns nonzero code if it should be skipped, and a text describing the error
+# on stdout
+# usage example:
+# local err
+# if ! err=$(is_disk_valid /dev/sda); then
+
+function is_disk_valid {
+ local disk="$1"
+ local size
+
+ if ! test -b "$disk" ; then
+ echo "$disk is not a block device"
+ return 1
+ fi
+ # capture stdout in a variable and redirect stderr to stdout - the error message
+ # will be our output
+ if { size=$(blockdev --getsize64 "$disk") ; } 2>&1 ; then
+ if ! test "$size" -gt 0 2>/dev/null ; then
+ echo "$disk has invalid size $size"
+ return 1
+ fi
+ return 0
+ else
+ return 1
+ fi
+}
+
function is_multipath_used {
# Return 'false' if there is no multipath command:
type multipath &>/dev/null || return 1

View File

@ -1,112 +0,0 @@
commit ed4c78d5fe493ea368989d0086a733653692f5cb
Merge: 3c9398bb 0cdcab02
Author: pcahyna <pcahyna@users.noreply.github.com>
Date: Mon Oct 30 18:31:01 2023 +0100
Merge pull request #3058 from pcahyna/skip-useless-xfs-mount-options
Skip useless xfs mount options when mounting during recovery
Cherry-picked-by: Lukáš Zaoral <lzaoral@redhat.com>
diff --git a/usr/share/rear/layout/prepare/GNU/Linux/133_include_mount_filesystem_code.sh b/usr/share/rear/layout/prepare/GNU/Linux/133_include_mount_filesystem_code.sh
index d5707779..f7115f55 100644
--- a/usr/share/rear/layout/prepare/GNU/Linux/133_include_mount_filesystem_code.sh
+++ b/usr/share/rear/layout/prepare/GNU/Linux/133_include_mount_filesystem_code.sh
@@ -29,6 +29,7 @@ mount_fs() {
case $name in
(options)
# Do not mount nodev, as chrooting later on would fail:
+ # FIXME: naive approach, will replace any "nodev" inside longer options/values
value=${value//nodev/dev}
# btrfs mount options like subvolid=259 or subvol=/@/.snapshots/1/snapshot
# from the old system cannot work here for recovery because btrfs subvolumes
@@ -36,13 +37,8 @@ mount_fs() {
# so that those mount options are removed here. All btrfs subvolume handling
# happens in the btrfs_subvolumes_setup_SLES function in 136_include_btrfs_subvolumes_SLES_code.sh
# or in the btrfs_subvolumes_setup_generic function in 135_include_btrfs_subvolumes_generic_code.sh
- # First add a comma at the end so that it is easier to remove a mount option at the end:
- value=${value/%/,}
- # Remove all subvolid= and subvol= mount options (the extglob shell option is enabled in rear):
- value=${value//subvolid=*([^,]),/}
- value=${value//subvol=*([^,]),/}
- # Remove all commas at the end:
- mountopts=${value/%,/}
+ # Remove all subvolid= and subvol= mount options:
+ mountopts="$( remove_mount_options_values $value subvolid subvol )"
;;
esac
done
@@ -147,6 +143,27 @@ mount_fs() {
echo "mount $mountopts,remount,user_xattr $device $TARGET_FS_ROOT$mountpoint"
) >> "$LAYOUT_CODE"
;;
+ (xfs)
+ # remove logbsize=... mount option. It is a purely performance/memory usage optimization option,
+ # which can lead to mount failures, because it must be an integer multiple of the log stripe unit
+ # and the log stripe unit can be different in the recreated filesystem from the original filesystem
+ # (for example when using MKFS_XFS_OPTIONS, or in some exotic situations involving an old filesystem,
+ # see GitHub issue #2777 ).
+ # If logbsize is not an integer multiple of the log stripe unit, mount fails with the warning
+ # "XFS (...): logbuf size must be greater than or equal to log stripe size"
+ # in the kernel log
+ # (and a confusing error message
+ # "mount: ...: wrong fs type, bad option, bad superblock on ..., missing codepage or helper program, or other error."
+ # from the mount command), causing the layout restoration in the recovery process to fail.
+ # Wrong sunit/swidth can cause mount to fail as well, with this in the kernel log:
+ # "kernel: XFS (...): alignment check failed: sunit/swidth vs. agsize",
+ # so remove the sunit=.../swidth=... mount options as well.
+ mountopts="$( remove_mount_options_values "$mountopts" logbsize sunit swidth )"
+ (
+ echo "mkdir -p $TARGET_FS_ROOT$mountpoint"
+ echo "mount $mountopts $device $TARGET_FS_ROOT$mountpoint"
+ ) >> "$LAYOUT_CODE"
+ ;;
(*)
(
echo "mkdir -p $TARGET_FS_ROOT$mountpoint"
diff --git a/usr/share/rear/lib/filesystems-functions.sh b/usr/share/rear/lib/filesystems-functions.sh
index f459c204..f0547706 100644
--- a/usr/share/rear/lib/filesystems-functions.sh
+++ b/usr/share/rear/lib/filesystems-functions.sh
@@ -256,3 +256,40 @@ function total_target_fs_used_disk_space() {
# Output xfs options for further use
echo "$xfs_opts"
}
+
+
+# $1 is a mount command argument (string containing comma-separated
+# mount options). The remaining arguments to the function ($2 ... )
+# specify the mount options to remove from $1, together with a trailing "="
+# and any value that follows each option.
+# For example, the call
+# "remove_mount_options_values nodev,uid=1,rw,gid=1 uid gid"
+# returns "nodev,rw".
+# There is no support for removing a mount option without a value and "=",
+# so "remove_mount_options_values nodev,uid=1,rw,gid=1 rw" will not work.
+# The function will return the modified string on stdout.
+
+function remove_mount_options_values () {
+ local str="$1"
+
+ shift
+ # First add a comma at the end so that it is easier to remove a mount option at the end:
+ str="${str/%/,}"
+ for i in "$@" ; do
+ # FIXME this also removes trailing strings at the end of longer words
+ # For example if one wants to remove any id=... option,
+ # the function will also replace "uid=1" by "u" by removing
+ # the trailing "id=1", which is not intended.
+ # Not easy to fix because $str can contain prefixes which are not
+ # mount options but arguments to the mount command itself
+ # (in particluar, "-o ").
+ # FIXME this simple approach would fail in case of mount options
+ # containing commas, for example the "context" option values,
+ # see mount(8)
+
+ # the extglob shell option is enabled in rear
+ str="${str//$i=*([^,]),/}"
+ done
+ # Remove all commas at the end:
+ echo "${str/%,/}"
+}

View File

@ -1,343 +0,0 @@
commit 283efdaea10ff62dc94e968f74e1136b8384a954
Merge: 41c2d9b1 70a39382
Author: Johannes Meixner <jsmeix@suse.com>
Date: Fri Jul 21 14:56:34 2023 +0200
Merge pull request #3025 from rear/jsmeix-create_grub2_cfg
Fixed create_grub2_cfg function usage:
Introduced GRUB2_SET_ROOT_COMMAND config variable
in addition to the existing GRUB2_SEARCH_ROOT_COMMAND
to get consistency how GRUB2 sets and/or searches its 'root' device
and adapted the create_grub2_cfg function calls accordingly.
Furthermore enhanced some messages regarding Secure Boot setup.
Cherry-picked-by: Lukáš Zaoral <lzaoral@redhat.com>
diff --git a/usr/share/rear/conf/default.conf b/usr/share/rear/conf/default.conf
index 3e29280f..5ec89049 100644
--- a/usr/share/rear/conf/default.conf
+++ b/usr/share/rear/conf/default.conf
@@ -1210,15 +1210,6 @@ USB_BIOS_BOOT_DEFAULT=""
# Default is using GRUB2 for EFI other then elilo, extlinux for ext, syslinux otherwise:
USB_BOOTLOADER=
#
-# USB EFI booting can benefit with a better search string than the default:
-# GRUB2_SEARCH_ROOT_COMMAND="search --no-floppy --set=root --label REAR-EFI
-# as hardcoded in script output/USB/Linux-i386/100_create_efiboot.sh
-# Only to be used by experts. An example of a different setup could be:
-# GRUB2_SEARCH_ROOT_COMMAND="search --no-floppy --set=root --label REAR-EFI --hint hd0,msdos1"
-# or
-# GRUB2_SEARCH_ROOT_COMMAND="search --no-floppy --set=root --file /EFI/BOOT/BOOTX64.efi"
-GRUB2_SEARCH_ROOT_COMMAND=""
-#
# Resulting files that should be copied onto the USB stick:
USB_FILES=()
#
@@ -3550,12 +3541,12 @@ GRUB2_INSTALL_DEVICES="${GRUB2_INSTALL_DEVICES:-}"
# and /boot/efi, if applicable.
# More modules can be installed into the Grub2 standalone image ramdisk without
# being included in the core image, see GRUB2_MODULES_UEFI.
-# This variable currently applies when building Grub2 boot loader for UEFI in two scenarios:
+# This variable currently applies when building GRUB2 boot loader for UEFI in two scenarios:
# 1. UEFI boot without secure boot (SECURE_BOOT_BOOTLOADER="")
# and / or
# 2. UEFI boot with GRUB_RESCUE="y"
-# Incorrect use of this variable can lead to unusable ReaR recovery system.
-# When you modify this variable, verify that your ReaR recovery system works.
+# Incorrect use of this variable can lead to an unusable ReaR recovery system.
+# When you specify it, verify that your ReaR recovery system works.
GRUB2_MODULES_UEFI_LOAD=()
##
@@ -3565,8 +3556,8 @@ GRUB2_MODULES_UEFI_LOAD=()
# When empty ReaR will use the defaults of grub-mkstandalone
# (install all modules in the standalone image ramdisk)
# This variable currently applies in the same scenarios as GRUB2_MODULES_UEFI_LOAD.
-# Incorrect use of this variable can lead to unusable ReaR recovery system.
-# When you modify this variable, verify that your ReaR recovery system works.
+# Incorrect use of this variable can lead to an unusable ReaR recovery system.
+# When you specify it, verify that your ReaR recovery system works.
GRUB2_MODULES_UEFI=()
##
@@ -3587,6 +3578,29 @@ GRUB2_DEFAULT_BOOT="chainloader"
# The timeout in seconds to automatically boot GRUB2_DEFAULT_BOOT
# when GRUB2 is used as bootloader for the ReaR recovery system.
GRUB2_TIMEOUT="$USER_INPUT_TIMEOUT"
+#
+# GRUB2_SET_ROOT_COMMAND
+# GRUB2_SEARCH_ROOT_COMMAND
+# Incorrect use of those variables can lead to an unusable ReaR recovery system.
+# When you specify one of them, verify that your ReaR recovery system works.
+# GRUB2_SET_ROOT_COMMAND is a GRUB2 command to set the 'root' device in GRUB2.
+# For example to set the first CDROM device to be used as 'root' device in GRUB2 use
+# GRUB2_SET_ROOT_COMMAND="set root=cd0"
+# GRUB2_SEARCH_ROOT_COMMAND is a GRUB2 command to let GRUB2 search for its 'root' device.
+# For example USB EFI booting may need a different search string than the default like
+# GRUB2_SEARCH_ROOT_COMMAND="search --no-floppy --set=root --label REAR-EFI"
+# cf. the script output/USB/Linux-i386/100_create_efiboot.sh
+# Other examples of a different setup could be like
+# GRUB2_SEARCH_ROOT_COMMAND="search --no-floppy --set=root --label REAR-EFI --hint hd0,msdos1"
+# or
+# GRUB2_SEARCH_ROOT_COMMAND="search --no-floppy --set=root --file /EFI/BOOT/BOOTX64.efi"
+# When both GRUB2_SET_ROOT_COMMAND and GRUB2_SEARCH_ROOT_COMMAND are specified
+# then GRUB2_SET_ROOT_COMMAND is done before GRUB2_SEARCH_ROOT_COMMAND
+# so GRUB2_SET_ROOT_COMMAND sets a default 'root' device and
+# then GRUB2 searches for a 'root' device via GRUB2_SEARCH_ROOT_COMMAND
+# which is used if one is found - otherwise the default 'root' device is used as fallback.
+GRUB2_SET_ROOT_COMMAND=""
+GRUB2_SEARCH_ROOT_COMMAND=""
##
# USING_UEFI_BOOTLOADER
@@ -3625,13 +3639,18 @@ USING_UEFI_BOOTLOADER=
##
# SECURE_BOOT_BOOTLOADER
#
-# When using Secure Boot set full path of your signed boot loader here.
-# e. g.
-# SECURE_BOOT_BOOTLOADER="/boot/efi/EFI/BOOT/shim.efi"
-#
-# SECURE_BOOT_BOOTLOADER overrides UEFI_BOOTLOADER
-#
-# c.f. https://github.com/rear/rear/pull/1385
+# When using Secure Boot specify the full path of the Secure Boot bootloader.
+# For example: SECURE_BOOT_BOOTLOADER="/boot/efi/EFI/BOOT/shim.efi"
+# SECURE_BOOT_BOOTLOADER overrides UEFI_BOOTLOADER.
+# Normally Shim is the only used Secure Boot bootloader.
+# For a technical description of Shim see https://mjg59.dreamwidth.org/19448.html
+# Shim is a first stage bootloader that loads and executes a second stage bootloader
+# which normally is GRUB that is usually available as a grub*.efi file.
+# When Shim is used, its second stage bootloader can be actually anything
+# named grub*.efi (second stage bootloader is Shim compile time option)
+# so when for example SECURE_BOOT_BOOTLOADER="/boot/efi/EFI/BOOT/shim.efi" is specified
+# then all /boot/efi/EFI/BOOT/grub*.efi files are made available as second stage bootloader.
+# For more details see the output/ISO/Linux-i386/250_populate_efibootimg.sh script.
SECURE_BOOT_BOOTLOADER=""
##
diff --git a/usr/share/rear/lib/bootloader-functions.sh b/usr/share/rear/lib/bootloader-functions.sh
index 5f18d2ad..f3e27937 100644
--- a/usr/share/rear/lib/bootloader-functions.sh
+++ b/usr/share/rear/lib/bootloader-functions.sh
@@ -536,25 +536,25 @@ function get_root_disk_UUID {
# so that kernel and initrd are /boot_mountpoint/path/to/kernel and /boot_mountpoint/path/to/initrd
# and that boot partition gets set as root device name for GRUB2's
# then $1 would have to be /path/to/kernel and $2 would have to be /path/to/initrd
-# $3 is an appropriate GRUB2 command to set its root device (usually via GRUB2's 'root' environment variable)
-# e.g. when the filesystem that contains kernel and initrd has the filesystem label REARBOOT
-# then $3 could be something like 'search --no-floppy --set root --label REARBOOT'
function create_grub2_cfg {
local grub2_kernel="$1"
test "$grub2_kernel" || BugError "create_grub2_cfg function called without grub2_kernel argument"
- DebugPrint "Configuring GRUB2 kernel $grub2_kernel"
+ DebugPrint "Let GRUB2 load kernel $grub2_kernel"
local grub2_initrd="$2"
test "$grub2_initrd" || BugError "create_grub2_cfg function called without grub2_initrd argument"
- DebugPrint "Configuring GRUB2 initrd $grub2_initrd"
- local grub2_search_root_command="$3"
- if ! test "$grub2_search_root_command" ; then
- test "$grub2_set_root" && grub2_search_root_command="set root=$grub2_set_root"
- fi
- if ! test "$grub2_search_root_command" ; then
- test "$GRUB2_SEARCH_ROOT_COMMAND" && grub2_search_root_command="$GRUB2_SEARCH_ROOT_COMMAND"
+ DebugPrint "Let GRUB2 load initrd $grub2_initrd"
+
+ # Before https://github.com/rear/rear/pull/3025 it was possible to call create_grub2_cfg()
+ # with a third argument that is a "search GRUB2 'root' device command" string:
+ test "$3" && BugError "create_grub2_cfg function must not be called with a third argument"
+ # Since https://github.com/rear/rear/pull/3025 GRUB2_SET_ROOT_COMMAND and/or GRUB2_SEARCH_ROOT_COMMAND must be specified:
+ if contains_visible_char "$GRUB2_SEARCH_ROOT_COMMAND" ; then
+ contains_visible_char "$GRUB2_SET_ROOT_COMMAND" && DebugPrint "Set GRUB2 default root device via '$GRUB2_SET_ROOT_COMMAND'"
+ DebugPrint "Let GRUB2 search root device via '$GRUB2_SEARCH_ROOT_COMMAND'"
+ else
+ contains_visible_char "$GRUB2_SET_ROOT_COMMAND" || BugError "create_grub2_cfg function called but neither GRUB2_SET_ROOT_COMMAND nor GRUB2_SEARCH_ROOT_COMMAND is specified"
+ DebugPrint "Set GRUB2 root device via '$GRUB2_SET_ROOT_COMMAND'"
fi
- test "$grub2_search_root_command" || grub2_search_root_command="search --no-floppy --set=root --file /boot/efiboot.img"
- DebugPrint "Configuring GRUB2 root device as '$grub2_search_root_command'"
local grub2_default_menu_entry="$GRUB2_DEFAULT_BOOT"
test "$grub2_default_menu_entry" || grub2_default_menu_entry="chainloader"
@@ -613,6 +613,9 @@ function create_grub2_cfg {
echo "terminal_input serial"
echo "terminal_output serial"
fi
+ else
+ DebugPrint "No serial console in GRUB2 (USE_SERIAL_CONSOLE is not true)"
+ echo "echo 'No serial console (USE_SERIAL_CONSOLE was not true)'"
fi
}
@@ -632,7 +635,6 @@ menuentry "Relax-and-Recover (BIOS or UEFI without Secure Boot)" --id=rear {
echo 'Loading initial ramdisk $grub2_initrd ...'
initrd $grub2_initrd
}
-
menuentry "Relax-and-Recover (UEFI and Secure Boot)" --id=rear_secure_boot {
insmod gzio
insmod xzio
@@ -714,10 +716,14 @@ EOF
# The actual work starts here.
# Create and output GRUB2 configuration.
- # Sleep 3 seconds before the GRUB2 menu replaces what there is on the screen
- # so that the user has a chance to see possible (error) messages on the screen.
+ # Sleep (interruptible) USER_INPUT_INTERRUPT_TIMEOUT seconds (by default 30 seconds)
+ # before the GRUB2 menu replaces what there is on the screen
+ # so that the user can read and understand possible (error) messages on the screen.
cat << EOF
-$grub2_search_root_command
+$GRUB2_SET_ROOT_COMMAND
+$GRUB2_SEARCH_ROOT_COMMAND
+echo "Using root device (\$root) - available devices are:"
+ls
insmod all_video
set gfxpayload=keep
insmod part_gpt
@@ -727,8 +733,8 @@ $( create_grub2_serial_entry )
set timeout="$grub2_timeout"
set default="$grub2_default_menu_entry"
set fallback="chainloader"
-echo 'Switching to GRUB2 boot menu...'
-sleep --verbose --interruptible 3
+echo 'Switching to GRUB boot menu...'
+sleep --verbose --interruptible $USER_INPUT_INTERRUPT_TIMEOUT
$( create_grub2_rear_boot_entry )
$( create_grub2_boot_next_entry )
$( create_grub2_reboot_entry )
diff --git a/usr/share/rear/output/ISO/Linux-i386/250_populate_efibootimg.sh b/usr/share/rear/output/ISO/Linux-i386/250_populate_efibootimg.sh
index c0fc5834..ff97dbd1 100644
--- a/usr/share/rear/output/ISO/Linux-i386/250_populate_efibootimg.sh
+++ b/usr/share/rear/output/ISO/Linux-i386/250_populate_efibootimg.sh
@@ -13,22 +13,32 @@ mkdir $v -p $efi_boot_tmp_dir || Error "Could not create $efi_boot_tmp_dir"
mkdir $v -p $efi_boot_tmp_dir/fonts || Error "Could not create $efi_boot_tmp_dir/fonts"
mkdir $v -p $efi_boot_tmp_dir/locale || Error "Could not create $efi_boot_tmp_dir/locale"
-# Copy the grub*.efi executable to EFI/BOOT/BOOTX64.efi
+# Copy the grub*.efi or shim.efi executable to EFI/BOOT/BOOTX64.efi
# Intentionally an empty UEFI_BOOTLOADER results an invalid "cp -v /tmp/.../mnt/EFI/BOOT/BOOTX64.efi" command that fails:
cp $v "$UEFI_BOOTLOADER" $efi_boot_tmp_dir/BOOTX64.efi || Error "Could not find UEFI_BOOTLOADER '$UEFI_BOOTLOADER'"
local uefi_bootloader_dirname="$( dirname $UEFI_BOOTLOADER )"
if test -f "$SECURE_BOOT_BOOTLOADER" ; then
- # FIXME: Explain why it tests that a SECURE_BOOT_BOOTLOADER file exists
- # but then it copies any grub*.efi files and ignores if there are none.
- # Why does it not copy SECURE_BOOT_BOOTLOADER and errors out if that fails?
- # If shim is used, bootloader can be actually anything
- # named as grub*.efi (follow-up loader is shim compile time option), see
+ # For a technical description of Shim see https://mjg59.dreamwidth.org/19448.html
+ # Shim is a signed EFI binary that is a first stage bootloader
+ # that loads and executes another (signed) EFI binary
+ # which normally is a second stage bootloader
+ # which normally is a GRUB EFI binary
+ # which normally is available as a file named grub*.efi
+ # so when SECURE_BOOT_BOOTLOADER is used as UEFI_BOOTLOADER
+ # (cf. rescue/default/850_save_sysfs_uefi_vars.sh)
+ # then Shim (usually shim.efi) was copied above as efi_boot_tmp_dir/BOOTX64.efi
+ # and Shim's second stage bootloader must be also copied where Shim already is.
+ DebugPrint "Using Shim '$SECURE_BOOT_BOOTLOADER' as first stage UEFI bootloader BOOTX64.efi"
+ # When Shim is used, its second stage bootloader can be actually anything
+ # named grub*.efi (second stage bootloader is Shim compile time option), see
# http://www.rodsbooks.com/efi-bootloaders/secureboot.html#initial_shim
+ local second_stage_UEFI_bootloader_files="$( echo $uefi_bootloader_dirname/grub*.efi )"
# Avoid 'nullglob' pitfall when nothing matches .../grub*.efi which results
# an invalid "cp -v /tmp/.../mnt/EFI/BOOT/" command that fails
# cf. https://github.com/rear/rear/issues/1921
- local shim_files="$( echo $uefi_bootloader_dirname/grub*.efi )"
- test "$shim_files" && cp $v $shim_files $efi_boot_tmp_dir/
+ test "$second_stage_UEFI_bootloader_files" || Error "Could not find second stage bootloader '$uefi_bootloader_dirname/grub*.efi' for Shim"
+ DebugPrint "Using second stage UEFI bootloader files for Shim: $second_stage_UEFI_bootloader_files"
+ cp $v $second_stage_UEFI_bootloader_files $efi_boot_tmp_dir/ || Error "Failed to copy second stage bootloader files for Shim"
fi
# FIXME: Do we need to test if we are ebiso at all?
@@ -47,6 +57,12 @@ if test "ebiso" = "$( basename $ISO_MKISOFS_BIN )" ; then
cp -pL $v $KERNEL_FILE $efi_boot_tmp_dir/kernel || Error "Failed to copy KERNEL_FILE '$KERNEL_FILE' to $efi_boot_tmp_dir/kernel"
cp $v $TMP_DIR/$REAR_INITRD_FILENAME $efi_boot_tmp_dir/$REAR_INITRD_FILENAME || Error "Failed to copy initrd '$REAR_INITRD_FILENAME' into $efi_boot_tmp_dir"
create_ebiso_elilo_conf > $efi_boot_tmp_dir/elilo.conf
+ # We need to set the GRUB environment variable 'root' to a reasonable default/fallback value
+ # because GRUB's default 'root' (or GRUB's 'root' identifcation heuristics) would point to the ramdisk
+ # but neither kernel nor initrd are located on the ramdisk but on the device where the recovery system was booted from.
+ # GRUB2_SET_ROOT_COMMAND and/or GRUB2_SEARCH_ROOT_COMMAND is needed by the create_grub2_cfg() function.
+ # Set GRUB2_SET_ROOT_COMMAND if not specified by the user:
+ contains_visible_char "$GRUB2_SET_ROOT_COMMAND" || GRUB2_SET_ROOT_COMMAND="set root=cd0"
create_grub2_cfg /isolinux/kernel /isolinux/$REAR_INITRD_FILENAME > $efi_boot_tmp_dir/grub.cfg
fi
fi
@@ -67,10 +83,12 @@ else
# This was seen at least in Debian Buster running in Qemu
# (VirtualBox works fine, RHEL/CentOS in Qemu works fine as well).
# The GRUB2 image created by grub-mkstandalone has 'root' set to memdisk, which can't work.
- # To make ReaR work in this case, set 'root' to a sensible value 'cd0' before trying search
- # (via ${grub2_set_root:+"set root=$grub2_set_root"} in the create_grub2_cfg function)
+ # To make ReaR work in this case, set 'root' to a sensible default value 'cd0'
+ # before trying to search via GRUB2_SEARCH_ROOT_COMMAND in the create_grub2_cfg function
# cf. https://github.com/rear/rear/issues/2434 and https://github.com/rear/rear/pull/2453
- grub2_set_root=cd0
+ # Set GRUB2_SET_ROOT_COMMAND and GRUB2_SEARCH_ROOT_COMMAND if not specified by the user:
+ contains_visible_char "$GRUB2_SET_ROOT_COMMAND" || GRUB2_SET_ROOT_COMMAND="set root=cd0"
+ contains_visible_char "$GRUB2_SEARCH_ROOT_COMMAND" || GRUB2_SEARCH_ROOT_COMMAND="search --no-floppy --set=root --file /boot/efiboot.img"
create_grub2_cfg /isolinux/kernel /isolinux/$REAR_INITRD_FILENAME > $efi_boot_tmp_dir/grub.cfg
fi
diff --git a/usr/share/rear/output/USB/Linux-i386/100_create_efiboot.sh b/usr/share/rear/output/USB/Linux-i386/100_create_efiboot.sh
index 1f6ca069..8ad4d97e 100644
--- a/usr/share/rear/output/USB/Linux-i386/100_create_efiboot.sh
+++ b/usr/share/rear/output/USB/Linux-i386/100_create_efiboot.sh
@@ -93,11 +93,13 @@ EOF
;;
(2)
DebugPrint "Configuring GRUB2 for EFI boot"
- # We need to explicitly set GRUB 2 'root' variable to $efi_label (hardcoded "REAR-EFI")
- # because default $root would point to memdisk, where kernel and initrd are NOT present.
- # GRUB2_SEARCH_ROOT_COMMAND is used in the create_grub2_cfg() function:
- [[ -z "$GRUB2_SEARCH_ROOT_COMMAND" ]] && GRUB2_SEARCH_ROOT_COMMAND="search --no-floppy --set=root --label $efi_label"
- # Create config for GRUB 2
+ # We need to set the GRUB environment variable 'root' to the partition device with label $efi_label (hardcoded "REAR-EFI")
+ # because GRUB's default 'root' (or GRUB's 'root' identifcation heuristics) would point to the ramdisk but neither kernel
+ # nor initrd are located on the ramdisk but on the partition device with label $efi_label.
+ # GRUB2_SET_ROOT_COMMAND and/or GRUB2_SEARCH_ROOT_COMMAND is needed by the create_grub2_cfg() function.
+ # Set GRUB2_SEARCH_ROOT_COMMAND if not specified by the user:
+ contains_visible_char "$GRUB2_SEARCH_ROOT_COMMAND" || GRUB2_SEARCH_ROOT_COMMAND="search --no-floppy --set=root --label $efi_label"
+ # Create config for GRUB2:
create_grub2_cfg $efi_dir/kernel $efi_dir/$REAR_INITRD_FILENAME > $efi_dst/grub.cfg
# Create BOOTX86.efi but only if we are NOT secure booting.
# We are not able to create signed boot loader
diff --git a/usr/share/rear/output/USB/Linux-i386/300_create_grub.sh b/usr/share/rear/output/USB/Linux-i386/300_create_grub.sh
index c2566bc5..1dbfe1de 100644
--- a/usr/share/rear/output/USB/Linux-i386/300_create_grub.sh
+++ b/usr/share/rear/output/USB/Linux-i386/300_create_grub.sh
@@ -70,10 +70,11 @@ if is_true $USING_UEFI_BOOTLOADER ; then
# grub[2]-install creates the $BUILD_DIR/outputfs/boot/grub[2] sub-directory that is needed
# to create the GRUB2 config $BUILD_DIR/outputfs/boot/grub[2].cfg in the next step:
DebugPrint "Creating GRUB2 config for legacy BIOS boot as USB bootloader"
-test "$USB_DEVICE_BOOT_LABEL" || USB_DEVICE_BOOT_LABEL="REARBOOT"
+contains_visible_char "$USB_DEVICE_BOOT_LABEL" || USB_DEVICE_BOOT_LABEL="REARBOOT"
# We need to set the GRUB environment variable 'root' to the partition device with filesystem label USB_DEVICE_BOOT_LABEL
# because GRUB's default 'root' (or GRUB's 'root' identifcation heuristics) would point to the ramdisk but neither kernel
# nor initrd are located on the ramdisk but on the partition device with filesystem label USB_DEVICE_BOOT_LABEL.
-# GRUB2_SEARCH_ROOT_COMMAND is used in the create_grub2_cfg() function:
-GRUB2_SEARCH_ROOT_COMMAND="search --no-floppy --set=root --label $USB_DEVICE_BOOT_LABEL"
-create_grub2_cfg /$USB_PREFIX/kernel /$USB_PREFIX/$REAR_INITRD_FILENAME > $usb_boot_dir/$grub_cfg || Error "Failed to create $usb_boot_dir/$grub_cfg"
+# GRUB2_SET_ROOT_COMMAND and/or GRUB2_SEARCH_ROOT_COMMAND is needed by the create_grub2_cfg() function.
+# Set GRUB2_SEARCH_ROOT_COMMAND if not specified by the user:
+contains_visible_char "$GRUB2_SEARCH_ROOT_COMMAND" || GRUB2_SEARCH_ROOT_COMMAND="search --no-floppy --set=root --label $USB_DEVICE_BOOT_LABEL"
+create_grub2_cfg /$USB_PREFIX/kernel /$USB_PREFIX/$REAR_INITRD_FILENAME > $usb_boot_dir/$grub_cfg
diff --git a/usr/share/rear/rescue/default/850_save_sysfs_uefi_vars.sh b/usr/share/rear/rescue/default/850_save_sysfs_uefi_vars.sh
index a1af17fa..051f2755 100644
--- a/usr/share/rear/rescue/default/850_save_sysfs_uefi_vars.sh
+++ b/usr/share/rear/rescue/default/850_save_sysfs_uefi_vars.sh
@@ -135,7 +135,11 @@ for dummy in "once" ; do
done
# Show to the user what will actually be used as UEFI bootloader file:
-LogPrint "Using '$UEFI_BOOTLOADER' as UEFI bootloader file"
+if test -f "$SECURE_BOOT_BOOTLOADER" ; then
+ LogPrint "Using '$UEFI_BOOTLOADER' as UEFI Secure Boot bootloader file"
+else
+ LogPrint "Using '$UEFI_BOOTLOADER' as UEFI bootloader file (non Secure Boot)"
+fi
# Save the variables we need in recover mode into the rescue.conf file:
cat - <<EOF >> "$ROOTFS_DIR/etc/rear/rescue.conf"

View File

@ -1,88 +0,0 @@
commit 46b29195bff7f93cf5bd4c2dd83d69e5676800cb
Merge: 2611da2b efb37fb9
Author: Johannes Meixner <jsmeix@suse.com>
Date: Tue Aug 8 14:44:16 2023 +0200
Merge pull request #3031 from rear/jsmeix-USB-Secure-Boot
Secure Boot support for OUTPUT=USB:
In output/USB/Linux-i386/100_create_efiboot.sh
added SECURE_BOOT_BOOTLOADER related code that is based
on the code in output/ISO/Linux-i386/250_populate_efibootimg.sh
with some adaptions to make it work within the existing USB code.
The basic idea for Secure Boot booting of the ReaR recovery system
is to "just copy" the (signed) EFI binaries of the Linux distribution
(shim*.efi and grub*.efi as first and second stage UEFI bootloaders)
instead of let ReaR make its own EFI binary via build_bootx86_efi()
see https://github.com/rear/rear/pull/3031
Cherry-picked-by: Lukáš Zaoral <lzaoral@redhat.com>
diff --git a/usr/share/rear/output/USB/Linux-i386/100_create_efiboot.sh b/usr/share/rear/output/USB/Linux-i386/100_create_efiboot.sh
index 8ad4d97e..123442cc 100644
--- a/usr/share/rear/output/USB/Linux-i386/100_create_efiboot.sh
+++ b/usr/share/rear/output/USB/Linux-i386/100_create_efiboot.sh
@@ -51,8 +51,44 @@ mkdir -p $efi_dst || Error "Failed to create directory '$efi_dst'"
# "cp: failed to preserve ownership for '/tmp/rear-efi.XXXXXXXXXX/EFI/BOOT/kernel': Operation not permitted"
# because it copies to a VFAT filesystem on the EFI partition (see format/USB/default/300_format_usb_disk.sh)
# cf. https://github.com/rear/rear/issues/2683
-# Copy boot loader:
-cp -L $v "$UEFI_BOOTLOADER" "$efi_dst/BOOTX64.efi" || Error "Failed to copy UEFI_BOOTLOADER '$UEFI_BOOTLOADER' to $efi_dst/BOOTX64.efi"
+# The SECURE_BOOT_BOOTLOADER related code below is based on the code in output/ISO/Linux-i386/250_populate_efibootimg.sh
+# because I <jsmeix@suse.de> noticed that Secure Boot works with ISO at least for me, cf.
+# https://github.com/rear/rear/pull/3025#issuecomment-1635876186
+# but not with USB, cf.
+# https://github.com/rear/rear/pull/3025#issuecomment-1643774477
+# so I tried to re-use the ISO Secure Boot code for USB
+# which made Secure Boot "just work" for me with USB
+# but I had to do some (minor) adaptions to make it work
+# within the existing USB code, cf.
+# https://github.com/rear/rear/pull/3031#issuecomment-1653443454
+# Copy UEFI bootloader:
+if test -f "$SECURE_BOOT_BOOTLOADER" ; then
+ # For a technical description of Shim see https://mjg59.dreamwidth.org/19448.html
+ # Shim is a signed EFI binary that is a first stage bootloader
+ # that loads and executes another (signed) EFI binary
+ # which normally is a second stage bootloader
+ # which normally is a GRUB EFI binary
+ # which normally is available as a file named grub*.efi
+ # so when SECURE_BOOT_BOOTLOADER is used as UEFI_BOOTLOADER
+ # (cf. rescue/default/850_save_sysfs_uefi_vars.sh)
+ # then Shim (usually shim.efi) must be copied as EFI/BOOT/BOOTX64.efi
+ # and Shim's second stage bootloader must be also copied where Shim already is.
+ DebugPrint "Using '$SECURE_BOOT_BOOTLOADER' as first stage Secure Boot bootloader BOOTX64.efi"
+ cp -L $v "$SECURE_BOOT_BOOTLOADER" "$efi_dst/BOOTX64.efi" || Error "Failed to copy SECURE_BOOT_BOOTLOADER '$SECURE_BOOT_BOOTLOADER' to $efi_dst/BOOTX64.efi"
+ # When Shim is used, its second stage bootloader can be actually anything
+ # named grub*.efi (second stage bootloader is Shim compile time option), see
+ # http://www.rodsbooks.com/efi-bootloaders/secureboot.html#initial_shim
+ local uefi_bootloader_dirname="$( dirname $SECURE_BOOT_BOOTLOADER )"
+ local second_stage_UEFI_bootloader_files="$( echo $uefi_bootloader_dirname/grub*.efi )"
+ # Avoid 'nullglob' pitfall when nothing matches .../grub*.efi which would result
+ # an invalid "cp -v /var/tmp/.../EFI/BOOT/" command that fails
+ # cf. https://github.com/rear/rear/issues/1921
+ test "$second_stage_UEFI_bootloader_files" || Error "Could not find second stage Secure Boot bootloader $uefi_bootloader_dirname/grub*.efi"
+ DebugPrint "Using second stage Secure Boot bootloader files: $second_stage_UEFI_bootloader_files"
+ cp -L $v $second_stage_UEFI_bootloader_files $efi_dst/ || Error "Failed to copy second stage Secure Boot bootloader files"
+else
+ cp -L $v "$UEFI_BOOTLOADER" "$efi_dst/BOOTX64.efi" || Error "Failed to copy UEFI_BOOTLOADER '$UEFI_BOOTLOADER' to $efi_dst/BOOTX64.efi"
+fi
# Copy kernel:
cp -L $v "$KERNEL_FILE" "$efi_dst/kernel" || Error "Failed to copy KERNEL_FILE '$KERNEL_FILE' to $efi_dst/kernel"
# Copy initrd:
@@ -101,8 +137,14 @@ EOF
[[ -z "$GRUB2_SEARCH_ROOT_COMMAND" ]] && GRUB2_SEARCH_ROOT_COMMAND="search --no-floppy --set=root --label $efi_label"
# Create config for GRUB 2
create_grub2_cfg $efi_dir/kernel $efi_dir/$REAR_INITRD_FILENAME > $efi_dst/grub.cfg
- # Create bootloader, this overwrite BOOTX64.efi copied in previous step ...
- build_bootx86_efi $efi_dst/BOOTX64.efi $efi_dst/grub.cfg "/boot" "$UEFI_BOOTLOADER"
+ # Create BOOTX86.efi but only if we are NOT secure booting.
+ # We are not able to create signed boot loader
+ # so we need to reuse existing one.
+ # See issue #1374
+ # build_bootx86_efi () can be safely used for other scenarios.
+ if ! test -f "$SECURE_BOOT_BOOTLOADER" ; then
+ build_bootx86_efi $efi_dst/BOOTX64.efi $efi_dst/grub.cfg "/boot" "$UEFI_BOOTLOADER"
+ fi
;;
(*)
Error "GRUB version '$grub_version' is neither '0' (legacy GRUB) nor '2' (GRUB 2)"

156
rear.spec
View File

@ -2,132 +2,44 @@
%global debug_package %{nil}
Name: rear
Version: 2.7
Release: 14%{?dist}
Version: 2.9
Release: 1%{?dist}
Summary: Relax-and-Recover is a Linux disaster recovery and system migration tool
URL: https://relax-and-recover.org
License: GPL-3.0-or-later
License: GPL-3.0-or-later AND LGPL-2.1-or-later
#Source0: https://github.com/rear/rear/archive/%%{version}.tar.gz#/rear-%%{version}.tar.gz
Source0: rear-%{version}-clean.tar.gz
Source0: https://github.com/rear/rear/archive/%{version}/rear-%{version}.tar.gz
# Add cronjob and systemd timer as documentation
Source1: rear.cron
Source2: rear.service
Source3: rear.timer
# doc/rear-release-notes.txt is CC-BY-ND-3.0, which is not an allowed license
# for documentation. Therefore we use this Makefile to remove the file
# before shipping it.
# Download the upstream tarball and invoke "make rear-%%{version}-clean.tar.gz"
# while in the tarball's directory:
Source4: Makefile
# Required for HTML user guide
BuildRequires: asciidoctor
BuildRequires: efi-srpm-macros
# Needed for %%autosetup -S git
BuildRequires: git-core
BuildRequires: make
######################
# upstream backports #
######################
# pass -y to lvcreate instead of piping the output of yes
# https://github.com/rear/rear/commit/bca0e7a92af16cb7fb82ef04401cdb3286068081
Patch101: rear-bz2104005.patch
# fix initrd generation on s390x
# https://github.com/rear/rear/commit/6d1e5ab96213a0d79489c4296cd1f5a4be645597
Patch102: rear-bz2130945.patch
# do not use ':' as a field separator in pvdisplay output
# https://github.com/rear/rear/commit/29e739ae7c0651f8f77c60846bfbe2b6c91baa29
Patch103: rear-bz2091163.patch
# do not autoformat DASDs on s390x
# https://github.com/rear/rear/commit/015c1ffd9fa96b01882b068714d3bc3aae3b5168
Patch104: s390-no-clobber-disks.patch
# continue when extracting shrank files with tar
# https://github.com/rear/rear/commit/41c2d9b1fbcece4b0890ab92e9f5817621917ad3
Patch105: rear-device-shrinking-bz2223895.patch
# add secure boot support for OUTPUT=USB
# https://github.com/rear/rear/commit/46b29195bff7f93cf5bd4c2dd83d69e5676800cb
Patch106: rear-uefi-usb-secureboot-bz2196445.patch
# remove the lvmdevices file at the end of recovery
# https://github.com/rear/rear/commit/5a8c5086bf3fc28236436ff3ef27196509f0375d
Patch107: rear-remove-lvmdevices-bz2145014.patch
# save LVM pool metadata volume size in disk layout
# https://github.com/rear/rear/commit/f6af518baf3b5a4dc06bf8cfea262e627eee3e07
Patch108: rear-save-lvm-poolmetadatasize-RHEL-6984.patch
# skip useless xfs mount options when mounting during recovery
# https://github.com/rear/rear/commit/ed4c78d5fe493ea368989d0086a733653692f5cb
Patch109: rear-skip-useless-xfs-mount-options-RHEL-10478.patch
# fix unusable recovery with newer systemd
# https://github.com/rear/rear/commit/060fef89b6968f0c8f254e6f612eff839b83c057
Patch110: rear-fix-compatibility-with-newer-systemd-bz2254871.patch
# make initrd accessible only by root
# https://github.com/rear/rear/commit/89b61793d80bc2cb2abe47a7d0549466fb087d16
Patch111: rear-CVE-2024-23301.patch
# copy the console= kernel arguments from the original system
# https://github.com/rear/rear/commit/88f11d19d748fff3f36357ef1471ee75fbfacabb
# https://github.com/rear/rear/commit/42e04f36f5f8eea0017915bb35e56ee285b394d7
# https://github.com/rear/rear/commit/07da02143b5597b202e66c187e53103561018255
Patch112: rear-copy-console-kernel-cmdline-from-host.patch
# support saving and restoring hybrid BIOS/UEFI bootloader setup and clean
# up bootloader detection
# https://github.com/rear/rear/commit/096bfde5e234f5a803bae74f24e3821798022c7c
# https://github.com/rear/rear/commit/ca99d855579cfcab37f985e2547a3187e0f0aeeb
Patch113: rear-restore-hybrid-bootloader-RHEL-16864.patch
# resolve libs for executable links in COPY_AS_IS
# https://github.com/rear/rear/commit/9f859c13f5ba285cd1d5983c9b595975c21888d3
Patch114: rear-resolve-libraries-for-symlinks-in-COPY_AS_IS-RHEL-15108.patch
# skip invalid disk drives (zero sized, no media) when saving layout
# https://github.com/rear/rear/commit/c08658d5a0260c3242bb817e77b9c6dadecd14f6
Patch115: rear-skip-invalid-drives-RHEL-22863.patch
# fix useless warning that libsystemd-core requires additional libraries
# and ReaR recovery system needs additional libraries
# https://github.com/rear/rear/commit/eb574592a21c7ca986393c4563fe5484b9f01454
Patch116: rear-fix-libsystemd-ldd-warning.patch
# fix IPv6 addresses in nfs:// and sshfs:// BACKUP/OUTPUT_URL
# https://github.com/rear/rear/commit/8a10135bf958c03b4b5077fc7ae7761ad2a71eec
Patch117: rear-fix-ipv6.patch
# ALREADY INCLUDED IN REAR 2.7!
# remove obsolete FAT16 options to avoid kernel warning
# https://github.com/rear/rear/commit/9a6b9a109aa77afc6c96cf05bbd7988cf0310d61
# Patch118: rear-no-fat-16.patch
# fix booting on UEFI with multiple CDROM devices
# https://github.com/rear/rear/commit/283efdaea10ff62dc94e968f74e1136b8384a954
Patch119: rear-uefi-booting-with-multiple-cdrom-devices.patch
# skip btrfs subvolumes when detecting ESP partitions
# https://github.com/rear/rear/commit/c8409e1f2972e9cd87d9390ca0b52b908d1a872a
Patch120: rear-skip-btrfs-subvolumes-when-detecting-ESP-partitions.patch
# fix backup of btrfs subvolumes
# https://github.com/rear/rear/commit/ec9080664303165799a215cef062826b65f6a6f8
# https://github.com/rear/rear/commit/2da70f54936e5c558c9f607b1526b9b17f6501b1
Patch121: rear-fix-backup-of-btrfs-subvolumes.patch
# Patch101 - Patch121 Reserved
# Empty...
######################
# downstream patches #
######################
# suggest to install grub-efi-x64-modules on x86_64 UEFI Fedora/RHEL machines
Patch201: rear-bz1492177-warning.patch
# No-longer applicable
# Patch201: rear-bz1492177-warning.patch
# avoid vgcfgrestore on unsupported volume types
# https://github.com/pcahyna/rear/commit/5d5d1db3ca621eb80b9481924d1fc470571cfc09
Patch202: rear-bz1747468.patch
# skip deliberately broken symlinks in initrd on Fedora/RHEL
Patch203: rear-bz2119501.patch
# No-longer applicable
# Patch203: rear-bz2119501.patch
# additional fixes for NBU support
Patch204: rear-bz2120736.patch
@ -146,8 +58,6 @@ ExclusiveArch: %ix86 x86_64 ppc ppc64 ppc64le ia64 s390x
# see the GitHub issue https://github.com/rear/rear/issues/629
%ifarch %ix86 x86_64
Requires: syslinux
# We need mkfs.vfat for recreating EFI System Partition
Recommends: dosfstools
%endif
%ifarch ppc ppc64 ppc64le
# Called by grub2-install (except on PowerNV)
@ -161,10 +71,14 @@ Requires: s390utils-base
Requires: s390utils-core
%endif
# Required for HTML user guide
BuildRequires: asciidoctor
BuildRequires: git
BuildRequires: make
# See https://github.com/rhboot/efi-rpm-macros/blob/main/README
%ifarch %{efi}
# We need mkfs.vfat for recreating EFI System Partition
Requires: dosfstools
# Needed for ISO image creation
Requires: grub2-efi-%{efi_arch}-modules
%endif
### Mandatory dependencies:
Requires: attr
@ -212,10 +126,6 @@ Professional services and support are available.
%prep
%autosetup -p1 -S git
### Add a specific os.conf so we do not depend on LSB dependencies
%{?fedora:echo -e "OS_VENDOR=Fedora\nOS_VERSION=%{?fedora}" >etc/rear/os.conf}
%{?rhel:echo -e "OS_VENDOR=RedHatEnterpriseServer\nOS_VERSION=%{?rhel}" >etc/rear/os.conf}
# Change /lib to /usr/lib for COPY_AS_IS
sed -E -e "s:([\"' ])/lib:\1/usr/lib:g" \
-i usr/share/rear/prep/GNU/Linux/*include*.sh
@ -234,7 +144,7 @@ sed -e 's:/lib/:/usr/lib/:g' \
# and spurious changes will be seen.
# Set the timezone to UTC as a workaround.
# https://wiki.debian.org/ReproducibleBuilds/TimestampsInDocumentationGeneratedByAsciidoc
TZ=UTC make doc
TZ=UTC %make_build doc
%install
%make_install sbindir=%{_sbindir}
@ -246,12 +156,9 @@ install -m 0644 %{SOURCE3} %{buildroot}%{_docdir}/%{name}/
#-- FILES ---------------------------------------------------------------------#
%files
%license COPYING
%doc MAINTAINERS README.adoc doc/user-guide/*.html
# the only upstream *.txt file has an unacceptable license (CC-BY-ND-3.0)
#%%doc doc/*.txt
%doc MAINTAINERS README.md doc/user-guide doc/*.txt
%dir %{_sysconfdir}/rear/
%config(noreplace) %{_sysconfdir}/rear/local.conf
%{_sysconfdir}/rear/os.conf
%{_datadir}/rear/
%{_docdir}/%{name}/rear.*
%{_mandir}/man8/rear.8*
@ -260,6 +167,15 @@ install -m 0644 %{SOURCE3} %{buildroot}%{_docdir}/%{name}/
#-- CHANGELOG -----------------------------------------------------------------#
%changelog
* Tue Feb 04 2025 Lukáš Zaoral <lzaoral@redhat.com> - 2.9-1
- rebase to version 2.9 (rhbz#2343296)
- drop upstreamed patches
- remove obsolete patch for rhbz2119501
- ReaR 2.7 and newer do not copy dangling symlinks in /lib/modules/*/
- remove broken patch for rhbz1492177 (VERBOSE is a read-only var, so the script silently failed)
- install correct packages using proper RPM dependencies instead
- rebase remaining patches
* Tue Jan 21 2025 Lukáš Zaoral <lzaoral@redhat.com> - 2.7-14
- fix FTBFS after F42 bin/sbin merge

View File

@ -1,797 +0,0 @@
commit 015c1ffd9fa96b01882b068714d3bc3aae3b5168
Merge: 02dad206 20cc0137
Author: Schlomo Schapiro <schlomo+github@schapiro.org>
Date: Tue Feb 28 22:46:13 2023 +0100
Merge pull request #2943 from pcahyna/s390-layout-format
s390x (IBM Z) disk formatting fixes
Cherry-picked-by: Lukáš Zaoral <lzaoral@redhat.com>
diff --git a/packaging/rpm/rear.spec b/packaging/rpm/rear.spec
index eba48198..fb943019 100644
--- a/packaging/rpm/rear.spec
+++ b/packaging/rpm/rear.spec
@@ -29,8 +29,8 @@ BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
# Of course the rear bash scripts can be installed on any architecture just as any binaries can be installed on any architecture.
# But the meaning of architecture dependent packages should be on what architectures they will work.
# Therefore only those architectures that are actually supported are explicitly listed.
-# This avoids that rear can be "just installed" on architectures that are actually not supported (e.g. ARM or IBM z Systems):
-ExclusiveArch: %ix86 x86_64 ppc ppc64 ppc64le ia64
+# This avoids that rear can be "just installed" on architectures that are actually not supported (e.g. ARM):
+ExclusiveArch: %ix86 x86_64 ppc ppc64 ppc64le ia64 s390x
# Furthermore for some architectures it requires architecture dependent packages (like syslinux for x86 and x86_64)
# so that rear must be architecture dependent because ifarch conditions never match in case of "BuildArch: noarch"
# see the GitHub issue https://github.com/rear/rear/issues/629
diff --git a/usr/share/rear/conf/default.conf b/usr/share/rear/conf/default.conf
index fe34636f..50baaf82 100644
--- a/usr/share/rear/conf/default.conf
+++ b/usr/share/rear/conf/default.conf
@@ -486,6 +486,17 @@ test "$MIGRATION_MODE" || MIGRATION_MODE=''
# Currently by default no disk is wiped to avoid issues until this feature was more tested:
DISKS_TO_BE_WIPED='false'
+##
+# Formatting DASDs (S/390 specific)
+# DASD (Direct Access Storage Device) denotes a disk drive on the S/390 architecture.
+# DASDs need to be formatted before use (even before creating a partition table on them).
+# By default ReaR will format the DASDs that are going to be used to recreate the system
+# (are referenced in disklayout.conf) before recreating the disk layout.
+# This can be suppressed by setting FORMAT_DASDS="false". It can be useful when one intends
+# to use already formatted DASDs as recovery target.
+FORMAT_DASDS=""
+##
+
##
# Resizing partitions in MIGRATION_MODE during "rear recover"
#
diff --git a/usr/share/rear/layout/prep-for-mount/Linux-s390/205_s390_enable_disk.sh b/usr/share/rear/layout/prep-for-mount/Linux-s390/205_s390_enable_disk.sh
new file mode 120000
index 00000000..5f7a2ac0
--- /dev/null
+++ b/usr/share/rear/layout/prep-for-mount/Linux-s390/205_s390_enable_disk.sh
@@ -0,0 +1 @@
+../../prepare/Linux-s390/205_s390_enable_disk.sh
\ No newline at end of file
diff --git a/usr/share/rear/layout/prepare/GNU/Linux/100_include_partition_code.sh b/usr/share/rear/layout/prepare/GNU/Linux/100_include_partition_code.sh
index 84a7cd33..acc65adf 100644
--- a/usr/share/rear/layout/prepare/GNU/Linux/100_include_partition_code.sh
+++ b/usr/share/rear/layout/prepare/GNU/Linux/100_include_partition_code.sh
@@ -24,6 +24,7 @@ fi
### Prepare a disk for partitioning/general usage.
create_disk() {
local component disk size label junk
+ local blocksize layout dasdtype dasdcyls junk2
read component disk size label junk < <(grep "^disk $1 " "$LAYOUT_FILE")
cat >> "$LAYOUT_CODE" <<EOF
@@ -57,7 +58,8 @@ sync
EOF
- create_partitions "$disk" "$label"
+ # $junk can contain useful DASD-specific fields
+ create_partitions "$disk" "$label" "$junk"
cat >> "$LAYOUT_CODE" <<EOF
# Make sure device nodes are visible (eg. in RHEL4)
@@ -83,6 +85,11 @@ create_partitions() {
### List partition types/names to detect disk label type.
local -a names=()
local part disk size pstart name junk
+ local orig_block_size layout dasdtype dasdcyls junk2
+ if [ "$label" == dasd ]; then
+ # dasd has more fields - junk is not junk anymore
+ read orig_block_size layout dasdtype dasdcyls junk2 <<<$3
+ fi
while read part disk size pstart name junk ; do
names+=( $name )
case $name in
@@ -217,12 +224,12 @@ EOF
if [[ "$end" ]] ; then
end=$( mathlib_calculate "$end - 1" )
fi
- if [[ "$ARCH" == "Linux-s390" ]] ; then
+ if [[ "$ARCH" == "Linux-s390" && "$label" == dasd ]] ; then
# LDL formatted disks are already partitioned and should not be partitioned with parted or fdasd , it will fail
- # the listDasdLdl array contains devices such as /dev/dasdb that are formatted as LDL
- # listDasdLdl is set in layout/prepare/Linux-s390/205_s390_enable_disk.sh
- if ! IsInArray "$device" "${listDasdLdl[@]}" ; then
- echo "not LDL dasd formated disk, create a partition"
+ if [ "$layout" == LDL ]; then
+ Debug "$device: LDL formatted DASD, do not create a partition"
+ else
+ Debug "$device: ${layout} formatted DASD, create a partition"
cat >> "$LAYOUT_CODE" <<EOF
create_disk_partition "$device" "$name" $number $start $end
EOF
diff --git a/usr/share/rear/layout/prepare/Linux-s390/090_include_dasd_code.sh b/usr/share/rear/layout/prepare/Linux-s390/090_include_dasd_code.sh
new file mode 100644
index 00000000..fc5be463
--- /dev/null
+++ b/usr/share/rear/layout/prepare/Linux-s390/090_include_dasd_code.sh
@@ -0,0 +1,17 @@
+# Generate code for low-level formatting of a DASD
+
+dasd_format_code() {
+ local device size blocksize layout dasdtype dasdcyls
+
+ device="$1"
+ size="$2"
+ blocksize="$3"
+ layout="$4"
+ dasdtype="$5"
+ dasdcyls="$6"
+
+ has_binary dasdfmt || Error "Cannot find 'dasdfmt' command"
+
+ LogPrint 'dasdfmt:' $device ', blocksize:' $blocksize ', layout:' $layout
+ echo "dasdfmt -b $blocksize -d $layout -y $device"
+}
diff --git a/usr/share/rear/layout/prepare/Linux-s390/205_s390_enable_disk.sh b/usr/share/rear/layout/prepare/Linux-s390/205_s390_enable_disk.sh
index 0ff2fd58..0f6946a9 100644
--- a/usr/share/rear/layout/prepare/Linux-s390/205_s390_enable_disk.sh
+++ b/usr/share/rear/layout/prepare/Linux-s390/205_s390_enable_disk.sh
@@ -2,45 +2,36 @@
# Before we can compare or map DASD devices we must enable them.
# This operation is only needed during "rear recover".
-format_s390_disk() {
- LogPrint "run dasdfmt"
- while read line ; do
- LogPrint 'dasdfmt:' "$line"
- # example format command: dasdfmt -b 4096 -d cdl -y /dev/dasda
- # where
- # b is the block size
- # d is the layout:
- # cdl - compatible disk layout (can be shared with zos and zvm apps)
- # ldl - linux disk layout
- # y - answer yes
- device=$( echo $line | awk '{ print $7 }' )
- blocksize=$( echo $line | awk '{ print $3 }' )
- layout=$( echo $line | awk '{ print tolower($5) }' )
- if [[ "$layout" == "ldl" ]] ; then
- # listDasdLdl contains devices such as /dev/dasdb that are formatted as LDL
- # LDL formatted disks are already partitioned and should not be partitioned with parted or fdasd , it will fail
- # this var, listDasdLdl, is used by 100_include_partition_code.sh to exclude writing partition code to diskrestore.sh for LDL disks
- listDasdLdl+=( $device )
- LogPrint "LDL disk '$device' will not be partitioned (LDL disks are already partitioned)"
- fi
- LogPrint 'dasdfmt:' $device ', blocksize:' $blocksize ', layout:' $layout
- # dasd format
- dasdfmt -b $blocksize -d $layout -y $device
- done < <( grep "^dasdfmt " "$LAYOUT_FILE" )
-}
-
+DISK_MAPPING_HINTS=()
enable_s390_disk() {
+ local keyword device bus len newname
+
LogPrint "run chccwdev"
- while read line ; do
- LogPrint 'dasd channel:' "$line"
- device=$( echo $line | awk '{ print $4 }' )
- bus=$( echo $line | awk '{ print $2 }' )
- channel=$( echo $line | awk '{ print $5 }' )
- LogPrint 'chccwdev:' $device ', bus:' $bus ', channel:' $channel
- # dasd channel enable
- chccwdev -e $bus
- done < <( grep "^dasd_channel " "$LAYOUT_FILE" )
+ while read len device bus ; do
+ # this while loop must be outside the pipeline so that variables propagate outside
+ # (pipelines run in subshells)
+ LogPrint "Enabling DASD $device with virtual device number $bus"
+ if chccwdev -e $bus ; then
+ newname=$(lsdasd $bus | awk "/$bus/ { print \$3}" )
+ if ! test $newname ; then
+ LogPrintError "New device with virtual device number $bus not found among online DASDs"
+ continue
+ fi
+ if [ "$newname" != "$device" ]; then
+ LogPrint "original DASD '$device' changed name to '$newname'"
+ test "$MIGRATION_MODE" || MIGRATION_MODE='true'
+ fi
+ DISK_MAPPING_HINTS+=( "/dev/$device /dev/$newname" )
+ else
+ LogPrintError "Failed to enable $bus"
+ fi
+ done < <( grep "^dasd_channel " "$LAYOUT_FILE" | while read keyword bus device; do
+ # add device name length, so that "dasdb" sorts properly before "dasdaa"
+ # we need to create devices in the same order as the kernel orders them (by minor number)
+ # - this increases the chance that they will get identical names
+ echo ${#device} $device $bus
+ done | sort -k1n -k2 )
}
# May need to look at $OS_VENDOR also as DASD disk layout is distro specific:
@@ -49,7 +40,6 @@ case $OS_MASTER_VENDOR in
# "Fedora" also handles Red Hat
# "Debian" also handles Ubuntu
enable_s390_disk
- format_s390_disk
;;
(*)
LogPrintError "No code for DASD disk device enablement on $OS_MASTER_VENDOR"
diff --git a/usr/share/rear/layout/prepare/Linux-s390/360_generate_dasd_format_code.sh b/usr/share/rear/layout/prepare/Linux-s390/360_generate_dasd_format_code.sh
new file mode 100644
index 00000000..14bb942d
--- /dev/null
+++ b/usr/share/rear/layout/prepare/Linux-s390/360_generate_dasd_format_code.sh
@@ -0,0 +1,51 @@
+# DASD_FORMAT_CODE is the script to recreate the dasd formatting (dasdformat.sh).
+
+local component disk size label junk
+local blocksize layout dasdtype dasdcyls junk2
+
+
+save_original_file "$DASD_FORMAT_CODE"
+
+# Initialize
+
+echo '#!/bin/bash' >"$DASD_FORMAT_CODE"
+
+# Show the current output of lsdasd, it can be useful for identifying disks
+# (in particular it shows the Linux device name <-> virtual device number mapping,
+# formatted / unformatted status and the number/size of blocks when formatted )
+echo "# Current output of 'lsdasd':" >>"$DASD_FORMAT_CODE"
+lsdasd | sed -e 's/^/# /' >>"$DASD_FORMAT_CODE"
+
+cat <<EOF >>"$DASD_FORMAT_CODE"
+
+LogPrint "Start DASD format restoration."
+
+set -e
+set -x
+
+EOF
+
+while read component disk size label junk; do
+ if [ "$label" == dasd ]; then
+ # Ignore excluded components.
+ # Normally they are removed in 520_exclude_components.sh,
+ # but we run before it, so we must skip them here as well.
+ if IsInArray "$disk" "${EXCLUDE_RECREATE[@]}" ; then
+ Log "Excluding $disk from DASD reformatting."
+ continue
+ fi
+ # dasd has more fields - junk is not junk anymore
+ read blocksize layout dasdtype dasdcyls junk2 <<<$junk
+ dasd_format_code "$disk" "$size" "$blocksize" "$layout" "$dasdtype" "$dasdcyls" >> "$DASD_FORMAT_CODE" || \
+ LogPrintError "Error producing DASD format code for $disk"
+ fi
+done < <(grep "^disk " "$LAYOUT_FILE")
+
+cat <<EOF >>"$DASD_FORMAT_CODE"
+
+set +x
+set +e
+
+LogPrint "DASD(s) formatted."
+
+EOF
diff --git a/usr/share/rear/layout/prepare/Linux-s390/370_confirm_dasd_format_code.sh b/usr/share/rear/layout/prepare/Linux-s390/370_confirm_dasd_format_code.sh
new file mode 100644
index 00000000..5ba4edd5
--- /dev/null
+++ b/usr/share/rear/layout/prepare/Linux-s390/370_confirm_dasd_format_code.sh
@@ -0,0 +1,69 @@
+# adapted from 100_confirm_layout_code.sh
+#
+# Let the user confirm the
+# DASD format code (dasdformat.sh) script.
+#
+
+is_false "$FORMAT_DASDS" && return 0
+
+# Show the user confirmation dialog in any case but when not in migration mode
+# automatically proceed with less timeout USER_INPUT_INTERRUPT_TIMEOUT (by default 10 seconds)
+# to avoid longer delays (USER_INPUT_TIMEOUT is by default 300 seconds) in case of unattended recovery:
+# (taken from 120_confirm_wipedisk_disks.sh)
+local timeout="$USER_INPUT_TIMEOUT"
+is_true "$MIGRATION_MODE" || timeout="$USER_INPUT_INTERRUPT_TIMEOUT"
+
+rear_workflow="rear $WORKFLOW"
+original_disk_space_usage_file="$VAR_DIR/layout/config/df.txt"
+rear_shell_history="$( echo -e "cd $VAR_DIR/layout/\nvi $DASD_FORMAT_CODE\nless $DASD_FORMAT_CODE" )"
+unset choices
+choices[0]="Confirm DASD format script and continue '$rear_workflow'"
+choices[1]="Edit DASD format script ($DASD_FORMAT_CODE)"
+choices[2]="View DASD format script ($DASD_FORMAT_CODE)"
+choices[3]="View original disk space usage ($original_disk_space_usage_file)"
+choices[4]="Confirm what is currently on the DASDs, skip formatting them and continue '$rear_workflow'"
+choices[5]="Use Relax-and-Recover shell and return back to here"
+choices[6]="Abort '$rear_workflow'"
+prompt="Confirm or edit the DASD format script"
+choice=""
+wilful_input=""
+# When USER_INPUT_DASD_FORMAT_CODE_CONFIRMATION has any 'true' value be liberal in what you accept and
+# assume choices[0] 'Confirm DASD format' was actually meant:
+is_true "$USER_INPUT_DASD_FORMAT_CODE_CONFIRMATION" && USER_INPUT_DASD_FORMAT_CODE_CONFIRMATION="${choices[0]}"
+while true ; do
+ choice="$( UserInput -I DASD_FORMAT_CODE_CONFIRMATION -t "$timeout" -p "$prompt" -D "${choices[0]}" "${choices[@]}" )" && wilful_input="yes" || wilful_input="no"
+ case "$choice" in
+ (${choices[0]})
+ # Confirm DASD format file and continue:
+ is_true "$wilful_input" && LogPrint "User confirmed DASD format script" || LogPrint "Continuing '$rear_workflow' by default"
+ break
+ ;;
+ (${choices[1]})
+ # Run 'vi' with the original STDIN STDOUT and STDERR when 'rear' was launched by the user:
+ vi $DASD_FORMAT_CODE 0<&6 1>&7 2>&8
+ ;;
+ (${choices[2]})
+ # Run 'less' with the original STDIN STDOUT and STDERR when 'rear' was launched by the user:
+ less $DASD_FORMAT_CODE 0<&6 1>&7 2>&8
+ ;;
+ (${choices[3]})
+ # Run 'less' with the original STDIN STDOUT and STDERR when 'rear' was launched by the user:
+ less $original_disk_space_usage_file 0<&6 1>&7 2>&8
+ ;;
+ (${choices[4]})
+ # Confirm what is on the disks and continue without formatting
+ FORMAT_DASDS="false"
+ ;;
+ (${choices[5]})
+ # rear_shell runs 'bash' with the original STDIN STDOUT and STDERR when 'rear' was launched by the user:
+ rear_shell "" "$rear_shell_history"
+ ;;
+ (${choices[6]})
+ abort_dasd_format
+ Error "User chose to abort '$rear_workflow' in ${BASH_SOURCE[0]}"
+ ;;
+ esac
+done
+
+chmod +x $DASD_FORMAT_CODE
+
diff --git a/usr/share/rear/layout/prepare/Linux-s390/400_run_dasd_format_code.sh b/usr/share/rear/layout/prepare/Linux-s390/400_run_dasd_format_code.sh
new file mode 100644
index 00000000..16451af6
--- /dev/null
+++ b/usr/share/rear/layout/prepare/Linux-s390/400_run_dasd_format_code.sh
@@ -0,0 +1,185 @@
+# adapted from 200_run_layout_code.sh
+#
+# Run the DASD format code (dasdformat.sh)
+# again and again until it succeeds or the user aborts.
+#
+
+# Skip DASD formatting when the user has explicitly specified to not format them
+# or when the user selected "Confirm what is currently on the DASDs, skip formatting them"
+# in 370_confirm_dasd_format_code.sh
+
+is_false "$FORMAT_DASDS" && return 0
+
+function lsdasd_output () {
+ lsdasd 1>> >( tee -a "$RUNTIME_LOGFILE" 1>&7 )
+}
+
+rear_workflow="rear $WORKFLOW"
+original_disk_space_usage_file="$VAR_DIR/layout/config/df.txt"
+rear_shell_history="$( echo -e "cd $VAR_DIR/layout/\nvi $DASD_FORMAT_CODE\nless $RUNTIME_LOGFILE" )"
+wilful_input=""
+
+unset choices
+choices[0]="Rerun DASD format script ($DASD_FORMAT_CODE)"
+choices[1]="View '$rear_workflow' log file ($RUNTIME_LOGFILE)"
+choices[2]="Edit DASD format script ($DASD_FORMAT_CODE)"
+choices[3]="Show what is currently on the disks ('lsdasd' device list)"
+choices[4]="View original disk space usage ($original_disk_space_usage_file)"
+choices[5]="Use Relax-and-Recover shell and return back to here"
+choices[6]="Confirm what is currently on the disks and continue '$rear_workflow'"
+choices[7]="Abort '$rear_workflow'"
+prompt="DASD format choices"
+
+choice=""
+# When USER_INPUT_DASD_FORMAT_CODE_RUN has any 'true' value be liberal in what you accept and
+# assume choices[0] 'Rerun DASD format script' was actually meant
+# regardless that this likely lets 'rear recover' run an endless loop
+# of failed DASD format attempts but ReaR must obey what the user specified
+# (perhaps it is intended to let 'rear recover' loop here until an admin intervenes):
+is_true "$USER_INPUT_DASD_FORMAT_CODE_RUN" && USER_INPUT_DASD_FORMAT_CODE_RUN="${choices[0]}"
+
+unset confirm_choices
+confirm_choices[0]="Confirm recreated DASD format and continue '$rear_workflow'"
+confirm_choices[1]="Go back one step to redo DASD format"
+confirm_choices[2]="Use Relax-and-Recover shell and return back to here"
+confirm_choices[3]="Abort '$rear_workflow'"
+confirm_prompt="Confirm the recreated DASD format or go back one step"
+confirm_choice=""
+# When USER_INPUT_DASD_FORMAT_MIGRATED_CONFIRMATION has any 'true' value be liberal in what you accept and
+# assume confirm_choices[0] 'Confirm recreated DASD format and continue' was actually meant:
+is_true "$USER_INPUT_DASD_FORMAT_MIGRATED_CONFIRMATION" && USER_INPUT_DASD_FORMAT_MIGRATED_CONFIRMATION="${confirm_choices[0]}"
+
+# Run the DASD format code (dasdformat.sh)
+# again and again until it succeeds or the user aborts
+# or the user confirms to continue with what is currently on the disks
+# (the user may have setup manually what he needs via the Relax-and-Recover shell):
+while true ; do
+ prompt="The DASD format had failed"
+ # After switching to recreating with DASD format script
+ # change choices[0] from "Run ..." to "Rerun ...":
+ choices[0]="Rerun DASD format script ($DASD_FORMAT_CODE)"
+ # Run DASD_FORMAT_CODE in a sub-shell because it sets 'set -e'
+ # so that it exits the running shell in case of an error
+ # but that exit must not exit this running bash here:
+ ( source $DASD_FORMAT_CODE )
+ # One must explicitly test whether or not $? is zero in a separated bash command
+ # because with bash 3.x and bash 4.x code like
+ # # ( set -e ; cat qqq ; echo "hello" ) && echo ok || echo failed
+ # cat: qqq: No such file or directory
+ # hello
+ # ok
+ # does not work as one may expect (cf. what "man bash" describes for 'set -e').
+ # There is a subtle behavioural difference between bash 3.x and bash 4.x
+ # when a script that has 'set -e' set gets sourced:
+ # With bash 3.x the 'set -e' inside the sourced script is effective:
+ # # echo 'set -e ; cat qqq ; echo hello' >script.sh
+ # # ( source script.sh ) && echo ok || echo failed
+ # cat: qqq: No such file or directory
+ # failed
+ # With bash 4.x the 'set -e' inside the sourced script gets noneffective:
+ # # echo 'set -e ; cat qqq ; echo hello' >script.sh
+ # # ( source script.sh ) && echo ok || echo failed
+ # cat: qqq: No such file or directory
+ # hello
+ # ok
+ # With bash 3.x and bash 4.x testing $? in a separated bash command
+ # keeps the 'set -e' inside the sourced script effective:
+ # # echo 'set -e ; cat qqq ; echo hello' >script.sh
+ # # ( source script.sh ) ; (( $? == 0 )) && echo ok || echo failed
+ # cat: qqq: No such file or directory
+ # failed
+ # See also https://github.com/rear/rear/pull/1573#issuecomment-344303590
+ if (( $? == 0 )) ; then
+ prompt="DASD format had been successful"
+ # When DASD_FORMAT_CODE succeeded and when not in migration mode
+ # break the outer while loop and continue the "rear recover" workflow
+ # which means continue with restoring the backup:
+ is_true "$MIGRATION_MODE" || break
+ # When DASD_FORMAT_CODE succeeded in migration mode
+ # let the user explicitly confirm the recreated (and usually migrated) format
+ # before continuing the "rear recover" workflow with restoring the backup.
+ # Show the recreated DASD format to the user on his terminal (and also in the log file):
+ LogPrint "Recreated DASD format:"
+ lsdasd_output
+ # Run an inner while loop with a user dialog so that the user can inspect the recreated DASD format
+ # and perhaps even manually fix the recreated DASD format if it is not what the user wants
+ # (e.g. by using the Relax-and-Recover shell and returning back to this user dialog):
+ while true ; do
+ confirm_choice="$( UserInput -I DASD_FORMAT_MIGRATED_CONFIRMATION -p "$confirm_prompt" -D "${confirm_choices[0]}" "${confirm_choices[@]}" )" && wilful_input="yes" || wilful_input="no"
+ case "$confirm_choice" in
+ (${confirm_choices[0]})
+ # Confirm recreated DASD format and continue:
+ is_true "$wilful_input" && LogPrint "User confirmed recreated DASD format" || LogPrint "Continuing with recreated DASD format by default"
+ # Break the outer while loop and continue with restoring the backup:
+ break 2
+ ;;
+ (${confirm_choices[1]})
+ # Go back one step to redo DASD format:
+ # Only break the inner while loop (i.e. this user dialog loop)
+ # and continue with the next user dialog below:
+ break
+ ;;
+ (${confirm_choices[2]})
+ # rear_shell runs 'bash' with the original STDIN STDOUT and STDERR when 'rear' was launched by the user:
+ rear_shell "" "$rear_shell_history"
+ ;;
+ (${confirm_choices[3]})
+ abort_dasd_format
+ Error "User did not confirm the recreated DASD format but aborted '$rear_workflow' in ${BASH_SOURCE[0]}"
+ ;;
+ esac
+ done
+ fi
+ # Run an inner while loop with a user dialog so that the user can fix things
+ # when DASD_FORMAT_CODE failed.
+ # Such a fix does not necessarily mean the user must change
+ # the dasdformat.sh script when DASD_FORMAT_CODE failed.
+ # The user might also fix things by only using the Relax-and-Recover shell and
+ # then confirm what is on the disks and continue with restoring the backup
+ # or abort this "rear recover" run to re-try from scratch.
+ while true ; do
+ choice="$( UserInput -I DASD_FORMAT_CODE_RUN -p "$prompt" -D "${choices[0]}" "${choices[@]}" )" && wilful_input="yes" || wilful_input="no"
+ case "$choice" in
+ (${choices[0]})
+ # Rerun or run (after switching to recreating with DASD format script) DASD format script:
+ is_true "$wilful_input" && LogPrint "User runs DASD format script" || LogPrint "Running DASD format script by default"
+ # Only break the inner while loop (i.e. the user dialog loop):
+ break
+ ;;
+ (${choices[1]})
+ # Run 'less' with the original STDIN STDOUT and STDERR when 'rear' was launched by the user:
+ less $RUNTIME_LOGFILE 0<&6 1>&7 2>&8
+ ;;
+ (${choices[2]})
+ # Run 'vi' with the original STDIN STDOUT and STDERR when 'rear' was launched by the user:
+ vi $DASD_FORMAT_CODE 0<&6 1>&7 2>&8
+ ;;
+ (${choices[3]})
+ LogPrint "This is the current list of DASDs:"
+ lsdasd_output
+ ;;
+ (${choices[4]})
+ # Run 'less' with the original STDIN STDOUT and STDERR when 'rear' was launched by the user:
+ less $original_disk_space_usage_file 0<&6 1>&7 2>&8
+ ;;
+ (${choices[5]})
+ # rear_shell runs 'bash' with the original STDIN STDOUT and STDERR when 'rear' was launched by the user:
+ rear_shell "" "$rear_shell_history"
+ ;;
+ (${choices[6]})
+ # Confirm what is on the disks and continue:
+ # Break the outer while loop and continue with restoring the backup:
+ break 2
+ ;;
+ (${choices[7]})
+ abort_dasd_format
+ Error "User chose to abort '$rear_workflow' in ${BASH_SOURCE[0]}"
+ ;;
+ esac
+ done
+# End of the outer while loop:
+done
+
+# Local functions must be 'unset' because bash does not support 'local function ...'
+# cf. https://unix.stackexchange.com/questions/104755/how-can-i-create-a-local-function-in-my-bashrc
+unset -f lsdasd_output
diff --git a/usr/share/rear/layout/prepare/default/010_prepare_files.sh b/usr/share/rear/layout/prepare/default/010_prepare_files.sh
index 7a980e63..4191be33 100644
--- a/usr/share/rear/layout/prepare/default/010_prepare_files.sh
+++ b/usr/share/rear/layout/prepare/default/010_prepare_files.sh
@@ -7,6 +7,8 @@ LAYOUT_CODE="$VAR_DIR/layout/diskrestore.sh"
LAYOUT_XFS_OPT_DIR="$VAR_DIR/layout/xfs"
LAYOUT_XFS_OPT_DIR_RESTORE="$LAYOUT_XFS_OPT_DIR/restore"
+DASD_FORMAT_CODE="$VAR_DIR/layout/dasdformat.sh"
+
FS_UUID_MAP="$VAR_DIR/layout/fs_uuid_mapping"
LUN_WWID_MAP="$VAR_DIR/layout/lun_wwid_mapping"
diff --git a/usr/share/rear/layout/prepare/default/250_compare_disks.sh b/usr/share/rear/layout/prepare/default/250_compare_disks.sh
index 260ab178..0931b183 100644
--- a/usr/share/rear/layout/prepare/default/250_compare_disks.sh
+++ b/usr/share/rear/layout/prepare/default/250_compare_disks.sh
@@ -58,7 +58,9 @@ local more_than_one_same_orig_size=''
while read disk dev size junk ; do
old_disks_and_sizes+=( "$dev $size" )
if IsInArray "$size" "${original_system_used_disk_sizes[@]}" ; then
- more_than_one_same_orig_size='true'
+ if ! has_mapping_hint "$dev" ; then
+ more_than_one_same_orig_size='true'
+ fi
else
original_system_used_disk_sizes+=( "$size" )
fi
@@ -143,8 +145,8 @@ fi
# No further disk comparisons are needed when MIGRATION_MODE is already set true above:
if ! is_true "$MIGRATION_MODE" ; then
# Compare original disks and their possible target disk one by one:
- while read disk dev size junk ; do
- dev=$( get_sysfs_name $dev )
+ while read disk devnode size junk ; do
+ dev=$( get_sysfs_name $devnode )
Log "Comparing $dev"
if test -e "/sys/block/$dev" ; then
Log "Device /sys/block/$dev exists"
@@ -156,6 +158,14 @@ if ! is_true "$MIGRATION_MODE" ; then
else
LogPrint "Device $dev has expected (same) size $size bytes (will be used for '$WORKFLOW')"
fi
+ elif test "$( get_mapping_hint $devnode )" == "$devnode" ; then
+ Debug "Found identical mapping hint ${devnode} -> ${devnode}"
+ if is_write_protected "/sys/block/$dev"; then
+ LogPrint "Device $dev is designated as write-protected (needs manual configuration)"
+ MIGRATION_MODE='true'
+ else
+ LogPrint "Device $dev found according to mapping hints (will be used for '$WORKFLOW')"
+ fi
else
LogPrint "Device $dev has size $newsize bytes but $size bytes is expected (needs manual configuration)"
MIGRATION_MODE='true'
diff --git a/usr/share/rear/layout/prepare/default/300_map_disks.sh b/usr/share/rear/layout/prepare/default/300_map_disks.sh
index 3353daea..d7b45a84 100644
--- a/usr/share/rear/layout/prepare/default/300_map_disks.sh
+++ b/usr/share/rear/layout/prepare/default/300_map_disks.sh
@@ -121,7 +121,14 @@ while read keyword orig_device orig_size junk ; do
# considered again during the subsequent "same size" tests:
excluded_target_device_names=()
# First, try to find if there is a current disk with same name and same size as the original:
- sysfs_device_name="$( get_sysfs_name "$orig_device" )"
+ # (possibly influenced by mapping hints if known)
+ if has_mapping_hint "$orig_device" ; then
+ candidate_target_device_name="$( get_mapping_hint "$orig_device" )"
+ Debug "Using mapping hint ${candidate_target_device_name} as candidate for $orig_device mapping"
+ else
+ candidate_target_device_name="$orig_device"
+ fi
+ sysfs_device_name="$( get_sysfs_name "$candidate_target_device_name" )"
current_device="/sys/block/$sysfs_device_name"
if test -e $current_device ; then
current_size=$( get_disk_size $sysfs_device_name )
@@ -129,23 +136,28 @@ while read keyword orig_device orig_size junk ; do
# its matching actual block device (e.g. /dev/sda) must be determined:
preferred_target_device_name="$( get_device_name $current_device )"
# Use the current one if it is of same size as the old one:
- if test "$orig_size" -eq "$current_size" ; then
+ if has_mapping_hint "$orig_device" || test "$orig_size" -eq "$current_size" ; then
# Ensure the target device is really a block device on the replacement hardware.
# Here the target device has same name as the original device which was a block device on the original hardware
# but it might perhaps happen that this device name is not a block device on the replacement hardware:
if test -b "$preferred_target_device_name" ; then
+ if has_mapping_hint "$orig_device" ; then
+ mapping_reason="determined by mapping hint"
+ else
+ mapping_reason="same name and same size $current_size"
+ fi
# Do not map if the current one is already used as target in the mapping file:
if is_mapping_target "$preferred_target_device_name" ; then
- DebugPrint "Cannot use $preferred_target_device_name (same name and same size) for recreating $orig_device ($preferred_target_device_name already exists as target in $MAPPING_FILE)"
+ DebugPrint "Cannot use $preferred_target_device_name ($mapping_reason) for recreating $orig_device ($preferred_target_device_name already exists as target in $MAPPING_FILE)"
excluded_target_device_names+=( "$preferred_target_device_name" )
else
# Ensure the determined target device is not write-protected:
if is_write_protected "$preferred_target_device_name" ; then
- DebugPrint "Cannot use $preferred_target_device_name (same name and same size) for recreating $orig_device ($preferred_target_device_name is write-protected)"
+ DebugPrint "Cannot use $preferred_target_device_name ($mapping_reason) for recreating $orig_device ($preferred_target_device_name is write-protected)"
excluded_target_device_names+=( "$preferred_target_device_name" )
else
add_mapping "$orig_device" "$preferred_target_device_name"
- LogPrint "Using $preferred_target_device_name (same name and same size $current_size) for recreating $orig_device"
+ LogPrint "Using $preferred_target_device_name ($mapping_reason) for recreating $orig_device"
# Continue with next original device because the current one is now mapped:
continue
fi
diff --git a/usr/share/rear/layout/save/GNU/Linux/200_partition_layout.sh b/usr/share/rear/layout/save/GNU/Linux/200_partition_layout.sh
index 52a4b142..a3e21c48 100644
--- a/usr/share/rear/layout/save/GNU/Linux/200_partition_layout.sh
+++ b/usr/share/rear/layout/save/GNU/Linux/200_partition_layout.sh
@@ -377,18 +377,27 @@ Log "Saving disks and their partitions"
if [[ $blockd == dasd* && "$ARCH" == "Linux-s390" ]] ; then
devname=$(get_device_name $disk)
+ dasdnum=$( lsdasd | awk "\$3 == \"$blockd\" { print \$1}" )
+ dasdstatus=$( lsdasd | awk "\$3 == \"$blockd\" { print \$2}" )
+ # ECKD or FBA
+ dasdtype=$( lsdasd | awk "\$3 == \"$blockd\" { print \$5}" )
+ if [ "$dasdtype" != ECKD ] && [ "$dasdtype" != FBA ]; then
+ LogPrint "Type $dasdtype of DASD $blockd unexpected: neither ECKD nor FBA"
+ fi
- echo "# active dasd bus and channel"
- echo "# bus-id <name device> type"
- echo "dasd_channel $( lsdasd|grep $blockd|awk '{ print $1 " " $2 " " $3 " " $4}' )"
-
- echo "# dasdfmt - disk layout is either cdl for the compatible disk layout (default) or ldl"
- echo "# example usage: dasdfmt -b 4096 -d cdl -y /dev/dasda"
- layout=$(dasdview -x /dev/$blockd|grep "^format"|awk '{print $7}')
- blocksize=$( dasdview -i /dev/$blockd|grep blocksize|awk '{print $6}' )
- echo "# dasdfmt $devname"
- echo "# dasdfmt -b <blocksize> -d <layout> -y <devname>"
- echo "dasdfmt -b $blocksize -d $layout -y $devname"
+ echo "# every DASD bus and channel"
+ echo "# Format: dasd_channel <bus-id> <device name>"
+ echo "dasd_channel $dasdnum $blockd"
+
+ # We need to print the dasd_channel line even for ignored devices,
+ # otherwise we could have naming gaps and naming would change when
+ # recreating layout.
+ # E.g. if dasda is ignored, and dasdb is not, we would create only dasdb
+ # during recreation, but it would be named dasda.
+ if [ "$dasdstatus" != active ]; then
+ Log "Ignoring $blockd: it is not active (Status is $dasdstatus)"
+ continue
+ fi
fi
#FIXME: exclude *rpmb (Replay Protected Memory Block) for nvme*, mmcblk* and uas
@@ -412,11 +421,38 @@ Log "Saving disks and their partitions"
# which can happen when /dev/sdX is an empty SD card slot without medium,
# see https://github.com/rear/rear/issues/2810
test $disktype || LogPrintError "No partition label type for 'disk $devname' (may cause 'rear recover' failure)"
-
- echo "# Disk $devname"
- echo "# Format: disk <devname> <size(bytes)> <partition label type>"
- echo "disk $devname $devsize $disktype"
-
+ if [ "$disktype" != "dasd" ]; then
+ echo "# Disk $devname"
+ echo "# Format: disk <devname> <size(bytes)> <partition label type>"
+ echo "disk $devname $devsize $disktype"
+ elif [[ $blockd == dasd* && "$ARCH" == "Linux-s390" ]] ; then
+ layout=$(dasdview -x $devname |grep "^format"|awk '{print $7}')
+ case "$layout" in
+ (NOT)
+ # NOT -> dasdview has printed "NOT formatted"
+ LogPrintError "Ignoring $blockd: it is not formatted"
+ continue
+ ;;
+ (LDL|CDL)
+ ;;
+ (*)
+ BugError "Invalid 'disk $devname' entry (unknown DASD layout $layout)"
+ ;;
+ esac
+ test $disktype || Error "No partition label type for DASD entry 'disk $devname'"
+ blocksize=$( get_block_size "$blockd" )
+ if ! test $blocksize ; then
+ # fallback - ugly method
+ blocksize=$( dasdview -i $devname |grep blocksize|awk '{print $6}' )
+ test $blocksize || Error "Unknown block size of DASD $devname"
+ fi
+ dasdcyls=$( get_dasd_cylinders "$blockd" )
+ echo "# Disk $devname"
+ echo "# Format: disk <devname> <size(bytes)> <partition label type> <logical block size> <DASD layout> <DASD type> <size(cylinders)>"
+ echo "disk $devname $devsize $disktype $blocksize $layout $dasdtype $dasdcyls"
+ else
+ Error "Invalid 'disk $devname' entry (DASD partition label on non-s390 arch $ARCH)"
+ fi
echo "# Partitions on $devname"
echo "# Format: part <device> <partition size(bytes)> <partition start(bytes)> <partition type|name> <flags> /dev/<partition>"
extract_partitions "$devname"
diff --git a/usr/share/rear/lib/layout-functions.sh b/usr/share/rear/lib/layout-functions.sh
index cb33ac28..6dd43313 100644
--- a/usr/share/rear/lib/layout-functions.sh
+++ b/usr/share/rear/lib/layout-functions.sh
@@ -87,6 +87,12 @@ abort_recreate() {
restore_original_file "$LAYOUT_FILE"
}
+abort_dasd_format() {
+ Log "Error detected during DASD formatting."
+ Log "Restoring saved original $DASD_FORMAT_FILE"
+ restore_original_file "$DASD_FORMAT_FILE"
+}
+
# Test and log if a component $1 (type $2) needs to be recreated.
create_component() {
local device="$1"
@@ -734,6 +740,46 @@ get_block_size() {
fi
}
+# Get the number of cylinders of a DASD.
+# The number of cylinders has the advantage of being fixed - size depends on formatting
+# and number of cylinders is valid even for unformatted DASDs, size is not.
+get_dasd_cylinders() {
+ local disk_name="${1##*/}" # /some/path/dasda -> dasda
+ local dasd_cyls
+
+ dasd_cyls=$(dasdview -i /dev/$disk_name | grep cylinders | cut -d ':' -f2 | awk '{print $4}')
+ ### Make sure we always return a number
+ echo $(( dasd_cyls ))
+}
+
+# Sometimes we know what the new device for the original device should be in a more reliable way
+# than by looking at disk sizes. THis information is called "mapping hints". Let's pass them
+# to the mapping code using the DISK_MAPPING_HINTS array. Each element of the array has the form
+# "/dev/source /dev/target" (space-separated).
+
+# Output the mapping hint for the original device.
+function get_mapping_hint () {
+ local device="$1"
+ local hint mapping_hint_source mapping_hint_target
+
+ for hint in "${DISK_MAPPING_HINTS[@]}"; do
+ mapping_hint_source=${hint%% *}
+ mapping_hint_target=${hint##* }
+ if [ "${device}" == "${mapping_hint_source}" ] ; then
+ echo "$mapping_hint_target"
+ return 0
+ fi
+ done
+ return 1
+}
+
+# Determine if there is a mapping hint for the original device.
+function has_mapping_hint () {
+ local device="$1"
+
+ get_mapping_hint "$device" > /dev/null
+}
+
# Get the UUID of a device.
# Device is something like /dev/sda1.
blkid_uuid_of_device() {

View File

@ -1 +1 @@
SHA512 (rear-2.7-clean.tar.gz) = 2fac6a20850b97501b35eddd08e53b53b0ce106f71be231a4874409a010e683f9042439f19db3e6cab142ed9762ee0faedb0807b7ea1d27fe6da3780a8df1a70
SHA512 (rear-2.9.tar.gz) = 9e6a8545f533deacb85839a351de9c0201a34197e9306fc8eebb51ee72e5a56c168e3d8a03e6c774f8f524f144583bd5f3c38fb6c11f91be166e6c8c39603716