Compare commits

...

6 Commits

Author SHA1 Message Date
notplants ec93c9830b Formatting 2022-07-28 14:58:24 +02:00
notplants f6c30a327a Remove debug statements 2022-07-28 14:56:27 +02:00
notplants dbf1c648ae Working in docker 2022-07-28 14:53:45 +02:00
notplants 8d9aeb6662 Change default name of go-sbot.service to go-sbot 2022-07-28 14:01:19 +02:00
notplants b24fb387b9 Fix supervisorctl 2022-07-27 19:03:36 +02:00
notplants ceb7e502ce modifications to system commands 2022-07-20 14:26:37 +02:00
11 changed files with 112 additions and 27 deletions

2
Cargo.lock generated
View File

@ -2241,7 +2241,7 @@ dependencies = [
[[package]] [[package]]
name = "peach-lib" name = "peach-lib"
version = "1.3.4" version = "1.3.5"
dependencies = [ dependencies = [
"async-std", "async-std",
"chrono", "chrono",

View File

@ -1,6 +1,6 @@
[package] [package]
name = "peach-lib" name = "peach-lib"
version = "1.3.4" version = "1.3.5"
authors = ["Andrew Reid <glyph@mycelial.technology>"] authors = ["Andrew Reid <glyph@mycelial.technology>"]
edition = "2018" edition = "2018"

View File

@ -57,10 +57,11 @@ pub fn get_peach_config_defaults() -> HashMap<String, String> {
("DYN_NAMESERVER", "ns.peachcloud.org"), ("DYN_NAMESERVER", "ns.peachcloud.org"),
("DYN_ENABLED", "false"), ("DYN_ENABLED", "false"),
("SSB_ADMIN_IDS", ""), ("SSB_ADMIN_IDS", ""),
("SYSTEM_MANAGER", "systemd"),
("ADMIN_PASSWORD_HASH", "47"), ("ADMIN_PASSWORD_HASH", "47"),
("TEMPORARY_PASSWORD_HASH", ""), ("TEMPORARY_PASSWORD_HASH", ""),
("GO_SBOT_DATADIR", "/home/peach/.ssb-go"), ("GO_SBOT_DATADIR", "/home/peach/.ssb-go"),
("GO_SBOT_SERVICE", "go-sbot.service"), ("GO_SBOT_SERVICE", "go-sbot"),
("PEACH_CONFIGDIR", "/var/lib/peachcloud"), ("PEACH_CONFIGDIR", "/var/lib/peachcloud"),
("PEACH_HOMEDIR", "/home/peach"), ("PEACH_HOMEDIR", "/home/peach"),
("PEACH_WEBDIR", "/usr/share/peach-web"), ("PEACH_WEBDIR", "/usr/share/peach-web"),

View File

@ -106,6 +106,10 @@ pub enum PeachError {
/// Represents a Golgi error /// Represents a Golgi error
Golgi(GolgiError), Golgi(GolgiError),
/// Represents a generic system error, whose details are specified in the string message
System(String),
} }
impl std::error::Error for PeachError { impl std::error::Error for PeachError {
@ -135,6 +139,7 @@ impl std::error::Error for PeachError {
PeachError::Utf8ToString(_) => None, PeachError::Utf8ToString(_) => None,
PeachError::Write { ref source, .. } => Some(source), PeachError::Write { ref source, .. } => Some(source),
PeachError::Golgi(_) => None, PeachError::Golgi(_) => None,
PeachError::System(_) => None,
} }
} }
} }
@ -193,6 +198,9 @@ impl std::fmt::Display for PeachError {
write!(f, "Write error: {}", path) write!(f, "Write error: {}", path)
} }
PeachError::Golgi(ref err) => err.fmt(f), PeachError::Golgi(ref err) => err.fmt(f),
PeachError::System(ref msg) => {
write!(f, "system error: {}", msg)
}
} }
} }
} }
@ -268,3 +276,4 @@ impl From<GolgiError> for PeachError {
PeachError::Golgi(err) PeachError::Golgi(err)
} }
} }

View File

@ -3,7 +3,7 @@
use std::{fs, fs::File, io, io::Write, path::PathBuf, process::Command, str}; use std::{fs, fs::File, io, io::Write, path::PathBuf, process::Command, str};
use golgi::{sbot::Keystore, Sbot}; use golgi::{sbot::Keystore, Sbot};
use log::debug; use log::{debug};
use crate::config_manager; use crate::config_manager;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -64,6 +64,41 @@ impl Default for SbotStatus {
impl SbotStatus { impl SbotStatus {
/// Retrieve statistics for the go-sbot systemd process by querying `systemctl`. /// Retrieve statistics for the go-sbot systemd process by querying `systemctl`.
pub fn read() -> Result<Self, PeachError> { pub fn read() -> Result<Self, PeachError> {
let system_manager = config_manager::get_config_value("SYSTEM_MANAGER")?;
match system_manager.as_str() {
"systemd" => {
SbotStatus::read_from_systemctl()
},
"supervisord" => {
SbotStatus::read_from_supervisorctl()
},
_ => Err(PeachError::System(format!(
"Invalid configuration for SYSTEM_MANAGER: {:?}",
system_manager)))
}
}
pub fn read_from_supervisorctl() -> Result<Self, PeachError> {
let mut status = SbotStatus::default();
let info_output = Command::new("supervisorctl")
.arg("status")
.arg(config_manager::get_config_value("GO_SBOT_SERVICE")?)
.output()?;
let service_info = std::str::from_utf8(&info_output.stdout)?;
for line in service_info.lines() {
// example line
// go-sbot RUNNING pid 11, uptime 0:04:23
if line.contains("RUNNING") {
// TODO: this should be an enum
status.state = Some("active".to_string());
}
}
Ok(status)
}
pub fn read_from_systemctl() -> Result<Self, PeachError> {
let mut status = SbotStatus::default(); let mut status = SbotStatus::default();
// note this command does not need to be run as sudo // note this command does not need to be run as sudo
@ -110,8 +145,8 @@ impl SbotStatus {
// using the index of the first ';' + 2 and the last ';' // using the index of the first ';' + 2 and the last ';'
status.boot_state = Some(line[start + 2..end].to_string()); status.boot_state = Some(line[start + 2..end].to_string());
} }
// example of the output line we're looking for here: // example of the output line we're looking for here:
// `Active: active (running) since Mon 2022-01-24 16:22:51 SAST; 4min 14s ago` // `Active: active (running) since Mon 2022-01-24 16:22:51 SAST; 4min 14s ago`
} else if line.contains("Active:") { } else if line.contains("Active:") {
let before_time = line.find(';'); let before_time = line.find(';');
let after_time = line.find(" ago"); let after_time = line.find(" ago");
@ -122,7 +157,7 @@ impl SbotStatus {
// if service is active then the `time` reading is uptime // if service is active then the `time` reading is uptime
if status.state == Some("active".to_string()) { if status.state == Some("active".to_string()) {
status.uptime = time.map(|t| t.to_string()) status.uptime = time.map(|t| t.to_string())
// if service is inactive then the `time` reading is downtime // if service is inactive then the `time` reading is downtime
} else if status.state == Some("inactive".to_string()) { } else if status.state == Some("inactive".to_string()) {
status.downtime = time.map(|t| t.to_string()) status.downtime = time.map(|t| t.to_string())
} }

View File

@ -18,6 +18,7 @@ pub enum PeachWebError {
Json(JsonError), Json(JsonError),
OsString, OsString,
PeachLib { source: PeachError, msg: String }, PeachLib { source: PeachError, msg: String },
System(String),
Yaml(YamlError), Yaml(YamlError),
} }
@ -31,6 +32,7 @@ impl std::error::Error for PeachWebError {
PeachWebError::Json(ref source) => Some(source), PeachWebError::Json(ref source) => Some(source),
PeachWebError::OsString => None, PeachWebError::OsString => None,
PeachWebError::PeachLib { ref source, .. } => Some(source), PeachWebError::PeachLib { ref source, .. } => Some(source),
PeachWebError::System(_) => None,
PeachWebError::Yaml(ref source) => Some(source), PeachWebError::Yaml(ref source) => Some(source),
} }
} }
@ -54,6 +56,9 @@ impl std::fmt::Display for PeachWebError {
"Filesystem error: failed to convert OsString to String for go-ssb directory path" "Filesystem error: failed to convert OsString to String for go-ssb directory path"
), ),
PeachWebError::PeachLib { ref source, .. } => write!(f, "{}", source), PeachWebError::PeachLib { ref source, .. } => write!(f, "{}", source),
PeachWebError::System(ref msg) => {
write!(f, "system error: {}", msg)
}
PeachWebError::Yaml(ref source) => write!(f, "Serde YAML error: {}", source), PeachWebError::Yaml(ref source) => write!(f, "Serde YAML error: {}", source),
} }
} }

View File

@ -243,13 +243,13 @@ pub fn handle_form(request: &Request, restart: bool) -> Response {
match data.startup { match data.startup {
true => { true => {
debug!("Enabling go-sbot.service"); debug!("Enabling go-sbot.service");
if let Err(e) = sbot::systemctl_sbot_cmd("enable") { if let Err(e) = sbot::system_sbot_cmd("enable") {
warn!("Failed to enable go-sbot.service: {}", e) warn!("Failed to enable go-sbot.service: {}", e)
} }
} }
false => { false => {
debug!("Disabling go-sbot.service"); debug!("Disabling go-sbot.service");
if let Err(e) = sbot::systemctl_sbot_cmd("disable") { if let Err(e) = sbot::system_sbot_cmd("disable") {
warn!("Failed to disable go-sbot.service: {}", e) warn!("Failed to disable go-sbot.service: {}", e)
} }
} }

View File

@ -1,7 +1,7 @@
use log::info; use log::info;
use rouille::Response; use rouille::Response;
use crate::utils::{flash::FlashResponse, sbot::systemctl_sbot_cmd}; use crate::utils::{flash::FlashResponse, sbot};
// ROUTE: /settings/scuttlebutt/restart // ROUTE: /settings/scuttlebutt/restart
@ -10,9 +10,9 @@ use crate::utils::{flash::FlashResponse, sbot::systemctl_sbot_cmd};
/// the attempt via a flash message. /// the attempt via a flash message.
pub fn restart_sbot() -> Response { pub fn restart_sbot() -> Response {
info!("Restarting go-sbot.service"); info!("Restarting go-sbot.service");
let (flash_name, flash_msg) = match systemctl_sbot_cmd("stop") { let (flash_name, flash_msg) = match sbot::system_sbot_cmd("stop") {
// if stop was successful, try to start the process // if stop was successful, try to start the process
Ok(_) => match systemctl_sbot_cmd("start") { Ok(_) => match sbot::system_sbot_cmd("start") {
Ok(_) => ( Ok(_) => (
"flash_name=success".to_string(), "flash_name=success".to_string(),
"flash_msg=Sbot process has been restarted".to_string(), "flash_msg=Sbot process has been restarted".to_string(),

View File

@ -1,7 +1,7 @@
use log::info; use log::info;
use rouille::Response; use rouille::Response;
use crate::utils::{flash::FlashResponse, sbot::systemctl_sbot_cmd}; use crate::utils::{flash::FlashResponse, sbot};
// ROUTE: /settings/scuttlebutt/start // ROUTE: /settings/scuttlebutt/start
@ -10,7 +10,7 @@ use crate::utils::{flash::FlashResponse, sbot::systemctl_sbot_cmd};
/// the attempt via a flash message. /// the attempt via a flash message.
pub fn start_sbot() -> Response { pub fn start_sbot() -> Response {
info!("Starting go-sbot.service"); info!("Starting go-sbot.service");
let (flash_name, flash_msg) = match systemctl_sbot_cmd("start") { let (flash_name, flash_msg) = match sbot::system_sbot_cmd("start") {
Ok(_) => ( Ok(_) => (
"flash_name=success".to_string(), "flash_name=success".to_string(),
"flash_msg=Sbot process has been started".to_string(), "flash_msg=Sbot process has been started".to_string(),

View File

@ -1,7 +1,7 @@
use log::info; use log::info;
use rouille::Response; use rouille::Response;
use crate::utils::{flash::FlashResponse, sbot::systemctl_sbot_cmd}; use crate::utils::{flash::FlashResponse, sbot};
// ROUTE: /settings/scuttlebutt/stop // ROUTE: /settings/scuttlebutt/stop
@ -10,7 +10,7 @@ use crate::utils::{flash::FlashResponse, sbot::systemctl_sbot_cmd};
/// the attempt via a flash message. /// the attempt via a flash message.
pub fn stop_sbot() -> Response { pub fn stop_sbot() -> Response {
info!("Stopping go-sbot.service"); info!("Stopping go-sbot.service");
let (flash_name, flash_msg) = match systemctl_sbot_cmd("stop") { let (flash_name, flash_msg) = match sbot::system_sbot_cmd("stop") {
Ok(_) => ( Ok(_) => (
"flash_name=success".to_string(), "flash_name=success".to_string(),
"flash_msg=Sbot process has been stopped".to_string(), "flash_msg=Sbot process has been stopped".to_string(),

View File

@ -24,23 +24,58 @@ use crate::{error::PeachWebError, utils::sbot};
// SBOT HELPER FUNCTIONS // SBOT HELPER FUNCTIONS
/// Executes a systemctl command for the go-sbot.service process. /// On non-docker based deployments (peachcloud, yunohost), we use systemctl
pub fn systemctl_sbot_cmd(cmd: &str) -> Result<Output, PeachWebError> { /// On docker-based deployments, we use supervisord
let output = Command::new("sudo") /// This utility function calls the correct system calls based on these parameters.
.arg("systemctl") pub fn system_sbot_cmd(cmd: &str) -> Result<Output, PeachWebError> {
.arg(cmd) let system_manager = config_manager::get_config_value("SYSTEM_MANAGER")?;
.arg(config_manager::get_config_value("GO_SBOT_SERVICE")?) match system_manager.as_str() {
.output()?; "systemd" => {
Ok(output) let output = Command::new("sudo")
.arg("systemctl")
.arg(cmd)
.arg(config_manager::get_config_value("GO_SBOT_SERVICE")?)
.output()?;
Ok(output)
}
"supervisord" => {
match cmd {
"enable" => {
// TODO: implement this
let output = Command::new("echo")
.arg("implement this (enable)")
.output()?;
Ok(output)
}
"disable" => {
let output = Command::new("echo")
.arg("implement this (disable)")
.output()?;
Ok(output)
}
_ => {
let output = Command::new("supervisorctl")
.arg(cmd)
.arg(config_manager::get_config_value("GO_SBOT_SERVICE")?)
.output()?;
Ok(output)
}
}
}
_ => Err(PeachWebError::System(format!(
"Invalid configuration for SYSTEM_MANAGER: {:?}",
system_manager
))),
}
} }
/// Executes a systemctl stop command followed by start command. /// Executes a system stop command followed by start command.
/// Returns a redirect with a flash message stating the output of the restart attempt. /// Returns a redirect with a flash message stating the output of the restart attempt.
pub fn restart_sbot_process() -> (String, String) { pub fn restart_sbot_process() -> (String, String) {
debug!("Restarting go-sbot.service"); debug!("Restarting go-sbot.service");
match systemctl_sbot_cmd("stop") { match system_sbot_cmd("stop") {
// if stop was successful, try to start the process // if stop was successful, try to start the process
Ok(_) => match systemctl_sbot_cmd("start") { Ok(_) => match system_sbot_cmd("start") {
Ok(_) => ( Ok(_) => (
"success".to_string(), "success".to_string(),
"Updated configuration and restarted the sbot process".to_string(), "Updated configuration and restarted the sbot process".to_string(),