network: fix typo in BondConfig to_config method

A mismatch between the key names in BondConfig's to_config method
and NetworkDev's netdev_info function was causing subiquity to
crash when creating a bond with a valid transmit hash policy and
then later trying to edit it (LP: #2051586).

The correct key name set by the to_config method should be
"transmit-hash-policy" since this later gets passed to netplan
and neither "xmit-hash-policy" nor "xmit_hash_policy" is a valid
key name in pure netplan config.
This commit is contained in:
Chris Peterson 2024-02-15 15:12:20 -08:00 committed by Chris Peterson
parent cf909d751c
commit efd5138853
3 changed files with 54 additions and 6 deletions

View File

@ -9,6 +9,18 @@ Keyboard:
layout: us layout: us
Network: Network:
actions: actions:
# LP: #2051586 the UI would crash when editing a 802.3ad bond
- action: create-bond
data:
name: bond10
devices:
- [interface index 0]
mode: 802.3ad
- obj: [interface name bond10]
action: EDIT_BOND
- obj: [interface name bond10]
action: DELETE
- action: create-bond - action: create-bond
data: data:
name: bond10 name: bond10

View File

@ -234,7 +234,7 @@ class NetworkDev:
bond = BondConfig( bond = BondConfig(
interfaces=self.config["interfaces"], interfaces=self.config["interfaces"],
mode=params["mode"], mode=params["mode"],
xmit_hash_policy=params.get("xmit-hash-policy"), xmit_hash_policy=params.get("transmit-hash-policy"),
lacp_rate=params.get("lacp-rate"), lacp_rate=params.get("lacp-rate"),
) )
vlan: Optional[VLANConfig] = None vlan: Optional[VLANConfig] = None

View File

@ -15,8 +15,9 @@
from unittest.mock import Mock from unittest.mock import Mock
from subiquitycore.models.network import NetworkDev from subiquitycore.models.network import BondConfig, BondParameters, NetworkDev
from subiquitycore.tests import SubiTestCase from subiquitycore.tests import SubiTestCase
from subiquitycore.tests.parameterized import parameterized
class TestRouteManagement(SubiTestCase): class TestRouteManagement(SubiTestCase):
@ -44,6 +45,9 @@ class TestRouteManagement(SubiTestCase):
class TestNetworkDev(SubiTestCase): class TestNetworkDev(SubiTestCase):
def setUp(self):
self.model = Mock(get_all_netdevs=Mock(return_value=[]))
def test_netdev_info_eth_inexistent(self): def test_netdev_info_eth_inexistent(self):
# LP: #2012659 - just after physically removing an Ethernet interface # LP: #2012659 - just after physically removing an Ethernet interface
# from the system, Subiquity tries to collect information via # from the system, Subiquity tries to collect information via
@ -51,16 +55,48 @@ class TestNetworkDev(SubiTestCase):
# reset to None when the interface got removed. # reset to None when the interface got removed.
# In other private reports, the same issue would occur with Wi-Fi # In other private reports, the same issue would occur with Wi-Fi
# interfaces. # interfaces.
model = Mock(get_all_netdevs=Mock(return_value=[])) nd = NetworkDev(self.model, "testdev0", "eth")
nd = NetworkDev(model, "testdev0", "eth")
info = nd.netdev_info() info = nd.netdev_info()
self.assertFalse(info.is_connected) self.assertFalse(info.is_connected)
def test_netdev_info_wlan_inexistent(self): def test_netdev_info_wlan_inexistent(self):
# Just like test_netdev_info_eth_inexistent but with Wi-Fi interfaces # Just like test_netdev_info_eth_inexistent but with Wi-Fi interfaces
# which suffer the same issue. # which suffer the same issue.
model = Mock(get_all_netdevs=Mock(return_value=[])) nd = NetworkDev(self.model, "testdev0", "wlan")
nd = NetworkDev(model, "testdev0", "wlan")
info = nd.netdev_info() info = nd.netdev_info()
self.assertIsNone(info.wlan.scan_state) self.assertIsNone(info.wlan.scan_state)
self.assertEqual(info.wlan.visible_ssids, []) self.assertEqual(info.wlan.visible_ssids, [])
def test_netdev_info_bond_extract(self):
nd = NetworkDev(self.model, "testdev0", "bond")
bond = BondConfig(["interface"], "802.3ad", "layer3+4", "slow")
nd.config = bond.to_config()
info = nd.netdev_info()
self.assertEqual(info.bond, bond)
class TestBondConfig(SubiTestCase):
@parameterized.expand(
[
(mode, ["interface"], mode, "transmit", "lacp")
for mode in BondParameters.modes
]
)
def test_to_config(self, name, interfaces, mode, transmit, lacp):
bond = BondConfig(interfaces, mode, transmit, lacp)
config = bond.to_config()
params = config["parameters"]
self.assertEqual(config["interfaces"], interfaces)
self.assertEqual(params["mode"], mode)
if mode in BondParameters.supports_xmit_hash_policy:
self.assertIn(
"transmit-hash-policy", params
) # redundant but helpful error message
self.assertEqual(params["transmit-hash-policy"], transmit)
else:
self.assertNotIn("transmit-hash-policy", params)
if mode in BondParameters.supports_lacp_rate:
self.assertIn("lacp-rate", params) # redundant but helpful error message
self.assertEqual(params["lacp-rate"], lacp)
else:
self.assertNotIn("lacp-rate", params)