1use super::vm::VM;
2use anyhow::{anyhow, Result};
3use serde::Serialize;
4use tinytemplate::TinyTemplate;
5
6const EMU_DEFAULT_PATH: &str = "/bin/emu";
7
8const SYSTEMD_UNIT: &str = "
9[Unit]
10Description=Virtual Machine: {vm_name}
11
12[Service]
13Type=simple
14ExecStart={emu_path} run -e {vm_name}
15TimeoutStopSec=30
16ExecStop={emu_path} shutdown {vm_name}
17KillSignal=SIGCONT
18FinalKillSignal=SIGKILL
19
20[Install]
21WantedBy=default.target
22";
23
24#[derive(Serialize)]
25pub struct Data {
26 vm_name: String,
27 emu_path: String,
28}
29
30impl Data {
31 pub fn new(vm_name: String) -> Self {
32 Self {
33 vm_name,
34 emu_path: match std::env::current_exe() {
35 Ok(path) => path.to_str().unwrap().to_string(),
36 Err(_) => EMU_DEFAULT_PATH.to_string(),
37 },
38 }
39 }
40}
41
42#[derive(Debug, Clone, Default)]
43pub struct Systemd;
44
45impl Systemd {
46 pub fn template(&self, vm: &VM) -> Result<String> {
47 let mut t = TinyTemplate::new();
48 t.add_template("systemd", SYSTEMD_UNIT)?;
49 let data = Data::new(vm.name());
50 match t.render("systemd", &data) {
51 Ok(x) => Ok(x),
52 Err(e) => Err(anyhow!(e)),
53 }
54 }
55}
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60 use anyhow::Result;
61
62 #[test]
63 fn test_template() -> Result<()> {
64 let out = Systemd::template(&Systemd, &"vm1".to_string().into())?;
65 assert!(out.contains("vm1"));
66
67 Ok(())
68 }
69}