Skip to content
Open
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
23 changes: 14 additions & 9 deletions src/engine/strat_engine/liminal/device_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -669,17 +669,22 @@ impl DeviceSet {
/// The encryption information and devices registered for stopped pools to
/// be exported over the API.
///
/// Error from gather_encryption_info is converted into an option because
/// unlocked Stratis devices and LUKS2 devices on which the Stratis devices are
/// stored may appear at different times in udev. This is not necessarily
/// an error case and may resolve itself after more devices appear in udev.
pub fn stopped_pool_info(&self) -> Option<StoppedPoolInfo> {
gather_encryption_info(
/// Converts an error result from gather_encryption_info into maximum
/// uncertainty, since the error means that encryption information is
/// completely missing from one device.
pub fn stopped_pool_info(&self) -> StoppedPoolInfo {
let info = gather_encryption_info(
self.internal.len(),
self.internal.values().map(|info| info.encryption_info()),
)
.ok()
.map(|info| StoppedPoolInfo {
.unwrap_or({
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this does the right thing. Errors are only returned when they're a mixture of encrypted and unencrypted devices. I think this aspect of the code should be handled in engine/shared.rs in the gather methods. Gather takes a function as a parameter so it can likely be modified to calculate whether it's PoolEncryption::KeyDesc(MaybeInconsistent::Yes), etc.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the two arguments to gather_encryption_info are constructed, the iterator derived from internal.values() returns None in one place, so that the flattened length is less than the unflattened.

I think that what you're saying is that when the information is being gathered, it is possible to determine what is the encryption info on the devices w/ valid encryption info.

So, if all the devices w/ valid LUKS metadata are KeyDescription only, then you would like to see PoolEncryptionInfo::KeyDesc(MaybeInconsistent::Yes) rather than both showing inconsistent?

I think we can do that, but my own position is that in the general case where the LUKS info is actually missing because invalid, that information is not certainly known, so I decided to use the most confused value.

If all the devices had valid LUKS2 metadata, and each had a key description, but some key descriptions were different from others, then I would think that it would be appropriate to return
`PoolEncryptionInfo::KeyDesc(MaybeInconsistent::Yes), but it actually make more sent to me to return Both``` as I do here, in this situation.

Some(PoolEncryptionInfo::Both(
MaybeInconsistent::Yes,
MaybeInconsistent::Yes,
))
});

StoppedPoolInfo {
info,
devices: self
.internal
Expand All @@ -699,7 +704,7 @@ impl DeviceSet {
}
})
.collect::<Vec<_>>(),
})
}
}

/// Process the data from a remove udev event. Since remove events are
Expand Down
8 changes: 2 additions & 6 deletions src/engine/strat_engine/liminal/liminal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -401,16 +401,12 @@ impl LiminalDevices {
stopped: self
.stopped_pools
.iter()
.filter_map(|(pool_uuid, map)| {
map.stopped_pool_info().map(|info| (*pool_uuid, info))
})
.map(|(pool_uuid, map)| (*pool_uuid, map.stopped_pool_info()))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks correct. It seems like we may have been only displaying encrypted pools in general for stopped pools, not just in the case of this bug!

.collect(),
partially_constructed: self
.partially_constructed_pools
.iter()
.filter_map(|(pool_uuid, map)| {
map.stopped_pool_info().map(|info| (*pool_uuid, info))
})
.map(|(pool_uuid, map)| (*pool_uuid, map.stopped_pool_info()))
.collect(),
}
}
Expand Down