2022-03-13 21:54:48 +01:00
|
|
|
use std::collections::HashMap;
|
|
|
|
use std::process::{Command, Stdio};
|
|
|
|
use futures_util::future::BoxFuture;
|
2022-04-26 23:21:43 +02:00
|
|
|
|
2022-03-13 21:54:48 +01:00
|
|
|
use crate::actors::Actor;
|
2022-03-16 18:10:59 +01:00
|
|
|
use crate::db::ArchivedValue;
|
|
|
|
use crate::resources::modules::fabaccess::ArchivedStatus;
|
2022-03-13 21:54:48 +01:00
|
|
|
use crate::resources::state::State;
|
|
|
|
|
|
|
|
pub struct Process {
|
|
|
|
name: String,
|
|
|
|
cmd: String,
|
|
|
|
args: Vec<String>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Process {
|
|
|
|
pub fn new(name: String, params: &HashMap<String, String>) -> Option<Self> {
|
|
|
|
let cmd = params.get("cmd").map(|s| s.to_string())?;
|
|
|
|
let args = params.get("args").map(|argv|
|
|
|
|
argv.split_whitespace()
|
|
|
|
.map(|s| s.to_string())
|
|
|
|
.collect())
|
|
|
|
.unwrap_or_else(Vec::new);
|
|
|
|
|
|
|
|
Some(Self { name, cmd, args })
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn into_boxed_actuator(self) -> Box<dyn Actor + Sync + Send> {
|
|
|
|
Box::new(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Actor for Process {
|
2022-03-16 18:10:59 +01:00
|
|
|
fn apply(&mut self, state: ArchivedValue<State>) -> BoxFuture<'static, ()> {
|
2022-03-13 21:54:48 +01:00
|
|
|
tracing::debug!(name=%self.name, cmd=%self.cmd, ?state,
|
|
|
|
"Process actor updating state");
|
|
|
|
let mut command = Command::new(&self.cmd);
|
|
|
|
command
|
|
|
|
.stdin(Stdio::null())
|
|
|
|
.args(self.args.iter())
|
|
|
|
.arg(&self.name);
|
|
|
|
|
2022-03-16 18:10:59 +01:00
|
|
|
match &state.as_ref().inner.state {
|
|
|
|
ArchivedStatus::Free => {
|
2022-03-13 21:54:48 +01:00
|
|
|
command.arg("free");
|
|
|
|
}
|
2022-03-16 18:10:59 +01:00
|
|
|
ArchivedStatus::InUse(by) => {
|
|
|
|
command.arg("inuse").arg(by.id.as_str());
|
2022-03-13 21:54:48 +01:00
|
|
|
}
|
2022-03-16 18:10:59 +01:00
|
|
|
ArchivedStatus::ToCheck(by) => {
|
2022-03-13 21:54:48 +01:00
|
|
|
command.arg("tocheck")
|
2022-03-16 18:10:59 +01:00
|
|
|
.arg(by.id.as_str());
|
2022-03-13 21:54:48 +01:00
|
|
|
}
|
2022-03-16 18:10:59 +01:00
|
|
|
ArchivedStatus::Blocked(by) => {
|
2022-03-13 21:54:48 +01:00
|
|
|
command.arg("blocked")
|
2022-03-16 18:10:59 +01:00
|
|
|
.arg(by.id.as_str());
|
2022-03-13 21:54:48 +01:00
|
|
|
}
|
2022-03-16 18:10:59 +01:00
|
|
|
ArchivedStatus::Disabled => { command.arg("disabled"); },
|
|
|
|
ArchivedStatus::Reserved(by) => {
|
2022-03-13 21:54:48 +01:00
|
|
|
command.arg("reserved")
|
2022-03-16 18:10:59 +01:00
|
|
|
.arg(by.id.as_str());
|
2022-03-13 21:54:48 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let name = self.name.clone();
|
|
|
|
Box::pin(async move { match command.output() {
|
|
|
|
Ok(retv) if retv.status.success() => {
|
|
|
|
tracing::trace!("Actor was successful");
|
|
|
|
let outstr = String::from_utf8_lossy(&retv.stdout);
|
|
|
|
for line in outstr.lines() {
|
|
|
|
tracing::debug!(%name, %line, "actor stdout");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(retv) => {
|
|
|
|
tracing::warn!(%name, ?state, code=?retv.status,
|
|
|
|
"Actor returned nonzero exitcode"
|
|
|
|
);
|
|
|
|
if !retv.stderr.is_empty() {
|
|
|
|
let errstr = String::from_utf8_lossy(&retv.stderr);
|
|
|
|
for line in errstr.lines() {
|
|
|
|
tracing::warn!(%name, %line, "actor stderr");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Err(error) => tracing::warn!(%name, ?error, "process actor failed to run cmd"),
|
|
|
|
}})
|
|
|
|
}
|
|
|
|
}
|