Skip to content

Commit

Permalink
Fix network v2 metric rendering (#4220)
Browse files Browse the repository at this point in the history
Metric info was not being included in v2-based routes.

Fixes GH-4217
  • Loading branch information
TheRealFalcon authored Jul 4, 2023
1 parent 5674a7d commit c68305a
Show file tree
Hide file tree
Showing 2 changed files with 234 additions and 19 deletions.
3 changes: 1 addition & 2 deletions cloudinit/net/network_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,6 @@ def to_passthrough(cls, network_state: dict) -> "NetworkState":


class NetworkStateInterpreter(metaclass=CommandHandlerMeta):

initial_network_state = {
"interfaces": {},
"routes": [],
Expand Down Expand Up @@ -644,7 +643,6 @@ def handle_bonds(self, command):
self._handle_bond_bridge(command, cmd_type="bond")

def handle_bridges(self, command):

"""
v2_command = {
br0: {
Expand Down Expand Up @@ -931,6 +929,7 @@ def _add_dhcp_overrides(overrides, subnet):
{
"destination": route.get("to"),
"gateway": route.get("via"),
"metric": route.get("metric"),
}
)
)
Expand Down
250 changes: 233 additions & 17 deletions tests/unittests/test_net.py
Original file line number Diff line number Diff line change
Expand Up @@ -988,7 +988,7 @@
""".lstrip()

NETWORK_CONFIGS = {
"small": {
"small_v1": {
"expected_networkd_eth99": textwrap.dedent(
"""\
[Match]
Expand Down Expand Up @@ -1195,6 +1195,178 @@
"""
),
},
# We test a separate set of configs here because v2 doesn't support
# generic nameservers, so that aspect needs to be modified
"small_v2": {
"expected_networkd_eth99": textwrap.dedent(
"""\
[Match]
Name=eth99
MACAddress=c0:d6:9f:2c:e8:80
[Address]
Address=192.168.21.3/24
[Network]
DHCP=ipv4
Domains=barley.maas sach.maas
DNS=8.8.8.8 8.8.4.4
[Route]
Gateway=65.61.151.37
Destination=0.0.0.0/0
Metric=10000
"""
).rstrip(" "),
"expected_networkd_eth1": textwrap.dedent(
"""\
[Match]
Name=eth1
MACAddress=cf:d6:af:48:e8:80
[Network]
DHCP=no
"""
).rstrip(" "),
"expected_eni": textwrap.dedent(
"""\
auto lo
iface lo inet loopback
dns-nameservers 8.8.8.8 8.8.4.4
dns-search wark.maas
iface eth1 inet manual
auto eth99
iface eth99 inet dhcp
# control-alias eth99
iface eth99 inet static
address 192.168.21.3/24
dns-nameservers 8.8.8.8 8.8.4.4
dns-search barley.maas sach.maas
post-up route add default gw 65.61.151.37 metric 10000 || true
pre-down route del default gw 65.61.151.37 metric 10000 || true
"""
).rstrip(" "),
"expected_sysconfig_opensuse": {
"ifcfg-eth1": textwrap.dedent(
"""\
BOOTPROTO=static
LLADDR=cf:d6:af:48:e8:80
STARTMODE=auto"""
),
"ifcfg-eth99": textwrap.dedent(
"""\
BOOTPROTO=dhcp4
LLADDR=c0:d6:9f:2c:e8:80
IPADDR=192.168.21.3
NETMASK=255.255.255.0
STARTMODE=auto"""
),
},
"expected_sysconfig_rhel": {
"ifcfg-eth1": textwrap.dedent(
"""\
BOOTPROTO=none
DEVICE=eth1
HWADDR=cf:d6:af:48:e8:80
NM_CONTROLLED=no
ONBOOT=yes
TYPE=Ethernet
USERCTL=no"""
),
"ifcfg-eth99": textwrap.dedent(
"""\
BOOTPROTO=dhcp
DEFROUTE=yes
DEVICE=eth99
DHCLIENT_SET_DEFAULT_ROUTE=yes
DNS1=8.8.8.8
DNS2=8.8.4.4
DOMAIN="barley.maas sach.maas"
GATEWAY=65.61.151.37
HWADDR=c0:d6:9f:2c:e8:80
IPADDR=192.168.21.3
NETMASK=255.255.255.0
METRIC=10000
NM_CONTROLLED=no
ONBOOT=yes
TYPE=Ethernet
USERCTL=no"""
),
},
"expected_network_manager": {
"cloud-init-eth1.nmconnection": textwrap.dedent(
"""\
# Generated by cloud-init. Changes will be lost.
[connection]
id=cloud-init eth1
uuid=3c50eb47-7260-5a6d-801d-bd4f587d6b58
autoconnect-priority=120
type=ethernet
[user]
org.freedesktop.NetworkManager.origin=cloud-init
[ethernet]
mac-address=CF:D6:AF:48:E8:80
"""
),
"cloud-init-eth99.nmconnection": textwrap.dedent(
"""\
# Generated by cloud-init. Changes will be lost.
[connection]
id=cloud-init eth99
uuid=b1b88000-1f03-5360-8377-1a2205efffb4
autoconnect-priority=120
type=ethernet
[user]
org.freedesktop.NetworkManager.origin=cloud-init
[ethernet]
mac-address=C0:D6:9F:2C:E8:80
[ipv4]
method=auto
may-fail=false
route1=0.0.0.0/0,65.61.151.37
address1=192.168.21.3/24
dns=8.8.8.8;8.8.4.4;
dns-search=barley.maas;sach.maas;
"""
),
},
"yaml": textwrap.dedent(
"""
version: 2
ethernets:
eth1:
match:
macaddress: cf:d6:af:48:e8:80
set-name: eth1
eth99:
addresses:
- 192.168.21.3/24
dhcp4: true
match:
macaddress: c0:d6:9f:2c:e8:80
nameservers:
addresses:
- 8.8.8.8
- 8.8.4.4
search:
- barley.maas
- sach.maas
routes:
- metric: 10000
to: 0.0.0.0/0
via: 65.61.151.37
set-name: eth99
"""
),
},
"v4_and_v6": {
"expected_networkd": textwrap.dedent(
"""\
Expand Down Expand Up @@ -4391,7 +4563,6 @@ def test_unstable_names_disabled(
mock.Mock(return_value=False),
)
class TestRhelSysConfigRendering(CiTestCase):

with_logs = True

scripts_dir = "/etc/sysconfig/network-scripts"
Expand Down Expand Up @@ -4824,8 +4995,14 @@ def test_all_config(self):
self.logs.getvalue(),
)

def test_small_config(self):
entry = NETWORK_CONFIGS["small"]
def test_small_config_v1(self):
entry = NETWORK_CONFIGS["small_v1"]
found = self._render_and_read(network_config=yaml.load(entry["yaml"]))
self._compare_files_to_expected(entry[self.expected_name], found)
self._assert_headers(found)

def test_small_config_v2(self):
entry = NETWORK_CONFIGS["small_v2"]
found = self._render_and_read(network_config=yaml.load(entry["yaml"]))
self._compare_files_to_expected(entry[self.expected_name], found)
self._assert_headers(found)
Expand Down Expand Up @@ -5311,7 +5488,6 @@ def test_iface_name_from_device_with_matching_mac_address(
mock.Mock(return_value=False),
)
class TestOpenSuseSysConfigRendering(CiTestCase):

with_logs = True

scripts_dir = "/etc/sysconfig/network"
Expand Down Expand Up @@ -5604,8 +5780,14 @@ def test_all_config(self):
self.logs.getvalue(),
)

def test_small_config(self):
entry = NETWORK_CONFIGS["small"]
def test_small_config_v1(self):
entry = NETWORK_CONFIGS["small_v1"]
found = self._render_and_read(network_config=yaml.load(entry["yaml"]))
self._compare_files_to_expected(entry[self.expected_name], found)
self._assert_headers(found)

def test_small_config_v2(self):
entry = NETWORK_CONFIGS["small_v1"]
found = self._render_and_read(network_config=yaml.load(entry["yaml"]))
self._compare_files_to_expected(entry[self.expected_name], found)
self._assert_headers(found)
Expand Down Expand Up @@ -5673,7 +5855,6 @@ def test_render_v6_and_v4(self):
mock.Mock(return_value=False),
)
class TestNetworkManagerRendering(CiTestCase):

with_logs = True

scripts_dir = "/etc/NetworkManager/system-connections"
Expand Down Expand Up @@ -5887,8 +6068,13 @@ def test_all_config(self):
self.logs.getvalue(),
)

def test_small_config(self):
entry = NETWORK_CONFIGS["small"]
def test_small_config_v1(self):
entry = NETWORK_CONFIGS["small_v1"]
found = self._render_and_read(network_config=yaml.load(entry["yaml"]))
self._compare_files_to_expected(entry[self.expected_name], found)

def test_small_config_v2(self):
entry = NETWORK_CONFIGS["small_v2"]
found = self._render_and_read(network_config=yaml.load(entry["yaml"]))
self._compare_files_to_expected(entry[self.expected_name], found)

Expand Down Expand Up @@ -6929,7 +7115,6 @@ def test_first_applicable_source_is_used(self):


class TestNetplanRoundTrip(CiTestCase):

NETPLAN_INFO_OUT = textwrap.dedent(
"""
netplan.io:
Expand Down Expand Up @@ -6991,7 +7176,7 @@ def testsimple_render_bond_v2_input_netplan(self):
)

def testsimple_render_small_netplan(self):
entry = NETWORK_CONFIGS["small"]
entry = NETWORK_CONFIGS["small_v1"]
files = self._render_and_read(network_config=yaml.load(entry["yaml"]))
self.assertEqual(
entry["expected_netplan"].splitlines(),
Expand Down Expand Up @@ -7201,8 +7386,17 @@ def testsimple_render_all(self):
files["/etc/network/interfaces"].splitlines(),
)

def testsimple_render_small(self):
entry = NETWORK_CONFIGS["small"]
def testsimple_render_small_v1(self):
entry = NETWORK_CONFIGS["small_v1"]
files = self._render_and_read(network_config=yaml.load(entry["yaml"]))
self.assertEqual(
entry["expected_eni"].splitlines(),
files["/etc/network/interfaces"].splitlines(),
)

@pytest.mark.xfail(reason="GH-4219")
def testsimple_render_small_v2(self):
entry = NETWORK_CONFIGS["small_v2"]
files = self._render_and_read(network_config=yaml.load(entry["yaml"]))
self.assertEqual(
entry["expected_eni"].splitlines(),
Expand Down Expand Up @@ -7582,10 +7776,33 @@ def _render_and_read(
return dir2dict(dir)

@mock.patch("cloudinit.net.util.chownbyname", return_value=True)
def testsimple_render_small_networkd(self, m_chown):
def testsimple_render_small_networkd_v1(self, m_chown):
nwk_fn1 = "/etc/systemd/network/10-cloud-init-eth99.network"
nwk_fn2 = "/etc/systemd/network/10-cloud-init-eth1.network"
entry = NETWORK_CONFIGS["small_v1"]
files = self._render_and_read(network_config=yaml.load(entry["yaml"]))

actual = files[nwk_fn1].splitlines()
actual = self.create_conf_dict(actual)

expected = entry["expected_networkd_eth99"].splitlines()
expected = self.create_conf_dict(expected)

self.compare_dicts(actual, expected)

actual = files[nwk_fn2].splitlines()
actual = self.create_conf_dict(actual)

expected = entry["expected_networkd_eth1"].splitlines()
expected = self.create_conf_dict(expected)

self.compare_dicts(actual, expected)

@mock.patch("cloudinit.net.util.chownbyname", return_value=True)
def testsimple_render_small_networkd_v2(self, m_chown):
nwk_fn1 = "/etc/systemd/network/10-cloud-init-eth99.network"
nwk_fn2 = "/etc/systemd/network/10-cloud-init-eth1.network"
entry = NETWORK_CONFIGS["small"]
entry = NETWORK_CONFIGS["small_v2"]
files = self._render_and_read(network_config=yaml.load(entry["yaml"]))

actual = files[nwk_fn1].splitlines()
Expand Down Expand Up @@ -8310,7 +8527,6 @@ def test_natural_order(self):
mock.Mock(return_value=False),
)
class TestGetIBHwaddrsByInterface(CiTestCase):

_ib_addr = "80:00:00:28:fe:80:00:00:00:00:00:00:00:11:22:03:00:33:44:56"
_ib_addr_eth_format = "00:11:22:33:44:56"
_data = {
Expand Down

0 comments on commit c68305a

Please sign in to comment.