disks: refactor partition type handling
in preparation to also get the file system type from lsblk. Co-developed-by: Wolfgang Bumiller <w.bumiller@proxmox.com> Signed-off-by: Fabian Ebner <f.ebner@proxmox.com>
This commit is contained in:
		
				
					committed by
					
						 Thomas Lamprecht
						Thomas Lamprecht
					
				
			
			
				
	
			
			
			
						parent
						
							b81818b6ad
						
					
				
				
					commit
					364299740f
				
			| @ -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<String, Vec<String>>, | ||||
|     lsblk_info: &[LsblkInfo], | ||||
| ) -> Result<HashSet<u64>, Error> { | ||||
|  | ||||
|     const PVS_BIN_PATH: &str = "pvs"; | ||||
| @ -29,12 +31,12 @@ pub fn get_lvm_devices( | ||||
|  | ||||
|     let mut device_set: HashSet<u64> = 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()); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
| @ -46,6 +46,16 @@ pub struct DiskManage { | ||||
|     mounted_devices: OnceCell<HashSet<dev_t>>, | ||||
| } | ||||
|  | ||||
| /// 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<String>, | ||||
| } | ||||
|  | ||||
| impl DiskManage { | ||||
|     /// Create a new disk management context. | ||||
|     pub fn new() -> Arc<Self> { | ||||
| @ -556,31 +566,16 @@ pub struct BlockDevStat { | ||||
| } | ||||
|  | ||||
| /// Use lsblk to read partition type uuids. | ||||
| pub fn get_partition_type_info() -> Result<HashMap<String, Vec<String>>, Error> { | ||||
| pub fn get_lsblk_info() -> Result<Vec<LsblkInfo>, 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<String, Vec<String>> = 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<HashSet<u64>, Error> { | ||||
|     let zfs_devices = zfs_devices(&lsblk_info, None).or_else(|err| -> Result<HashSet<u64>, 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 | ||||
|  | ||||
|  | ||||
| @ -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<Option<BlockDevStat>, 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<String, Vec<String>>, | ||||
|     lsblk_info: &[LsblkInfo], | ||||
|     pool: Option<String>, | ||||
| ) -> Result<HashSet<u64>, 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()); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
		Reference in New Issue
	
	Block a user