2019-02-21 16:39:34 +00:00
|
|
|
// Copyright © 2019 Intel Corporation
|
|
|
|
//
|
|
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
//
|
|
|
|
|
2019-02-22 16:05:02 +00:00
|
|
|
extern crate vmm;
|
|
|
|
|
2019-02-21 16:39:34 +00:00
|
|
|
#[macro_use(crate_version, crate_authors)]
|
|
|
|
extern crate clap;
|
|
|
|
|
|
|
|
use clap::{App, Arg};
|
2019-05-23 19:48:05 +00:00
|
|
|
use std::process;
|
|
|
|
use vmm::config;
|
2019-03-07 13:56:43 +00:00
|
|
|
|
2019-02-21 16:04:44 +00:00
|
|
|
fn main() {
|
2019-02-21 16:39:34 +00:00
|
|
|
let cmd_arguments = App::new("cloud-hypervisor")
|
|
|
|
.version(crate_version!())
|
|
|
|
.author(crate_authors!())
|
|
|
|
.about("Launch a cloud-hypervisor VMM.")
|
2019-05-23 19:48:05 +00:00
|
|
|
.arg(
|
|
|
|
Arg::with_name("cpus")
|
|
|
|
.long("cpus")
|
|
|
|
.help("Number of virtual CPUs")
|
|
|
|
.default_value(config::DEFAULT_VCPUS),
|
|
|
|
)
|
|
|
|
.arg(
|
|
|
|
Arg::with_name("memory")
|
|
|
|
.long("memory")
|
2019-05-24 19:21:23 +00:00
|
|
|
.help(
|
|
|
|
"Memory parameters \"size=<guest_memory_size>,\
|
|
|
|
file=<backing_file_path>\"",
|
|
|
|
)
|
2019-05-23 19:48:05 +00:00
|
|
|
.default_value(config::DEFAULT_MEMORY),
|
|
|
|
)
|
2019-02-21 16:39:34 +00:00
|
|
|
.arg(
|
|
|
|
Arg::with_name("kernel")
|
|
|
|
.long("kernel")
|
|
|
|
.help("Path to kernel image (vmlinux)")
|
|
|
|
.takes_value(true),
|
|
|
|
)
|
2019-05-06 20:24:57 +00:00
|
|
|
.arg(
|
|
|
|
Arg::with_name("cmdline")
|
|
|
|
.long("cmdline")
|
|
|
|
.help("Kernel command line")
|
|
|
|
.takes_value(true),
|
|
|
|
)
|
2019-05-06 19:15:44 +00:00
|
|
|
.arg(
|
|
|
|
Arg::with_name("disk")
|
|
|
|
.long("disk")
|
|
|
|
.help("Path to VM disk image")
|
2019-05-22 13:56:22 +00:00
|
|
|
.takes_value(true)
|
|
|
|
.min_values(1),
|
2019-05-06 19:15:44 +00:00
|
|
|
)
|
2019-05-09 15:01:42 +00:00
|
|
|
.arg(
|
|
|
|
Arg::with_name("net")
|
|
|
|
.long("net")
|
2019-05-23 19:48:05 +00:00
|
|
|
.help(
|
|
|
|
"Network parameters \"tap=<if_name>,\
|
|
|
|
ip=<ip_addr>,mask=<net_mask>,mac=<mac_addr>\"",
|
|
|
|
)
|
2019-03-11 16:48:35 +00:00
|
|
|
.takes_value(true),
|
|
|
|
)
|
2019-05-09 05:01:48 +00:00
|
|
|
.arg(
|
|
|
|
Arg::with_name("rng")
|
|
|
|
.long("rng")
|
|
|
|
.help("Path to entropy source")
|
2019-05-23 19:48:05 +00:00
|
|
|
.default_value(config::DEFAULT_RNG_SOURCE),
|
2019-05-09 05:01:48 +00:00
|
|
|
)
|
2019-05-22 20:06:49 +00:00
|
|
|
.arg(
|
|
|
|
Arg::with_name("fs")
|
|
|
|
.long("fs")
|
|
|
|
.help(
|
|
|
|
"virtio-fs parameters \"tag=<tag_name>,\
|
|
|
|
sock=<socket_path>,num_queues=<number_of_queues>,\
|
|
|
|
queue_size=<size_of_each_queue>\"",
|
|
|
|
)
|
|
|
|
.takes_value(true),
|
|
|
|
)
|
2019-02-21 16:39:34 +00:00
|
|
|
.get_matches();
|
|
|
|
|
2019-05-23 19:48:05 +00:00
|
|
|
// These .unwrap()s cannot fail as there is a default value defined
|
|
|
|
let cpus = cmd_arguments.value_of("cpus").unwrap();
|
|
|
|
let memory = cmd_arguments.value_of("memory").unwrap();
|
|
|
|
|
|
|
|
let kernel = cmd_arguments
|
2019-02-21 16:39:34 +00:00
|
|
|
.value_of("kernel")
|
|
|
|
.expect("Missing argument: kernel");
|
2019-03-07 13:56:43 +00:00
|
|
|
|
2019-05-23 19:48:05 +00:00
|
|
|
let cmdline = cmd_arguments.value_of("cmdline");
|
|
|
|
|
|
|
|
let disks: Vec<&str> = cmd_arguments
|
2019-05-22 13:56:22 +00:00
|
|
|
.values_of("disk")
|
2019-05-23 19:48:05 +00:00
|
|
|
.expect("Missing argument: disk. Provide at least one")
|
2019-05-22 13:56:22 +00:00
|
|
|
.collect();
|
2019-05-06 19:15:44 +00:00
|
|
|
|
2019-05-23 19:48:05 +00:00
|
|
|
let net = cmd_arguments.value_of("net");
|
2019-05-10 09:52:15 +00:00
|
|
|
|
2019-05-23 19:48:05 +00:00
|
|
|
// This .unwrap() cannot fail as there is a default value defined
|
|
|
|
let rng = cmd_arguments.value_of("rng").unwrap();
|
2019-05-09 15:01:42 +00:00
|
|
|
|
2019-05-22 20:06:49 +00:00
|
|
|
let fs = cmd_arguments.value_of("fs");
|
|
|
|
|
2019-05-23 19:48:05 +00:00
|
|
|
let vm_config = match config::VmConfig::parse(config::VmParams {
|
|
|
|
cpus,
|
|
|
|
memory,
|
|
|
|
kernel,
|
|
|
|
cmdline,
|
|
|
|
disks,
|
|
|
|
net,
|
2019-05-22 20:06:49 +00:00
|
|
|
rng,
|
|
|
|
fs,
|
2019-05-23 19:48:05 +00:00
|
|
|
}) {
|
|
|
|
Ok(config) => config,
|
|
|
|
Err(e) => {
|
|
|
|
println!("Failed parsing parameters {:?}", e);
|
|
|
|
process::exit(1);
|
|
|
|
}
|
2019-05-09 05:01:48 +00:00
|
|
|
};
|
|
|
|
|
2019-05-10 08:02:07 +00:00
|
|
|
println!(
|
2019-05-23 19:48:05 +00:00
|
|
|
"Cloud Hypervisor Guest\n\tvCPUs: {}\n\tMemory: {} MB\
|
|
|
|
\n\tKernel: {:?}\n\tKernel cmdline: {}\n\tDisk(s): {:?}",
|
|
|
|
u8::from(&vm_config.cpus),
|
2019-05-24 19:21:23 +00:00
|
|
|
vm_config.memory.size,
|
2019-05-23 19:48:05 +00:00
|
|
|
vm_config.kernel.path,
|
|
|
|
vm_config.cmdline.args.as_str(),
|
|
|
|
vm_config.disks,
|
2019-05-10 08:02:07 +00:00
|
|
|
);
|
2019-03-07 13:56:43 +00:00
|
|
|
|
2019-05-10 08:46:27 +00:00
|
|
|
if let Err(e) = vmm::boot_kernel(vm_config) {
|
|
|
|
println!("Guest boot failed: {}", e);
|
2019-05-23 19:48:05 +00:00
|
|
|
process::exit(1);
|
2019-05-10 08:46:27 +00:00
|
|
|
}
|
2019-02-21 16:04:44 +00:00
|
|
|
}
|
2019-05-23 15:45:13 +00:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
#[cfg(feature = "integration_tests")]
|
2019-06-04 15:24:39 +00:00
|
|
|
#[macro_use]
|
|
|
|
extern crate credibility;
|
2019-05-23 15:45:13 +00:00
|
|
|
|
2019-06-04 15:24:39 +00:00
|
|
|
#[cfg(test)]
|
|
|
|
#[cfg(feature = "integration_tests")]
|
|
|
|
mod tests {
|
2019-05-23 15:45:13 +00:00
|
|
|
use ssh2::Session;
|
|
|
|
use std::fs;
|
|
|
|
use std::io::Read;
|
|
|
|
use std::net::TcpStream;
|
2019-06-04 15:24:39 +00:00
|
|
|
use std::process::Command;
|
2019-05-23 15:45:13 +00:00
|
|
|
use std::thread;
|
|
|
|
|
|
|
|
fn ssh_command(command: &str) -> String {
|
|
|
|
let mut s = String::new();
|
|
|
|
#[derive(Debug)]
|
|
|
|
enum Error {
|
|
|
|
Connection,
|
|
|
|
Authentication,
|
|
|
|
Command,
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut counter = 0;
|
|
|
|
loop {
|
|
|
|
match (|| -> Result<(), Error> {
|
|
|
|
let tcp = TcpStream::connect("192.168.2.2:22").map_err(|_| Error::Connection)?;
|
|
|
|
let mut sess = Session::new().unwrap();
|
|
|
|
sess.handshake(&tcp).map_err(|_| Error::Connection)?;
|
|
|
|
|
|
|
|
sess.userauth_password("admin", "cloud123")
|
|
|
|
.map_err(|_| Error::Authentication)?;
|
|
|
|
assert!(sess.authenticated());
|
|
|
|
|
|
|
|
let mut channel = sess.channel_session().map_err(|_| Error::Command)?;
|
|
|
|
channel.exec(command).map_err(|_| Error::Command)?;
|
|
|
|
|
|
|
|
// Intentionally ignore these results here as their failure
|
|
|
|
// does not precipitate a repeat
|
|
|
|
let _ = channel.read_to_string(&mut s);
|
|
|
|
let _ = channel.close();
|
|
|
|
let _ = channel.wait_close();
|
|
|
|
Ok(())
|
|
|
|
})() {
|
|
|
|
Ok(_) => break,
|
|
|
|
Err(e) => {
|
|
|
|
counter += 1;
|
|
|
|
if counter >= 6 {
|
|
|
|
panic!("Took too many attempts to run command. Last error: {:?}", e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
thread::sleep(std::time::Duration::new(10, 0));
|
|
|
|
}
|
|
|
|
s
|
|
|
|
}
|
|
|
|
|
|
|
|
fn prepare_files() -> (Vec<&'static str>, String) {
|
|
|
|
let mut workload_path = dirs::home_dir().unwrap();
|
|
|
|
workload_path.push("workloads");
|
|
|
|
|
|
|
|
let mut fw_path = workload_path.clone();
|
|
|
|
fw_path.push("hypervisor-fw");
|
|
|
|
|
|
|
|
let mut osdisk_base_path = workload_path.clone();
|
2019-06-10 13:59:04 +00:00
|
|
|
osdisk_base_path.push("clear-29810-cloud.img");
|
2019-05-23 15:45:13 +00:00
|
|
|
|
|
|
|
let osdisk_path = "/tmp/osdisk.img";
|
|
|
|
let cloudinit_path = "/tmp/cloudinit.img";
|
|
|
|
|
|
|
|
fs::copy(osdisk_base_path, osdisk_path).expect("copying of OS source disk image failed");
|
|
|
|
|
|
|
|
let disks = vec![osdisk_path, cloudinit_path];
|
|
|
|
|
|
|
|
(disks, String::from(fw_path.to_str().unwrap()))
|
|
|
|
}
|
|
|
|
|
2019-06-15 00:41:13 +00:00
|
|
|
fn prepare_virtiofsd() -> (std::process::Child, String) {
|
|
|
|
let mut workload_path = dirs::home_dir().unwrap();
|
|
|
|
workload_path.push("workloads");
|
|
|
|
|
|
|
|
let mut virtiofsd_path = workload_path.clone();
|
|
|
|
virtiofsd_path.push("virtiofsd");
|
|
|
|
let virtiofsd_path = String::from(virtiofsd_path.to_str().unwrap());
|
|
|
|
|
|
|
|
let mut shared_dir_path = workload_path.clone();
|
|
|
|
shared_dir_path.push("shared_dir");
|
|
|
|
let shared_dir_path = String::from(shared_dir_path.to_str().unwrap());
|
|
|
|
|
|
|
|
let virtiofsd_socket_path = String::from("/tmp/virtiofs.sock");
|
|
|
|
|
|
|
|
// Start the daemon
|
|
|
|
let child = Command::new(virtiofsd_path.as_str())
|
|
|
|
.args(&[
|
|
|
|
"-o",
|
|
|
|
format!("vhost_user_socket={}", virtiofsd_socket_path).as_str(),
|
|
|
|
])
|
|
|
|
.args(&["-o", format!("source={}", shared_dir_path).as_str()])
|
|
|
|
.args(&["-o", "cache=none"])
|
|
|
|
.spawn()
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
(child, virtiofsd_socket_path)
|
|
|
|
}
|
|
|
|
|
2019-06-04 15:24:39 +00:00
|
|
|
fn get_cpu_count() -> u32 {
|
|
|
|
ssh_command("grep -c processor /proc/cpuinfo")
|
|
|
|
.trim()
|
|
|
|
.parse()
|
|
|
|
.unwrap()
|
|
|
|
}
|
|
|
|
|
2019-06-11 13:53:38 +00:00
|
|
|
fn get_initial_apicid() -> u32 {
|
|
|
|
ssh_command("grep \"initial apicid\" /proc/cpuinfo | grep -o \"[0-9]*\"")
|
|
|
|
.trim()
|
|
|
|
.parse()
|
|
|
|
.unwrap()
|
|
|
|
}
|
|
|
|
|
2019-06-04 15:24:39 +00:00
|
|
|
fn get_total_memory() -> u32 {
|
|
|
|
ssh_command("grep MemTotal /proc/meminfo | grep -o \"[0-9]*\"")
|
|
|
|
.trim()
|
|
|
|
.parse::<u32>()
|
|
|
|
.unwrap()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_entropy() -> u32 {
|
|
|
|
ssh_command("cat /proc/sys/kernel/random/entropy_avail")
|
|
|
|
.trim()
|
|
|
|
.parse::<u32>()
|
|
|
|
.unwrap()
|
|
|
|
}
|
|
|
|
|
2019-05-23 15:45:13 +00:00
|
|
|
#[test]
|
|
|
|
fn test_simple_launch() {
|
2019-06-04 15:24:39 +00:00
|
|
|
test_block!(tb, "", {
|
2019-05-23 15:45:13 +00:00
|
|
|
let (disks, fw_path) = prepare_files();
|
2019-06-04 15:24:39 +00:00
|
|
|
let mut child = Command::new("target/debug/cloud-hypervisor")
|
|
|
|
.args(&["--cpus", "1"])
|
2019-05-24 19:21:23 +00:00
|
|
|
.args(&["--memory", "size=512"])
|
2019-06-04 15:24:39 +00:00
|
|
|
.args(&["--kernel", fw_path.as_str()])
|
|
|
|
.args(&["--disk", disks[0], disks[1]])
|
|
|
|
.args(&["--net", "tap=,mac=,ip=192.168.2.1,mask=255.255.255.0"])
|
|
|
|
.spawn()
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
thread::sleep(std::time::Duration::new(10, 0));
|
|
|
|
|
|
|
|
aver_eq!(tb, get_cpu_count(), 1);
|
2019-06-11 13:53:38 +00:00
|
|
|
aver_eq!(tb, get_initial_apicid(), 0);
|
2019-06-10 14:00:14 +00:00
|
|
|
aver!(tb, get_total_memory() > 496_000);
|
2019-06-04 15:24:39 +00:00
|
|
|
aver!(tb, get_entropy() >= 1000);
|
2019-05-23 15:45:13 +00:00
|
|
|
|
2019-06-04 15:24:39 +00:00
|
|
|
ssh_command("sudo reboot");
|
|
|
|
thread::sleep(std::time::Duration::new(10, 0));
|
|
|
|
let _ = child.kill();
|
|
|
|
let _ = child.wait();
|
|
|
|
Ok(())
|
2019-05-23 15:45:13 +00:00
|
|
|
});
|
2019-06-04 15:24:39 +00:00
|
|
|
}
|
2019-05-23 15:45:13 +00:00
|
|
|
|
2019-06-04 15:24:39 +00:00
|
|
|
#[test]
|
|
|
|
fn test_multi_cpu() {
|
|
|
|
test_block!(tb, "", {
|
|
|
|
let (disks, fw_path) = prepare_files();
|
|
|
|
let mut child = Command::new("target/debug/cloud-hypervisor")
|
|
|
|
.args(&["--cpus", "2"])
|
2019-05-24 19:21:23 +00:00
|
|
|
.args(&["--memory", "size=512"])
|
2019-06-04 15:24:39 +00:00
|
|
|
.args(&["--kernel", fw_path.as_str()])
|
|
|
|
.args(&["--disk", disks[0], disks[1]])
|
|
|
|
.args(&["--net", "tap=,mac=,ip=192.168.2.1,mask=255.255.255.0"])
|
|
|
|
.spawn()
|
|
|
|
.unwrap();
|
2019-05-23 15:45:13 +00:00
|
|
|
|
2019-06-04 15:24:39 +00:00
|
|
|
thread::sleep(std::time::Duration::new(10, 0));
|
2019-05-23 15:45:13 +00:00
|
|
|
|
2019-06-04 15:24:39 +00:00
|
|
|
aver_eq!(tb, get_cpu_count(), 2);
|
2019-05-23 15:45:13 +00:00
|
|
|
|
2019-06-04 15:24:39 +00:00
|
|
|
ssh_command("sudo reboot");
|
|
|
|
thread::sleep(std::time::Duration::new(10, 0));
|
|
|
|
let _ = child.kill();
|
|
|
|
let _ = child.wait();
|
|
|
|
Ok(())
|
|
|
|
});
|
2019-05-23 15:45:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2019-06-04 15:24:39 +00:00
|
|
|
fn test_large_memory() {
|
|
|
|
test_block!(tb, "", {
|
|
|
|
let (disks, fw_path) = prepare_files();
|
|
|
|
let mut child = Command::new("target/debug/cloud-hypervisor")
|
|
|
|
.args(&["--cpus", "1"])
|
2019-05-24 19:21:23 +00:00
|
|
|
.args(&["--memory", "size=5120"])
|
2019-06-04 15:24:39 +00:00
|
|
|
.args(&["--kernel", fw_path.as_str()])
|
|
|
|
.args(&["--disk", disks[0], disks[1]])
|
|
|
|
.args(&["--net", "tap=,mac=,ip=192.168.2.1,mask=255.255.255.0"])
|
|
|
|
.spawn()
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
thread::sleep(std::time::Duration::new(10, 0));
|
|
|
|
|
2019-06-10 14:00:14 +00:00
|
|
|
aver!(tb, get_total_memory() > 5_063_000);
|
2019-06-04 15:24:39 +00:00
|
|
|
|
|
|
|
ssh_command("sudo reboot");
|
|
|
|
thread::sleep(std::time::Duration::new(10, 0));
|
|
|
|
let _ = child.kill();
|
|
|
|
let _ = child.wait();
|
|
|
|
Ok(())
|
|
|
|
});
|
2019-05-23 15:45:13 +00:00
|
|
|
}
|
2019-06-06 14:15:07 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_pci_msi() {
|
|
|
|
test_block!(tb, "", {
|
|
|
|
let (disks, fw_path) = prepare_files();
|
|
|
|
let mut child = Command::new("target/debug/cloud-hypervisor")
|
|
|
|
.args(&["--cpus", "1"])
|
2019-05-24 19:21:23 +00:00
|
|
|
.args(&["--memory", "size=512"])
|
2019-06-06 14:15:07 +00:00
|
|
|
.args(&["--kernel", fw_path.as_str()])
|
|
|
|
.args(&["--disk", disks[0], disks[1]])
|
|
|
|
.args(&["--net", "tap=,mac=,ip=192.168.2.1,mask=255.255.255.0"])
|
|
|
|
.spawn()
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
thread::sleep(std::time::Duration::new(10, 0));
|
|
|
|
|
|
|
|
aver_eq!(
|
|
|
|
tb,
|
|
|
|
ssh_command("grep -c PCI-MSI /proc/interrupts")
|
|
|
|
.trim()
|
|
|
|
.parse::<u32>()
|
|
|
|
.unwrap(),
|
|
|
|
8
|
|
|
|
);
|
|
|
|
|
|
|
|
ssh_command("sudo reboot");
|
|
|
|
thread::sleep(std::time::Duration::new(10, 0));
|
|
|
|
let _ = child.kill();
|
|
|
|
let _ = child.wait();
|
|
|
|
Ok(())
|
|
|
|
});
|
|
|
|
}
|
2019-06-10 14:02:53 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_vmlinux_boot() {
|
|
|
|
test_block!(tb, "", {
|
|
|
|
let (disks, _) = prepare_files();
|
|
|
|
let mut workload_path = dirs::home_dir().unwrap();
|
|
|
|
workload_path.push("workloads");
|
|
|
|
|
|
|
|
let mut kernel_path = workload_path.clone();
|
|
|
|
kernel_path.push("vmlinux");
|
|
|
|
|
|
|
|
let mut child = Command::new("target/debug/cloud-hypervisor")
|
|
|
|
.args(&["--cpus", "1"])
|
2019-05-24 19:21:23 +00:00
|
|
|
.args(&["--memory", "size=512"])
|
2019-06-10 14:02:53 +00:00
|
|
|
.args(&["--kernel", kernel_path.to_str().unwrap()])
|
|
|
|
.args(&["--disk", disks[0], disks[1]])
|
|
|
|
.args(&["--net", "tap=,mac=,ip=192.168.2.1,mask=255.255.255.0"])
|
2019-06-13 10:00:51 +00:00
|
|
|
.args(&["--cmdline", "root=PARTUUID=3cb0e0a5-925d-405e-bc55-edf0cec8f10a console=tty0 console=ttyS0,115200n8 console=hvc0 quiet init=/usr/lib/systemd/systemd-bootchart initcall_debug tsc=reliable no_timer_check noreplace-smp cryptomgr.notests rootfstype=ext4,btrfs,xfs kvm-intel.nested=1 rw"])
|
|
|
|
.spawn()
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
thread::sleep(std::time::Duration::new(10, 0));
|
|
|
|
|
|
|
|
aver_eq!(tb, get_cpu_count(), 1);
|
|
|
|
aver!(tb, get_total_memory() > 496_000);
|
|
|
|
aver!(tb, get_entropy() >= 1000);
|
|
|
|
aver_eq!(
|
|
|
|
tb,
|
|
|
|
ssh_command("grep -c PCI-MSI /proc/interrupts")
|
|
|
|
.trim()
|
|
|
|
.parse::<u32>()
|
|
|
|
.unwrap(),
|
|
|
|
8
|
|
|
|
);
|
|
|
|
|
|
|
|
ssh_command("sudo reboot");
|
|
|
|
thread::sleep(std::time::Duration::new(10, 0));
|
|
|
|
let _ = child.kill();
|
|
|
|
let _ = child.wait();
|
|
|
|
Ok(())
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_bzimage_boot() {
|
|
|
|
test_block!(tb, "", {
|
|
|
|
let (disks, _) = prepare_files();
|
|
|
|
let mut workload_path = dirs::home_dir().unwrap();
|
|
|
|
workload_path.push("workloads");
|
|
|
|
|
|
|
|
let mut kernel_path = workload_path.clone();
|
|
|
|
kernel_path.push("bzImage");
|
|
|
|
|
|
|
|
let mut child = Command::new("target/debug/cloud-hypervisor")
|
|
|
|
.args(&["--cpus", "1"])
|
2019-05-24 19:21:23 +00:00
|
|
|
.args(&["--memory", "size=512"])
|
2019-06-13 10:00:51 +00:00
|
|
|
.args(&["--kernel", kernel_path.to_str().unwrap()])
|
|
|
|
.args(&["--disk", disks[0], disks[1]])
|
|
|
|
.args(&["--net", "tap=,mac=,ip=192.168.2.1,mask=255.255.255.0"])
|
2019-06-10 14:02:53 +00:00
|
|
|
.args(&["--cmdline", "root=PARTUUID=3cb0e0a5-925d-405e-bc55-edf0cec8f10a console=tty0 console=ttyS0,115200n8 console=hvc0 quiet init=/usr/lib/systemd/systemd-bootchart initcall_debug tsc=reliable no_timer_check noreplace-smp cryptomgr.notests rootfstype=ext4,btrfs,xfs kvm-intel.nested=1 rw"])
|
|
|
|
.spawn()
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
thread::sleep(std::time::Duration::new(10, 0));
|
|
|
|
|
|
|
|
aver_eq!(tb, get_cpu_count(), 1);
|
|
|
|
aver!(tb, get_total_memory() > 496_000);
|
|
|
|
aver!(tb, get_entropy() >= 1000);
|
|
|
|
aver_eq!(
|
|
|
|
tb,
|
|
|
|
ssh_command("grep -c PCI-MSI /proc/interrupts")
|
|
|
|
.trim()
|
|
|
|
.parse::<u32>()
|
|
|
|
.unwrap(),
|
|
|
|
8
|
|
|
|
);
|
|
|
|
|
|
|
|
ssh_command("sudo reboot");
|
|
|
|
thread::sleep(std::time::Duration::new(10, 0));
|
|
|
|
let _ = child.kill();
|
|
|
|
let _ = child.wait();
|
|
|
|
Ok(())
|
|
|
|
});
|
|
|
|
}
|
2019-06-13 01:45:41 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_split_irqchip() {
|
|
|
|
test_block!(tb, "", {
|
|
|
|
let (disks, fw_path) = prepare_files();
|
|
|
|
let mut child = Command::new("target/debug/cloud-hypervisor")
|
|
|
|
.args(&["--cpus", "1"])
|
2019-06-15 00:41:13 +00:00
|
|
|
.args(&["--memory", "size=512"])
|
2019-06-13 01:45:41 +00:00
|
|
|
.args(&["--kernel", fw_path.as_str()])
|
|
|
|
.args(&["--disk", disks[0], disks[1]])
|
|
|
|
.args(&["--net", "tap=,mac=,ip=192.168.2.1,mask=255.255.255.0"])
|
|
|
|
.spawn()
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
thread::sleep(std::time::Duration::new(10, 0));
|
|
|
|
|
|
|
|
aver_eq!(
|
|
|
|
tb,
|
|
|
|
ssh_command("cat /proc/interrupts | grep 'IO-APIC' | grep -c 'timer'")
|
|
|
|
.trim()
|
|
|
|
.parse::<u32>()
|
|
|
|
.unwrap(),
|
|
|
|
0
|
|
|
|
);
|
|
|
|
aver_eq!(
|
|
|
|
tb,
|
|
|
|
ssh_command("cat /proc/interrupts | grep 'IO-APIC' | grep -c 'cascade'")
|
|
|
|
.trim()
|
|
|
|
.parse::<u32>()
|
|
|
|
.unwrap(),
|
|
|
|
0
|
|
|
|
);
|
|
|
|
|
|
|
|
ssh_command("sudo reboot");
|
|
|
|
thread::sleep(std::time::Duration::new(10, 0));
|
|
|
|
let _ = child.kill();
|
|
|
|
let _ = child.wait();
|
|
|
|
Ok(())
|
|
|
|
});
|
|
|
|
}
|
2019-06-15 00:41:13 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_virtio_fs() {
|
|
|
|
test_block!(tb, "", {
|
|
|
|
let (disks, _) = prepare_files();
|
|
|
|
let (mut daemon_child, virtiofsd_socket_path) = prepare_virtiofsd();
|
|
|
|
let mut workload_path = dirs::home_dir().unwrap();
|
|
|
|
workload_path.push("workloads");
|
|
|
|
|
|
|
|
let mut kernel_path = workload_path.clone();
|
|
|
|
kernel_path.push("vmlinux-custom");
|
|
|
|
|
|
|
|
let mut child = Command::new("target/debug/cloud-hypervisor")
|
|
|
|
.args(&["--cpus", "1"])
|
|
|
|
.args(&["--memory", "size=512,file=/dev/shm"])
|
|
|
|
.args(&["--kernel", kernel_path.to_str().unwrap()])
|
|
|
|
.args(&["--disk", disks[0], disks[1]])
|
|
|
|
.args(&["--net", "tap=,mac=,ip=192.168.2.1,mask=255.255.255.0"])
|
|
|
|
.args(&[
|
|
|
|
"--fs",
|
|
|
|
format!(
|
|
|
|
"tag=virtiofs,sock={},num_queues=1,queue_size=1024",
|
|
|
|
virtiofsd_socket_path
|
|
|
|
)
|
|
|
|
.as_str(),
|
|
|
|
])
|
|
|
|
.args(&["--cmdline", "root=PARTUUID=3cb0e0a5-925d-405e-bc55-edf0cec8f10a console=tty0 console=ttyS0,115200n8 console=hvc0 quiet init=/usr/lib/systemd/systemd-bootchart initcall_debug tsc=reliable no_timer_check noreplace-smp cryptomgr.notests rootfstype=ext4,btrfs,xfs kvm-intel.nested=1 rw"])
|
|
|
|
.spawn()
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
thread::sleep(std::time::Duration::new(10, 0));
|
|
|
|
|
|
|
|
// Mount shared directory through virtio_fs filesystem
|
|
|
|
aver_eq!(
|
|
|
|
tb,
|
|
|
|
ssh_command("mkdir -p mount_dir && sudo mount -t virtio_fs /dev/null mount_dir/ -o tag=virtiofs,rootmode=040000,user_id=1001,group_id=1001 && echo ok")
|
|
|
|
.trim(),
|
|
|
|
"ok"
|
|
|
|
);
|
|
|
|
// Check file1 exists and its content is "foo"
|
|
|
|
aver_eq!(tb, ssh_command("cat mount_dir/file1").trim(), "foo");
|
|
|
|
// Check file2 does not exist
|
|
|
|
aver_ne!(
|
|
|
|
tb,
|
|
|
|
ssh_command("ls mount_dir/file2").trim(),
|
|
|
|
"mount_dir/file2"
|
|
|
|
);
|
|
|
|
// Check file3 exists and its content is "bar"
|
|
|
|
aver_eq!(tb, ssh_command("cat mount_dir/file3").trim(), "bar");
|
|
|
|
|
|
|
|
ssh_command("sudo reboot");
|
|
|
|
let _ = child.wait();
|
|
|
|
let _ = daemon_child.wait();
|
|
|
|
Ok(())
|
|
|
|
});
|
|
|
|
}
|
2019-05-23 15:45:13 +00:00
|
|
|
}
|