Skip to content
This repository has been archived by the owner on May 21, 2024. It is now read-only.

Commit

Permalink
Implement qmt quota stats
Browse files Browse the repository at this point in the history
  • Loading branch information
RDruon committed Jul 18, 2023
1 parent 2da1d62 commit e86fa86
Show file tree
Hide file tree
Showing 8 changed files with 666 additions and 3 deletions.
57 changes: 57 additions & 0 deletions src/fixtures/valid/valid.txt
Original file line number Diff line number Diff line change
Expand Up @@ -328,3 +328,60 @@ req_active 1 samples [reqs] 1 1 1 1
req_timeout 1 samples [secs] 15 15 15 225
reqbuf_avail 3 samples [bufs] 1 1 3 3
ldlm_bl_callback 1 samples [usecs] 16 16 16 256
qmt.testfs-QMT0000.dt-0x0.glb-grp=
global_pool0_dt_grp
- id: 0
limits: { hard: 0, soft: 0, granted: 0, time: 604800 }
qmt.testfs-QMT0000.dt-0x0.glb-prj=
global_pool0_dt_prj
- id: 0
limits: { hard: 0, soft: 0, granted: 0, time: 604800 }
- id: 1337
limits: { hard: 309200, soft: 307200, granted: 1025032, time: 1687277628 }
qmt.testfs-QMT0000.dt-0x0.glb-usr=
global_pool0_dt_usr
- id: 0
limits: { hard: 0, soft: 0, granted: 0, time: 604800 }
qmt.testfs-QMT0000.dt-ddn_ssd.glb-grp=
global_index_copy:
- id: 0
limits: { hard: 0, soft: 0, granted: 0, time: 604800 }
qmt.testfs-QMT0000.dt-ddn_ssd.glb-prj=
global_index_copy:
- id: 0
limits: { hard: 0, soft: 0, granted: 0, time: 604800 }
- id: 1337
limits: { hard: 0, soft: 0, granted: 1024004, time: 281474976710656 }
qmt.testfs-QMT0000.dt-ddn_ssd.glb-usr=
global_index_copy:
- id: 0
limits: { hard: 0, soft: 0, granted: 0, time: 604800 }
qmt.testfs-QMT0000.dt-pool_1.glb-grp=
global_index_copy:
- id: 0
limits: { hard: 0, soft: 0, granted: 0, time: 604800 }
qmt.testfs-QMT0000.dt-pool_1.glb-prj=
global_index_copy:
- id: 0
limits: { hard: 0, soft: 0, granted: 0, time: 604800 }
- id: 1337
limits: { hard: 0, soft: 0, granted: 1024004, time: 281474976710656 }
qmt.testfs-QMT0000.dt-pool_1.glb-usr=
global_index_copy:
- id: 0
limits: { hard: 0, soft: 0, granted: 0, time: 604800 }
qmt.testfs-QMT0000.md-0x0.glb-grp=
global_pool0_md_grp
- id: 0
limits: { hard: 0, soft: 0, granted: 0, time: 604800 }
qmt.testfs-QMT0000.md-0x0.glb-prj=
global_pool0_md_prj
- id: 0
limits: { hard: 0, soft: 0, granted: 0, time: 604800 }
- id: 1337
limits: { hard: 11000, soft: 10000, granted: 1024, time: 0 }
qmt.testfs-QMT0000.md-0x0.glb-usr=
global_pool0_md_usr
- id: 0
limits: { hard: 0, soft: 0, granted: 0, time: 604800 }
ldlm.namespaces.filter-ai400-OST0001_UUID.resource_count=0
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ mod node_stats_parsers;
mod osd_parser;
mod oss;
pub mod parser;
pub(crate) mod qmt;
pub mod recovery_status_parser;
mod stats_parser;
mod time;
Expand Down
4 changes: 3 additions & 1 deletion src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
ldlm,
mds::{client_count_parser, mds_parser},
mgs::mgs_parser,
osd_parser, oss, top_level_parser,
osd_parser, oss, qmt, top_level_parser,
types::Record,
};
use combine::{choice, error::ParseError, many, Parser, Stream};
Expand All @@ -21,6 +21,7 @@ pub fn params() -> Vec<String> {
.chain(oss::params())
.chain(mds_parser::params())
.chain(ldlm::params())
.chain(qmt::params())
.collect()
}

Expand All @@ -37,6 +38,7 @@ where
mds_parser::parse().map(|x| vec![x]),
oss::parse().map(|x| vec![x]),
ldlm::parse().map(|x| vec![x]),
qmt::parse().map(|x| vec![x]),
)))
.map(|xs: Vec<_>| xs.into_iter().flatten().collect())
}
Expand Down
22 changes: 22 additions & 0 deletions src/qmt/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) 2023 DDN. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

use crate::{base_parsers::period, Record};
use combine::{parser::char::string, ParseError, Parser, Stream};

mod qmt_parser;

pub(crate) const QMT: &str = "qmt";

pub(crate) fn params() -> Vec<String> {
qmt_parser::params()
}

pub(crate) fn parse<I>() -> impl Parser<I, Output = Record>
where
I: Stream<Token = char>,
I::Error: ParseError<I::Token, I::Range, I::Position>,
{
(string(QMT), period()).with(qmt_parser::parse())
}
169 changes: 169 additions & 0 deletions src/qmt/qmt_parser.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
// Copyright (c) 2021 DDN. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

use crate::{
base_parsers::{param, period, target},
qmt::QMT,
types::{Param, Record, Target, TargetStats},
QuotaKind, QuotaStat, QuotaStats, TargetQuotaStat,
};
use combine::{
attempt, choice,
error::{ParseError, StreamError},
many, one_of, optional,
parser::{
char::{alpha_num, newline},
repeat::take_until,
},
stream::{Stream, StreamErrorFor},
Parser,
};

pub(crate) const USR_QUOTAS: &str = "glb-usr";
pub(crate) const PRJ_QUOTAS: &str = "glb-prj";
pub(crate) const GRP_QUOTAS: &str = "glb-grp";
pub(crate) const QMT_STATS: [&str; 3] = [USR_QUOTAS, PRJ_QUOTAS, GRP_QUOTAS];

/// Takes QMT_STATS and produces a list of params for
/// consumption in proper ltcl get_param format.
pub(crate) fn params() -> Vec<String> {
QMT_STATS.iter().map(|x| format!("{QMT}.*.*.{x}")).collect()
}

/// Parses the name of a target
fn qmt_target<I>() -> impl Parser<I, Output = (Target, Target)>
where
I: Stream<Token = char>,
I::Error: ParseError<I::Token, I::Range, I::Position>,
{
(target().skip(period()), target().skip(period()))
.map(|x| x)
.message("while parsing target_name")
}

pub(crate) fn quota_stats<I>() -> impl Parser<I, Output = Vec<QuotaStat>>
where
I: Stream<Token = char>,
I::Error: ParseError<I::Token, I::Range, I::Position>,
{
(
optional(newline()), // If quota stats are present, the whole yaml blob will be on a newline
many::<Vec<_>, _, _>(alpha_num().or(one_of("_-:".chars()))), // But yaml header might not be properly formatted, ignore it
newline(),
take_until(attempt((newline(), alpha_num()))),
)
.skip(newline())
.and_then(|(_, _, _, x): (_, _, _, String)| {
serde_yaml::from_str::<Vec<QuotaStat>>(&x).map_err(StreamErrorFor::<I>::other)
})
}

#[derive(Debug)]
pub enum QMTStat {
Usr(Vec<QuotaStat>),
Prj(Vec<QuotaStat>),
Grp(Vec<QuotaStat>),
}

pub(crate) fn qmt_stat<I>() -> impl Parser<I, Output = (Param, QMTStat)>
where
I: Stream<Token = char>,
I::Error: ParseError<I::Token, I::Range, I::Position>,
{
choice((
(param(USR_QUOTAS), quota_stats().map(QMTStat::Usr)),
(param(PRJ_QUOTAS), quota_stats().map(QMTStat::Prj)),
(param(GRP_QUOTAS), quota_stats().map(QMTStat::Grp)),
))
}

pub(crate) fn parse<I>() -> impl Parser<I, Output = Record>
where
I: Stream<Token = char>,
I::Error: ParseError<I::Token, I::Range, I::Position>,
{
(qmt_target(), qmt_stat())
.map(|((target, Target(pool)), (param, value))| match value {
QMTStat::Usr(stats) => TargetStats::QuotaStats(TargetQuotaStat {
pool,
target,
param,
value: QuotaStats {
kind: QuotaKind::Usr,
stats,
},
}),
QMTStat::Prj(stats) => TargetStats::QuotaStats(TargetQuotaStat {
pool,
target,
param,
value: QuotaStats {
kind: QuotaKind::Grp,
stats,
},
}),
QMTStat::Grp(stats) => TargetStats::QuotaStats(TargetQuotaStat {
pool,
target,
param,
value: QuotaStats {
kind: QuotaKind::Grp,
stats,
},
}),
})
.map(Record::Target)
.message("while parsing qmt")
}

#[cfg(test)]
mod tests {
use crate::{QuotaStat, QuotaStatLimits};

use super::*;

#[test]
fn test_qmt_params() {
assert_eq!(
params(),
vec![
"qmt.*.*.glb-usr".to_string(),
"qmt.*.*.glb-prj".to_string(),
"qmt.*.*.glb-grp".to_string(),
]
)
}

#[test]
fn test_yaml_deserialize() {
let x = r#"
- id: 0
limits: { hard: 0, soft: 0, granted: 0, time: 604800 }
- id: 1337
limits: { hard: 309200, soft: 307200, granted: 1025032, time: 1687277628 }"#;

let expected = vec![
QuotaStat {
id: 0,
limits: QuotaStatLimits {
hard: 0,
soft: 0,
granted: 0,
time: 604800,
},
},
QuotaStat {
id: 1337,
limits: QuotaStatLimits {
hard: 309200,
soft: 307200,
granted: 1025032,
time: 1687277628,
},
},
];

assert_eq!(serde_yaml::from_str::<Vec<QuotaStat>>(x).unwrap(), expected)
}
}
Loading

0 comments on commit e86fa86

Please sign in to comment.