Implement Chrony apply

This commit is contained in:
Samuel Lorch 2024-02-11 03:52:00 +01:00
parent e6816fe46f
commit 371b3d9fdf
6 changed files with 88 additions and 2 deletions

View file

@ -310,6 +310,7 @@ export const editTypes: { [key: string]: { [key: string]: any } } = {
name: 'NTP Server',
idType: 'Number',
fields: {
name: { is: 'TextBox', label: 'Name'},
interface: { is: 'SingleSelect', label: 'Interface', props: { searchProvider: GetInterfaces} },
comment: { is: 'MultilineTextBox', label: 'Comment'},
},

65
src/apply/chrony.rs Normal file
View file

@ -0,0 +1,65 @@
use super::ApplyError;
use crate::{
definitions::{config::Config, network::AddressingMode},
templates,
};
use ipnet::IpNet;
use std::process::Command;
use std::str::FromStr;
use std::{error::Error, io::Write};
use tera::Context;
use tracing::{error, info};
const CHRONY_CONFIG_PATH: &str = "/etc/chrony.conf";
const CHRONY_TEMPLATE_PATH: &str = "chrony/chrony.conf";
pub fn apply_chrony(pending_config: Config, _current_config: Config) -> Result<(), ApplyError> {
let config_data;
let mut context = Context::new();
let mut subnets = vec![];
for server in &pending_config.service.ntp_servers {
if let AddressingMode::Static { address } =
&server.interface(pending_config.clone()).addressing_mode
{
subnets.push(IpNet::from_str(address)?.network().to_string());
}
}
context.insert("subnets", &subnets);
match templates::TEMPLATES.render(CHRONY_TEMPLATE_PATH, &context) {
Ok(s) => config_data = 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));
}
}
info!("Deleting old Chrony Config");
std::fs::remove_file(CHRONY_CONFIG_PATH)?;
info!("Writing new Chrony Config");
let mut f = std::fs::File::create(CHRONY_CONFIG_PATH)?;
f.write_all(config_data.as_bytes())?;
info!("Restarting Chrony");
match Command::new("systemctl")
.arg("restart")
.arg("chronyd")
.output()
{
Ok(out) => {
if out.status.success() {
Ok(())
} else {
Err(ApplyError::ServiceRestartFailed)
}
}
Err(err) => Err(ApplyError::IOError(err)),
}
}

View file

@ -1,5 +1,6 @@
use thiserror::Error;
pub mod chrony;
pub mod networkd;
#[derive(Error, Debug)]
@ -10,6 +11,9 @@ pub enum ApplyError {
#[error(transparent)]
IOError(#[from] std::io::Error),
#[error(transparent)]
AddrParseError(#[from] ipnet::AddrParseError),
#[error("Service Restart Failed")]
ServiceRestartFailed,
}

View file

@ -35,7 +35,10 @@ 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];
) -> Result<(), super::apply::ApplyError>] = &[
super::apply::networkd::apply_networkd,
super::apply::chrony::apply_chrony,
];
#[derive(Clone)]
pub struct ConfigManager {

View file

@ -0,0 +1,13 @@
pool pool.ntp.org iburst
driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
keyfile /etc/chrony.keys
ntsdumpdir /var/lib/chrony
leapsectz right/UTC
logdir /var/log/chrony
# Allowed Networks
{% for subnet in subnets -%}
allow {{ subnet }}
{% endfor -%}

View file

@ -2,7 +2,7 @@ use tera::Tera;
lazy_static! {
pub static ref TEMPLATES: Tera = {
let tera = match Tera::new("src/templates/**/*.net*") {
let tera = match Tera::new("src/templates/**/*.*") {
Ok(t) => t,
Err(e) => {
println!("Parsing error(s): {}", e);