mirror of
https://github.com/centreon/centreon-plugins.git
synced 2025-07-31 01:24:35 +02:00
wip(generic-snmp): with a better json structure. Not functional
This commit is contained in:
parent
19a0a89634
commit
968922478e
@ -18,7 +18,7 @@ rasn = "0.24.0"
|
||||
rasn-snmp = "0.24.0"
|
||||
rasn-smi = "0.24.0"
|
||||
log = "0.4.25"
|
||||
clap = { version = "4.5.29", features = ["derive"] }
|
||||
lexopt = "0.3.0"
|
||||
serde = { version = "1.0.217", features = ["derive"] }
|
||||
serde_json = "1.0.138"
|
||||
lalrpop-util = { version = "0.22.1", features = ["lexer"] }
|
||||
|
@ -4,7 +4,7 @@
|
||||
{
|
||||
"name": "cpu",
|
||||
"oid": "1.3.6.1.2.1.25.3.3.1.2",
|
||||
"query": "Walk", // par défaut walk
|
||||
"query": "Walk"
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -13,18 +13,18 @@
|
||||
{
|
||||
"name": "core.cpu.usage.percent",
|
||||
"value": "{cpu}",
|
||||
"uom": "%", // optional
|
||||
"min": 0, // optional
|
||||
"max": 100 // optional
|
||||
"uom": "%",
|
||||
"min": 0,
|
||||
"max": 100
|
||||
}
|
||||
],
|
||||
"aggregations": [
|
||||
{
|
||||
"name": "avg.cpu.usage.percent",
|
||||
"value": "Average({cpu})", // si agregation, pas de prefix
|
||||
"uom": "%", // optional
|
||||
"min": 0, // optional
|
||||
"max": 100 // optional
|
||||
"value": "Average({cpu})",
|
||||
"uom": "%",
|
||||
"min": 0,
|
||||
"max": 100
|
||||
}
|
||||
]
|
||||
}
|
||||
|
31
experimental/examples/new-cpu.json.example
Normal file
31
experimental/examples/new-cpu.json.example
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"collect": {
|
||||
"snmp": [
|
||||
{
|
||||
"name": "cpu",
|
||||
"oid": "1.3.6.1.2.1.25.3.3.1.2",
|
||||
"query": "Walk", // par défaut walk
|
||||
}
|
||||
]
|
||||
},
|
||||
"compute": {
|
||||
"metrics": [
|
||||
{
|
||||
"name": "core.cpu.usage.percent",
|
||||
"value": "{cpu}",
|
||||
"uom": "%", // optional
|
||||
"min": 0, // optional
|
||||
"max": 100 // optional
|
||||
}
|
||||
],
|
||||
"aggregations": [
|
||||
{
|
||||
"name": "avg.cpu.usage.percent",
|
||||
"value": "Average({cpu})", // si agregation, pas de prefix
|
||||
"uom": "%", // optional
|
||||
"min": 0, // optional
|
||||
"max": 100 // optional
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
{
|
||||
"name": "disk",
|
||||
"oid": "1.3.6.1.2.1.25.2.3.1",
|
||||
"query": "Walk", // par défaut walk
|
||||
"query": "Walk",
|
||||
"labels": {
|
||||
".3": "label",
|
||||
".4": "allocationUnits",
|
||||
@ -17,28 +17,28 @@
|
||||
"compute": {
|
||||
"metrics": [
|
||||
{
|
||||
"prefix": "{disk.label}", // par défaut "{idx}"
|
||||
"prefix": "{disk.label}",
|
||||
"name": "disk.usage.percent",
|
||||
"value": "100 * {disk.used} / {disk.size}",
|
||||
"uom": "%", // optional
|
||||
"min": 0, // optional
|
||||
"max": 100, // optional
|
||||
"uom": "%",
|
||||
"min": 0,
|
||||
"max": 100
|
||||
},
|
||||
{
|
||||
"name": "disk.usage.bytes",
|
||||
"value": "{disk.used} * {disk.allocationUnits}",
|
||||
"uom": "B", // optional
|
||||
"min": 0, // optional
|
||||
"max_expr": "{disk.size} * {disk.allocationUnits}" // optional
|
||||
"uom": "B",
|
||||
"min": 0,
|
||||
"max_expr": "{disk.size} * {disk.allocationUnits}"
|
||||
}
|
||||
],
|
||||
"aggregations": [
|
||||
{
|
||||
"name": "avg.disk.usage.percent",
|
||||
"value": "Average({metrics.disk.usage.percent})", // si agregation, pas de prefix
|
||||
"uom": "%", // optional
|
||||
"min": 0, // optional
|
||||
"max": 100 // optional
|
||||
"value": "Average({metrics.disk.usage.percent})",
|
||||
"uom": "%",
|
||||
"min": 0,
|
||||
"max": 100
|
||||
}
|
||||
]
|
||||
}
|
||||
|
46
experimental/examples/new-disk.json.example
Normal file
46
experimental/examples/new-disk.json.example
Normal file
@ -0,0 +1,46 @@
|
||||
{
|
||||
"collect": {
|
||||
"snmp": [
|
||||
{
|
||||
"name": "disk",
|
||||
"oid": "1.3.6.1.2.1.25.2.3.1",
|
||||
"query": "Walk", // par défaut walk
|
||||
"labels": {
|
||||
".3": "label",
|
||||
".4": "allocationUnits",
|
||||
".5": "size",
|
||||
".6": "used"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"compute": {
|
||||
"metrics": [
|
||||
{
|
||||
"prefix": "{disk.label}", // par défaut "{idx}"
|
||||
"name": "disk.usage.percent",
|
||||
"value": "100 * {disk.used} / {disk.size}",
|
||||
"uom": "%", // optional
|
||||
"min": 0, // optional
|
||||
"max": 100, // optional
|
||||
},
|
||||
{
|
||||
"name": "disk.usage.bytes",
|
||||
"value": "{disk.used} * {disk.allocationUnits}",
|
||||
"uom": "B", // optional
|
||||
"min": 0, // optional
|
||||
"max_expr": "{disk.size} * {disk.allocationUnits}" // optional
|
||||
}
|
||||
],
|
||||
"aggregations": [
|
||||
{
|
||||
"name": "avg.disk.usage.percent",
|
||||
"value": "Average({metrics.disk.usage.percent})", // si agregation, pas de prefix
|
||||
"uom": "%", // optional
|
||||
"min": 0, // optional
|
||||
"max": 100 // optional
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -4,12 +4,12 @@
|
||||
{
|
||||
"name": "total",
|
||||
"oid": "1.3.6.1.4.1.2021.4.6.0",
|
||||
"query": "Get", // par défaut walk
|
||||
"query": "Get"
|
||||
},
|
||||
{
|
||||
"name": "free",
|
||||
"oid": "1.3.6.1.4.1.2021.4.11.0",
|
||||
"query": "Get", // par défaut walk
|
||||
"query": "Get"
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -18,16 +18,17 @@
|
||||
{
|
||||
"name": "core.mem.usage.percent",
|
||||
"value": "100 * (1 - {free}/{cpu})",
|
||||
"uom": "%", // optional
|
||||
"min": 0, // optional
|
||||
"max": 100 // optional
|
||||
"uom": "%",
|
||||
"min": 0,
|
||||
"max": 100,
|
||||
"threshold-suffix": "mem"
|
||||
},
|
||||
{
|
||||
"name": "avg.cpu.usage.percent",
|
||||
"value": "Average({cpu})", // si agregation, pas de prefix
|
||||
"uom": "%", // optional
|
||||
"min": 0, // optional
|
||||
"max": 100 // optional
|
||||
"value": "Average({cpu})",
|
||||
"uom": "%",
|
||||
"min": 0,
|
||||
"max": 100
|
||||
}
|
||||
]
|
||||
}
|
||||
|
36
experimental/examples/new-mem.json.example
Normal file
36
experimental/examples/new-mem.json.example
Normal file
@ -0,0 +1,36 @@
|
||||
{
|
||||
"collect": {
|
||||
"snmp": [
|
||||
{
|
||||
"name": "total",
|
||||
"oid": "1.3.6.1.4.1.2021.4.6.0",
|
||||
"query": "Get", // par défaut walk
|
||||
},
|
||||
{
|
||||
"name": "free",
|
||||
"oid": "1.3.6.1.4.1.2021.4.11.0",
|
||||
"query": "Get", // par défaut walk
|
||||
}
|
||||
]
|
||||
},
|
||||
"compute": {
|
||||
"metrics": [
|
||||
{
|
||||
"name": "core.mem.usage.percent",
|
||||
"value": "100 * (1 - {free}/{cpu})",
|
||||
"uom": "%", // optional
|
||||
"min": 0, // optional
|
||||
"max": 100, // optional
|
||||
"threshold-suffix": "mem", // optional (example: --warning-mem=78 --critical-mem=90)
|
||||
},
|
||||
{
|
||||
"name": "avg.cpu.usage.percent",
|
||||
"value": "Average({cpu})", // si agregation, pas de prefix
|
||||
"uom": "%", // optional
|
||||
"min": 0, // optional
|
||||
"max": 100 // optional
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -23,15 +23,6 @@ impl Status {
|
||||
}
|
||||
}
|
||||
|
||||
struct Metric<'b> {
|
||||
name: String,
|
||||
value: f32,
|
||||
warning: &'b Option<String>,
|
||||
critical: &'b Option<String>,
|
||||
status: Status,
|
||||
agregated: bool,
|
||||
}
|
||||
|
||||
fn worst(a: Status, b: Status) -> Status {
|
||||
let a_int = match a {
|
||||
Status::Ok => 0,
|
||||
@ -52,60 +43,42 @@ fn worst(a: Status, b: Status) -> Status {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone, Copy)]
|
||||
enum Operation {
|
||||
None,
|
||||
Average,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
enum QueryType {
|
||||
Walk,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct EntryOperation {
|
||||
struct Metric {
|
||||
name: String,
|
||||
op: Operation,
|
||||
value: String,
|
||||
uom: Option<String>,
|
||||
min: Option<f32>,
|
||||
max: Option<f32>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct EntryQuery {
|
||||
pub struct Compute {
|
||||
metrics: Vec<Metric>,
|
||||
aggregations: Vec<Metric>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct Snmp {
|
||||
name: String,
|
||||
oid: String,
|
||||
query: QueryType,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
enum Entry {
|
||||
Agregation(EntryOperation),
|
||||
Query(EntryQuery),
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct Data {
|
||||
uom: String,
|
||||
min: Option<f32>,
|
||||
max: Option<f32>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct OutputTable {
|
||||
header: String,
|
||||
text: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct Leaf {
|
||||
name: String,
|
||||
output: OutputTable,
|
||||
entries: Vec<Entry>,
|
||||
data: Option<Data>,
|
||||
pub struct Collect {
|
||||
snmp: Vec<Snmp>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct Command {
|
||||
leaf: Leaf,
|
||||
collect: Collect,
|
||||
compute: Compute,
|
||||
}
|
||||
|
||||
pub struct CmdResult {
|
||||
@ -136,66 +109,66 @@ fn compute_status(value: f32, warn: &Option<String>, crit: &Option<String>) -> S
|
||||
Status::Ok
|
||||
}
|
||||
|
||||
fn build_metrics<'a>(
|
||||
values: &Vec<(String, f32)>,
|
||||
ag: &Option<(&str, usize, f32)>,
|
||||
ext: &'a CommandExt,
|
||||
) -> (Vec<Metric<'a>>, Status) {
|
||||
let mut metrics: Vec<Metric> = Vec::new();
|
||||
let mut status = Status::Ok;
|
||||
match ag {
|
||||
Some(a) => {
|
||||
// The agregation is located in first place
|
||||
if a.1 == 0 {
|
||||
let w = &ext.warning_agregation;
|
||||
let c = &ext.critical_agregation;
|
||||
let current_status =
|
||||
compute_status(a.2, &ext.warning_agregation, &ext.critical_agregation);
|
||||
metrics.push(Metric {
|
||||
name: a.0.to_string(),
|
||||
value: a.2,
|
||||
warning: w,
|
||||
critical: c,
|
||||
status: current_status,
|
||||
agregated: true,
|
||||
});
|
||||
status = worst(current_status, status);
|
||||
}
|
||||
}
|
||||
None => (),
|
||||
}
|
||||
values.iter().enumerate().for_each(|(i, v)| {
|
||||
let current_status = compute_status(v.1, &ext.warning_core, &ext.critical_core);
|
||||
metrics.push(Metric {
|
||||
name: values[i].0.clone(),
|
||||
value: v.1,
|
||||
warning: &ext.warning_core,
|
||||
critical: &ext.critical_core,
|
||||
status: current_status,
|
||||
agregated: false,
|
||||
});
|
||||
status = worst(current_status, status);
|
||||
});
|
||||
match ag {
|
||||
Some(a) => {
|
||||
if a.1 > 0 {
|
||||
let current_status =
|
||||
compute_status(a.2, &ext.warning_agregation, &ext.critical_agregation);
|
||||
metrics.push(Metric {
|
||||
name: a.0.to_string(),
|
||||
value: a.2,
|
||||
warning: &ext.warning_agregation,
|
||||
critical: &ext.critical_agregation,
|
||||
status: current_status,
|
||||
agregated: true,
|
||||
});
|
||||
status = worst(current_status, status);
|
||||
}
|
||||
}
|
||||
None => (),
|
||||
}
|
||||
(metrics, status)
|
||||
}
|
||||
//fn build_metrics<'a>(
|
||||
// values: &Vec<(String, f32)>,
|
||||
// ag: &Option<(&str, usize, f32)>,
|
||||
// ext: &'a CommandExt,
|
||||
//) -> (Vec<Metric<'a>>, Status) {
|
||||
// let mut metrics: Vec<Metric> = Vec::new();
|
||||
// let mut status = Status::Ok;
|
||||
// match ag {
|
||||
// Some(a) => {
|
||||
// // The agregation is located in first place
|
||||
// if a.1 == 0 {
|
||||
// let w = &ext.warning_agregation;
|
||||
// let c = &ext.critical_agregation;
|
||||
// let current_status =
|
||||
// compute_status(a.2, &ext.warning_agregation, &ext.critical_agregation);
|
||||
// metrics.push(Metric {
|
||||
// name: a.0.to_string(),
|
||||
// value: a.2,
|
||||
// warning: w,
|
||||
// critical: c,
|
||||
// status: current_status,
|
||||
// agregated: true,
|
||||
// });
|
||||
// status = worst(current_status, status);
|
||||
// }
|
||||
// }
|
||||
// None => (),
|
||||
// }
|
||||
// values.iter().enumerate().for_each(|(i, v)| {
|
||||
// let current_status = compute_status(v.1, &ext.warning_core, &ext.critical_core);
|
||||
// metrics.push(Metric {
|
||||
// name: values[i].0.clone(),
|
||||
// value: v.1,
|
||||
// warning: &ext.warning_core,
|
||||
// critical: &ext.critical_core,
|
||||
// status: current_status,
|
||||
// agregated: false,
|
||||
// });
|
||||
// status = worst(current_status, status);
|
||||
// });
|
||||
// match ag {
|
||||
// Some(a) => {
|
||||
// if a.1 > 0 {
|
||||
// let current_status =
|
||||
// compute_status(a.2, &ext.warning_agregation, &ext.critical_agregation);
|
||||
// metrics.push(Metric {
|
||||
// name: a.0.to_string(),
|
||||
// value: a.2,
|
||||
// warning: &ext.warning_agregation,
|
||||
// critical: &ext.critical_agregation,
|
||||
// status: current_status,
|
||||
// agregated: true,
|
||||
// });
|
||||
// status = worst(current_status, status);
|
||||
// }
|
||||
// }
|
||||
// None => (),
|
||||
// }
|
||||
// (metrics, status)
|
||||
//}
|
||||
|
||||
impl Command {
|
||||
pub fn execute(
|
||||
@ -205,193 +178,197 @@ impl Command {
|
||||
community: &str,
|
||||
ext: &CommandExt,
|
||||
) -> CmdResult {
|
||||
let mut agregation = ("", 0, Operation::None);
|
||||
let mut res: Option<(&str, SnmpResult)> = None;
|
||||
for (idx, entry) in self.leaf.entries.iter().enumerate() {
|
||||
match entry {
|
||||
Entry::Agregation(op) => {
|
||||
agregation = (&op.name, idx, op.op);
|
||||
}
|
||||
Entry::Query(query) => match query.query {
|
||||
QueryType::Walk => {
|
||||
res = Some((
|
||||
&query.name,
|
||||
r_snmp_bulk_walk(target, version, community, &query.oid),
|
||||
));
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
match res {
|
||||
Some(r) => {
|
||||
let mut values: Vec<(String, f32)> = Vec::new();
|
||||
let mut idx = 0;
|
||||
r.1.variables.iter().for_each(|v| {
|
||||
let label = r.0.replace("{idx}", &idx.to_string());
|
||||
values.push((label, v.value.parse().unwrap()));
|
||||
idx += 1;
|
||||
});
|
||||
let count = values.len();
|
||||
let ag = match agregation.2 {
|
||||
Operation::Average => {
|
||||
let sum: f32 = values.iter().map(|(_, v)| v).sum();
|
||||
let avg = sum / values.len() as f32;
|
||||
Some((agregation.0, agregation.1, avg))
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
let (metrics, status) = build_metrics(&values, &ag, &ext);
|
||||
let output = self.build_output(count, status, &metrics, &ag, &ext);
|
||||
return CmdResult { status, output };
|
||||
}
|
||||
None => {
|
||||
return CmdResult {
|
||||
status: Status::Unknown,
|
||||
output: "No result".to_string(),
|
||||
};
|
||||
}
|
||||
// let mut agregation = ("", 0, Operation::None);
|
||||
// let mut res: Option<(&str, SnmpResult)> = None;
|
||||
// for (idx, entry) in self.leaf.entries.iter().enumerate() {
|
||||
// match entry {
|
||||
// Entry::Agregation(op) => {
|
||||
// agregation = (&op.name, idx, op.op);
|
||||
// }
|
||||
// Entry::Query(query) => match query.query {
|
||||
// QueryType::Walk => {
|
||||
// res = Some((
|
||||
// &query.name,
|
||||
// r_snmp_bulk_walk(target, version, community, &query.oid),
|
||||
// ));
|
||||
// }
|
||||
// },
|
||||
// }
|
||||
// }
|
||||
// match res {
|
||||
// Some(r) => {
|
||||
// let mut values: Vec<(String, f32)> = Vec::new();
|
||||
// let mut idx = 0;
|
||||
// r.1.variables.iter().for_each(|v| {
|
||||
// let label = r.0.replace("{idx}", &idx.to_string());
|
||||
// values.push((label, v.value.parse().unwrap()));
|
||||
// idx += 1;
|
||||
// });
|
||||
// let count = values.len();
|
||||
// let ag = match agregation.2 {
|
||||
// Operation::Average => {
|
||||
// let sum: f32 = values.iter().map(|(_, v)| v).sum();
|
||||
// let avg = sum / values.len() as f32;
|
||||
// Some((agregation.0, agregation.1, avg))
|
||||
// }
|
||||
// _ => None,
|
||||
// };
|
||||
// let (metrics, status) = build_metrics(&values, &ag, &ext);
|
||||
// let output = self.build_output(count, status, &metrics, &ag, &ext);
|
||||
// return CmdResult { status, output };
|
||||
// }
|
||||
// None => {
|
||||
// return CmdResult {
|
||||
// status: Status::Unknown,
|
||||
// output: "No result".to_string(),
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
CmdResult {
|
||||
status: Status::Unknown,
|
||||
output: "No result".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
fn build_output(
|
||||
&self,
|
||||
count: usize,
|
||||
status: Status,
|
||||
metrics: &Vec<Metric>,
|
||||
ag: &Option<(&str, usize, f32)>,
|
||||
ext: &CommandExt,
|
||||
) -> String {
|
||||
let no_threshold = ext.warning_core.is_none()
|
||||
&& ext.critical_core.is_none()
|
||||
&& ext.warning_agregation.is_none()
|
||||
&& ext.critical_agregation.is_none();
|
||||
let write_details =
|
||||
no_threshold || (ext.warning_core.is_some() || ext.critical_core.is_some());
|
||||
let write_agregation_details =
|
||||
no_threshold || (ext.warning_agregation.is_some() || ext.critical_agregation.is_some());
|
||||
let mut output_text = "".to_string();
|
||||
let mut begun = false;
|
||||
if &self.leaf.output.header != "" {
|
||||
output_text = self.leaf.output.header.replace("{status}", status.as_str());
|
||||
}
|
||||
for line in &self.leaf.output.text {
|
||||
if line.contains("idx") {
|
||||
if write_details {
|
||||
// We have to iterate on metrics
|
||||
let mut output_vec = (Vec::new(), Vec::new(), Vec::new());
|
||||
let mut idx = 0;
|
||||
for m in metrics.iter() {
|
||||
if !m.agregated {
|
||||
let text = line
|
||||
.replace("{idx}", idx.to_string().as_str())
|
||||
.replace("{name}", m.name.as_str())
|
||||
.replace("{value}", format!("{:.2}", m.value).as_str())
|
||||
.replace("{count}", count.to_string().as_str());
|
||||
match m.status {
|
||||
Status::Ok => {
|
||||
output_vec.0.push(text);
|
||||
}
|
||||
Status::Warning => {
|
||||
output_vec.1.push(text);
|
||||
}
|
||||
Status::Critical => {
|
||||
output_vec.2.push(text);
|
||||
}
|
||||
Status::Unknown => (),
|
||||
}
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
if !output_vec.2.is_empty() {
|
||||
if begun {
|
||||
output_text += " - ";
|
||||
} else {
|
||||
begun = true;
|
||||
}
|
||||
output_text += output_vec.2.join(" - ").as_str();
|
||||
}
|
||||
if !output_vec.1.is_empty() {
|
||||
if begun {
|
||||
output_text += " - ";
|
||||
} else {
|
||||
begun = true;
|
||||
}
|
||||
output_text += output_vec.1.join(" - ").as_str();
|
||||
}
|
||||
if !output_vec.0.is_empty() {
|
||||
if begun {
|
||||
output_text += " - ";
|
||||
}
|
||||
output_text += output_vec.0.join(" - ").as_str();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if write_agregation_details {
|
||||
match ag {
|
||||
Some(a) => {
|
||||
output_text += line
|
||||
.replace(
|
||||
format!("{{{}}}", a.0).as_str(),
|
||||
format!("{:.2}", a.2).as_str(),
|
||||
)
|
||||
.replace("{count}", count.to_string().as_str())
|
||||
.as_str();
|
||||
begun = true;
|
||||
}
|
||||
None => output_text += line,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut perfdata = " |".to_string();
|
||||
match &self.leaf.data {
|
||||
Some(d) => {
|
||||
metrics.iter().for_each(|m| {
|
||||
perfdata += format!(
|
||||
" '{}'={}{};{};{};{};{}",
|
||||
m.name,
|
||||
m.value,
|
||||
d.uom,
|
||||
match m.warning {
|
||||
Some(m) => m.to_string(),
|
||||
None => "".to_string(),
|
||||
},
|
||||
match m.critical {
|
||||
Some(m) => m.to_string(),
|
||||
None => "".to_string(),
|
||||
},
|
||||
match d.min {
|
||||
Some(m) => m.to_string(),
|
||||
None => "".to_string(),
|
||||
},
|
||||
match d.max {
|
||||
Some(m) => m.to_string(),
|
||||
None => "".to_string(),
|
||||
},
|
||||
)
|
||||
.as_str();
|
||||
});
|
||||
}
|
||||
None => {
|
||||
metrics.iter().for_each(|m| {
|
||||
perfdata += format!(
|
||||
" '{}'={};{};{}",
|
||||
m.name,
|
||||
m.value,
|
||||
match m.warning {
|
||||
Some(v) => v.to_string(),
|
||||
None => "".to_string(),
|
||||
},
|
||||
match m.critical {
|
||||
Some(v) => v.to_string(),
|
||||
None => "".to_string(),
|
||||
}
|
||||
)
|
||||
.as_str();
|
||||
});
|
||||
}
|
||||
};
|
||||
output_text + &perfdata
|
||||
}
|
||||
// fn build_output(
|
||||
// &self,
|
||||
// count: usize,
|
||||
// status: Status,
|
||||
// metrics: &Vec<Metric>,
|
||||
// ag: &Option<(&str, usize, f32)>,
|
||||
// ext: &CommandExt,
|
||||
// ) -> String {
|
||||
// let no_threshold = ext.warning_core.is_none()
|
||||
// && ext.critical_core.is_none()
|
||||
// && ext.warning_agregation.is_none()
|
||||
// && ext.critical_agregation.is_none();
|
||||
// let write_details =
|
||||
// no_threshold || (ext.warning_core.is_some() || ext.critical_core.is_some());
|
||||
// let write_agregation_details =
|
||||
// no_threshold || (ext.warning_agregation.is_some() || ext.critical_agregation.is_some());
|
||||
// let mut output_text = "".to_string();
|
||||
// let mut begun = false;
|
||||
// if &self.leaf.output.header != "" {
|
||||
// output_text = self.leaf.output.header.replace("{status}", status.as_str());
|
||||
// }
|
||||
// for line in &self.leaf.output.text {
|
||||
// if line.contains("idx") {
|
||||
// if write_details {
|
||||
// // We have to iterate on metrics
|
||||
// let mut output_vec = (Vec::new(), Vec::new(), Vec::new());
|
||||
// let mut idx = 0;
|
||||
// for m in metrics.iter() {
|
||||
// if !m.agregated {
|
||||
// let text = line
|
||||
// .replace("{idx}", idx.to_string().as_str())
|
||||
// .replace("{name}", m.name.as_str())
|
||||
// .replace("{value}", format!("{:.2}", m.value).as_str())
|
||||
// .replace("{count}", count.to_string().as_str());
|
||||
// match m.status {
|
||||
// Status::Ok => {
|
||||
// output_vec.0.push(text);
|
||||
// }
|
||||
// Status::Warning => {
|
||||
// output_vec.1.push(text);
|
||||
// }
|
||||
// Status::Critical => {
|
||||
// output_vec.2.push(text);
|
||||
// }
|
||||
// Status::Unknown => (),
|
||||
// }
|
||||
// idx += 1;
|
||||
// }
|
||||
// }
|
||||
// if !output_vec.2.is_empty() {
|
||||
// if begun {
|
||||
// output_text += " - ";
|
||||
// } else {
|
||||
// begun = true;
|
||||
// }
|
||||
// output_text += output_vec.2.join(" - ").as_str();
|
||||
// }
|
||||
// if !output_vec.1.is_empty() {
|
||||
// if begun {
|
||||
// output_text += " - ";
|
||||
// } else {
|
||||
// begun = true;
|
||||
// }
|
||||
// output_text += output_vec.1.join(" - ").as_str();
|
||||
// }
|
||||
// if !output_vec.0.is_empty() {
|
||||
// if begun {
|
||||
// output_text += " - ";
|
||||
// }
|
||||
// output_text += output_vec.0.join(" - ").as_str();
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// if write_agregation_details {
|
||||
// match ag {
|
||||
// Some(a) => {
|
||||
// output_text += line
|
||||
// .replace(
|
||||
// format!("{{{}}}", a.0).as_str(),
|
||||
// format!("{:.2}", a.2).as_str(),
|
||||
// )
|
||||
// .replace("{count}", count.to_string().as_str())
|
||||
// .as_str();
|
||||
// begun = true;
|
||||
// }
|
||||
// None => output_text += line,
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// let mut perfdata = " |".to_string();
|
||||
// match &self.leaf.data {
|
||||
// Some(d) => {
|
||||
// metrics.iter().for_each(|m| {
|
||||
// perfdata += format!(
|
||||
// " '{}'={}{};{};{};{};{}",
|
||||
// m.name,
|
||||
// m.value,
|
||||
// d.uom,
|
||||
// match m.warning {
|
||||
// Some(m) => m.to_string(),
|
||||
// None => "".to_string(),
|
||||
// },
|
||||
// match m.critical {
|
||||
// Some(m) => m.to_string(),
|
||||
// None => "".to_string(),
|
||||
// },
|
||||
// match d.min {
|
||||
// Some(m) => m.to_string(),
|
||||
// None => "".to_string(),
|
||||
// },
|
||||
// match d.max {
|
||||
// Some(m) => m.to_string(),
|
||||
// None => "".to_string(),
|
||||
// },
|
||||
// )
|
||||
// .as_str();
|
||||
// });
|
||||
// }
|
||||
// None => {
|
||||
// metrics.iter().for_each(|m| {
|
||||
// perfdata += format!(
|
||||
// " '{}'={};{};{}",
|
||||
// m.name,
|
||||
// m.value,
|
||||
// match m.warning {
|
||||
// Some(v) => v.to_string(),
|
||||
// None => "".to_string(),
|
||||
// },
|
||||
// match m.critical {
|
||||
// Some(v) => v.to_string(),
|
||||
// None => "".to_string(),
|
||||
// }
|
||||
// )
|
||||
// .as_str();
|
||||
// });
|
||||
// }
|
||||
// };
|
||||
// output_text + &perfdata
|
||||
// }
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
extern crate clap;
|
||||
extern crate lexopt;
|
||||
extern crate lalrpop_util;
|
||||
extern crate log;
|
||||
extern crate rasn;
|
||||
@ -11,8 +11,8 @@ extern crate serde_json;
|
||||
mod generic;
|
||||
mod lib;
|
||||
|
||||
use clap::Parser;
|
||||
use generic::{Command, CommandExt};
|
||||
use std::ffi::{OsString, OsStr};
|
||||
use lalrpop_util::lalrpop_mod;
|
||||
use lib::r_snmp_get;
|
||||
use serde_json::Result;
|
||||
@ -20,35 +20,35 @@ use std::fs;
|
||||
|
||||
lalrpop_mod!(grammar);
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(version, about)]
|
||||
#[derive(Debug)]
|
||||
//#[command(version, about)]
|
||||
struct Cli {
|
||||
/// Hostname to operate on
|
||||
#[arg(long, short = 'H', default_value = "localhost")]
|
||||
//#[arg(long, short = 'H', default_value = "localhost")]
|
||||
hostname: String,
|
||||
|
||||
#[arg(long, short, default_value_t = 161)]
|
||||
//#[arg(long, short, default_value_t = 161)]
|
||||
port: u16,
|
||||
|
||||
#[arg(long, short = 'v', default_value = "2c")]
|
||||
//#[arg(long, short = 'v', default_value = "2c")]
|
||||
snmp_version: String,
|
||||
|
||||
#[arg(long, short, default_value = "public")]
|
||||
//#[arg(long, short, default_value = "public")]
|
||||
community: String,
|
||||
|
||||
#[arg(long, short)]
|
||||
//#[arg(long, short)]
|
||||
json_conf: String,
|
||||
|
||||
#[arg(long, short)]
|
||||
//#[arg(long, short)]
|
||||
warning_core: Option<String>,
|
||||
|
||||
#[arg(long, short = 'C')]
|
||||
//#[arg(long, short = 'C')]
|
||||
critical_core: Option<String>,
|
||||
|
||||
#[arg(long, short = 'a')]
|
||||
//#[arg(long, short = 'a')]
|
||||
warning_agregation: Option<String>,
|
||||
|
||||
#[arg(long, short = 'b')]
|
||||
//#[arg(long, short = 'b')]
|
||||
critical_agregation: Option<String>,
|
||||
}
|
||||
|
||||
@ -67,19 +67,65 @@ fn json_to_command(file_name: &str) -> Result<Command> {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let cli = Cli::parse();
|
||||
let url = format!("{}:{}", cli.hostname, cli.port);
|
||||
let cmd = json_to_command(&cli.json_conf);
|
||||
use lexopt::prelude::*;
|
||||
let mut parser = lexopt::Parser::from_env();
|
||||
let mut hostname = "localhost".to_string();
|
||||
let mut port = 161;
|
||||
let mut json = None;
|
||||
loop {
|
||||
let arg = parser.next();
|
||||
match arg {
|
||||
Ok(arg) => {
|
||||
println!("{:?} ok", arg);
|
||||
match arg {
|
||||
Some(arg) => {
|
||||
match arg {
|
||||
Short('H') | Long("hostname") => {
|
||||
hostname = parser.value().unwrap().into_string().unwrap();
|
||||
},
|
||||
Short('p') | Long("port") => {
|
||||
port = parser.value().unwrap().parse::<u16>().unwrap();
|
||||
println!("port: {}", port);
|
||||
},
|
||||
Short('j') | Long("json") => {
|
||||
json = Some(parser.value().unwrap().into_string().unwrap());
|
||||
println!("json: {:?}", json);
|
||||
},
|
||||
_ => {
|
||||
println!("other");
|
||||
}
|
||||
}
|
||||
},
|
||||
None => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
println!("err: {:?}", err);
|
||||
std::process::exit(3);
|
||||
}
|
||||
}
|
||||
}
|
||||
let url = format!("{}:{}", hostname, port);
|
||||
|
||||
if json.is_none() {
|
||||
println!("json is empty");
|
||||
std::process::exit(3);
|
||||
}
|
||||
|
||||
let json = json.unwrap();
|
||||
let cmd = json_to_command(&json);
|
||||
let cmd = cmd.unwrap();
|
||||
let ext = CommandExt {
|
||||
warning_core: cli.warning_core,
|
||||
critical_core: cli.critical_core,
|
||||
warning_agregation: cli.warning_agregation,
|
||||
critical_agregation: cli.critical_agregation,
|
||||
};
|
||||
let result = cmd.execute(&url, &cli.snmp_version, &cli.community, &ext);
|
||||
println!("{}", result.output);
|
||||
std::process::exit(result.status as i32);
|
||||
//let ext = CommandExt {
|
||||
// warning_core: cli.warning_core,
|
||||
// critical_core: cli.critical_core,
|
||||
// warning_agregation: cli.warning_agregation,
|
||||
// critical_agregation: cli.critical_agregation,
|
||||
//};
|
||||
//let result = cmd.execute(&url, &cli.snmp_version, &cli.community, &ext);
|
||||
//println!("{}", result.output);
|
||||
//std::process::exit(result.status as i32);
|
||||
}
|
||||
|
||||
mod Test {
|
||||
|
Loading…
x
Reference in New Issue
Block a user