Skip to content

Commit

Permalink
Handle zypper operation on a different root
Browse files Browse the repository at this point in the history
If zypper is instructed to operate on a different root with the "--root"
argument the credentials are also expected to be found in this seperate
root tree. WE need to accomodate this redirection.
  • Loading branch information
rjschwei committed May 8, 2024
1 parent 79f93f9 commit 8cfa058
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 36 deletions.
25 changes: 22 additions & 3 deletions lib/cloudregister/registerutils.py
Expand Up @@ -159,10 +159,13 @@ def clear_rmt_as_scc_proxy_flag():
def credentials_files_are_equal(repo_credentials):
"""Compare the base credentials files the the repo header and make
sure they have the same values."""
credentials_location = '/etc/zypp/credentials.d/'

if not repo_credentials or not isinstance(repo_credentials, str):
return False


base_credentials_location = '/etc/zypp/credentials.d/'
target_root = get_zypper_target_root()
credentials_location = target_root + base_credentials_location
credentials_base = os.path.join(credentials_location, 'SCCcredentials')
credentials_header = os.path.join(credentials_location, repo_credentials)
ref_user, ref_pass = get_credentials(credentials_base)
Expand Down Expand Up @@ -522,7 +525,8 @@ def get_credentials_file(update_server, service_name=None):
after the system is properly registered.
"""
credentials_file = ''
credentials_loc = '/etc/zypp/credentials.d/'
target_root = get_zypper_target_root()
credentials_loc = target_root + '/etc/zypp/credentials.d/'
credential_names = [
'*' + update_server.get_FQDN().replace('.', '_'),
'SCC*'
Expand Down Expand Up @@ -874,6 +878,21 @@ def get_zypper_pid_cache():
return zypper_state_file.read()


# ----------------------------------------------------------------------------
def get_zypper_target_root():
"""Return the target root if zypper has the --root argument to
specify a target directory in which to operate.
"""
zypper_cmd = get_zypper_command()
target_root = ''
for root_arg in ('-R', '--root'):
if zypper_cmd and root_arg in zypper_cmd:
target_root = zypper_cmd.split(root_arg)[-1].split()[0].strip()
break

return target_root


# ----------------------------------------------------------------------------
def has_ipv6_access(smt):
"""IPv6 access is possible if we have an SMT server that has an IPv6
Expand Down
75 changes: 42 additions & 33 deletions usr/sbin/registercloudguest
Expand Up @@ -52,10 +52,50 @@ from requests.auth import HTTPBasicAuth
urllib3.disable_warnings()
registration_returncode = 0

# ----------------------------------------------------------------------------
def get_register_cmd():
"""Determine which command we need to use to register the system"""

register_cmd = '/usr/sbin/SUSEConnect'
# Figure out if we are on RO transactional-update system
p = subprocess.Popen(
['findmnt', '--noheadings', '--json', '/'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
res = p.communicate()
# If we get an error from findmnt move forward on a best effort basis
if p.returncode:
logging.warning('Unable to find filesystem information for "/"')
else:
fsinfo = json.loads(res[0])
fsdata = fsinfo.get('filesystems')
if fsdata:
fsoptions = fsdata[0].get('options')
# If we are on a RO system we need to use the
# transactional-update command
if 'ro' in fsoptions.split(','):
cmd_name = 'transactional-update'
for path in ['/sbin/','/usr/sbin/']:
exec_path = path + cmd_name
if os.path.exists(exec_path):
register_cmd = exec_path
break
else:
err_msg = 'transactional-update command not found.'
err_msg += 'But is required on a RO filesystem for '
err_msg += 'registration'
logging.error(err_msg)
print(err_msg, file=sys.stderr)
sys.exit(1)

return register_cmd

# ----------------------------------------------------------------------------
def register_modules(extensions, products, registered=[], failed=[]):
"""Register modules obeying dependencies"""
global registration_returncode
register_cmd = get_register_cmd()
for extension in extensions:
# If the extension is recommended it gets installed with the
# baseproduct registration. No need to run another registration
Expand All @@ -72,6 +112,7 @@ def register_modules(extensions, products, registered=[], failed=[]):
registered.append(triplet)
cmd = [
register_cmd,
sub_cmd,
'--url',
'https://%s' % registration_target.get_FQDN(),
'--product',
Expand Down Expand Up @@ -438,39 +479,7 @@ if instance_data:
if not utils.is_registration_supported(cfg):
sys.exit(0)

# Check SUSE/SLES registration command to be present
register_cmd = '/usr/sbin/SUSEConnect'
# For transactional systems we need to do a few extra things
p = subprocess.Popen(
['findmnt', '--noheadings', '--json', '/'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
res = p.communicate()
# If we get an error from findmnt move forward on a best effort basis
if p.returncode:
logging.warning('Unable to find filesystem information for "/"')
else:
fsinfo = json.loads(res[0])
fsdata = fsinfo.get('filesystems')
if fsdata:
fsoptions = fsdata[0].get('options')
# If we are on a RO system we need to use the
# transactional-update command
if 'ro' in fsoptions.split(','):
cmd_name = 'transactional-update'
for path in ['/sbin/','/usr/sbin/']:
exec_path = path + cmd_name
if os.path.exists(exec_path):
register_cmd = exec_path
break
else:
err_msg = 'transactional-update command not found.'
err_msg += 'But is required on a RO filesystem for '
err_msg += 'registration'
logging.error(err_msg)
print(err_msg, file=sys.stderr)
sys.exit(1)
register_cmd = get_register_cmd()
if not (os.path.exists(register_cmd) and os.access(register_cmd, os.X_OK)):
err_msg = 'No registration executable found'
logging.error(err_msg)
Expand Down

0 comments on commit 8cfa058

Please sign in to comment.