Skip to content

Commit

Permalink
pyanaconda: payload: split rsync command for /boot/efi to handle FAT …
Browse files Browse the repository at this point in the history
…filesystem limitations

The previous rsync command attempted to preserve attributes (permissions, ownership, symlinks)
that are not supported by FAT. This commit splits the rsync process for `/boot/efi` to avoid
these incompatible options and ensure proper handling of FAT-specific filesystems.

Resolves: rhbz#2329379
  • Loading branch information
KKoukiou committed Nov 29, 2024
1 parent d19089a commit 65df88d
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 20 deletions.
22 changes: 21 additions & 1 deletion pyanaconda/modules/payloads/payload/live_image/installation.py
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ def run(self):
"--exclude", "/run/",
"--exclude", "/boot/*rescue*",
"--exclude", "/boot/loader/",
"--exclude", "/boot/efi/loader/",
"--exclude", "/boot/efi/",
"--exclude", "/etc/machine-id",
"--exclude", "/etc/machine-info",
os.path.normpath(self._mount_point) + "/",
Expand All @@ -440,6 +440,26 @@ def run(self):
msg = "Failed to install image: {}".format(e)
raise PayloadInstallationError(msg) from None

if os.path.exists(os.path.join(self._mount_point, "boot/efi")):
# Handle /boot/efi separately due to FAT filesystem limitations
# FAT cannot support permissions, ownership, symlinks, hard links,
# xattrs, ACLs or modification times
args = [
"-rx",
"--stats", # show statistics at end of process
"--info=flist2,name,progress2", # show progress after each file
"--no-inc-recursive", # force calculating total work in advance
"--exclude", "/boot/efi/loader/",
os.path.normpath(self._mount_point) + "/boot/efi/",
os.path.join(self._sysroot, "boot/efi")
]

try:
execWithRedirect(cmd, args)
except (OSError, RuntimeError) as e:
msg = "Failed to install /boot/efi from image: {}".format(e)
raise PayloadInstallationError(msg) from None

def _parse_rsync_update(self, line):
"""Try to extract progress from rsync output.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,36 +91,55 @@ def _make_reader(self, rc):
return reader

@patch("pyanaconda.modules.payloads.payload.live_image.installation.os.sync")
@patch("pyanaconda.modules.payloads.payload.live_image.installation.execWithRedirect")
@patch("pyanaconda.modules.payloads.payload.live_image.installation.execReadlines")
def test_install_image_task(self, exec_readlines, os_sync):
def test_install_image_task(self, exec_readlines, exec_with_redirect, os_sync):
"""Test installation from an image task."""
exec_readlines.return_value = self._make_reader(0)
exec_with_redirect.return_value = 0

with tempfile.TemporaryDirectory() as mount_point:
task = InstallFromImageTask(
sysroot="/mnt/root",
mount_point=mount_point
)

task.run()

exec_readlines.assert_called_once_with("rsync", [
"-pogAXtlHrDx",
"--stats",
"--info=flist2,name,progress2",
"--no-inc-recursive",
"--exclude", "/dev/",
"--exclude", "/proc/",
"--exclude", "/tmp/*",
"--exclude", "/sys/",
"--exclude", "/run/",
"--exclude", "/boot/*rescue*",
"--exclude", "/boot/loader/",
"--exclude", "/boot/efi/loader/",
"--exclude", "/etc/machine-id",
"--exclude", "/etc/machine-info",
mount_point + "/",
"/mnt/root"
])
exec_readlines.assert_called_once_with("rsync", [
"-pogAXtlHrDx",
"--stats",
"--info=flist2,name,progress2",
"--no-inc-recursive",
"--exclude", "/dev/",
"--exclude", "/proc/",
"--exclude", "/tmp/*",
"--exclude", "/sys/",
"--exclude", "/run/",
"--exclude", "/boot/*rescue*",
"--exclude", "/boot/loader/",
"--exclude", "/boot/efi/",
"--exclude", "/etc/machine-id",
"--exclude", "/etc/machine-info",
mount_point + "/",
"/mnt/root"
])

exec_with_redirect.assert_not_called()

# Create /boot/efi directory in mount point.
os.makedirs(join_paths(mount_point, "boot/efi"))
task.run()

exec_with_redirect.assert_called_once_with("rsync", [
"-rx",
"--stats",
"--info=flist2,name,progress2",
"--no-inc-recursive",
"--exclude", "/boot/efi/loader/",
mount_point + "/boot/efi/",
"/mnt/root/boot/efi"
])

@patch("pyanaconda.modules.payloads.payload.live_image.installation.os.sync")
@patch("pyanaconda.modules.payloads.payload.live_image.installation.execReadlines")
Expand Down

0 comments on commit 65df88d

Please sign in to comment.