Skip to content

Commit

Permalink
CheckNetworkDeprecations9to10: Check for ifcfg artifacts
Browse files Browse the repository at this point in the history
Ifcfg support is going away in RHEL 10. Try to be a little more helpful,
either suggesting how to migrate automatically, deliver bad news about
migrating legacy policy routing rules manually, or report garbage
after what looks like bad migration (better sad than sorry).

JIRA: https://issues.redhat.com/browse/RHEL-58972
  • Loading branch information
lkundrak committed Jan 21, 2025
1 parent e7b4b0d commit d30e6d7
Show file tree
Hide file tree
Showing 2 changed files with 173 additions and 3 deletions.
104 changes: 102 additions & 2 deletions repos/system_upgrade/el9toel10/actors/networkdeprecations/actor.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import os

from leapp import reporting
from leapp.actors import Actor
from leapp.models import NetworkManagerConfig, Report
from leapp.models import IfCfg, NetworkManagerConfig, Report
from leapp.tags import ChecksPhaseTag, IPUWorkflowTag


Expand All @@ -15,7 +17,7 @@ class CheckNetworkDeprecations9to10(Actor):
"""

name = "network_deprecations"
consumes = (NetworkManagerConfig,)
consumes = (NetworkManagerConfig, IfCfg,)
produces = (Report,)
tags = (ChecksPhaseTag, IPUWorkflowTag,)

Expand All @@ -39,8 +41,106 @@ def report_dhclient():
reporting.RelatedResource('package', 'NetworkManager'),
])

@staticmethod
def report_ifcfg_rules(conn):
reporting.create_report([
reporting.Title('Legacy network configuration with policy routing rules found'),
reporting.Summary('Network configuration files in "ifcfg" format is present accompanied'
' by legacy routing rules. In Red Hat Enterprise Linux 10, support'
' for these files is no longer enabled and the configuration will be'
' ignored. Legacy routing rules are not supported by NetworkManager'
' natively and therefore can not be migrated automatically.'),
reporting.Remediation(hint='Replace the routing rules with equivalent'
' "ipv4.routing-rules" or "ipv6.routing-rules" properties,'
' then migrate the connection with "nmcli conn migrate"'),
reporting.ExternalLink(
url='https://access.redhat.com/solutions/7083803',
title='How to migrate the connection from ifcfg to NetworkManager keyfile plugin?'),
reporting.ExternalLink(
url='https://networkmanager.dev/docs/api/latest/nmcli.html',
title='nmcli(1) manual, describes "connection migrate" sub-command.'),
reporting.ExternalLink(
url='https://networkmanager.dev/docs/api/latest/nm-settings-ifcfg-rh.html',
title='nm-settings-ifcfg-rh(5), description of the "ifcfg" format'),
reporting.ExternalLink(
url='https://networkmanager.dev/docs/api/latest/nm-settings-keyfile.html',
title='nm-settings-keyfile(5), description of the "keyfile" format'),
reporting.Severity(reporting.Severity.HIGH),
reporting.Groups([reporting.Groups.NETWORK, reporting.Groups.SERVICES]),
reporting.Groups([reporting.Groups.INHIBITOR]),
reporting.RelatedResource('package', 'NetworkManager'),
reporting.RelatedResource('package', 'NetworkManager-dispatcher-routing-rules'),
] + [reporting.RelatedResource('file', file) for file in conn.values()])
pass

@staticmethod
def report_ifcfg_leftover(conn):
reporting.create_report([
reporting.Title('Unused legacy network configuration found'),
reporting.Summary('Files that used to accompany legacy network configuration in "ifcfg"'
' format are present, even though the configuration itself is not'
' longer there. These files will be ignored.'),
reporting.Remediation(hint='Verify that the files were not left behind by incomplete'
' migration, fix up configuration if necessary, and remove'
' them.'),
reporting.ExternalLink(
url='https://access.redhat.com/solutions/7083803',
title='How to migrate the connection from ifcfg to NetworkManager keyfile plugin?'),
reporting.Severity(reporting.Severity.HIGH),
reporting.Groups([reporting.Groups.NETWORK, reporting.Groups.SERVICES]),
reporting.Groups([reporting.Groups.INHIBITOR]),
] + [reporting.RelatedResource('file', file) for file in conn.values()])

@staticmethod
def report_ifcfg(conn):
reporting.create_report([
reporting.Title('Legacy network configuration found'),
reporting.Summary('Network configuration file in legacy "ifcfg" format is present.'
' In Red Hat Enterprise Linux 10, support for these files is no longer'
' enabled and the configuration will be ignored.'),
reporting.Remediation(
hint='Convert the configuration into NetworkManager native "keyfile" format.',
commands=[['nmcli', 'connection', 'migrate', conn['ifcfg']]]),
reporting.ExternalLink(
url='https://access.redhat.com/solutions/7083803',
title='How to migrate the connection from ifcfg to NetworkManager keyfile plugin?'),
reporting.ExternalLink(
url='https://networkmanager.dev/docs/api/latest/nmcli.html',
title='nmcli(1) manual, describes "connection migrate" sub-command.'),
reporting.ExternalLink(
url='https://networkmanager.dev/docs/api/latest/nm-settings-ifcfg-rh.html',
title='nm-settings-ifcfg-rh(5), description of the "ifcfg" format'),
reporting.ExternalLink(
url='https://networkmanager.dev/docs/api/latest/nm-settings-keyfile.html',
title='nm-settings-keyfile(5), description of the "keyfile" format'),
reporting.Severity(reporting.Severity.HIGH),
reporting.Groups([reporting.Groups.NETWORK, reporting.Groups.SERVICES]),
reporting.Groups([reporting.Groups.INHIBITOR]),
reporting.RelatedResource('package', 'NetworkManager'),
] + [reporting.RelatedResource('file', file) for file in conn.values()])

def process(self):
for nm_config in self.consume(NetworkManagerConfig):
self.log.info('Consuming dhcp={}'.format(nm_config.dhcp))
if nm_config.dhcp == 'dhclient':
CheckNetworkDeprecations9to10.report_dhclient()

conns = {}

for ifcfg in self.consume(IfCfg):
self.log.info('Consuming ifcfg={}'.format(ifcfg.filename))
rule_basename = os.path.basename(ifcfg.filename)
(kind, name) = rule_basename.split('-', 1)
if name not in conns:
conns[name] = {}
conns[name][kind] = ifcfg.filename

for name in conns:
conn = conns[name]
if 'ifcfg' in conn:
if 'rule' in conn or 'rule6' in conn:
CheckNetworkDeprecations9to10.report_ifcfg_rules(conn)
else:
CheckNetworkDeprecations9to10.report_ifcfg(conn)
else:
CheckNetworkDeprecations9to10.report_ifcfg_leftover(conn)
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from leapp.models import NetworkManagerConfig, Report
import pytest

from leapp.models import IfCfg, NetworkManagerConfig, Report
from leapp.utils.report import is_inhibitor

def test_dhcp_dhclient(current_actor_context):
current_actor_context.feed(NetworkManagerConfig(dhcp='dhclient'))
Expand All @@ -23,3 +25,71 @@ def test_dhcp_default(current_actor_context):
current_actor_context.run()
reports = list(current_actor_context.consume(Report))
assert not reports

def test_ifcfg(current_actor_context):
"""
Report when a file ready for migration is present.
"""

current_actor_context.feed(IfCfg(filename='/NM/ifcfg-eth-dev'))
current_actor_context.run()
reports = current_actor_context.consume(Report)
assert len(reports) == 1
report_fields = reports[0].report
assert is_inhibitor(report_fields)
assert report_fields['title'] == 'Legacy network configuration found'
resources = report_fields['detail']['related_resources']
assert len(resources) == 2
assert resources[0]['scheme'] == 'package'
assert resources[0]['title'] == 'NetworkManager'
assert resources[1]['scheme'] == 'file'
assert resources[1]['title'] == '/NM/ifcfg-eth-dev'

@pytest.mark.parametrize('files',
[('/NM/rule-lost',),
('/NM/route6-eth-dev', '/NM/rule-eth-dev')])
def test_leftovers(current_actor_context, files):
"""
Report when what appears like artifacts from unsuccessful migration are present.
"""

for file in files:
current_actor_context.feed(IfCfg(filename=file))
current_actor_context.run()
reports = current_actor_context.consume(Report)
assert len(reports) == 1
report_fields = reports[0].report
assert is_inhibitor(report_fields)
assert report_fields['title'] == 'Unused legacy network configuration found'
resources = report_fields['detail']['related_resources']
assert len(resources) == len(files)
for i in range(len(files)):
assert resources[i]['scheme'] == 'file'
assert resources[i]['title'] == files[i]

@pytest.mark.parametrize('files',
[('/NM/ifcfg-old', '/NM/rule-old'),
('/NM/ifcfg-old', '/NM/rule6-old'),
('/NM/ifcfg-old', '/NM/rule6-old', '/NM/rule-old')])
def test_rules(current_actor_context, files):
"""
Report when configuration that requires manual migration is present.
"""

for file in files:
current_actor_context.feed(IfCfg(filename=file))
current_actor_context.run()
reports = current_actor_context.consume(Report)
assert len(reports) == 1
report_fields = reports[0].report
assert is_inhibitor(report_fields)
assert report_fields['title'] == 'Legacy network configuration with policy routing rules found'
resources = report_fields['detail']['related_resources']
assert len(resources) == 2 + len(files)
assert resources[0]['scheme'] == 'package'
assert resources[0]['title'] == 'NetworkManager'
assert resources[1]['scheme'] == 'package'
assert resources[1]['title'] == 'NetworkManager-dispatcher-routing-rules'
for i in range(len(files)):
assert resources[2 + i]['scheme'] == 'file'
assert resources[2 + i]['title'] == files[i]

0 comments on commit d30e6d7

Please sign in to comment.