Bugfix/disk info (#770)

* use df for getting disk info

* fix import

* fix type errors

* add duplicity flag for different source hosts

* fix borrow

* reorder args

* update cargo lock

* use 1byte block sizes and using floating point numbers
This commit is contained in:
Lucy C
2021-11-05 16:03:43 -06:00
committed by Aiden McClelland
parent 44324b7127
commit eac7db091f
4 changed files with 121 additions and 67 deletions

View File

@@ -40,7 +40,7 @@ pub struct DiskInfo {
pub vendor: Option<String>,
pub model: Option<String>,
pub partitions: Vec<PartitionInfo>,
pub capacity: usize,
pub capacity: u64,
pub guid: Option<String>,
}
@@ -49,8 +49,8 @@ pub struct DiskInfo {
pub struct PartitionInfo {
pub logicalname: PathBuf,
pub label: Option<String>,
pub capacity: usize,
pub used: Option<usize>,
pub capacity: u64,
pub used: Option<u64>,
pub embassy_os: Option<EmbassyOsRecoveryInfo>,
}
@@ -109,7 +109,7 @@ pub async fn get_model<P: AsRef<Path>>(path: P) -> Result<Option<String>, Error>
}
#[instrument(skip(path))]
pub async fn get_capacity<P: AsRef<Path>>(path: P) -> Result<usize, Error> {
pub async fn get_capacity<P: AsRef<Path>>(path: P) -> Result<u64, Error> {
Ok(String::from_utf8(
Command::new("blockdev")
.arg("--getsize64")
@@ -118,7 +118,7 @@ pub async fn get_capacity<P: AsRef<Path>>(path: P) -> Result<usize, Error> {
.await?,
)?
.trim()
.parse()?)
.parse::<u64>()?)
}
#[instrument(skip(path))]
@@ -137,10 +137,11 @@ pub async fn get_label<P: AsRef<Path>>(path: P) -> Result<Option<String>, Error>
}
#[instrument(skip(path))]
pub async fn get_used<P: AsRef<Path>>(path: P) -> Result<usize, Error> {
pub async fn get_used<P: AsRef<Path>>(path: P) -> Result<u64, Error> {
Ok(String::from_utf8(
Command::new("df")
.arg("--output=used")
.arg("--block-size=1")
.arg(path.as_ref())
.invoke(crate::ErrorKind::Filesystem)
.await?,
@@ -150,7 +151,44 @@ pub async fn get_used<P: AsRef<Path>>(path: P) -> Result<usize, Error> {
.next()
.unwrap_or_default()
.trim()
.parse()?)
.parse::<u64>()?)
}
#[instrument(skip(path))]
pub async fn get_available<P: AsRef<Path>>(path: P) -> Result<u64, Error> {
Ok(String::from_utf8(
Command::new("df")
.arg("--output=avail")
.arg("--block-size=1")
.arg(path.as_ref())
.invoke(crate::ErrorKind::Filesystem)
.await?,
)?
.lines()
.skip(1)
.next()
.unwrap_or_default()
.trim()
.parse::<u64>()?)
}
#[instrument(skip(path))]
pub async fn get_percentage<P: AsRef<Path>>(path: P) -> Result<u64, Error> {
Ok(String::from_utf8(
Command::new("df")
.arg("--output=pcent")
.arg(path.as_ref())
.invoke(crate::ErrorKind::Filesystem)
.await?,
)?
.lines()
.skip(1)
.next()
.unwrap_or_default()
.trim()
.strip_suffix("%")
.unwrap()
.parse::<u64>()?)
}
pub async fn pvscan() -> Result<BTreeMap<PathBuf, Option<String>>, Error> {

View File

@@ -9,6 +9,7 @@ use tracing::instrument;
use crate::context::RpcContext;
use crate::db::util::WithRevision;
use crate::disk::util::{get_available, get_percentage, get_used};
use crate::logs::{display_logs, fetch_logs, LogResponse, LogSource};
use crate::shutdown::Shutdown;
use crate::util::{display_none, display_serializable, IoFormat};
@@ -601,65 +602,33 @@ async fn get_mem_info() -> Result<MetricsMemory, Error> {
#[instrument]
async fn get_disk_info() -> Result<MetricsDisk, Error> {
use crate::util::Invoke;
let mut size_cmd = tokio::process::Command::new("zpool");
let size_task = size_cmd
.arg("list")
.arg("-Hp")
.arg("-o")
.arg("size")
.arg("embassy-data")
.invoke(ErrorKind::ParseSysInfo);
let mut alloc_cmd = tokio::process::Command::new("zpool");
let alloc_task = alloc_cmd
.arg("list")
.arg("-Hp")
.arg("-o")
.arg("allocated")
.arg("embassy-data")
.invoke(ErrorKind::ParseSysInfo);
let mut free_cmd = tokio::process::Command::new("zpool");
let free_task = free_cmd
.arg("list")
.arg("-Hp")
.arg("-o")
.arg("free")
.arg("embassy-data")
.invoke(ErrorKind::ParseSysInfo);
let (size_bytes, alloc_bytes, free_bytes) =
futures::try_join!(size_task, alloc_task, free_task)?;
let size = String::from_utf8(size_bytes)?
.trim()
.parse::<f64>()
.map_err(|e| {
Error::new(
color_eyre::eyre::eyre!("Could not parse disk size: {}", e),
ErrorKind::ParseSysInfo,
)
})?;
let alloc = String::from_utf8(alloc_bytes)?
.trim()
.parse::<f64>()
.map_err(|e| {
Error::new(
color_eyre::eyre::eyre!("Could not parse disk alloc: {}", e),
ErrorKind::ParseSysInfo,
)
})?;
let free = String::from_utf8(free_bytes)?
.trim()
.parse::<f64>()
.map_err(|e| {
Error::new(
color_eyre::eyre::eyre!("Could not parse disk alloc: {}", e),
ErrorKind::ParseSysInfo,
)
})?;
let package_used_task = get_used("/embassy-data/package-data");
let package_available_task = get_available("/embassy-data/package-data");
let package_percentage_task = get_percentage("/embassy-data/package-data");
let os_used_task = get_used("/embassy-data/main");
let os_available_task = get_available("/embassy-data/main");
let os_percentage_task = get_percentage("/embassy-data/main");
let (package_used, package_available, package_percentage, os_used, os_available, os_percentage) =
futures::try_join!(
package_used_task,
package_available_task,
package_percentage_task,
os_used_task,
os_available_task,
os_percentage_task,
)?;
let total_used = package_used + os_used;
let total_available = package_available + os_available;
let total_percentage = package_percentage + os_percentage;
let total_size = total_used + total_available;
Ok(MetricsDisk {
size: GigaBytes(size / 1_000_000_000.0),
used: GigaBytes(alloc / 1_000_000_000.0),
available: GigaBytes(free / 1_000_000_000.0),
used_percentage: Percentage(alloc / size * 100.0),
size: GigaBytes(total_size as f64 / 1_000_000_000.0),
used: GigaBytes(total_used as f64 / 1_000_000_000.0),
available: GigaBytes(total_available as f64 / 1_000_000_000.0),
used_percentage: Percentage(total_percentage as f64),
})
}