leapp-repository/SOURCES/0066-Add-IfCfgScanner-actor.patch
2023-03-29 09:01:41 +00:00

247 lines
7.9 KiB
Diff

From cce48a6c1ad138b3217939ccfdb0f271a8492890 Mon Sep 17 00:00:00 2001
From: Lubomir Rintel <lkundrak@v3.sk>
Date: Mon, 26 Sep 2022 10:57:59 +0200
Subject: [PATCH 66/75] Add IfCfgScanner actor
This scans the legacy network configuration in
/etc/sysconfig/network-scripts and produces an IfCfg for each ifcfg-*
file encountered (along with associated keys-, rules-, routes-, etc. files).
---
.../el8toel9/actors/ifcfgscanner/actor.py | 18 +++
.../ifcfgscanner/libraries/ifcfgscanner.py | 67 ++++++++++
.../tests/unit_test_ifcfgscanner.py | 123 ++++++++++++++++++
3 files changed, 208 insertions(+)
create mode 100644 repos/system_upgrade/el8toel9/actors/ifcfgscanner/actor.py
create mode 100644 repos/system_upgrade/el8toel9/actors/ifcfgscanner/libraries/ifcfgscanner.py
create mode 100644 repos/system_upgrade/el8toel9/actors/ifcfgscanner/tests/unit_test_ifcfgscanner.py
diff --git a/repos/system_upgrade/el8toel9/actors/ifcfgscanner/actor.py b/repos/system_upgrade/el8toel9/actors/ifcfgscanner/actor.py
new file mode 100644
index 00000000..dd94986b
--- /dev/null
+++ b/repos/system_upgrade/el8toel9/actors/ifcfgscanner/actor.py
@@ -0,0 +1,18 @@
+from leapp.actors import Actor
+from leapp.libraries.actor import ifcfgscanner
+from leapp.models import IfCfg
+from leapp.tags import FactsPhaseTag, IPUWorkflowTag
+
+
+class IfCfgScanner(Actor):
+ """
+ Scan ifcfg files with legacy network configuration
+ """
+
+ name = "ifcfg_scanner"
+ consumes = ()
+ produces = (IfCfg,)
+ tags = (IPUWorkflowTag, FactsPhaseTag,)
+
+ def process(self):
+ ifcfgscanner.process()
diff --git a/repos/system_upgrade/el8toel9/actors/ifcfgscanner/libraries/ifcfgscanner.py b/repos/system_upgrade/el8toel9/actors/ifcfgscanner/libraries/ifcfgscanner.py
new file mode 100644
index 00000000..cfc385dc
--- /dev/null
+++ b/repos/system_upgrade/el8toel9/actors/ifcfgscanner/libraries/ifcfgscanner.py
@@ -0,0 +1,67 @@
+import errno
+from os import listdir, path
+
+from leapp.libraries.stdlib import api
+from leapp.models import IfCfg, IfCfgProperty
+
+SYSCONFIG_DIR = "/etc/sysconfig/network-scripts"
+
+
+def aux_file(prefix, filename):
+ directory = path.dirname(filename)
+ keys_base = path.basename(filename).replace("ifcfg-", prefix)
+ return path.join(directory, keys_base)
+
+
+def process_ifcfg(filename, secrets=False):
+ if not path.exists(filename):
+ return None
+
+ properties = []
+ for line in open(filename).readlines():
+ try:
+ (name, value) = line.split("#")[0].strip().split("=")
+ if secrets:
+ value = None
+ except ValueError:
+ # We're not interested in lines that are not
+ # simple assignments. Play it safe.
+ continue
+
+ properties.append(IfCfgProperty(name=name, value=value))
+ return properties
+
+
+def process_plain(filename):
+ if not path.exists(filename):
+ return None
+ return open(filename).readlines()
+
+
+def process_file(filename):
+ api.produce(IfCfg(
+ filename=filename,
+ properties=process_ifcfg(filename),
+ secrets=process_ifcfg(aux_file("keys-", filename), secrets=True),
+ rules=process_plain(aux_file("rule-", filename)),
+ rules6=process_plain(aux_file("rule6-", filename)),
+ routes=process_plain(aux_file("route-", filename)),
+ routes6=process_plain(aux_file("route6-", filename)),
+ ))
+
+
+def process_dir(directory):
+ try:
+ keyfiles = listdir(directory)
+ except OSError as e:
+ if e.errno == errno.ENOENT:
+ return
+ raise
+
+ for f in keyfiles:
+ if f.startswith("ifcfg-"):
+ process_file(path.join(directory, f))
+
+
+def process():
+ process_dir(SYSCONFIG_DIR)
diff --git a/repos/system_upgrade/el8toel9/actors/ifcfgscanner/tests/unit_test_ifcfgscanner.py b/repos/system_upgrade/el8toel9/actors/ifcfgscanner/tests/unit_test_ifcfgscanner.py
new file mode 100644
index 00000000..f5e3056a
--- /dev/null
+++ b/repos/system_upgrade/el8toel9/actors/ifcfgscanner/tests/unit_test_ifcfgscanner.py
@@ -0,0 +1,123 @@
+import errno
+import textwrap
+from os.path import basename
+
+import mock
+import six
+
+from leapp.libraries.actor import ifcfgscanner
+from leapp.libraries.common.testutils import make_OSError, produce_mocked
+from leapp.libraries.stdlib import api
+from leapp.models import IfCfg
+
+_builtins_open = "builtins.open" if six.PY3 else "__builtin__.open"
+
+
+def _listdir_ifcfg(path):
+ if path == ifcfgscanner.SYSCONFIG_DIR:
+ return ["ifcfg-net0"]
+ raise make_OSError(errno.ENOENT)
+
+
+def _listdir_ifcfg2(path):
+ if path == ifcfgscanner.SYSCONFIG_DIR:
+ return ["ifcfg-net0", "ifcfg-net1"]
+ raise make_OSError(errno.ENOENT)
+
+
+def _exists_ifcfg(filename):
+ return basename(filename).startswith("ifcfg-")
+
+
+def _exists_keys(filename):
+ if _exists_ifcfg(filename):
+ return True
+ return basename(filename).startswith("keys-")
+
+
+def test_no_conf(monkeypatch):
+ """
+ No report if there are no ifcfg files.
+ """
+
+ monkeypatch.setattr(ifcfgscanner, "listdir", lambda _: ())
+ monkeypatch.setattr(api, "produce", produce_mocked())
+ ifcfgscanner.process()
+ assert not api.produce.called
+
+
+def test_ifcfg1(monkeypatch):
+ """
+ Parse a single ifcfg file.
+ """
+
+ ifcfg_file = textwrap.dedent("""
+ TYPE=Wireless # Some comment
+ # Another comment
+ ESSID=wep1
+ NAME=wep1
+ MODE=Managed
+ WEP_KEY_FLAGS=ask
+ SECURITYMODE=open
+ DEFAULTKEY=1
+ KEY_TYPE=key
+ """)
+
+ mock_config = mock.mock_open(read_data=ifcfg_file)
+ with mock.patch(_builtins_open, mock_config):
+ monkeypatch.setattr(ifcfgscanner, "listdir", _listdir_ifcfg)
+ monkeypatch.setattr(ifcfgscanner.path, "exists", _exists_ifcfg)
+ monkeypatch.setattr(api, "produce", produce_mocked())
+ ifcfgscanner.process()
+
+ assert api.produce.called == 1
+ assert len(api.produce.model_instances) == 1
+ ifcfg = api.produce.model_instances[0]
+ assert isinstance(ifcfg, IfCfg)
+ assert ifcfg.filename == "/etc/sysconfig/network-scripts/ifcfg-net0"
+ assert ifcfg.secrets is None
+ assert len(ifcfg.properties) == 8
+ assert ifcfg.properties[0].name == "TYPE"
+ assert ifcfg.properties[0].value == "Wireless"
+ assert ifcfg.properties[1].name == "ESSID"
+ assert ifcfg.properties[1].value == "wep1"
+
+
+def test_ifcfg2(monkeypatch):
+ """
+ Parse two ifcfg files.
+ """
+
+ mock_config = mock.mock_open(read_data="TYPE=Ethernet")
+ with mock.patch(_builtins_open, mock_config):
+ monkeypatch.setattr(ifcfgscanner, "listdir", _listdir_ifcfg2)
+ monkeypatch.setattr(ifcfgscanner.path, "exists", _exists_ifcfg)
+ monkeypatch.setattr(api, "produce", produce_mocked())
+ ifcfgscanner.process()
+
+ assert api.produce.called == 2
+ assert len(api.produce.model_instances) == 2
+ ifcfg = api.produce.model_instances[0]
+ assert isinstance(ifcfg, IfCfg)
+
+
+def test_ifcfg_key(monkeypatch):
+ """
+ Report ifcfg secrets from keys- file.
+ """
+
+ mock_config = mock.mock_open(read_data="KEY_PASSPHRASE1=Hell0")
+ with mock.patch(_builtins_open, mock_config):
+ monkeypatch.setattr(ifcfgscanner, "listdir", _listdir_ifcfg)
+ monkeypatch.setattr(ifcfgscanner.path, "exists", _exists_keys)
+ monkeypatch.setattr(api, "produce", produce_mocked())
+ ifcfgscanner.process()
+
+ assert api.produce.called == 1
+ assert len(api.produce.model_instances) == 1
+ ifcfg = api.produce.model_instances[0]
+ assert isinstance(ifcfg, IfCfg)
+ assert ifcfg.filename == "/etc/sysconfig/network-scripts/ifcfg-net0"
+ assert len(ifcfg.secrets) == 1
+ assert ifcfg.secrets[0].name == "KEY_PASSPHRASE1"
+ assert ifcfg.secrets[0].value is None
--
2.39.0