rust_lxc/
lxc.rs

1use anyhow::{Context, Result};
2use std::process::{Command, Output};
3
4pub trait LxcCommander {
5    fn create(&self, name: &str, template: &str) -> Result<()>;
6    fn start(&self, name: &str) -> Result<()>;
7    fn stop(&self, name: &str) -> Result<()>;
8    fn delete(&self, name: &str) -> Result<()>;
9    fn list(&self) -> Result<String>;
10    fn shutdown(&self, name: &str) -> Result<()>;
11}
12
13pub struct RealLxcCommander;
14
15impl RealLxcCommander {
16    fn execute_command(&self, program: &str, args: &[&str]) -> Result<Output> {
17        let output = Command::new(program)
18            .args(args)
19            .output()
20            .context(format!("Failed to execute {}", program))?;
21
22        if output.status.success() {
23            Ok(output)
24        } else {
25            let error = String::from_utf8_lossy(&output.stderr);
26            Err(anyhow::anyhow!("{} failed: {}", program, error))
27        }
28    }
29}
30
31impl LxcCommander for RealLxcCommander {
32    fn create(&self, name: &str, template: &str) -> Result<()> {
33        let args = if template == "download" {
34            vec!["-n", name, "-t", template, "--", "-d", "ubuntu", "-r", "focal", "-a", "amd64"]
35        } else {
36            vec!["-n", name, "-t", template]
37        };
38        self.execute_command("lxc-create", &args)?;
39        Ok(())
40    }
41
42    fn start(&self, name: &str) -> Result<()> {
43        self.execute_command("lxc-start", &["-n", name])?;
44        Ok(())
45    }
46
47    fn stop(&self, name: &str) -> Result<()> {
48        self.execute_command("lxc-stop", &["-n", name])?;
49        Ok(())
50    }
51
52    fn delete(&self, name: &str) -> Result<()> {
53        self.execute_command("lxc-destroy", &["-n", name])?;
54        Ok(())
55    }
56
57    fn list(&self) -> Result<String> {
58        let output = self.execute_command("lxc-ls", &["-f"])?;
59        let list = String::from_utf8_lossy(&output.stdout);
60        Ok(list.to_string())
61    }
62
63    fn shutdown(&self, name: &str) -> Result<()> {
64        self.execute_command("lxc-stop", &["-n", name])?;
65        Ok(())
66    }
67}
68
69pub fn lxc_create(name: &str, template: &str) -> Result<()> {
70    let commander = RealLxcCommander;
71    commander.create(name, template)
72}
73
74pub fn lxc_start(name: &str) -> Result<()> {
75    let commander = RealLxcCommander;
76    commander.start(name)
77}
78
79pub fn lxc_stop(name: &str) -> Result<()> {
80    let commander = RealLxcCommander;
81    commander.stop(name)
82}
83
84pub fn lxc_delete(name: &str) -> Result<()> {
85    let commander = RealLxcCommander;
86    commander.delete(name)
87}
88
89pub fn lxc_list() -> Result<String> {
90    let commander = RealLxcCommander;
91    commander.list()
92}
93
94pub fn lxc_shutdown(name: &str) -> Result<()> {
95    let commander = RealLxcCommander;
96    commander.shutdown(name)
97}