src/tools/disks.rs: add/use get_partition_type_info

This commit is contained in:
Dietmar Maurer 2020-06-04 07:48:22 +02:00
parent 8d78589969
commit 5c264c8d80
3 changed files with 70 additions and 12 deletions

View File

@ -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()) {

View File

@ -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<HashMap<String, Vec<String>>, 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<String, Vec<String>> = 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)
}

View File

@ -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<I, O, E = VerboseError<I>> = Result<(I, O), nom::Err<E>>;
#[derive(Debug)]
@ -154,7 +166,10 @@ pub fn parse_zfs_list(i: &str) -> Result<Vec<ZFSPoolStatus>, Error> {
}
/// List devices used by zfs (or a specific zfs pool)
pub fn zfs_devices(pool: Option<&OsStr>) -> Result<Vec<String>, Error> {
pub fn zfs_devices(
partition_type_map: &HashMap<String, Vec<String>>,
pool: Option<&OsStr>,
) -> Result<HashSet<String>, 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<Vec<String>, 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)
}