You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
142 lines
3.2 KiB
Rust
142 lines
3.2 KiB
Rust
use std::fmt::{Display, Formatter};
|
|
use std::process::Child;
|
|
use vore_core::InstanceConfig;
|
|
|
|
#[derive(Debug)]
|
|
pub struct Instance {
|
|
config: InstanceConfig,
|
|
qemu: Option<Qemu>,
|
|
}
|
|
|
|
impl Instance {
|
|
pub fn from_config(config: InstanceConfig) -> Instance {
|
|
Instance { config, qemu: None }
|
|
}
|
|
|
|
pub fn spawn_qemu(&self) -> Result<(), anyhow::Error> {
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct ArgumentList {
|
|
items: Vec<Argument>,
|
|
}
|
|
|
|
impl Display for ArgumentList {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
let item = self.items.iter().fold(String::new(), |mut x, item| {
|
|
if x.len() > 0 {
|
|
x.push_str(" ")
|
|
}
|
|
x.push_str(item.as_str());
|
|
x
|
|
});
|
|
f.write_str(&item)
|
|
}
|
|
}
|
|
|
|
impl ArgumentList {
|
|
pub fn new(command: &'static str) -> ArgumentList {
|
|
ArgumentList {
|
|
items: vec![Argument::Borrowed(command)],
|
|
}
|
|
}
|
|
|
|
pub fn pair(&mut self, key: &'static str, value: String) {
|
|
self.push(key);
|
|
self.push(value);
|
|
}
|
|
}
|
|
|
|
pub trait PushArgument<T> {
|
|
fn push(&mut self, argument: T);
|
|
fn push_pair(&mut self, key: T, value: T) {
|
|
self.push(key);
|
|
self.push(value);
|
|
}
|
|
}
|
|
|
|
impl PushArgument<String> for ArgumentList {
|
|
fn push(&mut self, argument: String) {
|
|
self.items.push(Argument::Owned(argument))
|
|
}
|
|
}
|
|
|
|
impl PushArgument<&'static str> for ArgumentList {
|
|
fn push(&mut self, argument: &'static str) {
|
|
self.items.push(Argument::Borrowed(argument))
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
enum Argument {
|
|
Owned(String),
|
|
Borrowed(&'static str),
|
|
}
|
|
|
|
impl Argument {
|
|
fn as_str(&self) -> &str {
|
|
match self {
|
|
Argument::Owned(owned) => &owned,
|
|
Argument::Borrowed(borrowed) => borrowed,
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn build_qemu_command(config: &InstanceConfig) -> ArgumentList {
|
|
let mut cmd = ArgumentList::new("qemu-system-x86_64");
|
|
cmd.pair("-name", format!("guest={},debug-threads=on", config.name));
|
|
|
|
cmd.push("-S");
|
|
cmd.push("-no-user-config");
|
|
cmd.push("-no-defaults");
|
|
cmd.push("-no-shutdown");
|
|
|
|
if config.kvm {
|
|
cmd.push("-enable-kvm");
|
|
}
|
|
|
|
cmd.pair("-m", config.memory.to_string());
|
|
|
|
if config.uefi.enabled {
|
|
// OVMF will hang if S3 is not disabled
|
|
// disable S4 too, since libvirt does that 🤷
|
|
// https://bugs.archlinux.org/task/59465#comment172528
|
|
cmd.push_pair("-global", "ICH9-LPC.disable_s3=1");
|
|
cmd.push_pair("-global", "ICH9-LPC.disable_s4=1");
|
|
}
|
|
|
|
cmd.push_pair("-rtc", "driftfix=slew");
|
|
cmd.push_pair("-serial", "stdio");
|
|
|
|
#[cfg(any(target_arch = "x86_64", target_arch = "i686"))]
|
|
{
|
|
cmd.push_pair("-global", "kvm-pit.lost_tick_policy=discard")
|
|
}
|
|
|
|
cmd.push("-no-hpet");
|
|
cmd.push_pair("-boot", "strict=on");
|
|
|
|
cmd.pair(
|
|
"-smp",
|
|
format!(
|
|
"{},sockets={},dies={},cores={},threads={}",
|
|
config.cpu.amount,
|
|
config.cpu.sockets,
|
|
config.cpu.dies,
|
|
config.cpu.cores,
|
|
config.cpu.threads
|
|
),
|
|
);
|
|
|
|
cmd.push_pair("-msg", "timestamp=on");
|
|
|
|
cmd
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct Qemu {
|
|
process: Option<Child>,
|
|
}
|