wip: OKd installation, some cleanup of unused and some refactoring
All checks were successful
Run Check Script / check (pull_request) Successful in 1m13s
All checks were successful
Run Check Script / check (pull_request) Successful in 1m13s
This commit is contained in:
parent
35a459f63c
commit
241980ebec
18
Cargo.lock
generated
18
Cargo.lock
generated
@ -1775,6 +1775,24 @@ dependencies = [
|
|||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "example-okd-install"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"cidr",
|
||||||
|
"env_logger",
|
||||||
|
"harmony",
|
||||||
|
"harmony_cli",
|
||||||
|
"harmony_macros",
|
||||||
|
"harmony_secret",
|
||||||
|
"harmony_secret_derive",
|
||||||
|
"harmony_types",
|
||||||
|
"log",
|
||||||
|
"serde",
|
||||||
|
"tokio",
|
||||||
|
"url",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "example-opnsense"
|
name = "example-opnsense"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -5,7 +5,7 @@ use std::{
|
|||||||
|
|
||||||
use cidr::Ipv4Cidr;
|
use cidr::Ipv4Cidr;
|
||||||
use harmony::{
|
use harmony::{
|
||||||
hardware::{Location, PhysicalHost, SwitchGroup},
|
hardware::{HostCategory, Location, PhysicalHost, SwitchGroup},
|
||||||
infra::opnsense::OPNSenseManagementInterface,
|
infra::opnsense::OPNSenseManagementInterface,
|
||||||
inventory::Inventory,
|
inventory::Inventory,
|
||||||
modules::{
|
modules::{
|
||||||
@ -13,7 +13,7 @@ use harmony::{
|
|||||||
okd::{
|
okd::{
|
||||||
bootstrap_dhcp::OKDBootstrapDhcpScore,
|
bootstrap_dhcp::OKDBootstrapDhcpScore,
|
||||||
bootstrap_load_balancer::OKDBootstrapLoadBalancerScore, dhcp::OKDDhcpScore,
|
bootstrap_load_balancer::OKDBootstrapLoadBalancerScore, dhcp::OKDDhcpScore,
|
||||||
dns::OKDDnsScore,
|
dns::OKDDnsScore, ipxe::OkdIpxeScore,
|
||||||
},
|
},
|
||||||
tftp::TftpScore,
|
tftp::TftpScore,
|
||||||
},
|
},
|
||||||
@ -130,7 +130,16 @@ async fn main() {
|
|||||||
)),
|
)),
|
||||||
files: vec![],
|
files: vec![],
|
||||||
};
|
};
|
||||||
let ipxe_score = IpxeScore::new();
|
|
||||||
|
let kickstart_filename = "inventory.kickstart".to_string();
|
||||||
|
let cluster_pubkey_filename = "cluster_ssh_key.pub".to_string();
|
||||||
|
let harmony_inventory_agent = "harmony_inventory_agent".to_string();
|
||||||
|
|
||||||
|
let ipxe_score = OkdIpxeScore {
|
||||||
|
kickstart_filename,
|
||||||
|
harmony_inventory_agent,
|
||||||
|
cluster_pubkey_filename,
|
||||||
|
};
|
||||||
|
|
||||||
harmony_tui::run(
|
harmony_tui::run(
|
||||||
inventory,
|
inventory,
|
||||||
|
21
examples/okd_installation/Cargo.toml
Normal file
21
examples/okd_installation/Cargo.toml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
[package]
|
||||||
|
name = "example-okd-install"
|
||||||
|
edition = "2024"
|
||||||
|
version.workspace = true
|
||||||
|
readme.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
publish = false
|
||||||
|
|
||||||
|
[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
|
20
examples/okd_installation/src/main.rs
Normal file
20
examples/okd_installation/src/main.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
mod topology;
|
||||||
|
|
||||||
|
use crate::topology::{get_inventory, get_topology};
|
||||||
|
use harmony::modules::okd::{installation::OKDInstallationScore, ipxe::OkdIpxeScore};
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
|
let inventory = get_inventory();
|
||||||
|
let topology = get_topology().await;
|
||||||
|
|
||||||
|
let kickstart_filename = "inventory.kickstart".to_string();
|
||||||
|
let cluster_pubkey_filename = "cluster_ssh_key.pub".to_string();
|
||||||
|
let harmony_inventory_agent = "harmony_inventory_agent".to_string();
|
||||||
|
|
||||||
|
let okd_install = Box::new(OKDInstallationScore {});
|
||||||
|
|
||||||
|
harmony_cli::run(inventory, topology, vec![okd_install], None)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
}
|
77
examples/okd_installation/src/topology.rs
Normal file
77
examples/okd_installation/src/topology.rs
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
use cidr::Ipv4Cidr;
|
||||||
|
use harmony::{
|
||||||
|
hardware::{FirewallGroup, HostCategory, Location, PhysicalHost, SwitchGroup},
|
||||||
|
infra::opnsense::OPNSenseManagementInterface,
|
||||||
|
inventory::Inventory,
|
||||||
|
topology::{HAClusterTopology, LogicalHost, UnmanagedRouter},
|
||||||
|
};
|
||||||
|
use harmony_macros::{ip, ipv4};
|
||||||
|
use harmony_secret::{Secret, SecretManager};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::{net::IpAddr, sync::Arc};
|
||||||
|
|
||||||
|
#[derive(Secret, Serialize, Deserialize, Debug, PartialEq)]
|
||||||
|
struct OPNSenseFirewallConfig {
|
||||||
|
username: String,
|
||||||
|
password: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_topology() -> HAClusterTopology {
|
||||||
|
let firewall = harmony::topology::LogicalHost {
|
||||||
|
ip: ip!("192.168.1.1"),
|
||||||
|
name: String::from("opnsense-1"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let config = SecretManager::get::<OPNSenseFirewallConfig>().await;
|
||||||
|
let config = config.unwrap();
|
||||||
|
|
||||||
|
let opnsense = Arc::new(
|
||||||
|
harmony::infra::opnsense::OPNSenseFirewall::new(
|
||||||
|
firewall,
|
||||||
|
None,
|
||||||
|
&config.username,
|
||||||
|
&config.password,
|
||||||
|
)
|
||||||
|
.await,
|
||||||
|
);
|
||||||
|
let lan_subnet = ipv4!("192.168.1.0");
|
||||||
|
let gateway_ipv4 = ipv4!("192.168.1.1");
|
||||||
|
let gateway_ip = IpAddr::V4(gateway_ipv4);
|
||||||
|
harmony::topology::HAClusterTopology {
|
||||||
|
domain_name: "demo.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!("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![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_inventory() -> Inventory {
|
||||||
|
Inventory {
|
||||||
|
location: Location::new(
|
||||||
|
"Some virtual machine or maybe a physical machine if you're cool".to_string(),
|
||||||
|
"testopnsense".to_string(),
|
||||||
|
),
|
||||||
|
switch: SwitchGroup::from([]),
|
||||||
|
firewall_mgmt: Box::new(OPNSenseManagementInterface::new()),
|
||||||
|
storage_host: vec![],
|
||||||
|
worker_host: vec![],
|
||||||
|
control_plane_host: vec![],
|
||||||
|
}
|
||||||
|
}
|
7
examples/okd_installation/ssh_example_key
Normal file
7
examples/okd_installation/ssh_example_key
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||||
|
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
|
||||||
|
QyNTUxOQAAACAcemw8pbwuvHFaYynxBbS0Cf3ThYuj1Utr7CDqjwySHAAAAJikacCNpGnA
|
||||||
|
jQAAAAtzc2gtZWQyNTUxOQAAACAcemw8pbwuvHFaYynxBbS0Cf3ThYuj1Utr7CDqjwySHA
|
||||||
|
AAAECiiKk4V6Q5cVs6axDM4sjAzZn/QCZLQekmYQXS9XbEYxx6bDylvC68cVpjKfEFtLQJ
|
||||||
|
/dOFi6PVS2vsIOqPDJIcAAAAEGplYW5nYWJAbGlsaWFuZTIBAgMEBQ==
|
||||||
|
-----END OPENSSH PRIVATE KEY-----
|
1
examples/okd_installation/ssh_example_key.pub
Normal file
1
examples/okd_installation/ssh_example_key.pub
Normal file
@ -0,0 +1 @@
|
|||||||
|
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBx6bDylvC68cVpjKfEFtLQJ/dOFi6PVS2vsIOqPDJIc jeangab@liliane2
|
@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
hardware::PhysicalHost,
|
hardware::PhysicalHost,
|
||||||
inventory::{InventoryRepository, RepoError},
|
inventory::{HostRole, InventoryRepository, RepoError},
|
||||||
};
|
};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use harmony_types::id::Id;
|
use harmony_types::id::Id;
|
||||||
@ -55,6 +55,18 @@ impl InventoryRepository for SqliteInventoryRepository {
|
|||||||
.await?;
|
.await?;
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn get_all_hosts(&self) -> Result<Vec<PhysicalHost>, RepoError> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn save_role_mapping(
|
||||||
|
&self,
|
||||||
|
role: &HostRole,
|
||||||
|
host: &PhysicalHost,
|
||||||
|
) -> Result<(), RepoError> {
|
||||||
|
todo!("save role, host.id in the table host_role_mapping")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use sqlx::types::Json;
|
use sqlx::types::Json;
|
||||||
|
@ -44,12 +44,10 @@
|
|||||||
//! which must be configured on host AND switch to connect properly.
|
//! which must be configured on host AND switch to connect properly.
|
||||||
//!
|
//!
|
||||||
//! Configuration knobs
|
//! Configuration knobs
|
||||||
//! - lan_cidr: CIDR to scan/allow for discovery endpoints.
|
|
||||||
//! - public_domain: External wildcard/apps domain (e.g., apps.example.com).
|
//! - public_domain: External wildcard/apps domain (e.g., apps.example.com).
|
||||||
//! - internal_domain: Internal cluster domain (e.g., cluster.local or harmony.mcd).
|
//! - internal_domain: Internal cluster domain (e.g., cluster.local or harmony.mcd).
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use chrono::Duration;
|
|
||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
use harmony_types::id::Id;
|
use harmony_types::id::Id;
|
||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
@ -75,14 +73,7 @@ use crate::{
|
|||||||
// -------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, new)]
|
#[derive(Debug, Clone, Serialize, Deserialize, new)]
|
||||||
pub struct OKDInstallationScore {
|
pub struct OKDInstallationScore {}
|
||||||
/// The LAN CIDR where discovery endpoints live (e.g., 192.168.10.0/24)
|
|
||||||
pub lan_cidr: String,
|
|
||||||
/// Public external domain (e.g., example.com). Used for api/apps wildcard, etc.
|
|
||||||
pub public_domain: String,
|
|
||||||
/// Internal cluster domain (e.g., harmony.mcd). Used for internal svc/ingress and DNS.
|
|
||||||
pub internal_domain: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Score<HAClusterTopology> for OKDInstallationScore {
|
impl Score<HAClusterTopology> for OKDInstallationScore {
|
||||||
fn create_interpret(&self) -> Box<dyn Interpret<HAClusterTopology>> {
|
fn create_interpret(&self) -> Box<dyn Interpret<HAClusterTopology>> {
|
||||||
@ -123,7 +114,7 @@ impl OKDInstallationInterpret {
|
|||||||
// 1) Prepare DNS and DHCP lease registration (optional)
|
// 1) Prepare DNS and DHCP lease registration (optional)
|
||||||
|
|
||||||
// 2) Serve default iPXE + Kickstart and poll discovery
|
// 2) Serve default iPXE + Kickstart and poll discovery
|
||||||
let discovery_score = OKDSetup01InventoryScore::new(self.score.lan_cidr.clone());
|
let discovery_score = OKDSetup01InventoryScore::new();
|
||||||
discovery_score.interpret(inventory, topology).await?;
|
discovery_score.interpret(inventory, topology).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -135,10 +126,7 @@ impl OKDInstallationInterpret {
|
|||||||
topology: &HAClusterTopology,
|
topology: &HAClusterTopology,
|
||||||
) -> Result<(), InterpretError> {
|
) -> Result<(), InterpretError> {
|
||||||
// Select and provision bootstrap
|
// Select and provision bootstrap
|
||||||
let bootstrap_score = OKDSetup02BootstrapScore::new(
|
let bootstrap_score = OKDSetup02BootstrapScore::new();
|
||||||
self.score.public_domain.clone(),
|
|
||||||
self.score.internal_domain.clone(),
|
|
||||||
);
|
|
||||||
bootstrap_score.interpret(inventory, topology).await?;
|
bootstrap_score.interpret(inventory, topology).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -178,10 +166,7 @@ impl OKDInstallationInterpret {
|
|||||||
inventory: &Inventory,
|
inventory: &Inventory,
|
||||||
topology: &HAClusterTopology,
|
topology: &HAClusterTopology,
|
||||||
) -> Result<(), InterpretError> {
|
) -> Result<(), InterpretError> {
|
||||||
let report_score = OKDSetup06InstallationReportScore::new(
|
let report_score = OKDSetup06InstallationReportScore::new();
|
||||||
self.score.public_domain.clone(),
|
|
||||||
self.score.internal_domain.clone(),
|
|
||||||
);
|
|
||||||
report_score.interpret(inventory, topology).await?;
|
report_score.interpret(inventory, topology).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -212,10 +197,7 @@ impl Interpret<HAClusterTopology> for OKDInstallationInterpret {
|
|||||||
) -> Result<Outcome, InterpretError> {
|
) -> Result<Outcome, InterpretError> {
|
||||||
instrument(HarmonyEvent::HarmonyStarted).ok();
|
instrument(HarmonyEvent::HarmonyStarted).ok();
|
||||||
|
|
||||||
info!(
|
info!("Starting OKD installation pipeline",);
|
||||||
"Starting OKD installation pipeline for public_domain={} internal_domain={} lan_cidr={}",
|
|
||||||
self.score.public_domain, self.score.internal_domain, self.score.lan_cidr
|
|
||||||
);
|
|
||||||
|
|
||||||
self.run_inventory_phase(inventory, topology).await?;
|
self.run_inventory_phase(inventory, topology).await?;
|
||||||
|
|
||||||
@ -400,10 +382,7 @@ impl Interpret<HAClusterTopology> for OKDSetup01InventoryInterpret {
|
|||||||
// -------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, new)]
|
#[derive(Debug, Clone, Serialize, new)]
|
||||||
struct OKDSetup02BootstrapScore {
|
struct OKDSetup02BootstrapScore {}
|
||||||
public_domain: String,
|
|
||||||
internal_domain: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Score<HAClusterTopology> for OKDSetup02BootstrapScore {
|
impl Score<HAClusterTopology> for OKDSetup02BootstrapScore {
|
||||||
fn create_interpret(&self) -> Box<dyn Interpret<HAClusterTopology>> {
|
fn create_interpret(&self) -> Box<dyn Interpret<HAClusterTopology>> {
|
||||||
@ -754,10 +733,7 @@ impl Interpret<HAClusterTopology> for OKDSetup05SanityCheckInterpret {
|
|||||||
// -------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, new)]
|
#[derive(Debug, Clone, Serialize, new)]
|
||||||
struct OKDSetup06InstallationReportScore {
|
struct OKDSetup06InstallationReportScore {}
|
||||||
public_domain: String,
|
|
||||||
internal_domain: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Score<HAClusterTopology> for OKDSetup06InstallationReportScore {
|
impl Score<HAClusterTopology> for OKDSetup06InstallationReportScore {
|
||||||
fn create_interpret(&self) -> Box<dyn Interpret<HAClusterTopology>> {
|
fn create_interpret(&self) -> Box<dyn Interpret<HAClusterTopology>> {
|
||||||
@ -787,10 +763,7 @@ impl OKDSetup06InstallationReportInterpret {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn generate(&self) -> Result<(), InterpretError> {
|
async fn generate(&self) -> Result<(), InterpretError> {
|
||||||
info!(
|
info!("[Report] Generating OKD installation report",);
|
||||||
"[Report] Generating installation report for {} / {}",
|
|
||||||
self.score.public_domain, self.score.internal_domain
|
|
||||||
);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user