Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stop pool changes #3297

Merged
merged 1 commit into from
May 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions src/dbus_api/api/manager_3_2/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ where
return Ok(vec![return_message.append3(default_return, rc, rs)]);
}
};

let unlock_method = {
let unlock_method_tup: (bool, &str) = get_next_arg(&mut iter, 1)?;
match tuple_to_option(unlock_method_tup) {
Expand Down Expand Up @@ -79,7 +80,7 @@ where
}
};

let (pool_name, _, pool) = guard.as_tuple();
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();
Expand Down Expand Up @@ -169,7 +170,11 @@ where
})
.unwrap_or(false);

let msg = match handle_action!(block_on(dbus_context.engine.stop_pool(pool_uuid))) {
let msg = match handle_action!(block_on(
dbus_context
.engine
.stop_pool(PoolIdentifier::Uuid(pool_uuid), false)
)) {
Ok(StopAction::Stopped(_)) => {
dbus_context.push_remove(&pool_path, consts::pool_interface_list());
if send_locked_signal {
Expand All @@ -182,6 +187,7 @@ where
OK_STRING.to_string(),
)
}
Ok(StopAction::CleanedUp(_)) => unreachable!("!has_partially_constructed above"),
Ok(StopAction::Identity) => return_message.append3(
default_return,
DbusErrorEnum::OK as u16,
Expand Down
29 changes: 29 additions & 0 deletions src/dbus_api/api/manager_3_6/api.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// 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_tree::{Factory, MTSync, Method};

use crate::{
dbus_api::{api::manager_3_6::methods::stop_pool, types::TData},
engine::Engine,
};

pub fn stop_pool_method<E>(
f: &Factory<MTSync<TData<E>>, TData<E>>,
) -> Method<MTSync<TData<E>>, TData<E>>
where
E: 'static + Engine,
{
f.method("StopPool", (), stop_pool)
.in_arg(("id", "s"))
.in_arg(("id_type", "s"))
// In order from left to right:
// b: true if the pool was newly stopped
// s: string representation of UUID of stopped pool
//
// Rust representation: (bool, String)
.out_arg(("result", "(bs)"))
.out_arg(("return_code", "q"))
.out_arg(("return_string", "s"))
}
116 changes: 116 additions & 0 deletions src/dbus_api/api/manager_3_6/methods.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// 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::Message;
use dbus_tree::{MTSync, MethodInfo, MethodResult};
use futures::executor::block_on;

use crate::{
dbus_api::{
consts,
types::{DbusErrorEnum, TData, OK_STRING},
util::{engine_to_dbus_err_tuple, get_next_arg},
},
engine::{Engine, Name, Pool, PoolIdentifier, PoolUuid, StopAction, StratisUuid},
stratis::StratisError,
};

pub fn stop_pool<E>(m: &MethodInfo<'_, MTSync<TData<E>>, TData<E>>) -> MethodResult
where
E: 'static + Engine,
{
let message: &Message = m.msg;
let mut iter = message.iter_init();
let dbus_context = m.tree.get_data();
let default_return = (false, String::new());
let return_message = message.method_return();

let id_str: &str = get_next_arg(&mut iter, 0)?;
let pool_id = {
let id_type_str: &str = get_next_arg(&mut iter, 1)?;
match id_type_str {
"uuid" => match PoolUuid::parse_str(id_str) {
Ok(u) => PoolIdentifier::Uuid(u),
Err(e) => {
let (rc, rs) = engine_to_dbus_err_tuple(&e);
return Ok(vec![return_message.append3(default_return, rc, rs)]);
}
},
"name" => PoolIdentifier::Name(Name::new(id_str.to_string())),
_ => {
let (rc, rs) = engine_to_dbus_err_tuple(&StratisError::Msg(format!(
"ID type {id_type_str} not recognized"
)));
return Ok(vec![return_message.append3(default_return, rc, rs)]);
}
}
};

// If Some(_), send a locked pool property change signal only if the pool is
// encrypted. If None, the pool may already be stopped or not exist at all.
// Both of these cases are handled by stop_pool and the value we provide
// for send_locked_signal does not matter as send_locked_signal is only
// used when a pool is newly stopped which can only occur if the pool is found
// here.
let send_locked_signal = block_on(dbus_context.engine.get_pool(pool_id.clone()))
.map(|g| {
let (_, _, p) = g.as_tuple();
p.is_encrypted()
})
.unwrap_or(false);

let msg = match handle_action!(block_on(dbus_context.engine.stop_pool(pool_id, true))) {
Ok(StopAction::Stopped(pool_uuid)) => {
match m.tree.iter().find_map(|opath| {
opath
.get_data()
.as_ref()
.and_then(|op_cxt| match op_cxt.uuid {
StratisUuid::Pool(u) => {
if u == pool_uuid {
Some(opath.get_name())
} else {
None
}
}
StratisUuid::Fs(_) => None,
StratisUuid::Dev(_) => None,
})
}) {
Some(pool_path) => {
dbus_context.push_remove(pool_path, consts::pool_interface_list());
if send_locked_signal {
dbus_context
.push_locked_pools(block_on(dbus_context.engine.locked_pools()));
}
dbus_context.push_stopped_pools(block_on(dbus_context.engine.stopped_pools()));
}
None => {
warn!("Could not find pool D-Bus path for the pool that was just stopped");
}
}
return_message.append3(
(true, uuid_to_string!(pool_uuid)),
DbusErrorEnum::OK as u16,
OK_STRING.to_string(),
)
}
Ok(StopAction::CleanedUp(pool_uuid)) => return_message.append3(
(true, uuid_to_string!(pool_uuid)),
DbusErrorEnum::OK as u16,
OK_STRING.to_string(),
),
Ok(StopAction::Identity) => return_message.append3(
default_return,
DbusErrorEnum::OK as u16,
OK_STRING.to_string(),
),
Err(e) => {
let (rc, rs) = engine_to_dbus_err_tuple(&e);
return Ok(vec![return_message.append3(default_return, rc, rs)]);
}
};

Ok(vec![msg])
}
4 changes: 4 additions & 0 deletions src/dbus_api/api/manager_3_6/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
mod api;
mod methods;

pub use api::stop_pool_method;
3 changes: 2 additions & 1 deletion src/dbus_api/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ mod manager_3_0;
mod manager_3_2;
mod manager_3_4;
mod manager_3_5;
mod manager_3_6;
pub mod prop_conv;
mod report_3_0;
mod shared;
Expand Down Expand Up @@ -135,7 +136,7 @@ where
.add_m(manager_3_0::destroy_pool_method(&f))
.add_m(manager_3_0::engine_state_report_method(&f))
.add_m(manager_3_4::start_pool_method(&f))
.add_m(manager_3_2::stop_pool_method(&f))
.add_m(manager_3_6::stop_pool_method(&f))
.add_m(manager_3_2::refresh_state_method(&f))
.add_p(manager_3_0::version_property(&f))
.add_p(manager_3_2::stopped_pools_property(&f)),
Expand Down
6 changes: 5 additions & 1 deletion src/engine/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,11 @@ pub trait Engine: Debug + Report + Send + Sync {

/// Stop and tear down a pool, storing the information for it to be started
/// again later.
async fn stop_pool(&self, pool_uuid: PoolUuid) -> StratisResult<StopAction<PoolUuid>>;
async fn stop_pool(
&self,
pool_id: PoolIdentifier<PoolUuid>,
has_partially_constructed: bool,
) -> StratisResult<StopAction<PoolUuid>>;

/// Refresh the state of all pools and liminal devices.
async fn refresh_state(&self) -> StratisResult<()>;
Expand Down
40 changes: 29 additions & 11 deletions src/engine/sim_engine/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -342,24 +342,42 @@ impl Engine for SimEngine {
}
}

async fn stop_pool(&self, pool_uuid: PoolUuid) -> StratisResult<StopAction<PoolUuid>> {
if self
.stopped_pools
.read()
.await
.get_by_uuid(pool_uuid)
.is_some()
{
Ok(StopAction::Identity)
} else if let Some((name, pool)) = self.pools.write_all().await.remove_by_uuid(pool_uuid) {
async fn stop_pool(
&self,
pool_id: PoolIdentifier<PoolUuid>,
_: bool,
) -> StratisResult<StopAction<PoolUuid>> {
let is_stopped = match pool_id {
PoolIdentifier::Name(ref n) => self.stopped_pools.read().await.get_by_name(n).is_some(),
PoolIdentifier::Uuid(u) => self.stopped_pools.read().await.get_by_uuid(u).is_some(),
};
if is_stopped {
return Ok(StopAction::Identity);
}

let pool_entry = match pool_id {
PoolIdentifier::Name(ref n) => self
.pools
.write_all()
.await
.remove_by_name(n)
.map(|(u, p)| (n.clone(), u, p)),
PoolIdentifier::Uuid(u) => self
.pools
.write_all()
.await
.remove_by_uuid(u)
.map(|(n, p)| (n, u, p)),
};
if let Some((name, pool_uuid, pool)) = pool_entry {
self.stopped_pools
.write()
.await
.insert(name, pool_uuid, pool);
Ok(StopAction::Stopped(pool_uuid))
} else {
Err(StratisError::Msg(format!(
"Pool with UUID {pool_uuid} was not found and cannot be stopped"
"Pool with ID {pool_id} was not found and cannot be stopped"
)))
}
}
Expand Down
60 changes: 42 additions & 18 deletions src/engine/strat_engine/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -657,29 +657,49 @@ impl Engine for StratEngine {
}
}

async fn stop_pool(&self, pool_uuid: PoolUuid) -> StratisResult<StopAction<PoolUuid>> {
async fn stop_pool(
&self,
pool_id: PoolIdentifier<PoolUuid>,
has_partially_constructed: bool,
) -> StratisResult<StopAction<PoolUuid>> {
let id_str = pool_id.to_string();

let stopped_pools = self.liminal_devices.read().await.stopped_pools();
let pool_uuid = match pool_id {
PoolIdentifier::Name(ref n) => stopped_pools.name_to_uuid.get(n),
PoolIdentifier::Uuid(ref u) => Some(u),
};
if let Some(pool_uuid) = pool_uuid {
if has_partially_constructed {
if stopped_pools.stopped.get(pool_uuid).is_some() {
return Ok(StopAction::Identity);
} else if stopped_pools.partially_constructed.get(pool_uuid).is_some() {
self.liminal_devices
.write()
.await
.stop_partially_constructed_pool(*pool_uuid)?;
return Ok(StopAction::CleanedUp(*pool_uuid));
}
} else if stopped_pools.stopped.get(pool_uuid).is_some()
|| stopped_pools.partially_constructed.get(pool_uuid).is_some()
{
return Ok(StopAction::Identity);
}
}

let mut pools = self.pools.write_all().await;
if let Some((name, pool)) = pools.remove_by_uuid(pool_uuid) {
if let Some((name, pool_uuid, pool)) = match pool_id {
PoolIdentifier::Name(n) => pools.remove_by_name(&n).map(|(u, p)| (n, u, p)),
PoolIdentifier::Uuid(u) => pools.remove_by_uuid(u).map(|(n, p)| (n, u, p)),
} {
self.liminal_devices
.write()
.await
.stop_pool(&mut pools, name, pool_uuid, pool)?;
return Ok(StopAction::Stopped(pool_uuid));
}

drop(pools);

let stopped_pools = self.liminal_devices.read().await.stopped_pools();
if stopped_pools.stopped.get(&pool_uuid).is_some()
|| stopped_pools
.partially_constructed
.get(&pool_uuid)
.is_some()
{
Ok(StopAction::Identity)
Ok(StopAction::Stopped(pool_uuid))
} else {
Err(StratisError::Msg(format!(
"Pool with UUID {pool_uuid} could not be found and cannot be stopped"
"Pool with UUID {id_str} could not be found and cannot be stopped"
)))
}
}
Expand Down Expand Up @@ -938,7 +958,7 @@ mod test {
let res = init_res.and_then(|_| needs_clean_up(&mut pool, fail_device, operation));
drop(pool);

test_async!(engine.stop_pool(uuid))?;
test_async!(engine.stop_pool(PoolIdentifier::Uuid(uuid), true))?;
res?;

test_async!(engine.start_pool(PoolIdentifier::Uuid(uuid), Some(unlock_method)))?;
Expand Down Expand Up @@ -1360,7 +1380,11 @@ mod test {
.unwrap()
.changed()
.unwrap();
assert!(test_async!(engine.stop_pool(uuid)).unwrap().is_changed());
assert!(
test_async!(engine.stop_pool(PoolIdentifier::Uuid(uuid), true))
.unwrap()
.is_changed()
);
assert_eq!(test_async!(engine.stopped_pools()).stopped.len(), 1);
assert_eq!(test_async!(engine.pools()).len(), 0);

Expand Down
14 changes: 14 additions & 0 deletions src/engine/strat_engine/liminal/liminal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,20 @@ impl LiminalDevices {
}
}

/// Tear down a partially constructed pool.
pub fn stop_partially_constructed_pool(&mut self, pool_uuid: PoolUuid) -> StratisResult<()> {
if let Some(device_set) = self.partially_constructed_pools.get(&pool_uuid) {
stop_partially_constructed_pool(
pool_uuid,
&device_set
.iter()
.map(|(dev_uuid, _)| *dev_uuid)
.collect::<Vec<_>>(),
)?;
}
Ok(())
}

/// Get a mapping of pool UUIDs from all of the LUKS2 devices that are currently
/// locked to their encryption info in the set of pools that are not yet set up.
pub fn locked_pools(&self) -> LockedPoolsInfo {
Expand Down
Loading