Skip to content

Commit

Permalink
Require at least one blockdev for initialization actions
Browse files Browse the repository at this point in the history
Currently we do not check that initialization actions like
creating a pool or initializing the cache are provided at least one
blockdev. Given that blockdevs are required for these actions,
this PR adds a check at the top level of the engine to return a
helpful error message if no blockdevs are given.
  • Loading branch information
jbaublitz committed Feb 19, 2020
1 parent 43d084e commit b8305a5
Show file tree
Hide file tree
Showing 17 changed files with 222 additions and 209 deletions.
7 changes: 7 additions & 0 deletions src/engine/macros.rs
Expand Up @@ -153,3 +153,10 @@ macro_rules! create_pool_generate_error_string {
)
};
}

#[cfg(test)]
macro_rules! strs_to_paths {
($slice:expr) => {
&$slice.iter().map(Path::new).collect::<Vec<_>>()
};
}
78 changes: 59 additions & 19 deletions src/engine/sim_engine/engine.rs
Expand Up @@ -41,19 +41,27 @@ impl Engine for SimEngine {
match self.pools.get_by_name(name) {
Some((_, pool)) => create_pool_idempotent_or_err(pool, name, blockdev_paths),
None => {
let device_set: HashSet<_, RandomState> = HashSet::from_iter(blockdev_paths);
let devices = device_set.into_iter().cloned().collect::<Vec<&Path>>();

let (pool_uuid, pool) = SimPool::new(&Rc::clone(&self.rdm), &devices, redundancy);

if self.rdm.borrow_mut().throw_die() {
return Err(StratisError::Engine(ErrorEnum::Error, "X".into()));
if blockdev_paths.is_empty() {
Err(StratisError::Engine(
ErrorEnum::Invalid,
"At least one blockdev is required to create a pool.".to_string(),
))
} else {
let device_set: HashSet<_, RandomState> = HashSet::from_iter(blockdev_paths);
let devices = device_set.into_iter().cloned().collect::<Vec<&Path>>();

let (pool_uuid, pool) =
SimPool::new(&Rc::clone(&self.rdm), &devices, redundancy);

if self.rdm.borrow_mut().throw_die() {
return Err(StratisError::Engine(ErrorEnum::Error, "X".into()));
}

self.pools
.insert(Name::new(name.to_owned()), pool_uuid, pool);

Ok(CreateAction::Created(pool_uuid))
}

self.pools
.insert(Name::new(name.to_owned()), pool_uuid, pool);

Ok(CreateAction::Created(pool_uuid))
}
}
}
Expand Down Expand Up @@ -181,7 +189,11 @@ mod tests {
fn destroy_empty_pool() {
let mut engine = SimEngine::default();
let uuid = engine
.create_pool("name", &[], None)
.create_pool(
"name",
strs_to_paths!(["/dev/one", "/dev/two", "/dev/three"]),
None,
)
.unwrap()
.changed()
.unwrap();
Expand Down Expand Up @@ -258,7 +270,11 @@ mod tests {
.create_pool(name, &[Path::new("/s/d")], None)
.unwrap();
assert_matches!(
engine.create_pool(name, &[], None),
engine.create_pool(
name,
strs_to_paths!(["/dev/one", "/dev/two", "/dev/three"]),
None,
),
Err(StratisError::Engine(ErrorEnum::Invalid, _))
);
}
Expand Down Expand Up @@ -302,7 +318,11 @@ mod tests {
let name = "name";
let mut engine = SimEngine::default();
let uuid = engine
.create_pool(name, &[], None)
.create_pool(
name,
strs_to_paths!(["/dev/one", "/dev/two", "/dev/three"]),
None,
)
.unwrap()
.changed()
.unwrap();
Expand All @@ -317,7 +337,11 @@ mod tests {
fn rename_happens() {
let mut engine = SimEngine::default();
let uuid = engine
.create_pool("old_name", &[], None)
.create_pool(
"old_name",
strs_to_paths!(["/dev/one", "/dev/two", "/dev/three"]),
None,
)
.unwrap()
.changed()
.unwrap();
Expand All @@ -333,11 +357,21 @@ mod tests {
let new_name = "new_name";
let mut engine = SimEngine::default();
let uuid = engine
.create_pool("old_name", &[], None)
.create_pool(
"old_name",
strs_to_paths!(["/dev/one", "/dev/two", "/dev/three"]),
None,
)
.unwrap()
.changed()
.unwrap();
engine.create_pool(new_name, &[], None).unwrap();
engine
.create_pool(
new_name,
strs_to_paths!(["/dev/four", "/dev/five", "/dev/six"]),
None,
)
.unwrap();
assert_matches!(
engine.rename_pool(uuid, new_name),
Err(StratisError::Engine(ErrorEnum::AlreadyExists, _))
Expand All @@ -349,7 +383,13 @@ mod tests {
fn rename_no_op() {
let new_name = "new_name";
let mut engine = SimEngine::default();
engine.create_pool(new_name, &[], None).unwrap();
engine
.create_pool(
new_name,
strs_to_paths!(["/dev/one", "/dev/two", "/dev/three"]),
None,
)
.unwrap();
assert_matches!(
engine.rename_pool(Uuid::new_v4(), new_name),
Ok(RenameAction::NoSource)
Expand Down
82 changes: 70 additions & 12 deletions src/engine/sim_engine/pool.rs
Expand Up @@ -112,6 +112,16 @@ impl Pool for SimPool {
paths: &[&Path],
tier: BlockDevTier,
) -> StratisResult<SetCreateAction<DevUuid>> {
if paths.is_empty() {
return if !self.has_cache() && tier == BlockDevTier::Cache {
Err(StratisError::Engine(
ErrorEnum::Invalid,
"At least one blockdev path is required to initialize a cache.".to_string(),
))
} else {
Ok(SetCreateAction::new(vec![]))
};
}
let devices: HashSet<_, RandomState> = HashSet::from_iter(paths);

let device_pairs: Vec<_> = devices
Expand Down Expand Up @@ -332,7 +342,11 @@ mod tests {
let mut engine = SimEngine::default();
let pool_name = "pool_name";
let uuid = engine
.create_pool(pool_name, &[], None)
.create_pool(
pool_name,
strs_to_paths!(["/dev/one", "/dev/two", "/dev/three"]),
None,
)
.unwrap()
.changed()
.unwrap();
Expand All @@ -351,7 +365,11 @@ mod tests {
let mut engine = SimEngine::default();
let pool_name = "pool_name";
let uuid = engine
.create_pool(pool_name, &[], None)
.create_pool(
pool_name,
strs_to_paths!(["/dev/one", "/dev/two", "/dev/three"]),
None,
)
.unwrap()
.changed()
.unwrap();
Expand All @@ -376,7 +394,11 @@ mod tests {
let mut engine = SimEngine::default();
let pool_name = "pool_name";
let uuid = engine
.create_pool(pool_name, &[], None)
.create_pool(
pool_name,
strs_to_paths!(["/dev/one", "/dev/two", "/dev/three"]),
None,
)
.unwrap()
.changed()
.unwrap();
Expand All @@ -402,7 +424,11 @@ mod tests {
let mut engine = SimEngine::default();
let pool_name = "pool_name";
let uuid = engine
.create_pool(pool_name, &[], None)
.create_pool(
pool_name,
strs_to_paths!(["/dev/one", "/dev/two", "/dev/three"]),
None,
)
.unwrap()
.changed()
.unwrap();
Expand All @@ -421,7 +447,11 @@ mod tests {
let mut engine = SimEngine::default();
let pool_name = "pool_name";
let uuid = engine
.create_pool(pool_name, &[], None)
.create_pool(
pool_name,
strs_to_paths!(["/dev/one", "/dev/two", "/dev/three"]),
None,
)
.unwrap()
.changed()
.unwrap();
Expand All @@ -438,7 +468,11 @@ mod tests {
let mut engine = SimEngine::default();
let pool_name = "pool_name";
let uuid = engine
.create_pool(pool_name, &[], None)
.create_pool(
pool_name,
strs_to_paths!(["/dev/one", "/dev/two", "/dev/three"]),
None,
)
.unwrap()
.changed()
.unwrap();
Expand All @@ -455,7 +489,11 @@ mod tests {
let mut engine = SimEngine::default();
let pool_name = "pool_name";
let uuid = engine
.create_pool(pool_name, &[], None)
.create_pool(
pool_name,
strs_to_paths!(["/dev/one", "/dev/two", "/dev/three"]),
None,
)
.unwrap()
.changed()
.unwrap();
Expand All @@ -478,7 +516,11 @@ mod tests {
let mut engine = SimEngine::default();
let pool_name = "pool_name";
let uuid = engine
.create_pool(pool_name, &[], None)
.create_pool(
pool_name,
strs_to_paths!(["/dev/one", "/dev/two", "/dev/three"]),
None,
)
.unwrap()
.changed()
.unwrap();
Expand All @@ -493,7 +535,11 @@ mod tests {
let mut engine = SimEngine::default();
let pool_name = "pool_name";
let uuid = engine
.create_pool(pool_name, &[], None)
.create_pool(
pool_name,
strs_to_paths!(["/dev/one", "/dev/two", "/dev/three"]),
None,
)
.unwrap()
.changed()
.unwrap();
Expand All @@ -515,7 +561,11 @@ mod tests {
let mut engine = SimEngine::default();
let pool_name = "pool_name";
let uuid = engine
.create_pool(pool_name, &[], None)
.create_pool(
pool_name,
strs_to_paths!(["/dev/one", "/dev/two", "/dev/three"]),
None,
)
.unwrap()
.changed()
.unwrap();
Expand All @@ -535,7 +585,11 @@ mod tests {
let mut engine = SimEngine::default();
let pool_name = "pool_name";
let uuid = engine
.create_pool(pool_name, &[], None)
.create_pool(
pool_name,
strs_to_paths!(["/dev/one", "/dev/two", "/dev/three"]),
None,
)
.unwrap()
.changed()
.unwrap();
Expand All @@ -555,7 +609,11 @@ mod tests {
fn add_device_empty() {
let mut engine = SimEngine::default();
let uuid = engine
.create_pool("pool_name", &[], None)
.create_pool(
"pool_name",
strs_to_paths!(["/dev/one", "/dev/two", "/dev/three"]),
None,
)
.unwrap()
.changed()
.unwrap();
Expand Down
19 changes: 13 additions & 6 deletions src/engine/strat_engine/engine.rs
Expand Up @@ -205,12 +205,19 @@ impl Engine for StratEngine {
match self.pools.get_by_name(name) {
Some((_, pool)) => create_pool_idempotent_or_err(pool, name, blockdev_paths),
None => {
let (uuid, pool) = StratPool::initialize(name, blockdev_paths, redundancy)?;

let name = Name::new(name.to_owned());
devlinks::pool_added(&name);
self.pools.insert(name, uuid, pool);
Ok(CreateAction::Created(uuid))
if blockdev_paths.is_empty() {
Err(StratisError::Engine(
ErrorEnum::Invalid,
"At least one blockdev is required to create a pool.".to_string(),
))
} else {
let (uuid, pool) = StratPool::initialize(name, blockdev_paths, redundancy)?;

let name = Name::new(name.to_owned());
devlinks::pool_added(&name);
self.pools.insert(name, uuid, pool);
Ok(CreateAction::Created(uuid))
}
}
}
}
Expand Down
10 changes: 10 additions & 0 deletions src/engine/strat_engine/pool.rs
Expand Up @@ -309,6 +309,16 @@ impl Pool for StratPool {
paths: &[&Path],
tier: BlockDevTier,
) -> StratisResult<SetCreateAction<DevUuid>> {
if paths.is_empty() {
return if !self.has_cache() && tier == BlockDevTier::Cache {
Err(StratisError::Engine(
ErrorEnum::Invalid,
"At least one blockdev path is required to initialize a cache.".to_string(),
))
} else {
Ok(SetCreateAction::new(vec![]))
};
}
let bdev_info = if tier == BlockDevTier::Cache {
// If adding cache devices, must suspend the pool, since the cache
// must be augmeneted with the new devices.
Expand Down
Expand Up @@ -31,3 +31,12 @@ class StratisdErrors(IntEnum):
BUSY = 3
INTERNAL_ERROR = 4
NOT_FOUND = 5


class BlockDevTiers(IntEnum):
"""
Tier to which a blockdev device belongs.
"""

Data = 0
Cache = 1
Expand Up @@ -21,7 +21,7 @@

from .._misc import SimTestCase, device_name_list

_DEVICE_STRATEGY = device_name_list()
_DEVICE_STRATEGY = device_name_list(1)


class FetchPropertiesTestCase(SimTestCase):
Expand Down
2 changes: 1 addition & 1 deletion tests/client-dbus/tests/dbus/filesystem/test_properties.py
Expand Up @@ -24,7 +24,7 @@

from .._misc import SimTestCase, device_name_list

_DEVICE_STRATEGY = device_name_list()
_DEVICE_STRATEGY = device_name_list(1)


class SetNameTestCase(SimTestCase):
Expand Down
2 changes: 1 addition & 1 deletion tests/client-dbus/tests/dbus/filesystem/test_rename.py
Expand Up @@ -29,7 +29,7 @@

from .._misc import SimTestCase, device_name_list

_DEVICE_STRATEGY = device_name_list()
_DEVICE_STRATEGY = device_name_list(1)


class SetNameTestCase(SimTestCase):
Expand Down

0 comments on commit b8305a5

Please sign in to comment.