src/api2/node/status.rs: rework api, implement reboot and shutdown

This commit is contained in:
Dietmar Maurer 2020-04-30 11:52:40 +02:00
parent ca9dfe5fa4
commit ed751dc2ab
2 changed files with 60 additions and 11 deletions

View File

@ -1,13 +1,14 @@
use anyhow::{Error}; use std::process::Command;
use anyhow::{Error, format_err, bail};
use serde_json::{json, Value}; use serde_json::{json, Value};
use proxmox::sys::linux::procfs; use proxmox::sys::linux::procfs;
use proxmox::api::{api, ApiMethod, Router, RpcEnvironment, SubdirMap, Permission}; use proxmox::api::{api, ApiMethod, Router, RpcEnvironment, Permission};
use proxmox::list_subdirs_api_method;
use crate::api2::types::*; use crate::api2::types::*;
use crate::config::acl::PRIV_SYS_AUDIT; use crate::config::acl::{PRIV_SYS_AUDIT, PRIV_SYS_POWER_MANAGEMENT};
#[api( #[api(
input: { input: {
@ -70,12 +71,49 @@ fn get_usage(
})) }))
} }
pub const USAGE_ROUTER: Router = Router::new() #[api(
.get(&API_METHOD_GET_USAGE); protected: true,
input: {
properties: {
node: {
schema: NODE_SCHEMA,
},
command: {
type: NodePowerCommand,
},
}
},
access: {
permission: &Permission::Privilege(&["system", "status"], PRIV_SYS_POWER_MANAGEMENT, false),
},
)]
/// Reboot or shutdown the node.
fn reboot_or_shutdown(command: NodePowerCommand) -> Result<(), Error> {
let systemctl_command = match command {
NodePowerCommand::Reboot => "reboot",
NodePowerCommand::Shutdown => "poweroff",
};
let output = Command::new("/bin/systemctl")
.arg(systemctl_command)
.output()
.map_err(|err| format_err!("failed to execute systemctl - {}", err))?;
if !output.status.success() {
match output.status.code() {
Some(code) => {
let msg = String::from_utf8(output.stderr)
.map(|m| if m.is_empty() { String::from("no error message") } else { m })
.unwrap_or_else(|_| String::from("non utf8 error message (suppressed)"));
bail!("diff failed with status code: {} - {}", code, msg);
}
None => bail!("systemctl terminated by signal"),
}
}
Ok(())
}
pub const SUBDIRS: SubdirMap = &[
("usage", &USAGE_ROUTER),
];
pub const ROUTER: Router = Router::new() pub const ROUTER: Router = Router::new()
.get(&list_subdirs_api_method!(SUBDIRS)) .get(&API_METHOD_GET_USAGE)
.subdirs(SUBDIRS); .post(&API_METHOD_REBOOT_OR_SHUTDOWN);

View File

@ -499,6 +499,17 @@ pub struct TaskListItem {
pub status: Option<String>, pub status: Option<String>,
} }
#[api()]
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
/// Node Power command type.
pub enum NodePowerCommand {
/// Restart the server
Reboot,
/// Shutdown the server
Shutdown,
}
#[api()] #[api()]
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)] #[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")] #[serde(rename_all = "lowercase")]