Skip to content

Commit 5d0ece8

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 929a1c0 commit 5d0ece8

File tree

1 file changed

+48
-16
lines changed
  • repos/system_upgrade/common/actors/targetuserspacecreator/libraries

1 file changed

+48
-16
lines changed

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

Lines changed: 48 additions & 16 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
@@ -312,9 +312,25 @@ def _get_files_owned_by_rpms(context, dirpath, pkgs=None):
312312
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.
315+
316+
If the recursive param is set to True, all files owned by a package in the
317+
directory tree starting at dirpath are returned. Otherwise, only the
318+
files within dirpath are checked.
315319
"""
320+
316321
files_owned_by_rpms = []
317-
for fname in os.listdir(context.full_path(dirpath)):
322+
323+
file_list = []
324+
searchdir = context.full_path(dirpath)
325+
if recursive:
326+
for root, _, files in os.walk(searchdir):
327+
for filename in files:
328+
relpath = os.path.relpath(os.path.join(root, filename), searchdir)
329+
file_list.append(relpath)
330+
else:
331+
file_list = os.listdir(searchdir)
332+
333+
for fname in file_list:
318334
try:
319335
result = context.call(['rpm', '-qf', os.path.join(dirpath, fname)])
320336
except CalledProcessError:
@@ -325,6 +341,7 @@ def _get_files_owned_by_rpms(context, dirpath, pkgs=None):
325341
continue
326342
api.current_logger().debug('Found the file owned by an rpm: {}.'.format(fname))
327343
files_owned_by_rpms.append(fname)
344+
328345
return files_owned_by_rpms
329346

330347

@@ -333,25 +350,40 @@ def _copy_certificates(context, target_userspace):
333350
Copy the needed cetificates into the container, but preserve original ones
334351
335352
Some certificates are already installed in the container and those are
336-
default certificates for the target OS. We know we should preserve at
337-
least certificates located at rpm-gpg directory. So preserve these for
338-
now at least.
353+
default certificates for the target OS, so we preserve these.
339354
"""
355+
340356
target_pki = os.path.join(target_userspace, 'etc', 'pki')
341357
backup_pki = os.path.join(target_userspace, 'etc', 'pki.backup')
342358

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
359+
with mounting.NspawnActions(base_dir=target_userspace) as target_context:
360+
files_owned_by_rpms = _get_files_owned_by_rpms(target_context, '/etc/pki', recursive=True)
361+
api.current_logger().debug('Files owned by rpms: {}'.format(' '.join(files_owned_by_rpms)))
362+
347363
run(['mv', target_pki, backup_pki])
348364
context.copytree_from('/etc/pki', target_pki)
349365

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)
366+
for filepath in files_owned_by_rpms:
367+
src_path = os.path.join(backup_pki, filepath)
368+
dst_path = os.path.join(target_pki, filepath)
369+
370+
# Resolve and skip any broken symlinks
371+
is_broken_symlink = False
372+
while os.path.islink(src_path):
373+
# The symlink points to a path relative to the target userspace so
374+
# we need to readjust it
375+
src_path = os.path.join(target_userspace, os.readlink(src_path)[1:])
376+
if not os.path.exists(src_path):
377+
is_broken_symlink = True
378+
api.current_logger().warn('File {} is a broken symlink!'.format(src_path))
379+
break
380+
381+
if is_broken_symlink:
382+
continue
383+
354384
run(['rm', '-rf', dst_path])
385+
parent_dir = os.path.dirname(dst_path)
386+
run(['mkdir', '-p', parent_dir])
355387
run(['cp', '-a', src_path, dst_path])
356388

357389

@@ -362,10 +394,10 @@ def _prep_repository_access(context, target_userspace):
362394
target_etc = os.path.join(target_userspace, 'etc')
363395
target_yum_repos_d = os.path.join(target_etc, 'yum.repos.d')
364396
backup_yum_repos_d = os.path.join(target_etc, 'yum.repos.d.backup')
397+
398+
_copy_certificates(context, target_userspace)
399+
365400
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)
369401
run(['rm', '-rf', os.path.join(target_etc, 'rhsm')])
370402
context.copytree_from('/etc/rhsm', os.path.join(target_etc, 'rhsm'))
371403
# NOTE: we cannot just remove the original target yum.repos.d dir

0 commit comments

Comments
 (0)