mirror of
https://github.com/centreon/centreon-plugins.git
synced 2025-07-29 16:45:04 +02:00
wip(generic-snmp)
This commit is contained in:
parent
6020f9973e
commit
9ff58afa42
@ -6,12 +6,13 @@ version = "1.0.0"
|
||||
lalrpop = "0.22.1"
|
||||
|
||||
[dependencies]
|
||||
regex = "1.11.1"
|
||||
rasn = "0.26.2"
|
||||
rasn-snmp = "0.26.2"
|
||||
rasn-smi = "0.26.2"
|
||||
log = "0.4.27"
|
||||
env_logger = "0.11.8"
|
||||
lalrpop-util = { version = "0.22.1", features = ["lexer"] }
|
||||
lexopt = "0.3.1"
|
||||
log = "0.4.27"
|
||||
rasn = "0.26.2"
|
||||
rasn-smi = "0.26.2"
|
||||
rasn-snmp = "0.26.2"
|
||||
regex = "1.11.1"
|
||||
serde = { version = "1.0.219", features = ["derive"] }
|
||||
serde_json = "1.0.140"
|
||||
lalrpop-util = { version = "0.22.1", features = ["lexer"] }
|
||||
|
@ -1,3 +1,4 @@
|
||||
use log::{debug, info, trace};
|
||||
use snmp::SnmpResult;
|
||||
use std::str;
|
||||
|
||||
@ -232,20 +233,21 @@ impl<'input> Expr<'input> {
|
||||
Expr::Number(n) => ExprResult::Scalar(*n),
|
||||
Expr::Id(key) => {
|
||||
let k = str::from_utf8(key).unwrap();
|
||||
println!("Evaluation of Id '{}'", k);
|
||||
for result in collect {
|
||||
let item = &result.items[k];
|
||||
match item {
|
||||
ExprResult::Vector(n) => {
|
||||
if n.len() == 1 {
|
||||
println!("value {}", n[0]);
|
||||
return ExprResult::Scalar(n[0]);
|
||||
} else {
|
||||
println!("value {:?}", n);
|
||||
return ExprResult::Vector(n.clone());
|
||||
match result.items.get(k) {
|
||||
Some(item) => match item {
|
||||
ExprResult::Vector(n) => {
|
||||
if n.len() == 1 {
|
||||
info!("ID '{}' has value {}", k, n[0]);
|
||||
return ExprResult::Scalar(n[0]);
|
||||
} else {
|
||||
info!("ID '{}' has value {:?}", k, n);
|
||||
return ExprResult::Vector(n.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => panic!("Should be a number"),
|
||||
_ => panic!("Should be a number"),
|
||||
},
|
||||
None => continue,
|
||||
}
|
||||
}
|
||||
ExprResult::Scalar(0.0)
|
||||
|
@ -1,4 +1,4 @@
|
||||
use log::debug;
|
||||
use log::{debug, error, trace};
|
||||
use std::str;
|
||||
|
||||
pub type Spanned<Tok, Loc, Error> = Result<(Loc, Tok, Loc), Error>;
|
||||
@ -54,7 +54,7 @@ impl<'input> Lexer<'input> {
|
||||
end = chars.len();
|
||||
}
|
||||
|
||||
debug!(
|
||||
trace!(
|
||||
"Token Number from {} to {} with value '{}'",
|
||||
start,
|
||||
end,
|
||||
@ -83,7 +83,7 @@ impl<'input> Lexer<'input> {
|
||||
if !done {
|
||||
end = chars.len();
|
||||
}
|
||||
debug!(
|
||||
trace!(
|
||||
"Token Identifier from {} to {} with value '{}'",
|
||||
start,
|
||||
end,
|
||||
@ -119,12 +119,12 @@ impl<'input> Iterator for Lexer<'input> {
|
||||
}
|
||||
b'(' => {
|
||||
self.offset = i + 1;
|
||||
debug!("Token LParen at {}", i);
|
||||
trace!("Token LParen at {}", i);
|
||||
return Some(Ok((i, Tok::LParen, i + 1)));
|
||||
}
|
||||
b')' => {
|
||||
self.offset = i + 1;
|
||||
debug!("Token RParen at {}", i);
|
||||
trace!("Token RParen at {}", i);
|
||||
return Some(Ok((i, Tok::RParen, i + 1)));
|
||||
}
|
||||
b'{' => {
|
||||
@ -144,7 +144,7 @@ impl<'input> Iterator for Lexer<'input> {
|
||||
}
|
||||
_ => {
|
||||
// Unknown character
|
||||
debug!("Unknown character at {}: '{}'", i, *c as char);
|
||||
error!("Unknown character at {}: '{}'", i, *c as char);
|
||||
self.offset = i + 1;
|
||||
return Some(Err(LexicalError::NotPossible));
|
||||
}
|
||||
@ -158,8 +158,13 @@ impl<'input> Iterator for Lexer<'input> {
|
||||
mod Test {
|
||||
use super::*;
|
||||
|
||||
fn init() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lexer_num_id_num() {
|
||||
init();
|
||||
let input = "123 abc 456";
|
||||
let mut lexer = Lexer::new(input);
|
||||
assert_eq!(lexer.next(), Some(Ok((0, Tok::Num(123_f64), 3))));
|
||||
@ -170,6 +175,7 @@ mod Test {
|
||||
|
||||
#[test]
|
||||
fn test_lexer_id_num_id() {
|
||||
init();
|
||||
let input = "abc 123 def";
|
||||
let mut lexer = Lexer::new(input);
|
||||
assert_eq!(lexer.next(), Some(Ok((0, Tok::Id(b"abc"), 3))));
|
||||
@ -179,6 +185,7 @@ mod Test {
|
||||
|
||||
#[test]
|
||||
fn test_lexer_num_op() {
|
||||
init();
|
||||
let input = "1+2*3";
|
||||
let mut lexer = Lexer::new(input);
|
||||
assert_eq!(lexer.next(), Some(Ok((0, Tok::Num(1_f64), 1))));
|
||||
|
@ -4,6 +4,8 @@ pub mod lexer;
|
||||
use self::ast::ExprResult;
|
||||
use self::lexer::{LexicalError, Tok};
|
||||
use lalrpop_util::{lalrpop_mod, ParseError};
|
||||
use log::{trace, debug};
|
||||
use regex::Regex;
|
||||
use serde::Deserialize;
|
||||
use snmp::SnmpResult;
|
||||
|
||||
@ -44,6 +46,7 @@ impl<'a> Parser<'a> {
|
||||
&self,
|
||||
expr: &'a str,
|
||||
) -> Result<ExprResult, ParseError<usize, Tok<'a>, LexicalError>> {
|
||||
debug!("Parsing expression: {}", expr);
|
||||
let lexer = lexer::Lexer::new(expr);
|
||||
let res = self.parser.parse(lexer);
|
||||
match res {
|
||||
@ -54,14 +57,68 @@ impl<'a> Parser<'a> {
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn eval_str(
|
||||
&self,
|
||||
expr: &'a str,
|
||||
) -> Result<ExprResult, ParseError<usize, Tok<'a>, LexicalError>> {
|
||||
let re = Regex::new(r"\{[a-zA-Z_][a-zA-Z0-9_.]*\}").unwrap();
|
||||
let mut suffix = expr;
|
||||
let mut result: ExprResult = ExprResult::StrVector(vec![]);
|
||||
loop {
|
||||
let found = re.find(suffix);
|
||||
if let Some(m) = found {
|
||||
let start = m.start();
|
||||
let end = m.end();
|
||||
debug!(
|
||||
"Identifier '{}' found in expr '{}'",
|
||||
&expr[start + 1..end - 1],
|
||||
expr
|
||||
);
|
||||
let prefix = &expr[0..start];
|
||||
suffix = &expr[end..];
|
||||
let mut result = vec![];
|
||||
for snmp_result in self.collect {
|
||||
if let Some(v) = snmp_result.items.get(&expr[start + 1..end - 1]) {
|
||||
result = join_str_expr(prefix, v);
|
||||
break;
|
||||
}
|
||||
}
|
||||
trace!("Result string {:?}", result);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
fn join_str_expr(prefix: &str, v: &ExprResult) -> Vec<String> {
|
||||
match v {
|
||||
ExprResult::StrVector(v) => {
|
||||
let mut result = vec![];
|
||||
for item in v {
|
||||
result.push(format!("{}{}", prefix, item));
|
||||
}
|
||||
result
|
||||
}
|
||||
_ => panic!("Expected a string vector"),
|
||||
}
|
||||
}
|
||||
|
||||
mod Test {
|
||||
use super::*;
|
||||
use log::info;
|
||||
use std::collections::HashMap;
|
||||
|
||||
fn init() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn term() {
|
||||
init();
|
||||
info!("test term");
|
||||
let lexer = lexer::Lexer::new("123");
|
||||
let res = grammar::ExprParser::new().parse(lexer);
|
||||
assert!(res.is_ok());
|
||||
@ -80,6 +137,7 @@ mod Test {
|
||||
|
||||
#[test]
|
||||
fn sum() {
|
||||
init();
|
||||
let lexer = lexer::Lexer::new("1 + 2");
|
||||
let res = grammar::ExprParser::new().parse(lexer);
|
||||
assert!(res.is_ok());
|
||||
@ -129,6 +187,7 @@ mod Test {
|
||||
|
||||
#[test]
|
||||
fn product() {
|
||||
init();
|
||||
let lexer = lexer::Lexer::new("2 * 3");
|
||||
let res = grammar::ExprParser::new().parse(lexer);
|
||||
assert!(res.is_ok());
|
||||
@ -180,6 +239,7 @@ mod Test {
|
||||
|
||||
#[test]
|
||||
fn sum_product() {
|
||||
init();
|
||||
let lexer = lexer::Lexer::new("1 + (3 + 2 * 3) / 3");
|
||||
let res = grammar::ExprParser::new().parse(lexer);
|
||||
assert!(res.is_ok());
|
||||
@ -193,6 +253,7 @@ mod Test {
|
||||
|
||||
#[test]
|
||||
fn identifier() {
|
||||
init();
|
||||
let lexer = lexer::Lexer::new("{abc} + 1");
|
||||
let res = grammar::ExprParser::new().parse(lexer);
|
||||
assert!(res.is_ok());
|
||||
@ -212,6 +273,7 @@ mod Test {
|
||||
|
||||
#[test]
|
||||
fn two_identifiers() {
|
||||
init();
|
||||
let lexer = lexer::Lexer::new("100 * (1 - {free}/{total})");
|
||||
let res = grammar::ExprParser::new().parse(lexer);
|
||||
assert!(res.is_ok());
|
||||
@ -229,6 +291,7 @@ mod Test {
|
||||
|
||||
#[test]
|
||||
fn function() {
|
||||
init();
|
||||
let lexer = lexer::Lexer::new("Average({abc})");
|
||||
let res = grammar::ExprParser::new().parse(lexer);
|
||||
assert!(res.is_ok());
|
||||
@ -243,4 +306,34 @@ mod Test {
|
||||
_ => panic!("Expected a scalar value"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn identifier_str() {
|
||||
init();
|
||||
let items = HashMap::from([
|
||||
(
|
||||
"free".to_string(),
|
||||
ExprResult::StrVector(vec!["free-one".to_string(), "free-two".to_string()]),
|
||||
),
|
||||
(
|
||||
"total".to_string(),
|
||||
ExprResult::StrVector(vec!["total-one".to_string(), "total-two".to_string()]),
|
||||
),
|
||||
]);
|
||||
let collect = vec![SnmpResult::new(items)];
|
||||
let parser = Parser::new(&collect);
|
||||
let res = parser.eval_str("{free}foo{total}bar");
|
||||
assert!(res.is_ok());
|
||||
let res = res.unwrap();
|
||||
match res {
|
||||
ExprResult::StrVector(v) => {
|
||||
assert_eq!(v.len(), 4);
|
||||
assert_eq!(v[0], "free-onefoo");
|
||||
assert_eq!(v[1], "free-twofoo");
|
||||
assert_eq!(v[2], "total-onebar");
|
||||
assert_eq!(v[3], "total-twobar");
|
||||
}
|
||||
_ => panic!("Expected a string vector"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,12 @@ extern crate serde;
|
||||
extern crate serde_json;
|
||||
|
||||
use compute::{ast::ExprResult, Compute, Parser};
|
||||
use log::{debug, trace};
|
||||
use serde::Deserialize;
|
||||
use snmp::{snmp_bulk_get, snmp_bulk_walk, snmp_bulk_walk_with_labels};
|
||||
use std::collections::HashMap;
|
||||
use std::{collections::HashMap, ops::IndexMut};
|
||||
|
||||
use crate::snmp::SnmpResult;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Perfdata {
|
||||
@ -142,22 +145,23 @@ impl Command {
|
||||
let r = snmp_bulk_get(target, version, community, 1, 1, &to_get, &get_name);
|
||||
collect.push(r);
|
||||
}
|
||||
println!("{:#?}", collect);
|
||||
|
||||
let mut idx: u32 = 0;
|
||||
let mut metrics = vec![];
|
||||
let mut my_res = SnmpResult::new(HashMap::new());
|
||||
for metric in self.compute.metrics.iter() {
|
||||
let value = &metric.value;
|
||||
let min = metric.min;
|
||||
let max = metric.max;
|
||||
let parser = Parser::new(&collect);
|
||||
let value = parser.eval(value).unwrap();
|
||||
println!("ExprResult: {:?}", value);
|
||||
match value {
|
||||
|
||||
match &value {
|
||||
ExprResult::Vector(v) => {
|
||||
for item in v {
|
||||
let name = match &metric.prefix {
|
||||
Some(prefix) => {
|
||||
let name_resolved = parser.eval_str(prefix).unwrap();
|
||||
format!("{:?}#{}", prefix, metric.name)
|
||||
}
|
||||
None => {
|
||||
@ -168,10 +172,11 @@ impl Command {
|
||||
};
|
||||
let m = Perfdata {
|
||||
name,
|
||||
value: item,
|
||||
value: *item,
|
||||
min,
|
||||
max,
|
||||
};
|
||||
trace!("New metric '{}' with value {:?}", m.name, m.value);
|
||||
metrics.push(m);
|
||||
}
|
||||
}
|
||||
@ -188,16 +193,20 @@ impl Command {
|
||||
};
|
||||
let m = Perfdata {
|
||||
name,
|
||||
value: s,
|
||||
value: *s,
|
||||
min,
|
||||
max,
|
||||
};
|
||||
trace!("New metric '{}' with value {:?}", m.name, m.value);
|
||||
metrics.push(m);
|
||||
}
|
||||
_ => panic!("Aggregation must be applied to a vector"),
|
||||
}
|
||||
println!("perfdata: {:?}", metrics);
|
||||
let key = format!("metrics.{}", metric.name);
|
||||
debug!("New ID '{}' with content: {:?}", key, value);
|
||||
my_res.items.insert(key, value);
|
||||
}
|
||||
collect.push(my_res);
|
||||
if let Some(aggregations) = self.compute.aggregations.as_ref() {
|
||||
for metric in aggregations {
|
||||
let value = &metric.value;
|
||||
@ -252,6 +261,7 @@ impl Command {
|
||||
min,
|
||||
max,
|
||||
};
|
||||
trace!("New metric '{}' with value {:?}", m.name, m.value);
|
||||
metrics.push(m);
|
||||
}
|
||||
}
|
||||
@ -263,14 +273,16 @@ impl Command {
|
||||
min,
|
||||
max,
|
||||
};
|
||||
trace!("New metric '{}' with value {:?}", m.name, m.value);
|
||||
metrics.push(m);
|
||||
}
|
||||
_ => panic!("Aggregation must be applied to a vector"),
|
||||
}
|
||||
println!("perfdata: {:?}", metrics);
|
||||
}
|
||||
}
|
||||
|
||||
trace!("collect: {:#?}", collect);
|
||||
println!("metrics: {:#?}", metrics);
|
||||
CmdResult {
|
||||
status: Status::Unknown,
|
||||
output: "No result".to_string(),
|
||||
|
@ -1,3 +1,4 @@
|
||||
extern crate env_logger;
|
||||
extern crate lalrpop_util;
|
||||
extern crate lexopt;
|
||||
extern crate log;
|
||||
@ -14,8 +15,8 @@ mod snmp;
|
||||
|
||||
use generic::Command;
|
||||
use lalrpop_util::lalrpop_mod;
|
||||
use log::{debug, info, trace};
|
||||
use serde_json::Result;
|
||||
//use snmp::snmp_get;
|
||||
use std::fs;
|
||||
|
||||
lalrpop_mod!(grammar);
|
||||
@ -67,6 +68,8 @@ fn json_to_command(file_name: &str) -> Result<Command> {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
|
||||
use lexopt::prelude::*;
|
||||
let mut parser = lexopt::Parser::from_env();
|
||||
let mut hostname = "localhost".to_string();
|
||||
@ -78,30 +81,30 @@ fn main() {
|
||||
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();
|
||||
trace!("hostname: {:}", hostname);
|
||||
}
|
||||
Short('p') | Long("port") => {
|
||||
port = parser.value().unwrap().parse::<u16>().unwrap();
|
||||
println!("port: {}", port);
|
||||
trace!("port: {}", port);
|
||||
}
|
||||
Short('j') | Long("json") => {
|
||||
json = Some(parser.value().unwrap().into_string().unwrap());
|
||||
println!("json: {:?}", json);
|
||||
trace!("json: {:?}", json);
|
||||
}
|
||||
Short('v') | Long("snmp-version") => {
|
||||
snmp_version = parser.value().unwrap().into_string().unwrap();
|
||||
println!("snmp_version: {}", snmp_version);
|
||||
trace!("snmp_version: {}", snmp_version);
|
||||
}
|
||||
Short('c') | Long("snmp-community") => {
|
||||
snmp_community = parser.value().unwrap().into_string().unwrap();
|
||||
println!("snmp_community: {}", snmp_community);
|
||||
trace!("snmp_community: {}", snmp_community);
|
||||
}
|
||||
_ => {
|
||||
println!("other");
|
||||
debug!("other unknown argument");
|
||||
}
|
||||
},
|
||||
None => {
|
||||
|
Loading…
x
Reference in New Issue
Block a user