mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
vmm: Make serial port controllable via command line
Add a "--serial" command line that takes as input either "off", "tty" (default and current behaviour) and "file=/path/to/file". When "--serial off" is used the serial device is not added to the VM configuration at all. Integration tests added that check for interrupts present (or not) and that when sending to a file the file contains the expected serial output. Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
114
src/main.rs
114
src/main.rs
@@ -88,27 +88,28 @@ fn main() {
|
||||
.takes_value(true)
|
||||
.min_values(1),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("serial")
|
||||
.long("serial")
|
||||
.help("Control serial port: off|tty|file=/path/to/a/file")
|
||||
.default_value("tty"),
|
||||
)
|
||||
.get_matches();
|
||||
|
||||
// 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 rng = cmd_arguments.value_of("rng").unwrap();
|
||||
let serial = cmd_arguments.value_of("serial").unwrap();
|
||||
|
||||
let kernel = cmd_arguments
|
||||
.value_of("kernel")
|
||||
.expect("Missing argument: kernel");
|
||||
|
||||
let cmdline = cmd_arguments.value_of("cmdline");
|
||||
|
||||
let disks: Option<Vec<&str>> = cmd_arguments.values_of("disk").map(|x| x.collect());
|
||||
|
||||
let net: Option<Vec<&str>> = cmd_arguments.values_of("net").map(|x| x.collect());
|
||||
|
||||
// This .unwrap() cannot fail as there is a default value defined
|
||||
let rng = cmd_arguments.value_of("rng").unwrap();
|
||||
|
||||
let fs: Option<Vec<&str>> = cmd_arguments.values_of("fs").map(|x| x.collect());
|
||||
|
||||
let pmem: Option<Vec<&str>> = cmd_arguments.values_of("pmem").map(|x| x.collect());
|
||||
|
||||
let vm_config = match config::VmConfig::parse(config::VmParams {
|
||||
@@ -121,6 +122,7 @@ fn main() {
|
||||
rng,
|
||||
fs,
|
||||
pmem,
|
||||
serial,
|
||||
}) {
|
||||
Ok(config) => config,
|
||||
Err(e) => {
|
||||
@@ -760,4 +762,102 @@ mod tests {
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serial_disable() {
|
||||
test_block!(tb, "", {
|
||||
let (disks, fw_path) = prepare_files();
|
||||
let mut child = Command::new("target/debug/cloud-hypervisor")
|
||||
.args(&["--cpus", "1"])
|
||||
.args(&["--memory", "size=512M"])
|
||||
.args(&["--kernel", fw_path.as_str()])
|
||||
.args(&["--disk", disks[0], disks[1]])
|
||||
.args(&[
|
||||
"--net",
|
||||
"tap=,mac=12:34:56:78:90:ab,ip=192.168.2.1,mask=255.255.255.0",
|
||||
])
|
||||
.args(&["--serial", "off"])
|
||||
.spawn()
|
||||
.unwrap();
|
||||
|
||||
thread::sleep(std::time::Duration::new(10, 0));
|
||||
|
||||
// Test that there is no ttyS0
|
||||
aver_eq!(
|
||||
tb,
|
||||
ssh_command("cat /proc/interrupts | grep 'IO-APIC' | grep -c 'ttyS0'")
|
||||
.trim()
|
||||
.parse::<u32>()
|
||||
.unwrap(),
|
||||
0
|
||||
);
|
||||
|
||||
// Further test that we're MSI only now
|
||||
aver_eq!(
|
||||
tb,
|
||||
ssh_command("cat /proc/interrupts | grep -c 'IO-APIC'")
|
||||
.trim()
|
||||
.parse::<u32>()
|
||||
.unwrap(),
|
||||
0
|
||||
);
|
||||
|
||||
ssh_command("sudo reboot");
|
||||
thread::sleep(std::time::Duration::new(10, 0));
|
||||
let _ = child.kill();
|
||||
let _ = child.wait();
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serial_file() {
|
||||
test_block!(tb, "", {
|
||||
let serial_path = std::path::Path::new("/tmp/serial-output");
|
||||
let (disks, fw_path) = prepare_files();
|
||||
let mut child = Command::new("target/debug/cloud-hypervisor")
|
||||
.args(&["--cpus", "1"])
|
||||
.args(&["--memory", "size=512M"])
|
||||
.args(&["--kernel", fw_path.as_str()])
|
||||
.args(&["--disk", disks[0], disks[1]])
|
||||
.args(&[
|
||||
"--net",
|
||||
"tap=,mac=12:34:56:78:90:ab,ip=192.168.2.1,mask=255.255.255.0",
|
||||
])
|
||||
.args(&[
|
||||
"--serial",
|
||||
format!("file={}", serial_path.to_str().unwrap()).as_str(),
|
||||
])
|
||||
.spawn()
|
||||
.unwrap();
|
||||
|
||||
thread::sleep(std::time::Duration::new(10, 0));
|
||||
|
||||
// Test that there is a ttyS0
|
||||
aver_eq!(
|
||||
tb,
|
||||
ssh_command("cat /proc/interrupts | grep 'IO-APIC' | grep -c 'ttyS0'")
|
||||
.trim()
|
||||
.parse::<u32>()
|
||||
.unwrap(),
|
||||
1
|
||||
);
|
||||
|
||||
ssh_command("sudo reboot");
|
||||
thread::sleep(std::time::Duration::new(10, 0));
|
||||
|
||||
// Do this check after shutdown of the VM as an easy way to ensure
|
||||
// all writes are flushed to disk
|
||||
let mut f = std::fs::File::open(serial_path).unwrap();
|
||||
let mut buf = String::new();
|
||||
f.read_to_string(&mut buf).unwrap();
|
||||
aver!(tb, buf.contains("cloud login:"));
|
||||
std::fs::remove_file(serial_path).unwrap();
|
||||
|
||||
let _ = child.kill();
|
||||
let _ = child.wait();
|
||||
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user