From 3f77bc7aefe59024583e22731817fa3e84d0bcdf Mon Sep 17 00:00:00 2001 From: Sylvain Tremblay Date: Sat, 1 Mar 2025 08:56:41 -0500 Subject: [PATCH] feat: support new configurable field in dhcp config: filename --- harmony/src/domain/topology/ha_cluster.rs | 3 +++ harmony/src/domain/topology/network.rs | 1 + harmony/src/infra/opnsense/dhcp.rs | 10 ++++++++++ harmony/src/modules/dhcp.rs | 19 +++++++++++++++++-- harmony/src/modules/okd/bootstrap_dhcp.rs | 2 ++ harmony/src/modules/okd/dhcp.rs | 4 +++- opnsense-config-xml/src/data/dhcpd.rs | 1 + opnsense-config/src/modules/dhcp.rs | 16 +++++++++++++++- 8 files changed, 52 insertions(+), 4 deletions(-) diff --git a/harmony/src/domain/topology/ha_cluster.rs b/harmony/src/domain/topology/ha_cluster.rs index ba7c063..5ceaa8a 100644 --- a/harmony/src/domain/topology/ha_cluster.rs +++ b/harmony/src/domain/topology/ha_cluster.rs @@ -121,6 +121,9 @@ impl DhcpServer for DummyInfra { async fn set_boot_filename(&self, _boot_filename: &str) -> Result<(), ExecutorError> { unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA) } + async fn set_filename(&self, _filename: &str) -> Result<(), ExecutorError> { + unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA) + } fn get_ip(&self) -> IpAddress { unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA) } diff --git a/harmony/src/domain/topology/network.rs b/harmony/src/domain/topology/network.rs index f45c87d..cd013be 100644 --- a/harmony/src/domain/topology/network.rs +++ b/harmony/src/domain/topology/network.rs @@ -48,6 +48,7 @@ pub trait DhcpServer: Send + Sync { async fn list_static_mappings(&self) -> Vec<(MacAddress, IpAddress)>; async fn set_next_server(&self, ip: IpAddress) -> Result<(), ExecutorError>; async fn set_boot_filename(&self, boot_filename: &str) -> Result<(), ExecutorError>; + async fn set_filename(&self, filename: &str) -> Result<(), ExecutorError>; fn get_ip(&self) -> IpAddress; fn get_host(&self) -> LogicalHost; async fn commit_config(&self) -> Result<(), ExecutorError>; diff --git a/harmony/src/infra/opnsense/dhcp.rs b/harmony/src/infra/opnsense/dhcp.rs index 028921f..6fd0be4 100644 --- a/harmony/src/infra/opnsense/dhcp.rs +++ b/harmony/src/infra/opnsense/dhcp.rs @@ -69,4 +69,14 @@ impl DhcpServer for OPNSenseFirewall { Ok(()) } + + async fn set_filename(&self, filename: &str) -> Result<(), ExecutorError> { + { + let mut writable_opnsense = self.opnsense_config.write().await; + writable_opnsense.dhcp().set_filename(filename); + debug!("OPNsense dhcp server set filename {filename}"); + } + + Ok(()) + } } diff --git a/harmony/src/modules/dhcp.rs b/harmony/src/modules/dhcp.rs index 604d624..f4b5472 100644 --- a/harmony/src/modules/dhcp.rs +++ b/harmony/src/modules/dhcp.rs @@ -18,6 +18,8 @@ pub struct DhcpScore { pub host_binding: Vec, pub next_server: Option, pub boot_filename: Option, + pub filename: Option, + pub filename_ipxe: Option, } impl Score for DhcpScore { @@ -125,8 +127,21 @@ impl DhcpInterpret { None => Outcome::noop(), }; + let filename_outcome = match &self.score.filename { + Some(filename) => { + let dhcp_server = Arc::new(topology.dhcp_server.clone()); + dhcp_server.set_filename(&filename).await?; + Outcome::new( + InterpretStatus::SUCCESS, + format!("Dhcp Interpret Set filename to {filename}"), + ) + } + None => Outcome::noop(), + }; + if next_server_outcome.status == InterpretStatus::NOOP && boot_filename_outcome.status == InterpretStatus::NOOP + && filename_outcome.status == InterpretStatus::NOOP { return Ok(Outcome::noop()); } @@ -134,8 +149,8 @@ impl DhcpInterpret { Ok(Outcome::new( InterpretStatus::SUCCESS, format!( - "Dhcp Interpret Set next boot to {:?} and boot_filename to {:?}", - self.score.boot_filename, self.score.boot_filename + "Dhcp Interpret Set next boot to [{:?}], boot_filename to [{:?}], filename to [{:?}]", + self.score.boot_filename, self.score.boot_filename, self.score.filename ), )) } diff --git a/harmony/src/modules/okd/bootstrap_dhcp.rs b/harmony/src/modules/okd/bootstrap_dhcp.rs index 4f5c6ee..e9e74c8 100644 --- a/harmony/src/modules/okd/bootstrap_dhcp.rs +++ b/harmony/src/modules/okd/bootstrap_dhcp.rs @@ -41,6 +41,8 @@ impl OKDBootstrapDhcpScore { // router address, this is leaking implementation details Some(topology.router.get_gateway()), Some("bootx64.efi".to_string()), + Some(format!("{}:8080/boot.ipxe", topology.router.get_gateway())), + Some("undionly.kpxe".to_string()), ), } } diff --git a/harmony/src/modules/okd/dhcp.rs b/harmony/src/modules/okd/dhcp.rs index c976f8d..e5cd346 100644 --- a/harmony/src/modules/okd/dhcp.rs +++ b/harmony/src/modules/okd/dhcp.rs @@ -32,7 +32,9 @@ impl OKDDhcpScore { dhcp_score: DhcpScore { host_binding, next_server: Some(topology.router.get_gateway()), - boot_filename: Some("bootx64.efi".to_string()), + boot_filename: None, + filename_ipxe: Some(format!("{}:8080/boot.ipxe", topology.router.get_gateway())), + filename: Some("undionly.kpxe".to_string()), }, } } diff --git a/opnsense-config-xml/src/data/dhcpd.rs b/opnsense-config-xml/src/data/dhcpd.rs index a8baa76..4cb47d0 100644 --- a/opnsense-config-xml/src/data/dhcpd.rs +++ b/opnsense-config-xml/src/data/dhcpd.rs @@ -22,6 +22,7 @@ pub struct DhcpInterface { pub nextserver: Option, pub filename64: Option, pub filename: Option, + pub filenameipxe: Option, #[yaserde(rename = "ddnsdomainalgorithm")] pub ddns_domain_algorithm: Option, #[yaserde(rename = "numberoptions")] diff --git a/opnsense-config/src/modules/dhcp.rs b/opnsense-config/src/modules/dhcp.rs index 2c06304..3ab9ba1 100644 --- a/opnsense-config/src/modules/dhcp.rs +++ b/opnsense-config/src/modules/dhcp.rs @@ -179,7 +179,21 @@ impl<'a> DhcpConfig<'a> { pub fn set_boot_filename(&mut self, boot_filename: &str) { self.enable_netboot(); - self.get_lan_dhcpd().filename64 = Some(boot_filename.to_string()); self.get_lan_dhcpd().bootfilename = Some(boot_filename.to_string()); } + + pub fn set_filename(&mut self, filename: &str) { + self.enable_netboot(); + self.get_lan_dhcpd().filename = Some(filename.to_string()); + } + + pub fn set_filename64(&mut self, filename64: &str) { + self.enable_netboot(); + self.get_lan_dhcpd().filename64 = Some(filename64.to_string()); + } + + pub fn set_filenameipxe(&mut self, filenameipxe: &str) { + self.enable_netboot(); + self.get_lan_dhcpd().filenameipxe = Some(filenameipxe.to_string()); + } }