[pbs-devel] [PATCH proxmox-backup 1/3] api2: disks endpoint return partitions
Wolfgang Bumiller
w.bumiller at proxmox.com
Wed Apr 6 11:12:39 CEST 2022
On Mon, Apr 04, 2022 at 09:50:46AM +0000, Hannes Laimer wrote:
> Signed-off-by: Hannes Laimer <h.laimer at proxmox.com>
> ---
> src/api2/node/disks/directory.rs | 2 +-
> src/api2/node/disks/mod.rs | 11 ++-
> src/api2/node/disks/zfs.rs | 2 +-
> src/tools/disks/mod.rs | 121 ++++++++++++++++++++++++++++++-
> 4 files changed, 130 insertions(+), 6 deletions(-)
>
> diff --git a/src/api2/node/disks/directory.rs b/src/api2/node/disks/directory.rs
> index bf1a1be6..79fe2624 100644
> --- a/src/api2/node/disks/directory.rs
> +++ b/src/api2/node/disks/directory.rs
> @@ -149,7 +149,7 @@ pub fn create_datastore_disk(
>
> let auth_id = rpcenv.get_auth_id().unwrap();
>
> - let info = get_disk_usage_info(&disk, true)?;
> + let info = get_disk_usage_info(&disk, true, false)?;
I already feel like 2 bool parameters in a row warrants a query builder
type sane with defaults.
DiskUsageQuery::new(&disk)
.smart(false) // optional
.partitions(true) // optional
.query()
but this can be added later (the implementation itself can still stay as
a regular function anyway )
>
> if info.used != DiskUsageType::Unused {
> bail!("disk '{}' is already in use.", disk);
(...)
> diff --git a/src/tools/disks/mod.rs b/src/tools/disks/mod.rs
> index 94da7b3a..fb9c78a9 100644
> --- a/src/tools/disks/mod.rs
> +++ b/src/tools/disks/mod.rs
> @@ -602,6 +602,26 @@ fn get_file_system_devices(lsblk_info: &[LsblkInfo]) -> Result<HashSet<u64>, Err
> Ok(device_set)
> }
>
> +#[api()]
> +#[derive(Debug, Serialize, Deserialize, PartialEq)]
+Clone
And if it's just a simple list like this +Copy, however, this should
probably contain the file system string in the last member, so not Copy.
> +#[serde(rename_all = "lowercase")]
> +pub enum PartitionUsageType {
> + /// Partition is not used (as far we can tell)
> + Unused,
> + /// Partition is mounted
> + Mounted,
I don't think `Mounted` should be in the same enum here.
In PVE::Diskmanage we can have a file system type with " (mounted)"
attached to it as a string, as well as "just" mounted with no extra
info.
> + /// Partition is used by LVM
> + LVM,
> + /// Partition is used by ZFS
> + ZFS,
> + /// Partition is an EFI partition
> + EFI,
> + /// Partition is a BIOS partition
> + BIOS,
> + /// Partition contains a file system label
> + FileSystem,
This should contain the file system string.
> +}
> +
> #[api()]
> #[derive(Debug, Serialize, Deserialize, PartialEq)]
> #[serde(rename_all = "lowercase")]
(...)
> @@ -837,6 +888,71 @@ pub fn get_disks(
>
> let wwn = disk.wwn().map(|s| s.to_string_lossy().into_owned());
>
> + let partitions: Option<Vec<PartitionInfo>> = if include_partitions {
> + let lsblk_infos = get_lsblk_info();
Please explicitly discard the error with a `.ok()` here and match for
`Some` instead of `Ok` later on.
> + disk.partitions().map_or(None, |parts| {
> + Some(
> + parts
> + .iter()
> + .map(|(nr, disk)| {
Too much indentation, please factorize.
This looks like $determine_usage in PVE::Diskmanage.
If factorized into its own function it's easy to just use `return` (and
keep it in the same order as the perl code, particularly the mounted
part is a bit different atm.)
Makes it easier to check for equivalent API behavior (if we want that).
(On a side node: Ideally I *would* like to move the perl & rust code
into a direction where we can soon replace `PVE::Diskmanage` itself with
this rust code via pve-rs)
> + let devpath = disk
> + .device_path()
> + .map(|p| p.to_owned())
> + .map(|p| p.to_string_lossy().to_string());
> +
> + let mut used = PartitionUsageType::Unused;
> +
> + if let Some(devnum) = disk.devnum().ok() {
> + if lvm_devices.contains(&devnum) {
> + used = PartitionUsageType::LVM;
> + }
> + if zfs_devices.contains(&devnum) {
> + used = PartitionUsageType::ZFS;
> + }
> + }
> + match disk.is_mounted() {
> + Ok(true) => used = PartitionUsageType::Mounted,
> + Ok(false) => {}
> + Err(_) => {} // skip devices with undetectable mount status
> + }
> +
> + if let Some(devpath) = devpath.as_ref() {
> + if let Ok(infos) = lsblk_infos.as_ref() {
Could drop a level of indentation here via a tuple match:
if let (Some(devpath), Some(infos)) = (devpath.as_ref(), lsblk_info.as_ref()) {
> + for info in infos.iter().filter(|i| i.path.eq(devpath)) {
> + used = match info.partition_type.as_deref() {
> + Some("21686148-6449-6e6f-744e-656564454649") => {
> + PartitionUsageType::BIOS
> + }
> + Some("c12a7328-f81f-11d2-ba4b-00a0c93ec93b") => {
> + PartitionUsageType::EFI
> + }
PVE::Diskmanage also has a 'ZFS reserved' case, should we not add this
here as well?
> + _ => used,
> + }
> + }
> + }
> + }
> +
> + if used == PartitionUsageType::Unused
> + && file_system_devices.contains(&devnum)
> + {
> + used = PartitionUsageType::FileSystem;
> + }
> +
> + PartitionInfo {
> + name: format!("{}{}", name, nr),
> + devpath,
> + used,
> + size: disk.size().ok(),
> + gpt: disk.has_gpt(),
> + }
> + })
> + .collect(),
> + )
> + })
> + } else {
> + None
> + };
> +
> if usage != DiskUsageType::Mounted {
> match scan_partitions(disk_manager.clone(), &lvm_devices, &zfs_devices, &name) {
> Ok(part_usage) => {
> @@ -870,6 +986,7 @@ pub fn get_disks(
> name: name.clone(),
> vendor,
> model,
> + partitions,
> serial,
> devpath,
> size,
> --
> 2.30.2
More information about the pbs-devel
mailing list