proxmox-backup/src/api2/node/journal.rs
2020-04-30 09:30:00 +02:00

127 lines
3.4 KiB
Rust

use std::process::{Command, Stdio};
use anyhow::{Error};
use serde_json::{json, Value};
use std::io::{BufRead,BufReader};
use proxmox::api::{api, ApiMethod, Router, RpcEnvironment, Permission};
use crate::api2::types::*;
use crate::config::acl::PRIV_SYS_AUDIT;
#[api(
protected: true,
input: {
properties: {
node: {
schema: NODE_SCHEMA,
},
since: {
type: Integer,
optional: true,
description: "Display all log since this UNIX epoch. Conflicts with 'startcursor'.",
minimum: 0,
},
until: {
type: Integer,
optional: true,
description: "Display all log until this UNIX epoch. Conflicts with 'endcursor'.",
minimum: 0,
},
lastentries: {
type: Integer,
optional: true,
description: "Limit to the last X lines. Conflicts with a range.",
minimum: 0,
},
startcursor: {
type: String,
description: "Start after the given Cursor. Conflicts with 'since'.",
optional: true,
},
endcursor: {
type: String,
description: "End before the given Cursor. Conflicts with 'until'",
optional: true,
},
},
},
returns: {
type: Array,
description: "Returns a list of journal entries.",
items: {
type: String,
description: "Line text.",
},
},
access: {
permission: &Permission::Privilege(&["system", "log"], PRIV_SYS_AUDIT, false),
},
)]
/// Read syslog entries.
fn get_journal(
param: Value,
_info: &ApiMethod,
_rpcenv: &mut dyn RpcEnvironment,
) -> Result<Value, Error> {
let mut args = vec![];
if let Some(lastentries) = param["lastentries"].as_u64() {
args.push(String::from("-n"));
args.push(format!("{}", lastentries));
}
if let Some(since) = param["since"].as_str() {
args.push(String::from("-b"));
args.push(since.to_owned());
}
if let Some(until) = param["until"].as_str() {
args.push(String::from("-e"));
args.push(until.to_owned());
}
if let Some(startcursor) = param["startcursor"].as_str() {
args.push(String::from("-f"));
args.push(startcursor.to_owned());
}
if let Some(endcursor) = param["endcursor"].as_str() {
args.push(String::from("-t"));
args.push(endcursor.to_owned());
}
let mut lines: Vec<String> = vec![];
let mut child = Command::new("/usr/bin/mini-journalreader")
.args(&args)
.stdout(Stdio::piped())
.spawn()?;
if let Some(ref mut stdout) = child.stdout {
for line in BufReader::new(stdout).lines() {
match line {
Ok(line) => {
lines.push(line);
}
Err(err) => {
log::error!("reading journal failed: {}", err);
let _ = child.kill();
break;
}
}
}
}
let status = child.wait().unwrap();
if !status.success() {
log::error!("journalctl failed with {}", status);
}
Ok(json!(lines))
}
pub const ROUTER: Router = Router::new()
.get(&API_METHOD_GET_JOURNAL);