94 lines
2.5 KiB
Rust
94 lines
2.5 KiB
Rust
![]() |
use itertools::Itertools;
|
||
|
use log::{info, warn};
|
||
|
use std::collections::BTreeSet as Set;
|
||
|
use std::process::Command;
|
||
|
|
||
|
use super::{format_err, retry_or_ignore, Config, Result};
|
||
|
use crate::{
|
||
|
udev,
|
||
|
utils::{select_n_by_regex, NameAliases},
|
||
|
};
|
||
|
|
||
|
pub fn setup(cfg: &Config) -> Result<()> {
|
||
|
if cfg.networks.is_empty() {
|
||
|
warn!("no networks configured");
|
||
|
return Ok(());
|
||
|
}
|
||
|
|
||
|
let mut assigned: Set<String> = Set::new();
|
||
|
|
||
|
for net in &cfg.networks {
|
||
|
retry_or_ignore(|| {
|
||
|
info!("setting up network {}", net.name);
|
||
|
|
||
|
let netdevs = get_interfaces()?
|
||
|
.filter(|dev| !assigned.contains(dev.name()))
|
||
|
.collect::<Vec<_>>();
|
||
|
|
||
|
for dev in &netdevs {
|
||
|
info!(
|
||
|
"- available network device: {}, aliases [{}]",
|
||
|
dev.name(),
|
||
|
dev.aliases().join(", ")
|
||
|
);
|
||
|
}
|
||
|
|
||
|
let mut cmd = Command::new("ash");
|
||
|
cmd.arg("-c");
|
||
|
cmd.arg(&net.script);
|
||
|
|
||
|
let mut selected = Vec::new();
|
||
|
|
||
|
for iface in &net.interfaces {
|
||
|
let var = &iface.var;
|
||
|
|
||
|
let netdevs = netdevs.iter().filter(|na| !assigned.contains(na.name()));
|
||
|
let if_names = select_n_by_regex(iface.n, &iface.regexps, netdevs);
|
||
|
|
||
|
if if_names.is_empty() {
|
||
|
return Err(format_err!("- no interface match for {var:?}"));
|
||
|
}
|
||
|
|
||
|
let value = if_names.join(" ");
|
||
|
info!("- {var}={value}");
|
||
|
cmd.env(var, value);
|
||
|
|
||
|
selected.extend(if_names);
|
||
|
}
|
||
|
|
||
|
info!("- running script");
|
||
|
let status = cmd.status()?;
|
||
|
if !status.success() {
|
||
|
return Err(format_err!("setup script failed: {status}"));
|
||
|
}
|
||
|
|
||
|
assigned.extend(selected);
|
||
|
Ok(())
|
||
|
});
|
||
|
}
|
||
|
|
||
|
Ok(())
|
||
|
}
|
||
|
|
||
|
fn get_interfaces() -> Result<impl Iterator<Item = NameAliases>> {
|
||
|
Ok(udev::get_devices("net")?.into_iter().map(|dev| {
|
||
|
let mut na = NameAliases::new(dev.sysname().to_string());
|
||
|
|
||
|
for (property, value) in dev.properties() {
|
||
|
if [
|
||
|
"INTERFACE",
|
||
|
"ID_NET_NAME",
|
||
|
"ID_NET_NAME_PATH",
|
||
|
"ID_NET_NAME_MAC",
|
||
|
"ID_NET_NAME_SLOT",
|
||
|
]
|
||
|
.contains(&property)
|
||
|
{
|
||
|
na.push(value.to_string());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
na
|
||
|
}))
|
||
|
}
|