]> git.proxmox.com Git - proxmox-backup.git/blobdiff - src/tools/disks/mod.rs
update to first proxmox crate split
[proxmox-backup.git] / src / tools / disks / mod.rs
index 1a72a6c84b69915c42f7dcdecfd177e429d32240..d3e69c6d1bf28fdc7f2859efa801881cf99b10ab 100644 (file)
@@ -17,9 +17,9 @@ use ::serde::{Deserialize, Serialize};
 use proxmox::sys::error::io_err_other;
 use proxmox::sys::linux::procfs::{MountInfo, mountinfo::Device};
 use proxmox::{io_bail, io_format_err};
-use proxmox::api::api;
+use proxmox_schema::api;
 
-use crate::api2::types::{BLOCKDEVICE_NAME_REGEX, StorageStatus};
+use pbs_api_types::{BLOCKDEVICE_NAME_REGEX, StorageStatus};
 
 mod zfs;
 pub use zfs::*;
@@ -46,6 +46,19 @@ 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>,
+    /// File system label.
+    #[serde(rename = "fstype")]
+    file_system_type: Option<String>,
+}
+
 impl DiskManage {
     /// Create a new disk management context.
     pub fn new() -> Arc<Self> {
@@ -555,32 +568,36 @@ pub struct BlockDevStat {
     pub io_ticks: u64, // milliseconds
 }
 
-/// Use lsblk to read partition type uuids.
-pub fn get_partition_type_info() -> Result<HashMap<String, Vec<String>>, Error> {
+/// Use lsblk to read partition type uuids and file system types.
+pub fn get_lsblk_info() -> Result<Vec<LsblkInfo>, Error> {
 
     let mut command = std::process::Command::new("lsblk");
-    command.args(&["--json", "-o", "path,parttype"]);
+    command.args(&["--json", "-o", "path,parttype,fstype"]);
 
-    let output = crate::tools::run_command(command, None)?;
+    let output = pbs_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(serde_json::from_value(output["blockdevices"].take())?)
+}
+
+/// Get set of devices with a file system label.
+///
+/// The set is indexed by using the unix raw device number (dev_t is u64)
+fn get_file_system_devices(
+    lsblk_info: &[LsblkInfo],
+) -> Result<HashSet<u64>, Error> {
+
+    let mut device_set: HashSet<u64> = HashSet::new();
+
+    for info in lsblk_info.iter() {
+        if info.file_system_type.is_some() {
+            let meta = std::fs::metadata(&info.path)?;
+            device_set.insert(meta.rdev());
         }
     }
-    Ok(res)
+
+    Ok(device_set)
 }
 
 #[api()]
@@ -599,6 +616,8 @@ pub enum DiskUsageType {
     DeviceMapper,
     /// Disk has partitions
     Partitions,
+    /// Disk contains a file system label
+    FileSystem,
 }
 
 #[api(
@@ -736,14 +755,16 @@ 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)?;
+
+    let file_system_devices = get_file_system_devices(&lsblk_info)?;
 
     // fixme: ceph journals/volumes
 
@@ -820,6 +841,10 @@ pub fn get_disks(
             };
         }
 
+        if usage == DiskUsageType::Unused && file_system_devices.contains(&devnum) {
+            usage = DiskUsageType::FileSystem;
+        }
+
         if usage == DiskUsageType::Unused && disk.has_holders()? {
             usage = DiskUsageType::DeviceMapper;
         }
@@ -861,7 +886,7 @@ pub fn reread_partition_table(disk: &Disk) -> Result<(), Error> {
     command.arg("--rereadpt");
     command.arg(disk_path);
 
-    crate::tools::run_command(command, None)?;
+    pbs_tools::run_command(command, None)?;
 
     Ok(())
 }
@@ -880,7 +905,7 @@ pub fn inititialize_gpt_disk(disk: &Disk, uuid: Option<&str>) -> Result<(), Erro
     command.arg(disk_path);
     command.args(&["-U", uuid]);
 
-    crate::tools::run_command(command, None)?;
+    pbs_tools::run_command(command, None)?;
 
     Ok(())
 }
@@ -897,7 +922,7 @@ pub fn create_single_linux_partition(disk: &Disk) -> Result<Disk, Error> {
     command.args(&["-n1", "-t1:8300"]);
     command.arg(disk_path);
 
-    crate::tools::run_command(command, None)?;
+    pbs_tools::run_command(command, None)?;
 
     let mut partitions = disk.partitions()?;
 
@@ -950,7 +975,7 @@ pub fn create_file_system(disk: &Disk, fs_type: FileSystemType) -> Result<(), Er
     command.args(&["-t", &fs_type]);
     command.arg(disk_path);
 
-    crate::tools::run_command(command, None)?;
+    pbs_tools::run_command(command, None)?;
 
     Ok(())
 }
@@ -988,7 +1013,7 @@ pub fn get_fs_uuid(disk: &Disk) -> Result<String, Error> {
     command.args(&["-o", "export"]);
     command.arg(disk_path);
 
-    let output = crate::tools::run_command(command, None)?;
+    let output = pbs_tools::run_command(command, None)?;
 
     for line in output.lines() {
         if let Some(uuid) = line.strip_prefix("UUID=") {