add blocking shell cmd execution

This commit is contained in:
Robin Müller 2024-04-25 01:20:54 +02:00
parent 60e4af435a
commit 1e57b1f978
Signed by: muellerr
GPG Key ID: A649FB78196E3849
2 changed files with 117 additions and 17 deletions

@ -38,6 +38,7 @@ pub enum GroupId {
Hk = 1,
Mode = 2,
Action = 3,
Controller = 4,
}
pub const TEST_EVENT: EventU32TypedSev<SeverityInfo> =
@ -212,6 +213,27 @@ pub mod mode_err {
pub const WRONG_MODE: ResultU16 = ResultU16::new(GroupId::Mode as u8, 0);
}
pub mod ctrl_err {
use super::*;
use satrs::res_code::ResultU16;
#[resultcode]
pub const INVALID_CMD_FORMAT: ResultU16 = ResultU16::new(GroupId::Controller as u8, 0);
#[resultcode]
pub const SHELL_CMD_IO_ERROR: ResultU16 = ResultU16::new(GroupId::Controller as u8, 1);
#[resultcode]
pub const SHELL_CMD_EXECUTION_FAILURE: ResultU16 = ResultU16::new(GroupId::Controller as u8, 2);
#[resultcode]
pub const SHELL_CMD_INVALID_FORMAT: ResultU16 = ResultU16::new(GroupId::Controller as u8, 3);
pub const CTRL_ERR_RESULTS: &[ResultU16Info] = &[
INVALID_CMD_FORMAT_EXT,
SHELL_CMD_IO_ERROR_EXT,
SHELL_CMD_EXECUTION_FAILURE_EXT,
SHELL_CMD_INVALID_FORMAT_EXT,
];
}
pub mod pool {
use satrs::pool::{StaticMemoryPool, StaticPoolConfig};

@ -1,16 +1,23 @@
use num_enum::TryFromPrimitive;
use satrs::{
action::ActionRequest,
action::{ActionRequest, ActionRequestVariant},
params::Params,
pus::action::{ActionReplyPus, ActionReplyVariant},
request::{GenericMessage, MessageMetadata},
res_code::ResultU16,
};
use std::{
env::temp_dir,
path::{Path, PathBuf},
process::Command,
sync::{atomic::AtomicBool, mpsc, Arc},
};
use ops_sat_rs::config::{action_err::INVALID_ACTION_ID, HOME_PATH, STOP_FILE_NAME};
use ops_sat_rs::config::{
action_err::INVALID_ACTION_ID,
ctrl_err::{SHELL_CMD_EXECUTION_FAILURE, SHELL_CMD_INVALID_FORMAT, SHELL_CMD_IO_ERROR},
HOME_PATH, STOP_FILE_NAME,
};
use crate::requests::CompositeRequest;
@ -18,6 +25,7 @@ use crate::requests::CompositeRequest;
#[repr(u32)]
pub enum ActionId {
StopExperiment = 1,
ExecuteShellCommandBlocking = 2,
}
pub struct ExperimentController {
@ -69,34 +77,104 @@ impl ExperimentController {
self.check_stop_file();
}
pub fn send_completion_success(&self, requestor: &MessageMetadata, action_req: &ActionRequest) {
let result = self.action_reply_tx.send(GenericMessage::new_action_reply(
*requestor,
action_req.action_id,
ActionReplyVariant::Completed,
));
if result.is_err() {
log::error!("sending action reply failed");
}
}
pub fn send_completion_failure(
&self,
requestor: &MessageMetadata,
action_req: &ActionRequest,
error_code: ResultU16,
params: Option<Params>,
) {
let result = self.action_reply_tx.send(GenericMessage::new_action_reply(
*requestor,
action_req.action_id,
ActionReplyVariant::CompletionFailed { error_code, params },
));
if result.is_err() {
log::error!("sending action reply failed");
}
}
pub fn handle_action_request(&mut self, requestor: MessageMetadata, action_req: ActionRequest) {
let action_id = ActionId::try_from(action_req.action_id);
if action_id.is_err() {
let send_completion_failure = |error_code: ResultU16, params: Option<Params>| {
let result = self.action_reply_tx.send(GenericMessage::new_action_reply(
requestor,
action_req.action_id,
ActionReplyVariant::CompletionFailed {
error_code: INVALID_ACTION_ID,
params: None,
},
ActionReplyVariant::CompletionFailed { error_code, params },
));
if result.is_err() {
log::error!("sending action reply failed");
}
};
let action_id = ActionId::try_from(action_req.action_id);
if action_id.is_err() {
send_completion_failure(INVALID_ACTION_ID, None);
return;
}
let action_id = action_id.unwrap();
match action_id {
match action_id.unwrap() {
ActionId::StopExperiment => {
self.stop_signal
.store(true, std::sync::atomic::Ordering::Relaxed);
let result = self.action_reply_tx.send(GenericMessage::new_action_reply(
requestor,
action_req.action_id,
ActionReplyVariant::Completed,
));
if result.is_err() {
log::error!("sending action reply failed");
self.send_completion_success(&requestor, &action_req);
}
ActionId::ExecuteShellCommandBlocking => {
self.handle_shell_command_execution(&requestor, &action_req);
}
}
}
pub fn handle_shell_command_execution(
&self,
requestor: &MessageMetadata,
action_req: &ActionRequest,
) {
if let ActionRequestVariant::VecData(data) = &action_req.variant {
match String::from_utf8(data.to_vec()) {
Ok(cmd_str) => {
log::info!("executing command: {}", cmd_str);
match Command::new(cmd_str).status() {
Ok(status) => {
if status.success() {
self.send_completion_success(requestor, action_req);
} else {
log::warn!("execution of command failed: {}", status);
self.send_completion_failure(
requestor,
action_req,
SHELL_CMD_EXECUTION_FAILURE,
Some(status.to_string().into()),
);
}
}
Err(e) => {
log::warn!("execution of command failed with IO error: {}", e);
self.send_completion_failure(
requestor,
action_req,
SHELL_CMD_IO_ERROR,
Some(e.to_string().into()),
);
}
}
}
Err(e) => {
log::warn!("invalid utf-8 data in action request: {}", e);
self.send_completion_failure(
requestor,
action_req,
SHELL_CMD_INVALID_FORMAT,
Some(e.to_string().into()),
);
}
}
}