api2/node/services.rs: start services api
This commit is contained in:
parent
0f253593c6
commit
d2ab5f19e2
@ -6,6 +6,7 @@ mod time;
|
||||
mod network;
|
||||
mod dns;
|
||||
mod syslog;
|
||||
mod services;
|
||||
|
||||
pub fn router() -> Router {
|
||||
|
||||
@ -19,6 +20,7 @@ pub fn router() -> Router {
|
||||
ObjectSchema::new("Directory index.")))
|
||||
.subdir("dns", dns::router())
|
||||
.subdir("network", network::router())
|
||||
.subdir("services", services::router())
|
||||
.subdir("syslog", syslog::router())
|
||||
.subdir("time", time::router());
|
||||
|
||||
|
119
src/api2/node/services.rs
Normal file
119
src/api2/node/services.rs
Normal file
@ -0,0 +1,119 @@
|
||||
use failure::*;
|
||||
|
||||
use crate::tools;
|
||||
use crate::api::schema::*;
|
||||
use crate::api::router::*;
|
||||
use serde_json::{json, Value};
|
||||
|
||||
use std::sync::Arc;
|
||||
use lazy_static::lazy_static;
|
||||
use crate::tools::common_regex;
|
||||
use std::process::{Command, Stdio};
|
||||
|
||||
static SERVICE_NAME_LIST: [&str; 6] = [
|
||||
"proxmox-backup",
|
||||
"sshd",
|
||||
"syslog",
|
||||
"cron",
|
||||
"postfix",
|
||||
"systemd-timesyncd",
|
||||
];
|
||||
|
||||
fn get_full_service_state(service: &str) -> Result<Value, Error> {
|
||||
|
||||
let mut real_service_name = service;
|
||||
|
||||
// since postfix package 3.1.0-3.1 the postfix unit is only here
|
||||
// to manage subinstances, of which the default is called "-".
|
||||
// This is where we look for the daemon status
|
||||
|
||||
if service == "postfix" { real_service_name = "postfix@-"; }
|
||||
|
||||
let mut child = Command::new("/bin/systemctl")
|
||||
.args(&["show", real_service_name])
|
||||
.stdout(Stdio::piped())
|
||||
.spawn()?;
|
||||
|
||||
use std::io::{BufRead,BufReader};
|
||||
|
||||
let mut result = json!({});
|
||||
|
||||
if let Some(ref mut stdout) = child.stdout {
|
||||
for line in BufReader::new(stdout).lines() {
|
||||
match line {
|
||||
Ok(line) => {
|
||||
let mut iter = line.splitn(2, '=');
|
||||
let key = iter.next();
|
||||
let value = iter.next();
|
||||
if let (Some(key), Some(value)) = (key, value) {
|
||||
result[key] = Value::from(value);
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
log::error!("reading service config failed: {}", err);
|
||||
let _ = child.kill();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let status = child.wait().unwrap();
|
||||
if !status.success() {
|
||||
bail!("systemctl show failed with {}", status);
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn list_services(
|
||||
param: Value,
|
||||
_info: &ApiMethod,
|
||||
rpcenv: &mut RpcEnvironment,
|
||||
) -> Result<Value, Error> {
|
||||
|
||||
let mut list = vec![];
|
||||
|
||||
for service in &SERVICE_NAME_LIST {
|
||||
match get_full_service_state(service) {
|
||||
Ok(status) => {
|
||||
if let Some(desc) = status["Description"].as_str() {
|
||||
let name = status["Name"].as_str().unwrap_or(service);
|
||||
let state = status["SubState"].as_str().unwrap_or("unknown");
|
||||
list.push(json!({
|
||||
"service": service,
|
||||
"name": name,
|
||||
"desc": desc,
|
||||
"state": state,
|
||||
}));
|
||||
}
|
||||
}
|
||||
Err(err) => log::error!("{}", err),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Value::from(list))
|
||||
}
|
||||
|
||||
pub fn router() -> Router {
|
||||
|
||||
let route = Router::new()
|
||||
.get(
|
||||
ApiMethod::new(
|
||||
list_services,
|
||||
ObjectSchema::new("Service list.")
|
||||
).returns(
|
||||
ArraySchema::new(
|
||||
"Returns a list of systemd services.",
|
||||
ObjectSchema::new("Service details.")
|
||||
.required("service", StringSchema::new("Service ID."))
|
||||
.required("name", StringSchema::new("systemd service name."))
|
||||
.required("desc", StringSchema::new("systemd service description."))
|
||||
.required("state", StringSchema::new("systemd service 'SubState'."))
|
||||
.into()
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
route
|
||||
}
|
Loading…
Reference in New Issue
Block a user