From b01f2bcf5cc5129bd21700d2c379f30bef255e1b Mon Sep 17 00:00:00 2001 From: Matteo Chesi Date: Fri, 12 Jun 2026 14:01:26 +0200 Subject: [PATCH] Add imagestore keepalive --- Cargo.lock | 29 +++++++++++++++++++ crates/raster/Cargo.toml | 1 + crates/raster/src/config.rs | 23 ++++++++++++++++ crates/raster/src/imagestore.rs | 49 +++++++++++++++++++++++++++++++++ crates/raster/src/lib.rs | 2 ++ crates/skybox/src/sync.rs | 7 +++++ 6 files changed, 111 insertions(+) create mode 100644 crates/raster/src/imagestore.rs diff --git a/Cargo.lock b/Cargo.lock index f38d35c..386f188 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1301,6 +1301,7 @@ dependencies = [ "serial_test", "shellexpand", "toml", + "walkdir", ] [[package]] @@ -1451,6 +1452,15 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "sarus-suite-podman-driver" version = "0.4.0" @@ -2094,6 +2104,16 @@ dependencies = [ "libc", ] +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "want" version = "0.3.1" @@ -2242,6 +2262,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/crates/raster/Cargo.toml b/crates/raster/Cargo.toml index 3c778a3..f259325 100644 --- a/crates/raster/Cargo.toml +++ b/crates/raster/Cargo.toml @@ -14,3 +14,4 @@ regex = "1.12.2" serial_test = "3.2.0" nix = { version = "0.30.1", features = ["user","fs","signal"] } is_executable = "1.0.5" +walkdir = "2.5.0" diff --git a/crates/raster/src/config.rs b/crates/raster/src/config.rs index 160234f..f9b7bff 100644 --- a/crates/raster/src/config.rs +++ b/crates/raster/src/config.rs @@ -11,6 +11,7 @@ pub struct RawConfig { edf_system_search_path: Option, hooks: Option, parallax_imagestore: Option, + parallax_imagestore_keepalive: Option, parallax_mount_program: Option, parallax_path: Option, parallax_mp_uid: Option, @@ -40,6 +41,8 @@ pub struct Config { pub hooks: ConfigHooks, #[serde(default = "get_default_parallax_imagestore")] pub parallax_imagestore: String, + #[serde(default = "get_default_parallax_imagestore_keepalive")] + pub parallax_imagestore_keepalive: bool, #[serde(default = "get_default_parallax_mount_program")] pub parallax_mount_program: String, #[serde(default = "get_default_parallax_path")] @@ -91,6 +94,10 @@ fn get_default_parallax_imagestore() -> String { return String::from(""); } +fn get_default_parallax_imagestore_keepalive() -> bool { + return false; +} + fn get_default_parallax_mount_program() -> String { return String::from(""); } @@ -173,6 +180,10 @@ impl From for Config { Some(s) => s, None => get_default_parallax_imagestore(), }, + parallax_imagestore_keepalive: match r.parallax_imagestore_keepalive { + Some(s) => s, + None => get_default_parallax_imagestore_keepalive(), + }, parallax_mount_program: match r.parallax_mount_program { Some(s) => s, None => get_default_parallax_mount_program(), @@ -245,6 +256,9 @@ impl RawConfig { if i.parallax_imagestore.is_some() { self.parallax_imagestore = i.parallax_imagestore; } + if i.parallax_imagestore_keepalive.is_some() { + self.parallax_imagestore_keepalive = i.parallax_imagestore_keepalive; + } if i.parallax_mount_program.is_some() { self.parallax_mount_program = i.parallax_mount_program; } @@ -483,6 +497,15 @@ pub fn update_config_by_user(config: &mut Config, edf: EDF) -> SarusResult<()> { config.parallax_imagestore = parallax_imagestore.unwrap().to_string(); } + let parallax_imagestore_keepalive = edf.annotations.get("com.sarus.parallax_imagestore_keepalive"); + if parallax_imagestore_keepalive.is_some() { + config.parallax_imagestore_keepalive = match parallax_imagestore_keepalive.unwrap().as_str() { + "true" => true, + "false" => false, + _ => config.parallax_imagestore_keepalive, + }; + } + let parallax_mount_program = edf.annotations.get("com.sarus.parallax_mount_program"); if parallax_mount_program.is_some() { config.parallax_mount_program = parallax_mount_program.unwrap().to_string(); diff --git a/crates/raster/src/imagestore.rs b/crates/raster/src/imagestore.rs new file mode 100644 index 0000000..c3bdbbb --- /dev/null +++ b/crates/raster/src/imagestore.rs @@ -0,0 +1,49 @@ +use std::path::Path; +use std::fs::{self, File, FileTimes}; +use std::time::{Duration, SystemTime}; +use walkdir::WalkDir; +use crate::Config; + +pub fn imagestore_keepalive(config: &Config) -> Result,String> { + + let output; + let imagestore = &config.parallax_imagestore; + + if ! config.parallax_imagestore_keepalive { + return Ok(None); + } + + let path = Path::new(&imagestore); + if ! path.exists() { + return Err(format!("imagestore {} doesn't exist", imagestore)); + } + + let now = SystemTime::now(); + let mut num_entries = 0; + let mut upd_entries = 0; + for entry in WalkDir::new(&path) { + num_entries += 1; + + // Best effort, skip errors + let Ok(entrystr) = entry else { continue }; + let Ok(metadata) = fs::metadata(entrystr.path()) else { continue }; + let Ok(atime) = metadata.accessed() else { continue }; + + // skip if recent + if atime.elapsed().unwrap() < Duration::new(86400, 0) { continue } + + // Update atime if old + let Ok(file) = File::open(entrystr.path()) else { continue }; + let Ok(mtime) = metadata.modified() else { continue }; + let times = FileTimes::new() + .set_accessed(now) + .set_modified(mtime); + match file.set_times(times) { + Ok(_) => (), + Err(_) => continue, + } + upd_entries += 1; + } + output = Some(format!("Keep alive imagestore {}, refreshed {}/{} inodes", imagestore, upd_entries, num_entries)); + Ok(output) +} diff --git a/crates/raster/src/lib.rs b/crates/raster/src/lib.rs index e0486bd..140427b 100644 --- a/crates/raster/src/lib.rs +++ b/crates/raster/src/lib.rs @@ -16,11 +16,13 @@ pub mod common; pub mod config; pub mod error; pub mod hooks; +pub mod imagestore; pub mod mount; pub use crate::common::expand_vars_string; pub use crate::config::{Config, VarExpand, load_config, load_config_path, update_config_by_user}; pub use crate::hooks::{hook_run, ExecutedCommand}; +pub use crate::imagestore::{imagestore_keepalive}; #[allow(dead_code)] #[derive(Derivative, Serialize, Deserialize, Clone, Default)] diff --git a/crates/skybox/src/sync.rs b/crates/skybox/src/sync.rs index b0c67d7..fbf40f7 100644 --- a/crates/skybox/src/sync.rs +++ b/crates/skybox/src/sync.rs @@ -363,6 +363,13 @@ pub(crate) fn sync_cleanup_fs_shared( } } + match raster::imagestore_keepalive(&ssb.config)? { + Some(output) => { + skybox_log_debug!("{}", output); + }, + None => (), + }; + Ok(()) }