feat: implementation for opnsense os-node_exporter
Some checks are pending
Run Check Script / check (pull_request) Waiting to run
Some checks are pending
Run Check Script / check (pull_request) Waiting to run
This commit is contained in:
parent
7536f4ec4b
commit
8126b233d8
@ -1,5 +1,6 @@
|
|||||||
mod ha_cluster;
|
mod ha_cluster;
|
||||||
pub mod ingress;
|
pub mod ingress;
|
||||||
|
pub mod node_exporter;
|
||||||
use harmony_types::net::IpAddress;
|
use harmony_types::net::IpAddress;
|
||||||
mod host_binding;
|
mod host_binding;
|
||||||
mod http;
|
mod http;
|
||||||
|
@ -4,6 +4,7 @@ mod firewall;
|
|||||||
mod http;
|
mod http;
|
||||||
mod load_balancer;
|
mod load_balancer;
|
||||||
mod management;
|
mod management;
|
||||||
|
pub mod node_exporter;
|
||||||
mod tftp;
|
mod tftp;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
44
harmony/src/infra/opnsense/node_exporter.rs
Normal file
44
harmony/src/infra/opnsense/node_exporter.rs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
use async_trait::async_trait;
|
||||||
|
use log::debug;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
executors::ExecutorError, infra::opnsense::OPNSenseFirewall,
|
||||||
|
topology::node_exporter::NodeExporter,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl NodeExporter for OPNSenseFirewall {
|
||||||
|
async fn ensure_initialized(&self) -> Result<(), ExecutorError> {
|
||||||
|
let mut config = self.opnsense_config.write().await;
|
||||||
|
let node_exporter = config.node_exporter();
|
||||||
|
if let Some(config) = node_exporter.get_full_config() {
|
||||||
|
debug!(
|
||||||
|
"Node exporter available in opnsense config, assuming it is already installed. {config:?}"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
config
|
||||||
|
.install_package("os-node_exporter")
|
||||||
|
.await
|
||||||
|
.map_err(|e| {
|
||||||
|
ExecutorError::UnexpectedError(format!("Executor failed when trying to install os-node_exporter package with error {e:?}"
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
|
||||||
|
config.node_exporter().enable(true);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
async fn commit_config(&self) -> Result<(), ExecutorError> {
|
||||||
|
OPNSenseFirewall::commit_config(self).await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn reload_restart(&self) -> Result<(), ExecutorError> {
|
||||||
|
self.opnsense_config
|
||||||
|
.write()
|
||||||
|
.await
|
||||||
|
.node_exporter()
|
||||||
|
.reload_restart()
|
||||||
|
.await
|
||||||
|
.map_err(|e| ExecutorError::UnexpectedError(e.to_string()))
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
pub mod node_exporter;
|
||||||
mod shell;
|
mod shell;
|
||||||
mod upgrade;
|
mod upgrade;
|
||||||
pub use shell::*;
|
pub use shell::*;
|
||||||
|
70
harmony/src/modules/opnsense/node_exporter.rs
Normal file
70
harmony/src/modules/opnsense/node_exporter.rs
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
use async_trait::async_trait;
|
||||||
|
use harmony_types::id::Id;
|
||||||
|
use log::info;
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
data::Version,
|
||||||
|
interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome},
|
||||||
|
inventory::Inventory,
|
||||||
|
score::Score,
|
||||||
|
topology::{Topology, node_exporter::NodeExporter},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
pub struct NodeExporterScore {}
|
||||||
|
|
||||||
|
impl<T: Topology + NodeExporter> Score<T> for NodeExporterScore {
|
||||||
|
fn name(&self) -> String {
|
||||||
|
"NodeExporterScore".to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_interpret(&self) -> Box<dyn Interpret<T>> {
|
||||||
|
Box::new(NodeExporterInterpret {})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct NodeExporterInterpret {}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl<T: Topology + NodeExporter> Interpret<T> for NodeExporterInterpret {
|
||||||
|
async fn execute(
|
||||||
|
&self,
|
||||||
|
_inventory: &Inventory,
|
||||||
|
node_exporter: &T,
|
||||||
|
) -> Result<Outcome, InterpretError> {
|
||||||
|
info!(
|
||||||
|
"Making sure node exporter is initiailized: {:?}",
|
||||||
|
node_exporter.ensure_initialized().await?
|
||||||
|
);
|
||||||
|
|
||||||
|
info!("Applying Node Exporter configuration");
|
||||||
|
|
||||||
|
node_exporter.commit_config().await?;
|
||||||
|
|
||||||
|
info!("Reloading and restarting Node Exporter");
|
||||||
|
|
||||||
|
node_exporter.reload_restart().await?;
|
||||||
|
|
||||||
|
Ok(Outcome::success(format!(
|
||||||
|
"NodeExporter successfully configured"
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_name(&self) -> InterpretName {
|
||||||
|
InterpretName::Custom("NodeExporter")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_version(&self) -> Version {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_status(&self) -> InterpretStatus {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_children(&self) -> Vec<Id> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
@ -433,7 +433,7 @@ pub struct OPNsenseXmlSection {
|
|||||||
#[yaserde(rename = "Interfaces")]
|
#[yaserde(rename = "Interfaces")]
|
||||||
pub interfaces: Option<ConfigInterfaces>,
|
pub interfaces: Option<ConfigInterfaces>,
|
||||||
#[yaserde(rename = "NodeExporter")]
|
#[yaserde(rename = "NodeExporter")]
|
||||||
pub node_exporter: Option<RawXml>,
|
pub node_exporter: Option<NodeExporter>,
|
||||||
#[yaserde(rename = "Kea")]
|
#[yaserde(rename = "Kea")]
|
||||||
pub kea: Option<RawXml>,
|
pub kea: Option<RawXml>,
|
||||||
pub monit: Option<Monit>,
|
pub monit: Option<Monit>,
|
||||||
@ -1595,3 +1595,21 @@ pub struct Ifgroups {
|
|||||||
#[yaserde(attribute = true)]
|
#[yaserde(attribute = true)]
|
||||||
pub version: String,
|
pub version: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||||
|
pub struct NodeExporter {
|
||||||
|
pub enabled: u8,
|
||||||
|
pub listenaddress: Option<MaybeString>,
|
||||||
|
pub listenport: u16,
|
||||||
|
pub cpu: u8,
|
||||||
|
pub exec: u8,
|
||||||
|
pub filesystem: u8,
|
||||||
|
pub loadavg: u8,
|
||||||
|
pub meminfo: u8,
|
||||||
|
pub netdev: u8,
|
||||||
|
pub time: u8,
|
||||||
|
pub devstat: u8,
|
||||||
|
pub interrupts: u8,
|
||||||
|
pub ntp: u8,
|
||||||
|
pub zfs: u8,
|
||||||
|
}
|
||||||
|
@ -5,7 +5,8 @@ use crate::{
|
|||||||
error::Error,
|
error::Error,
|
||||||
modules::{
|
modules::{
|
||||||
caddy::CaddyConfig, dhcp_legacy::DhcpConfigLegacyISC, dns::UnboundDnsConfig,
|
caddy::CaddyConfig, dhcp_legacy::DhcpConfigLegacyISC, dns::UnboundDnsConfig,
|
||||||
dnsmasq::DhcpConfigDnsMasq, load_balancer::LoadBalancerConfig, tftp::TftpConfig,
|
dnsmasq::DhcpConfigDnsMasq, load_balancer::LoadBalancerConfig,
|
||||||
|
node_exporter::NodeExporterConfig, tftp::TftpConfig,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use log::{debug, info, trace, warn};
|
use log::{debug, info, trace, warn};
|
||||||
@ -71,6 +72,10 @@ impl Config {
|
|||||||
LoadBalancerConfig::new(&mut self.opnsense, self.shell.clone())
|
LoadBalancerConfig::new(&mut self.opnsense, self.shell.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn node_exporter(&mut self) -> NodeExporterConfig<'_> {
|
||||||
|
NodeExporterConfig::new(&mut self.opnsense, self.shell.clone())
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn upload_files(&self, source: &str, destination: &str) -> Result<String, Error> {
|
pub async fn upload_files(&self, source: &str, destination: &str) -> Result<String, Error> {
|
||||||
self.shell.upload_folder(source, destination).await
|
self.shell.upload_folder(source, destination).await
|
||||||
}
|
}
|
||||||
|
@ -4,4 +4,5 @@ pub mod dhcp_legacy;
|
|||||||
pub mod dns;
|
pub mod dns;
|
||||||
pub mod dnsmasq;
|
pub mod dnsmasq;
|
||||||
pub mod load_balancer;
|
pub mod load_balancer;
|
||||||
|
pub mod node_exporter;
|
||||||
pub mod tftp;
|
pub mod tftp;
|
||||||
|
55
opnsense-config/src/modules/node_exporter.rs
Normal file
55
opnsense-config/src/modules/node_exporter.rs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use opnsense_config_xml::{NodeExporter, OPNsense};
|
||||||
|
|
||||||
|
use crate::{config::OPNsenseShell, Error};
|
||||||
|
|
||||||
|
pub struct NodeExporterConfig<'a> {
|
||||||
|
opnsense: &'a mut OPNsense,
|
||||||
|
opnsense_shell: Arc<dyn OPNsenseShell>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> NodeExporterConfig<'a> {
|
||||||
|
pub fn new(opnsense: &'a mut OPNsense, opnsense_shell: Arc<dyn OPNsenseShell>) -> Self {
|
||||||
|
Self {
|
||||||
|
opnsense,
|
||||||
|
opnsense_shell,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_full_config(&self) -> &Option<NodeExporter> {
|
||||||
|
&self.opnsense.opnsense.node_exporter
|
||||||
|
}
|
||||||
|
fn with_node_exporter<F, R>(&mut self, f: F) -> R
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut NodeExporter) -> R,
|
||||||
|
{
|
||||||
|
match &mut self.opnsense.opnsense.node_exporter.as_mut() {
|
||||||
|
Some(node_exporter) => f(node_exporter),
|
||||||
|
None => unimplemented!(
|
||||||
|
"
|
||||||
|
node exporter is not yet installed"
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn enable(&mut self, enabled: bool) {
|
||||||
|
self.with_node_exporter(|node_exporter| node_exporter.enabled = enabled as u8)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn reload_restart(&self) -> Result<(), Error> {
|
||||||
|
self.opnsense_shell
|
||||||
|
.exec("configctl node_exporter stop")
|
||||||
|
.await?;
|
||||||
|
self.opnsense_shell
|
||||||
|
.exec("configctl template reload OPNsense/NodeExporter")
|
||||||
|
.await?;
|
||||||
|
self.opnsense_shell
|
||||||
|
.exec("configctl node_exporter configtest")
|
||||||
|
.await?;
|
||||||
|
self.opnsense_shell
|
||||||
|
.exec("configctl node_exporter start")
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user