Skip to content

Commit 0d7ddbc

Browse files
committed
WIP non-sca-inhibit
1 parent d183370 commit 0d7ddbc

File tree

5 files changed

+138
-17
lines changed

5 files changed

+138
-17
lines changed

repos/system_upgrade/common/libraries/rhsm.py

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,15 @@
2020

2121
SCA_TEXT = "Content Access Mode is set to Simple Content Access"
2222

23+
_DEFAULT_EXCEPTION_HINT = (
24+
'Please ensure you have a valid RHEL subscription and your network is up.'
25+
' If you are using proxy for Red Hat subscription-manager, please make sure'
26+
' it is specified inside the /etc/rhsm/rhsm.conf file.'
27+
' Or use the --no-rhsm option when running leapp, if you do not want to'
28+
' use subscription-manager for the in-place upgrade and you want to'
29+
' deliver all target repositories by yourself or using RHUI on public cloud.'
30+
)
31+
2332

2433
def _rhsm_retry(max_attempts, sleep=None):
2534
"""
@@ -72,20 +81,12 @@ def _handle_rhsm_exceptions(hint=None):
7281
}
7382
)
7483
except CalledProcessError as e:
75-
_def_hint = (
76-
'Please ensure you have a valid RHEL subscription and your network is up.'
77-
' If you are using proxy for Red Hat subscription-manager, please make sure'
78-
' it is specified inside the /etc/rhsm/rhsm.conf file.'
79-
' Or use the --no-rhsm option when running leapp, if you do not want to'
80-
' use subscription-manager for the in-place upgrade and you want to'
81-
' deliver all target repositories by yourself or using RHUI on public cloud.'
82-
)
8384
raise StopActorExecutionError(
8485
message='A subscription-manager command failed to execute',
8586
details={
8687
'details': str(e),
8788
'stderr': e.stderr,
88-
'hint': hint or _def_hint,
89+
'hint': hint or _DEFAULT_EXCEPTION_HINT,
8990
'link': 'https://access.redhat.com/solutions/6138372'
9091
}
9192
)
@@ -383,6 +384,42 @@ def switch_certificate(context, rhsm_info, cert_path):
383384
context.copy_to(cert_path, os.path.join(path, os.path.basename(cert_path)))
384385

385386

387+
def is_rhsm_registered(context):
388+
"""
389+
Check whether the system is registered with Red Hat Subscription Manager
390+
391+
Note that this doesn't differentiate between SCA and SKU access
392+
393+
:param context: An instance of a mounting.IsolatedActions class
394+
:type context: mounting.IsolatedActions class
395+
:return: True if it is registered, false otherwise
396+
:rtype: bool
397+
"""
398+
try:
399+
result = context.call(['subscription-manager', 'identity', '--no-progress-messages'], checked=False)
400+
except OSError as e:
401+
api.current_logger().error('Failed to execute subscription-manager executable')
402+
raise StopActorExecutionError(
403+
message='Unable to execute subscription-manager executable: {}'.format(str(e)),
404+
details={
405+
'hint': 'Please ensure subscription-manager is installed and executable.'
406+
}
407+
)
408+
409+
if result['exit_code'] == 0:
410+
return True
411+
if result['exit_code'] == 1:
412+
return False
413+
raise StopActorExecutionError(
414+
message='A subscription-manager command failed to execute',
415+
details={
416+
'details': f'Command \'subscription-manager identity\' exited with exit code: {result["exit_code"]}',
417+
'hint': _DEFAULT_EXCEPTION_HINT,
418+
'link': 'https://access.redhat.com/solutions/6138372' # TODO check link
419+
}
420+
)
421+
422+
386423
@with_rhsm
387424
def scan_rhsm_info(context):
388425
"""
@@ -402,4 +439,5 @@ def scan_rhsm_info(context):
402439
info.release = get_release(context)
403440
info.existing_product_certificates.extend(get_existing_product_certificates(context))
404441
info.sca_detected = is_manifest_sca(context)
442+
info.is_registered = is_rhsm_registered(context)
405443
return info

repos/system_upgrade/common/libraries/tests/test_rhsm.py

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
CMD_RHSM_STATUS = ('subscription-manager', 'status')
2020
CMD_RHSM_RELEASE = ('subscription-manager', 'release')
2121
CMD_RHSM_LIST_ENABLED_REPOS = ('subscription-manager', 'repos', '--list-enabled')
22+
CMD_RHSM_IDENTITY = ('subscription-manager', 'identity', '--no-progress-messages')
2223

2324
RHSM_STATUS_OUTPUT_NOSCA = '''
2425
+-------------------------------------------+
@@ -79,11 +80,13 @@ def call(self, cmd, *args, **dummy_kwargs):
7980
tuple(cmd), # Cast to tuple, as list is not hashable
8081
self.call_return)
8182

82-
def add_mocked_command_call_with_stdout(self, cmd, stdout):
83+
def add_mocked_command_call(self, cmd, stdout=None, stderr=None, exit_code=0):
8384
# We cast `cmd` from list to tuple, as a list cannot be hashed
8485
self.mocked_command_call_outputs[tuple(cmd)] = {
8586
'stdout': stdout,
86-
'stderr': None}
87+
'stderr': stderr,
88+
'exit_code': exit_code
89+
}
8790

8891
def full_path(self, path):
8992
return path
@@ -203,7 +206,7 @@ def test_inhibit_on_duplicate_repos_no_dups(monkeypatch):
203206

204207
def test_sku_listing(monkeypatch, actor_mocked, context_mocked):
205208
"""Tests whether the rhsm library can obtain used SKUs correctly."""
206-
context_mocked.add_mocked_command_call_with_stdout(CMD_RHSM_LIST_CONSUMED, 'SKU: 598339696910')
209+
context_mocked.add_mocked_command_call(CMD_RHSM_LIST_CONSUMED, 'SKU: 598339696910')
207210

208211
attached_skus = rhsm.get_attached_skus(context_mocked)
209212

@@ -234,7 +237,7 @@ def test_scanrhsminfo_with_skip_rhsm(monkeypatch, context_mocked):
234237

235238
def test_get_release(monkeypatch, actor_mocked, context_mocked):
236239
"""Tests whether the library correctly retrieves release from RHSM."""
237-
context_mocked.add_mocked_command_call_with_stdout(CMD_RHSM_RELEASE, 'Release: 7.9')
240+
context_mocked.add_mocked_command_call(CMD_RHSM_RELEASE, 'Release: 7.9')
238241

239242
release = rhsm.get_release(context_mocked)
240243

@@ -245,7 +248,7 @@ def test_get_release(monkeypatch, actor_mocked, context_mocked):
245248
def test_get_release_with_release_not_set(monkeypatch, actor_mocked, context_mocked):
246249
"""Tests whether the library does not retrieve release information when the release is not set."""
247250
# Test whether no release is detected correctly too
248-
context_mocked.add_mocked_command_call_with_stdout(CMD_RHSM_RELEASE, 'Release not set')
251+
context_mocked.add_mocked_command_call(CMD_RHSM_RELEASE, 'Release not set')
249252

250253
release = rhsm.get_release(context_mocked)
251254

@@ -255,15 +258,15 @@ def test_get_release_with_release_not_set(monkeypatch, actor_mocked, context_moc
255258

256259
def test_is_manifest_sca_on_nonsca_system(monkeypatch, actor_mocked, context_mocked):
257260
"""Tests whether the library obtains the SCA information correctly from a non-SCA system."""
258-
context_mocked.add_mocked_command_call_with_stdout(CMD_RHSM_STATUS, RHSM_STATUS_OUTPUT_NOSCA)
261+
context_mocked.add_mocked_command_call(CMD_RHSM_STATUS, RHSM_STATUS_OUTPUT_NOSCA)
259262

260263
is_sca = rhsm.is_manifest_sca(context_mocked)
261264
assert not is_sca, 'SCA was detected on a non-SCA system.'
262265

263266

264267
def test_is_manifest_sca_on_sca_system(monkeypatch, actor_mocked, context_mocked):
265268
"""Tests whether the library obtains the SCA information from SCA system correctly."""
266-
context_mocked.add_mocked_command_call_with_stdout(CMD_RHSM_STATUS, RHSM_STATUS_OUTPUT_SCA)
269+
context_mocked.add_mocked_command_call(CMD_RHSM_STATUS, RHSM_STATUS_OUTPUT_SCA)
267270

268271
is_sca = rhsm.is_manifest_sca(context_mocked)
269272
assert is_sca, 'Failed to detected SCA on a SCA system.'
@@ -286,7 +289,7 @@ def test_get_enabled_repo_ids(monkeypatch, actor_mocked, context_mocked):
286289
rhsm_output_fragment += '\n'
287290
rhsm_list_enabled_output += rhsm_output_fragment
288291

289-
context_mocked.add_mocked_command_call_with_stdout(CMD_RHSM_LIST_ENABLED_REPOS, rhsm_list_enabled_output)
292+
context_mocked.add_mocked_command_call(CMD_RHSM_LIST_ENABLED_REPOS, rhsm_list_enabled_output)
290293

291294
enabled_repo_ids = rhsm.get_enabled_repo_ids(context_mocked)
292295

@@ -385,3 +388,24 @@ def mocked_listdir(path):
385388
assert len(existing_product_certificates) == 1, fail_description
386389
fail_description = 'Library failed to identify certificate from mocked outputs.'
387390
assert existing_product_certificates[0] == '/etc/pki/product-default/cert', fail_description
391+
392+
393+
def test_is_registered_on_registered_system(context_mocked):
394+
"""Tests whether the library obtains the registraton status correctly from a registered system."""
395+
context_mocked.add_mocked_command_call(CMD_RHSM_IDENTITY, exit_code=0)
396+
assert rhsm.is_rhsm_registered(context_mocked)
397+
398+
399+
def test_is_registered_on_unregistered_system(context_mocked):
400+
"""Tests whether the library obtains the registraton status correctly from an unregistered system."""
401+
context_mocked.add_mocked_command_call(CMD_RHSM_IDENTITY, exit_code=1)
402+
assert not rhsm.is_rhsm_registered(context_mocked)
403+
404+
405+
def test_is_registered_error(context_mocked):
406+
"""Tests whether the is_rhsm_registered function correctly handles command errors"""
407+
context_mocked.add_mocked_command_call(CMD_RHSM_IDENTITY, exit_code=2)
408+
with pytest.raises(StopActorExecutionError) as err:
409+
rhsm.is_rhsm_registered(context_mocked)
410+
411+
assert 'A subscription-manager command failed to execute' in str(err)

repos/system_upgrade/common/models/rhsminfo.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,10 @@ class RHSMInfo(Model):
2020
""" Product certificates that are currently installed on the system. """
2121
sca_detected = fields.Boolean(default=False)
2222
""" Info about whether SCA manifest was used or not. """
23+
is_registered = fields.Boolean(default=False)
24+
"""
25+
Whether the system is registered through subscription-manager
26+
27+
Note that this doesn't differentiate between a registration to an SKU or
28+
SCA organization.
29+
"""
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from leapp.actors import Actor
2+
from leapp.libraries.actor import nonscarhsm
3+
from leapp.models import Report, RHSMInfo
4+
from leapp.tags import ChecksPhaseTag, IPUWorkflowTag
5+
6+
7+
class CheckRedHatSubscriptionManagerSCA(Actor):
8+
"""
9+
Ensure that a registered system is in SCA (Simple Content Access)
10+
11+
This actor verifies that in case the system is subscribed to the Red Hat
12+
Subscription Manager it is registered to an SCA organization. The actor
13+
will inhibit the upgrade if the system is registered to an entitlements
14+
organization. This actor will run regardless of whether the --skip-rhsm
15+
command line parameter is specified.
16+
"""
17+
18+
name = 'check_rhsmsca'
19+
consumes = (RHSMInfo,)
20+
produces = (Report,)
21+
tags = (IPUWorkflowTag, ChecksPhaseTag)
22+
23+
def process(self):
24+
nonscarhsm.process()
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
from leapp import reporting
2+
from leapp.libraries.stdlib import api
3+
from leapp.models import RHSMInfo
4+
from leapp.reporting import create_report
5+
6+
7+
def process():
8+
for info in api.consume(RHSMInfo):
9+
if info.is_registered and not info.sca_detected:
10+
# TODO summary, remediation hint, external link
11+
create_report([
12+
reporting.Title('The system is not registered to an SCA organization'),
13+
reporting.Summary(
14+
'Leapp detected that the system is registered to an SKU organization.'
15+
' On RHEL 10, Red Hat Subscription Manager cannot be registered to an'
16+
' SKU organization.'
17+
),
18+
reporting.Severity(reporting.Severity.HIGH),
19+
reporting.Groups([reporting.Groups.SANITY]),
20+
reporting.Groups([reporting.Groups.INHIBITOR]),
21+
reporting.Remediation(
22+
hint='Register your system with the subscription-manager tool and attach'
23+
' proper SKUs to be able to proceed the upgrade or use the --no-rhsm'
24+
' leapp option if you want to provide target repositories by yourself.'),
25+
reporting.RelatedResource('package', 'subscription-manager'),
26+
reporting.ExternalLink(url='',
27+
title=''),
28+
])

0 commit comments

Comments
 (0)