Skip to content

Commit 51155a0

Browse files
committed
Add support for upgrade with custom https repos
Currently, upgrades with custom repositories hosted on private https servers are not functional. The reason is that the server certificates are unavailable in the upgrade container as they are not copied from the source system; therefore, the upgrade fails when trying to access the custom repository. This change fixes the issue by copying all files from the ``/etc/pki`` folder of the source system, while respecting any new files installed by packages into the container. If a conflict arises a file installed by a package into a container is preferred. Any broken symlinks are skipped and ignored.
1 parent 1b471b2 commit 51155a0

File tree

1 file changed

+47
-13
lines changed
  • repos/system_upgrade/common/actors/targetuserspacecreator/libraries

1 file changed

+47
-13
lines changed

repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ def _get_all_rhui_pkgs():
303303
return pkgs
304304

305305

306-
def _get_files_owned_by_rpms(context, dirpath, pkgs=None):
306+
def _get_files_owned_by_rpms(context, dirpath, pkgs=None, recursive=False):
307307
"""
308308
Return the list of file names inside dirpath owned by RPMs.
309309
@@ -313,8 +313,20 @@ def _get_files_owned_by_rpms(context, dirpath, pkgs=None):
313313
In case the pkgs param is None or empty, do not filter any specific rpms.
314314
Otherwise return filenames that are owned by any pkg in the given list.
315315
"""
316+
316317
files_owned_by_rpms = []
317-
for fname in os.listdir(context.full_path(dirpath)):
318+
319+
file_list = []
320+
searchdir = context.full_path(dirpath)
321+
if recursive:
322+
for root, _, files in os.walk(searchdir):
323+
for filename in files:
324+
relpath = os.path.relpath(os.path.join(root, filename), searchdir)
325+
file_list.append(relpath)
326+
else:
327+
file_list = os.listdir(searchdir)
328+
329+
for fname in file_list:
318330
try:
319331
result = context.call(['rpm', '-qf', os.path.join(dirpath, fname)])
320332
except CalledProcessError:
@@ -325,6 +337,7 @@ def _get_files_owned_by_rpms(context, dirpath, pkgs=None):
325337
continue
326338
api.current_logger().debug('Found the file owned by an rpm: {}.'.format(fname))
327339
files_owned_by_rpms.append(fname)
340+
328341
return files_owned_by_rpms
329342

330343

@@ -337,21 +350,42 @@ def _copy_certificates(context, target_userspace):
337350
least certificates located at rpm-gpg directory. So preserve these for
338351
now at least.
339352
"""
353+
340354
target_pki = os.path.join(target_userspace, 'etc', 'pki')
341355
backup_pki = os.path.join(target_userspace, 'etc', 'pki.backup')
342356

343-
# FIXME(pstodulk): search for all files owned by RPMs inside the container
344-
# before the mv, and all such files restore
345-
# - this is requirement to not break IPU with RHUI when making the copy
346-
# of certificates unconditional
357+
with mounting.NspawnActions(base_dir=target_userspace) as target_context:
358+
files_owned_by_rpms = _get_files_owned_by_rpms(target_context, '/etc/pki', recursive=True)
359+
api.current_logger().debug('Files owned by rpms: {}'.format(' '.join(files_owned_by_rpms)))
360+
361+
# TODO(dkubek): Delete dangling symlinks so copytree_from does not raise an
362+
# error
363+
347364
run(['mv', target_pki, backup_pki])
348365
context.copytree_from('/etc/pki', target_pki)
349366

350-
# TODO(pstodulk): restore the files owned by rpms instead of the code below
351-
for fname in os.listdir(os.path.join(backup_pki, 'rpm-gpg')):
352-
src_path = os.path.join(backup_pki, 'rpm-gpg', fname)
353-
dst_path = os.path.join(target_pki, 'rpm-gpg', fname)
367+
for filepath in files_owned_by_rpms:
368+
src_path = os.path.join(backup_pki, filepath)
369+
dst_path = os.path.join(target_pki, filepath)
370+
371+
# Resolve and skip any broken symlinks
372+
is_broken_symlink = False
373+
while os.path.islink(src_path):
374+
# The symlink points to a path relative to the target userspace so
375+
# we need to readjust it
376+
src_path = os.path.join(target_userspace, os.readlink(src_path)[1:])
377+
if not os.path.exists(src_path):
378+
# TODO(dkubek): What if the symlink points to a path in /etc/pki?
379+
is_broken_symlink = True
380+
api.current_logger().warn('File {} is a broken symlink!'.format(filepath))
381+
break
382+
383+
if is_broken_symlink:
384+
continue
385+
354386
run(['rm', '-rf', dst_path])
387+
parent_dir = os.path.dirname(dst_path)
388+
run(['mkdir', '-p', parent_dir])
355389
run(['cp', '-a', src_path, dst_path])
356390

357391

@@ -362,10 +396,10 @@ def _prep_repository_access(context, target_userspace):
362396
target_etc = os.path.join(target_userspace, 'etc')
363397
target_yum_repos_d = os.path.join(target_etc, 'yum.repos.d')
364398
backup_yum_repos_d = os.path.join(target_etc, 'yum.repos.d.backup')
399+
400+
_copy_certificates(context, target_userspace)
401+
365402
if not rhsm.skip_rhsm():
366-
# TODO: make the _copy_certificates unconditional. keeping it conditional
367-
# due to issues causing on RHUI
368-
_copy_certificates(context, target_userspace)
369403
run(['rm', '-rf', os.path.join(target_etc, 'rhsm')])
370404
context.copytree_from('/etc/rhsm', os.path.join(target_etc, 'rhsm'))
371405
# NOTE: we cannot just remove the original target yum.repos.d dir

0 commit comments

Comments
 (0)