use uuid::Uuid;
const NAMESPACE_BYTES: &[u8] = b"node-hardware-id";
pub fn get_hardware_uuid() -> Uuid {
match machine_uid::get() {
Ok(machine_id) => {
match Uuid::parse_str(&machine_id) {
Ok(uuid) => {
tracing::debug!(
machine_id = %machine_id,
node_uuid = %uuid,
"Using hardware UUID"
);
uuid
}
Err(parse_err) => {
tracing::warn!(
machine_id = %machine_id,
error = %parse_err,
"Machine ID is not a valid UUID, using hash-based UUID"
);
let combined = [NAMESPACE_BYTES, b":", machine_id.as_bytes()].concat();
Uuid::new_v5(&uuid::Uuid::NAMESPACE_DNS, &combined)
}
}
}
Err(e) => {
let random_uuid = Uuid::new_v4();
let random_bytes = random_uuid.as_bytes();
let hybrid_bytes = [
0,
0,
0,
0,
0,
0,
0,
0, random_bytes[8],
random_bytes[9],
random_bytes[10],
random_bytes[11],
random_bytes[12],
random_bytes[13],
random_bytes[14],
random_bytes[15],
];
let hybrid_uuid = Uuid::from_bytes(hybrid_bytes);
tracing::error!(
error = %e,
fallback_uuid = %hybrid_uuid,
"Failed to get hardware machine ID, using hybrid UUID (00000000-0000-0000-xxxx-xxxxxxxxxxxx)"
);
hybrid_uuid
}
}
}
#[cfg(test)]
#[cfg_attr(coverage_nightly, coverage(off))]
mod tests {
use super::*;
#[test]
fn test_hardware_uuid_is_consistent() {
let uuid1 = get_hardware_uuid();
let uuid2 = get_hardware_uuid();
assert_eq!(uuid1, uuid2, "Hardware UUID should be consistent");
}
#[test]
fn test_hardware_uuid_format() {
let uuid = get_hardware_uuid();
let uuid_bytes = uuid.as_bytes();
let is_fallback = uuid_bytes[0..8].iter().all(|&b| b == 0);
if is_fallback {
let right_part_all_zeros = uuid_bytes[8..16].iter().all(|&b| b == 0);
assert!(
!right_part_all_zeros,
"Fallback UUID should have random right part"
);
} else {
assert!(
!is_fallback,
"Real hardware should not produce fallback UUID"
);
}
}
}