Skip to content

Commit

Permalink
Fix metric setting for ifcfg network connections for rhel
Browse files Browse the repository at this point in the history
Most RHEL systems use Network manager to bring up manage network connections.
Network manager does not recognize "METRIC" option for network connections.
It uses IPV4_ROUTE_METRIC and IPV6_ROUTE_METRIC options. Please see
https://people.freedesktop.org/~lkundrak/nm-docs/nm-settings-ifcfg-rh.html

This change ensures that cloud-init generates ifcfg network connection files
with IPV{4/6}_ROUTE_METRIC options that are compatible with RHEL and
network manager.

Fixes: GH-5776
Signed-off-by: Ani Sinha <[email protected]>
  • Loading branch information
ani-sinha committed Oct 3, 2024
1 parent 2e866d3 commit 0a3e496
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 19 deletions.
21 changes: 18 additions & 3 deletions cloudinit/net/sysconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ def to_string(self, proto="ipv4"):
)
metric_key = "METRIC" + index
if metric_key in self._conf:
metric_value = str(self._conf["METRIC" + index])
metric_value = str(self._conf[metric_key])
buf.write(
"%s=%s\n"
% ("METRIC" + str(reindex), _quote_value(metric_value))
Expand Down Expand Up @@ -548,7 +548,12 @@ def _render_subnets(cls, iface_cfg, subnets, has_default_route, flavor):
subnet_type = subnet.get("type")
# metric may apply to both dhcp and static config
if "metric" in subnet:
if flavor != "suse":
if flavor == "rhel":
if subnet_is_ipv6(subnet):
iface_cfg["IPV6_ROUTE_METRIC"] = subnet["metric"]
else:
iface_cfg["IPV4_ROUTE_METRIC"] = subnet["metric"]
elif flavor != "suse":
iface_cfg["METRIC"] = subnet["metric"]
if subnet_type in ["dhcp", "dhcp4"]:
# On SUSE distros 'DHCLIENT_SET_DEFAULT_ROUTE' is a global
Expand Down Expand Up @@ -655,7 +660,17 @@ def _render_subnet_routes(cls, iface_cfg, route_cfg, subnets, flavor):
iface_cfg["GATEWAY"] = route["gateway"]
route_cfg.has_set_default_ipv4 = True
if "metric" in route:
iface_cfg["METRIC"] = route["metric"]
if flavor == "rhel":
if subnet_is_ipv6(subnet):
iface_cfg["IPV6_ROUTE_METRIC"] = route[
"metric"
]
else:
iface_cfg["IPV4_ROUTE_METRIC"] = route[
"metric"
]
else:
iface_cfg["METRIC"] = route["metric"]

else:
# add default routes only to ifcfg files, not
Expand Down
4 changes: 2 additions & 2 deletions tests/unittests/net/network_configs.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@
HWADDR=c0:d6:9f:2c:e8:80
IPADDR=192.168.21.3
NETMASK=255.255.255.0
METRIC=10000
IPV4_ROUTE_METRIC=10000
ONBOOT=yes
TYPE=Ethernet
USERCTL=no"""
Expand Down Expand Up @@ -376,7 +376,7 @@
HWADDR=c0:d6:9f:2c:e8:80
IPADDR=192.168.21.3
NETMASK=255.255.255.0
METRIC=10000
IPV4_ROUTE_METRIC=10000
ONBOOT=yes
TYPE=Ethernet
USERCTL=no"""
Expand Down
31 changes: 17 additions & 14 deletions tests/unittests/test_net.py
Original file line number Diff line number Diff line change
Expand Up @@ -2379,23 +2379,26 @@ def test_from_v2_route_metric(self):
}
},
}
expected = {
"ifcfg-eno1": textwrap.dedent(
"""\
BOOTPROTO=dhcp
DEVICE=eno1
HWADDR=07-1c-c6-75-a4-be
METRIC=100
ONBOOT=yes
TYPE=Ethernet
USERCTL=no
"""
),
}
for dhcp_ver in ("dhcp4", "dhcp6"):
expected = {
"ifcfg-eno1": textwrap.dedent(
"""\
BOOTPROTO=dhcp
DEVICE=eno1
HWADDR=07-1c-c6-75-a4-be
ONBOOT=yes
TYPE=Ethernet
USERCTL=no
"""
),
}
v2data = copy.deepcopy(v2base)
if dhcp_ver == "dhcp6":
expected["ifcfg-eno1"] += "IPV6INIT=yes\nDHCPV6C=yes\n"
expected[
"ifcfg-eno1"
] += "IPV6INIT=yes\nDHCPV6C=yes\nIPV6_ROUTE_METRIC=100\n"
else:
expected["ifcfg-eno1"] += "IPV4_ROUTE_METRIC=100\n"
v2data["ethernets"]["eno1"].update(
{dhcp_ver: True, "{0}-overrides".format(dhcp_ver): overrides}
)
Expand Down

0 comments on commit 0a3e496

Please sign in to comment.