src/tools/disks/zpool_status.rs: improve parser

This commit is contained in:
Dietmar Maurer 2020-06-18 14:55:22 +02:00
parent 547f0c97e4
commit 9438aca6c9

View File

@ -19,10 +19,14 @@ use nom::{
pub struct ZFSPoolVDevState { pub struct ZFSPoolVDevState {
pub name: String, pub name: String,
pub lvl: u64, pub lvl: u64,
pub state: String, #[serde(skip_serializing_if="Option::is_none")]
pub read: u64, pub state: Option<String>,
pub write: u64, #[serde(skip_serializing_if="Option::is_none")]
pub cksum: u64, pub read: Option<u64>,
#[serde(skip_serializing_if="Option::is_none")]
pub write: Option<u64>,
#[serde(skip_serializing_if="Option::is_none")]
pub cksum: Option<u64>,
#[serde(skip_serializing_if="Option::is_none")] #[serde(skip_serializing_if="Option::is_none")]
pub msg: Option<String>, pub msg: Option<String>,
} }
@ -36,6 +40,20 @@ fn parse_zpool_status_vdev(i: &str) -> IResult<&str, ZFSPoolVDevState> {
let i = n; let i = n;
let (i, vdev_name) = notspace1(i)?; let (i, vdev_name) = notspace1(i)?;
if let Ok((n, _)) = preceded(multispace0, line_ending)(i) { // sepecial device
let vdev = ZFSPoolVDevState {
name: vdev_name.to_string(),
lvl: (indent.len() as u64)/2,
state: None,
read: None,
write: None,
cksum: None,
msg: None,
};
return Ok((n, vdev));
}
let (i, state) = preceded(multispace1, notspace1)(i)?; let (i, state) = preceded(multispace1, notspace1)(i)?;
let (i, read) = preceded(multispace1, parse_u64)(i)?; let (i, read) = preceded(multispace1, parse_u64)(i)?;
let (i, write) = preceded(multispace1, parse_u64)(i)?; let (i, write) = preceded(multispace1, parse_u64)(i)?;
@ -46,8 +64,10 @@ fn parse_zpool_status_vdev(i: &str) -> IResult<&str, ZFSPoolVDevState> {
let vdev = ZFSPoolVDevState { let vdev = ZFSPoolVDevState {
name: vdev_name.to_string(), name: vdev_name.to_string(),
lvl: (indent.len() as u64)/2, lvl: (indent.len() as u64)/2,
state: state.to_string(), state: Some(state.to_string()),
read, write, cksum, read: Some(read),
write: Some(write),
cksum: Some(cksum),
msg: msg.map(String::from), msg: msg.map(String::from),
}; };
@ -118,8 +138,9 @@ pub fn parse_zpool_status_config_tree(i: &str) -> Result<Vec<ZFSPoolVDevState>,
parse_complete("zfs status config tree", i, parse_zpool_status_tree) parse_complete("zfs status config tree", i, parse_zpool_status_tree)
} }
fn parse_zpool_status(i: &str) -> Result<Vec<(String, String)>, Error> { fn parse_zpool_status(input: &str) -> Result<Vec<(String, String)>, Error> {
parse_complete("zfs status output", i, many0(parse_zpool_status_field)) let input = input.replace('\t', " "); // important!
parse_complete("zfs status output", &input, many0(parse_zpool_status_field))
} }
pub fn vdev_list_to_tree(vdev_list: &[ZFSPoolVDevState]) -> Value { pub fn vdev_list_to_tree(vdev_list: &[ZFSPoolVDevState]) -> Value {
@ -235,7 +256,7 @@ config:
NAME STATE READ WRITE CKSUM NAME STATE READ WRITE CKSUM
tank DEGRADED 0 0 0 tank DEGRADED 0 0 0
mirror-0 DEGRADED 0 0 0 mirror-0 DEGRADED 0 0 0
c1t0d0 ONLINE 0 0 0 c1t0d0 ONLINE 0 0 0
c1t2d0 ONLINE 0 0 0 c1t2d0 ONLINE 0 0 0
c1t1d0 UNAVAIL 0 0 0 cannot open c1t1d0 UNAVAIL 0 0 0 cannot open
@ -251,8 +272,44 @@ errors: No known data errors
println!("{} => {}", k,v); println!("{} => {}", k,v);
if k == "config" { if k == "config" {
let vdev_list = parse_zpool_status_config_tree(&v)?; let vdev_list = parse_zpool_status_config_tree(&v)?;
let tree = vdev_list_to_tree(&vdev_list); let _tree = vdev_list_to_tree(&vdev_list);
println!("TREE1 {}", serde_json::to_string_pretty(&tree)?); //println!("TREE1 {}", serde_json::to_string_pretty(&tree)?);
}
}
Ok(())
}
#[test]
fn test_zpool_status_parser2() -> Result<(), Error> {
// Note: this input create TABS
let output = r###" pool: btest
state: ONLINE
scan: none requested
config:
NAME STATE READ WRITE CKSUM
btest ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
/dev/sda1 ONLINE 0 0 0
/dev/sda2 ONLINE 0 0 0
mirror-1 ONLINE 0 0 0
/dev/sda3 ONLINE 0 0 0
/dev/sda4 ONLINE 0 0 0
logs
/dev/sda5 ONLINE 0 0 0
errors: No known data errors
"###;
let key_value_list = parse_zpool_status(&output)?;
for (k, v) in key_value_list {
println!("{} => {}", k,v);
if k == "config" {
let vdev_list = parse_zpool_status_config_tree(&v)?;
let _tree = vdev_list_to_tree(&vdev_list);
//println!("TREE1 {}", serde_json::to_string_pretty(&tree)?);
} }
} }