tests: Add initial support of CVM test on MSHV

This patch adds the skeleton of the CVM test
support and modify existing scripts and test framework
to enable such scenario. Split the sha1sum to support both
regular and CVM guest. Add one test case for CVM. Will further
add more test cases.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
This commit is contained in:
Muminul Islam
2025-10-17 20:03:41 -07:00
committed by Rob Bradford
parent f391a37a35
commit 258f826027
13 changed files with 155 additions and 12 deletions

View File

@@ -18,6 +18,7 @@ use std::str::FromStr;
use std::time::Duration;
use std::{env, fmt, fs, io, thread};
use rand::RngCore;
use serde_json::Value;
use ssh2::Session;
use thiserror::Error;
@@ -75,6 +76,7 @@ pub struct GuestNetworkConfig {
pub const DEFAULT_TCP_LISTENER_MESSAGE: &str = "booted";
pub const DEFAULT_TCP_LISTENER_PORT: u16 = 8000;
pub const DEFAULT_TCP_LISTENER_TIMEOUT: u32 = 120;
pub const DEFAULT_CVM_TCP_LISTENER_TIMEOUT: u32 = 120;
#[derive(Error, Debug)]
pub enum WaitForBootError {
@@ -891,6 +893,7 @@ pub struct Guest {
pub boot_timeout: u32,
pub kernel_path: Option<String>,
pub kernel_cmdline: Option<String>,
pub console_type: Option<String>,
}
// Return the next id that can be used for this guest. This is stored in a
@@ -959,6 +962,7 @@ impl Guest {
boot_timeout: DEFAULT_TCP_LISTENER_TIMEOUT,
kernel_path: None,
kernel_cmdline: None,
console_type: None,
}
}
@@ -1481,8 +1485,20 @@ impl<'a> GuestCommand<'a> {
}
pub fn default_kernel_cmdline(&mut self) -> &mut Self {
if let Some(kernel) = &self.guest.kernel_path {
self.command.args(["--kernel", kernel]);
if self.guest.vm_type == GuestVmType::Confidential {
let console_str = if let Some(c) = &self.guest.console_type {
c.as_str()
} else {
"hvc0"
};
let igvm = direct_igvm_boot_path(Some(console_str))
.expect("IGVM boot file not found for console type: {console_str}");
self.command.args(["--igvm", igvm.to_str().unwrap()]);
self.command
.args(["--host-data", generate_host_data().as_str()]);
self.command.args(["--platform", "sev_snp=on"]);
} else if let Some(kernel) = &self.guest.kernel_path {
self.command.args(["--kernel", kernel.as_str()]);
if let Some(cmdline) = &self.guest.kernel_cmdline {
self.command.args(["--cmdline", cmdline]);
}
@@ -1893,3 +1909,27 @@ pub enum GuestVmType {
Regular,
Confidential,
}
// Get the direct igvm boot file path based on the console type
fn direct_igvm_boot_path(console: Option<&str>) -> Option<PathBuf> {
// get the default hvc0 igvm file if console string is not passed
let console_str = console.unwrap_or("hvc0");
if console_str != "hvc0" && console_str != "ttyS0" {
panic!("IGVM console should be hvc0 or ttyS0, got: {console_str}");
}
let igvm_filepath = format!("/igvm_files/linux-{console_str}.bin");
if Path::new(&igvm_filepath).exists() {
Some(PathBuf::from(igvm_filepath))
} else {
None
}
}
// Generate a random 64-character hex string for host data
fn generate_host_data() -> String {
let mut bytes = [0u8; 32];
rand::rng().fill_bytes(&mut bytes);
bytes.iter().map(|b| format!("{b:02x}")).collect()
}