tests: Test OVMF with Linux guest

Extending the test_simple_launch() integration test to validate Cloud
Hypervisor boots correctly with both rust-hypervisor-fw and OVMF on
x86_64 platforms.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
Sebastien Boeuf 2021-12-03 18:17:23 +01:00
parent 7bb343dce8
commit cab0b3446f
3 changed files with 91 additions and 34 deletions

42
Jenkinsfile vendored
View File

@ -25,12 +25,26 @@ pipeline{
parallel { parallel {
stage ('Worker build') { stage ('Worker build') {
agent { node { label 'impish' } } agent { node { label 'impish' } }
environment {
AZURE_CONNECTION_STRING = credentials('46b4e7d6-315f-4cc1-8333-b58780863b9b')
}
stages { stages {
stage ('Checkout') { stage ('Checkout') {
steps { steps {
checkout scm checkout scm
} }
} }
stage ('Install azure-cli') {
steps {
installAzureCli()
}
}
stage ('Download assets') {
steps {
sh "mkdir ${env.HOME}/workloads"
sh 'az storage blob download --container-name private-images --file "$HOME/workloads/OVMF-83041af43c.fd" --name OVMF-83041af43c.fd --connection-string "$AZURE_CONNECTION_STRING"'
}
}
stage ('Run OpenAPI tests') { stage ('Run OpenAPI tests') {
steps { steps {
sh "scripts/run_openapi_tests.sh" sh "scripts/run_openapi_tests.sh"
@ -84,12 +98,26 @@ pipeline{
} }
stage ('Worker build (musl)') { stage ('Worker build (musl)') {
agent { node { label 'impish' } } agent { node { label 'impish' } }
environment {
AZURE_CONNECTION_STRING = credentials('46b4e7d6-315f-4cc1-8333-b58780863b9b')
}
stages { stages {
stage ('Checkout') { stage ('Checkout') {
steps { steps {
checkout scm checkout scm
} }
} }
stage ('Install azure-cli') {
steps {
installAzureCli()
}
}
stage ('Download assets') {
steps {
sh "mkdir ${env.HOME}/workloads"
sh 'az storage blob download --container-name private-images --file "$HOME/workloads/OVMF-83041af43c.fd" --name OVMF-83041af43c.fd --connection-string "$AZURE_CONNECTION_STRING"'
}
}
stage ('Run unit tests for musl') { stage ('Run unit tests for musl') {
steps { steps {
sh "scripts/dev_cli.sh tests --unit --libc musl" sh "scripts/dev_cli.sh tests --unit --libc musl"
@ -191,11 +219,7 @@ pipeline{
} }
stage ('Install azure-cli') { stage ('Install azure-cli') {
steps { steps {
sh "sudo apt install -y ca-certificates curl apt-transport-https lsb-release gnupg" installAzureCli()
sh "curl -sL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/microsoft.gpg > /dev/null"
sh "echo \"deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ hirsute main\" | sudo tee /etc/apt/sources.list.d/azure-cli.list"
sh "sudo apt update"
sh "sudo apt install -y azure-cli"
} }
} }
stage ('Download assets') { stage ('Download assets') {
@ -286,3 +310,11 @@ def cancelPreviousBuilds() {
} }
} }
} }
def installAzureCli() {
sh "sudo apt install -y ca-certificates curl apt-transport-https lsb-release gnupg"
sh "curl -sL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/microsoft.gpg > /dev/null"
sh "echo \"deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ hirsute main\" | sudo tee /etc/apt/sources.list.d/azure-cli.list"
sh "sudo apt update"
sh "sudo apt install -y azure-cli"
}

View File

@ -138,6 +138,7 @@ pub trait DiskConfig {
fn disk(&self, disk_type: DiskType) -> Option<String>; fn disk(&self, disk_type: DiskType) -> Option<String>;
} }
#[derive(Clone)]
pub struct UbuntuDiskConfig { pub struct UbuntuDiskConfig {
osdisk_path: String, osdisk_path: String,
cloudinit_path: String, cloudinit_path: String,

View File

@ -480,10 +480,13 @@ mod tests {
} }
} }
impl Guest { enum FwType {
fn new_from_ip_range(mut disk_config: Box<dyn DiskConfig>, class: &str, id: u8) -> Self { Ovmf,
let tmp_dir = TempDir::new_with_prefix("/tmp/ch").unwrap(); RustHypervisorFirmware,
}
impl Guest {
fn fw_path(fw_type: FwType) -> String {
let mut workload_path = dirs::home_dir().unwrap(); let mut workload_path = dirs::home_dir().unwrap();
workload_path.push("workloads"); workload_path.push("workloads");
@ -491,8 +494,19 @@ mod tests {
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
fw_path.push("CLOUDHV_EFI.fd"); fw_path.push("CLOUDHV_EFI.fd");
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
fw_path.push("hypervisor-fw"); {
let fw_path = String::from(fw_path.to_str().unwrap()); match fw_type {
FwType::Ovmf => fw_path.push(OVMF_NAME),
FwType::RustHypervisorFirmware => fw_path.push("hypervisor-fw"),
}
}
fw_path.to_str().unwrap().to_string()
}
fn new_from_ip_range(mut disk_config: Box<dyn DiskConfig>, class: &str, id: u8) -> Self {
let tmp_dir = TempDir::new_with_prefix("/tmp/ch").unwrap();
let network = GuestNetworkConfig { let network = GuestNetworkConfig {
guest_ip: format!("{}.{}.2", class, id), guest_ip: format!("{}.{}.2", class, id),
l2_guest_ip1: format!("{}.{}.3", class, id), l2_guest_ip1: format!("{}.{}.3", class, id),
@ -511,7 +525,7 @@ mod tests {
Guest { Guest {
tmp_dir, tmp_dir,
disk_config, disk_config,
fw_path, fw_path: Self::fw_path(FwType::RustHypervisorFirmware),
network, network,
} }
} }
@ -2365,33 +2379,43 @@ mod tests {
vec![Box::new(bionic), Box::new(focal)] vec![Box::new(bionic), Box::new(focal)]
.drain(..) .drain(..)
.for_each(|disk_config| { .for_each(|disk_config| {
let guest = Guest::new(disk_config); vec![
Guest::fw_path(FwType::Ovmf),
Guest::fw_path(FwType::RustHypervisorFirmware),
]
.drain(..)
.for_each(|fw_path| {
let guest = Guest::new(disk_config.clone());
let mut child = GuestCommand::new(&guest) let mut child = GuestCommand::new(&guest)
.args(&["--cpus", "boot=1"]) .args(&["--cpus", "boot=1"])
.args(&["--memory", "size=512M"]) .args(&["--memory", "size=512M"])
.args(&["--kernel", guest.fw_path.as_str()]) .args(&["--kernel", fw_path.as_str()])
.default_disks() .default_disks()
.default_net() .default_net()
.args(&["--serial", "tty", "--console", "off"]) .args(&["--serial", "tty", "--console", "off"])
.capture_output() .capture_output()
.spawn() .spawn()
.unwrap(); .unwrap();
let r = std::panic::catch_unwind(|| { let r = std::panic::catch_unwind(|| {
guest.wait_vm_boot(Some(120)).unwrap(); guest.wait_vm_boot(Some(120)).unwrap();
assert_eq!(guest.get_cpu_count().unwrap_or_default(), 1); assert_eq!(guest.get_cpu_count().unwrap_or_default(), 1);
assert_eq!(guest.get_initial_apicid().unwrap_or(1), 0); assert_eq!(guest.get_initial_apicid().unwrap_or(1), 0);
assert!(guest.get_total_memory().unwrap_or_default() > 480_000); assert!(guest.get_total_memory().unwrap_or_default() > 480_000);
assert!(guest.get_entropy().unwrap_or_default() >= 900); assert!(guest.get_entropy().unwrap_or_default() >= 900);
assert_eq!(guest.get_pci_bridge_class().unwrap_or_default(), "0x060000"); assert_eq!(
guest.get_pci_bridge_class().unwrap_or_default(),
"0x060000"
);
});
let _ = child.kill();
let output = child.wait_with_output().unwrap();
handle_child_output(r, &output);
}); });
let _ = child.kill();
let output = child.wait_with_output().unwrap();
handle_child_output(r, &output);
}); });
} }