Compare commits

...

6 Commits

6 changed files with 122 additions and 71 deletions

2
Cargo.lock generated
View File

@ -1206,7 +1206,7 @@ dependencies = [
[[package]] [[package]]
name = "rasp_mgr" name = "rasp_mgr"
version = "1.0.0" version = "2.0.4"
dependencies = [ dependencies = [
"async-std", "async-std",
"clap", "clap",

View File

@ -1,6 +1,6 @@
[package] [package]
name = "rasp_mgr" name = "rasp_mgr"
version = "1.0.0" version = "2.0.4"
description = "A simple server manager for local newtrok" description = "A simple server manager for local newtrok"
authors = ["PiyushXCoder <piyush.raj.kit@gmail.com>"] authors = ["PiyushXCoder <piyush.raj.kit@gmail.com>"]
license = "GPL-3.0-only" license = "GPL-3.0-only"
@ -12,17 +12,17 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
clap = "2.33.3" clap = "2.33"
toml = "0.5.8" toml = "0.5"
tide = "0.16.0" tide = "0.16"
async-std = { version = "1.6.0", features = ["attributes"] } async-std = { version = "1.6", features = ["attributes"] }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
humantime = "2.1.0" humantime = "2.1"
sys-info = "0.9.0" sys-info = "0.9"
libc = "0.2.97" libc = "0.2"
mnt = "0.3.1" mnt = "0.3"
libmedium = "0.6.0" libmedium = "0.6"

33
api.http Normal file
View File

@ -0,0 +1,33 @@
GET http://0.0.0.0:8080/sysinfo
HTTP/1.1 200 - OK
content-length: 788
content-type: application/json
date: Fri, 24 Dec 2021 16:01:32 GMT
###
GET http://0.0.0.0:8080/cmdquery
HTTP/1.1 200 - OK
content-length: 179
content-type: application/json
date: Fri, 24 Dec 2021 15:58:24 GMT
###
GET http://0.0.0.0:8080/exec/lsblk
HTTP/1.1 200 - OK
content-length: 533
content-type: text/plain;charset=utf-8
date: Fri, 24 Dec 2021 15:48:27 GMT
###
GET http://0.0.0.0:8080/exec/random
HTTP/1.1 400 - Bad Request
content-length: 30
content-type: application/json
date: Fri, 24 Dec 2021 16:05:03 GMT

View File

@ -1,35 +1,29 @@
# Maintainer: Rajnish Mishra <contact.rajnishmishra@gmail.com> # Maintainer: Rajnish Mishra <contact.rajnishmishra@gmail.com>
pkgname=raspmgr-git pkgname=raspmgr
_pkgname=Rasp-Manager _pkgname=Rasp-Manager
pkgver=1.0.0.r11.1901188 pkgver=2.0.2
pkgrel=1 pkgrel=1
pkgdesc="A simple server manager for local network (especially for Raspberry Pi)" pkgdesc="A simple server manager for local network (especially for Raspberry Pi)"
arch=('any') arch=('any')
url="https://github.com/PiyushXCoder/${_pkgname}" url="https://github.com/PiyushXCoder/${_pkgname}"
license=('GPL3') license=('GPL3')
makedepends=('git' 'cargo') makedepends=('git' 'cargo')
source=("git+${url}.git") source=("${_pkgname}-${pkgver}.tar.gz::https://github.com/PiyushXCoder/${_pkgname}/archive/V${pkgver}.tar.gz")
md5sums=('SKIP') sha256sums=('76df28aa278424420914737567085a358eddbbe23840103e72d59f2749d26838')
pkgver() {
cd "${_pkgname}"
v=$(grep -R -A3 '^version =' Cargo.toml | grep 'version =' | cut -d\" -f2)
printf "$v.r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() { prepare() {
cd "${_pkgname}" cd "${_pkgname}-${pkgver}"
sed -i 's/port = 8080/port = 80/g;s/\".\/static\"/\"\/var\/lib\/rasp_mgr\/static\"/g' Config.toml sed -i 's/port = 8080/port = 80/g;s/\".\/static\"/\"\/var\/lib\/rasp_mgr\/static\"/g' Config.toml
} }
build() { build() {
cd "${_pkgname}" cd "${_pkgname}-${pkgver}"
cargo build --release cargo build --release
} }
package() { package() {
cd "${_pkgname}" cd "${_pkgname}-${pkgver}"
install -Dm755 "target/release/rasp_mgr" "${pkgdir}/usr/bin/rasp_mgr" install -Dm755 "target/release/rasp_mgr" "${pkgdir}/usr/bin/rasp_mgr"
install -Dm644 "Config.toml" "${pkgdir}/etc/rasp_mgr/Config.toml" install -Dm644 "Config.toml" "${pkgdir}/etc/rasp_mgr/Config.toml"
install -Dm644 "rasp_mgr.service" "${pkgdir}/usr/lib/systemd/system/rasp_mgr.service" install -Dm644 "rasp_mgr.service" "${pkgdir}/usr/lib/systemd/system/rasp_mgr.service"

View File

@ -14,8 +14,11 @@
use std::{path::Path, process::Command}; use std::{path::Path, process::Command};
use config::Config; use config::Config;
use tide::{prelude::*, Request, Response, http::StatusCode, log::warn}; use libmedium::{
use libmedium::{parse_hwmons,sensors::{Input, Sensor}}; parse_hwmons,
sensors::{Input, Sensor},
};
use tide::{http::StatusCode, log::warn, prelude::*, utils::After, Request, Response};
mod config; mod config;
mod disks; mod disks;
@ -36,20 +39,20 @@ struct SystemInfo {
swap_total: f64, swap_total: f64,
swap_used: f64, swap_used: f64,
disk: Vec<Disk>, disk: Vec<Disk>,
temperature: Vec<Temprature> temperature: Vec<Temprature>,
} }
#[derive(Serialize)] #[derive(Serialize)]
struct Disk { struct Disk {
mount: String, mount: String,
total: f64, total: f64,
available: f64 available: f64,
} }
#[derive(Serialize)] #[derive(Serialize)]
struct Temprature { struct Temprature {
label: String, label: String,
temp: f64 temp: f64,
} }
#[async_std::main] #[async_std::main]
@ -59,11 +62,21 @@ async fn main() -> tide::Result<()> {
tide::log::start(); tide::log::start();
let mut app = tide::with_state(conf.clone()); let mut app = tide::with_state(conf.clone());
app.with(After(|mut res: Response| async move {
if let Some(err) = res.downcast_error::<&str>() {
let err = err.to_owned();
res.set_body(json!({ "message": err }));
}
Ok(res)
}));
if let Some(val) = conf.static_dir { if let Some(val) = conf.static_dir {
let path = Path::new(&val); let path = Path::new(&val);
if path.exists() && path.is_dir() { if path.exists() && path.is_dir() {
app.at("").serve_dir(path.to_str().unwrap())?; app.at("").serve_dir(path.to_str().unwrap())?;
} else { warn!("Static Directory dosen't exists!") } } else {
warn!("Static Directory dosen't exists!")
}
let path = path.join("index.html"); let path = path.join("index.html");
if path.exists() { if path.exists() {
@ -71,11 +84,11 @@ async fn main() -> tide::Result<()> {
} }
} }
app.at("/sysinfo").get(system_info);
app.at("/cmdquery").get(cmd_query);
app.at("/exec/:command").get(exec_cmd); app.at("/exec/:command").get(exec_cmd);
app.at("/poweroff").get(poweroff); app.at("/poweroff").get(poweroff);
app.at("/reboot").get(reboot); app.at("/reboot").get(reboot);
app.at("/sysinfo").get(system_info);
app.at("/cmdquery").get(cmd_query);
app.listen(format!("{}:{}", conf.addr, conf.port)).await?; app.listen(format!("{}:{}", conf.addr, conf.port)).await?;
Ok(()) Ok(())
} }
@ -83,7 +96,9 @@ async fn main() -> tide::Result<()> {
async fn poweroff(_: Request<Config>) -> tide::Result { async fn poweroff(_: Request<Config>) -> tide::Result {
async_std::task::spawn(async { async_std::task::spawn(async {
async_std::task::sleep(std::time::Duration::from_secs(3)).await; async_std::task::sleep(std::time::Duration::from_secs(3)).await;
Command::new("poweroff").spawn().expect("Failed to poweroff!"); Command::new("poweroff")
.spawn()
.expect("Failed to poweroff!");
}); });
Ok("Reqesting to poweroff. Please see green led for for activity".into()) Ok("Reqesting to poweroff. Please see green led for for activity".into())
} }
@ -120,7 +135,7 @@ async fn system_info(_: Request<Config>) -> tide::Result {
disk.push(Disk { disk.push(Disk {
mount: d.mount, mount: d.mount,
total: d.total as f64 / 1048576.0, // bytes to mb total: d.total as f64 / 1048576.0, // bytes to mb
available: d.available as f64 / 1048576.0 // bytes to mb available: d.available as f64 / 1048576.0, // bytes to mb
}); });
} }
@ -131,15 +146,14 @@ async fn system_info(_: Request<Config>) -> tide::Result {
let tmp = temp_sensor.read_input().unwrap(); let tmp = temp_sensor.read_input().unwrap();
temperature.push(Temprature { temperature.push(Temprature {
label: temp_sensor.name(), label: temp_sensor.name(),
temp: tmp.as_degrees_celsius() temp: tmp.as_degrees_celsius(),
}); });
} }
} }
let boottime = std::time::Duration::from_secs(match sys_info::boottime() { let boottime = std::time::Duration::from_secs(match sys_info::boottime() {
Ok(s) => s.tv_sec as u64, Ok(s) => s.tv_sec as u64,
Err(_) => 0 Err(_) => 0,
}); });
let sys_info = SystemInfo { let sys_info = SystemInfo {
@ -157,10 +171,15 @@ async fn system_info(_: Request<Config>) -> tide::Result {
swap_total, swap_total,
swap_used, swap_used,
disk, disk,
temperature temperature,
}; };
Ok(json!(sys_info).to_string().into()) let body = tide::Body::from_json(&sys_info).map_err(|e| {
tide::log::error!("Error: {}", e);
tide::Error::from_str(StatusCode::ServiceUnavailable, "Internal server error!")
})?;
let res = Response::builder(StatusCode::Ok).body(body).build();
Ok(res)
} }
fn last_update() -> Option<String> { fn last_update() -> Option<String> {
@ -169,14 +188,15 @@ fn last_update() -> Option<String> {
let stdout = match cmd.output() { let stdout = match cmd.output() {
Ok(out) => out.stdout, Ok(out) => out.stdout,
Err(_) => return None Err(_) => return None,
}; };
match String::from_utf8(stdout) { match String::from_utf8(stdout) {
Ok(val) => { Ok(val) => {
let s = val.split(" ").next()?; let s = val.split(" ").next()?;
return Some(s[1..s.len()-1].to_owned()); return Some(s[1..s.len() - 1].to_owned());
}, Err(_) => return None }
Err(_) => return None,
} }
} }
@ -189,19 +209,21 @@ fn exec(cmd: &mut Command) -> String {
match String::from_utf8(out.unwrap().stdout) { match String::from_utf8(out.unwrap().stdout) {
Ok(out) => return out, Ok(out) => return out,
Err(_) => return "Request timeout".to_owned() Err(_) => return "Request timeout".to_owned(),
} }
} }
async fn exec_cmd(req: Request<Config>) -> tide::Result { async fn exec_cmd(req: Request<Config>) -> tide::Result {
let cmd = req.state().commands.get( let cmd = req
req.param("command").map_err(|e| { .state()
.commands
.get(req.param("command").map_err(|e| {
tide::log::error!("Error: {}", e); tide::log::error!("Error: {}", e);
tide::Error::from_str(StatusCode::BadRequest, "Invalid Request!") tide::Error::from_str(StatusCode::BadRequest, "Invalid Request!")
})? })?)
).ok_or_else(|| { .ok_or_else(|| tide::Error::from_str(StatusCode::BadRequest, "No such command!"))?
tide::Error::from_str(StatusCode::BadRequest, "No such command!") .command
})?.command.as_str(); .as_str();
let args: Vec<_> = cmd.split_ascii_whitespace().collect(); let args: Vec<_> = cmd.split_ascii_whitespace().collect();
Ok(exec(Command::new(&args[0]).args(&args[1..])).into()) Ok(exec(Command::new(&args[0]).args(&args[1..])).into())
} }

View File

@ -1,5 +1,6 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
@ -8,6 +9,7 @@
<title>Rasp Manager</title> <title>Rasp Manager</title>
<link rel="stylesheet" href="awsm.min.css"> <link rel="stylesheet" href="awsm.min.css">
</head> </head>
<body> <body>
<header> <header>
<h1>Rasp Manager</h1> <h1>Rasp Manager</h1>
@ -30,10 +32,9 @@
<script src="jquery-3.6.0.min.js"></script> <script src="jquery-3.6.0.min.js"></script>
<script> <script>
$.get("/sysinfo", function(data) { $.get("/sysinfo", function (data) {
var data = JSON.parse(data);
var area = $('#sysinfo'); var area = $('#sysinfo');
var pushin = function(parent, label, dat) { var pushin = function (parent, label, dat) {
parent.append($('<b>').append(label)) parent.append($('<b>').append(label))
.append(dat) .append(dat)
.append('<br>'); .append('<br>');
@ -43,10 +44,10 @@
var fset = $('<fieldset>'); var fset = $('<fieldset>');
fset.append($('<legend>').append('System')); fset.append($('<legend>').append('System'));
pushin(fset, 'System Name: ', data.system_name); pushin(fset, 'System Name: ', data.system_name);
if(data.os_version != undefined) if (data.os_version != undefined)
pushin(fset, 'Operating System Version: ', data.os_version); pushin(fset, 'Operating System Version: ', data.os_version);
pushin(fset, 'Kernel Version: ', data.kernel_ver); pushin(fset, 'Kernel Version: ', data.kernel_ver);
if(data.last_uadate != undefined) if (data.last_uadate != undefined)
pushin(fset, 'Last Update: ', data.last_uadate); pushin(fset, 'Last Update: ', data.last_uadate);
pushin(fset, 'Hostname: ', data.hostname); pushin(fset, 'Hostname: ', data.hostname);
pushin(fset, 'Boot Time: ', data.boot_time); pushin(fset, 'Boot Time: ', data.boot_time);
@ -68,38 +69,39 @@
var fset = $('<fieldset>'); var fset = $('<fieldset>');
fset.append($('<legend>').append('Disk')); fset.append($('<legend>').append('Disk'));
fset.append($('<small>', {style:'color: grey'}).append('available/total<br>')); fset.append($('<small>', { style: 'color: grey' }).append('available/total<br>'));
data.disk.forEach(e => { data.disk.forEach(e => {
pushin(fset, '→ '+e.mount, ''); pushin(fset, '→ ' + e.mount, '');
var available = e.available; var available = e.available;
var total = e.total; var total = e.total;
var unit_available = 'MB'; var unit_available = 'MB';
var unit_total = 'MB'; var unit_total = 'MB';
if(available > 1024) { if (available > 1024) {
available /= 1024; available /= 1024;
unit_available = 'GB'; unit_available = 'GB';
} }
if(total > 1024) { if (total > 1024) {
total /= 1024; total /= 1024;
unit_total = 'GB'; unit_total = 'GB';
} }
pushin(fset, '', +available.toFixed(2)+ ' '+unit_available+'/' +total.toFixed(2)+ ' '+unit_total); pushin(fset, '', +available.toFixed(2) + ' ' + unit_available + '/' + total.toFixed(2) + ' ' + unit_total);
}); });
area.append(fset); area.append(fset);
var fset = $('<fieldset>'); var fset = $('<fieldset>');
fset.append($('<legend>').append('Temperature')); fset.append($('<legend>').append('Temperature'));
data.temperature.forEach(e => { data.temperature.forEach(e => {
pushin(fset, '→ '+e.label+': ', e.temp.toFixed(2) +'°C'); pushin(fset, '→ ' + e.label + ': ', e.temp.toFixed(2) + '°C');
}); });
area.append(fset); area.append(fset);
}).fail(function() { }).fail(function () {
$('#sysinfo').empty().append($('<span>', {style: 'color: red'}) $('#sysinfo').empty().append($('<span>', { style: 'color: red' })
.append('Error in getting system information!')); .append('Error in getting system information!'));
}); });
</script> </script>
</body> </body>
</html> </html>