diff --git a/src/parse.c b/src/parse.c index 1a94ee071..426d1673e 100644 --- a/src/parse.c +++ b/src/parse.c @@ -2313,6 +2313,11 @@ handle_bond_primary_member(NetplanParser* npp, yaml_node_t* node, const void* da npp->current.netdef->id, npp->current.netdef->bond_params.primary_member); ref_ptr = ((char**) ((void*) component + GPOINTER_TO_UINT(data))); + if (*ref_ptr) { + NetplanNetDefinition* bond = _netplan_parser_find_bond_for_primary_member(npp, *ref_ptr); + return yaml_error(npp, node, error, "%s: interface '%s' is already a primary of %s", + npp->current.netdef->id, *ref_ptr, bond->id); + } *ref_ptr = g_strdup(scalar(node)); npp->current.netdef->bond_params.primary_member = g_strdup(scalar(node)); mark_data_as_dirty(npp, ref_ptr); diff --git a/src/util-internal.h b/src/util-internal.h index 86bd1b7da..e9994d0ff 100644 --- a/src/util-internal.h +++ b/src/util-internal.h @@ -78,6 +78,9 @@ netplan_netdef_new(NetplanParser* npp, const char* id, NetplanDefType type, Netp const char * netplan_parser_get_filename(NetplanParser* npp); +NetplanNetDefinition* +_netplan_parser_find_bond_for_primary_member(const NetplanParser* npp, const char* primary); + gboolean has_openvswitch(const NetplanOVSSettings* ovs, NetplanBackend backend, GHashTable *ovs_ports); diff --git a/src/util.c b/src/util.c index 36eb896a2..659a990c3 100644 --- a/src/util.c +++ b/src/util.c @@ -1184,3 +1184,23 @@ _is_valid_macaddress(const char* value) return regexec(&re, value, 0, NULL, 0) == 0; } + +/* Given a netdef ID, look for the netdef representing a bond device that has it as primary member */ +NetplanNetDefinition* +_netplan_parser_find_bond_for_primary_member(const NetplanParser* npp, const char* primary) +{ + GList* iter = npp->ordered; + NetplanNetDefinition* netdef = NULL; + + while (iter) { + netdef = iter->data; + if (netdef->type == NETPLAN_DEF_TYPE_BOND) { + if (!g_strcmp0(netdef->bond_params.primary_member, primary)) { + break; + } + } + iter = iter->next; + } + + return netdef; +} diff --git a/tests/generator/test_bonds.py b/tests/generator/test_bonds.py index bd5bdefc2..885c41e8c 100644 --- a/tests/generator/test_bonds.py +++ b/tests/generator/test_bonds.py @@ -968,6 +968,20 @@ def test_bond_multiple_assignments(self): interfaces: [eno1]''', expect_fail=True) self.assertIn("bond1: interface 'eno1' is already assigned to bond bond0", err) + def test_bond_primary_multiple_assignments(self): + err = self.generate('''network: + version: 2 + ethernets: + eno1: {} + bonds: + bond0: + parameters: + primary: eno1 + bond1: + parameters: + primary: eno1''', expect_fail=True) + self.assertIn("bond1: interface 'eno1' is already a primary of bond0", err) + def test_bond_bridge_cross_assignments1(self): err = self.generate('''network: version: 2