datastore status: factor out api type DataStoreStatusListItem
And use the rust type instead of json::Value.
This commit is contained in:
parent
80ab05e40c
commit
762f7d15dc
|
@ -633,6 +633,48 @@ pub struct DataStoreStatus {
|
||||||
pub counts: Option<Counts>,
|
pub counts: Option<Counts>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[api(
|
||||||
|
properties: {
|
||||||
|
store: {
|
||||||
|
schema: DATASTORE_SCHEMA,
|
||||||
|
},
|
||||||
|
history: {
|
||||||
|
type: Array,
|
||||||
|
optional: true,
|
||||||
|
items: {
|
||||||
|
type: Number,
|
||||||
|
description: "The usage of a time in the past. Either null or between 0.0 and 1.0.",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)]
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all="kebab-case")]
|
||||||
|
/// Status of a Datastore
|
||||||
|
pub struct DataStoreStatusListItem {
|
||||||
|
pub store: String,
|
||||||
|
/// The Size of the underlying storage in bytes.
|
||||||
|
pub total: u64,
|
||||||
|
/// The used bytes of the underlying storage.
|
||||||
|
pub used: u64,
|
||||||
|
/// The available bytes of the underlying storage.
|
||||||
|
pub avail: u64,
|
||||||
|
/// A list of usages of the past (last Month).
|
||||||
|
pub history: Option<Vec<Option<f64>>>,
|
||||||
|
/// History start time (epoch)
|
||||||
|
pub history_start: Option<u64>,
|
||||||
|
/// History resolution (seconds)
|
||||||
|
pub history_delta: Option<u64>,
|
||||||
|
/// Estimation of the UNIX epoch when the storage will be full.
|
||||||
|
/// This is calculated via a simple Linear Regression (Least
|
||||||
|
/// Squares) of RRD data of the last Month. Missing if there are
|
||||||
|
/// not enough data points yet. If the estimate lies in the past,
|
||||||
|
/// the usage is decreasing.
|
||||||
|
pub estimated_full_date: Option<i64>,
|
||||||
|
/// An error description, for example, when the datastore could not be looked up
|
||||||
|
pub error: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
pub const ADMIN_DATASTORE_LIST_SNAPSHOTS_RETURN_TYPE: ReturnType = ReturnType {
|
pub const ADMIN_DATASTORE_LIST_SNAPSHOTS_RETURN_TYPE: ReturnType = ReturnType {
|
||||||
optional: false,
|
optional: false,
|
||||||
schema: &ArraySchema::new(
|
schema: &ArraySchema::new(
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//! Datastote status
|
//! Datastote status
|
||||||
|
|
||||||
use anyhow::{Error};
|
use anyhow::Error;
|
||||||
use serde_json::{json, Value};
|
use serde_json::Value;
|
||||||
|
|
||||||
use proxmox_schema::api;
|
use proxmox_schema::api;
|
||||||
use proxmox_router::{
|
use proxmox_router::{
|
||||||
|
@ -14,7 +14,7 @@ use proxmox_router::{
|
||||||
use proxmox_router::list_subdirs_api_method;
|
use proxmox_router::list_subdirs_api_method;
|
||||||
|
|
||||||
use pbs_api_types::{
|
use pbs_api_types::{
|
||||||
Authid, DATASTORE_SCHEMA, RRDMode, RRDTimeFrame,
|
Authid, DataStoreStatusListItem, RRDMode, RRDTimeFrame,
|
||||||
PRIV_DATASTORE_AUDIT, PRIV_DATASTORE_BACKUP,
|
PRIV_DATASTORE_AUDIT, PRIV_DATASTORE_BACKUP,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -29,47 +29,7 @@ use crate::rrd_cache::extract_rrd_data;
|
||||||
description: "Lists the Status of the Datastores.",
|
description: "Lists the Status of the Datastores.",
|
||||||
type: Array,
|
type: Array,
|
||||||
items: {
|
items: {
|
||||||
description: "Status of a Datastore",
|
type: DataStoreStatusListItem,
|
||||||
type: Object,
|
|
||||||
properties: {
|
|
||||||
store: {
|
|
||||||
schema: DATASTORE_SCHEMA,
|
|
||||||
},
|
|
||||||
total: {
|
|
||||||
type: Integer,
|
|
||||||
description: "The Size of the underlying storage in bytes",
|
|
||||||
},
|
|
||||||
used: {
|
|
||||||
type: Integer,
|
|
||||||
description: "The used bytes of the underlying storage",
|
|
||||||
},
|
|
||||||
avail: {
|
|
||||||
type: Integer,
|
|
||||||
description: "The available bytes of the underlying storage",
|
|
||||||
},
|
|
||||||
history: {
|
|
||||||
type: Array,
|
|
||||||
optional: true,
|
|
||||||
description: "A list of usages of the past (last Month).",
|
|
||||||
items: {
|
|
||||||
type: Number,
|
|
||||||
description: "The usage of a time in the past. Either null or between 0.0 and 1.0.",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"estimated-full-date": {
|
|
||||||
type: Integer,
|
|
||||||
optional: true,
|
|
||||||
description: "Estimation of the UNIX epoch when the storage will be full.\
|
|
||||||
This is calculated via a simple Linear Regression (Least Squares)\
|
|
||||||
of RRD data of the last Month. Missing if there are not enough data points yet.\
|
|
||||||
If the estimate lies in the past, the usage is decreasing.",
|
|
||||||
},
|
|
||||||
"error": {
|
|
||||||
type: String,
|
|
||||||
optional: true,
|
|
||||||
description: "An error description, for example, when the datastore could not be looked up.",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
access: {
|
access: {
|
||||||
|
@ -81,7 +41,7 @@ pub fn datastore_status(
|
||||||
_param: Value,
|
_param: Value,
|
||||||
_info: &ApiMethod,
|
_info: &ApiMethod,
|
||||||
rpcenv: &mut dyn RpcEnvironment,
|
rpcenv: &mut dyn RpcEnvironment,
|
||||||
) -> Result<Value, Error> {
|
) -> Result<Vec<DataStoreStatusListItem>, Error> {
|
||||||
|
|
||||||
let (config, _digest) = pbs_config::datastore::config()?;
|
let (config, _digest) = pbs_config::datastore::config()?;
|
||||||
|
|
||||||
|
@ -100,25 +60,33 @@ pub fn datastore_status(
|
||||||
let datastore = match DataStore::lookup_datastore(store) {
|
let datastore = match DataStore::lookup_datastore(store) {
|
||||||
Ok(datastore) => datastore,
|
Ok(datastore) => datastore,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
list.push(json!({
|
list.push(DataStoreStatusListItem {
|
||||||
"store": store,
|
store: store.clone(),
|
||||||
"total": -1,
|
total: 0,
|
||||||
"used": -1,
|
used: 0,
|
||||||
"avail": -1,
|
avail: 0,
|
||||||
"error": err.to_string()
|
history: None,
|
||||||
}));
|
history_start: None,
|
||||||
|
history_delta: None,
|
||||||
|
estimated_full_date: None,
|
||||||
|
error: Some(err.to_string()),
|
||||||
|
});
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let status = crate::tools::disks::disk_usage(&datastore.base_path())?;
|
let status = crate::tools::disks::disk_usage(&datastore.base_path())?;
|
||||||
|
|
||||||
let mut entry = json!({
|
let mut entry = DataStoreStatusListItem {
|
||||||
"store": store,
|
store: store.clone(),
|
||||||
"total": status.total,
|
total: status.total,
|
||||||
"used": status.used,
|
used: status.used,
|
||||||
"avail": status.avail,
|
avail: status.avail,
|
||||||
"gc-status": datastore.last_gc_status(),
|
history: None,
|
||||||
});
|
history_start: None,
|
||||||
|
history_delta: None,
|
||||||
|
estimated_full_date: None,
|
||||||
|
error: None,
|
||||||
|
};
|
||||||
|
|
||||||
let rrd_dir = format!("datastore/{}", store);
|
let rrd_dir = format!("datastore/{}", store);
|
||||||
|
|
||||||
|
@ -149,23 +117,23 @@ pub fn datastore_status(
|
||||||
time_list.push(start + (idx as u64)*reso);
|
time_list.push(start + (idx as u64)*reso);
|
||||||
let usage = used/total;
|
let usage = used/total;
|
||||||
usage_list.push(usage);
|
usage_list.push(usage);
|
||||||
history.push(json!(usage));
|
history.push(Some(usage));
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
history.push(json!(null))
|
history.push(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
entry["history-start"] = start.into();
|
entry.history_start = Some(start);
|
||||||
entry["history-delta"] = reso.into();
|
entry.history_delta = Some(reso);
|
||||||
entry["history"] = history.into();
|
entry.history = Some(history);
|
||||||
|
|
||||||
// we skip the calculation for datastores with not enough data
|
// we skip the calculation for datastores with not enough data
|
||||||
if usage_list.len() >= 7 {
|
if usage_list.len() >= 7 {
|
||||||
entry["estimated-full-date"] = match linear_regression(&time_list, &usage_list) {
|
entry.estimated_full_date = match linear_regression(&time_list, &usage_list) {
|
||||||
Some((a, b)) if b != 0.0 => Value::from(((1.0 - a) / b).floor() as u64),
|
Some((a, b)) if b != 0.0 => Some(((1.0 - a) / b).floor() as i64),
|
||||||
_ => Value::from(0),
|
_ => None,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue