diff options
Diffstat (limited to 'zone_nspawn/src/nspawn.rs')
-rw-r--r-- | zone_nspawn/src/nspawn.rs | 86 |
1 files changed, 50 insertions, 36 deletions
diff --git a/zone_nspawn/src/nspawn.rs b/zone_nspawn/src/nspawn.rs index 017e5a3..89f51ef 100644 --- a/zone_nspawn/src/nspawn.rs +++ b/zone_nspawn/src/nspawn.rs @@ -1,24 +1,53 @@ use std::{ffi::OsStr, path::PathBuf, process::Command}; +use async_trait::async_trait; use tokio::sync::mpsc::UnboundedReceiver; use wspty::{PtyCommand, PtyMaster}; +use zone_core::{Container, Runtime}; -use crate::{Container, Error, Result}; +use crate::{Error, Result}; #[derive(Default, Debug)] pub struct NSpawn; impl NSpawn { - pub fn list(&self) -> Result<Vec<Container>> { + async fn spawn<O, S, C, A>(opts: O, cmd: C, kill_rx: UnboundedReceiver<()>) -> Result<PtyMaster> + where + O: IntoIterator<Item = S>, + S: AsRef<OsStr>, + C: IntoIterator<Item = A>, + A: AsRef<OsStr>, + { + let base_opts = ["--quiet", "--wait", "--collect", "--service-type=exec"]; + + let mut proc = tokio::process::Command::new("systemd-run"); + + proc.args(base_opts) + .args(opts) + .args(cmd) + .env("TERM", "xterm-256color"); + + PtyCommand::from(proc) + .run(kill_rx) + .await + .map_err(Error::from) + } +} + +#[async_trait] +impl Runtime for NSpawn { + type Error = crate::Error; + + fn list(&self) -> Result<Vec<Container>> { Command::new("machinectl") .arg("list") .args(["-o", "json"]) .output() - .map(|o| serde_json::from_slice(o.stdout.as_slice()))? .map_err(Error::from) + .and_then(|o| serde_json::from_slice(o.stdout.as_slice()).map_err(Error::from)) } - pub fn create(&self, root: PathBuf, name: String) -> Result<()> { + fn create(&self, root: PathBuf, container: &Container) -> Result<()> { let opts = [ "--settings=trusted", "--quiet", @@ -34,41 +63,25 @@ impl NSpawn { Command::new("systemd-nspawn") .arg("--machine") - .arg(name) + .arg(container.to_string()) .arg("--directory") .arg(root) .args(opts) - .status()? + .status() + .map_err(Error::from)? .success() .then(|| ()) - .ok_or_else(|| Error::NSpawn(format!("Failed to create container: {:?}", self))) - } - - async fn spawn<O, S, C, A>(opts: O, cmd: C, kill_rx: UnboundedReceiver<()>) -> Result<PtyMaster> - where - O: IntoIterator<Item = S>, - S: AsRef<OsStr>, - C: IntoIterator<Item = A>, - A: AsRef<OsStr>, - { - let base_opts = ["--quiet", "--wait", "--collect", "--service-type=exec"]; - - let mut proc = tokio::process::Command::new("systemd-run"); - - proc.args(base_opts) - .args(opts) - .args(cmd) - .env("TERM", "xterm-256color"); - - PtyCommand::from(proc) - .run(kill_rx) - .await + .ok_or_else(|| Error::Initialization(container.to_owned())) .map_err(Error::from) } - pub async fn attach(&self, name: String, kill_rx: UnboundedReceiver<()>) -> Result<PtyMaster> { + async fn attach( + &self, + container: Container, + kill_rx: UnboundedReceiver<()>, + ) -> Result<PtyMaster> { let opts = [ - &format!("{}={}", "--machine", name), + &format!("--machine={}", container), "--pty", "--send-sighup", ]; @@ -76,18 +89,19 @@ impl NSpawn { Self::spawn(opts, cmd, kill_rx).await } - pub async fn run<C, S>( + async fn run<C, S>( &self, - name: String, + container: Container, cmd: C, kill_rx: UnboundedReceiver<()>, ) -> Result<PtyMaster> where C: IntoIterator<Item = S>, + C: std::marker::Send, S: AsRef<OsStr>, { let opts = [ - &format!("{}={}", "--machine", name), + &format!("--machine={}", container), "--pty", "--send-sighup", ]; @@ -95,13 +109,13 @@ impl NSpawn { Self::spawn(opts, cmd, kill_rx).await } - pub fn shutdown(name: String) -> Result<()> { + fn shutdown(container: Container) -> Result<()> { Command::new("machinectl") .arg("poweroff") - .arg(&name) + .arg(container.to_string()) .status()? .success() .then(|| ()) - .ok_or_else(|| Error::NSpawn(format!("Failed to shutdown container: {:?}", name))) + .ok_or(Error::Shutdown(container)) } } |