Skip to content

Commit d4e0a0b

Browse files
Copilotbenhillis
andcommitted
Implement VM name truncation to fix Hyper-V 100-character limit
Co-authored-by: benhillis <17727402+benhillis@users.noreply.github.com>
1 parent 1fb1e25 commit d4e0a0b

File tree

1 file changed

+78
-1
lines changed

1 file changed

+78
-1
lines changed

petri/src/vm/hyperv/mod.rs

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ pub mod powershell;
66
pub mod vm;
77
use vmsocket::VmAddress;
88
use vmsocket::VmSocket;
9+
use std::collections::hash_map::DefaultHasher;
10+
use std::hash::{Hash, Hasher};
911

1012
use super::ProcessorTopology;
1113
use crate::Firmware;
@@ -231,6 +233,33 @@ impl PetriVmArtifactsHyperV {
231233
}
232234

233235
impl PetriVmConfigHyperV {
236+
/// Creates a valid Hyper-V VM name from a test name.
237+
///
238+
/// Hyper-V limits VM names to 100 characters. If the test name exceeds this limit,
239+
/// we truncate it and append a hash to maintain uniqueness.
240+
fn create_vm_name(test_name: &str) -> String {
241+
const MAX_VM_NAME_LENGTH: usize = 100;
242+
243+
if test_name.len() <= MAX_VM_NAME_LENGTH {
244+
return test_name.to_owned();
245+
}
246+
247+
// Create a hash of the full name for uniqueness
248+
let mut hasher = DefaultHasher::new();
249+
test_name.hash(&mut hasher);
250+
let hash = hasher.finish();
251+
let hash_suffix = format!("-{:x}", hash);
252+
253+
// Reserve space for the hash suffix
254+
let max_prefix_length = MAX_VM_NAME_LENGTH - hash_suffix.len();
255+
256+
// Take the end of the test name to preserve the most specific part
257+
let start_pos = test_name.len().saturating_sub(max_prefix_length);
258+
let truncated = &test_name[start_pos..];
259+
260+
format!("{}{}", truncated, hash_suffix)
261+
}
262+
234263
/// Create a new Hyper-V petri VM config
235264
pub fn new(
236265
params: &PetriTestParams<'_>,
@@ -287,7 +316,7 @@ impl PetriVmConfigHyperV {
287316
let openhcl_igvm = igvm_artifact.cloned();
288317

289318
Ok(PetriVmConfigHyperV {
290-
name: params.test_name.to_owned(),
319+
name: Self::create_vm_name(params.test_name),
291320
arch,
292321
generation,
293322
guest_state_isolation_type,
@@ -778,3 +807,51 @@ fn acl_read_for_vm(path: &Path, id: Option<guid::Guid>) -> anyhow::Result<()> {
778807
}
779808
Ok(())
780809
}
810+
811+
#[cfg(test)]
812+
mod tests {
813+
use super::*;
814+
815+
#[test]
816+
fn test_create_vm_name() {
817+
// Test short names remain unchanged
818+
let short_name = "test::short_name";
819+
assert_eq!(PetriVmConfigHyperV::create_vm_name(short_name), short_name);
820+
821+
// Test long names are truncated to 100 characters
822+
let long_name = "multiarch::openhcl_servicing::hyperv_openhcl_uefi_aarch64_ubuntu_2404_server_aarch64_openhcl_servicing";
823+
let vm_name = PetriVmConfigHyperV::create_vm_name(long_name);
824+
assert!(vm_name.len() <= 100);
825+
assert!(vm_name.len() == 100); // Should be exactly 100 for this case
826+
827+
// Test different long names get different hashes
828+
let long_name2 = "multiarch::openhcl_servicing::hyperv_openhcl_uefi_aarch64_ubuntu_2404_server_aarch64_openhcl_different";
829+
let vm_name2 = PetriVmConfigHyperV::create_vm_name(long_name2);
830+
assert!(vm_name2.len() <= 100);
831+
assert_ne!(vm_name, vm_name2);
832+
833+
// Test the most specific part is preserved
834+
assert!(vm_name.contains("openhcl_servicing"));
835+
assert!(vm_name2.contains("openhcl_different"));
836+
}
837+
838+
#[test]
839+
fn test_vm_name_exactly_100_chars() {
840+
let exactly_100 = "a".repeat(100);
841+
let result = PetriVmConfigHyperV::create_vm_name(&exactly_100);
842+
assert_eq!(result, exactly_100);
843+
assert_eq!(result.len(), 100);
844+
}
845+
846+
#[test]
847+
fn test_vm_name_101_chars() {
848+
let exactly_101 = "a".repeat(101);
849+
let result = PetriVmConfigHyperV::create_vm_name(&exactly_101);
850+
assert_eq!(result.len(), 100);
851+
assert!(result.ends_with(&format!("-{:x}", {
852+
let mut hasher = DefaultHasher::new();
853+
exactly_101.hash(&mut hasher);
854+
hasher.finish()
855+
})));
856+
}
857+
}

0 commit comments

Comments
 (0)