ifaces: Allow partial consuming port interface from ignore to up

Given a bridge `br0` with `eth1` and `eth2` ports, all of them are
`state: ignore`. When applying this state,

```yaml
interfaces:
- name: br0
  type: linux-bridge
  state: up
- name: eth1
  type: ethernet
  state: up
```

nmstate should partially convert br0 and eth1 to managed state and
leaving eth2 untouched.

Both unit and integration test case included.

Signed-off-by: Gris Ge <fge@redhat.com>
This commit is contained in:
Gris Ge 2022-08-09 19:05:25 +08:00 committed by Fernando Fernández Mancera
parent b1e5028d6e
commit f5eb8e907e
2 changed files with 68 additions and 2 deletions

View File

@ -168,12 +168,37 @@ fn handle_changed_ports_of_iface(
) -> Result<(), NmstateError> {
let desire_port_names = match iface.ports() {
Some(p) => HashSet::from_iter(p.iter().cloned()),
None => return Ok(()),
None => {
if let Some(cur_iface) =
cur_ifaces.get_iface(iface.name(), iface.iface_type())
{
if cur_iface.is_ignore() {
// Desire state would like to convert from ignore and
// preserving existing port lists
match cur_iface.ports().map(|ports| {
HashSet::<&str>::from_iter(ports.iter().cloned())
}) {
Some(p) => p,
None => return Ok(()),
}
} else {
return Ok(());
}
} else {
return Ok(());
}
}
};
let current_port_names = cur_ifaces
.get_iface(iface.name(), iface.iface_type())
.and_then(|cur_iface| cur_iface.ports())
.and_then(|cur_iface| {
if cur_iface.is_ignore() {
None
} else {
cur_iface.ports()
}
})
.map(|ports| HashSet::<&str>::from_iter(ports.iter().cloned()))
.unwrap_or_default();

View File

@ -300,3 +300,44 @@ def test_ignore_interface_mentioned_in_port_list(
f"nmcli -g GENERAL.STATE d show {DUMMY1}".split(), check=True
)[1]
)
def test_partially_consume_linux_bridge_port(
external_managed_bridge_with_unmanaged_ports,
):
desired_state = {
Interface.KEY: [
{
Interface.NAME: BRIDGE0,
Interface.STATE: InterfaceState.UP,
},
{
Interface.NAME: DUMMY0,
Interface.STATE: InterfaceState.UP,
},
]
}
libnmstate.apply(desired_state)
current_state = show_only((BRIDGE0,))
bridge_state = current_state[Interface.KEY][0][LB.CONFIG_SUBTREE]
port_names = [port[LB.Port.NAME] for port in bridge_state[LB.PORT_SUBTREE]]
assert port_names == [DUMMY0, DUMMY1]
assert (
"connected"
in exec_cmd(
f"nmcli -g GENERAL.STATE d show {BRIDGE0}".split(), check=True
)[1]
)
assert (
"connected"
in exec_cmd(
f"nmcli -g GENERAL.STATE d show {DUMMY0}".split(), check=True
)[1]
)
assert (
"unmanaged"
in exec_cmd(
f"nmcli -g GENERAL.STATE d show {DUMMY1}".split(), check=True
)[1]
)