Merge pull request 'execution' (#6) from execution into main
Reviewed-on: #6
This commit is contained in:
commit
d3fb3e8974
6 changed files with 384 additions and 27 deletions
41
01_phase_rust_src/sv/src/executor.rs
Normal file
41
01_phase_rust_src/sv/src/executor.rs
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
|
||||||
|
|
||||||
|
pub mod sent_signal;
|
||||||
|
|
||||||
|
use crate::status_obj;
|
||||||
|
|
||||||
|
pub fn execute(svdir_var: String, svwait_var: i32, verbose: i8, command: &str, services: Vec<String>) -> i32{
|
||||||
|
|
||||||
|
let mut exit_code: i32 = 0;
|
||||||
|
|
||||||
|
for sv in services {
|
||||||
|
let ch1 = sv.chars().next().unwrap();
|
||||||
|
let ch2_row = &sv.chars().collect::<Vec<_>>()[..2];
|
||||||
|
let ch2: String = ch2_row.into_iter().collect();
|
||||||
|
let path;
|
||||||
|
|
||||||
|
if ch1 == '/' || ch2 == "~/"{
|
||||||
|
// case absolute path for the service
|
||||||
|
//
|
||||||
|
path = sv.clone();
|
||||||
|
} else {
|
||||||
|
// case relative path for the service.
|
||||||
|
//
|
||||||
|
path = svdir_var.clone() + "/" + &sv;
|
||||||
|
}
|
||||||
|
|
||||||
|
let status_option = status_obj::StatusObj::new(path, sv);
|
||||||
|
match status_option {
|
||||||
|
Some(status) => {
|
||||||
|
exit_code += sent_signal::sent_signal(svwait_var, verbose, command, status);
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
if exit_code < 99 {
|
||||||
|
exit_code += 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return exit_code
|
||||||
|
|
||||||
|
}
|
48
01_phase_rust_src/sv/src/executor/sent_signal.rs
Normal file
48
01_phase_rust_src/sv/src/executor/sent_signal.rs
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
|
||||||
|
|
||||||
|
use crate::status_obj;
|
||||||
|
|
||||||
|
pub fn sent_signal( svwait_var: i32, verbose: i8, command: &str, mut sv: status_obj::StatusObj) -> i32 {
|
||||||
|
// Return 0 in case everything worked fine, return 1 if timeout or error.
|
||||||
|
|
||||||
|
dbg!(svwait_var);
|
||||||
|
dbg!(verbose);
|
||||||
|
|
||||||
|
// execute command.
|
||||||
|
if command == "s" {
|
||||||
|
// case command is status
|
||||||
|
let mut status_sv = sv.get_status_string();
|
||||||
|
let is_log = sv.get_log();
|
||||||
|
if is_log {
|
||||||
|
let log_option = sv.get_obj_log();
|
||||||
|
match log_option {
|
||||||
|
Some(mut log) => {
|
||||||
|
status_sv = status_sv + "; " + &log.get_status_string();
|
||||||
|
},
|
||||||
|
None => {// TODO: Do nothing for now, eventually, increase by one exit code.
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
println!("{}", status_sv);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//let service = fs::OpenOptions::new().append(true).open("supervise/control");
|
||||||
|
|
||||||
|
//if ! service.is_ok() {
|
||||||
|
// println!("warning: {}: unable to append to supervise/control: file does not exist", sv.clone());
|
||||||
|
// return make_exit_code(exit_code);
|
||||||
|
//}
|
||||||
|
//let mut control = match service {
|
||||||
|
// Ok(file) => file,
|
||||||
|
// Err(..) => panic!("Shouln't goes there, the programmer is trash."),
|
||||||
|
//};
|
||||||
|
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// sent the proper signal to supervise/control
|
||||||
|
//
|
||||||
|
// if verbose = 1, wait for the service to reach the proper state or timeout.
|
||||||
|
println!("Error, command not implemented.");
|
||||||
|
return 1;
|
||||||
|
}
|
|
@ -1,5 +1,7 @@
|
||||||
|
|
||||||
mod parser;
|
mod parser;
|
||||||
|
mod executor;
|
||||||
|
pub mod status_obj;
|
||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
|
@ -23,29 +25,24 @@ fn main() {
|
||||||
Err(..) => 7,
|
Err(..) => 7,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut verbose = 0;
|
let mut verbose: i8 = 0;
|
||||||
|
|
||||||
dbg!(svdir_var);
|
|
||||||
dbg!(svwait_var);
|
|
||||||
|
|
||||||
|
|
||||||
// run the parser
|
// run the parser
|
||||||
let args: Vec<String> = env::args().collect();
|
let args: Vec<String> = env::args().collect();
|
||||||
|
|
||||||
let arg_parser: Vec<String> = parser::parse_args(args);
|
let arg_parser: Vec<String> = parser::parse_args(args);
|
||||||
|
|
||||||
//dbg!(arg_parser);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
let mut command;
|
let mut command = "INVALID";
|
||||||
|
let mut services: Vec<String> = Vec::new();
|
||||||
|
|
||||||
|
// make data from parser.
|
||||||
|
|
||||||
for val in arg_parser.iter() {
|
for val in arg_parser.iter() {
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
if val == "-v" {
|
if val == "-v" {
|
||||||
verbose = 1;
|
verbose = 1;
|
||||||
dbg!(verbose);
|
|
||||||
}
|
}
|
||||||
else if val == "-w" {
|
else if val == "-w" {
|
||||||
i = 3;
|
i = 3;
|
||||||
|
@ -55,32 +52,39 @@ fn main() {
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if val.len() == 2 {
|
if val.len() >= 2 {
|
||||||
println!("sv: illegal option -- {}", val.chars().nth(1).unwrap() );
|
let mut j = 0;
|
||||||
// TODO: thread NOT pannic if it is not an ASCII character.
|
for ch in val.chars() {
|
||||||
|
if j == 1 {
|
||||||
|
println!("sv: illegal option -- {}", ch );
|
||||||
|
}
|
||||||
|
j += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
parser::misc::usage();
|
parser::misc::usage();
|
||||||
exit(100);
|
exit(100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if i == 1 {
|
else if i == 1 {
|
||||||
|
// Set the command as first arguments.
|
||||||
command = val;
|
command = val;
|
||||||
dbg!(command);
|
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
// TODO: Exec the command on all given services.
|
else if i == 2 {
|
||||||
|
// add services to control.
|
||||||
|
services.push(val.to_string());
|
||||||
|
}
|
||||||
else if i == 3 {
|
else if i == 3 {
|
||||||
|
// change svwait after flag -w
|
||||||
svwait_var = match val.parse::<i32>() {
|
svwait_var = match val.parse::<i32>() {
|
||||||
Ok(val) => val,
|
Ok(val) => val,
|
||||||
Err(..) => svwait_var,
|
Err(..) => svwait_var,
|
||||||
};
|
};
|
||||||
dbg!(svwait_var);
|
|
||||||
i = 0;
|
i = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Exit after all services are correctly executed.
|
||||||
|
exit(executor::execute(svdir_var, svwait_var, verbose, command, services));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,7 @@ pub fn parse_args(args: Vec<String>) -> Vec<String>{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return parser;
|
return parser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +72,7 @@ fn phase2(arg: &String) -> String {
|
||||||
|
|
||||||
pub fn parse_args_1(arg: &String) -> String{
|
pub fn parse_args_1(arg: &String) -> String{
|
||||||
// Get a string
|
// Get a string
|
||||||
// Return a vect ('first_char', 'length', 'entry_necessary')
|
// Return the flag.
|
||||||
|
|
||||||
|
|
||||||
let ch1 = arg.chars().next().unwrap();
|
let ch1 = arg.chars().next().unwrap();
|
||||||
|
@ -79,12 +80,13 @@ pub fn parse_args_1(arg: &String) -> String{
|
||||||
//println!("{}", ch1);
|
//println!("{}", ch1);
|
||||||
|
|
||||||
if ch1 == '-' && arg.len() >= 2{
|
if ch1 == '-' && arg.len() >= 2{
|
||||||
return (&arg[..2]).to_string()
|
let retour = &arg.chars().collect::<Vec<_>>()[..2];
|
||||||
|
return retour.into_iter().collect();
|
||||||
} else if ch1 == '-' {
|
} else if ch1 == '-' {
|
||||||
return ch1.to_string()
|
return ch1.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("{}",arg);
|
//println!("{}",arg);
|
||||||
return "".to_string()
|
return "".to_string()
|
||||||
|
|
||||||
|
|
||||||
|
@ -95,15 +97,12 @@ pub fn parse_args_2(arg: &String) -> String{
|
||||||
const POSSIBLE: &'static [&'static str] = &["start", "stop", "reload", "restart", "shutdown", "force-stop", "force-reload", "force-restart", "force-shutdown", "try-restart"];
|
const POSSIBLE: &'static [&'static str] = &["start", "stop", "reload", "restart", "shutdown", "force-stop", "force-reload", "force-restart", "force-shutdown", "try-restart"];
|
||||||
const CPOSSIBLE: &'static [char] = &['s', 'u', 'd', 'o', 'p', 'c', 'h', 'a', 'i', 'q', '1', '2', 't', 'k'];
|
const CPOSSIBLE: &'static [char] = &['s', 'u', 'd', 'o', 'p', 'c', 'h', 'a', 'i', 'q', '1', '2', 't', 'k'];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for var in POSSIBLE.iter() {
|
for var in POSSIBLE.iter() {
|
||||||
if arg == var {
|
if arg == var {
|
||||||
return var.to_string()
|
return var.to_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let ch1 = arg.chars().next().unwrap();
|
let ch1 = arg.chars().next().unwrap();
|
||||||
|
|
||||||
|
|
||||||
|
@ -113,7 +112,6 @@ pub fn parse_args_2(arg: &String) -> String{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return "INVALID".to_string()
|
return "INVALID".to_string()
|
||||||
|
|
||||||
|
|
||||||
|
|
192
01_phase_rust_src/sv/src/status_obj.rs
Normal file
192
01_phase_rust_src/sv/src/status_obj.rs
Normal file
|
@ -0,0 +1,192 @@
|
||||||
|
|
||||||
|
mod misc;
|
||||||
|
|
||||||
|
use std::path::Path;
|
||||||
|
use std::env::set_current_dir;
|
||||||
|
use std::fs;
|
||||||
|
use std::io::prelude::*;
|
||||||
|
use std::time::SystemTime;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pub struct StatusObj {
|
||||||
|
svname: String, // Service name
|
||||||
|
svpath: String, // Service path
|
||||||
|
time: u64, // 0 -> 7
|
||||||
|
//nano_seconds: u32, // 8 -> 11
|
||||||
|
pid: u32, // 12 -> 15
|
||||||
|
pause_run: bool, // 16
|
||||||
|
up_down: char, // 17
|
||||||
|
term_sig: bool, // 18
|
||||||
|
run_finish: bool, // 19
|
||||||
|
down: bool, // is down file ?
|
||||||
|
log: bool, // is log/supervise/ok exists ?
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StatusObj {
|
||||||
|
pub fn new(path_string: String, sv: String ) -> Option<StatusObj> {
|
||||||
|
// if error when making the status_obj, return None,
|
||||||
|
// Else, return the status_obj.
|
||||||
|
//
|
||||||
|
|
||||||
|
let path = Path::new(&path_string);
|
||||||
|
|
||||||
|
if ! set_current_dir(path).is_ok() {
|
||||||
|
println!("fail: {}: unable to change to service directory: file does not exist", sv);
|
||||||
|
return None
|
||||||
|
}
|
||||||
|
let ok_option = Path::new("supervise/ok");
|
||||||
|
if ! ok_option.exists() {
|
||||||
|
println!("warning: {}: unable to open supervise/ok: file does not exist", sv);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: check if there is a process reading the pipe.
|
||||||
|
// piste : https://docs.rs/tokio/latest/tokio/net/unix/pipe/struct.OpenOptions.html
|
||||||
|
//let mut control_option = fs::File::open("supervise/control");
|
||||||
|
//let status_option = fs::OpenOptions::new().read(true).open("supervise/control");
|
||||||
|
//match control_option {
|
||||||
|
// Ok(_file) => {},
|
||||||
|
// Err(ee) => {
|
||||||
|
// println!("fail: {}: runsv not running {}", sv, ee);
|
||||||
|
// return None;
|
||||||
|
// },
|
||||||
|
//};
|
||||||
|
let status_option = fs::OpenOptions::new().read(true).open("supervise/status");
|
||||||
|
let mut status = match status_option {
|
||||||
|
Ok(file) => file,
|
||||||
|
Err(..) => {
|
||||||
|
println!("warning: {}: unable to open supervise/status: file does not exist", sv);
|
||||||
|
return None;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let mut contents: Vec<u8> = Vec::new();
|
||||||
|
let option_size = status.read_to_end(&mut contents);
|
||||||
|
|
||||||
|
let size = match option_size {
|
||||||
|
Ok(size) => size,
|
||||||
|
Err(..) => {
|
||||||
|
println!("warning: {}: couldn't read supervise/status", sv);
|
||||||
|
return None
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if size != 20 {
|
||||||
|
dbg!(size);
|
||||||
|
dbg!(contents);
|
||||||
|
println!("warning: {}: bad supervise/status format", sv);
|
||||||
|
return None
|
||||||
|
}
|
||||||
|
|
||||||
|
let is_down;
|
||||||
|
if Path::new("down").exists() {
|
||||||
|
is_down = true
|
||||||
|
} else {
|
||||||
|
is_down = false
|
||||||
|
}
|
||||||
|
|
||||||
|
let log_exists;
|
||||||
|
if Path::new("log/supervise/ok").exists() {
|
||||||
|
log_exists = true
|
||||||
|
} else {
|
||||||
|
log_exists = false
|
||||||
|
}
|
||||||
|
|
||||||
|
let time_buf: Vec<u8> = contents[0..8].to_vec();
|
||||||
|
//let nano_buf: Vec<u8> = contents[8..12].to_vec();
|
||||||
|
let pid_buf: Vec<u8> = contents[12..16].to_vec();
|
||||||
|
|
||||||
|
let seconds = misc::return_u8_in_u64(time_buf);
|
||||||
|
//let nano = misc::return_u8_in_u32(nano_buf);
|
||||||
|
let pid_found = misc::return_reverse_u8_in_u32(pid_buf);
|
||||||
|
|
||||||
|
let pause_run_raw = misc::make_pause_run(contents[16]); // done
|
||||||
|
let up_down_raw = misc::make_up_down(contents[17]); // done
|
||||||
|
let term_sig_raw = misc::make_term_sig(contents[18]); // done
|
||||||
|
let run_finish_raw = misc::make_run_finish(contents[19]); // done
|
||||||
|
|
||||||
|
Some(StatusObj {
|
||||||
|
svname: sv,
|
||||||
|
svpath: path_string,
|
||||||
|
time: seconds,
|
||||||
|
//nano_seconds: nano,
|
||||||
|
pid: pid_found,
|
||||||
|
pause_run: pause_run_raw,
|
||||||
|
up_down: up_down_raw,
|
||||||
|
term_sig: term_sig_raw,
|
||||||
|
run_finish: run_finish_raw,
|
||||||
|
down: is_down,
|
||||||
|
log: log_exists,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
pub fn get_status_string(&mut self) -> String {
|
||||||
|
|
||||||
|
let status_sv;
|
||||||
|
let pid_string: String;
|
||||||
|
let down_string;
|
||||||
|
let pause_string;
|
||||||
|
let ud_string;
|
||||||
|
let term_string;
|
||||||
|
if self.run_finish == false {
|
||||||
|
status_sv = "down:";
|
||||||
|
pid_string = "".to_owned();
|
||||||
|
if self.down == false {
|
||||||
|
down_string = ", normally up";
|
||||||
|
} else {
|
||||||
|
down_string = "";
|
||||||
|
}
|
||||||
|
if self.up_down == 'u' {
|
||||||
|
ud_string = ", want up";
|
||||||
|
} else {
|
||||||
|
ud_string = "";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
status_sv = "run:";
|
||||||
|
pid_string = "(pid ".to_owned() + &self.pid.to_string() + ") ";
|
||||||
|
if self.down == true {
|
||||||
|
down_string = ", normally down";
|
||||||
|
} else {
|
||||||
|
down_string = "";
|
||||||
|
}
|
||||||
|
if self.up_down == 'd' {
|
||||||
|
ud_string = ", want down";
|
||||||
|
} else {
|
||||||
|
ud_string = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if self.pause_run == true {
|
||||||
|
pause_string = ", paused";
|
||||||
|
} else {
|
||||||
|
pause_string = "";
|
||||||
|
}
|
||||||
|
if self.term_sig == true {
|
||||||
|
term_string = ", got TERM";
|
||||||
|
} else {
|
||||||
|
term_string = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
let time_repaired: u64 = self.time - 4611686018427387914;
|
||||||
|
let sys_time_result = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH);
|
||||||
|
let sys_time = match sys_time_result {
|
||||||
|
Ok(x) => x.as_secs(),
|
||||||
|
Err(..) => time_repaired,
|
||||||
|
};
|
||||||
|
let dif_time = sys_time - time_repaired;
|
||||||
|
|
||||||
|
// Make the string to return
|
||||||
|
let return_string: String = status_sv.to_owned() + " " + &self.svname + ": " + &pid_string + &dif_time.to_string() + "s" + down_string + pause_string + ud_string + term_string;
|
||||||
|
|
||||||
|
return return_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_log(&mut self) -> bool {
|
||||||
|
return self.log;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_obj_log(&mut self) -> Option<StatusObj> {
|
||||||
|
return StatusObj::new(self.svpath.clone() + "/log", "log".to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
74
01_phase_rust_src/sv/src/status_obj/misc.rs
Normal file
74
01_phase_rust_src/sv/src/status_obj/misc.rs
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
|
||||||
|
pub fn make_pause_run(pr_int: u8) -> bool {
|
||||||
|
if pr_int == 0 {
|
||||||
|
return false // run
|
||||||
|
} else {
|
||||||
|
return true // pause.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn make_up_down(ud_int: u8) -> char {
|
||||||
|
if ud_int == 117 {
|
||||||
|
return 'u'
|
||||||
|
} else {
|
||||||
|
return 'd'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn make_term_sig(ts_int: u8) -> bool{
|
||||||
|
if ts_int == 0 {
|
||||||
|
return false // Normal
|
||||||
|
} else {
|
||||||
|
return true // Got Term
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn make_run_finish(rf_int: u8) -> bool {
|
||||||
|
if rf_int == 0 {
|
||||||
|
return false // service finish.
|
||||||
|
} else {
|
||||||
|
return true // service run
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn return_reverse_u8_in_u32(mut table: Vec<u8>) -> u32 {
|
||||||
|
// Table make 4 values u8 in one u32
|
||||||
|
if table.len() != 4 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
let mut r: u32 = 0;
|
||||||
|
table.reverse();
|
||||||
|
for i in table.iter() {
|
||||||
|
r = r * 256;
|
||||||
|
r += <u8 as Into<u32>>::into(*i);
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn return_u8_in_u32(table: Vec<u8>) -> u32 {
|
||||||
|
// Table make 4 values u8 in one u32
|
||||||
|
if table.len() != 4 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
let mut r: u32 = 0;
|
||||||
|
for i in table.iter() {
|
||||||
|
r = r * 256;
|
||||||
|
r += <u8 as Into<u32>>::into(*i);
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn return_u8_in_u64(table: Vec<u8>) -> u64 {
|
||||||
|
// Table make 8 values u8 in one u64
|
||||||
|
if table.len() != 8 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
let mut r: u64 = 0;
|
||||||
|
for i in table.iter() {
|
||||||
|
r = r * 256;
|
||||||
|
r += <u8 as Into<u64>>::into(*i);
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue