diff --git a/harmony-rs/fqm/src/lib.rs b/harmony-rs/fqm/src/lib.rs index e39d3a9..266b60e 100644 --- a/harmony-rs/fqm/src/lib.rs +++ b/harmony-rs/fqm/src/lib.rs @@ -1,4 +1,5 @@ pub mod inventory; +pub mod topology; pub fn add(left: usize, right: usize) -> usize { left + right } diff --git a/harmony-rs/fqm/src/main.rs b/harmony-rs/fqm/src/main.rs index 99b8082..86df6fb 100644 --- a/harmony-rs/fqm/src/main.rs +++ b/harmony-rs/fqm/src/main.rs @@ -18,5 +18,5 @@ async fn main() { let score = OPNSenseDhcpScore::new(InventoryFilter::new(vec![])); let result = maestro.interpret(score).await.unwrap(); info!("{result}"); - }).await; + }).await.unwrap(); } diff --git a/harmony-rs/fqm/src/topology.rs b/harmony-rs/fqm/src/topology.rs new file mode 100644 index 0000000..94638ca --- /dev/null +++ b/harmony-rs/fqm/src/topology.rs @@ -0,0 +1,86 @@ +use std::net::{IpAddr, Ipv4Addr}; + +use harmony::{ + hardware::*, + topology::{ClusterMember, HAClusterTopology, IpAddress, OPNSenseManagement}, +}; + +pub fn fqm_topology() -> HAClusterTopology { + HAClusterTopology { + firewall: vec![ClusterMember { + management: Box::new(OPNSenseManagement::new( + "user".to_string(), + "password".to_string(), + )), + host: Host { + category: HostCategory::Firewall, + network: vec![ + NetworkInterface::new( + "igb0".to_string(), + "00:90:7f:df:2c:1f".to_string(), + 1_000_000_000, + true, + ), + NetworkInterface::new( + "igb1".to_string(), + "00:90:7f:df:2c:20".to_string(), + 1_000_000_000, + true, + ), + NetworkInterface::new( + "igb2".to_string(), + "00:90:7f:df:2c:21".to_string(), + 1_000_000_000, + true, + ), + NetworkInterface::new( + "igb3".to_string(), + "00:90:7f:df:2c:22".to_string(), + 1_000_000_000, + true, + ), + NetworkInterface::new( + "igb4".to_string(), + "00:90:7f:df:2c:23".to_string(), + 1_000_000_000, + true, + ), + NetworkInterface::new( + "igb5".to_string(), + "00:90:7f:df:2c:24".to_string(), + 1_000_000_000, + true, + ), + NetworkInterface::new( + "igb6".to_string(), + "00:90:7f:df:2c:25".to_string(), + 1_000_000_000, + true, + ), + NetworkInterface::new( + "igb7".to_string(), + "00:90:7f:df:2c:26".to_string(), + 1_000_000_000, + true, + ), + ], + storage: vec![Storage::new( + StorageConnectionType::Sata6g, + StorageKind::SSD, + 240_000_000_000, + "TODO".to_string(), + )], + labels: vec![Label::new( + "operatingSystem".to_string(), + "opnsense".to_string(), + )], + }, + }], + control_plane: todo!(), + workers: todo!(), + ceph_hosts: todo!(), + switch: todo!(), + gateway: IpAddress::V4(Ipv4Addr::new(10, 10, 8, 1)), + load_balancer: IpAddress::V4(Ipv4Addr::new(10, 10, 8, 1)), + } +} diff --git a/harmony-rs/harmony/src/domain/hardware/mod.rs b/harmony-rs/harmony/src/domain/hardware/mod.rs index 32de3e1..f6a4e20 100644 --- a/harmony-rs/harmony/src/domain/hardware/mod.rs +++ b/harmony-rs/harmony/src/domain/hardware/mod.rs @@ -20,8 +20,9 @@ pub enum HostCategory { #[derive(Debug, new)] pub struct NetworkInterface { - speed: u64, + name: String, mac_address: MacAddress, + speed: u64, plugged_in: bool, } type MacAddress = String; @@ -40,7 +41,7 @@ pub enum StorageKind { NVME, HDD, } -#[derive(Debug)] +#[derive(Debug, new)] pub struct Storage { connection: StorageConnectionType, kind: StorageKind, @@ -56,7 +57,7 @@ pub struct Switch { #[derive(Debug)] pub struct Firewall {} -#[derive(Debug)] +#[derive(Debug, new)] pub struct Label { name: String, value: String, diff --git a/harmony-rs/harmony/src/domain/topology/mod.rs b/harmony-rs/harmony/src/domain/topology/mod.rs index a8013b1..4ab5c9d 100644 --- a/harmony-rs/harmony/src/domain/topology/mod.rs +++ b/harmony-rs/harmony/src/domain/topology/mod.rs @@ -1,13 +1,48 @@ +mod network; +pub use network::*; + use std::net::IpAddr; -use super::hardware::HostGroup; +use derive_new::new; -pub struct OKDHACluster { - firewall: HostGroup, - control_plane: HostGroup, - workers: HostGroup, - ceph_hosts: HostGroup, - switch: HostGroup, +use super::hardware::{Host, HostGroup}; + +pub struct HAClusterTopology { + pub gateway: IpAddress, + pub load_balancer: IpAddress, + pub firewall: Box, + pub dhcp_server: Box, + pub dns_server: Box, + pub control_plane: Vec, + pub workers: Vec, + pub ceph_hosts: Vec, + pub switch: Vec, } -pub struct IpAddress(IpAddr); +pub type IpAddress = IpAddr; + +pub struct ClusterMember { + pub management: Box, + pub host: Host, +} + +pub trait ManagementInterface { + fn boot_to_pxe(&self); + fn get_ip(&self) -> IpAddress; +} + +#[derive(new)] +pub struct OPNSenseManagement { + username: String, + password: String, +} + +impl ManagementInterface for OPNSenseManagement { + fn boot_to_pxe(&self) { + todo!() + } + + fn get_ip(&self) -> IpAddress { + todo!() + } +} diff --git a/harmony-rs/harmony/src/domain/topology/network.rs b/harmony-rs/harmony/src/domain/topology/network.rs new file mode 100644 index 0000000..abae511 --- /dev/null +++ b/harmony-rs/harmony/src/domain/topology/network.rs @@ -0,0 +1,94 @@ +use std::net::{IpAddr, Ipv4Addr}; + +pub trait Firewall { + fn add_rule(&mut self, rule: FirewallRule) -> Result<(), FirewallError>; + fn remove_rule(&mut self, rule_id: &str) -> Result<(), FirewallError>; + fn list_rules(&self) -> Vec; +} + +pub trait DhcpServer { + fn add_static_mapping(&mut self, mac: MacAddress, ip: Ipv4Addr) -> Result<(), DhcpError>; + fn remove_static_mapping(&mut self, mac: &MacAddress) -> Result<(), DhcpError>; + fn list_static_mappings(&self) -> Vec<(MacAddress, Ipv4Addr)>; +} + +pub trait DnsServer { + fn add_record(&mut self, name: &str, record_type: DnsRecordType, value: &str) -> Result<(), DnsError>; + fn remove_record(&mut self, name: &str, record_type: DnsRecordType) -> Result<(), DnsError>; + fn list_records(&self) -> Vec; +} + +pub trait LoadBalancer { + fn add_backend(&mut self, backend: Backend) -> Result<(), LoadBalancerError>; + fn remove_backend(&mut self, backend_id: &str) -> Result<(), LoadBalancerError>; + fn add_frontend(&mut self, frontend: Frontend) -> Result<(), LoadBalancerError>; + fn remove_frontend(&mut self, frontend_id: &str) -> Result<(), LoadBalancerError>; + fn list_backends(&self) -> Vec; + fn list_frontends(&self) -> Vec; +} + +// Supporting types + +#[derive(Clone, Debug)] +pub struct FirewallRule { + pub id: String, + pub source: IpAddr, + pub destination: IpAddr, + pub port: u16, + pub protocol: Protocol, + pub action: Action, +} + +#[derive(Clone, Debug)] +pub enum Protocol { + TCP, + UDP, + ICMP, +} + +#[derive(Clone, Debug)] +pub enum Action { + Allow, + Deny, +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct MacAddress([u8; 6]); + +#[derive(Clone, Debug)] +pub enum DnsRecordType { + A, + AAAA, + CNAME, + MX, + TXT, +} + +#[derive(Clone, Debug)] +pub struct DnsRecord { + pub name: String, + pub record_type: DnsRecordType, + pub value: String, +} + +#[derive(Clone, Debug)] +pub struct Backend { + pub id: String, + pub ip: IpAddr, + pub port: u16, + pub weight: u8, +} + +#[derive(Clone, Debug)] +pub struct Frontend { + pub id: String, + pub ip: IpAddr, + pub port: u16, + pub backend_ids: Vec, +} + +// Error types +pub struct FirewallError; +pub struct DhcpError; +pub struct DnsError; +pub struct LoadBalancerError; diff --git a/harmony-rs/harmony/src/lib.rs b/harmony-rs/harmony/src/lib.rs index 8c3d0f6..be55110 100644 --- a/harmony-rs/harmony/src/lib.rs +++ b/harmony-rs/harmony/src/lib.rs @@ -1,3 +1,4 @@ -pub mod domain; +mod domain; +pub use domain::*; pub mod infra; pub mod modules;