diff --git a/src/api2/node/rrd.rs b/src/api2/node/rrd.rs index c59a35a4..b53076d7 100644 --- a/src/api2/node/rrd.rs +++ b/src/api2/node/rrd.rs @@ -10,7 +10,7 @@ use pbs_api_types::{ use proxmox_rrd::rrd::RRD_DATA_ENTRIES; -use crate::RRD_CACHE; +use crate::get_rrd_cache; pub fn create_value_from_rrd( basedir: &str, @@ -22,8 +22,10 @@ pub fn create_value_from_rrd( let mut result = Vec::new(); let now = proxmox_time::epoch_f64(); + let rrd_cache = get_rrd_cache()?; + for name in list { - let (start, reso, list) = match RRD_CACHE.extract_cached_data(basedir, name, now, timeframe, cf) { + let (start, reso, list) = match rrd_cache.extract_cached_data(basedir, name, now, timeframe, cf) { Some(result) => result, None => continue, }; diff --git a/src/api2/status.rs b/src/api2/status.rs index 9c7d4f7d..40a9e5b4 100644 --- a/src/api2/status.rs +++ b/src/api2/status.rs @@ -22,7 +22,7 @@ use pbs_datastore::DataStore; use pbs_config::CachedUserInfo; use crate::tools::statistics::{linear_regression}; -use crate::RRD_CACHE; +use crate::get_rrd_cache; #[api( returns: { @@ -90,6 +90,8 @@ pub fn datastore_status( let mut list = Vec::new(); + let rrd_cache = get_rrd_cache()?; + for (store, (_, _)) in &config.sections { let user_privs = user_info.lookup_privs(&auth_id, &["datastore", &store]); let allowed = (user_privs & (PRIV_DATASTORE_AUDIT| PRIV_DATASTORE_BACKUP)) != 0; @@ -123,7 +125,8 @@ pub fn datastore_status( let rrd_dir = format!("datastore/{}", store); let now = proxmox_time::epoch_f64(); - let get_rrd = |what: &str| RRD_CACHE.extract_cached_data( + + let get_rrd = |what: &str| rrd_cache.extract_cached_data( &rrd_dir, what, now, diff --git a/src/bin/proxmox-backup-api.rs b/src/bin/proxmox-backup-api.rs index 3c963a77..8d6c3170 100644 --- a/src/bin/proxmox-backup-api.rs +++ b/src/bin/proxmox-backup-api.rs @@ -16,7 +16,6 @@ use proxmox_rest_server::{daemon, AuthError, ApiConfig, RestServer, RestEnvironm use proxmox_backup::server::auth::check_pbs_auth; use proxmox_backup::auth_helpers::*; -use proxmox_backup::RRD_CACHE; use proxmox_backup::config; fn main() { @@ -73,9 +72,6 @@ async fn run() -> Result<(), Error> { config::update_self_signed_cert(false)?; proxmox_backup::server::create_run_dir()?; - - RRD_CACHE.apply_journal()?; - proxmox_backup::server::jobstate::create_jobstate_dir()?; proxmox_backup::tape::create_tape_status_dir()?; proxmox_backup::tape::create_drive_state_dir()?; diff --git a/src/bin/proxmox-backup-proxy.rs b/src/bin/proxmox-backup-proxy.rs index 8da98ff8..66d81bdb 100644 --- a/src/bin/proxmox-backup-proxy.rs +++ b/src/bin/proxmox-backup-proxy.rs @@ -32,7 +32,7 @@ use proxmox_rest_server::{ }; use proxmox_backup::{ - RRD_CACHE, + get_rrd_cache, initialize_rrd_cache, server::{ auth::check_pbs_auth, jobstate::{ @@ -208,6 +208,9 @@ async fn run() -> Result<(), Error> { let _ = public_auth_key(); // load with lazy_static let _ = csrf_secret(); // load with lazy_static + let rrd_cache = initialize_rrd_cache()?; + rrd_cache.apply_journal()?; + let mut config = ApiConfig::new( pbs_buildcfg::JS_DIR, &proxmox_backup::api2::ROUTER, @@ -901,14 +904,18 @@ async fn run_stat_generator() { } fn rrd_update_gauge(name: &str, value: f64) { - if let Err(err) = RRD_CACHE.update_value(name, value, DST::Gauge) { - eprintln!("rrd::update_value '{}' failed - {}", name, err); + if let Ok(rrd_cache) = get_rrd_cache() { + if let Err(err) = rrd_cache.update_value(name, value, DST::Gauge) { + eprintln!("rrd::update_value '{}' failed - {}", name, err); + } } } fn rrd_update_derive(name: &str, value: f64) { - if let Err(err) = RRD_CACHE.update_value(name, value, DST::Derive) { - eprintln!("rrd::update_value '{}' failed - {}", name, err); + if let Ok(rrd_cache) = get_rrd_cache() { + if let Err(err) = rrd_cache.update_value(name, value, DST::Derive) { + eprintln!("rrd::update_value '{}' failed - {}", name, err); + } } } diff --git a/src/lib.rs b/src/lib.rs index 5d2b4590..a1ac23bf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,6 +5,9 @@ use std::path::PathBuf; +use once_cell::sync::OnceCell; +use anyhow::{format_err, Error}; + use proxmox::tools::fs::CreateOptions; use pbs_buildcfg::configdir; @@ -39,25 +42,39 @@ pub fn cert_info() -> Result { CertInfo::from_path(PathBuf::from(configdir!("/proxy.pem"))) } -lazy_static::lazy_static!{ - /// Proxmox Backup Server RRD cache instance - pub static ref RRD_CACHE: RRDCache = { - let backup_user = pbs_config::backup_user().unwrap(); - let file_options = CreateOptions::new() - .owner(backup_user.uid) - .group(backup_user.gid); +pub static RRD_CACHE: OnceCell = OnceCell::new(); - let dir_options = CreateOptions::new() - .owner(backup_user.uid) - .group(backup_user.gid); - - let apply_interval = 30.0*60.0; // 30 minutes - - RRDCache::new( - "/var/lib/proxmox-backup/rrdb", - Some(file_options), - Some(dir_options), - apply_interval, - ).unwrap() - }; +/// Get the RRD cache instance +pub fn get_rrd_cache() -> Result<&'static RRDCache, Error> { + RRD_CACHE.get().ok_or_else(|| format_err!("RRD cache not initialized!")) +} + +/// Initialize the RRD cache instance +/// +/// Note: Only a single process must do this (proxmox-backup-proxy) +pub fn initialize_rrd_cache() -> Result<&'static RRDCache, Error> { + + let backup_user = pbs_config::backup_user()?; + + let file_options = CreateOptions::new() + .owner(backup_user.uid) + .group(backup_user.gid); + + let dir_options = CreateOptions::new() + .owner(backup_user.uid) + .group(backup_user.gid); + + let apply_interval = 30.0*60.0; // 30 minutes + + let cache = RRDCache::new( + "/var/lib/proxmox-backup/rrdb", + Some(file_options), + Some(dir_options), + apply_interval, + )?; + + RRD_CACHE.set(cache) + .map_err(|_| format_err!("RRD cache already initialized!"))?; + + Ok(RRD_CACHE.get().unwrap()) }