src/config/network.rs: avoid duplicate port usage

This commit is contained in:
Dietmar Maurer 2020-05-08 11:15:00 +02:00
parent 80bf084876
commit a4ccb46176

View File

@ -1,5 +1,5 @@
use std::io::{Write}; use std::io::{Write};
use std::collections::{HashSet, HashMap}; use std::collections::{HashSet, HashMap, BTreeMap};
use anyhow::{Error, format_err, bail}; use anyhow::{Error, format_err, bail};
use serde::de::{value, IntoDeserializer, Deserialize}; use serde::de::{value, IntoDeserializer, Deserialize};
@ -278,7 +278,7 @@ enum NetworkOrderEntry {
#[derive(Debug)] #[derive(Debug)]
pub struct NetworkConfig { pub struct NetworkConfig {
pub interfaces: HashMap<String, Interface>, pub interfaces: BTreeMap<String, Interface>,
order: Vec<NetworkOrderEntry>, order: Vec<NetworkOrderEntry>,
} }
@ -300,7 +300,7 @@ impl NetworkConfig {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
interfaces: HashMap::new(), interfaces: BTreeMap::new(),
order: Vec::new(), order: Vec::new(),
} }
} }
@ -319,8 +319,31 @@ impl NetworkConfig {
Ok(interface) Ok(interface)
} }
/// Check if ports are used only once
pub fn check_port_usage(&self) -> Result<(), Error> {
let mut used_ports = HashMap::new();
let mut check_port_usage = |iface, ports: &Vec<String>| {
for port in ports.iter() {
if let Some(prev_iface) = used_ports.get(port) {
bail!("iface '{}' port '{}' is already used on interface '{}'",
iface, port, prev_iface);
}
used_ports.insert(port.to_string(), iface);
}
Ok(())
};
for (iface, interface) in self.interfaces.iter() {
if let Some(ports) = &interface.bridge_ports { check_port_usage(iface, ports)?; }
if let Some(slaves) = &interface.slaves { check_port_usage(iface, slaves)?; }
}
Ok(())
}
pub fn write_config(&self, w: &mut dyn Write) -> Result<(), Error> { pub fn write_config(&self, w: &mut dyn Write) -> Result<(), Error> {
self.check_port_usage()?;
let mut done = HashSet::new(); let mut done = HashSet::new();
let mut last_entry_was_comment = false; let mut last_entry_was_comment = false;