rd_agent_intf/
sysreqs.rs

1// Copyright (c) Facebook, Inc. and its affiliates.
2use enum_iterator::IntoEnumIterator;
3use log::warn;
4use serde::{Deserialize, Serialize};
5use std::collections::{BTreeMap, BTreeSet};
6use std::fmt::Write;
7
8use rd_util::*;
9
10const SYSREQ_DOC: &str = "\
11//
12// rd-agent system requirements report
13//
14// satisfied: List of satifised system requirements
15// missed: List of missed system requirements
16// scr_dev_model: Scratch storage device model string
17// scr_dev_fwrev: Scratch storage device firmware revision string
18// scr_dev_size: Scratch storage device size
19// swap_size: Swap size
20//
21";
22
23lazy_static::lazy_static! {
24    pub static ref ALL_SYSREQS_SET: BTreeSet<SysReq> = SysReq::into_enum_iter().collect();
25}
26
27#[derive(
28    Debug,
29    Clone,
30    Copy,
31    PartialEq,
32    Eq,
33    PartialOrd,
34    Ord,
35    Hash,
36    IntoEnumIterator,
37    Serialize,
38    Deserialize,
39)]
40pub enum SysReq {
41    Controllers,
42    Freezer,
43    MemCgRecursiveProt,
44    MemShadowInodeProt, // Enforced only by resctl-bench
45    IoCost,
46    IoCostVer,
47    NoOtherIoControllers,
48    AnonBalance,
49    Btrfs,
50    BtrfsAsyncDiscard,
51    NoCompositeStorage,
52    IoSched,
53    NoWbt,
54    SwapOnScratch,
55    Swap,
56    Oomd,
57    NoSysOomd,
58    HostCriticalServices,
59    DepsBase,
60    DepsIoCostCoefGen,
61    DepsSide,
62    DepsLinuxBuild,
63}
64
65#[derive(Clone, Debug, Default, Serialize, Deserialize)]
66pub struct MissedSysReqs {
67    #[serde(flatten)]
68    pub map: BTreeMap<SysReq, Vec<String>>,
69}
70
71impl MissedSysReqs {
72    pub fn add_quiet(&mut self, req: SysReq, msg: &str) {
73        match self.map.get_mut(&req) {
74            Some(msgs) => msgs.push(msg.to_string()),
75            None => {
76                self.map.insert(req, vec![msg.to_string()]);
77            }
78        }
79    }
80
81    pub fn add(&mut self, req: SysReq, msg: &str) {
82        self.add_quiet(req, msg);
83        warn!("cfg: {}", msg);
84    }
85
86    pub fn format<'a>(&self, out: &mut Box<dyn Write + 'a>) {
87        writeln!(
88            out,
89            "Missed sysreqs: {}",
90            &self
91                .map
92                .keys()
93                .map(|x| format!("{:?}", x))
94                .collect::<Vec<String>>()
95                .join(", ")
96        )
97        .unwrap();
98
99        for (_req, msgs) in self.map.iter() {
100            for msg in msgs.iter() {
101                writeln!(out, "    * {}", msg).unwrap();
102            }
103        }
104    }
105}
106
107#[derive(Clone, Debug, Default, Serialize, Deserialize)]
108pub struct SysReqsReport {
109    pub satisfied: BTreeSet<SysReq>,
110    pub missed: MissedSysReqs,
111    pub kernel_version: String,
112    pub agent_version: String,
113    pub hashd_version: String,
114    pub nr_cpus: usize,
115    pub total_memory: usize,
116    pub total_swap: usize,
117    pub scr_dev: String,
118    pub scr_devnr: (u32, u32),
119    pub scr_dev_model: String,
120    pub scr_dev_fwrev: String,
121    pub scr_dev_size: u64,
122    pub scr_dev_iosched: String,
123    pub enforce: super::EnforceConfig,
124}
125
126impl JsonLoad for SysReqsReport {}
127
128impl JsonSave for SysReqsReport {
129    fn preamble() -> Option<String> {
130        Some(SYSREQ_DOC.to_string())
131    }
132}