mirror of
https://github.com/speatzle/nfsense.git
synced 2025-05-11 19:08:20 +00:00
Add wip networkd Apply
This commit is contained in:
parent
163c097d2d
commit
ee013ec9ad
7 changed files with 237 additions and 8 deletions
173
src/apply/networkd/mod.rs
Normal file
173
src/apply/networkd/mod.rs
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
use super::ApplyError;
|
||||||
|
use crate::{
|
||||||
|
definitions::{config::Config, network::NetworkInterfaceType},
|
||||||
|
templates,
|
||||||
|
};
|
||||||
|
use std::error::Error;
|
||||||
|
use tera::Context;
|
||||||
|
use tracing::{error, info};
|
||||||
|
|
||||||
|
pub struct File {
|
||||||
|
pub name: String,
|
||||||
|
pub content: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn apply_networkd(pending_config: Config, current_config: Config) -> Result<(), ApplyError> {
|
||||||
|
let files = generate_networkd_config_files(pending_config, current_config)?;
|
||||||
|
info!("Got Files");
|
||||||
|
for file in files {
|
||||||
|
info!("Conf File {}", file.name);
|
||||||
|
info!("{}", file.content);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generate_networkd_config_files(
|
||||||
|
pending_config: Config,
|
||||||
|
_current_config: Config,
|
||||||
|
) -> Result<Vec<File>, ApplyError> {
|
||||||
|
let mut files = Vec::new();
|
||||||
|
|
||||||
|
// Step 1 Generate vlan netdev files
|
||||||
|
for interface in &pending_config.network.interfaces {
|
||||||
|
if let NetworkInterfaceType::Vlan { id, .. } = &interface.interface_type {
|
||||||
|
let mut context = Context::new();
|
||||||
|
context.insert("name", &interface.name);
|
||||||
|
context.insert("vlan_id", &id);
|
||||||
|
|
||||||
|
files.push(generate_config_file(
|
||||||
|
context,
|
||||||
|
"networkd/create-vlan.netdev",
|
||||||
|
format!("10-create-vlan-{}.netdev", &interface.name),
|
||||||
|
)?);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 2 Generate bond netdev files
|
||||||
|
for interface in &pending_config.network.interfaces {
|
||||||
|
if let NetworkInterfaceType::Bond { .. } = &interface.interface_type {
|
||||||
|
let mut context = Context::new();
|
||||||
|
context.insert("name", &interface.name);
|
||||||
|
|
||||||
|
files.push(generate_config_file(
|
||||||
|
context,
|
||||||
|
"networkd/create-bond.netdev",
|
||||||
|
format!("20-create-bond-{}.netdev", &interface.name),
|
||||||
|
)?);
|
||||||
|
|
||||||
|
// Create Membership files
|
||||||
|
for member in interface
|
||||||
|
.interface_type
|
||||||
|
.bond_members(pending_config.clone())
|
||||||
|
{
|
||||||
|
let mut context = Context::new();
|
||||||
|
context.insert("bond_name", &interface.name);
|
||||||
|
|
||||||
|
// if interface is a hardware interface then we want to use device instead
|
||||||
|
match member.interface_type {
|
||||||
|
NetworkInterfaceType::Hardware { device } => context.insert("name", &device),
|
||||||
|
_ => context.insert("name", &member.name),
|
||||||
|
};
|
||||||
|
|
||||||
|
files.push(generate_config_file(
|
||||||
|
context,
|
||||||
|
"networkd/bond-membership.network",
|
||||||
|
format!("50-bond-membership-{}.network", &member.name),
|
||||||
|
)?);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 3 Generate bridge netdev files
|
||||||
|
for interface in &pending_config.network.interfaces {
|
||||||
|
if let NetworkInterfaceType::Bridge { .. } = &interface.interface_type {
|
||||||
|
let mut context = Context::new();
|
||||||
|
context.insert("name", &interface.name);
|
||||||
|
|
||||||
|
files.push(generate_config_file(
|
||||||
|
context,
|
||||||
|
"networkd/create-bridge.netdev",
|
||||||
|
format!("30-create-bridge-{}.netdev", &interface.name),
|
||||||
|
)?);
|
||||||
|
|
||||||
|
// Create Membership files
|
||||||
|
for member in interface
|
||||||
|
.interface_type
|
||||||
|
.bridge_members(pending_config.clone())
|
||||||
|
{
|
||||||
|
let mut context = Context::new();
|
||||||
|
context.insert("bridge_name", &interface.name);
|
||||||
|
|
||||||
|
// if interface is a hardware interface then we want to use device instead
|
||||||
|
match member.interface_type {
|
||||||
|
NetworkInterfaceType::Hardware { device } => context.insert("name", &device),
|
||||||
|
_ => context.insert("name", &member.name),
|
||||||
|
};
|
||||||
|
|
||||||
|
files.push(generate_config_file(
|
||||||
|
context,
|
||||||
|
"networkd/bridge-membership.network",
|
||||||
|
format!("60-bridge-membership-{}.network", &member.name),
|
||||||
|
)?);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 4 Generate wireguard netdev files
|
||||||
|
/* TODO
|
||||||
|
for interface in &pending_config.network.interfaces {
|
||||||
|
if let NetworkInterfaceType::Bridge { .. } = interface.interface_type {
|
||||||
|
let mut context = Context::new();
|
||||||
|
context.insert("name", &interface.name);
|
||||||
|
|
||||||
|
files.push(generate_config_file(
|
||||||
|
context,
|
||||||
|
"networkd/create-wireguard.netdev",
|
||||||
|
format!("40-create-wireguard-{}.netdev", &interface.name),
|
||||||
|
)?);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Step 5 Generate Addressing network files
|
||||||
|
/*
|
||||||
|
for interface in &pending_config.network.interfaces {
|
||||||
|
if let NetworkInterfaceType::Vlan { id, .. } = &interface.interface_type {
|
||||||
|
let mut context = Context::new();
|
||||||
|
match &interface.interface_type {
|
||||||
|
NetworkInterfaceType::Hardware { device } => context.insert("name", &device),
|
||||||
|
_ => context.insert("name", &member.name),
|
||||||
|
};
|
||||||
|
|
||||||
|
files.push(generate_config_file(
|
||||||
|
context,
|
||||||
|
"networkd/config-addressing.network",
|
||||||
|
format!("70-config-addressing-{}.network", &interface.name),
|
||||||
|
)?);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
Ok(files)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_config_file(
|
||||||
|
context: Context,
|
||||||
|
template_name: &str,
|
||||||
|
file_name: String,
|
||||||
|
) -> Result<File, ApplyError> {
|
||||||
|
match templates::TEMPLATES.render(template_name, &context) {
|
||||||
|
Ok(s) => Ok(File {
|
||||||
|
name: file_name,
|
||||||
|
content: s,
|
||||||
|
}),
|
||||||
|
Err(e) => {
|
||||||
|
error!("Error: {}", e);
|
||||||
|
let mut cause = e.source();
|
||||||
|
while let Some(e) = cause {
|
||||||
|
error!("Reason: {}", e);
|
||||||
|
cause = e.source();
|
||||||
|
}
|
||||||
|
return Err(ApplyError::TemplateError(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,13 +1,11 @@
|
||||||
use serde::Serialize;
|
|
||||||
use validator::Validate;
|
|
||||||
|
|
||||||
use super::definitions::config::Config;
|
use super::definitions::config::Config;
|
||||||
|
use pwhash::sha512_crypt;
|
||||||
|
use serde::Serialize;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::sync::{Arc, Mutex, MutexGuard};
|
use std::sync::{Arc, Mutex, MutexGuard};
|
||||||
|
|
||||||
use pwhash::sha512_crypt;
|
|
||||||
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
use tracing::{error, info};
|
||||||
|
use validator::Validate;
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum ConfigError {
|
pub enum ConfigError {
|
||||||
|
@ -34,6 +32,11 @@ pub enum ConfigError {
|
||||||
pub const CURRENT_CONFIG_PATH: &str = "config.json";
|
pub const CURRENT_CONFIG_PATH: &str = "config.json";
|
||||||
pub const PENDING_CONFIG_PATH: &str = "pending.json";
|
pub const PENDING_CONFIG_PATH: &str = "pending.json";
|
||||||
|
|
||||||
|
static APPLY_FUNCTIONS: &'static [fn(
|
||||||
|
pending_config: Config,
|
||||||
|
current_config: Config,
|
||||||
|
) -> Result<(), super::apply::ApplyError>] = &[super::apply::networkd::apply_networkd];
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ConfigManager {
|
pub struct ConfigManager {
|
||||||
shared_data: Arc<Mutex<SharedData>>,
|
shared_data: Arc<Mutex<SharedData>>,
|
||||||
|
@ -93,8 +96,36 @@ impl ConfigManager {
|
||||||
|
|
||||||
pub fn apply_pending_changes(&mut self) -> Result<(), ConfigError> {
|
pub fn apply_pending_changes(&mut self) -> Result<(), ConfigError> {
|
||||||
let mut data = self.shared_data.lock().unwrap();
|
let mut data = self.shared_data.lock().unwrap();
|
||||||
// TODO run Apply functions
|
|
||||||
// TODO Revert on Apply Failure and Return
|
// TODO Improve Error Handling
|
||||||
|
for apply_function in APPLY_FUNCTIONS {
|
||||||
|
match (apply_function)(data.pending_config.clone(), data.current_config.clone()) {
|
||||||
|
Ok(_) => info!("Applied"),
|
||||||
|
Err(e) => {
|
||||||
|
error!("Applying function, Reverting to current config...");
|
||||||
|
|
||||||
|
for apply_function in APPLY_FUNCTIONS {
|
||||||
|
match (apply_function)(
|
||||||
|
// These are swapped for revert
|
||||||
|
data.current_config.clone(),
|
||||||
|
data.pending_config.clone(),
|
||||||
|
) {
|
||||||
|
Ok(_) => info!("Applied"),
|
||||||
|
Err(e) => {
|
||||||
|
error!("Reverting failed, giving up.");
|
||||||
|
return Err(ConfigError::ApplyError(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
info!("Revert Done.");
|
||||||
|
return Err(ConfigError::ApplyError(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
info!("Apply Done.");
|
||||||
|
|
||||||
write_config_to_file(CURRENT_CONFIG_PATH, data.pending_config.clone())?;
|
write_config_to_file(CURRENT_CONFIG_PATH, data.pending_config.clone())?;
|
||||||
// TODO revert if config save fails
|
// TODO revert if config save fails
|
||||||
// TODO Remove Pending Config File
|
// TODO Remove Pending Config File
|
||||||
|
|
5
src/templates/networkd/bond-membership.network
Normal file
5
src/templates/networkd/bond-membership.network
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
[Match]
|
||||||
|
Name={{ name }}
|
||||||
|
|
||||||
|
[Network]
|
||||||
|
Bond={{ bond_name }}
|
5
src/templates/networkd/bridge-membership.network
Normal file
5
src/templates/networkd/bridge-membership.network
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
[Match]
|
||||||
|
Name={{ name }}
|
||||||
|
|
||||||
|
[Network]
|
||||||
|
Bridge={{ bridge_name }}
|
6
src/templates/networkd/create-bond.netdev
Normal file
6
src/templates/networkd/create-bond.netdev
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[NetDev]
|
||||||
|
Name={{ name }}
|
||||||
|
Kind=bond
|
||||||
|
|
||||||
|
[Bond]
|
||||||
|
Mode=active-backup
|
3
src/templates/networkd/create-bridge.netdev
Normal file
3
src/templates/networkd/create-bridge.netdev
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[NetDev]
|
||||||
|
Name={{ name }}
|
||||||
|
Kind=bridge
|
6
src/templates/networkd/create-vlan.netdev
Normal file
6
src/templates/networkd/create-vlan.netdev
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[NetDev]
|
||||||
|
Name={{ name }}
|
||||||
|
Kind=vlan
|
||||||
|
|
||||||
|
[VLAN]
|
||||||
|
Id={{ vlan_id }}
|
Loading…
Add table
Reference in a new issue