fix: Dhcp static hostname has to have domain specified with dnsmasq, also progress on okd installation automation
Some checks failed
Run Check Script / check (pull_request) Failing after 32s
Some checks failed
Run Check Script / check (pull_request) Failing after 32s
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum DhcpError {
|
||||
InvalidMacAddress(String),
|
||||
InvalidIpAddress(String),
|
||||
|
||||
@@ -69,9 +69,9 @@ impl<'a> DhcpConfigDnsMasq<'a> {
|
||||
/// This function implements specific logic to handle existing entries:
|
||||
/// - If no host exists for the given IP or hostname, a new entry is created.
|
||||
/// - If exactly one host exists for the IP and/or hostname, the new MAC is appended to it.
|
||||
/// - It will panic if the IP and hostname exist but point to two different host entries,
|
||||
/// - It will error if the IP and hostname exist but point to two different host entries,
|
||||
/// as this represents an unresolvable conflict.
|
||||
/// - It will also panic if multiple entries are found for the IP or hostname, indicating an
|
||||
/// - It will also error if multiple entries are found for the IP or hostname, indicating an
|
||||
/// ambiguous state.
|
||||
pub fn add_static_mapping(
|
||||
&mut self,
|
||||
@@ -79,6 +79,10 @@ impl<'a> DhcpConfigDnsMasq<'a> {
|
||||
ipaddr: Ipv4Addr,
|
||||
hostname: &str,
|
||||
) -> Result<(), DhcpError> {
|
||||
let mut hostname_split = hostname.split(".");
|
||||
let hostname = hostname_split.next().expect("hostname cannot be empty");
|
||||
let domain_name = hostname_split.collect::<Vec<&str>>().join(".");
|
||||
|
||||
if !Self::is_valid_mac(mac) {
|
||||
return Err(DhcpError::InvalidMacAddress(mac.to_string()));
|
||||
}
|
||||
@@ -107,10 +111,10 @@ impl<'a> DhcpConfigDnsMasq<'a> {
|
||||
&& !hostname_indices.is_empty()
|
||||
&& ip_set.intersection(&hostname_set).count() == 0
|
||||
{
|
||||
panic!(
|
||||
return Err(DhcpError::Configuration(format!(
|
||||
"Configuration conflict: IP {} and hostname '{}' exist, but in different static host entries.",
|
||||
ipaddr, hostname
|
||||
);
|
||||
)));
|
||||
}
|
||||
|
||||
let mut all_indices: Vec<&usize> = ip_set.union(&hostname_set).collect();
|
||||
@@ -129,6 +133,7 @@ impl<'a> DhcpConfigDnsMasq<'a> {
|
||||
hwaddr: mac.to_string().into(),
|
||||
local: MaybeString::from("1"),
|
||||
ignore: Some(0),
|
||||
domain: domain_name.into(),
|
||||
..Default::default()
|
||||
};
|
||||
hosts.push(new_host);
|
||||
@@ -162,7 +167,7 @@ impl<'a> DhcpConfigDnsMasq<'a> {
|
||||
let mut updated_macs = host_to_modify.hwaddr.content_string().to_string();
|
||||
updated_macs.push(',');
|
||||
updated_macs.push_str(mac);
|
||||
host_to_modify.hwaddr = updated_macs.into();
|
||||
host_to_modify.hwaddr.content = updated_macs.into();
|
||||
} else {
|
||||
info!(
|
||||
"MAC {} already present in static host entry for {} ({}). No changes made.",
|
||||
@@ -171,10 +176,10 @@ impl<'a> DhcpConfigDnsMasq<'a> {
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
panic!(
|
||||
return Err(DhcpError::Configuration(format!(
|
||||
"Configuration conflict: Found multiple host entries matching IP {} and/or hostname '{}'. Cannot resolve automatically.",
|
||||
ipaddr, hostname
|
||||
);
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,8 +207,11 @@ impl<'a> DhcpConfigDnsMasq<'a> {
|
||||
.exec("configctl dhcpd list static")
|
||||
.await?;
|
||||
|
||||
let value: serde_json::Value = serde_json::from_str(&list_static_output)
|
||||
.unwrap_or_else(|_| panic!("Got invalid json from configctl {list_static_output}"));
|
||||
let value: serde_json::Value = serde_json::from_str(&list_static_output).map_err(|e| {
|
||||
Error::Command(format!(
|
||||
"Got invalid json from configctl {list_static_output} : {e}"
|
||||
))
|
||||
})?;
|
||||
|
||||
// The JSON output key might be 'dhcpd' even when dnsmasq is the backend.
|
||||
let static_maps = value["dhcpd"]
|
||||
@@ -358,6 +366,28 @@ mod test {
|
||||
assert!(Uuid::parse_str(&host.uuid).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hostname_split_into_host_domain() {
|
||||
let mut dhcp_config = setup_test_env(vec![]);
|
||||
let ip = Ipv4Addr::new(192, 168, 1, 10);
|
||||
let mac = "00:11:22:33:44:55";
|
||||
let hostname = "new-host";
|
||||
let domain = "some.domain";
|
||||
|
||||
dhcp_config
|
||||
.add_static_mapping(mac, ip, &format!("{hostname}.{domain}"))
|
||||
.unwrap();
|
||||
|
||||
let hosts = &dhcp_config.opnsense.dnsmasq.as_ref().unwrap().hosts;
|
||||
assert_eq!(hosts.len(), 1);
|
||||
let host = &hosts[0];
|
||||
assert_eq!(host.host, hostname);
|
||||
assert_eq!(host.domain.content_string(), domain);
|
||||
assert_eq!(host.ip, ip.to_string().into());
|
||||
assert_eq!(host.hwaddr.content_string(), mac);
|
||||
assert!(Uuid::parse_str(&host.uuid).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add_mac_to_existing_host_by_ip_and_hostname() {
|
||||
let initial_host = create_host(
|
||||
@@ -462,41 +492,33 @@ mod test {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(
|
||||
expected = "Configuration conflict: IP 192.168.1.10 and hostname 'host-b' exist, but in different static host entries."
|
||||
)]
|
||||
fn test_panic_on_conflicting_ip_and_hostname() {
|
||||
fn test_error_on_conflicting_ip_and_hostname() {
|
||||
let host_a = create_host("uuid-a", "host-a", "192.168.1.10", "AA:AA:AA:AA:AA:AA");
|
||||
let host_b = create_host("uuid-b", "host-b", "192.168.1.20", "BB:BB:BB:BB:BB:BB");
|
||||
let mut dhcp_config = setup_test_env(vec![host_a, host_b]);
|
||||
|
||||
let result = dhcp_config.add_static_mapping(
|
||||
"CC:CC:CC:CC:CC:CC",
|
||||
Ipv4Addr::new(192, 168, 1, 10),
|
||||
"host-b",
|
||||
);
|
||||
// This IP belongs to host-a, but the hostname belongs to host-b.
|
||||
dhcp_config
|
||||
.add_static_mapping(
|
||||
"CC:CC:CC:CC:CC:CC",
|
||||
Ipv4Addr::new(192, 168, 1, 10),
|
||||
"host-b",
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(result, Err(DhcpError::Configuration("Configuration conflict: IP 192.168.1.10 and hostname 'host-b' exist, but in different static host entries.".to_string())));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(
|
||||
expected = "Configuration conflict: Found multiple host entries matching IP 192.168.1.30 and/or hostname 'new-host'."
|
||||
)]
|
||||
fn test_panic_on_multiple_ip_matches() {
|
||||
fn test_error_on_multiple_ip_matches() {
|
||||
let host_a = create_host("uuid-a", "host-a", "192.168.1.30", "AA:AA:AA:AA:AA:AA");
|
||||
let host_b = create_host("uuid-b", "host-b", "192.168.1.30", "BB:BB:BB:BB:BB:BB");
|
||||
let mut dhcp_config = setup_test_env(vec![host_a, host_b]);
|
||||
|
||||
// This IP is ambiguous.
|
||||
dhcp_config
|
||||
.add_static_mapping(
|
||||
"CC:CC:CC:CC:CC:CC",
|
||||
Ipv4Addr::new(192, 168, 1, 30),
|
||||
"new-host",
|
||||
)
|
||||
.unwrap();
|
||||
let result = dhcp_config.add_static_mapping(
|
||||
"CC:CC:CC:CC:CC:CC",
|
||||
Ipv4Addr::new(192, 168, 1, 30),
|
||||
"new-host",
|
||||
);
|
||||
assert_eq!(result, Err(DhcpError::Configuration("Configuration conflict: Found multiple host entries matching IP 192.168.1.30 and/or hostname 'new-host'. Cannot resolve automatically.".to_string())));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user