Files
initrd/src/lvm.rs
2025-07-17 16:48:38 +02:00

103 lines
2.4 KiB
Rust

use eyre::{Result, format_err};
use tokio::process::Command;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
struct Report {
report: Vec<ReportObj>,
}
#[derive(Debug, serde::Deserialize, serde::Serialize)]
enum ReportObj {
#[serde(rename = "pv")]
PV(Vec<PV>),
#[serde(rename = "vg")]
VG(Vec<VG>),
#[serde(rename = "lv")]
LV(Vec<LV>),
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
pub struct PV {
pub pv_name: String,
pub vg_name: String,
pub pv_fmt: String,
pub pv_attr: String,
pub pv_size: String,
pub pv_free: String,
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
pub struct VG {
pub vg_name: String,
pub pv_count: String,
pub lv_count: String,
pub snap_count: String,
pub vg_attr: String,
pub vg_size: String,
pub vg_free: String,
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
pub struct LV {
pub lv_name: String,
pub vg_name: String,
pub lv_attr: String,
pub lv_size: String,
pub pool_lv: String,
pub origin: String,
pub data_percent: String,
pub metadata_percent: String,
pub move_pv: String,
pub mirror_log: String,
pub copy_percent: String,
pub convert_lv: String,
}
impl LV {
pub fn equal_name(&self, vg_name: &str, lv_name: &str) -> bool {
vg_name == &self.vg_name && lv_name == &self.lv_name
}
}
pub async fn pvs() -> Result<Vec<PV>> {
report_cmd("pvs", |o| match o {
ReportObj::PV(pv) => Some(pv),
_ => None,
})
.await
}
pub async fn vgs() -> Result<Vec<VG>> {
report_cmd("vgs", |o| match o {
ReportObj::VG(vg) => Some(vg),
_ => None,
})
.await
}
pub async fn lvs() -> Result<Vec<LV>> {
report_cmd("lvs", |o| match o {
ReportObj::LV(lv) => Some(lv),
_ => None,
})
.await
}
async fn report_cmd<T>(cmd: &str, find: fn(ReportObj) -> Option<Vec<T>>) -> Result<Vec<T>> {
let output = Command::new(cmd)
.arg("--reportformat=json")
.output()
.await?;
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr.trim_ascii());
return Err(format_err!("{cmd} failed: {}", stderr));
}
let report: Report = serde_json::from_slice(&output.stdout).unwrap();
Ok((report.report.into_iter())
.filter_map(find)
.flatten()
.collect())
}