1 use proxmox
::list_subdirs_api_method
;
4 use serde_json
::{json, Value}
;
16 use crate::api2
::types
::{
19 RRDTimeFrameResolution
,
24 use crate::backup
::{DataStore}
;
25 use crate::config
::datastore
;
26 use crate::tools
::epoch_now_f64
;
27 use crate::tools
::statistics
::{linear_regression}
;
28 use crate::config
::cached_user_info
::CachedUserInfo
;
29 use crate::config
::acl
::{
32 PRIV_DATASTORE_BACKUP
,
37 description
: "Lists the Status of the Datastores.",
40 description
: "Status of a Datastore",
44 schema
: DATASTORE_SCHEMA
,
48 description
: "The Size of the underlying storage in bytes",
52 description
: "The used bytes of the underlying storage",
56 description
: "The available bytes of the underlying storage",
60 description
: "A list of usages of the past (last Month).",
63 description
: "The usage of a time in the past. Either null or between 0.0 and 1.0.",
66 "estimated-full-date": {
69 description
: "Estimation of the UNIX epoch when the storage will be full.\
70 This is calculated via a simple Linear Regression (Least Squares)\
71 of RRD data of the last Month. Missing if there are not enough data points yet.\
72 If the estimate lies in the past, the usage is decreasing.",
78 /// List Datastore usages and estimates
82 rpcenv
: &mut dyn RpcEnvironment
,
83 ) -> Result
<Value
, Error
> {
85 let (config
, _digest
) = datastore
::config()?
;
87 let username
= rpcenv
.get_user().unwrap();
88 let user_info
= CachedUserInfo
::new()?
;
90 let mut list
= Vec
::new();
92 for (store
, (_
, _
)) in &config
.sections
{
93 let user_privs
= user_info
.lookup_privs(&username
, &["datastore", &store
]);
94 let allowed
= (user_privs
& (PRIV_DATASTORE_AUDIT
| PRIV_DATASTORE_BACKUP
)) != 0;
99 let datastore
= DataStore
::lookup_datastore(&store
)?
;
100 let status
= crate::tools
::disks
::disk_usage(&datastore
.base_path())?
;
102 let mut entry
= json
!({
104 "total": status
.total
,
106 "avail": status
.avail
,
109 let rrd_dir
= format
!("datastore/{}", store
);
110 let now
= epoch_now_f64()?
;
111 let rrd_resolution
= RRDTimeFrameResolution
::Month
;
112 let rrd_mode
= RRDMode
::Average
;
114 let total_res
= crate::rrd
::extract_cached_data(
122 let used_res
= crate::rrd
::extract_cached_data(
130 match (total_res
, used_res
) {
131 (Some((start
, reso
, total_list
)), Some((_
, _
, used_list
))) => {
132 let mut usage_list
: Vec
<f64> = Vec
::new();
133 let mut time_list
: Vec
<u64> = Vec
::new();
134 let mut history
= Vec
::new();
136 for (idx
, used
) in used_list
.iter().enumerate() {
137 let total
= if idx
< total_list
.len() {
143 match (total
, used
) {
144 (Some(total
), Some(used
)) if total
!= 0.0 => {
145 time_list
.push(start
+ (idx
as u64)*reso
);
146 let usage
= used
/total
;
147 usage_list
.push(usage
);
148 history
.push(json
!(usage
));
151 history
.push(json
!(null
))
156 entry
["history"] = history
.into();
158 // we skip the calculation for datastores with not enough data
159 if usage_list
.len() >= 7 {
160 if let Some((a
,b
)) = linear_regression(&time_list
, &usage_list
) {
162 let estimate
= (1.0 - a
) / b
;
163 entry
["estimated-full-date"] = Value
::from(estimate
.floor() as u64);
165 entry
["estimated-full-date"] = Value
::from(0);
184 description
: "Only list tasks since this UNIX epoch.",
190 description
: "A list of tasks.",
192 items
: { type: TaskListItem }
,
195 description
: "Users can only see there own tasks, unless the have Sys.Audit on /system/tasks.",
196 permission
: &Permission
::Anybody
,
202 rpcenv
: &mut dyn RpcEnvironment
,
203 ) -> Result
<Vec
<TaskListItem
>, Error
> {
205 let username
= rpcenv
.get_user().unwrap();
206 let user_info
= CachedUserInfo
::new()?
;
207 let user_privs
= user_info
.lookup_privs(&username
, &["system", "tasks"]);
209 let list_all
= (user_privs
& PRIV_SYS_AUDIT
) != 0;
211 // TODO: replace with call that gets all task since 'since' epoch
212 let list
: Vec
<TaskListItem
> = server
::read_task_list()?
214 .map(TaskListItem
::from
)
215 .filter(|entry
| list_all
|| entry
.user
== username
)
221 const SUBDIRS
: SubdirMap
= &[
222 ("datastore-usage", &Router
::new().get(&API_METHOD_DATASTORE_STATUS
)),
223 ("tasks", &Router
::new().get(&API_METHOD_LIST_TASKS
)),
226 pub const ROUTER
: Router
= Router
::new()
227 .get(&list_subdirs_api_method
!(SUBDIRS
))