mirror of
https://github.com/speatzle/nfsense.git
synced 2025-05-10 18:38:22 +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 pwhash::sha512_crypt;
|
||||
use serde::Serialize;
|
||||
use std::fs;
|
||||
use std::sync::{Arc, Mutex, MutexGuard};
|
||||
|
||||
use pwhash::sha512_crypt;
|
||||
|
||||
use thiserror::Error;
|
||||
use tracing::{error, info};
|
||||
use validator::Validate;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum ConfigError {
|
||||
|
@ -34,6 +32,11 @@ pub enum ConfigError {
|
|||
pub const CURRENT_CONFIG_PATH: &str = "config.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)]
|
||||
pub struct ConfigManager {
|
||||
shared_data: Arc<Mutex<SharedData>>,
|
||||
|
@ -93,8 +96,36 @@ impl ConfigManager {
|
|||
|
||||
pub fn apply_pending_changes(&mut self) -> Result<(), ConfigError> {
|
||||
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())?;
|
||||
// TODO revert if config save fails
|
||||
// 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