diff --git a/src/dbus_api/pool/mod.rs b/src/dbus_api/pool/mod.rs index 9bce858b2a..1667b58f63 100644 --- a/src/dbus_api/pool/mod.rs +++ b/src/dbus_api/pool/mod.rs @@ -260,6 +260,7 @@ pub fn create_dbus_pool<'a>( .add_m(pool_3_0::rename_method(&f)) .add_m(pool_3_3::grow_physical_device_method(&f)) .add_m(pool_3_7::get_metadata_method(&f)) + .add_m(pool_3_7::get_fs_metadata_method(&f)) .add_p(pool_3_0::name_property(&f)) .add_p(pool_3_0::uuid_property(&f)) .add_p(pool_3_0::encrypted_property(&f)) diff --git a/src/dbus_api/pool/pool_3_7/api.rs b/src/dbus_api/pool/pool_3_7/api.rs index 59603f4e34..02ca0ed08d 100644 --- a/src/dbus_api/pool/pool_3_7/api.rs +++ b/src/dbus_api/pool/pool_3_7/api.rs @@ -7,7 +7,7 @@ use dbus_tree::{Access, EmitsChangedSignal, Factory, MTSync, Method, Property}; use crate::dbus_api::{ consts, pool::pool_3_7::{ - methods::{destroy_filesystems, metadata}, + methods::{destroy_filesystems, fs_metadata, metadata}, props::get_pool_metadata_version, }, types::TData, @@ -47,3 +47,14 @@ pub fn metadata_version_property( .emits_changed(EmitsChangedSignal::Const) .on_get(get_pool_metadata_version) } + +pub fn get_fs_metadata_method(f: &Factory, TData>) -> Method, TData> { + f.method("FilesystemMetadata", (), fs_metadata) + // A string representing the pool's filesystem metadata in serialized + // JSON format. + // + // Rust representation: String + .out_arg(("results", "s")) + .out_arg(("return_code", "q")) + .out_arg(("return_string", "s")) +} diff --git a/src/dbus_api/pool/pool_3_7/methods.rs b/src/dbus_api/pool/pool_3_7/methods.rs index 1d3bbfbb48..70fe74cdf4 100644 --- a/src/dbus_api/pool/pool_3_7/methods.rs +++ b/src/dbus_api/pool/pool_3_7/methods.rs @@ -148,3 +148,39 @@ pub fn metadata(m: &MethodInfo<'_, MTSync, TData>) -> MethodResult { }; Ok(vec![msg]) } + +pub fn fs_metadata(m: &MethodInfo<'_, MTSync, TData>) -> MethodResult { + let default_return = String::new(); + + let message: &Message = m.msg; + + let return_message = message.method_return(); + + let dbus_context = m.tree.get_data(); + let object_path = m.path.get_name(); + + let pool_path = m + .tree + .get(object_path) + .expect("implicit argument must be in tree"); + let pool_uuid = typed_uuid!( + get_data!(pool_path; default_return; return_message).uuid; + Pool; + default_return; + return_message + ); + + let guard = get_pool!(dbus_context.engine; pool_uuid; default_return; return_message); + let (_, _, pool) = guard.as_tuple(); + + let result = pool.last_metadata(); + + let msg = match result { + Ok(v) => return_message.append3(v, DbusErrorEnum::OK as u16, OK_STRING.to_string()), + Err(err) => { + let (rc, rs) = engine_to_dbus_err_tuple(&err); + return_message.append3(default_return, rc, rs) + } + }; + Ok(vec![msg]) +} diff --git a/src/dbus_api/pool/pool_3_7/mod.rs b/src/dbus_api/pool/pool_3_7/mod.rs index 834df4053d..037c6a6758 100644 --- a/src/dbus_api/pool/pool_3_7/mod.rs +++ b/src/dbus_api/pool/pool_3_7/mod.rs @@ -6,4 +6,7 @@ mod api; mod methods; mod props; -pub use api::{destroy_filesystems_method, get_metadata_method, metadata_version_property}; +pub use api::{ + destroy_filesystems_method, get_fs_metadata_method, get_metadata_method, + metadata_version_property, +}; diff --git a/src/engine/engine.rs b/src/engine/engine.rs index 66d01ef8fb..ccf4527af4 100644 --- a/src/engine/engine.rs +++ b/src/engine/engine.rs @@ -350,6 +350,9 @@ pub trait Pool: Debug + Send + Sync { /// Get the metadata version for a given pool. fn metadata_version(&self) -> StratSigblockVersion; + + /// Get the last written filesystem metadata. + fn last_fs_metadata(&self) -> StratisResult; } pub type HandleEvents

= ( diff --git a/src/engine/sim_engine/filesystem.rs b/src/engine/sim_engine/filesystem.rs index 5198f234bf..039917a2fd 100644 --- a/src/engine/sim_engine/filesystem.rs +++ b/src/engine/sim_engine/filesystem.rs @@ -10,10 +10,23 @@ use serde_json::{Map, Value}; use devicemapper::{Bytes, Sectors}; use crate::{ - engine::{types::FilesystemUuid, Filesystem}, + engine::{ + types::{FilesystemUuid, Name}, + Filesystem, + }, stratis::{StratisError, StratisResult}, }; +#[derive(Debug, Eq, PartialEq, Serialize)] +pub struct FilesystemSave { + name: String, + uuid: FilesystemUuid, + size: Sectors, + created: u64, + fs_size_limit: Option, + origin: Option, +} + #[derive(Debug)] pub struct SimFilesystem { rand: u32, @@ -73,6 +86,17 @@ impl SimFilesystem { self.origin = None; changed } + + pub fn record(&self, name: &Name, uuid: FilesystemUuid) -> FilesystemSave { + FilesystemSave { + name: name.to_owned(), + uuid, + size: self.size, + created: self.created.timestamp() as u64, + fs_size_limit: self.size_limit, + origin: self.origin, + } + } } impl Filesystem for SimFilesystem { diff --git a/src/engine/sim_engine/pool.rs b/src/engine/sim_engine/pool.rs index 45f45eb0f6..c56a71fb53 100644 --- a/src/engine/sim_engine/pool.rs +++ b/src/engine/sim_engine/pool.rs @@ -758,6 +758,16 @@ impl Pool for SimPool { fn metadata_version(&self) -> StratSigblockVersion { StratSigblockVersion::V2 } + + fn last_fs_metadata(&self) -> StratisResult { + self.filesystems + .iter() + .map(|(name, uuid, fs)| { + serde_json::to_string(&fs.record(name, *uuid)).map_err(|e| e.into()) + }) + .collect::>>() + .map(|v| v.join("\n")) + } } #[cfg(test)] diff --git a/src/engine/strat_engine/pool/shared.rs b/src/engine/strat_engine/pool/shared.rs index 3c17b2e361..b4160256f3 100644 --- a/src/engine/strat_engine/pool/shared.rs +++ b/src/engine/strat_engine/pool/shared.rs @@ -348,4 +348,11 @@ impl Pool for AnyPool { AnyPool::V2(p) => p.metadata_version(), } } + + fn last_fs_metadata(&self) -> StratisResult { + match self { + AnyPool::V1(p) => p.last_fs_metadata(), + AnyPool::V2(p) => p.last_fs_metadata(), + } + } } diff --git a/src/engine/strat_engine/pool/v1.rs b/src/engine/strat_engine/pool/v1.rs index 932dbe3849..a8f4f7ac36 100644 --- a/src/engine/strat_engine/pool/v1.rs +++ b/src/engine/strat_engine/pool/v1.rs @@ -1293,6 +1293,17 @@ impl Pool for StratPool { fn metadata_version(&self) -> StratSigblockVersion { StratSigblockVersion::V1 } + + fn last_fs_metadata(&self) -> StratisResult { + self.thin_pool + .filesystems() + .iter() + .map(|(name, uuid, fs)| { + serde_json::to_string(&fs.record(name, *uuid)).map_err(|e| e.into()) + }) + .collect::>>() + .map(|v| v.join("\n")) + } } pub struct StratPoolState { diff --git a/src/engine/strat_engine/pool/v2.rs b/src/engine/strat_engine/pool/v2.rs index e82c6cfbca..e17712b065 100644 --- a/src/engine/strat_engine/pool/v2.rs +++ b/src/engine/strat_engine/pool/v2.rs @@ -1200,6 +1200,17 @@ impl Pool for StratPool { fn metadata_version(&self) -> StratSigblockVersion { StratSigblockVersion::V2 } + + fn last_fs_metadata(&self) -> StratisResult { + self.thin_pool + .filesystems() + .iter() + .map(|(name, uuid, fs)| { + serde_json::to_string(&fs.record(name, *uuid)).map_err(|e| e.into()) + }) + .collect::>>() + .map(|v| v.join("\n")) + } } pub struct StratPoolState {