From 1995970d274a147039e05e64423fcd60b5a8590f Mon Sep 17 00:00:00 2001 From: Yuriy Kohut Date: Thu, 9 Apr 2026 19:11:32 +0300 Subject: [PATCH] Update Vendors patch with the ability to use a pre-built rootfs instead of bootstrapping the target userspace container via 'dnf install --installroot'. The package version 0.24.0-1.elevate.6 --- SOURCES/leapp-repository-0.24.0-elevate.patch | 131 ++++++++++++++++-- SPECS/leapp-repository.spec | 5 +- 2 files changed, 125 insertions(+), 11 deletions(-) diff --git a/SOURCES/leapp-repository-0.24.0-elevate.patch b/SOURCES/leapp-repository-0.24.0-elevate.patch index b3cd69e..ab2a8ee 100644 --- a/SOURCES/leapp-repository-0.24.0-elevate.patch +++ b/SOURCES/leapp-repository-0.24.0-elevate.patch @@ -7204,10 +7204,18 @@ index 59b12c87..85d4a09e 100644 def process(self): self.produce(systemfacts.get_sysctls_status()) diff --git a/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py b/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py -index 66843645..a021c628 100644 +index 66843645..9f07cb0f 100644 --- a/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py +++ b/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py -@@ -165,9 +165,10 @@ def _import_gpg_keys(context, install_root_dir, target_major_version): +@@ -69,6 +69,7 @@ PROD_CERTS_FOLDER = 'prod-certs' + PERSISTENT_PACKAGE_CACHE_DIR = '/var/lib/leapp/persistent_package_cache' + DEDICATED_LEAPP_PART_URL = 'https://access.redhat.com/solutions/7011704' + FMT_LIST_SEPARATOR = '\n - ' ++CUSTOM_ROOTFS_PATH = '/etc/leapp/files/rootfs' + + + def _check_deprecated_rhsm_skip(): +@@ -165,9 +166,10 @@ def _import_gpg_keys(context, install_root_dir, target_major_version): # installation of initial packages try: # Import also any other keys provided by the customer in the same directory @@ -7221,7 +7229,7 @@ index 66843645..a021c628 100644 except CalledProcessError as exc: raise StopActorExecutionError( message=( -@@ -178,26 +179,7 @@ def _import_gpg_keys(context, install_root_dir, target_major_version): +@@ -178,26 +180,7 @@ def _import_gpg_keys(context, install_root_dir, target_major_version): ) @@ -7248,15 +7256,118 @@ index 66843645..a021c628 100644 NO_SPACE_STR = 'more space needed on the' # Disk Requirements: -@@ -670,6 +652,7 @@ def _prep_repository_access(context, target_userspace): - run(["chroot", target_userspace, "/bin/bash", "-c", "su - -c update-ca-trust"]) +@@ -234,6 +217,27 @@ def prepare_target_userspace(context, userspace_dir, enabled_repos, packages): + run(['rm', '-rf', userspace_dir]) + _create_target_userspace_directories(userspace_dir) + ++ # Check if a custom rootfs tarball is available to use instead of dnf --installroot ++ rootfs_tarball = _get_custom_rootfs_tarball() ++ if rootfs_tarball: ++ api.current_logger().info( ++ 'Using custom rootfs tarball for target userspace: %s', rootfs_tarball ++ ) ++ try: ++ run(['tar', '-xf', rootfs_tarball, '-C', userspace_dir]) ++ except CalledProcessError as exc: ++ raise StopActorExecutionError( ++ message='Failed to extract custom rootfs tarball: {}'.format(rootfs_tarball), ++ details={'details': str(exc), 'stderr': exc.stderr} ++ ) ++ return ++ ++ # Check if a container image is configured to use as rootfs ++ container_image = get_env('LEAPP_DEVEL_ROOTFS_CONTAINER_IMAGE', None) ++ if container_image: ++ _pull_and_extract_container_rootfs(userspace_dir, container_image) ++ return ++ + target_major_version = get_target_major_version() + install_root_dir = '/el{}target'.format(target_major_version) + with mounting.BindMount(source=userspace_dir, target=os.path.join(context.base_dir, install_root_dir.lstrip('/'))): +@@ -667,9 +671,10 @@ def _prep_repository_access(context, target_userspace): + # NOTE(dkubek): context.call(['update-ca-trust']) seems to not be working. + # I am not really sure why. The changes to files are not + # being written to disk. +- run(["chroot", target_userspace, "/bin/bash", "-c", "su - -c update-ca-trust"]) ++ run(["chroot", target_userspace, "/usr/bin/update-ca-trust"]) if not rhsm.skip_rhsm(): + _copy_certificates(context, target_userspace) run(['rm', '-rf', os.path.join(target_etc, 'rhsm')]) context.copytree_from('/etc/rhsm', os.path.join(target_etc, 'rhsm')) -@@ -863,9 +846,8 @@ def _inhibit_if_no_base_repos(distro_repoids): +@@ -791,6 +796,70 @@ def _create_target_userspace_directories(target_userspace): + ) + + ++def _get_custom_rootfs_tarball(): ++ """Find a custom rootfs tarball in CUSTOM_ROOTFS_PATH if it exists.""" ++ if not os.path.isdir(CUSTOM_ROOTFS_PATH): ++ return None ++ for fname in sorted(os.listdir(CUSTOM_ROOTFS_PATH)): ++ if fname.endswith(('.tar.xz', '.tar.gz', '.tar.bz2', '.tar')): ++ return os.path.join(CUSTOM_ROOTFS_PATH, fname) ++ return None ++ ++ ++def _pull_and_extract_container_rootfs(userspace_dir, image_url): ++ """ ++ Pull a container image and extract its filesystem into userspace_dir. ++ ++ Uses podman to pull the image, create a temporary container, and ++ export its flat filesystem directly into the target userspace. ++ ++ The platform can be specified via the LEAPP_DEVEL_ROOTFS_CONTAINER_PLATFORM ++ environment variable (e.g. ``linux/amd64/v2``). ++ """ ++ platform = get_env('LEAPP_DEVEL_ROOTFS_CONTAINER_PLATFORM', None) ++ platform_opts = ['--platform', platform] if platform else [] ++ ++ api.current_logger().info( ++ 'Pulling container image for target userspace: %s (platform=%s)', ++ image_url, platform or 'default' ++ ) ++ try: ++ run(['podman', 'pull'] + platform_opts + [image_url]) ++ except CalledProcessError as exc: ++ raise StopActorExecutionError( ++ message='Failed to pull container image: {}'.format(image_url), ++ details={'details': str(exc), 'stderr': exc.stderr} ++ ) ++ ++ container_name = 'leapp-userspace-rootfs-tmp' ++ try: ++ # Remove stale container from a previous failed run, if any ++ try: ++ run(['podman', 'rm', '-f', container_name]) ++ except CalledProcessError: ++ pass ++ # Create a temporary container (do not start it) ++ run(['podman', 'create'] + platform_opts + ['--name', container_name, image_url, '/bin/bash']) ++ # Export and extract the flat filesystem into the userspace directory ++ run([ ++ 'bash', '-c', ++ 'podman export {} | tar -xf - -C {}'.format(container_name, userspace_dir) ++ ]) ++ except CalledProcessError as exc: ++ raise StopActorExecutionError( ++ message='Failed to export container rootfs from image: {}'.format(image_url), ++ details={'details': str(exc), 'stderr': exc.stderr} ++ ) ++ finally: ++ # Clean up the temporary container ++ try: ++ run(['podman', 'rm', '-f', container_name]) ++ except CalledProcessError: ++ api.current_logger().warning( ++ 'Failed to remove temporary container: %s', container_name ++ ) ++ ++ + def _inhibit_on_duplicate_repos(repofiles): + """ + Inhibit the upgrade if any repoid is defined multiple times. +@@ -863,9 +932,8 @@ def _inhibit_if_no_base_repos(distro_repoids): no_baseos = all("baseos" not in ri for ri in distro_repoids) no_appstream = all("appstream" not in ri for ri in distro_repoids) if no_baseos or no_appstream: @@ -7268,7 +7379,7 @@ index 66843645..a021c628 100644 reporting.Summary( 'This can happen when a repository ID was entered incorrectly either while using the --enablerepo' ' option of leapp or in a third party actor that produces a CustomTargetRepositoryMessage.' -@@ -873,17 +855,6 @@ def _inhibit_if_no_base_repos(distro_repoids): +@@ -873,17 +941,6 @@ def _inhibit_if_no_base_repos(distro_repoids): reporting.Groups([reporting.Groups.REPOSITORY]), reporting.Severity(reporting.Severity.HIGH), reporting.Groups([reporting.Groups.INHIBITOR]), @@ -7286,7 +7397,7 @@ index 66843645..a021c628 100644 reporting.ExternalLink( url='https://access.redhat.com/solutions/5392811', title='RHEL 7 to RHEL 8 LEAPP Upgrade Failing When Using Red Hat Satellite' -@@ -893,8 +864,22 @@ def _inhibit_if_no_base_repos(distro_repoids): +@@ -893,8 +950,22 @@ def _inhibit_if_no_base_repos(distro_repoids): # https://red.ht/preparing-for-upgrade-to-rhel9 # https://red.ht/preparing-for-upgrade-to-rhel10 url='https://red.ht/preparing-for-upgrade-to-rhel{}'.format(target_major_version), @@ -7311,7 +7422,7 @@ index 66843645..a021c628 100644 raise StopActorExecution() -@@ -991,8 +976,8 @@ def _get_distro_available_repoids(context, indata): +@@ -991,8 +1062,8 @@ def _get_distro_available_repoids(context, indata): provider has itw own rpm). On other: Repositories are provided in specific repofiles (e.g. centos.repo and centos-addons.repo on CS) @@ -7322,7 +7433,7 @@ index 66843645..a021c628 100644 Conversions: Only custom repos - no distro repoids (all distros) :return: A set of repoids provided by distribution -@@ -1004,10 +989,14 @@ def _get_distro_available_repoids(context, indata): +@@ -1004,10 +1075,14 @@ def _get_distro_available_repoids(context, indata): is_source_cs8 = ( get_source_distro_id() == "centos" and get_source_major_version() == '8' ) diff --git a/SPECS/leapp-repository.spec b/SPECS/leapp-repository.spec index a5de956..b4968c2 100644 --- a/SPECS/leapp-repository.spec +++ b/SPECS/leapp-repository.spec @@ -53,7 +53,7 @@ py2_byte_compile "%1" "%2"} Epoch: 1 Name: leapp-repository Version: 0.24.0 -Release: 1%{?dist}.elevate.5 +Release: 1%{?dist}.elevate.6 Summary: Repositories for leapp License: ASL 2.0 @@ -350,6 +350,9 @@ fi %changelog +* Tue Apr 14 2026 Yuriy Kohut - 0.24.0-1.elevate.6 +- Enable upgrades to x86_64_v2: implement the ability to use a pre-built rootfs instead of bootstrapping the target userspace container via 'dnf install --installroot'. + * Tue Apr 07 2026 Yuriy Kohut - 0.24.0-1.elevate.5 - ELevate vendors support for upstream 0.24.0-1 version (87c192519e8764f59516cca563816f062428a533) - New upgrade paths: 8.10→9.9, 9.9→10.3 with prod certs -- 2.47.3