Compare commits
6 Commits
main
...
supervisor
Author | SHA1 | Date |
---|---|---|
notplants | ec93c9830b | |
notplants | f6c30a327a | |
notplants | dbf1c648ae | |
notplants | 8d9aeb6662 | |
notplants | b24fb387b9 | |
notplants | ceb7e502ce |
|
@ -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",
|
||||||
|
|
|
@ -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"
|
||||||
|
|
||||||
|
|
|
@ -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"),
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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())
|
||||||
}
|
}
|
||||||
|
|
|
@ -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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
Loading…
Reference in New Issue