weird
This commit is contained in:
parent
9ed17eca06
commit
92452ce4d6
10 changed files with 190 additions and 122 deletions
47
Cargo.lock
generated
47
Cargo.lock
generated
|
@ -33,6 +33,21 @@ version = "1.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bstr"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a40b47ad93e1a5404e6c18dec46b628214fee441c70f4ab5d6942142cc268a3d"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cc"
|
||||||
|
version = "1.0.67"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
@ -55,6 +70,15 @@ dependencies = [
|
||||||
"yaml-rust",
|
"yaml-rust",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "erased-serde"
|
||||||
|
version = "0.3.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0465971a8cc1fa2455c8465aaa377131e1f1cf4983280f474a13e68793aa770c"
|
||||||
|
dependencies = [
|
||||||
|
"serde 1.0.125",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "0.4.7"
|
version = "0.4.7"
|
||||||
|
@ -98,6 +122,21 @@ version = "2.3.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
|
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mlua"
|
||||||
|
version = "0.5.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6f2fc8e1085d53b72898c59ceee1980b5826b0c98ce99886b7518f0ead00e5cb"
|
||||||
|
dependencies = [
|
||||||
|
"bstr",
|
||||||
|
"cc",
|
||||||
|
"erased-serde",
|
||||||
|
"lazy_static",
|
||||||
|
"num-traits 0.2.14",
|
||||||
|
"pkg-config",
|
||||||
|
"serde 1.0.125",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nom"
|
name = "nom"
|
||||||
version = "5.1.2"
|
version = "5.1.2"
|
||||||
|
@ -127,6 +166,12 @@ dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pkg-config"
|
||||||
|
version = "0.3.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.26"
|
version = "1.0.26"
|
||||||
|
@ -276,7 +321,9 @@ dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"config",
|
"config",
|
||||||
"kiam",
|
"kiam",
|
||||||
|
"mlua",
|
||||||
"serde 1.0.125",
|
"serde 1.0.125",
|
||||||
|
"toml",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
23
config/global.toml
Normal file
23
config/global.toml
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
[qemu]
|
||||||
|
script = "qemu.lua"
|
||||||
|
|
||||||
|
default = [
|
||||||
|
"-rtc", "driftfix=slew",
|
||||||
|
"-serial", "stdio",
|
||||||
|
"-no-hpet",
|
||||||
|
"-boot", "strict=on"
|
||||||
|
]
|
||||||
|
|
||||||
|
arch.i686 = []
|
||||||
|
arch.x86_64 = ["-global", "kvm-pit.lost_tick_policy=discard"]
|
||||||
|
|
||||||
|
uefi = [
|
||||||
|
# OVMF will hang if S3 is not disabled
|
||||||
|
# disable S4 too, since libvirt does that 🤷
|
||||||
|
# https://bugs.archlinux.org/task/59465#comment172528
|
||||||
|
"-global", "ICH9-LPC.disable_s3=1",
|
||||||
|
"-global", "ICH9-LPC.disable_s4=1"
|
||||||
|
]
|
||||||
|
|
||||||
|
[[disk.default]]
|
||||||
|
flag = "blockdev"
|
37
config/qemu.lua
Normal file
37
config/qemu.lua
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
function build_command(instance, args)
|
||||||
|
args:add("-rtc", "driftfix=slew")
|
||||||
|
args:add("-serial", "stdio")
|
||||||
|
args:add("-no-hpet")
|
||||||
|
args:add("-boot", "strict=on")
|
||||||
|
|
||||||
|
if instance.kvm then
|
||||||
|
args:add("-enable-kvm")
|
||||||
|
end
|
||||||
|
|
||||||
|
if instance.arch == "x86_64" or instance.arch == "i868" then
|
||||||
|
args:add("-global", "kvm-pit.lost_tick_policy=discard")
|
||||||
|
end
|
||||||
|
|
||||||
|
args:add("-no-user-config")
|
||||||
|
args:add("-no-defaults")
|
||||||
|
args:add("-no-shutdown")
|
||||||
|
args:add("-m", tostring(instance.memory))
|
||||||
|
|
||||||
|
local cpu = instance.cpu;
|
||||||
|
args:add(string.format("%d,sockets=%d,dies=%d,cores=%d,threads=%d",
|
||||||
|
cpu.amount,
|
||||||
|
cpu.sockets,
|
||||||
|
cpu.dies,
|
||||||
|
cpu.cores,
|
||||||
|
cpu.threads))
|
||||||
|
|
||||||
|
if instance.uefi.enabled and string.find(instance.chipset, "q35") == 0 then
|
||||||
|
-- OVMF will hang if S3 is not disabled
|
||||||
|
-- disable S4 too, since libvirt does that 🤷
|
||||||
|
-- https://bugs.archlinux.org/task/59465#comment172528
|
||||||
|
args:add("-global", "ICH9-LPC.disable_s3=1")
|
||||||
|
args:add("-global", "ICH9-LPC.disable_s4=1")
|
||||||
|
end
|
||||||
|
|
||||||
|
return args
|
||||||
|
end
|
|
@ -9,5 +9,7 @@ edition = "2018"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
config = "0.11.0"
|
config = "0.11.0"
|
||||||
serde = { version = "1.0.125", features = ["serde_derive"] }
|
serde = { version = "1.0.125", features = ["serde_derive"] }
|
||||||
|
toml = "*"
|
||||||
anyhow = "1.0.40"
|
anyhow = "1.0.40"
|
||||||
kiam = "0.1"
|
kiam = "0.1"
|
||||||
|
mlua = { version = "0.5.3", features = ["lua54", "serialize"] }
|
21
vore-core/src/global_config.rs
Normal file
21
vore-core/src/global_config.rs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
use anyhow::Context;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
pub struct GlobalConfig {
|
||||||
|
pub qemu: GlobalQemuConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
pub struct GlobalQemuConfig {
|
||||||
|
pub default: Vec<String>,
|
||||||
|
pub arch: HashMap<String, Vec<String>>,
|
||||||
|
pub uefi: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GlobalConfig {
|
||||||
|
pub fn load(toml: &str) -> Result<GlobalConfig, anyhow::Error> {
|
||||||
|
toml::from_str(toml).context("Failed to parse toml for global config")
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,6 +7,8 @@ use std::str::FromStr;
|
||||||
#[derive(Deserialize, Serialize, Clone, Debug)]
|
#[derive(Deserialize, Serialize, Clone, Debug)]
|
||||||
pub struct InstanceConfig {
|
pub struct InstanceConfig {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
pub arch: String,
|
||||||
|
pub chipset: String,
|
||||||
pub kvm: bool,
|
pub kvm: bool,
|
||||||
pub memory: u64,
|
pub memory: u64,
|
||||||
pub cpu: CpuConfig,
|
pub cpu: CpuConfig,
|
||||||
|
@ -61,6 +63,8 @@ impl Default for InstanceConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
InstanceConfig {
|
InstanceConfig {
|
||||||
name: "vore".to_string(),
|
name: "vore".to_string(),
|
||||||
|
arch: std::env::consts::ARCH.to_string(),
|
||||||
|
chipset: "q35".to_string(),
|
||||||
kvm: true,
|
kvm: true,
|
||||||
// 2 GB
|
// 2 GB
|
||||||
memory: 2 * 1024 * 1024 * 1024,
|
memory: 2 * 1024 * 1024 * 1024,
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
mod global_config;
|
||||||
mod instance_config;
|
mod instance_config;
|
||||||
|
mod qemu;
|
||||||
|
|
||||||
|
pub use global_config::*;
|
||||||
pub use instance_config::*;
|
pub use instance_config::*;
|
||||||
|
pub use qemu::build_qemu_command;
|
||||||
|
|
47
vore-core/src/qemu.rs
Normal file
47
vore-core/src/qemu.rs
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
use crate::{GlobalConfig, InstanceConfig};
|
||||||
|
use mlua::{Function, LuaSerdeExt, MultiValue, ToLua, UserData, UserDataMethods, Value};
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Deserialize, Clone)]
|
||||||
|
struct LuaFreeList(Vec<String>);
|
||||||
|
|
||||||
|
impl UserData for LuaFreeList {
|
||||||
|
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||||
|
methods.add_method_mut("add", |_, this, args: MultiValue| {
|
||||||
|
for item in args.iter() {
|
||||||
|
if let Value::String(item) = item {
|
||||||
|
this.0.push(item.to_str()?.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Value::Nil)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build_qemu_command(config: &InstanceConfig, global_config: &GlobalConfig) -> Vec<String> {
|
||||||
|
let lua = mlua::Lua::new();
|
||||||
|
// TODO: load correct script
|
||||||
|
lua.load(include_str!("../../config/qemu.lua"))
|
||||||
|
.eval::<()>()
|
||||||
|
.unwrap();
|
||||||
|
let val: Function = lua.globals().get("build_command").unwrap();
|
||||||
|
let item = LuaFreeList::default();
|
||||||
|
let multi = MultiValue::from_vec(vec![
|
||||||
|
lua.to_value(config).unwrap(),
|
||||||
|
item.to_lua(&lua).unwrap(),
|
||||||
|
]);
|
||||||
|
let mut x = val.call::<MultiValue, LuaFreeList>(multi).unwrap();
|
||||||
|
println!("{:?}", x);
|
||||||
|
|
||||||
|
let mut cmd: Vec<String> = vec![];
|
||||||
|
cmd.push("-name".to_string());
|
||||||
|
cmd.push(format!("guest={},debug-threads=on", config.name));
|
||||||
|
|
||||||
|
cmd.push("-S".to_string());
|
||||||
|
cmd.push("-msg".to_string());
|
||||||
|
cmd.push("timestamps=on".to_string());
|
||||||
|
cmd.append(&mut x.0);
|
||||||
|
|
||||||
|
cmd
|
||||||
|
}
|
|
@ -1,4 +1,3 @@
|
||||||
use std::fmt::{Display, Formatter};
|
|
||||||
use std::process::Child;
|
use std::process::Child;
|
||||||
use vore_core::InstanceConfig;
|
use vore_core::InstanceConfig;
|
||||||
|
|
||||||
|
@ -18,123 +17,6 @@ impl Instance {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[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)]
|
#[derive(Debug)]
|
||||||
pub struct Qemu {
|
pub struct Qemu {
|
||||||
process: Option<Child>,
|
process: Option<Child>,
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
use crate::instance::build_qemu_command;
|
use vore_core::{build_qemu_command, GlobalConfig, InstanceConfig};
|
||||||
use vore_core::InstanceConfig;
|
|
||||||
|
|
||||||
mod instance;
|
mod instance;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let cfg = InstanceConfig::from_toml(include_str!("../../config/example.toml")).unwrap();
|
let cfg = InstanceConfig::from_toml(include_str!("../../config/example.toml")).unwrap();
|
||||||
println!("Hello, world! {}", build_qemu_command(&cfg));
|
let global = GlobalConfig::load(include_str!("../../config/global.toml")).unwrap();
|
||||||
|
println!("Hello, world! {:?}", build_qemu_command(&cfg, &global));
|
||||||
|
print!("hello world {:#?}", global);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue