validator: Validate duplicate interface names

The current interface state is using the name property as an unique
key. Passing in duplicate interfaces names causes a failure only at the
verification step (if it is executed), making it hard to understand the
problem.

This change adds a validation for duplicate interface names, raising an
error early on.

Signed-off-by: Edward Haas <edwardh@redhat.com>
This commit is contained in:
Edward Haas 2020-02-09 10:31:11 +02:00
parent 649a133628
commit 8aba09ef64
3 changed files with 30 additions and 2 deletions

View File

@ -59,6 +59,7 @@ def apply(desired_state, verify_change=True, commit=True, rollback_timeout=60):
desired_state = copy.deepcopy(desired_state)
validator.validate(desired_state)
validator.validate_capabilities(desired_state, netinfo.capabilities())
validator.validate_unique_interface_name(desired_state)
validator.validate_dhcp(desired_state)
validator.validate_dns(desired_state)
validator.validate_vxlan(desired_state)

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2018-2019 Red Hat, Inc.
# Copyright (c) 2018-2020 Red Hat, Inc.
#
# This file is part of nmstate
#
@ -48,6 +48,10 @@ class NmstateRouteWithNoIPInterfaceError(NmstateValueError):
pass
class NmstateDuplicateInterfaceNameError(NmstateValueError):
pass
def validate(data, validation_schema=schema.ifaces_schema):
data = copy.deepcopy(data)
for ifstate in data.get(schema.Interface.KEY, ()):
@ -109,6 +113,17 @@ def validate_link_aggregation_state(desired_state, current_state):
specified_slaves |= slaves
def validate_unique_interface_name(state):
ifaces_names = [
ifstate[schema.Interface.NAME]
for ifstate in state.get(schema.Interface.KEY, [])
]
if len(ifaces_names) != len(set(ifaces_names)):
raise NmstateDuplicateInterfaceNameError(
f"Duplicate interfaces names detected: {sorted(ifaces_names)}"
)
def validate_dhcp(state):
for iface_state in state[Constants.INTERFACES]:
for family in ("ipv4", "ipv6"):

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2018-2019 Red Hat, Inc.
# Copyright (c) 2018-2020 Red Hat, Inc.
#
# This file is part of nmstate
#
@ -154,6 +154,18 @@ def test_dns_three_nameservers():
)
def test_unique_interface_name():
with pytest.raises(validator.NmstateDuplicateInterfaceNameError):
libnmstate.validator.validate_unique_interface_name(
{
schema.Interface.KEY: [
{schema.Interface.NAME: "foo0"},
{schema.Interface.NAME: "foo0"},
]
}
)
def empty_state():
return state.State({})