diff --git a/src/tools/disks.rs b/src/tools/disks.rs index 8573695d..885edf47 100644 --- a/src/tools/disks.rs +++ b/src/tools/disks.rs @@ -46,6 +46,16 @@ pub struct DiskManage { mounted_devices: OnceCell>, } +/// Information for a device as returned by lsblk. +#[derive(Deserialize)] +pub struct LsblkInfo { + /// Path to the device. + path: String, + /// Partition type GUID. + #[serde(rename = "parttype")] + partition_type: Option, +} + impl DiskManage { /// Create a new disk management context. pub fn new() -> Arc { @@ -556,31 +566,16 @@ pub struct BlockDevStat { } /// Use lsblk to read partition type uuids. -pub fn get_partition_type_info() -> Result>, Error> { +pub fn get_lsblk_info() -> Result, Error> { let mut command = std::process::Command::new("lsblk"); command.args(&["--json", "-o", "path,parttype"]); let output = crate::tools::run_command(command, None)?; - let mut res: HashMap> = HashMap::new(); + let mut output: serde_json::Value = output.parse()?; - let output: serde_json::Value = output.parse()?; - if let Some(list) = output["blockdevices"].as_array() { - for info in list { - let path = match info["path"].as_str() { - Some(p) => p, - None => continue, - }; - let partition_type = match info["parttype"].as_str() { - Some(t) => t.to_owned(), - None => continue, - }; - let devices = res.entry(partition_type).or_insert(Vec::new()); - devices.push(path.to_string()); - } - } - Ok(res) + Ok(serde_json::from_value(output["blockdevices"].take())?) } #[api()] @@ -736,14 +731,14 @@ pub fn get_disks( let disk_manager = DiskManage::new(); - let partition_type_map = get_partition_type_info()?; + let lsblk_info = get_lsblk_info()?; - let zfs_devices = zfs_devices(&partition_type_map, None).or_else(|err| -> Result, Error> { + let zfs_devices = zfs_devices(&lsblk_info, None).or_else(|err| -> Result, Error> { eprintln!("error getting zfs devices: {}", err); Ok(HashSet::new()) })?; - let lvm_devices = get_lvm_devices(&partition_type_map)?; + let lvm_devices = get_lvm_devices(&lsblk_info)?; // fixme: ceph journals/volumes diff --git a/src/tools/disks/lvm.rs b/src/tools/disks/lvm.rs index 1e8f825d..1a81cea0 100644 --- a/src/tools/disks/lvm.rs +++ b/src/tools/disks/lvm.rs @@ -1,10 +1,12 @@ -use std::collections::{HashSet, HashMap}; +use std::collections::HashSet; use std::os::unix::fs::MetadataExt; use anyhow::{Error}; use serde_json::Value; use lazy_static::lazy_static; +use super::LsblkInfo; + lazy_static!{ static ref LVM_UUIDS: HashSet<&'static str> = { let mut set = HashSet::new(); @@ -17,7 +19,7 @@ lazy_static!{ /// /// The set is indexed by using the unix raw device number (dev_t is u64) pub fn get_lvm_devices( - partition_type_map: &HashMap>, + lsblk_info: &[LsblkInfo], ) -> Result, Error> { const PVS_BIN_PATH: &str = "pvs"; @@ -29,12 +31,12 @@ pub fn get_lvm_devices( let mut device_set: HashSet = HashSet::new(); - for device_list in partition_type_map.iter() - .filter_map(|(uuid, list)| if LVM_UUIDS.contains(uuid.as_str()) { Some(list) } else { None }) - { - for device in device_list { - let meta = std::fs::metadata(device)?; - device_set.insert(meta.rdev()); + for info in lsblk_info.iter() { + if let Some(partition_type) = &info.partition_type { + if LVM_UUIDS.contains(partition_type.as_str()) { + let meta = std::fs::metadata(&info.path)?; + device_set.insert(meta.rdev()); + } } } diff --git a/src/tools/disks/zfs.rs b/src/tools/disks/zfs.rs index e0084939..55e0aa30 100644 --- a/src/tools/disks/zfs.rs +++ b/src/tools/disks/zfs.rs @@ -1,5 +1,5 @@ use std::path::PathBuf; -use std::collections::{HashMap, HashSet}; +use std::collections::HashSet; use std::os::unix::fs::MetadataExt; use anyhow::{bail, Error}; @@ -67,12 +67,11 @@ pub fn zfs_pool_stats(pool: &OsStr) -> Result, Error> { Ok(Some(stat)) } - /// Get set of devices used by zfs (or a specific zfs pool) /// /// The set is indexed by using the unix raw device number (dev_t is u64) pub fn zfs_devices( - partition_type_map: &HashMap>, + lsblk_info: &[LsblkInfo], pool: Option, ) -> Result, Error> { @@ -86,12 +85,12 @@ pub fn zfs_devices( } } - for device_list in partition_type_map.iter() - .filter_map(|(uuid, list)| if ZFS_UUIDS.contains(uuid.as_str()) { Some(list) } else { None }) - { - for device in device_list { - let meta = std::fs::metadata(device)?; - device_set.insert(meta.rdev()); + for info in lsblk_info.iter() { + if let Some(partition_type) = &info.partition_type { + if ZFS_UUIDS.contains(partition_type.as_str()) { + let meta = std::fs::metadata(&info.path)?; + device_set.insert(meta.rdev()); + } } }