From: Hannes Laimer <h.laimer@proxmox.com>
To: pbs-devel@lists.proxmox.com
Subject: [pbs-devel] [PATCH proxmox-backup 1/3] api2: disks endpoint return partitions
Date: Mon, 4 Apr 2022 09:50:46 +0000 [thread overview]
Message-ID: <20220404095048.25443-2-h.laimer@proxmox.com> (raw)
In-Reply-To: <20220404095048.25443-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 | 121 ++++++++++++++++++++++++++++++-
4 files changed, 130 insertions(+), 6 deletions(-)
diff --git a/src/api2/node/disks/directory.rs b/src/api2/node/disks/directory.rs
index bf1a1be6..79fe2624 100644
--- a/src/api2/node/disks/directory.rs
+++ b/src/api2/node/disks/directory.rs
@@ -149,7 +149,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 a542f9e0..5329f44f 100644
--- a/src/api2/node/disks/zfs.rs
+++ b/src/api2/node/disks/zfs.rs
@@ -177,7 +177,7 @@ pub fn create_zpool(
let devices: Vec<String> = devices.as_array().unwrap().iter()
.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 94da7b3a..fb9c78a9 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 mounted
+ Mounted,
+ /// Partition is used by LVM
+ LVM,
+ /// Partition is used by ZFS
+ ZFS,
+ /// 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,23 @@ pub enum DiskUsageType {
FileSystem,
}
+#[api()]
+#[derive(Debug, Serialize, Deserialize)]
+#[serde(rename_all = "kebab-case")]
+/// Baic information about a partition
+pub struct PartitionInfo {
+ /// The partition name
+ pub name: String,
+ /// What the partition is used for
+ pub used: PartitionUsageType,
+ /// The partition devpath
+ pub devpath: Option<String>,
+ /// Size in bytes
+ pub size: Option<u64>,
+ /// Size in bytes
+ pub gpt: bool,
+}
+
#[api(
properties: {
used: {
@@ -632,6 +669,12 @@ pub enum DiskUsageType {
},
status: {
type: SmartStatus,
+ },
+ partitions: {
+ optional: true,
+ items: {
+ type: PartitionInfo
+ }
}
}
)]
@@ -656,6 +699,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 +778,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 {
@@ -750,6 +799,8 @@ pub fn get_disks(
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 +888,71 @@ pub fn get_disks(
let wwn = disk.wwn().map(|s| s.to_string_lossy().into_owned());
+ let partitions: Option<Vec<PartitionInfo>> = if include_partitions {
+ let lsblk_infos = get_lsblk_info();
+ disk.partitions().map_or(None, |parts| {
+ Some(
+ parts
+ .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;
+ }
+ if zfs_devices.contains(&devnum) {
+ used = PartitionUsageType::ZFS;
+ }
+ }
+ match disk.is_mounted() {
+ Ok(true) => used = PartitionUsageType::Mounted,
+ Ok(false) => {}
+ Err(_) => {} // skip devices with undetectable mount status
+ }
+
+ if let Some(devpath) = devpath.as_ref() {
+ if let Ok(infos) = 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
+ }
+ _ => used,
+ }
+ }
+ }
+ }
+
+ if used == PartitionUsageType::Unused
+ && file_system_devices.contains(&devnum)
+ {
+ used = PartitionUsageType::FileSystem;
+ }
+
+ PartitionInfo {
+ name: format!("{}{}", name, nr),
+ devpath,
+ used,
+ size: disk.size().ok(),
+ gpt: disk.has_gpt(),
+ }
+ })
+ .collect(),
+ )
+ })
+ } else {
+ None
+ };
+
if usage != DiskUsageType::Mounted {
match scan_partitions(disk_manager.clone(), &lvm_devices, &zfs_devices, &name) {
Ok(part_usage) => {
@@ -870,6 +986,7 @@ pub fn get_disks(
name: name.clone(),
vendor,
model,
+ partitions,
serial,
devpath,
size,
--
2.30.2
next prev parent reply other threads:[~2022-04-04 9:51 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-04-04 9:50 [pbs-devel] [SERIES proxmox-backup proxmox-widget-toolkit 0/3] add partitions to disks/list endpoint Hannes Laimer
2022-04-04 9:50 ` Hannes Laimer [this message]
2022-04-06 9:12 ` [pbs-devel] [PATCH proxmox-backup 1/3] api2: disks endpoint return partitions Wolfgang Bumiller
2022-04-04 9:50 ` [pbs-devel] [PATCH proxmox-widget-toolkit 2/2] DiskList: handle partition data from PBS backend Hannes Laimer
2022-04-07 8:37 ` Dominik Csapak
2022-04-04 9:50 ` [pbs-devel] [PATCH proxmox-backup 3/3] ui: disks: show partitions by default Hannes Laimer
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=20220404095048.25443-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.