From 0b7058f97dedddd89dfdfa9d7003d240d977b276 Mon Sep 17 00:00:00 2001 From: Michal Hecko Date: Sun, 20 Oct 2024 16:08:49 +0200 Subject: [PATCH] userspacegen(rhui): remove repofiles only if now owned by an RPM We copy files into the target userspace when setting up target repository content. If this file is named equally as some of the files installed by the target RHUI client installed during early phases of target userspace setup process, we would delete it in cleanup. Therefore, if we copy a repofile named /etc/yum.repos.d/X.repo and the target client also owns a file /etc/yum.repos.d/X.repo, we would remove it, making the container loose access to target content. This patch prevents us from blindly deleting files, keeping files that are owned by some RPM (usually that would be the target RHUI client). --- .../libraries/userspacegen.py | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py b/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py index d7698056f5..12736ab738 100644 --- a/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py +++ b/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py @@ -1120,6 +1120,27 @@ def _get_target_userspace(): return constants.TARGET_USERSPACE.format(get_target_major_version()) +def _remove_injected_repofiles_from_our_rhui_packages(target_userspace_ctx, rhui_setup_info): + target_userspace_path = _get_target_userspace() + for copy in rhui_setup_info.preinstall_tasks.files_to_copy_into_overlay: + dst_in_container = get_copy_location_from_copy_in_task(target_userspace_path, copy) + dst_in_container = dst_in_container.strip('/') + dst_in_host = os.path.join(target_userspace_path, dst_in_container) + + if os.path.isfile(dst_in_host) and dst_in_host.endswith('.repo'): + # The repofile might have been replaced by a new one provided by the RHUI client if names collide + # Performance: Do the query here and not earlier, because we would be running rpm needlessly + try: + path_with_root = '/' + dst_in_container + target_userspace_ctx.call(['rpm', '-q', '--whatprovides', path_with_root]) + api.current_logger().debug('Repofile {0} kept as it is owned by some RPM.'.format(dst_in_host)) + except CalledProcessError: + # rpm exists with 1 if the file is not owned by any RPM. We might be catching all kinds of other + # problems here, but still better than always removing repofiles. + api.current_logger().debug('Removing repofile - not owned by any RPM: {0}'.format(dst_in_host)) + os.remove(dst_in_host) + + def _create_target_userspace(context, indata, packages, files, target_repoids): """Create the target userspace.""" target_path = _get_target_userspace() @@ -1139,14 +1160,7 @@ def _create_target_userspace(context, indata, packages, files, target_repoids): ) setup_info = indata.rhui_info.target_client_setup_info if not setup_info.bootstrap_target_client: - target_userspace_path = _get_target_userspace() - for copy in setup_info.preinstall_tasks.files_to_copy_into_overlay: - dst_in_container = get_copy_location_from_copy_in_task(target_userspace_path, copy) - dst_in_container = dst_in_container.strip('/') - dst_in_host = os.path.join(target_userspace_path, dst_in_container) - if os.path.isfile(dst_in_host) and dst_in_host.endswith('.repo'): - api.current_logger().debug('Removing repofile: {0}'.format(dst_in_host)) - os.remove(dst_in_host) + _remove_injected_repofiles_from_our_rhui_packages(context, setup_info) # and do not forget to set the rhsm into the container mode again with mounting.NspawnActions(_get_target_userspace()) as target_context: