extract related logic into an OkdIpxeScore
Some checks failed
Run Check Script / check (pull_request) Failing after 33s
Some checks failed
Run Check Script / check (pull_request) Failing after 33s
This commit is contained in:
parent
7bb3602ab8
commit
b857412151
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -1732,7 +1732,6 @@ dependencies = [
|
|||||||
name = "example-pxe"
|
name = "example-pxe"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"askama",
|
|
||||||
"cidr",
|
"cidr",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"harmony",
|
"harmony",
|
||||||
@ -2169,6 +2168,7 @@ dependencies = [
|
|||||||
name = "harmony"
|
name = "harmony"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"askama",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
"bollard",
|
"bollard",
|
||||||
|
@ -18,5 +18,4 @@ harmony_macros = { path = "../../harmony_macros" }
|
|||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
env_logger = { workspace = true }
|
env_logger = { workspace = true }
|
||||||
url = { workspace = true }
|
url = { workspace = true }
|
||||||
askama = "0.14.0"
|
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
|
@ -1,97 +1,24 @@
|
|||||||
mod topology;
|
mod topology;
|
||||||
|
|
||||||
use std::net::IpAddr;
|
|
||||||
|
|
||||||
use askama::Template;
|
|
||||||
use harmony::{
|
|
||||||
data::{FileContent, FilePath},
|
|
||||||
modules::{dhcp::DhcpScore, http::StaticFilesHttpScore, tftp::TftpScore},
|
|
||||||
score::Score,
|
|
||||||
topology::{HAClusterTopology, Url},
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::topology::{get_inventory, get_topology};
|
use crate::topology::{get_inventory, get_topology};
|
||||||
|
use harmony::modules::okd::ipxe::OkdIpxeScore;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let inventory = get_inventory();
|
let inventory = get_inventory();
|
||||||
let topology = get_topology().await;
|
let topology = get_topology().await;
|
||||||
let gateway_ip = &topology.router.get_gateway();
|
|
||||||
|
|
||||||
let kickstart_filename = "inventory.kickstart";
|
let kickstart_filename = "inventory.kickstart".to_string();
|
||||||
let cluster_pubkey_filename = "cluster_ssh_key.pub";
|
let cluster_pubkey_filename = "cluster_ssh_key.pub".to_string();
|
||||||
let harmony_inventory_agent = "harmony_inventory_agent";
|
let harmony_inventory_agent = "harmony_inventory_agent".to_string();
|
||||||
|
|
||||||
// TODO: this should be a single IPXEScore instead of having the user do this step by step
|
let ipxe_score = OkdIpxeScore {
|
||||||
let scores: Vec<Box<dyn Score<HAClusterTopology>>> = vec![
|
kickstart_filename,
|
||||||
Box::new(DhcpScore {
|
harmony_inventory_agent,
|
||||||
host_binding: vec![],
|
cluster_pubkey_filename,
|
||||||
next_server: Some(topology.router.get_gateway()),
|
};
|
||||||
boot_filename: None,
|
|
||||||
filename: Some("undionly.kpxe".to_string()),
|
|
||||||
filename64: Some("ipxe.efi".to_string()),
|
|
||||||
filenameipxe: Some(format!("http://{gateway_ip}:8080/boot.ipxe").to_string()),
|
|
||||||
}),
|
|
||||||
Box::new(TftpScore {
|
|
||||||
files_to_serve: Url::LocalFolder("./data/pxe/okd/tftpboot/".to_string()),
|
|
||||||
}),
|
|
||||||
Box::new(StaticFilesHttpScore {
|
|
||||||
// TODO The current russh based copy is way too slow, check for a lib update or use scp
|
|
||||||
// when available
|
|
||||||
//
|
|
||||||
// For now just run :
|
|
||||||
// scp -r data/pxe/okd/http_files/* root@192.168.1.1:/usr/local/http/
|
|
||||||
//
|
|
||||||
folder_to_serve: None,
|
|
||||||
// folder_to_serve: Some(Url::LocalFolder("./data/pxe/okd/http_files/".to_string())),
|
|
||||||
files: vec![
|
|
||||||
FileContent {
|
|
||||||
path: FilePath::Relative("boot.ipxe".to_string()),
|
|
||||||
content: BootIpxeTpl { gateway_ip }.to_string(),
|
|
||||||
},
|
|
||||||
FileContent {
|
|
||||||
path: FilePath::Relative(kickstart_filename.to_string()),
|
|
||||||
content: InventoryKickstartTpl {
|
|
||||||
gateway_ip,
|
|
||||||
harmony_inventory_agent,
|
|
||||||
cluster_pubkey_filename,
|
|
||||||
}
|
|
||||||
.to_string(),
|
|
||||||
},
|
|
||||||
FileContent {
|
|
||||||
path: FilePath::Relative("fallback.ipxe".to_string()),
|
|
||||||
content: FallbackIpxeTpl {
|
|
||||||
gateway_ip,
|
|
||||||
kickstart_filename,
|
|
||||||
}
|
|
||||||
.to_string(),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
];
|
|
||||||
|
|
||||||
harmony_cli::run(inventory, topology, scores, None)
|
harmony_cli::run(inventory, topology, vec![Box::new(ipxe_score)], None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Template)]
|
|
||||||
#[template(path = "boot.ipxe.j2")]
|
|
||||||
struct BootIpxeTpl<'a> {
|
|
||||||
gateway_ip: &'a IpAddr,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Template)]
|
|
||||||
#[template(path = "fallback.ipxe.j2")]
|
|
||||||
struct FallbackIpxeTpl<'a> {
|
|
||||||
gateway_ip: &'a IpAddr,
|
|
||||||
kickstart_filename: &'a str,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Template)]
|
|
||||||
#[template(path = "inventory.kickstart.j2")]
|
|
||||||
struct InventoryKickstartTpl<'a> {
|
|
||||||
gateway_ip: &'a IpAddr,
|
|
||||||
cluster_pubkey_filename: &'a str,
|
|
||||||
harmony_inventory_agent: &'a str,
|
|
||||||
}
|
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
use std::{net::IpAddr, sync::Arc};
|
|
||||||
|
|
||||||
use cidr::Ipv4Cidr;
|
use cidr::Ipv4Cidr;
|
||||||
use harmony::{
|
use harmony::{
|
||||||
hardware::{FirewallGroup, HostCategory, Location, PhysicalHost, SwitchGroup},
|
hardware::{FirewallGroup, HostCategory, Location, PhysicalHost, SwitchGroup},
|
||||||
@ -10,6 +8,7 @@ use harmony::{
|
|||||||
use harmony_macros::{ip, ipv4};
|
use harmony_macros::{ip, ipv4};
|
||||||
use harmony_secret::{Secret, SecretManager};
|
use harmony_secret::{Secret, SecretManager};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::{net::IpAddr, sync::Arc};
|
||||||
|
|
||||||
#[derive(Secret, Serialize, Deserialize, Debug, PartialEq)]
|
#[derive(Secret, Serialize, Deserialize, Debug, PartialEq)]
|
||||||
struct OPNSenseFirewallConfig {
|
struct OPNSenseFirewallConfig {
|
||||||
|
@ -69,6 +69,7 @@ base64.workspace = true
|
|||||||
once_cell = "1.21.3"
|
once_cell = "1.21.3"
|
||||||
harmony_inventory_agent = { path = "../harmony_inventory_agent" }
|
harmony_inventory_agent = { path = "../harmony_inventory_agent" }
|
||||||
harmony_secret_derive = { version = "0.1.0", path = "../harmony_secret_derive" }
|
harmony_secret_derive = { version = "0.1.0", path = "../harmony_secret_derive" }
|
||||||
|
askama = "0.14.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
pretty_assertions.workspace = true
|
pretty_assertions.workspace = true
|
||||||
|
148
harmony/src/modules/okd/ipxe.rs
Normal file
148
harmony/src/modules/okd/ipxe.rs
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
use askama::Template;
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use derive_new::new;
|
||||||
|
use serde::Serialize;
|
||||||
|
use std::net::IpAddr;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
data::{FileContent, FilePath, Id, Version},
|
||||||
|
interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome},
|
||||||
|
inventory::Inventory,
|
||||||
|
modules::{dhcp::DhcpScore, http::StaticFilesHttpScore, tftp::TftpScore},
|
||||||
|
score::Score,
|
||||||
|
topology::{DhcpServer, HttpServer, Router, TftpServer, Topology, Url},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, new, Clone, Serialize)]
|
||||||
|
pub struct OkdIpxeScore {
|
||||||
|
pub kickstart_filename: String,
|
||||||
|
pub harmony_inventory_agent: String,
|
||||||
|
pub cluster_pubkey_filename: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Topology + DhcpServer + TftpServer + HttpServer + Router> Score<T> for OkdIpxeScore {
|
||||||
|
fn create_interpret(&self) -> Box<dyn Interpret<T>> {
|
||||||
|
Box::new(IpxeInterpret::new(self.clone()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn name(&self) -> String {
|
||||||
|
"OkdIpxeScore".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, new, Clone)]
|
||||||
|
pub struct IpxeInterpret {
|
||||||
|
score: OkdIpxeScore,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl<T: Topology + DhcpServer + TftpServer + HttpServer + Router> Interpret<T> for IpxeInterpret {
|
||||||
|
async fn execute(
|
||||||
|
&self,
|
||||||
|
inventory: &Inventory,
|
||||||
|
topology: &T,
|
||||||
|
) -> Result<Outcome, InterpretError> {
|
||||||
|
let gateway_ip = topology.get_gateway();
|
||||||
|
|
||||||
|
let scores: Vec<Box<dyn Score<T>>> = vec![
|
||||||
|
Box::new(DhcpScore {
|
||||||
|
host_binding: vec![],
|
||||||
|
next_server: Some(topology.get_gateway()),
|
||||||
|
boot_filename: None,
|
||||||
|
filename: Some("undionly.kpxe".to_string()),
|
||||||
|
filename64: Some("ipxe.efi".to_string()),
|
||||||
|
filenameipxe: Some(format!("http://{gateway_ip}:8080/boot.ipxe").to_string()),
|
||||||
|
}),
|
||||||
|
Box::new(TftpScore {
|
||||||
|
files_to_serve: Url::LocalFolder("./data/pxe/okd/tftpboot/".to_string()),
|
||||||
|
}),
|
||||||
|
Box::new(StaticFilesHttpScore {
|
||||||
|
// TODO The current russh based copy is way too slow, check for a lib update or use scp
|
||||||
|
// when available
|
||||||
|
//
|
||||||
|
// For now just run :
|
||||||
|
// scp -r data/pxe/okd/http_files/* root@192.168.1.1:/usr/local/http/
|
||||||
|
//
|
||||||
|
folder_to_serve: None,
|
||||||
|
// folder_to_serve: Some(Url::LocalFolder("./data/pxe/okd/http_files/".to_string())),
|
||||||
|
files: vec![
|
||||||
|
FileContent {
|
||||||
|
path: FilePath::Relative("boot.ipxe".to_string()),
|
||||||
|
content: BootIpxeTpl {
|
||||||
|
gateway_ip: &gateway_ip,
|
||||||
|
}
|
||||||
|
.to_string(),
|
||||||
|
},
|
||||||
|
FileContent {
|
||||||
|
path: FilePath::Relative(self.score.kickstart_filename.clone()),
|
||||||
|
content: InventoryKickstartTpl {
|
||||||
|
gateway_ip: &gateway_ip,
|
||||||
|
harmony_inventory_agent: &self.score.harmony_inventory_agent,
|
||||||
|
cluster_pubkey_filename: &self.score.cluster_pubkey_filename,
|
||||||
|
}
|
||||||
|
.to_string(),
|
||||||
|
},
|
||||||
|
FileContent {
|
||||||
|
path: FilePath::Relative("fallback.ipxe".to_string()),
|
||||||
|
content: FallbackIpxeTpl {
|
||||||
|
gateway_ip: &gateway_ip,
|
||||||
|
kickstart_filename: &self.score.kickstart_filename,
|
||||||
|
}
|
||||||
|
.to_string(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
|
||||||
|
for score in scores {
|
||||||
|
let result = score.interpret(inventory, topology).await;
|
||||||
|
match result {
|
||||||
|
Ok(outcome) => match outcome.status {
|
||||||
|
InterpretStatus::SUCCESS => continue,
|
||||||
|
InterpretStatus::NOOP => continue,
|
||||||
|
_ => return Err(InterpretError::new(outcome.message)),
|
||||||
|
},
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Outcome::success("Ipxe installed".to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_name(&self) -> InterpretName {
|
||||||
|
InterpretName::Ipxe
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_version(&self) -> Version {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_status(&self) -> InterpretStatus {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_children(&self) -> Vec<Id> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Template)]
|
||||||
|
#[template(path = "boot.ipxe.j2")]
|
||||||
|
struct BootIpxeTpl<'a> {
|
||||||
|
gateway_ip: &'a IpAddr,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Template)]
|
||||||
|
#[template(path = "fallback.ipxe.j2")]
|
||||||
|
struct FallbackIpxeTpl<'a> {
|
||||||
|
gateway_ip: &'a IpAddr,
|
||||||
|
kickstart_filename: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Template)]
|
||||||
|
#[template(path = "inventory.kickstart.j2")]
|
||||||
|
struct InventoryKickstartTpl<'a> {
|
||||||
|
gateway_ip: &'a IpAddr,
|
||||||
|
cluster_pubkey_filename: &'a str,
|
||||||
|
harmony_inventory_agent: &'a str,
|
||||||
|
}
|
@ -2,5 +2,6 @@ pub mod bootstrap_dhcp;
|
|||||||
pub mod bootstrap_load_balancer;
|
pub mod bootstrap_load_balancer;
|
||||||
pub mod dhcp;
|
pub mod dhcp;
|
||||||
pub mod dns;
|
pub mod dns;
|
||||||
|
pub mod ipxe;
|
||||||
pub mod load_balancer;
|
pub mod load_balancer;
|
||||||
pub mod upgrade;
|
pub mod upgrade;
|
||||||
|
Loading…
Reference in New Issue
Block a user