[pbs-devel] [PATCH proxmox-backup 10/15] proxmox-rrd: add binary to create/manage rrd files
Dietmar Maurer
dietmar at proxmox.com
Wed Oct 13 10:24:47 CEST 2021
---
proxmox-rrd/Cargo.toml | 1 +
proxmox-rrd/src/bin/rrd.rs | 215 +++++++++++++++++++++++++++++++++++++
2 files changed, 216 insertions(+)
create mode 100644 proxmox-rrd/src/bin/rrd.rs
diff --git a/proxmox-rrd/Cargo.toml b/proxmox-rrd/Cargo.toml
index 69a68530..e3ab5380 100644
--- a/proxmox-rrd/Cargo.toml
+++ b/proxmox-rrd/Cargo.toml
@@ -16,4 +16,5 @@ serde_cbor = "0.11.1"
proxmox = { version = "0.14.0" }
proxmox-time = "1"
+proxmox-router = "1"
proxmox-schema = { version = "1", features = [ "api-macro" ] }
diff --git a/proxmox-rrd/src/bin/rrd.rs b/proxmox-rrd/src/bin/rrd.rs
new file mode 100644
index 00000000..fdb61ffd
--- /dev/null
+++ b/proxmox-rrd/src/bin/rrd.rs
@@ -0,0 +1,215 @@
+//! RRD toolkit - create/manage/update proxmox RRD (v2) file
+
+use std::path::PathBuf;
+
+use anyhow::{bail, Error};
+use serde::{Serialize, Deserialize};
+
+use proxmox_router::RpcEnvironment;
+use proxmox_router::cli::{run_cli_command, CliCommand, CliCommandMap, CliEnvironment};
+use proxmox_schema::{api, parse_property_string};
+use proxmox_schema::{ApiStringFormat, ApiType, Schema, StringSchema};
+
+use proxmox::tools::fs::CreateOptions;
+
+use proxmox_rrd::rrd::{CF, DST, RRA, RRD};
+
+pub const RRA_CONFIG_STRING_SCHEMA: Schema = StringSchema::new(
+ "RRA configuration")
+ .format(&ApiStringFormat::PropertyString(&RRAConfig::API_SCHEMA))
+ .schema();
+
+#[api(
+ properties: {},
+ default_key: "cf",
+)]
+#[derive(Debug, Serialize, Deserialize)]
+/// RRA configuration
+pub struct RRAConfig {
+ /// Time resolution
+ pub r: u64,
+ pub cf: CF,
+ /// Number of data points
+ pub n: u64,
+}
+
+#[api(
+ input: {
+ properties: {
+ path: {
+ description: "The filename."
+ },
+ },
+ },
+)]
+/// Dump the RRDB database in JSON format
+pub fn dump_rrdb(path: String) -> Result<(), Error> {
+
+ let rrd = RRD::load(&PathBuf::from(path))?;
+ serde_json::to_writer_pretty(std::io::stdout(), &rrd)?;
+ Ok(())
+}
+
+#[api(
+ input: {
+ properties: {
+ path: {
+ description: "The filename."
+ },
+ time: {
+ description: "Update time.",
+ optional: true,
+ },
+ value: {
+ description: "Update value.",
+ },
+ },
+ },
+)]
+/// Update the RRDB database
+pub fn update_rrdb(
+ path: String,
+ time: Option<u64>,
+ value: f64,
+) -> Result<(), Error> {
+
+ let path = PathBuf::from(path);
+
+ let time = time.map(|v| v as f64)
+ .unwrap_or_else(proxmox_time::epoch_f64);
+
+ let mut rrd = RRD::load(&path)?;
+ rrd.update(time, value);
+
+ rrd.save(&path, CreateOptions::new())?;
+
+ Ok(())
+}
+
+#[api(
+ input: {
+ properties: {
+ path: {
+ description: "The filename."
+ },
+ cf: {
+ type: CF,
+ },
+ resolution: {
+ description: "Time resulution",
+ },
+ start: {
+ description: "Start time. If not sepecified, we simply extract 10 data points.",
+ optional: true,
+ },
+ end: {
+ description: "End time (Unix Epoch). Default is the last update time.",
+ optional: true,
+ },
+ },
+ },
+)]
+/// Fetch data from the RRDB database
+pub fn fetch_rrdb(
+ path: String,
+ cf: CF,
+ resolution: u64,
+ start: Option<u64>,
+ end: Option<u64>,
+) -> Result<(), Error> {
+
+ let rrd = RRD::load(&PathBuf::from(path))?;
+
+ let data = rrd.extract_data(cf, resolution, start, end)?;
+
+ println!("{}", serde_json::to_string_pretty(&data)?);
+
+ Ok(())
+}
+
+#[api(
+ input: {
+ properties: {
+ dst: {
+ type: DST,
+ },
+ path: {
+ description: "The filename to create."
+ },
+ rra: {
+ description: "Configuration of contained RRAs.",
+ type: Array,
+ items: {
+ schema: RRA_CONFIG_STRING_SCHEMA,
+ }
+ },
+ },
+ },
+)]
+/// Create a new RRDB database file
+pub fn create_rrdb(
+ dst: DST,
+ path: String,
+ rra: Vec<String>,
+) -> Result<(), Error> {
+
+ let mut rra_list = Vec::new();
+
+ for item in rra.iter() {
+ let rra: RRAConfig = serde_json::from_value(
+ parse_property_string(item, &RRAConfig::API_SCHEMA)?
+ )?;
+ println!("GOT {:?}", rra);
+ rra_list.push(RRA::new(rra.cf, rra.r, rra.n as usize));
+ }
+
+ let path = PathBuf::from(path);
+
+ let rrd = RRD::new(dst, rra_list);
+
+ rrd.save(&path, CreateOptions::new())?;
+
+ Ok(())
+}
+
+
+fn main() -> Result<(), Error> {
+
+ let uid = nix::unistd::Uid::current();
+
+ let username = match nix::unistd::User::from_uid(uid)? {
+ Some(user) => user.name,
+ None => bail!("unable to get user name"),
+ };
+
+ let cmd_def = CliCommandMap::new()
+ .insert(
+ "create",
+ CliCommand::new(&API_METHOD_CREATE_RRDB)
+ .arg_param(&["path"])
+ )
+ .insert(
+ "update",
+ CliCommand::new(&API_METHOD_UPDATE_RRDB)
+ .arg_param(&["path"])
+ )
+ .insert(
+ "fetch",
+ CliCommand::new(&API_METHOD_FETCH_RRDB)
+ .arg_param(&["path"])
+ )
+ .insert(
+ "dump",
+ CliCommand::new(&API_METHOD_DUMP_RRDB)
+ .arg_param(&["path"])
+ )
+ ;
+
+ let mut rpcenv = CliEnvironment::new();
+ rpcenv.set_auth_id(Some(format!("{}@pam", username)));
+
+ run_cli_command(cmd_def, rpcenv, None);
+
+ Ok(())
+
+}
--
2.30.2
More information about the pbs-devel
mailing list