From fff6de4a18fa4eca709870e995de99c543a4ac1c Mon Sep 17 00:00:00 2001 From: Andrew Kutz <101085+akutz@users.noreply.github.com> Date: Tue, 9 Nov 2021 13:41:03 -0600 Subject: Fix for set-name bug in networkd renderer (#1100) This patch address an issue where the use of the "set-name" directive caused the networkd renderer to fail. LP: #1949407 --- cloudinit/net/networkd.py | 17 ++++++++-- cloudinit/net/tests/test_networkd.py | 64 ++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 cloudinit/net/tests/test_networkd.py diff --git a/cloudinit/net/networkd.py b/cloudinit/net/networkd.py index ee6fd2ad..c97c18f6 100644 --- a/cloudinit/net/networkd.py +++ b/cloudinit/net/networkd.py @@ -41,11 +41,11 @@ class CfgParser: def get_final_conf(self): contents = '' - for k, v in self.conf_dict.items(): + for k, v in sorted(self.conf_dict.items()): if not v: continue contents += '['+k+']\n' - for e in v: + for e in sorted(v): contents += e + '\n' contents += '\n' @@ -242,6 +242,19 @@ class Renderer(renderer.Renderer): name = iface['name'] # network state doesn't give dhcp domain info # using ns.config as a workaround here + + # Check to see if this interface matches against an interface + # from the network state that specified a set-name directive. + # If there is a device with a set-name directive and it has + # set-name value that matches the current name, then update the + # current name to the device's name. That will be the value in + # the ns.config['ethernets'] dict below. + for dev_name, dev_cfg in ns.config['ethernets'].items(): + if 'set-name' in dev_cfg: + if dev_cfg.get('set-name') == name: + name = dev_name + break + self.dhcp_domain(ns.config['ethernets'][name], cfg) ret_dict.update({link: cfg.get_final_conf()}) diff --git a/cloudinit/net/tests/test_networkd.py b/cloudinit/net/tests/test_networkd.py new file mode 100644 index 00000000..8dc90b48 --- /dev/null +++ b/cloudinit/net/tests/test_networkd.py @@ -0,0 +1,64 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +from cloudinit import safeyaml +from cloudinit.net import networkd, network_state + +V2_CONFIG_SET_NAME = """\ +network: + version: 2 + ethernets: + eth0: + match: + macaddress: '00:11:22:33:44:55' + nameservers: + search: [spam.local, eggs.local] + addresses: [8.8.8.8] + eth1: + match: + macaddress: '66:77:88:99:00:11' + set-name: "ens92" + nameservers: + search: [foo.local, bar.local] + addresses: [4.4.4.4] +""" + +V2_CONFIG_SET_NAME_RENDERED_ETH0 = """[Match] +MACAddress=00:11:22:33:44:55 +Name=eth0 + +[Network] +DHCP=no +DNS=8.8.8.8 +Domains=spam.local eggs.local + +""" + +V2_CONFIG_SET_NAME_RENDERED_ETH1 = """[Match] +MACAddress=66:77:88:99:00:11 +Name=ens92 + +[Network] +DHCP=no +DNS=4.4.4.4 +Domains=foo.local bar.local + +""" + + +class TestNetworkdRenderState: + def _parse_network_state_from_config(self, config): + yaml = safeyaml.load(config) + return network_state.parse_net_config_data(yaml["network"]) + + def test_networkd_render_with_set_name(self): + ns = self._parse_network_state_from_config(V2_CONFIG_SET_NAME) + renderer = networkd.Renderer() + rendered_content = renderer._render_content(ns) + + assert "eth0" in rendered_content + assert rendered_content["eth0"] == V2_CONFIG_SET_NAME_RENDERED_ETH0 + assert "ens92" in rendered_content + assert rendered_content["ens92"] == V2_CONFIG_SET_NAME_RENDERED_ETH1 + + +# vi: ts=4 expandtab -- cgit v1.2.3