Skip to content

Commit

Permalink
Add integrity tag and journal size parameters to D-Bus
Browse files Browse the repository at this point in the history
  • Loading branch information
jbaublitz committed Dec 9, 2024
1 parent 3ce9af2 commit 012e012
Show file tree
Hide file tree
Showing 15 changed files with 272 additions and 40 deletions.
5 changes: 3 additions & 2 deletions src/dbus_api/api/manager_3_0/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use futures::executor::block_on;

use crate::{
dbus_api::{
api::shared::EncryptionParams,
blockdev::create_dbus_blockdev,
consts,
filesystem::create_dbus_filesystem,
Expand All @@ -28,8 +29,6 @@ use crate::{
stratis::StratisError,
};

type EncryptionParams = (Option<(bool, String)>, Option<(bool, (String, String))>);

pub fn destroy_pool(m: &MethodInfo<'_, MTSync<TData>, TData>) -> MethodResult {
let message: &Message = m.msg;
let mut iter = message.iter_init();
Expand Down Expand Up @@ -329,6 +328,8 @@ pub fn create_pool(m: &MethodInfo<'_, MTSync<TData>, TData>) -> MethodResult {
name,
&devs.map(Path::new).collect::<Vec<&Path>>(),
EncryptionInfo::from_options((key_desc, clevis_info)).as_ref(),
None,
None,
)));
match create_result {
Ok(pool_uuid_action) => match pool_uuid_action {
Expand Down
2 changes: 2 additions & 0 deletions src/dbus_api/api/manager_3_5/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ pub fn create_pool(m: &MethodInfo<'_, MTSync<TData>, TData>) -> MethodResult {
name,
&devs.map(Path::new).collect::<Vec<&Path>>(),
EncryptionInfo::from_options((key_desc, clevis_info)).as_ref(),
None,
None,
)));
match create_result {
Ok(pool_uuid_action) => match pool_uuid_action {
Expand Down
49 changes: 48 additions & 1 deletion src/dbus_api/api/manager_3_8/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ use dbus_tree::{Access, EmitsChangedSignal, Factory, MTSync, Method, Property};

use crate::dbus_api::{
api::{
manager_3_8::{methods::start_pool, props::get_stopped_pools},
manager_3_8::{
methods::{create_pool, start_pool},
props::get_stopped_pools,
},
prop_conv::StoppedOrLockedPools,
},
consts,
Expand All @@ -31,6 +34,50 @@ pub fn start_pool_method(f: &Factory<MTSync<TData>, TData>) -> Method<MTSync<TDa
.out_arg(("return_string", "s"))
}

pub fn create_pool_method(f: &Factory<MTSync<TData>, TData>) -> Method<MTSync<TData>, TData> {
f.method("CreatePool", (), create_pool)
.in_arg(("name", "s"))
.in_arg(("devices", "as"))
// Optional key description of key in the kernel keyring
// b: true if the pool should be encrypted and able to be
// unlocked with a passphrase associated with this key description.
// s: key description
//
// Rust representation: (bool, String)
.in_arg(("key_desc", "(bs)"))
// Optional Clevis information for binding on initialization.
// b: true if the pool should be encrypted and able to be unlocked
// using Clevis.
// s: pin name
// s: JSON config for Clevis use
//
// Rust representation: (bool, (String, String))
.in_arg(("clevis_info", "(b(ss))"))
// Optional journal size for integrity metadata reservation.
// b: true if the size should be specified.
// false if the default should be used.
// i: Integer representing journal size in bytes.
//
// Rust representation: (bool, u64)
.in_arg(("journal_size", "(bt)"))
// Optional tag size for integrity metadata reservation.
// b: true if the size should be specified.
// false if the default should be used.
// i: Integer representing tag size in bytes.
//
// Rust representation: (bool, u8)
.in_arg(("tag_size", "(by)"))
// In order from left to right:
// b: true if a pool was created and object paths were returned
// o: Object path for Pool
// a(o): Array of object paths for block devices
//
// Rust representation: (bool, (dbus::Path, Vec<dbus::Path>))
.out_arg(("result", "(b(oao))"))
.out_arg(("return_code", "q"))
.out_arg(("return_string", "s"))
}

pub fn stopped_pools_property(f: &Factory<MTSync<TData>, TData>) -> Property<MTSync<TData>, TData> {
f.property::<StoppedOrLockedPools, _>(consts::STOPPED_POOLS_PROP, ())
.access(Access::Read)
Expand Down
122 changes: 118 additions & 4 deletions src/dbus_api/api/manager_3_8/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,30 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use dbus::{arg::OwnedFd, Message, Path};
use std::path::Path;

use dbus::{
arg::{Array, OwnedFd},
Message,
};
use dbus_tree::{MTSync, MethodInfo, MethodResult};
use futures::executor::block_on;

use devicemapper::Bytes;

use crate::{
dbus_api::{
api::shared::EncryptionParams,
blockdev::create_dbus_blockdev,
filesystem::create_dbus_filesystem,
pool::create_dbus_pool,
types::{DbusErrorEnum, TData, OK_STRING},
util::{engine_to_dbus_err_tuple, get_next_arg, tuple_to_option},
},
engine::{Name, PoolIdentifier, PoolUuid, StartAction, UnlockMethod},
engine::{
CreateAction, EncryptionInfo, KeyDescription, Name, PoolIdentifier, PoolUuid, StartAction,
UnlockMethod,
},
stratis::StratisError,
};

Expand All @@ -25,8 +36,12 @@ pub fn start_pool(m: &MethodInfo<'_, MTSync<TData>, TData>) -> MethodResult {
let dbus_context = m.tree.get_data();
let default_return: (
bool,
(Path<'static>, Vec<Path<'static>>, Vec<Path<'static>>),
) = (false, (Path::default(), Vec::new(), Vec::new()));
(
dbus::Path<'static>,
Vec<dbus::Path<'static>>,
Vec<dbus::Path<'static>>,
),
) = (false, (dbus::Path::default(), Vec::new(), Vec::new()));
let return_message = message.method_return();

let id_str: &str = get_next_arg(&mut iter, 0)?;
Expand Down Expand Up @@ -130,3 +145,102 @@ pub fn start_pool(m: &MethodInfo<'_, MTSync<TData>, TData>) -> MethodResult {
OK_STRING.to_string(),
)])
}

pub fn create_pool(m: &MethodInfo<'_, MTSync<TData>, TData>) -> MethodResult {
let base_path = m.path.get_name();
let message: &Message = m.msg;
let mut iter = message.iter_init();

let name: &str = get_next_arg(&mut iter, 0)?;
let devs: Array<'_, &str, _> = get_next_arg(&mut iter, 1)?;
let (key_desc_tuple, clevis_tuple): EncryptionParams = (
Some(get_next_arg(&mut iter, 2)?),
Some(get_next_arg(&mut iter, 3)?),
);
let journal_size_tuple: (bool, u64) = get_next_arg(&mut iter, 4)?;
let tag_size_tuple: (bool, u8) = get_next_arg(&mut iter, 5)?;

let return_message = message.method_return();

let default_return: (bool, (dbus::Path<'static>, Vec<dbus::Path<'static>>)) =
(false, (dbus::Path::default(), Vec::new()));

let key_desc = match key_desc_tuple.and_then(tuple_to_option) {
Some(kds) => match KeyDescription::try_from(kds) {
Ok(kd) => Some(kd),
Err(e) => {
let (rc, rs) = engine_to_dbus_err_tuple(&e);
return Ok(vec![return_message.append3(default_return, rc, rs)]);
}
},
None => None,
};

let clevis_info = match clevis_tuple.and_then(tuple_to_option) {
Some((pin, json_string)) => match serde_json::from_str(json_string.as_str()) {
Ok(j) => Some((pin, j)),
Err(e) => {
let (rc, rs) = engine_to_dbus_err_tuple(&StratisError::Serde(e));
return Ok(vec![return_message.append3(default_return, rc, rs)]);
}
},
None => None,
};

let journal_size = tuple_to_option(journal_size_tuple).map(|i| Bytes::from(i));
let tag_size = tuple_to_option(tag_size_tuple).map(Bytes::from);

let dbus_context = m.tree.get_data();
let create_result = handle_action!(block_on(dbus_context.engine.create_pool(
name,
&devs.map(Path::new).collect::<Vec<&Path>>(),
EncryptionInfo::from_options((key_desc, clevis_info)).as_ref(),
journal_size,
tag_size,
)));
match create_result {
Ok(pool_uuid_action) => match pool_uuid_action {
CreateAction::Created(uuid) => {
let guard = match block_on(dbus_context.engine.get_pool(PoolIdentifier::Uuid(uuid)))
{
Some(g) => g,
None => {
let (rc, rs) = engine_to_dbus_err_tuple(&StratisError::Msg(
format!("Pool with UUID {uuid} was successfully started but appears to have been removed before it could be exposed on the D-Bus")
));
return Ok(vec![return_message.append3(default_return, rc, rs)]);
}
};

let (pool_name, pool_uuid, pool) = guard.as_tuple();
let pool_path =
create_dbus_pool(dbus_context, base_path.clone(), &pool_name, pool_uuid, pool);
let mut bd_paths = Vec::new();
for (bd_uuid, tier, bd) in pool.blockdevs() {
bd_paths.push(create_dbus_blockdev(
dbus_context,
pool_path.clone(),
bd_uuid,
tier,
bd,
));
}

Ok(vec![return_message.append3(
(true, (pool_path, bd_paths)),
DbusErrorEnum::OK as u16,
OK_STRING.to_string(),
)])
}
CreateAction::Identity => Ok(vec![return_message.append3(
default_return,
DbusErrorEnum::OK as u16,
OK_STRING.to_string(),
)]),
},
Err(x) => {
let (rc, rs) = engine_to_dbus_err_tuple(&x);
Ok(vec![return_message.append3(default_return, rc, rs)])
}
}
}
2 changes: 1 addition & 1 deletion src/dbus_api/api/manager_3_8/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ mod api;
mod methods;
mod props;

pub use api::{start_pool_method, stopped_pools_property};
pub use api::{create_pool_method, start_pool_method, stopped_pools_property};
2 changes: 1 addition & 1 deletion src/dbus_api/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ pub fn get_base_tree<'a>(
)
.add(
f.interface(consts::MANAGER_INTERFACE_NAME_3_8, ())
.add_m(manager_3_5::create_pool_method(&f))
.add_m(manager_3_8::create_pool_method(&f))
.add_m(manager_3_0::set_key_method(&f))
.add_m(manager_3_0::unset_key_method(&f))
.add_m(manager_3_0::list_keys_method(&f))
Expand Down
2 changes: 2 additions & 0 deletions src/dbus_api/api/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ use crate::{
engine::{AllLockReadGuard, DevUuid, Engine, FilesystemUuid, Pool, PoolUuid, StratisUuid},
};

pub type EncryptionParams = (Option<(bool, String)>, Option<(bool, (String, String))>);

pub fn get_managed_objects_method(
f: &Factory<MTSync<TData>, TData>,
) -> Method<MTSync<TData>, TData> {
Expand Down
2 changes: 2 additions & 0 deletions src/engine/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,8 @@ pub trait Engine: Debug + Report + Send + Sync {
name: &str,
blockdev_paths: &[&Path],
encryption_info: Option<&EncryptionInfo>,
journal_size: Option<Bytes>,
tag_size: Option<Bytes>,
) -> StratisResult<CreateAction<PoolUuid>>;

/// Handle a libudev event.
Expand Down
Loading

0 comments on commit 012e012

Please sign in to comment.