use dbus::{arg::IterAppend, Path};
use dbus_tree::{MTSync, MethodErr, PropInfo, Tree};
use crate::{
dbus_api::types::TData,
engine::{BlockDev, BlockDevTier},
};
pub fn blockdev_operation<F, R>(
tree: &Tree<MTSync<TData>, TData>,
object_path: &Path<'static>,
closure: F,
) -> Result<R, String>
where
F: Fn(BlockDevTier, &dyn BlockDev) -> Result<R, String>,
R: dbus::arg::Append,
{
let dbus_context = tree.get_data();
let blockdev_path = tree
.get(object_path)
.expect("tree must contain implicit argument");
let blockdev_data = blockdev_path
.get_data()
.as_ref()
.ok_or_else(|| format!("no data for object path {}", object_path))?;
let blockdev_uuid = typed_uuid_string_err!(blockdev_data.uuid; Dev);
let pool_path = tree
.get(&blockdev_data.parent)
.ok_or_else(|| format!("no path for parent object path {}", &blockdev_data.parent))?;
let pool_uuid = typed_uuid_string_err!(
pool_path
.get_data()
.as_ref()
.ok_or_else(|| format!("no data for object path {}", object_path))?
.uuid;
Pool
);
let mutex_lock = dbus_context.engine.blocking_lock();
let (_, pool) = mutex_lock
.get_pool(pool_uuid)
.ok_or_else(|| format!("no pool corresponding to uuid {}", &pool_uuid))?;
let (tier, blockdev) = pool
.get_blockdev(blockdev_uuid)
.ok_or_else(|| format!("no blockdev with uuid {}", blockdev_data.uuid))?;
closure(tier, blockdev)
}
pub fn get_blockdev_property<F, R>(
i: &mut IterAppend,
p: &PropInfo<MTSync<TData>, TData>,
getter: F,
) -> Result<(), MethodErr>
where
F: Fn(BlockDevTier, &dyn BlockDev) -> Result<R, String>,
R: dbus::arg::Append,
{
i.append(
blockdev_operation(p.tree, p.path.get_name(), getter)
.map_err(|ref e| MethodErr::failed(e))?,
);
Ok(())
}
#[inline]
pub fn blockdev_devnode_prop(dev: &dyn BlockDev) -> String {
let pathbuf = match dev.user_path() {
Ok(path) => path,
Err(e) => {
warn!(
"Failed to canonicalize metadata path for block device: {}; \
falling back on non-canonicalized path",
e
);
dev.metadata_path().to_owned()
}
};
pathbuf.display().to_string()
}
#[inline]
pub fn blockdev_hardware_info_prop(dev: &dyn BlockDev) -> (bool, String) {
dev.hardware_info()
.map_or_else(|| (false, "".to_owned()), |val| (true, val.to_owned()))
}
#[inline]
pub fn blockdev_user_info_prop(dev: &dyn BlockDev) -> (bool, String) {
dev.user_info()
.map_or_else(|| (false, "".to_owned()), |val| (true, val.to_owned()))
}
#[inline]
pub fn blockdev_init_time_prop(dev: &dyn BlockDev) -> u64 {
dev.initialization_time().timestamp() as u64
}
#[inline]
pub fn blockdev_tier_prop(tier: BlockDevTier) -> u16 {
tier as u16
}
#[inline]
pub fn blockdev_physical_path_prop(dev: &dyn BlockDev) -> String {
dev.devnode().display().to_string()
}