fix: added impl node exporter for hacluster topology and dummy infra
Some checks are pending
Run Check Script / check (pull_request) Waiting to run

This commit is contained in:
Willem 2025-10-22 14:39:12 -04:00
parent 5af13800b7
commit 5ab58f0253
8 changed files with 187 additions and 3 deletions

View File

@ -39,8 +39,7 @@ async fn main() {
let gateway_ipv4 = Ipv4Addr::new(192, 168, 33, 1); let gateway_ipv4 = Ipv4Addr::new(192, 168, 33, 1);
let gateway_ip = IpAddr::V4(gateway_ipv4); let gateway_ip = IpAddr::V4(gateway_ipv4);
let topology = harmony::topology::HAClusterTopology { let topology = harmony::topology::HAClusterTopology {
domain_name: "ncd0.harmony.mcd".to_string(), // TODO this must be set manually correctly domain_name: "ncd0.harmony.mcd".to_string(),
// when setting up the opnsense firewall
router: Arc::new(UnmanagedRouter::new( router: Arc::new(UnmanagedRouter::new(
gateway_ip, gateway_ip,
Ipv4Cidr::new(lan_subnet, 24).unwrap(), Ipv4Cidr::new(lan_subnet, 24).unwrap(),
@ -84,6 +83,7 @@ async fn main() {
}, },
], ],
switch: vec![], switch: vec![],
node_exporter: opnsense.clone(),
}; };
let inventory = Inventory { let inventory = Inventory {

View File

@ -59,6 +59,7 @@ pub async fn get_topology() -> HAClusterTopology {
}, },
workers: vec![], workers: vec![],
switch: vec![], switch: vec![],
node_exporter: opnsense.clone(),
} }
} }

View File

@ -53,6 +53,7 @@ pub async fn get_topology() -> HAClusterTopology {
}, },
workers: vec![], workers: vec![],
switch: vec![], switch: vec![],
node_exporter: opnsense.clone(),
} }
} }

View File

@ -55,6 +55,7 @@ async fn main() {
}, },
workers: vec![], workers: vec![],
switch: vec![], switch: vec![],
node_exporter: opnsense.clone(),
}; };
let inventory = Inventory { let inventory = Inventory {

View File

@ -0,0 +1,20 @@
[package]
name = "example-opnsense-node-exporter"
edition = "2024"
version.workspace = true
readme.workspace = true
license.workspace = true
[dependencies]
harmony = { path = "../../harmony" }
harmony_cli = { path = "../../harmony_cli" }
harmony_types = { path = "../../harmony_types" }
harmony_secret = { path = "../../harmony_secret" }
harmony_secret_derive = { path = "../../harmony_secret_derive" }
cidr = { workspace = true }
tokio = { workspace = true }
harmony_macros = { path = "../../harmony_macros" }
log = { workspace = true }
env_logger = { workspace = true }
url = { workspace = true }
serde.workspace = true

View File

@ -0,0 +1,110 @@
use std::{
net::{IpAddr, Ipv4Addr},
sync::Arc,
};
use cidr::Ipv4Cidr;
use harmony::{
hardware::{HostCategory, Location, PhysicalHost, SwitchGroup},
infra::opnsense::OPNSenseManagementInterface,
inventory::Inventory,
modules::opnsense::node_exporter::NodeExporterScore,
topology::{HAClusterTopology, LogicalHost, UnmanagedRouter},
};
use harmony_macros::{ip, ipv4, mac_address};
#[tokio::main]
async fn main() {
let firewall = harmony::topology::LogicalHost {
ip: ip!("192.168.33.1"),
name: String::from("fw0"),
};
let opnsense = Arc::new(
harmony::infra::opnsense::OPNSenseFirewall::new(firewall, None, "root", "opnsense").await,
);
let lan_subnet = Ipv4Addr::new(192, 168, 33, 0);
let gateway_ipv4 = Ipv4Addr::new(192, 168, 33, 1);
let gateway_ip = IpAddr::V4(gateway_ipv4);
let topology = harmony::topology::HAClusterTopology {
domain_name: "ncd0.harmony.mcd".to_string(),
router: Arc::new(UnmanagedRouter::new(
gateway_ip,
Ipv4Cidr::new(lan_subnet, 24).unwrap(),
)),
load_balancer: opnsense.clone(),
firewall: opnsense.clone(),
tftp_server: opnsense.clone(),
http_server: opnsense.clone(),
dhcp_server: opnsense.clone(),
dns_server: opnsense.clone(),
control_plane: vec![
LogicalHost {
ip: ip!("192.168.33.20"),
name: "cp0".to_string(),
},
LogicalHost {
ip: ip!("192.168.33.21"),
name: "cp1".to_string(),
},
LogicalHost {
ip: ip!("192.168.33.22"),
name: "cp2".to_string(),
},
],
bootstrap_host: LogicalHost {
ip: ip!("192.168.33.66"),
name: "bootstrap".to_string(),
},
workers: vec![
LogicalHost {
ip: ip!("192.168.33.30"),
name: "wk0".to_string(),
},
LogicalHost {
ip: ip!("192.168.33.31"),
name: "wk1".to_string(),
},
LogicalHost {
ip: ip!("192.168.33.32"),
name: "wk2".to_string(),
},
],
switch: vec![],
node_exporter: opnsense.clone(),
};
let inventory = Inventory {
location: Location::new("I am mobile".to_string(), "earth".to_string()),
switch: SwitchGroup::from([]),
firewall_mgmt: Box::new(OPNSenseManagementInterface::new()),
storage_host: vec![],
worker_host: vec![
PhysicalHost::empty(HostCategory::Server)
.mac_address(mac_address!("C4:62:37:02:61:0F")),
PhysicalHost::empty(HostCategory::Server)
.mac_address(mac_address!("C4:62:37:02:61:26")),
PhysicalHost::empty(HostCategory::Server)
.mac_address(mac_address!("C4:62:37:02:61:70")),
],
control_plane_host: vec![
PhysicalHost::empty(HostCategory::Server)
.mac_address(mac_address!("C4:62:37:02:60:FA")),
PhysicalHost::empty(HostCategory::Server)
.mac_address(mac_address!("C4:62:37:02:61:1A")),
PhysicalHost::empty(HostCategory::Server)
.mac_address(mac_address!("C4:62:37:01:BC:68")),
],
};
let node_exporter_score = NodeExporterScore {};
harmony_cli::run(
inventory,
topology,
vec![Box::new(node_exporter_score)],
None,
)
.await
.unwrap();
}

View File

@ -11,7 +11,6 @@ use kube::api::ObjectMeta;
use log::debug; use log::debug;
use log::info; use log::info;
use crate::data::FileContent;
use crate::executors::ExecutorError; use crate::executors::ExecutorError;
use crate::hardware::PhysicalHost; use crate::hardware::PhysicalHost;
use crate::infra::brocade::BrocadeSwitchAuth; use crate::infra::brocade::BrocadeSwitchAuth;
@ -21,6 +20,7 @@ use crate::modules::okd::crd::{
nmstate::{self, NMState, NodeNetworkConfigurationPolicy, NodeNetworkConfigurationPolicySpec}, nmstate::{self, NMState, NodeNetworkConfigurationPolicy, NodeNetworkConfigurationPolicySpec},
}; };
use crate::topology::PxeOptions; use crate::topology::PxeOptions;
use crate::{data::FileContent, topology::node_exporter::NodeExporter};
use super::{ use super::{
DHCPStaticEntry, DhcpServer, DnsRecord, DnsRecordType, DnsServer, Firewall, HostNetworkConfig, DHCPStaticEntry, DhcpServer, DnsRecord, DnsRecordType, DnsServer, Firewall, HostNetworkConfig,
@ -43,6 +43,7 @@ pub struct HAClusterTopology {
pub tftp_server: Arc<dyn TftpServer>, pub tftp_server: Arc<dyn TftpServer>,
pub http_server: Arc<dyn HttpServer>, pub http_server: Arc<dyn HttpServer>,
pub dns_server: Arc<dyn DnsServer>, pub dns_server: Arc<dyn DnsServer>,
pub node_exporter: Arc<dyn NodeExporter>,
pub bootstrap_host: LogicalHost, pub bootstrap_host: LogicalHost,
pub control_plane: Vec<LogicalHost>, pub control_plane: Vec<LogicalHost>,
pub workers: Vec<LogicalHost>, pub workers: Vec<LogicalHost>,
@ -333,6 +334,7 @@ impl HAClusterTopology {
tftp_server: dummy_infra.clone(), tftp_server: dummy_infra.clone(),
http_server: dummy_infra.clone(), http_server: dummy_infra.clone(),
dns_server: dummy_infra.clone(), dns_server: dummy_infra.clone(),
node_exporter: dummy_infra.clone(),
bootstrap_host: dummy_host, bootstrap_host: dummy_host,
control_plane: vec![], control_plane: vec![],
workers: vec![], workers: vec![],
@ -516,6 +518,23 @@ impl Switch for HAClusterTopology {
self.configure_bond(host, &config).await?; self.configure_bond(host, &config).await?;
self.configure_port_channel(host, &config).await self.configure_port_channel(host, &config).await
} }
//TODO add snmp here
}
#[async_trait]
impl NodeExporter for HAClusterTopology {
async fn ensure_initialized(&self) -> Result<(), ExecutorError> {
self.node_exporter.ensure_initialized().await
}
async fn commit_config(&self) -> Result<(), ExecutorError> {
self.node_exporter.commit_config().await
}
async fn reload_restart(&self) -> Result<(), ExecutorError> {
self.node_exporter.reload_restart().await
}
} }
#[derive(Debug)] #[derive(Debug)]
@ -704,3 +723,18 @@ impl DnsServer for DummyInfra {
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA) unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
} }
} }
#[async_trait]
impl NodeExporter for DummyInfra {
async fn ensure_initialized(&self) -> Result<(), ExecutorError> {
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
}
async fn commit_config(&self) -> Result<(), ExecutorError> {
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
}
async fn reload_restart(&self) -> Result<(), ExecutorError> {
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
}
}

View File

@ -0,0 +1,17 @@
use async_trait::async_trait;
use crate::executors::ExecutorError;
#[async_trait]
pub trait NodeExporter: Send + Sync {
async fn ensure_initialized(&self) -> Result<(), ExecutorError>;
async fn commit_config(&self) -> Result<(), ExecutorError>;
async fn reload_restart(&self) -> Result<(), ExecutorError>;
}
//TODO complete this impl
impl std::fmt::Debug for dyn NodeExporter {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("NodeExporter ",))
}
}