diff --git a/ansible/inventory/group_vars/all/ipa b/ansible/inventory/group_vars/all/ipa index 0ace49f8f..7b98c3366 100644 --- a/ansible/inventory/group_vars/all/ipa +++ b/ansible/inventory/group_vars/all/ipa @@ -178,8 +178,8 @@ ipa_benchmarks: > # List of default kernel parameters for Ironic python agent. ipa_kernel_options_default: > {{ ['ipa-collect-lldp=' ~ ('1' if ipa_collect_lldp | bool else '0')] + - ['ipa-inspection-collectors=' ~ ipa_collectors | join(',')] + - ['ipa-inspection-benchmarks=' ~ ipa_benchmarks | join(',')] }} + (['ipa-inspection-collectors=' ~ ipa_collectors | join(',')] if ipa_collectors else []) + + (['ipa-inspection-benchmarks=' ~ ipa_benchmarks | join(',')] if ipa_benchmarks else []) }} # List of additional kernel parameters for Ironic python agent. ipa_kernel_options_extra: [] diff --git a/doc/source/configuration/reference/ironic-python-agent.rst b/doc/source/configuration/reference/ironic-python-agent.rst index 6492bb04e..3ece11e96 100644 --- a/doc/source/configuration/reference/ironic-python-agent.rst +++ b/doc/source/configuration/reference/ironic-python-agent.rst @@ -327,9 +327,10 @@ inspection. ``ipa_benchmarks_default`` and ``ipa_benchmarks_extra``. ``ipa_kernel_options_default`` List of default kernel parameters for Ironic python agent. Default includes - ``ipa-collect-lldp``, ``ipa-inspection-collectors`` and - ``ipa-inspection-benchmarks``, with arguments taken from - ``ipa_collect_lldp``, ``ipa_collectors`` and ``ipa_benchmarks``. + ``ipa-collect-lldp``, ``ipa-inspection-collectors`` (if ``ipa_collectors`` + is not empty) and ``ipa-inspection-benchmarks`` (if ``ipa_benchmarks`` is + not empty), with arguments taken from ``ipa_collect_lldp``, + ``ipa_collectors`` and ``ipa_benchmarks``. ``ipa_kernel_options_extra`` List of additional kernel parameters for Ironic python agent. Default is none. diff --git a/kayobe/plugins/filter/nmstate.py b/kayobe/plugins/filter/nmstate.py index 7fae395f1..78d55cccf 100644 --- a/kayobe/plugins/filter/nmstate.py +++ b/kayobe/plugins/filter/nmstate.py @@ -519,6 +519,8 @@ def get_iface(name): # _port_type_. for port in br_ports or []: port_iface = get_iface(port) + if mtu: + port_iface.setdefault("mtu", mtu) if "type" not in port_iface: # Check for explicit type configuration port_type = networks.net_attr( @@ -586,6 +588,22 @@ def get_iface(name): parent = re.sub( r'\.{}$'.format(vlan_id), '', iface_name) + # NOTE(bbezak): Do not pass MTU for VLAN interfaces on bridges when + # it is identical to the parent bridge, to work around a + # NetworkManager bug. + bridge_mtus = {} + for bridge in networks.net_select_bridges( + context, names, inventory_hostname): + bridge_interface = networks.net_interface( + context, bridge, inventory_hostname) + bridge_mtus[bridge_interface] = networks.net_mtu( + context, bridge, inventory_hostname) + + if parent in bridge_mtus: + parent_mtu = bridge_mtus[parent] + if mtu and mtu == parent_mtu: + del iface["mtu"] + iface["vlan"] = { "base-iface": parent, "id": int(vlan_id) diff --git a/kayobe/tests/unit/plugins/filter/test_nmstate.py b/kayobe/tests/unit/plugins/filter/test_nmstate.py index da1fef140..b3b5efe1e 100644 --- a/kayobe/tests/unit/plugins/filter/test_nmstate.py +++ b/kayobe/tests/unit/plugins/filter/test_nmstate.py @@ -44,6 +44,7 @@ class TestNMStateFilter(unittest.TestCase): "net3_interface": "br0", "net3_bridge_ports": ['eth1'], "net3_bridge_stp": True, + "net3_mtu": 9000, # net4: bond on bond0 with slaves eth2 and eth3. "net4_interface": "bond0", "net4_bond_slaves": ['eth2', 'eth3'], @@ -123,6 +124,7 @@ def test_nmstate_config_bridge(self): result = nmstate.nmstate_config(self.context, ["net3"]) br_iface = next(i for i in result["interfaces"] if i["name"] == "br0") self.assertEqual(br_iface["type"], "linux-bridge") + self.assertEqual(br_iface["mtu"], 9000) self.assertEqual(br_iface["bridge"]["port"], [{"name": "eth1"}]) self.assertTrue(br_iface["bridge"]["options"]["stp"]["enabled"]) @@ -130,6 +132,7 @@ def test_nmstate_config_bridge(self): eth1_iface = next(i for i in result["interfaces"] if i["name"] == "eth1") self.assertEqual(eth1_iface["type"], "ethernet") + self.assertEqual(eth1_iface["mtu"], 9000) def test_nmstate_config_bond(self): result = nmstate.nmstate_config(self.context, ["net4"]) @@ -434,6 +437,44 @@ def test_vlan_interface_explicit_vlan_and_parent(self): self.assertEqual(vlan_iface["vlan"]["base-iface"], "eth0") self.assertEqual(vlan_iface["vlan"]["id"], 100) + def test_vlan_on_bridge_inherits_matching_mtu(self): + variables = { + "inventory_hostname": "test-host", + "ansible_facts": {"os_family": "RedHat"}, + "vlan_interface": "br0.6", + "vlan_vlan": 6, + "vlan_mtu": 9150, + "bridge_interface": "br0", + "bridge_bridge_ports": ["eth0"], + "bridge_mtu": 9150, + } + context = self._make_context(variables) + result = nmstate.nmstate_config(context, ["vlan", "bridge"]) + + vlan_iface = next( + i for i in result["interfaces"] + if i["name"] == "br0.6") + self.assertNotIn("mtu", vlan_iface) + + def test_vlan_on_bridge_keeps_different_mtu(self): + variables = { + "inventory_hostname": "test-host", + "ansible_facts": {"os_family": "RedHat"}, + "vlan_interface": "br0.6", + "vlan_vlan": 6, + "vlan_mtu": 9000, + "bridge_interface": "br0", + "bridge_bridge_ports": ["eth0"], + "bridge_mtu": 9150, + } + context = self._make_context(variables) + result = nmstate.nmstate_config(context, ["vlan", "bridge"]) + + vlan_iface = next( + i for i in result["interfaces"] + if i["name"] == "br0.6") + self.assertEqual(vlan_iface["mtu"], 9000) + def test_vlan_interface_invalid_name(self): """Test VLAN with invalid interface name is skipped gracefully.""" variables = { diff --git a/releasenotes/notes/bug-2162755-9852bd6b0606d9d8.yaml b/releasenotes/notes/bug-2162755-9852bd6b0606d9d8.yaml new file mode 100644 index 000000000..19a316df3 --- /dev/null +++ b/releasenotes/notes/bug-2162755-9852bd6b0606d9d8.yaml @@ -0,0 +1,6 @@ +--- +fixes: + - | + Fixes Bifrost deployment by ensuring that extra kernel parameters are + successfully parsed by Ironic. + `LP#2162755 `__ diff --git a/roles/kayobe-ci-prep/tasks/main.yml b/roles/kayobe-ci-prep/tasks/main.yml index 11847e719..cc813b87b 100644 --- a/roles/kayobe-ci-prep/tasks/main.yml +++ b/roles/kayobe-ci-prep/tasks/main.yml @@ -64,7 +64,7 @@ - name: Install kernel-modules-extra for running kernel ansible.builtin.dnf: - name: "kernel-modules-extra-{{ ansible_facts.kernel }}" + name: "kernel-modules-extra-matched" state: present when: ansible_facts.os_family == 'RedHat'