From f2977392208ad6874802bed30af9616853c77c08 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Mon, 26 Sep 2022 12:54:57 +0200 Subject: [PATCH 71/75] Make CheckIfCfg consume IfCfg This actor used to scan the NetworkManager ifcfg files itself. Now it uses IfCfg messages, sharing the scanning code with CheckNetworkDeprecations. --- .../el8toel9/actors/checkifcfg/actor.py | 8 +- .../checkifcfg/libraries/checkifcfg_ifcfg.py | 40 +--- .../checkifcfg/tests/unit_test_ifcfg.py | 207 +++++++++--------- 3 files changed, 118 insertions(+), 137 deletions(-) diff --git a/repos/system_upgrade/el8toel9/actors/checkifcfg/actor.py b/repos/system_upgrade/el8toel9/actors/checkifcfg/actor.py index c6927d96..3ad0b5a0 100644 --- a/repos/system_upgrade/el8toel9/actors/checkifcfg/actor.py +++ b/repos/system_upgrade/el8toel9/actors/checkifcfg/actor.py @@ -1,7 +1,7 @@ from leapp.actors import Actor from leapp.libraries.actor import checkifcfg_ifcfg as ifcfg -from leapp.models import InstalledRPM, Report, RpmTransactionTasks -from leapp.tags import FactsPhaseTag, IPUWorkflowTag +from leapp.models import IfCfg, InstalledRPM, Report, RpmTransactionTasks +from leapp.tags import ChecksPhaseTag, IPUWorkflowTag class CheckIfcfg(Actor): @@ -16,9 +16,9 @@ class CheckIfcfg(Actor): """ name = "check_ifcfg" - consumes = (InstalledRPM,) + consumes = (IfCfg, InstalledRPM,) produces = (Report, RpmTransactionTasks,) - tags = (IPUWorkflowTag, FactsPhaseTag,) + tags = (ChecksPhaseTag, IPUWorkflowTag,) def process(self): ifcfg.process() diff --git a/repos/system_upgrade/el8toel9/actors/checkifcfg/libraries/checkifcfg_ifcfg.py b/repos/system_upgrade/el8toel9/actors/checkifcfg/libraries/checkifcfg_ifcfg.py index 9a9fe96b..5c843583 100644 --- a/repos/system_upgrade/el8toel9/actors/checkifcfg/libraries/checkifcfg_ifcfg.py +++ b/repos/system_upgrade/el8toel9/actors/checkifcfg/libraries/checkifcfg_ifcfg.py @@ -3,13 +3,12 @@ import os from leapp import reporting from leapp.libraries.common.rpms import has_package from leapp.libraries.stdlib import api -from leapp.models import InstalledRPM, RpmTransactionTasks +from leapp.models import IfCfg, InstalledRPM, RpmTransactionTasks FMT_LIST_SEPARATOR = '\n - ' def process(): - SYSCONFIG_DIR = '/etc/sysconfig/network-scripts' TRUE_VALUES = ['yes', 'true', '1'] TYPE_MAP = { 'ethernet': 'NetworkManager', @@ -31,48 +30,33 @@ def process(): # we don't do anything. return - for f in os.listdir(SYSCONFIG_DIR): + for ifcfg in api.consume(IfCfg): bad_type = False got_type = None nm_controlled = True - path = os.path.join(SYSCONFIG_DIR, f) - - if not os.path.isfile(path): - continue - - if f.startswith('rule-') or f.startswith('rule6-'): + if ifcfg.rules is not None or ifcfg.rules6 is not None: if 'NetworkManager-dispatcher-routing-rules' not in rpms_to_install: rpms_to_install.append('NetworkManager-dispatcher-routing-rules') continue - if not f.startswith('ifcfg-'): + if os.path.basename(ifcfg.filename) == 'ifcfg-lo': continue - if f == 'ifcfg-lo': - continue - - for line in open(path).readlines(): - try: - (key, value) = line.split('#')[0].strip().split('=') - except ValueError: - # We're not interested in lines that are not - # simple assignments. Play it safe. - continue - - if key in ('TYPE', 'DEVICETYPE'): + for prop in ifcfg.properties: + if prop.name in ('TYPE', 'DEVICETYPE'): if got_type is None: - got_type = value.lower() - elif got_type != value.lower(): + got_type = prop.value.lower() + elif got_type != prop.value.lower(): bad_type = True - if key == 'BONDING_MASTER': + if prop.name == 'BONDING_MASTER': if got_type is None: got_type = 'bond' elif got_type != 'bond': bad_type = True - if key == 'NM_CONTROLLED' and value.lower() not in TRUE_VALUES: + if prop.name == 'NM_CONTROLLED' and prop.value.lower() not in TRUE_VALUES: nm_controlled = False if got_type in TYPE_MAP: @@ -84,9 +68,9 @@ def process(): # Don't bother reporting the file for NM_CONTROLLED=no # if its type is not supportable with NetworkManager anyway if bad_type is True: - bad_type_files.append(path) + bad_type_files.append(ifcfg.filename) elif nm_controlled is False: - not_controlled_files.append(path) + not_controlled_files.append(ifcfg.filename) if bad_type_files: title = 'Network configuration for unsupported device types detected' diff --git a/repos/system_upgrade/el8toel9/actors/checkifcfg/tests/unit_test_ifcfg.py b/repos/system_upgrade/el8toel9/actors/checkifcfg/tests/unit_test_ifcfg.py index 10e2adb1..ddabedf2 100644 --- a/repos/system_upgrade/el8toel9/actors/checkifcfg/tests/unit_test_ifcfg.py +++ b/repos/system_upgrade/el8toel9/actors/checkifcfg/tests/unit_test_ifcfg.py @@ -1,147 +1,144 @@ -import mock -import six +from leapp.models import IfCfg, IfCfgProperty, InstalledRPM, RPM, RpmTransactionTasks +from leapp.reporting import Report +from leapp.utils.report import is_inhibitor -from leapp import reporting -from leapp.libraries.actor import checkifcfg_ifcfg as ifcfg -from leapp.libraries.common.testutils import create_report_mocked, CurrentActorMocked, produce_mocked -from leapp.libraries.stdlib import api -from leapp.models import InstalledRPM, RPM, RpmTransactionTasks - -RH_PACKAGER = 'Red Hat, Inc. ' +RH_PACKAGER = "Red Hat, Inc. " NETWORK_SCRIPTS_RPM = RPM( - name='network-scripts', version='10.00.17', release='1.el8', epoch='', - packager=RH_PACKAGER, arch='x86_64', - pgpsig='RSA/SHA256, Fri 04 Feb 2022 03:32:47 PM CET, Key ID 199e2f91fd431d51' + name="network-scripts", + version="10.00.17", + release="1.el8", + epoch="", + packager=RH_PACKAGER, + arch="x86_64", + pgpsig="RSA/SHA256, Fri 04 Feb 2022 03:32:47 PM CET, Key ID 199e2f91fd431d51", ) NETWORK_MANAGER_RPM = RPM( - name='NetworkManager', version='1.36.0', release='0.8.el8', epoch='1', - packager=RH_PACKAGER, arch='x86_64', - pgpsig='RSA/SHA256, Mon 14 Feb 2022 08:45:37 PM CET, Key ID 199e2f91fd431d51' -) - -INITSCRIPTS_INSTALLED = CurrentActorMocked( - msgs=[InstalledRPM(items=[NETWORK_SCRIPTS_RPM])] + name="NetworkManager", + version="1.36.0", + release="0.8.el8", + epoch="1", + packager=RH_PACKAGER, + arch="x86_64", + pgpsig="RSA/SHA256, Mon 14 Feb 2022 08:45:37 PM CET, Key ID 199e2f91fd431d51", ) -INITSCRIPTS_AND_NM_INSTALLED = CurrentActorMocked( - msgs=[InstalledRPM(items=[NETWORK_SCRIPTS_RPM, NETWORK_MANAGER_RPM])] -) +INITSCRIPTS_INSTALLED = InstalledRPM(items=[ + NETWORK_SCRIPTS_RPM +]) +INITSCRIPTS_AND_NM_INSTALLED = InstalledRPM(items=[ + NETWORK_SCRIPTS_RPM, + NETWORK_MANAGER_RPM +]) -def test_ifcfg_none(monkeypatch): +def test_ifcfg_none(current_actor_context): """ No report and don't install anything if there are no ifcfg files. """ - monkeypatch.setattr(ifcfg.api, 'current_actor', INITSCRIPTS_AND_NM_INSTALLED) - monkeypatch.setattr(ifcfg.api, "produce", produce_mocked()) - monkeypatch.setattr(ifcfg.os, 'listdir', lambda dummy: ('hello', 'world',)) - monkeypatch.setattr(ifcfg.os.path, 'isfile', lambda dummy: True) - monkeypatch.setattr(reporting, "create_report", create_report_mocked()) - ifcfg.process() - assert not reporting.create_report.called - assert not api.produce.called + current_actor_context.feed(INITSCRIPTS_AND_NM_INSTALLED) + current_actor_context.run() + assert not current_actor_context.consume(Report) + assert not current_actor_context.consume(RpmTransactionTasks) -def test_ifcfg_rule_file(monkeypatch): +def test_ifcfg_rule_file(current_actor_context): """ Install NetworkManager-dispatcher-routing-rules package if there's a file with ip rules. """ - monkeypatch.setattr(ifcfg.api, 'current_actor', INITSCRIPTS_AND_NM_INSTALLED) - monkeypatch.setattr(ifcfg.api, "produce", produce_mocked()) - monkeypatch.setattr(ifcfg.os, 'listdir', lambda dummy: ('hello', 'world', 'rule-eth0',)) - monkeypatch.setattr(ifcfg.os.path, 'isfile', lambda dummy: True) - monkeypatch.setattr(reporting, "create_report", create_report_mocked()) - ifcfg.process() - assert not reporting.create_report.called - assert api.produce.called - assert isinstance(api.produce.model_instances[0], RpmTransactionTasks) - assert api.produce.model_instances[0].to_install == ['NetworkManager-dispatcher-routing-rules'] + current_actor_context.feed(IfCfg( + filename="/NM/ifcfg-eth0", + properties=(IfCfgProperty(name="TYPE", value="Ethernet"),), + rules=("foo bar baz",), + )) + current_actor_context.feed(INITSCRIPTS_AND_NM_INSTALLED) + current_actor_context.run() + assert not current_actor_context.consume(Report) + assert len(current_actor_context.consume(RpmTransactionTasks)) == 1 + rpm_transaction = current_actor_context.consume(RpmTransactionTasks)[0] + assert rpm_transaction.to_install == ["NetworkManager-dispatcher-routing-rules"] -def test_ifcfg_good_type(monkeypatch): +def test_ifcfg_good_type(current_actor_context): """ No report if there's an ifcfg file that would work with NetworkManager. Make sure NetworkManager itself is installed though. """ - mock_config = mock.mock_open(read_data="TYPE=Ethernet") - with mock.patch("builtins.open" if six.PY3 else "__builtin__.open", mock_config) as mock_ifcfg: - monkeypatch.setattr(ifcfg.api, 'current_actor', INITSCRIPTS_AND_NM_INSTALLED) - monkeypatch.setattr(ifcfg.api, "produce", produce_mocked()) - monkeypatch.setattr(ifcfg.os, 'listdir', lambda dummy: ('hello', 'world', 'ifcfg-eth0', 'ifcfg-lo',)) - monkeypatch.setattr(ifcfg.os.path, 'isfile', lambda dummy: True) - monkeypatch.setattr(reporting, "create_report", create_report_mocked()) - ifcfg.process() - mock_ifcfg.assert_called_once_with('/etc/sysconfig/network-scripts/ifcfg-eth0') - assert not reporting.create_report.called - assert api.produce.called - assert isinstance(api.produce.model_instances[0], RpmTransactionTasks) - assert api.produce.model_instances[0].to_install == ['NetworkManager'] - - -def test_ifcfg_not_controlled(monkeypatch): + current_actor_context.feed(IfCfg( + filename="/NM/ifcfg-lo", + properties=() + )) + current_actor_context.feed(IfCfg( + filename="/NM/ifcfg-eth0", + properties=(IfCfgProperty(name="TYPE", value="Ethernet"),) + )) + current_actor_context.feed(INITSCRIPTS_AND_NM_INSTALLED) + current_actor_context.run() + assert not current_actor_context.consume(Report) + assert len(current_actor_context.consume(RpmTransactionTasks)) == 1 + rpm_transaction = current_actor_context.consume(RpmTransactionTasks)[0] + assert rpm_transaction.to_install == ["NetworkManager"] + + +def test_ifcfg_not_controlled(current_actor_context): """ Report if there's a NM_CONTROLLED=no file. """ - mock_config = mock.mock_open(read_data="TYPE=Ethernet\nNM_CONTROLLED=no") - with mock.patch("builtins.open" if six.PY3 else "__builtin__.open", mock_config) as mock_ifcfg: - monkeypatch.setattr(ifcfg.api, 'current_actor', INITSCRIPTS_INSTALLED) - monkeypatch.setattr(ifcfg.api, "produce", produce_mocked()) - monkeypatch.setattr(ifcfg.os, 'listdir', lambda dummy: ('hello', 'world', 'ifcfg-eth0',)) - monkeypatch.setattr(ifcfg.os.path, 'isfile', lambda dummy: True) - monkeypatch.setattr(reporting, "create_report", create_report_mocked()) - ifcfg.process() - mock_ifcfg.assert_called_once_with('/etc/sysconfig/network-scripts/ifcfg-eth0') - assert reporting.create_report.called - assert 'disabled NetworkManager' in reporting.create_report.report_fields['title'] - assert api.produce.called - - -def test_ifcfg_unknown_type(monkeypatch): + current_actor_context.feed(IfCfg( + filename="/NM/ifcfg-eth0", + properties=( + IfCfgProperty(name="TYPE", value="Ethernet"), + IfCfgProperty(name="NM_CONTROLLED", value="no"), + ) + )) + current_actor_context.feed(INITSCRIPTS_INSTALLED) + current_actor_context.run() + assert len(current_actor_context.consume(Report)) == 1 + report_fields = current_actor_context.consume(Report)[0].report + assert is_inhibitor(report_fields) + assert "disabled NetworkManager" in report_fields['title'] + + +def test_ifcfg_unknown_type(current_actor_context): """ Report if there's configuration for a type we don't recognize. """ - mock_config = mock.mock_open(read_data="TYPE=AvianCarrier") - with mock.patch("builtins.open" if six.PY3 else "__builtin__.open", mock_config) as mock_ifcfg: - monkeypatch.setattr(ifcfg.api, 'current_actor', INITSCRIPTS_AND_NM_INSTALLED) - monkeypatch.setattr(ifcfg.api, "produce", produce_mocked()) - monkeypatch.setattr(ifcfg.os, 'listdir', lambda dummy: ('hello', 'world', 'ifcfg-pigeon0',)) - monkeypatch.setattr(ifcfg.os.path, 'isfile', lambda dummy: True) - monkeypatch.setattr(reporting, "create_report", create_report_mocked()) - ifcfg.process() - mock_ifcfg.assert_called_once_with('/etc/sysconfig/network-scripts/ifcfg-pigeon0') - assert reporting.create_report.called - assert 'unsupported device types' in reporting.create_report.report_fields['title'] - assert not api.produce.called - - -def test_ifcfg_install_subpackage(monkeypatch): + current_actor_context.feed(IfCfg( + filename="/NM/ifcfg-pigeon0", + properties=(IfCfgProperty(name="TYPE", value="AvianCarrier"),) + )) + current_actor_context.feed(INITSCRIPTS_AND_NM_INSTALLED) + current_actor_context.run() + assert len(current_actor_context.consume(Report)) == 1 + report_fields = current_actor_context.consume(Report)[0].report + assert is_inhibitor(report_fields) + assert "unsupported device types" in report_fields['title'] + + +def test_ifcfg_install_subpackage(current_actor_context): """ Install NetworkManager-team if there's a team connection and also ensure NetworkManager-config-server is installed if NetworkManager was not there. """ - mock_config = mock.mock_open(read_data="TYPE=Team") - with mock.patch("builtins.open" if six.PY3 else "__builtin__.open", mock_config) as mock_ifcfg: - monkeypatch.setattr(ifcfg.api, 'current_actor', INITSCRIPTS_INSTALLED) - monkeypatch.setattr(ifcfg.api, "produce", produce_mocked()) - monkeypatch.setattr(ifcfg.os, 'listdir', lambda dummy: ('ifcfg-team0',)) - monkeypatch.setattr(ifcfg.os.path, 'isfile', lambda dummy: True) - monkeypatch.setattr(reporting, "create_report", create_report_mocked()) - ifcfg.process() - mock_ifcfg.assert_called_once_with('/etc/sysconfig/network-scripts/ifcfg-team0') - assert not reporting.create_report.called - assert api.produce.called - assert isinstance(api.produce.model_instances[0], RpmTransactionTasks) - assert api.produce.model_instances[0].to_install == [ - 'NetworkManager-team', - 'NetworkManager-config-server' - ] + current_actor_context.feed(IfCfg( + filename="/NM/ifcfg-team0", + properties=(IfCfgProperty(name="TYPE", value="Team"),) + )) + current_actor_context.feed(INITSCRIPTS_INSTALLED) + current_actor_context.run() + assert not current_actor_context.consume(Report) + assert len(current_actor_context.consume(RpmTransactionTasks)) == 1 + rpm_transaction = current_actor_context.consume(RpmTransactionTasks)[0] + assert rpm_transaction.to_install == [ + "NetworkManager-team", + "NetworkManager-config-server", + ] -- 2.39.0