Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft: Skip broken symlink when copying /etc/pki #1112

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ def _get_all_rhui_pkgs():
return pkgs


def _get_files_owned_by_rpms(context, dirpath, pkgs=None):
def _get_files_owned_by_rpms(context, dirpath, pkgs=None, recursive=False):
"""
Return the list of file names inside dirpath owned by RPMs.

Expand All @@ -313,8 +313,20 @@ def _get_files_owned_by_rpms(context, dirpath, pkgs=None):
In case the pkgs param is None or empty, do not filter any specific rpms.
Otherwise return filenames that are owned by any pkg in the given list.
"""

files_owned_by_rpms = []
for fname in os.listdir(context.full_path(dirpath)):

file_list = []
searchdir = context.full_path(dirpath)
if recursive:
for root, _, files in os.walk(searchdir):
for filename in files:
relpath = os.path.relpath(os.path.join(root, filename), searchdir)
file_list.append(relpath)
else:
file_list = os.listdir(searchdir)

for fname in file_list:
try:
result = context.call(['rpm', '-qf', os.path.join(dirpath, fname)])
except CalledProcessError:
Expand All @@ -325,6 +337,7 @@ def _get_files_owned_by_rpms(context, dirpath, pkgs=None):
continue
api.current_logger().debug('Found the file owned by an rpm: {}.'.format(fname))
files_owned_by_rpms.append(fname)

return files_owned_by_rpms


Expand All @@ -337,21 +350,55 @@ def _copy_certificates(context, target_userspace):
least certificates located at rpm-gpg directory. So preserve these for
now at least.
"""

target_pki = os.path.join(target_userspace, 'etc', 'pki')
backup_pki = os.path.join(target_userspace, 'etc', 'pki.backup')

# FIXME(pstodulk): search for all files owned by RPMs inside the container
# before the mv, and all such files restore
# - this is requirement to not break IPU with RHUI when making the copy
# of certificates unconditional
with mounting.NspawnActions(base_dir=target_userspace) as target_context:
files_owned_by_rpms = _get_files_owned_by_rpms(target_context, '/etc/pki', recursive=True)
api.current_logger().debug('Files owned by rpms: {}'.format(' '.join(files_owned_by_rpms)))

run(['mv', target_pki, backup_pki])
context.copytree_from('/etc/pki', target_pki)
# We don't use context.copytree_from here as it fails on broken symlinks.
# Instead we copy the directory manually.
for root, _, files in os.walk('/etc/pki'):
for filename in files:
source_filepath = os.path.join(root, filename)
target_filepath = os.path.join(target_pki, filename)

# Skip broken symlinks
if not os.path.exists(source_filepath):
continue

# Ensure parent directory exists
parent_dir = os.path.dirname(target_filepath)
if not os.path.exists(parent_dir):
os.makedirs(parent_dir)

run(['cp', '-a', source_filepath, target_filepath])

for filepath in files_owned_by_rpms:
src_path = os.path.join(backup_pki, filepath)
dst_path = os.path.join(target_pki, filepath)

# Resolve and skip any broken symlinks
is_broken_symlink = False
while os.path.islink(src_path):
# The symlink points to a path relative to the target userspace so
# we need to readjust it
src_path = os.path.join(target_userspace, os.readlink(src_path)[1:])
if not os.path.exists(src_path):
# TODO(dkubek): What if the symlink points to a path in /etc/pki?
is_broken_symlink = True
api.current_logger().warn('File {} is a broken symlink!'.format(filepath))
break

if is_broken_symlink:
continue

# TODO(pstodulk): restore the files owned by rpms instead of the code below
for fname in os.listdir(os.path.join(backup_pki, 'rpm-gpg')):
src_path = os.path.join(backup_pki, 'rpm-gpg', fname)
dst_path = os.path.join(target_pki, 'rpm-gpg', fname)
run(['rm', '-rf', dst_path])
parent_dir = os.path.dirname(dst_path)
run(['mkdir', '-p', parent_dir])
run(['cp', '-a', src_path, dst_path])


Expand All @@ -362,10 +409,10 @@ def _prep_repository_access(context, target_userspace):
target_etc = os.path.join(target_userspace, 'etc')
target_yum_repos_d = os.path.join(target_etc, 'yum.repos.d')
backup_yum_repos_d = os.path.join(target_etc, 'yum.repos.d.backup')

_copy_certificates(context, target_userspace)

if not rhsm.skip_rhsm():
# TODO: make the _copy_certificates unconditional. keeping it conditional
# due to issues causing on RHUI
_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'))
# NOTE: we cannot just remove the original target yum.repos.d dir
Expand Down