src/api2/node/status.rs: rework api, implement reboot and shutdown
This commit is contained in:
parent
ca9dfe5fa4
commit
ed751dc2ab
@ -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);
|
||||||
|
@ -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")]
|
||||||
|
Loading…
Reference in New Issue
Block a user