Skip to content

Commit 608ccc9

Browse files
committed
fix: el7 interface functionality requires NetworkManager
Cause: NetworkManager is not installed on some EL7 systems by default. Consequence: The interface_pci_id could not be found. Fix: Ensure NetworkManager is installed on EL7. Result: The interface_pci_id can be used on EL7. Also - `module.warn` is deprecated - use `warnings` instead if `module.warn` is not supported. Fix the interface pci test to ensure NetworkManager is running before the test. add warnings parameter for tests Signed-off-by: Rich Megginson <[email protected]>
1 parent 8fa1b8c commit 608ccc9

File tree

4 files changed

+73
-28
lines changed

4 files changed

+73
-28
lines changed

library/firewall_lib.py

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1664,22 +1664,26 @@ def parse_pci_id(module, item):
16641664
if not module.params["online"]:
16651665
module.fail_json(msg="interface_pci_id is not supported in offline mode.")
16661666

1667+
warning = ""
16671668
if PCI_REGEX.search(item):
16681669
global pci_ids
16691670
if not pci_ids:
16701671
pci_ids = get_interface_pci()
16711672

1672-
interface_name = pci_ids.get(item)
1673-
if interface_name:
1674-
return interface_name
1673+
interface_names = pci_ids.get(item)
1674+
if interface_names:
1675+
return interface_names, warning
16751676

1676-
module.warn(msg="No network interfaces found with PCI device ID %s" % item)
1677+
warning = "No network interfaces found with PCI device ID %s" % item
1678+
if callable(getattr(module, "warn", None)):
1679+
module.warn(warning)
1680+
warning = ""
16771681
else:
16781682
module.fail_json(
16791683
msg="PCI id %s does not match format: XXXX:XXXX (X = hexadecimal number)"
16801684
% item
16811685
)
1682-
return []
1686+
return [], warning
16831687

16841688

16851689
def parse_port(module, item):
@@ -1938,6 +1942,7 @@ def main():
19381942
if not HAS_FIREWALLD:
19391943
module.fail_json(msg="No firewall backend could be imported.")
19401944

1945+
warnings = []
19411946
# Argument parse
19421947
firewalld_conf = module.params["firewalld_conf"]
19431948
if firewalld_conf:
@@ -1946,9 +1951,14 @@ def main():
19461951
FW_VERSION
19471952
) >= lsr_parse_version("1.0.0")
19481953
if allow_zone_drifting_deprecated and firewalld_conf.get("allow_zone_drifting"):
1949-
module.warn(
1950-
"AllowZoneDrifting is deprecated in this version of firewalld and no longer supported"
1951-
)
1954+
if callable(getattr(module, "warn", None)):
1955+
module.warn(
1956+
"AllowZoneDrifting is deprecated in this version of firewalld and no longer supported"
1957+
)
1958+
else:
1959+
warnings.append(
1960+
"AllowZoneDrifting is deprecated in this version of firewalld and no longer supported"
1961+
)
19521962
else:
19531963
# CodeQL will produce an error without this line
19541964
allow_zone_drifting_deprecated = None
@@ -1991,9 +2001,12 @@ def main():
19912001
module.fail_json(msg="cannot have more than one destination ipv6")
19922002
interface = module.params["interface"]
19932003
for _interface in module.params["interface_pci_id"]:
1994-
for interface_name in parse_pci_id(module, _interface):
2004+
interface_names, warning = parse_pci_id(module, _interface)
2005+
for interface_name in interface_names:
19952006
if interface_name not in interface:
19962007
interface.append(interface_name)
2008+
if warning:
2009+
warnings.append(warning)
19972010
icmp_block = module.params["icmp_block"]
19982011
icmp_block_inversion = module.params["icmp_block_inversion"]
19992012
timeout = module.params["timeout"]
@@ -2282,7 +2295,7 @@ def main():
22822295
backend.finalize()
22832296

22842297
changed = backend.changed and module.params["__report_changed"]
2285-
module.exit_json(changed=changed, __firewall_changed=changed)
2298+
module.exit_json(changed=changed, __firewall_changed=changed, warnings=warnings)
22862299

22872300

22882301
#################################################

tests/tests_interface_pci.yml

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,20 @@
22
# Tests interface_pci field, test must be used in VM
33
- name: Test interfaces with PCI ids
44
hosts: all
5+
become: true
56
tags:
67
# container builds have no PCI devices, so ethernet interface detection
78
# won't find anything; so save ourselves the extra initial role invocation
89
- tests::booted
9-
become: true
10-
roles:
11-
- linux-system-roles.firewall
12-
10+
gather_facts: true
11+
vars_files:
12+
- vars/rh_distros_vars.yml
1313
tasks:
1414
- name: Set expected backend
1515
set_fact:
16-
nftables_backend:
17-
"{{ true
18-
if ansible_facts['distribution'] in ['RedHat', 'CentOS', 'Fedora']
19-
and ansible_facts['distribution_major_version'] is version('8', '>=')
20-
else false }}"
16+
nftables_backend: "{{
17+
__firewall_is_rh_distro_fedora and
18+
ansible_facts['distribution_major_version'] is version('8', '>=') }}"
2119

2220
- name: Find ethernet interface
2321
shell: |
@@ -57,6 +55,7 @@
5755
set -euo pipefail
5856
nft list ruleset > {{ temp_dir.path }}/nft_before.txt || :
5957
changed_when: false
58+
when: nftables_backend | bool
6059

6160
- name: Determine interface vendor/product ID
6261
shell: |
@@ -67,6 +66,21 @@
6766
register: pci_id
6867
changed_when: false
6968

69+
- name: Set up for el7
70+
when:
71+
- __firewall_is_rh_distro
72+
- ansible_facts['distribution_major_version'] is version('8', '<')
73+
block:
74+
- name: Install NetworkManager
75+
package:
76+
name: NetworkManager
77+
state: present
78+
79+
- name: Start NetworkManager
80+
service:
81+
name: NetworkManager
82+
state: started
83+
7084
- name: Add pci device ethernet controller
7185
include_role:
7286
name: linux-system-roles.firewall
@@ -94,6 +108,7 @@
94108
diff -u {{ temp_dir.path }}/nft_before.txt {{ temp_dir.path }}/nft_after.txt || :
95109
rm -rf {{ temp_dir.path }}
96110
changed_when: false
111+
when: nftables_backend | bool
97112

98113
- name: Get nftable ruleset
99114
command: nft list ruleset

tests/unit/test_firewall_lib.py

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -948,10 +948,16 @@ def test_allow_zone_drifting_deprecated(self, firewall_class, am_class):
948948
"permanent": True,
949949
}
950950
firewall_lib.main()
951-
am.warn.assert_called_with(
952-
"AllowZoneDrifting is deprecated in this version of firewalld and no longer supported"
953-
)
954-
am.exit_json.assert_called_with(changed=False, __firewall_changed=False)
951+
warning_msg = "AllowZoneDrifting is deprecated in this version of firewalld and no longer supported"
952+
if getattr(am, "warn", None):
953+
am.warn.assert_called_with(warning_msg)
954+
am.exit_json.assert_called_with(
955+
changed=False, __firewall_changed=False, warnings=[]
956+
)
957+
else:
958+
am.exit_json.assert_called_with(
959+
changed=False, __firewall_changed=False, warnings=[warning_msg]
960+
)
955961

956962
@patch("firewall_lib.HAS_FIREWALLD", True)
957963
@patch("firewall_lib.FW_VERSION", "0.9.0", create=True)
@@ -1003,7 +1009,9 @@ def test_nm_integration_interfaces(
10031009
try_set_zone_of_interface.return_value = rv
10041010
fw_settings.queryService.return_value = state == "disabled"
10051011
firewall_lib.main()
1006-
am.exit_json.assert_called_with(changed=rv[1], __firewall_changed=rv[1])
1012+
am.exit_json.assert_called_with(
1013+
changed=rv[1], __firewall_changed=rv[1], warnings=[]
1014+
)
10071015

10081016
for state in ["enabled", "disabled"]:
10091017
am.params["state"] = state
@@ -1012,7 +1020,9 @@ def test_nm_integration_interfaces(
10121020
try_set_zone_of_interface.return_value = rv
10131021
fw_settings.queryService.return_value = state == "disabled"
10141022
firewall_lib.main()
1015-
am.exit_json.assert_called_with(changed=True, __firewall_changed=True)
1023+
am.exit_json.assert_called_with(
1024+
changed=True, __firewall_changed=True, warnings=[]
1025+
)
10161026

10171027
@patch("firewall_lib.HAS_FIREWALLD", True)
10181028
@patch("firewall_lib.FW_VERSION", "0.9.0", create=True)
@@ -1534,7 +1544,9 @@ def test_module_parameters(method, state, input, expected, _offline_cmd):
15341544
if permanent:
15351545
called_mock = getattr(fw_settings, called_mock_name)
15361546
assert expected["permanent"] == called_mock.call_args_list
1537-
am.exit_json.assert_called_once_with(changed=True, __firewall_changed=True)
1547+
am.exit_json.assert_called_once_with(
1548+
changed=True, __firewall_changed=True, warnings=[]
1549+
)
15381550
finally:
15391551
am_class_patcher.stop()
15401552
fw_client_patcher.stop()
@@ -1614,7 +1626,9 @@ def mock_run_command(args, check_rc=False):
16141626
else:
16151627
firewall_lib.main()
16161628
assert called_cmds == expected["offline"]
1617-
am.exit_json.assert_called_once_with(changed=True, __firewall_changed=True)
1629+
am.exit_json.assert_called_once_with(
1630+
changed=True, __firewall_changed=True, warnings=[]
1631+
)
16181632
finally:
16191633
am_class_patcher.stop()
16201634
has_fw_patcher.stop()

vars/main.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@ __firewall_required_facts_subsets: "{{ ['!all', '!min'] +
2222

2323
__firewall_packages_base: [firewalld]
2424

25-
__firewall_packages_extra: "{{ ['python-ipaddress']
25+
# NetworkManager is required for the interface_pci_id functionality
26+
# python-ipaddress is required for the ipaddress module
27+
# These are built-in (?) on EL8 and later
28+
__firewall_packages_extra: "{{ ['NetworkManager', 'python-ipaddress']
2629
if __firewall_is_rh_distro and ansible_facts['distribution_major_version'] | int < 8
2730
else [] }}"
2831

0 commit comments

Comments
 (0)