1 use std
::process
::Command
;
4 use anyhow
::{Error, format_err, bail}
;
7 use proxmox
::sys
::linux
::procfs
;
9 use proxmox
::api
::{api, ApiMethod, Router, RpcEnvironment, Permission}
;
11 use pbs_tools
::cert
::CertInfo
;
13 use crate::api2
::types
::*;
14 use crate::config
::acl
::{PRIV_SYS_AUDIT, PRIV_SYS_POWER_MANAGEMENT}
;
16 impl std
::convert
::From
<procfs
::ProcFsCPUInfo
> for NodeCpuInformation
{
17 fn from(info
: procfs
::ProcFsCPUInfo
) -> Self {
20 sockets
: info
.sockets
,
38 permission
: &Permission
::Privilege(&["system", "status"], PRIV_SYS_AUDIT
, false),
41 /// Read node memory, CPU and (root) disk usage
45 _rpcenv
: &mut dyn RpcEnvironment
,
46 ) -> Result
<NodeStatus
, Error
> {
47 let meminfo
: procfs
::ProcFsMemInfo
= procfs
::read_meminfo()?
;
48 let memory
= NodeMemoryCounters
{
49 total
: meminfo
.memtotal
,
50 used
: meminfo
.memused
,
51 free
: meminfo
.memfree
,
54 let swap
= NodeSwapCounters
{
55 total
: meminfo
.swaptotal
,
56 used
: meminfo
.swapused
,
57 free
: meminfo
.swapfree
,
60 let kstat
: procfs
::ProcFsStat
= procfs
::read_proc_stat()?
;
62 let wait
= kstat
.iowait_percent
;
64 let loadavg
= procfs
::Loadavg
::read()?
;
65 let loadavg
= [loadavg
.one(), loadavg
.five(), loadavg
.fifteen()];
67 let cpuinfo
= procfs
::read_cpuinfo()?
;
68 let cpuinfo
= cpuinfo
.into();
70 let uname
= nix
::sys
::utsname
::uname();
71 let kversion
= format
!(
81 root
: crate::tools
::disks
::disk_usage(Path
::new("/"))?
,
82 uptime
: procfs
::read_proc_uptime()?
.0 as u64,
88 info
: NodeInformation
{
89 fingerprint
: CertInfo
::new()?
.fingerprint()?
,
102 type: NodePowerCommand
,
107 permission
: &Permission
::Privilege(&["system", "status"], PRIV_SYS_POWER_MANAGEMENT
, false),
110 /// Reboot or shutdown the node.
111 fn reboot_or_shutdown(command
: NodePowerCommand
) -> Result
<(), Error
> {
113 let systemctl_command
= match command
{
114 NodePowerCommand
::Reboot
=> "reboot",
115 NodePowerCommand
::Shutdown
=> "poweroff",
118 let output
= Command
::new("systemctl")
119 .arg(systemctl_command
)
121 .map_err(|err
| format_err
!("failed to execute systemctl - {}", err
))?
;
123 if !output
.status
.success() {
124 match output
.status
.code() {
126 let msg
= String
::from_utf8(output
.stderr
)
127 .map(|m
| if m
.is_empty() { String::from("no error message") }
else { m }
)
128 .unwrap_or_else(|_
| String
::from("non utf8 error message (suppressed)"));
129 bail
!("diff failed with status code: {} - {}", code
, msg
);
131 None
=> bail
!("systemctl terminated by signal"),
137 pub const ROUTER
: Router
= Router
::new()
138 .get(&API_METHOD_GET_STATUS
)
139 .post(&API_METHOD_REBOOT_OR_SHUTDOWN
);