From: Hannes Laimer <h.laimer@proxmox.com>
To: pbs-devel@lists.proxmox.com
Subject: [pbs-devel] [PATCH proxmox-backup v2 1/3] api2: disks endpoint return partitions
Date: Wed, 8 Jun 2022 08:51:51 +0000 [thread overview]
Message-ID: <20220608085154.11271-2-h.laimer@proxmox.com> (raw)
In-Reply-To: <20220608085154.11271-1-h.laimer@proxmox.com>
Signed-off-by: Hannes Laimer <h.laimer@proxmox.com>
---
src/api2/node/disks/directory.rs | 2 +-
src/api2/node/disks/mod.rs | 11 ++-
src/api2/node/disks/zfs.rs | 2 +-
src/tools/disks/mod.rs | 132 ++++++++++++++++++++++++++++++-
4 files changed, 140 insertions(+), 7 deletions(-)
diff --git a/src/api2/node/disks/directory.rs b/src/api2/node/disks/directory.rs
index f4d85d0a..123a8d7b 100644
--- a/src/api2/node/disks/directory.rs
+++ b/src/api2/node/disks/directory.rs
@@ -147,7 +147,7 @@ pub fn create_datastore_disk(
let auth_id = rpcenv.get_auth_id().unwrap();
- let info = get_disk_usage_info(&disk, true)?;
+ let info = get_disk_usage_info(&disk, true, false)?;
if info.used != DiskUsageType::Unused {
bail!("disk '{}' is already in use.", disk);
diff --git a/src/api2/node/disks/mod.rs b/src/api2/node/disks/mod.rs
index c44ccfee..478829fb 100644
--- a/src/api2/node/disks/mod.rs
+++ b/src/api2/node/disks/mod.rs
@@ -33,6 +33,12 @@ pub mod zfs;
optional: true,
default: false,
},
+ "include-partitions": {
+ description: "Include partitions.",
+ type: bool,
+ optional: true,
+ default: false,
+ },
"usage-type": {
type: DiskUsageType,
optional: true,
@@ -53,11 +59,12 @@ pub mod zfs;
/// List local disks
pub fn list_disks(
skipsmart: bool,
+ include_partitions: bool,
usage_type: Option<DiskUsageType>,
) -> Result<Vec<DiskUsageInfo>, Error> {
let mut list = Vec::new();
- for (_, info) in get_disks(None, skipsmart)? {
+ for (_, info) in get_disks(None, skipsmart, include_partitions)? {
if let Some(ref usage_type) = usage_type {
if info.used == *usage_type {
list.push(info);
@@ -140,7 +147,7 @@ pub fn initialize_disk(
let auth_id = rpcenv.get_auth_id().unwrap();
- let info = get_disk_usage_info(&disk, true)?;
+ let info = get_disk_usage_info(&disk, true, false)?;
if info.used != DiskUsageType::Unused {
bail!("disk '{}' is already in use.", disk);
diff --git a/src/api2/node/disks/zfs.rs b/src/api2/node/disks/zfs.rs
index dac6f535..5cb23e70 100644
--- a/src/api2/node/disks/zfs.rs
+++ b/src/api2/node/disks/zfs.rs
@@ -174,7 +174,7 @@ pub fn create_zpool(
.map(|v| v.as_str().unwrap().to_string())
.collect();
- let disk_map = crate::tools::disks::get_disks(None, true)?;
+ let disk_map = crate::tools::disks::get_disks(None, true, false)?;
for disk in devices.iter() {
match disk_map.get(disk) {
Some(info) => {
diff --git a/src/tools/disks/mod.rs b/src/tools/disks/mod.rs
index 568dccbf..ea4c687a 100644
--- a/src/tools/disks/mod.rs
+++ b/src/tools/disks/mod.rs
@@ -602,6 +602,26 @@ fn get_file_system_devices(lsblk_info: &[LsblkInfo]) -> Result<HashSet<u64>, Err
Ok(device_set)
}
+#[api()]
+#[derive(Debug, Serialize, Deserialize, PartialEq)]
+#[serde(rename_all = "lowercase")]
+pub enum PartitionUsageType {
+ /// Partition is not used (as far we can tell)
+ Unused,
+ /// Partition is used by LVM
+ LVM,
+ /// Partition is used by ZFS
+ ZFS,
+ /// Partition is ZFS reserved
+ ZfsReserved,
+ /// Partition is an EFI partition
+ EFI,
+ /// Partition is a BIOS partition
+ BIOS,
+ /// Partition contains a file system label
+ FileSystem,
+}
+
#[api()]
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "lowercase")]
@@ -622,6 +642,27 @@ pub enum DiskUsageType {
FileSystem,
}
+#[api()]
+#[derive(Debug, Serialize, Deserialize)]
+#[serde(rename_all = "kebab-case")]
+/// Baisc information about a partition
+pub struct PartitionInfo {
+ /// The partition name
+ pub name: String,
+ /// What the partition is used for
+ pub used: PartitionUsageType,
+ /// Is the partition mounted
+ pub mounted: bool,
+ /// The filesystem of the partition
+ pub filesystem: Option<String>,
+ /// The partition devpath
+ pub devpath: Option<String>,
+ /// Size in bytes
+ pub size: Option<u64>,
+ /// GPT partition
+ pub gpt: bool,
+}
+
#[api(
properties: {
used: {
@@ -632,6 +673,12 @@ pub enum DiskUsageType {
},
status: {
type: SmartStatus,
+ },
+ partitions: {
+ optional: true,
+ items: {
+ type: PartitionInfo
+ }
}
}
)]
@@ -656,6 +703,8 @@ pub struct DiskUsageInfo {
pub size: u64,
/// Serisal number
pub serial: Option<String>,
+ /// Partitions on the device
+ pub partitions: Option<Vec<PartitionInfo>>,
/// Linux device path (/dev/xxx)
pub devpath: Option<String>,
/// Set if disk contains a GPT partition table
@@ -733,10 +782,14 @@ fn scan_partitions(
}
/// Get disk usage information for a single disk
-pub fn get_disk_usage_info(disk: &str, no_smart: bool) -> Result<DiskUsageInfo, Error> {
+pub fn get_disk_usage_info(
+ disk: &str,
+ no_smart: bool,
+ include_partitions: bool,
+) -> Result<DiskUsageInfo, Error> {
let mut filter = Vec::new();
filter.push(disk.to_string());
- let mut map = get_disks(Some(filter), no_smart)?;
+ let mut map = get_disks(Some(filter), no_smart, include_partitions)?;
if let Some(info) = map.remove(disk) {
Ok(info)
} else {
@@ -744,12 +797,72 @@ pub fn get_disk_usage_info(disk: &str, no_smart: bool) -> Result<DiskUsageInfo,
}
}
+fn get_partitions_info(
+ partitions: HashMap<u64, Disk>,
+ lvm_devices: &HashSet<u64>,
+ zfs_devices: &HashSet<u64>,
+ file_system_devices: &HashSet<u64>,
+) -> Vec<PartitionInfo> {
+ let lsblk_infos = get_lsblk_info().ok();
+ partitions
+ .iter()
+ .map(|(_nr, disk)| {
+ let devpath = disk
+ .device_path()
+ .map(|p| p.to_owned())
+ .map(|p| p.to_string_lossy().to_string());
+
+ let mut used = PartitionUsageType::Unused;
+
+ if let Some(devnum) = disk.devnum().ok() {
+ if lvm_devices.contains(&devnum) {
+ used = PartitionUsageType::LVM;
+ } else if zfs_devices.contains(&devnum) {
+ used = PartitionUsageType::ZFS;
+ } else if file_system_devices.contains(&devnum) {
+ used = PartitionUsageType::FileSystem;
+ }
+ }
+
+ let mounted = disk.is_mounted().unwrap_or(false);
+ let mut filesystem = None;
+ if let (Some(devpath), Some(infos)) = (devpath.as_ref(), lsblk_infos.as_ref()) {
+ for info in infos.iter().filter(|i| i.path.eq(devpath)) {
+ used = match info.partition_type.as_deref() {
+ Some("21686148-6449-6e6f-744e-656564454649") => PartitionUsageType::BIOS,
+ Some("c12a7328-f81f-11d2-ba4b-00a0c93ec93b") => PartitionUsageType::EFI,
+ Some("6a945a3b-1dd2-11b2-99a6-080020736631") => {
+ PartitionUsageType::ZfsReserved
+ }
+ _ => used,
+ };
+ if used == PartitionUsageType::FileSystem {
+ filesystem = info.file_system_type.clone();
+ }
+ }
+ }
+
+ PartitionInfo {
+ name: disk.sysname().to_str().unwrap_or("?").to_string(),
+ devpath,
+ used,
+ mounted,
+ filesystem,
+ size: disk.size().ok(),
+ gpt: disk.has_gpt(),
+ }
+ })
+ .collect()
+}
+
/// Get disk usage information for multiple disks
pub fn get_disks(
// filter - list of device names (without leading /dev)
disks: Option<Vec<String>>,
// do no include data from smartctl
no_smart: bool,
+ // include partitions
+ include_partitions: bool,
) -> Result<HashMap<String, DiskUsageInfo>, Error> {
let disk_manager = DiskManage::new();
@@ -837,6 +950,19 @@ pub fn get_disks(
let wwn = disk.wwn().map(|s| s.to_string_lossy().into_owned());
+ let partitions: Option<Vec<PartitionInfo>> = if include_partitions {
+ disk.partitions().map_or(None, |parts| {
+ Some(get_partitions_info(
+ parts,
+ &lvm_devices,
+ &zfs_devices,
+ &file_system_devices,
+ ))
+ })
+ } else {
+ None
+ };
+
if usage != DiskUsageType::Mounted {
match scan_partitions(disk_manager.clone(), &lvm_devices, &zfs_devices, &name) {
Ok(part_usage) => {
@@ -870,6 +996,7 @@ pub fn get_disks(
name: name.clone(),
vendor,
model,
+ partitions,
serial,
devpath,
size,
@@ -989,7 +1116,6 @@ pub fn create_file_system(disk: &Disk, fs_type: FileSystemType) -> Result<(), Er
Ok(())
}
-
/// Block device name completion helper
pub fn complete_disk_name(_arg: &str, _param: &HashMap<String, String>) -> Vec<String> {
let dir =
--
2.30.2
next prev parent reply other threads:[~2022-06-08 8:53 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-06-08 8:51 [pbs-devel] [PATCH proxmox-backup/proxmox-widget-toolkit v2 0/4] add partitions to disks/list endpoint Hannes Laimer
2022-06-08 8:51 ` Hannes Laimer [this message]
2022-06-08 8:51 ` [pbs-devel] [PATCH proxmox-backup v2 2/3] disks: use builder pattern for querying disk usage Hannes Laimer
2022-06-09 10:38 ` Wolfgang Bumiller
2022-06-15 6:07 ` [pbs-devel] [PATCH proxmox-backup v3 " Hannes Laimer
2022-06-15 6:17 ` Hannes Laimer
2022-06-08 8:51 ` [pbs-devel] [PATCH proxmox-backup v2 3/3] ui: disks: show partitions by default Hannes Laimer
2022-06-08 8:51 ` [pbs-devel] [PATCH proxmox-widget-toolkit v2 1/1] ui: DiskLisk: handle partition data from PBS backend Hannes Laimer
2022-06-15 8:58 ` [pbs-devel] applied: " Wolfgang Bumiller
2022-06-15 7:58 ` [pbs-devel] [PATCH proxmox-backup/proxmox-widget-toolkit v2 0/4] add partitions to disks/list endpoint Wolfgang Bumiller
2022-06-15 8:08 ` Dominik Csapak
2022-06-15 8:10 ` Hannes Laimer
2022-06-15 8:17 ` Wolfgang Bumiller
2022-06-15 9:09 ` [pbs-devel] applied-series: [PATCH proxmox-backup/proxmox-widget-toolkit v2 0/4] add partitions to disks/list endpointg Wolfgang Bumiller
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220608085154.11271-2-h.laimer@proxmox.com \
--to=h.laimer@proxmox.com \
--cc=pbs-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.