feat(bootstrapping): add bootstrap load balancer and DHCP configurations
- Introduce `bootstrap_load_balancer` module for handling initial load balancing configuration. - Add `bootstrap_dhcp` module for bootstrapping DHCP settings. - Create `harmony_types` crate to house shared types, including `MacAddress`. - Update `harmony_macros` to use `harmony_types` instead of directly referencing `harmony`.
This commit is contained in:
parent
a80ead418e
commit
bec96c2954
8
harmony-rs/Cargo.lock
generated
8
harmony-rs/Cargo.lock
generated
@ -893,6 +893,8 @@ dependencies = [
|
||||
"cidr",
|
||||
"derive-new",
|
||||
"env_logger",
|
||||
"harmony_macros",
|
||||
"harmony_types",
|
||||
"libredfish",
|
||||
"log",
|
||||
"opnsense-config",
|
||||
@ -912,11 +914,15 @@ dependencies = [
|
||||
name = "harmony_macros"
|
||||
version = "1.0.0"
|
||||
dependencies = [
|
||||
"harmony",
|
||||
"harmony_types",
|
||||
"quote",
|
||||
"syn 2.0.90",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "harmony_types"
|
||||
version = "1.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.5"
|
||||
|
@ -4,7 +4,10 @@ members = [
|
||||
"private_repos/*",
|
||||
"demo/*",
|
||||
"harmony",
|
||||
"opnsense-config", "opnsense-config-xml", "harmony_macros",
|
||||
"harmony_types",
|
||||
"harmony_macros",
|
||||
"opnsense-config",
|
||||
"opnsense-config-xml",
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
|
@ -10,7 +10,9 @@ use harmony::{
|
||||
inventory::Inventory,
|
||||
maestro::Maestro,
|
||||
modules::{
|
||||
http::HttpScore, okd::{dhcp::OKDBootstrapDhcpScore, dns::OKDBootstrapDnsScore}, tftp::TftpScore
|
||||
http::HttpScore,
|
||||
okd::{dhcp::OKDDhcpScore, dns::OKDDnsScore},
|
||||
tftp::TftpScore,
|
||||
},
|
||||
topology::{LogicalHost, UnmanagedRouter, Url},
|
||||
};
|
||||
@ -48,6 +50,10 @@ async fn main() {
|
||||
ip: ip!("10.100.8.20"),
|
||||
name: "cp0".to_string(),
|
||||
}],
|
||||
bootstrap_host: LogicalHost {
|
||||
ip: ip!("10.100.8.20"),
|
||||
name: "cp0".to_string(),
|
||||
},
|
||||
workers: vec![],
|
||||
switch: vec![],
|
||||
};
|
||||
@ -73,8 +79,8 @@ async fn main() {
|
||||
// TODO regroup smaller scores in a larger one such as this
|
||||
// let okd_boostrap_preparation();
|
||||
|
||||
// let dhcp_score = OKDBootstrapDhcpScore::new(&topology, &inventory);
|
||||
// let dns_score = OKDBootstrapDnsScore::new(&topology);
|
||||
// let dhcp_score = OKDDhcpScore::new(&topology, &inventory);
|
||||
// let dns_score = OKDDnsScore::new(&topology);
|
||||
// let load_balancer_score =
|
||||
// harmony::modules::okd::load_balancer::OKDLoadBalancerScore::new(&topology);
|
||||
|
||||
|
@ -19,5 +19,7 @@ async-trait = { workspace = true }
|
||||
cidr = { workspace = true }
|
||||
opnsense-config = { path = "../opnsense-config" }
|
||||
opnsense-config-xml = { path = "../opnsense-config-xml" }
|
||||
harmony_macros = { path = "../harmony_macros" }
|
||||
harmony_types = { path = "../harmony_types" }
|
||||
uuid = { workspace = true }
|
||||
url = { workspace = true }
|
||||
|
@ -1,8 +1,8 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use derive_new::new;
|
||||
use harmony_types::net::MacAddress;
|
||||
|
||||
use crate::topology::MacAddress;
|
||||
|
||||
pub type HostGroup = Vec<PhysicalHost>;
|
||||
pub type SwitchGroup = Vec<Switch>;
|
||||
|
@ -1,15 +1,15 @@
|
||||
mod host_binding;
|
||||
mod http;
|
||||
mod load_balancer;
|
||||
mod router;
|
||||
mod tftp;
|
||||
mod http;
|
||||
pub use load_balancer::*;
|
||||
pub use router::*;
|
||||
mod network;
|
||||
pub use host_binding::*;
|
||||
pub use http::*;
|
||||
pub use network::*;
|
||||
pub use tftp::*;
|
||||
pub use http::*;
|
||||
|
||||
use std::{net::IpAddr, sync::Arc};
|
||||
|
||||
@ -23,6 +23,7 @@ pub struct HAClusterTopology {
|
||||
pub tftp_server: Arc<dyn TftpServer>,
|
||||
pub http_server: Arc<dyn HttpServer>,
|
||||
pub dns_server: Arc<dyn DnsServer>,
|
||||
pub bootstrap_host: LogicalHost,
|
||||
pub control_plane: Vec<LogicalHost>,
|
||||
pub workers: Vec<LogicalHost>,
|
||||
pub switch: Vec<LogicalHost>,
|
||||
|
@ -1,6 +1,7 @@
|
||||
use std::{error::Error, net::Ipv4Addr, str::FromStr};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use harmony_types::net::MacAddress;
|
||||
|
||||
use crate::executors::ExecutorError;
|
||||
|
||||
@ -117,35 +118,6 @@ pub enum Action {
|
||||
Deny,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct MacAddress(pub [u8; 6]);
|
||||
|
||||
|
||||
impl MacAddress {
|
||||
#[cfg(test)]
|
||||
pub fn dummy() -> Self {
|
||||
Self([0, 0, 0, 0, 0, 0])
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&MacAddress> for String {
|
||||
fn from(value: &MacAddress) -> Self {
|
||||
format!(
|
||||
"{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
|
||||
value.0[0], value.0[1], value.0[2], value.0[3], value.0[4], value.0[5]
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for MacAddress {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_fmt(format_args!(
|
||||
"MacAddress {}",
|
||||
String::from(self)
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum DnsRecordType {
|
||||
A,
|
||||
|
@ -1,9 +1,12 @@
|
||||
use crate::{hardware::ManagementInterface, topology::{IpAddress, MacAddress}};
|
||||
use crate::hardware::ManagementInterface;
|
||||
use crate::topology::IpAddress;
|
||||
use derive_new::new;
|
||||
use harmony_types::net::MacAddress;
|
||||
|
||||
#[derive(new)]
|
||||
pub struct HPIlo {
|
||||
ip_address: IpAddress,
|
||||
ip_address: Option<IpAddress>,
|
||||
mac_address: Option<MacAddress>,
|
||||
}
|
||||
|
||||
impl ManagementInterface for HPIlo {
|
||||
|
@ -1,8 +1,6 @@
|
||||
use crate::{
|
||||
hardware::ManagementInterface,
|
||||
topology::{IpAddress, MacAddress},
|
||||
};
|
||||
use crate::hardware::ManagementInterface;
|
||||
use derive_new::new;
|
||||
use harmony_types::net::MacAddress;
|
||||
|
||||
#[derive(new)]
|
||||
pub struct IntelAmtManagement {
|
||||
|
@ -1,4 +1,5 @@
|
||||
use async_trait::async_trait;
|
||||
use harmony_types::net::MacAddress;
|
||||
use log::debug;
|
||||
|
||||
use crate::{executors::ExecutorError, topology::{DHCPStaticEntry, DhcpServer, IpAddress, LogicalHost}};
|
||||
@ -28,12 +29,12 @@ impl DhcpServer for OPNSenseFirewall {
|
||||
|
||||
async fn remove_static_mapping(
|
||||
&self,
|
||||
_mac: &crate::topology::MacAddress,
|
||||
_mac: &MacAddress,
|
||||
) -> Result<(), ExecutorError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn list_static_mappings(&self) -> Vec<(crate::topology::MacAddress, IpAddress)> {
|
||||
async fn list_static_mappings(&self) -> Vec<(MacAddress, IpAddress)> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
use derive_new::new;
|
||||
|
||||
use crate::{hardware::ManagementInterface, topology::MacAddress};
|
||||
use crate::hardware::ManagementInterface;
|
||||
|
||||
#[derive(new)]
|
||||
pub struct OPNSenseManagementInterface {}
|
||||
|
55
harmony-rs/harmony/src/modules/okd/bootstrap_dhcp.rs
Normal file
55
harmony-rs/harmony/src/modules/okd/bootstrap_dhcp.rs
Normal file
@ -0,0 +1,55 @@
|
||||
use crate::{
|
||||
inventory::Inventory,
|
||||
modules::dhcp::DhcpScore,
|
||||
score::Score,
|
||||
topology::{HAClusterTopology, HostBinding, LogicalHost},
|
||||
};
|
||||
|
||||
use harmony_macros::ip;
|
||||
#[derive(Debug)]
|
||||
pub struct OKDBootstrapDhcpScore {
|
||||
dhcp_score: DhcpScore,
|
||||
}
|
||||
|
||||
impl OKDBootstrapDhcpScore {
|
||||
pub fn new(topology: &HAClusterTopology, inventory: &Inventory) -> Self {
|
||||
let mut host_binding: Vec<_> = topology
|
||||
.control_plane
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, topology_entry)| HostBinding {
|
||||
logical_host: topology_entry.clone(),
|
||||
physical_host: inventory
|
||||
.control_plane_host
|
||||
.get(index)
|
||||
.expect("Iventory should contain at least as many physical hosts as topology")
|
||||
.clone(),
|
||||
})
|
||||
.collect();
|
||||
host_binding.push(HostBinding {
|
||||
logical_host: topology.bootstrap_host.clone(),
|
||||
physical_host: inventory
|
||||
.worker_host
|
||||
.get(0)
|
||||
.expect("Should have at least one worker to be used as bootstrap node")
|
||||
.clone(),
|
||||
});
|
||||
Self {
|
||||
dhcp_score: DhcpScore::new(
|
||||
host_binding,
|
||||
// TODO : we should add a tftp server to the topology instead of relying on the
|
||||
// router address, this is leaking implementation details
|
||||
Some(topology.router.get_gateway()),
|
||||
Some("bootx64.efi".to_string()),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Score for OKDBootstrapDhcpScore {
|
||||
type InterpretType = <DhcpScore as Score>::InterpretType;
|
||||
|
||||
fn create_interpret(self) -> Self::InterpretType {
|
||||
self.dhcp_score.create_interpret()
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
use std::net::SocketAddr;
|
||||
|
||||
use crate::{
|
||||
modules::load_balancer::LoadBalancerScore,
|
||||
score::Score,
|
||||
topology::{
|
||||
BackendServer, HAClusterTopology, HealthCheck, HttpMethod, HttpStatusCode,
|
||||
LoadBalancerService,
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct OKDBootstrapLoadBalancerScore {
|
||||
load_balancer_score: LoadBalancerScore,
|
||||
}
|
||||
|
||||
impl OKDBootstrapLoadBalancerScore {
|
||||
pub fn new(topology: &HAClusterTopology) -> Self {
|
||||
let private_ip = topology.router.get_gateway();
|
||||
|
||||
let bootstrap_host = &topology.bootstrap_host;
|
||||
|
||||
let private_services = vec![
|
||||
LoadBalancerService {
|
||||
backend_servers: vec![BackendServer {
|
||||
address: bootstrap_host.ip.to_string(),
|
||||
port: 80,
|
||||
}],
|
||||
listening_port: SocketAddr::new(private_ip, 80),
|
||||
health_check: Some(HealthCheck::TCP(None)),
|
||||
},
|
||||
LoadBalancerService {
|
||||
backend_servers: vec![BackendServer {
|
||||
address: bootstrap_host.ip.to_string(),
|
||||
port: 443,
|
||||
}],
|
||||
listening_port: SocketAddr::new(private_ip, 443),
|
||||
health_check: Some(HealthCheck::TCP(None)),
|
||||
},
|
||||
LoadBalancerService {
|
||||
backend_servers: vec![BackendServer {
|
||||
address: bootstrap_host.ip.to_string(),
|
||||
port: 22623,
|
||||
}],
|
||||
listening_port: SocketAddr::new(private_ip, 22623),
|
||||
health_check: Some(HealthCheck::TCP(None)),
|
||||
},
|
||||
LoadBalancerService {
|
||||
backend_servers: vec![BackendServer {
|
||||
address: bootstrap_host.ip.to_string(),
|
||||
port: 6443,
|
||||
}],
|
||||
listening_port: SocketAddr::new(private_ip, 6443),
|
||||
health_check: Some(HealthCheck::HTTP(
|
||||
"/readyz".to_string(),
|
||||
HttpMethod::GET,
|
||||
HttpStatusCode::Success2xx,
|
||||
)),
|
||||
},
|
||||
];
|
||||
Self {
|
||||
load_balancer_score: LoadBalancerScore {
|
||||
public_services: vec![],
|
||||
private_services,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Score for OKDBootstrapLoadBalancerScore {
|
||||
type InterpretType = <LoadBalancerScore as Score>::InterpretType;
|
||||
|
||||
fn create_interpret(self) -> Self::InterpretType {
|
||||
self.load_balancer_score.create_interpret()
|
||||
}
|
||||
}
|
@ -6,11 +6,11 @@ use crate::{
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct OKDBootstrapDhcpScore {
|
||||
pub struct OKDDhcpScore {
|
||||
dhcp_score: DhcpScore,
|
||||
}
|
||||
|
||||
impl OKDBootstrapDhcpScore {
|
||||
impl OKDDhcpScore {
|
||||
pub fn new(topology: &HAClusterTopology, inventory: &Inventory) -> Self {
|
||||
let host_binding = topology
|
||||
.control_plane
|
||||
@ -37,7 +37,7 @@ impl OKDBootstrapDhcpScore {
|
||||
}
|
||||
}
|
||||
|
||||
impl Score for OKDBootstrapDhcpScore {
|
||||
impl Score for OKDDhcpScore {
|
||||
type InterpretType = <DhcpScore as Score>::InterpretType;
|
||||
|
||||
fn create_interpret(self) -> Self::InterpretType {
|
||||
|
@ -5,11 +5,11 @@ use crate::{
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct OKDBootstrapDnsScore {
|
||||
pub struct OKDDnsScore {
|
||||
dns_score: DnsScore,
|
||||
}
|
||||
|
||||
impl OKDBootstrapDnsScore {
|
||||
impl OKDDnsScore {
|
||||
pub fn new(topology: &HAClusterTopology) -> Self {
|
||||
let cluster_domain_name = &topology.domain_name;
|
||||
let dns_entries = vec![
|
||||
@ -39,7 +39,7 @@ impl OKDBootstrapDnsScore {
|
||||
}
|
||||
}
|
||||
|
||||
impl Score for OKDBootstrapDnsScore {
|
||||
impl Score for OKDDnsScore {
|
||||
type InterpretType = <DnsScore as Score>::InterpretType;
|
||||
|
||||
fn create_interpret(self) -> Self::InterpretType {
|
||||
|
@ -1,4 +1,6 @@
|
||||
pub mod dhcp;
|
||||
pub mod dns;
|
||||
pub mod load_balancer;
|
||||
pub mod bootstrap_load_balancer;
|
||||
pub mod bootstrap_dhcp;
|
||||
|
||||
|
@ -7,6 +7,6 @@ version = "1.0.0"
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
harmony = { version = "0.1.0", path = "../harmony" }
|
||||
harmony_types = { path = "../harmony_types" }
|
||||
quote = "1.0.37"
|
||||
syn = "2.0.90"
|
||||
|
@ -1,6 +1,5 @@
|
||||
extern crate proc_macro;
|
||||
|
||||
use harmony::topology::MacAddress;
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{LitStr, parse_macro_input};
|
||||
|
4
harmony-rs/harmony_types/Cargo.toml
Normal file
4
harmony-rs/harmony_types/Cargo.toml
Normal file
@ -0,0 +1,4 @@
|
||||
[package]
|
||||
name = "harmony_types"
|
||||
edition = "2024"
|
||||
version = "1.0.0"
|
26
harmony-rs/harmony_types/src/lib.rs
Normal file
26
harmony-rs/harmony_types/src/lib.rs
Normal file
@ -0,0 +1,26 @@
|
||||
pub mod net {
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct MacAddress(pub [u8; 6]);
|
||||
|
||||
impl MacAddress {
|
||||
#[cfg(test)]
|
||||
pub fn dummy() -> Self {
|
||||
Self([0, 0, 0, 0, 0, 0])
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&MacAddress> for String {
|
||||
fn from(value: &MacAddress) -> Self {
|
||||
format!(
|
||||
"{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
|
||||
value.0[0], value.0[1], value.0[2], value.0[3], value.0[4], value.0[5]
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for MacAddress {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_fmt(format_args!("MacAddress {}", String::from(self)))
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user