1 use std
::process
::Command
;
4 use anyhow
::{Error, format_err, bail}
;
7 use proxmox
::sys
::linux
::procfs
;
9 use proxmox_router
::{ApiMethod, Router, RpcEnvironment, Permission}
;
10 use proxmox_schema
::api
;
12 use pbs_api_types
::{NODE_SCHEMA, NodePowerCommand, PRIV_SYS_AUDIT, PRIV_SYS_POWER_MANAGEMENT}
;
14 use crate::api2
::types
::{
15 NodeCpuInformation
, NodeStatus
, NodeMemoryCounters
, NodeSwapCounters
, NodeInformation
,
18 impl std
::convert
::From
<procfs
::ProcFsCPUInfo
> for NodeCpuInformation
{
19 fn from(info
: procfs
::ProcFsCPUInfo
) -> Self {
22 sockets
: info
.sockets
,
40 permission
: &Permission
::Privilege(&["system", "status"], PRIV_SYS_AUDIT
, false),
43 /// Read node memory, CPU and (root) disk usage
47 _rpcenv
: &mut dyn RpcEnvironment
,
48 ) -> Result
<NodeStatus
, Error
> {
49 let meminfo
: procfs
::ProcFsMemInfo
= procfs
::read_meminfo()?
;
50 let memory
= NodeMemoryCounters
{
51 total
: meminfo
.memtotal
,
52 used
: meminfo
.memused
,
53 free
: meminfo
.memfree
,
56 let swap
= NodeSwapCounters
{
57 total
: meminfo
.swaptotal
,
58 used
: meminfo
.swapused
,
59 free
: meminfo
.swapfree
,
62 let kstat
: procfs
::ProcFsStat
= procfs
::read_proc_stat()?
;
64 let wait
= kstat
.iowait_percent
;
66 let loadavg
= procfs
::Loadavg
::read()?
;
67 let loadavg
= [loadavg
.one(), loadavg
.five(), loadavg
.fifteen()];
69 let cpuinfo
= procfs
::read_cpuinfo()?
;
70 let cpuinfo
= cpuinfo
.into();
72 let uname
= nix
::sys
::utsname
::uname();
73 let kversion
= format
!(
83 root
: crate::tools
::disks
::disk_usage(Path
::new("/"))?
,
84 uptime
: procfs
::read_proc_uptime()?
.0 as u64,
90 info
: NodeInformation
{
91 fingerprint
: crate::cert_info()?
.fingerprint()?
,
104 type: NodePowerCommand
,
109 permission
: &Permission
::Privilege(&["system", "status"], PRIV_SYS_POWER_MANAGEMENT
, false),
112 /// Reboot or shutdown the node.
113 fn reboot_or_shutdown(command
: NodePowerCommand
) -> Result
<(), Error
> {
115 let systemctl_command
= match command
{
116 NodePowerCommand
::Reboot
=> "reboot",
117 NodePowerCommand
::Shutdown
=> "poweroff",
120 let output
= Command
::new("systemctl")
121 .arg(systemctl_command
)
123 .map_err(|err
| format_err
!("failed to execute systemctl - {}", err
))?
;
125 if !output
.status
.success() {
126 match output
.status
.code() {
128 let msg
= String
::from_utf8(output
.stderr
)
129 .map(|m
| if m
.is_empty() { String::from("no error message") }
else { m }
)
130 .unwrap_or_else(|_
| String
::from("non utf8 error message (suppressed)"));
131 bail
!("diff failed with status code: {} - {}", code
, msg
);
133 None
=> bail
!("systemctl terminated by signal"),
139 pub const ROUTER
: Router
= Router
::new()
140 .get(&API_METHOD_GET_STATUS
)
141 .post(&API_METHOD_REBOOT_OR_SHUTDOWN
);