Skip to content

Commit fa9db2f

Browse files
committed
Add PoolR0 interface
1 parent 8e98784 commit fa9db2f

8 files changed

Lines changed: 844 additions & 17 deletions

File tree

;

Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
// This Source Code Form is subject to the terms of the Mozilla Public
2+
// License, v. 2.0. If a copy of the MPL was not distributed with this
3+
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4+
5+
use std::{
6+
collections::HashSet,
7+
sync::{atomic::AtomicU64, Arc},
8+
};
9+
10+
use tokio::sync::RwLock;
11+
use zbus::{zvariant::ObjectPath, Connection};
12+
13+
use devicemapper::Bytes;
14+
15+
use crate::{
16+
dbus::{
17+
consts::OK_STRING,
18+
filesystem::{register_filesystem, unregister_filesystem},
19+
manager::Manager,
20+
types::DbusErrorEnum,
21+
util::{engine_to_dbus_err_tuple, tuple_to_option},
22+
},
23+
engine::{Engine, EngineAction, FilesystemUuid, Lockable, PoolIdentifier, PoolUuid, Name, CreateAction},
24+
stratis::StratisError,
25+
};
26+
27+
pub async fn create_filesystems_method<'a>(
28+
engine: &Arc<dyn Engine>,
29+
connection: &Arc<Connection>,
30+
manager: &Lockable<Arc<RwLock<Manager>>>,
31+
counter: &Arc<AtomicU64>,
32+
pool_uuid: PoolUuid,
33+
filesystems: Vec<(&str, (bool, &str))>,
34+
) -> ((bool, Vec<ObjectPath<'a>>), u16, String) {
35+
let default_return = (false, (Vec::new()));
36+
37+
let filesystem_specs = match filesystems
38+
.into_iter()
39+
.map(|(name, size_opt)| {
40+
let size = tuple_to_option(size_opt)
41+
.map(|val| {
42+
val.parse::<u128>().map_err(|_| {
43+
format!("Could not parse filesystem size string {val} to integer value")
44+
})
45+
})
46+
.transpose()?;
47+
Ok((name.to_string(), size.map(Bytes), None))
48+
})
49+
.collect::<Result<Vec<(String, Option<Bytes>, Option<Bytes>)>, String>>()
50+
{
51+
Ok(fs_specs) => fs_specs,
52+
Err(e) => {
53+
let (rc, rs) = (DbusErrorEnum::ERROR as u16, e);
54+
return (default_return, rc, rs);
55+
}
56+
};
57+
58+
let guard_res = engine
59+
.get_mut_pool(PoolIdentifier::Uuid(pool_uuid))
60+
.await
61+
.ok_or_else(|| StratisError::Msg(format!("No pool associated with uuid {pool_uuid}")));
62+
match tokio::task::spawn_blocking(move || {
63+
let mut guard = guard_res?;
64+
let (name, _, pool) = guard.as_mut_tuple();
65+
handle_action!(pool.create_filesystems(
66+
name.to_string().as_str(),
67+
pool_uuid,
68+
filesystem_specs
69+
.iter()
70+
.map(|(s, b1, b2)| (s.as_str(), *b1, *b2))
71+
.collect::<Vec<_>>()
72+
.as_slice(),
73+
))
74+
})
75+
.await
76+
{
77+
Ok(Ok(changed)) => {
78+
let mut object_paths = Vec::new();
79+
match changed.changed() {
80+
Some(v) => {
81+
for (_, uuid, _) in v {
82+
match register_filesystem(
83+
engine, connection, manager, counter, pool_uuid, uuid,
84+
)
85+
.await
86+
{
87+
Ok(path) => {
88+
object_paths.push(path);
89+
}
90+
Err(e) => {
91+
warn!("Failed to register the filesystem with the D-Bus: {e}; object may not be visible to clients");
92+
}
93+
}
94+
}
95+
(
96+
(true, object_paths),
97+
DbusErrorEnum::OK as u16,
98+
OK_STRING.to_string(),
99+
)
100+
}
101+
None => (
102+
default_return,
103+
DbusErrorEnum::OK as u16,
104+
OK_STRING.to_string(),
105+
),
106+
}
107+
}
108+
Ok(Err(e)) => {
109+
let (rc, rs) = engine_to_dbus_err_tuple(&e);
110+
(default_return, rc, rs)
111+
}
112+
Err(e) => {
113+
let (rc, rs) = engine_to_dbus_err_tuple(&StratisError::from(e));
114+
(default_return, rc, rs)
115+
}
116+
}
117+
}
118+
119+
pub async fn destroy_filesystems_method(
120+
engine: &Arc<dyn Engine>,
121+
connection: &Arc<Connection>,
122+
manager: &Lockable<Arc<RwLock<Manager>>>,
123+
pool_uuid: PoolUuid,
124+
filesystems: Vec<ObjectPath<'_>>,
125+
) -> ((bool, Vec<FilesystemUuid>), u16, String) {
126+
let default_return = (false, (Vec::new()));
127+
128+
let uuids = {
129+
let lock = manager.read().await;
130+
filesystems
131+
.iter()
132+
.filter_map(|op| lock.filesystem_get_uuid(op))
133+
.collect::<HashSet<_>>()
134+
};
135+
136+
let guard_res = engine
137+
.get_mut_pool(PoolIdentifier::Uuid(pool_uuid))
138+
.await
139+
.ok_or_else(|| StratisError::Msg(format!("No pool associated with uuid {pool_uuid}")));
140+
match tokio::task::spawn_blocking(move || {
141+
let mut guard = guard_res?;
142+
let (name, _, pool) = guard.as_mut_tuple();
143+
handle_action!(pool.destroy_filesystems(name.to_string().as_str(), &uuids,))
144+
})
145+
.await
146+
{
147+
Ok(Ok(changed)) => {
148+
let mut uuids = Vec::new();
149+
match changed.changed() {
150+
Some((v, _)) => {
151+
for op in filesystems.iter() {
152+
match unregister_filesystem(connection, manager, op).await {
153+
Ok(uuid) => {
154+
uuids.push(uuid);
155+
}
156+
Err(e) => {
157+
warn!("Failed to register the filesystem with the D-Bus: {e}; object may not be visible to clients");
158+
}
159+
}
160+
}
161+
((true, v), DbusErrorEnum::OK as u16, OK_STRING.to_string())
162+
}
163+
None => (
164+
default_return,
165+
DbusErrorEnum::OK as u16,
166+
OK_STRING.to_string(),
167+
),
168+
}
169+
}
170+
Ok(Err(e)) => {
171+
let (rc, rs) = engine_to_dbus_err_tuple(&e);
172+
(default_return, rc, rs)
173+
}
174+
Err(e) => {
175+
let (rc, rs) = engine_to_dbus_err_tuple(&StratisError::from(e));
176+
(default_return, rc, rs)
177+
}
178+
}
179+
}
180+
181+
pub async fn snapshot_filesystems_method<'a>(
182+
engine: &Arc<dyn Engine>,
183+
connection: &Arc<Connection>,
184+
manager: &Lockable<Arc<RwLock<Manager>>>,
185+
counter: &Arc<AtomicU64>,
186+
pool_uuid: PoolUuid,
187+
filesystem: ObjectPath<'_>,
188+
snapshot_name: &str,
189+
) -> ((bool, ObjectPath<'a>), u16, String) {
190+
let default_return = (false, ObjectPath::default());
191+
192+
let fs_uuid = match manager.read().await.filesystem_get_uuid(&filesystem) {
193+
Some(u) => u,
194+
None => {
195+
return (default_return, DbusErrorEnum::ERROR as u16, format!("No filesystem UUID associated with path {filesystem}"));
196+
}
197+
};
198+
199+
let guard_res = engine
200+
.get_mut_pool(PoolIdentifier::Uuid(pool_uuid))
201+
.await
202+
.ok_or_else(|| StratisError::Msg(format!("No pool associated with uuid {pool_uuid}")));
203+
match tokio::task::spawn_blocking(move || {
204+
let mut guard = guard_res?;
205+
let (name, _, pool) = guard.as_mut_tuple();
206+
handle_action!(pool.snapshot_filesystem(name.to_string().as_str(), pool_uuid, fs_uuid, snapshot_name)).map(|_| ())
207+
})
208+
.await
209+
{
210+
Ok(Ok(Crea)) => {
211+
let mut uuids = Vec::new();
212+
match changed.changed() {
213+
Some(uuid) => {
214+
register_filesystem(engine, connection, manager, counter, pool_uuid, fs_uuid);
215+
((true, v), DbusErrorEnum::OK as u16, OK_STRING.to_string())
216+
}
217+
None => (
218+
default_return,
219+
DbusErrorEnum::OK as u16,
220+
OK_STRING.to_string(),
221+
),
222+
}
223+
}
224+
Ok(Err(e)) => {
225+
let (rc, rs) = engine_to_dbus_err_tuple(&e);
226+
(default_return, rc, rs)
227+
}
228+
Err(e) => {
229+
let (rc, rs) = engine_to_dbus_err_tuple(&StratisError::from(e));
230+
(default_return, rc, rs)
231+
}
232+
}
233+
}

src/dbus/filesystem/filesystem_3_9/mod.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,17 @@ impl FilesystemR9 {
3939
connection.object_server().at(path, filesystem).await?;
4040
Ok(())
4141
}
42+
43+
pub async fn unregister(
44+
connection: &Arc<Connection>,
45+
path: ObjectPath<'_>,
46+
) -> StratisResult<()> {
47+
connection
48+
.object_server()
49+
.remove::<FilesystemR9, _>(path)
50+
.await?;
51+
Ok(())
52+
}
4253
}
4354

4455
#[interface(name = "org.storage.stratis3.filesystem.r9")]

src/dbus/filesystem/mod.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use zbus::{zvariant::ObjectPath, Connection};
1313
use crate::{
1414
dbus::{consts, Manager},
1515
engine::{Engine, FilesystemUuid, Lockable, PoolUuid},
16-
stratis::StratisResult,
16+
stratis::{StratisError, StratisResult},
1717
};
1818

1919
mod filesystem_3_0;
@@ -41,3 +41,19 @@ pub async fn register_filesystem<'a>(
4141

4242
Ok(path)
4343
}
44+
45+
pub async fn unregister_filesystem(
46+
connection: &Arc<Connection>,
47+
manager: &Lockable<Arc<RwLock<Manager>>>,
48+
path: &ObjectPath<'_>,
49+
) -> StratisResult<FilesystemUuid> {
50+
FilesystemR9::unregister(connection, path.clone()).await?;
51+
52+
let mut lock = manager.write().await;
53+
let uuid = lock
54+
.filesystem_get_uuid(path)
55+
.ok_or_else(|| StratisError::Msg(format!("No UUID associated with path {path}")))?;
56+
lock.remove_filesystem(path);
57+
58+
Ok(uuid)
59+
}

src/dbus/pool/mod.rs

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ mod pool_3_6;
2121
mod pool_3_9;
2222
mod shared;
2323

24+
pub use pool_3_0::PoolR0;
2425
pub use pool_3_9::PoolR9;
2526

2627
pub async fn register_pool<'a>(
@@ -35,15 +36,30 @@ pub async fn register_pool<'a>(
3536
consts::STRATIS_BASE_PATH,
3637
counter.fetch_add(1, Ordering::AcqRel),
3738
))?;
38-
PoolR9::register(
39+
if let Err(e) = PoolR0::register(
3940
engine,
4041
connection,
4142
manager,
4243
counter,
4344
path.clone(),
4445
pool_uuid,
4546
)
46-
.await?;
47+
.await
48+
{
49+
warn!("Failed to register interface pool.r0 for pool with UUID {pool_uuid}: {e}");
50+
}
51+
if let Err(e) = PoolR9::register(
52+
engine,
53+
connection,
54+
manager,
55+
counter,
56+
path.clone(),
57+
pool_uuid,
58+
)
59+
.await
60+
{
61+
warn!("Failed to register interface pool.r9 for pool with UUID {pool_uuid}: {e}");
62+
}
4763

4864
manager.write().await.add_pool(&path, pool_uuid);
4965

@@ -55,13 +71,21 @@ pub async fn unregister_pool(
5571
manager: &Lockable<Arc<RwLock<Manager>>>,
5672
path: &ObjectPath<'_>,
5773
) -> StratisResult<PoolUuid> {
58-
PoolR9::unregister(connection, path.clone()).await?;
74+
let uuid = {
75+
let mut lock = manager.write().await;
76+
let uuid = lock
77+
.pool_get_uuid(path)
78+
.ok_or_else(|| StratisError::Msg(format!("No UUID associated with path {path}")))?;
79+
lock.remove_pool(path);
80+
uuid
81+
};
5982

60-
let mut lock = manager.write().await;
61-
let uuid = lock
62-
.pool_get_uuid(path)
63-
.ok_or_else(|| StratisError::Msg(format!("No UUID associated with path {path}")))?;
64-
lock.remove_pool(path);
83+
if let Err(e) = PoolR0::unregister(connection, path.clone()).await {
84+
warn!("Failed to deregister interface pool.r0 for path {path}: {e}");
85+
}
86+
if let Err(e) = PoolR9::unregister(connection, path.clone()).await {
87+
warn!("Failed to deregister interface pool.r9 for path {path}: {e}");
88+
}
6589

6690
Ok(uuid)
6791
}

0 commit comments

Comments
 (0)