Files
initrd/src/cmd/init/networks.rs

94 lines
2.5 KiB
Rust
Raw Normal View History

2024-04-29 12:54:25 +02:00
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
}))
}