--- /dev/null
+use std::process::{Command, Stdio};
+
+use failure::*;
+use serde_json::{json, Value};
+use std::io::{BufRead,BufReader};
+
+use proxmox::api::{api, ApiMethod, Router, RpcEnvironment};
+
+use crate::api2::types::*;
+
+#[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.",
+ },
+ },
+)]
+/// 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);