diff --git a/src/bin/proxmox-backup-proxy.rs b/src/bin/proxmox-backup-proxy.rs index 3471ddbc..167dff5e 100644 --- a/src/bin/proxmox-backup-proxy.rs +++ b/src/bin/proxmox-backup-proxy.rs @@ -15,7 +15,7 @@ use proxmox_backup::server; use proxmox_backup::tools::daemon; use proxmox_backup::server::{ApiConfig, rest::*}; use proxmox_backup::auth_helpers::*; -use proxmox_backup::tools::disks::{ DiskManage, zfs::zfs_pool_stats }; +use proxmox_backup::tools::disks::{ DiskManage, zfs_pool_stats }; fn main() { if let Err(err) = proxmox_backup::tools::runtime::main(run()) { diff --git a/src/tools/disks.rs b/src/tools/disks.rs index c8f7cbbf..edf32272 100644 --- a/src/tools/disks.rs +++ b/src/tools/disks.rs @@ -1,6 +1,6 @@ //! Disk query/management utilities for. -use std::collections::HashSet; +use std::collections::{HashMap, HashSet}; use std::ffi::{OsStr, OsString}; use std::io; use std::os::unix::ffi::{OsStrExt, OsStringExt}; @@ -16,7 +16,8 @@ use proxmox::sys::error::io_err_other; use proxmox::sys::linux::procfs::{MountInfo, mountinfo::Device}; use proxmox::{io_bail, io_format_err}; -pub mod zfs; +mod zfs; +pub use zfs::*; bitflags! { /// Ways a device is being used. @@ -511,3 +512,42 @@ pub struct BlockDevStat { pub write_sectors: u64, pub io_ticks: u64, // milliseconds } + +/// Use lsblk to read partition type uuids. +pub fn get_partition_type_info() -> Result>, Error> { + + const LSBLK_BIN_PATH: &str = "/usr/bin/lsblk"; + + let mut command = std::process::Command::new(LSBLK_BIN_PATH); + command.args(&["--json", "-o", "path,parttype"]); + + let output = command.output() + .map_err(|err| format_err!("failed to execute '{}' - {}", LSBLK_BIN_PATH, err))?; + + let output = crate::tools::command_output(output, None) + .map_err(|err| format_err!("lsblk command failed: {}", err))?; + + let mut res: HashMap> = HashMap::new(); + + let output: serde_json::Value = output.parse()?; + match output["blockdevices"].as_array() { + Some(list) => { + 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()); + } + } + None => { + + } + } + Ok(res) +} diff --git a/src/tools/disks/zfs.rs b/src/tools/disks/zfs.rs index cc46d5a1..fd23ba19 100644 --- a/src/tools/disks/zfs.rs +++ b/src/tools/disks/zfs.rs @@ -1,6 +1,9 @@ use std::path::PathBuf; +use std::collections::{HashMap, HashSet}; use anyhow::{bail, Error}; +use lazy_static::lazy_static; + use nom::{ error::VerboseError, bytes::complete::{take_while, take_while1, take_till, take_till1}, @@ -12,6 +15,15 @@ use nom::{ use super::*; +lazy_static!{ + static ref ZFS_UUIDS: HashSet<&'static str> = { + let mut set = HashSet::new(); + set.insert("6a898cc3-1dd2-11b2-99a6-080020736631"); // apple + set.insert("516e7cba-6ecf-11d6-8ff8-00022d09712b"); // bsd + set + }; +} + type IResult> = Result<(I, O), nom::Err>; #[derive(Debug)] @@ -154,7 +166,10 @@ pub fn parse_zfs_list(i: &str) -> Result, Error> { } /// List devices used by zfs (or a specific zfs pool) -pub fn zfs_devices(pool: Option<&OsStr>) -> Result, Error> { +pub fn zfs_devices( + partition_type_map: &HashMap>, + pool: Option<&OsStr>, +) -> Result, Error> { // Note: zpools list output can include entries for 'special', 'cache' and 'logs' // and maybe other things. @@ -172,17 +187,20 @@ pub fn zfs_devices(pool: Option<&OsStr>) -> Result, Error> { let list = parse_zfs_list(&output)?; - let mut done = std::collections::HashSet::new(); - - let mut device_list = Vec::new(); + let mut device_set = HashSet::new(); for entry in list { for device in entry.devices { - if !done.contains(&device) { - device_list.push(device.clone()); - done.insert(device); - } + device_set.insert(device.clone()); } } - Ok(device_list) + 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 { + device_set.insert(device.clone()); + } + } + + Ok(device_set) }