Merge pull request 'Start and stop go-sbot process' (#78) from sbot_process_start_stop into main
Reviewed-on: #78
This commit is contained in:
@ -16,7 +16,9 @@ use crate::StatsError;
|
|||||||
#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
|
||||||
pub struct SbotStat {
|
pub struct SbotStat {
|
||||||
/// Current process state.
|
/// Current process state.
|
||||||
pub state: String,
|
pub state: Option<String>,
|
||||||
|
/// Current process boot state.
|
||||||
|
pub boot_state: Option<String>,
|
||||||
/// Current process memory usage in bytes.
|
/// Current process memory usage in bytes.
|
||||||
pub memory: Option<u32>,
|
pub memory: Option<u32>,
|
||||||
/// Uptime for the process (if state is `active`).
|
/// Uptime for the process (if state is `active`).
|
||||||
@ -29,7 +31,8 @@ impl SbotStat {
|
|||||||
/// Default builder for `SbotStat`.
|
/// Default builder for `SbotStat`.
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
state: String::new(),
|
state: None,
|
||||||
|
boot_state: None,
|
||||||
memory: None,
|
memory: None,
|
||||||
uptime: None,
|
uptime: None,
|
||||||
downtime: None,
|
downtime: None,
|
||||||
@ -54,7 +57,7 @@ pub fn sbot_stats() -> Result<SbotStat, StatsError> {
|
|||||||
for line in service_info.lines() {
|
for line in service_info.lines() {
|
||||||
if line.starts_with("ActiveState=") {
|
if line.starts_with("ActiveState=") {
|
||||||
if let Some(state) = line.strip_prefix("ActiveState=") {
|
if let Some(state) = line.strip_prefix("ActiveState=") {
|
||||||
status.state = state.to_string()
|
status.state = Some(state.to_string())
|
||||||
}
|
}
|
||||||
} else if line.starts_with("MemoryCurrent=") {
|
} else if line.starts_with("MemoryCurrent=") {
|
||||||
if let Some(memory) = line.strip_prefix("MemoryCurrent=") {
|
if let Some(memory) = line.strip_prefix("MemoryCurrent=") {
|
||||||
@ -68,15 +71,25 @@ pub fn sbot_stats() -> Result<SbotStat, StatsError> {
|
|||||||
.arg("status")
|
.arg("status")
|
||||||
.arg("go-sbot.service")
|
.arg("go-sbot.service")
|
||||||
.output()
|
.output()
|
||||||
.unwrap();
|
.map_err(StatsError::Systemctl)?;
|
||||||
|
|
||||||
let service_status = str::from_utf8(&status_output.stdout).map_err(StatsError::Utf8String)?;
|
let service_status = str::from_utf8(&status_output.stdout).map_err(StatsError::Utf8String)?;
|
||||||
|
|
||||||
// example of the output line we're looking for:
|
|
||||||
// `Active: active (running) since Mon 2022-01-24 16:22:51 SAST; 4min 14s ago`
|
|
||||||
|
|
||||||
for line in service_status.lines() {
|
for line in service_status.lines() {
|
||||||
if line.contains("Active:") {
|
// example of the output line we're looking for:
|
||||||
|
// `Loaded: loaded (/home/glyph/.config/systemd/user/go-sbot.service; enabled; vendor
|
||||||
|
// preset: enabled)`
|
||||||
|
if line.contains("Loaded:") {
|
||||||
|
let before_boot_state = line.find(';');
|
||||||
|
let after_boot_state = line.rfind(';');
|
||||||
|
if let (Some(start), Some(end)) = (before_boot_state, after_boot_state) {
|
||||||
|
// extract the enabled / disabled from the `Loaded: ...` line
|
||||||
|
// using the index of the first ';' + 2 and the last ';'
|
||||||
|
status.boot_state = Some(line[start + 2..end].to_string());
|
||||||
|
}
|
||||||
|
// 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`
|
||||||
|
} 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");
|
||||||
if let (Some(start), Some(end)) = (before_time, after_time) {
|
if let (Some(start), Some(end)) = (before_time, after_time) {
|
||||||
@ -84,10 +97,10 @@ pub fn sbot_stats() -> Result<SbotStat, StatsError> {
|
|||||||
// using the index of ';' + 2 and the index of " ago"
|
// using the index of ';' + 2 and the index of " ago"
|
||||||
let time = Some(&line[start + 2..end]);
|
let time = Some(&line[start + 2..end]);
|
||||||
// if service is active then the `time` reading is uptime
|
// if service is active then the `time` reading is uptime
|
||||||
if status.state == "active" {
|
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 == "inactive" {
|
} else if status.state == Some("inactive".to_string()) {
|
||||||
status.downtime = time.map(|t| t.to_string())
|
status.downtime = time.map(|t| t.to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,13 @@ pub fn mount_peachpub_routes(rocket: Rocket<Build>) -> Rocket<Build> {
|
|||||||
)
|
)
|
||||||
.mount(
|
.mount(
|
||||||
"/settings/scuttlebutt",
|
"/settings/scuttlebutt",
|
||||||
routes![ssb_settings_menu, configure_sbot],
|
routes![
|
||||||
|
ssb_settings_menu,
|
||||||
|
configure_sbot,
|
||||||
|
restart_sbot,
|
||||||
|
start_sbot,
|
||||||
|
stop_sbot
|
||||||
|
],
|
||||||
)
|
)
|
||||||
.mount(
|
.mount(
|
||||||
"/scuttlebutt",
|
"/scuttlebutt",
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use peach_stats::sbot;
|
||||||
use rocket::{get, request::FlashMessage, State};
|
use rocket::{get, request::FlashMessage, State};
|
||||||
use rocket_dyn_templates::{tera::Context, Template};
|
use rocket_dyn_templates::{tera::Context, Template};
|
||||||
|
|
||||||
@ -8,7 +9,11 @@ use crate::RocketConfig;
|
|||||||
|
|
||||||
#[get("/")]
|
#[get("/")]
|
||||||
pub fn home(_auth: Authenticated, config: &State<RocketConfig>) -> Template {
|
pub fn home(_auth: Authenticated, config: &State<RocketConfig>) -> Template {
|
||||||
|
// retrieve go-sbot systemd process stats
|
||||||
|
let sbot_stats = sbot::sbot_stats().ok();
|
||||||
|
|
||||||
let mut context = Context::new();
|
let mut context = Context::new();
|
||||||
|
context.insert("sbot_stats", &sbot_stats);
|
||||||
context.insert("flash_name", &None::<()>);
|
context.insert("flash_name", &None::<()>);
|
||||||
context.insert("flash_msg", &None::<()>);
|
context.insert("flash_msg", &None::<()>);
|
||||||
context.insert("title", &None::<()>);
|
context.insert("title", &None::<()>);
|
||||||
|
@ -1,4 +1,15 @@
|
|||||||
use rocket::{get, request::FlashMessage};
|
use std::{
|
||||||
|
io,
|
||||||
|
process::{Command, Output},
|
||||||
|
};
|
||||||
|
|
||||||
|
use log::info;
|
||||||
|
use peach_stats::sbot;
|
||||||
|
use rocket::{
|
||||||
|
get,
|
||||||
|
request::FlashMessage,
|
||||||
|
response::{Flash, Redirect},
|
||||||
|
};
|
||||||
use rocket_dyn_templates::{tera::Context, Template};
|
use rocket_dyn_templates::{tera::Context, Template};
|
||||||
|
|
||||||
use crate::routes::authentication::Authenticated;
|
use crate::routes::authentication::Authenticated;
|
||||||
@ -9,6 +20,9 @@ use crate::routes::authentication::Authenticated;
|
|||||||
#[get("/")]
|
#[get("/")]
|
||||||
pub fn ssb_settings_menu(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
pub fn ssb_settings_menu(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
||||||
let mut context = Context::new();
|
let mut context = Context::new();
|
||||||
|
// retrieve go-sbot systemd process stats
|
||||||
|
let sbot_stats = sbot::sbot_stats().ok();
|
||||||
|
context.insert("sbot_stats", &sbot_stats);
|
||||||
context.insert("back", &Some("/settings".to_string()));
|
context.insert("back", &Some("/settings".to_string()));
|
||||||
context.insert("title", &Some("Scuttlebutt Settings".to_string()));
|
context.insert("title", &Some("Scuttlebutt Settings".to_string()));
|
||||||
|
|
||||||
@ -34,3 +48,105 @@ pub fn configure_sbot(flash: Option<FlashMessage>, _auth: Authenticated) -> Temp
|
|||||||
|
|
||||||
Template::render("settings/scuttlebutt/configure_sbot", &context.into_json())
|
Template::render("settings/scuttlebutt/configure_sbot", &context.into_json())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Attempt to start the go-sbot.service process.
|
||||||
|
/// Redirect to the Scuttlebutt settings menu and communicate the outcome of
|
||||||
|
/// the attempt via a flash message.
|
||||||
|
#[get("/start")]
|
||||||
|
pub fn start_sbot(_auth: Authenticated) -> Flash<Redirect> {
|
||||||
|
match start_sbot_cmd() {
|
||||||
|
Ok(_) => Flash::success(
|
||||||
|
Redirect::to("/settings/scuttlebutt"),
|
||||||
|
"Sbot process has been started",
|
||||||
|
),
|
||||||
|
Err(_) => Flash::error(
|
||||||
|
Redirect::to("/settings/scuttlebutt"),
|
||||||
|
"Failed to start the sbot process",
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Attempt to stop the go-sbot.service process.
|
||||||
|
/// Redirect to the Scuttlebutt settings menu and communicate the outcome of
|
||||||
|
/// the attempt via a flash message.
|
||||||
|
#[get("/stop")]
|
||||||
|
pub fn stop_sbot(_auth: Authenticated) -> Flash<Redirect> {
|
||||||
|
match stop_sbot_cmd() {
|
||||||
|
Ok(_) => Flash::success(
|
||||||
|
Redirect::to("/settings/scuttlebutt"),
|
||||||
|
"Sbot process has been stopped",
|
||||||
|
),
|
||||||
|
Err(_) => Flash::error(
|
||||||
|
Redirect::to("/settings/scuttlebutt"),
|
||||||
|
"Failed to stop the sbot process",
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Attempt to restart the go-sbot.service process.
|
||||||
|
/// Redirect to the Scuttlebutt settings menu and communicate the outcome of
|
||||||
|
/// the attempt via a flash message.
|
||||||
|
#[get("/restart")]
|
||||||
|
pub fn restart_sbot(_auth: Authenticated) -> Flash<Redirect> {
|
||||||
|
// try to stop the process
|
||||||
|
match stop_sbot_cmd() {
|
||||||
|
// if stop was successful, try to start the process
|
||||||
|
Ok(_) => match start_sbot_cmd() {
|
||||||
|
Ok(_) => Flash::success(
|
||||||
|
Redirect::to("/settings/scuttlebutt"),
|
||||||
|
"Sbot process has been restarted",
|
||||||
|
),
|
||||||
|
|
||||||
|
Err(_) => Flash::error(
|
||||||
|
Redirect::to("/settings/scuttlebutt"),
|
||||||
|
"Failed to start the sbot process",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
Err(_) => Flash::error(
|
||||||
|
Redirect::to("/settings/scuttlebutt"),
|
||||||
|
"Failed to stop the sbot process",
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// HELPER FUNCTIONS
|
||||||
|
|
||||||
|
/// Executes a systemctl disable command for the go-sbot.service process.
|
||||||
|
pub fn disable_sbot_cmd() -> io::Result<Output> {
|
||||||
|
info!("Disabling go-sbot.service");
|
||||||
|
Command::new("systemctl")
|
||||||
|
.arg("--user")
|
||||||
|
.arg("disable")
|
||||||
|
.arg("go-sbot.service")
|
||||||
|
.output()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Executes a systemctl enable command for the go-sbot.service process.
|
||||||
|
pub fn enable_sbot_cmd() -> io::Result<Output> {
|
||||||
|
info!("Enabling go-sbot.service");
|
||||||
|
Command::new("systemctl")
|
||||||
|
.arg("--user")
|
||||||
|
.arg("enable")
|
||||||
|
.arg("go-sbot.service")
|
||||||
|
.output()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Executes a systemctl start command for the go-sbot.service process.
|
||||||
|
pub fn start_sbot_cmd() -> io::Result<Output> {
|
||||||
|
info!("Starting go-sbot.service");
|
||||||
|
Command::new("systemctl")
|
||||||
|
.arg("--user")
|
||||||
|
.arg("start")
|
||||||
|
.arg("go-sbot.service")
|
||||||
|
.output()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Executes a systemctl stop command for the go-sbot.service process.
|
||||||
|
pub fn stop_sbot_cmd() -> io::Result<Output> {
|
||||||
|
info!("Stopping go-sbot.service");
|
||||||
|
Command::new("systemctl")
|
||||||
|
.arg("--user")
|
||||||
|
.arg("stop")
|
||||||
|
.arg("go-sbot.service")
|
||||||
|
.output()
|
||||||
|
}
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
</a>
|
</a>
|
||||||
<!-- middle -->
|
<!-- middle -->
|
||||||
<a class="middle">
|
<a class="middle">
|
||||||
<div class="circle circle-large"></div>
|
<div class="circle circle-large {% if sbot_stats.state == "active" %}circle-success{% else %}circle-error{% endif %}"></div>
|
||||||
</a>
|
</a>
|
||||||
<!-- bottom-left -->
|
<!-- bottom-left -->
|
||||||
<!-- SYSTEM STATUS LINK AND ICON -->
|
<!-- SYSTEM STATUS LINK AND ICON -->
|
||||||
|
@ -41,11 +41,14 @@
|
|||||||
</div>
|
</div>
|
||||||
<br>
|
<br>
|
||||||
<div class="center" style="width: 80%;" title="Broadcast the IP and port of this sbot instance so that local peers can discovery it and attempt to connect">
|
<div class="center" style="width: 80%;" title="Broadcast the IP and port of this sbot instance so that local peers can discovery it and attempt to connect">
|
||||||
<input type="checkbox" id="lan_broadcast" name="lan_broadcast">
|
<input type="checkbox" id="lanBroadcast" name="lan_broadcast">
|
||||||
<label for="lan_broadcast">Enable LAN Broadcasting</label><br>
|
<label for="lanBroadcast">Enable LAN Broadcasting</label><br>
|
||||||
<br>
|
<br>
|
||||||
<input type="checkbox" id="lan_discovery" name="lan_discovery" title="Listen for the presence of local peers and attempt to connect if found">
|
<input type="checkbox" id="lanDiscovery" name="lan_discovery" title="Listen for the presence of local peers and attempt to connect if found">
|
||||||
<label for="lan_discovery">Enable LAN Discovery</label><br>
|
<label for="lanDiscovery">Enable LAN Discovery</label><br>
|
||||||
|
<br>
|
||||||
|
<input type="checkbox" id="startup" name="startup" title="Define whether the pub runs automatically on system startup">
|
||||||
|
<label for="startup">Run pub on system startup</label><br>
|
||||||
</div>
|
</div>
|
||||||
<br>
|
<br>
|
||||||
<input class="button button-primary center" type="button" value="Save">
|
<input class="button button-primary center" type="button" value="Save">
|
||||||
|
@ -5,12 +5,17 @@
|
|||||||
<!-- BUTTONS -->
|
<!-- BUTTONS -->
|
||||||
<div id="settingsButtons">
|
<div id="settingsButtons">
|
||||||
<a id="configureSbot" class="button button-primary center" href="/settings/scuttlebutt/configure" title="Configure Sbot">Configure Sbot</a>
|
<a id="configureSbot" class="button button-primary center" href="/settings/scuttlebutt/configure" title="Configure Sbot">Configure Sbot</a>
|
||||||
<a id="disable" class="button button-primary center" href="/settings/scuttlebutt/disable" title="Disable Sbot">Disable Sbot</a>
|
{% if sbot_stats.state == "active" %}
|
||||||
<a id="enable" class="button button-primary center" href="/settings/scuttlebutt/enable" title="Enable Sbot">Enable Sbot</a>
|
<a id="stop" class="button button-primary center" href="/settings/scuttlebutt/stop" title="Stop Sbot">Stop Sbot</a>
|
||||||
<a id="restart" class="button button-primary center" href="/settings/scuttlebutt/restart" title="Restart Sbot">Restart Sbot</a>
|
<a id="restart" class="button button-primary center" href="/settings/scuttlebutt/restart" title="Restart Sbot">Restart Sbot</a>
|
||||||
|
{% else %}
|
||||||
|
<a id="start" class="button button-primary center" href="/settings/scuttlebutt/start" title="Start Sbot">Start Sbot</a>
|
||||||
|
{% endif %}
|
||||||
<a id="checkFilesystem" class="button button-primary center" href="/settings/scuttlebutt/check_fs" title="Check Filesystem">Check Filesystem</a>
|
<a id="checkFilesystem" class="button button-primary center" href="/settings/scuttlebutt/check_fs" title="Check Filesystem">Check Filesystem</a>
|
||||||
<a id="repairFilesystem" class="button button-primary center" href="/settings/scuttlebutt/repair" title="Repair Filesystem">Repair Filesystem</a>
|
<a id="repairFilesystem" class="button button-primary center" href="/settings/scuttlebutt/repair" title="Repair Filesystem">Repair Filesystem</a>
|
||||||
<a id="removeFeeds" class="button button-primary center" href="/settings/scuttlebutt/remove_feeds" title="Remove Blocked Feeds">Remove Blocked Feeds</a>
|
<a id="removeFeeds" class="button button-primary center" href="/settings/scuttlebutt/remove_feeds" title="Remove Blocked Feeds">Remove Blocked Feeds</a>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- FLASH MESSAGE -->
|
||||||
|
{% include "snippets/flash_message" %}
|
||||||
</div>
|
</div>
|
||||||
{%- endblock card -%}
|
{%- endblock card -%}
|
||||||
|
@ -31,10 +31,18 @@
|
|||||||
{% if sbot_stats.state == "active" %}
|
{% if sbot_stats.state == "active" %}
|
||||||
<label class="label-small font-gray" for="sbotUptime" title="go-sbot uptime" style="margin-top: 0.5rem;">UPTIME</label>
|
<label class="label-small font-gray" for="sbotUptime" title="go-sbot uptime" style="margin-top: 0.5rem;">UPTIME</label>
|
||||||
<p id="sbotUptime" class="card-text" title="Uptime">{{ sbot_stats.uptime }}</p>
|
<p id="sbotUptime" class="card-text" title="Uptime">{{ sbot_stats.uptime }}</p>
|
||||||
{%- else -%}
|
{# render downtime element if downtime is `Some(time)` #}
|
||||||
|
{# downtime will be `None` if service is stopped and disabled #}
|
||||||
|
{%- elif sbot_stats.downtime -%}
|
||||||
<label class="label-small font-gray" for="sbotDowntime" title="go-sbot downtime" style="margin-top: 0.5rem;">DOWNTIME</label>
|
<label class="label-small font-gray" for="sbotDowntime" title="go-sbot downtime" style="margin-top: 0.5rem;">DOWNTIME</label>
|
||||||
<p id="sbotDowntime" class="card-text" title="Downtime">{{ sbot_stats.downtime }}</p>
|
<p id="sbotDowntime" class="card-text" title="Downtime">{{ sbot_stats.downtime }}</p>
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
|
<label class="label-small font-gray" for="sbotBootState" title="go-sbot boot state" style="margin-top: 0.5rem;">RUN ON STARTUP</label>
|
||||||
|
{% if sbot_stats.boot_state == "enabled" %}
|
||||||
|
<p id="runOnStartup" class="card-text" title="Enabled">Enabled</p>
|
||||||
|
{% else %}
|
||||||
|
<p id="runOnStartup" class="card-text" title="Disabled">Disabled</p>
|
||||||
|
{%- endif -%}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr style="color: var(--light-gray);">
|
<hr style="color: var(--light-gray);">
|
||||||
|
Reference in New Issue
Block a user