use crate::config::{Config, NamespaceName}; use crate::link::{LinkError, LinkManager}; use crate::namespace::NetNs; use main_error::MainResult; use tracing::error; pub fn up(config: Config) -> MainResult { let mut namespaces = NetNs::existing(false)? .map(NetNs::new) .collect::, _>>()?; for removed in namespaces.extract_if(.., |namespace| { config.get_namespace(namespace.name()).is_none() }) { removed.delete()?; } for new in config.namespaces { if !has_namespace(&namespaces, &new.name) { namespaces.push(NetNs::new(new.name.clone())?); } let namespace = get_namespace(&namespaces, &new.name).expect("namespace is just created"); for device in new.devices { if let Err(error) = namespace.move_device(&device) { error!(%error, "failed to move device into namespace"); } } for route in new.routes { namespace.handle().run_in(|| { let manager = LinkManager::new()?; let link = manager.get_link(&route.device)?; manager.add_route(&link, route.destination)?; Ok::<_, LinkError>(()) })??; } } Ok(()) } fn has_namespace(namespaces: &[NetNs], name: &NamespaceName) -> bool { namespaces.iter().any(|existing| existing.name() == name) } fn get_namespace<'a>(namespaces: &'a [NetNs], name: &NamespaceName) -> Option<&'a NetNs> { namespaces.iter().find(|existing| existing.name() == name) }