enh(generic-snmp): the best version to work with new-disk.json

We have to rewrite the plugin to work also with others json files.
This commit is contained in:
David Boucher 2025-04-09 00:50:11 +02:00
parent 1e69310f40
commit 65f386159b
5 changed files with 517 additions and 421 deletions

View File

@ -18,7 +18,7 @@
"metrics": [ "metrics": [
{ {
"prefix": "{disk.label}", // par défaut "{idx}" "prefix": "{disk.label}", // par défaut "{idx}"
"name": "disk.usage.percent", "name": "disk.usage.percent", // le nom final est `prefix`#`name`
"value": "100 * {disk.used} / {disk.size}", "value": "100 * {disk.used} / {disk.size}",
"uom": "%", // optional "uom": "%", // optional
"min": 0, // optional "min": 0, // optional

View File

@ -0,0 +1,17 @@
use serde::Deserialize;
#[derive(Deserialize, Debug)]
pub struct Metric {
pub name: String,
pub prefix: Option<String>,
value: String,
uom: Option<String>,
min: Option<f32>,
max: Option<f32>,
}
#[derive(Deserialize, Debug)]
pub struct Compute {
pub metrics: Vec<Metric>,
pub aggregations: Option<Vec<Metric>>,
}

View File

@ -1,10 +1,11 @@
extern crate serde; extern crate serde;
extern crate serde_json; extern crate serde_json;
use compute::Compute;
use serde::Deserialize; use serde::Deserialize;
use snmp::{snmp_bulk_get, snmp_bulk_walk, SnmpResult, SnmpValue}; use snmp::{snmp_bulk_get, snmp_bulk_walk, snmp_bulk_walk_with_labels, SnmpResult, SnmpValue};
use std::collections::BTreeMap; use std::collections::{BTreeMap, HashMap};
#[derive(Copy, Clone, PartialEq)] #[derive(Copy, Clone, PartialEq)]
pub enum Status { pub enum Status {
@ -51,21 +52,6 @@ enum QueryType {
Walk, Walk,
} }
#[derive(Deserialize, Debug)]
struct Metric {
name: String,
value: String,
uom: Option<String>,
min: Option<f32>,
max: Option<f32>,
}
#[derive(Deserialize, Debug)]
pub struct Compute {
metrics: Vec<Metric>,
aggregations: Option<Vec<Metric>>,
}
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
pub struct Snmp { pub struct Snmp {
name: String, name: String,
@ -182,29 +168,36 @@ impl Command {
community: &str, community: &str,
//ext: &CommandExt, //ext: &CommandExt,
) -> CmdResult { ) -> CmdResult {
let mut res: BTreeMap<String, i64> = BTreeMap::new();
let mut to_get = Vec::new(); let mut to_get = Vec::new();
let mut get_name = Vec::new(); let mut get_name = Vec::new();
let mut collect = Vec::new();
for s in self.collect.snmp.iter() { for s in self.collect.snmp.iter() {
match s.query { match s.query {
QueryType::Walk => { QueryType::Walk => {
let r = snmp_bulk_walk(target, version, community, &s.oid); if let Some(lab) = &s.labels {
match r.variables.len() { let r = snmp_bulk_walk_with_labels(
1 => { target, version, community, &s.oid, &s.name, &lab,
let result = r.variables.get(0).unwrap(); );
if let SnmpValue::Integer(v) = result.value { collect.push(r);
res.insert(s.name.clone(), v); } else {
} let r = snmp_bulk_walk(target, version, community, &s.oid);
}
_ => {
for (idx, result) in r.variables.iter().enumerate() {
if let SnmpValue::Integer(v) = result.value {
res.insert(format!("{}_{}", &s.name, idx), v);
}
}
}
} }
// match r.variables.len() {
// 1 => {
// let result = r.variables.get(0).unwrap();
// if let SnmpValue::Integer(v) = result.value {
// res.insert(s.name.clone(), v);
// }
// }
// _ => {
// for (idx, result) in r.variables.iter().enumerate() {
// if let SnmpValue::Integer(v) = result.value {
// res.insert(format!("{}_{}", &s.name, idx), v);
// }
// }
// }
// }
} }
QueryType::Get => { QueryType::Get => {
to_get.push(s.oid.as_str()); to_get.push(s.oid.as_str());
@ -212,15 +205,24 @@ impl Command {
} }
} }
} }
if !to_get.is_empty() { println!("{:#?}", collect);
let r = snmp_bulk_get(target, version, community, 1, 1, &to_get); //let mut variables = HashMap::new();
for (idx, result) in r.variables.iter().enumerate() { //for res in collect.iter_mut() {
if let SnmpValue::Integer(v) = result.value { // variables.extend(res.get_variables());
res.insert(get_name[idx].to_string(), v); //}
}
} for metric in &self.compute.metrics {
if let Some(prefix) = &metric.prefix {}
}
if !to_get.is_empty() {
// let r = snmp_bulk_get(target, version, community, 1, 1, &to_get);
// for (idx, result) in r.variables.iter().enumerate() {
// if let SnmpValue::Integer(v) = result.value {
// res.insert(get_name[idx].to_string(), v);
// }
// }
} }
println!("Result variables: {:?}", res);
// let mut aggregation = ("", 0, Operation::None); // let mut aggregation = ("", 0, Operation::None);
// let mut res: Option<(&str, SnmpResult)> = None; // let mut res: Option<(&str, SnmpResult)> = None;
// for (idx, entry) in self.leaf.entries.iter().enumerate() { // for (idx, entry) in self.leaf.entries.iter().enumerate() {

View File

@ -8,14 +8,14 @@ extern crate regex;
extern crate serde; extern crate serde;
extern crate serde_json; extern crate serde_json;
mod compute;
mod generic; mod generic;
mod snmp; mod snmp;
use generic::{Command, CommandExt}; use generic::{Command, CommandExt};
use lalrpop_util::lalrpop_mod; use lalrpop_util::lalrpop_mod;
use serde_json::Result; use serde_json::Result;
use snmp::r_snmp_get; //use snmp::snmp_get;
use std::ffi::{OsStr, OsString};
use std::fs; use std::fs;
lalrpop_mod!(grammar); lalrpop_mod!(grammar);

View File

@ -11,22 +11,42 @@ use rasn_snmp::v2::VarBindValue;
use rasn_snmp::v2::{BulkPdu, Pdu}; use rasn_snmp::v2::{BulkPdu, Pdu};
use rasn_snmp::v2::{GetBulkRequest, GetNextRequest, GetRequest}; use rasn_snmp::v2::{GetBulkRequest, GetNextRequest, GetRequest};
use rasn_snmp::v2c::Message; use rasn_snmp::v2c::Message;
use std::collections::BTreeMap; use std::collections::{BTreeMap, HashMap};
use std::convert::TryInto; use std::convert::TryInto;
use std::net::UdpSocket; use std::net::UdpSocket;
#[derive(Debug, PartialEq)] pub enum ValueType {
pub struct SnmpSubResult<'a> { None(()),
pub label: &'a str, Integer(i64),
pub value: &'a str, Float(f32),
pub variables: Vec<SnmpVariable>, String(String),
} }
#[derive(Debug, PartialEq)] #[derive(Debug)]
pub struct SnmpResult<'a> { pub enum SnmpItem {
pub labels: Vec<SnmpSubResult<'a>>, Nbr(Vec<f32>),
Str(Vec<String>),
} }
#[derive(Debug)]
pub struct SnmpResult {
items: BTreeMap<String, SnmpItem>,
last_oid: Vec<u32>,
}
//#[derive(Debug, PartialEq)]
//pub struct SnmpSubResult<'a> {
// pub label: &'a str,
// pub value: &'a str,
// pub variables: Vec<SnmpVariable>,
//}
//#[derive(Debug, PartialEq)]
//pub struct SnmpResult<'a> {
// pub labels: Vec<SnmpSubResult<'a>>,
// last_oid: Vec<u32>,
//}
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum SnmpValue { pub enum SnmpValue {
Integer(i64), Integer(i64),
@ -39,58 +59,79 @@ pub struct SnmpVariable {
pub value: SnmpValue, pub value: SnmpValue,
} }
impl SnmpVariable { //impl<'a> SnmpResult<'a> {
fn new(name: String, value: SnmpValue) -> SnmpVariable { // fn new(labels: &'a BTreeMap<String, String>) -> SnmpResult<'a> {
SnmpVariable { name, value } // let mut retval: Vec<SnmpSubResult> = Vec::new();
} // retval.reserve(labels.len());
} // for (label, value) in labels.iter() {
// let item = SnmpSubResult {
impl<'a> SnmpResult<'a> { // label: &label,
fn new(labels: &'a BTreeMap<String, String>) -> SnmpResult<'a> { // value: &value,
let mut retval: Vec<SnmpSubResult> = Vec::new(); // variables: Vec::new(),
retval.reserve(labels.len()); // };
for (label, value) in labels.iter() { // retval.push(item);
let item = SnmpSubResult { // }
label: &label, // SnmpResult {
value: &value, // labels: retval,
variables: Vec::new(), // last_oid: Vec::new(),
}; // }
retval.push(item); // }
} //
SnmpResult { labels: retval } // fn new_simple() -> SnmpResult<'a> {
} // let label = SnmpSubResult {
// label: "",
fn new_simple() -> SnmpResult<'a> { // value: "",
let label = SnmpSubResult{label: "", value: "", variables: Vec::new() }; // variables: Vec::new(),
SnmpResult { labels: vec![label], } // };
} // SnmpResult {
// labels: vec![label],
fn add_variable(&mut self, idx: usize, name: String, value: SnmpValue) { // last_oid: Vec::new(),
self.labels[idx].variables.push(SnmpVariable::new(name, value)); // }
} // }
//
fn get_last_oid(&self, idx: usize) -> &str { // fn add_variable(&mut self, idx: usize, name: String, value: SnmpValue) {
if self.labels.is_empty() { // self.labels[idx]
return ""; // .variables
} // .push(SnmpVariable { name, value });
let last = self.labels[idx].variables.iter().last().unwrap(); // }
if last.name.is_empty() { //
return ""; // fn get_last_oid(&self, idx: usize) -> &str {
} // if self.labels.is_empty() {
last.name.as_str() // return "";
} // }
// let last = self.labels[idx].variables.iter().last().unwrap();
fn concat(&mut self, mut other: SnmpResult) { // if last.name.is_empty() {
for v in other.labels.iter_mut() { // return "";
for vv in self.labels.iter_mut() { // }
if v.label == vv.label { // last.name.as_str()
vv.variables.extend(v.variables); // }
break; //
} // fn merge(&mut self, mut other: SnmpResult) {
} // for v in other.labels.iter_mut() {
} // for vv in self.labels.iter_mut() {
} // if v.label == vv.label {
} // while !v.variables.is_empty() {
// let last = v.variables.pop().unwrap();
// vv.variables.push(last);
// }
// break;
// }
// }
// }
// self.last_oid = other.last_oid;
// }
//
// pub fn get_variables(&self) -> HashMap<String, SnmpValue> {
// let retval = HashMap::new();
// // for r in self.labels.iter() {
// // for s in r.variables.iter() {
// // let name = format!("{}.{}", self.name, r.label, s.label);
// // retval.insert(name, s.value);
// // }
// // }
// retval
// }
//}
//pub fn snmp_get(target: &str, oid: &str, community: &str) -> SnmpResult { //pub fn snmp_get(target: &str, oid: &str, community: &str) -> SnmpResult {
// let oid_tab = oid // let oid_tab = oid
@ -196,7 +237,7 @@ impl<'a> SnmpResult<'a> {
// } // }
// message = create_next_request(request_id, &resp_oid); // message = create_next_request(request_id, &resp_oid);
// } // }
// retval.concat(build_response(decoded, &oid, true).0); // retval.merge(build_response(decoded, &oid, true).0);
// request_id += 1; // request_id += 1;
// } // }
// retval // retval
@ -218,69 +259,72 @@ impl<'a> SnmpResult<'a> {
/// use snmp_rust::r_snmp_bulk_get; /// use snmp_rust::r_snmp_bulk_get;
/// let result = snmp_bulk_get("127.0.0.1:161", "2c", "public", "1.3.6.1.2.1.25.3.3.1.2"); /// let result = snmp_bulk_get("127.0.0.1:161", "2c", "public", "1.3.6.1.2.1.25.3.3.1.2");
/// ``` /// ```
//pub fn snmp_bulk_get( pub fn snmp_bulk_get<'a>(
// target: &str, target: &str,
// _version: &str, _version: &str,
// community: &str, community: &str,
// non_repeaters: u32, non_repeaters: u32,
// max_repetitions: u32, max_repetitions: u32,
// oid: &Vec<&str>, oid: &Vec<&str>,
//) -> SnmpResult { ) -> SnmpResult {
// let mut oids_tab = oid // let mut oids_tab = oid
// .iter() // .iter()
// .map(|x| { // .map(|x| {
// x.split('.') // x.split('.')
// .map(|x| x.parse::<u32>().unwrap()) // .map(|x| x.parse::<u32>().unwrap())
// .collect::<Vec<u32>>() // .collect::<Vec<u32>>()
// }) // })
// .collect::<Vec<Vec<u32>>>(); // .collect::<Vec<Vec<u32>>>();
// //
// let mut retval = SnmpResult::new(); let mut retval = SnmpResult {
// let mut request_id: i32 = 1; items: BTreeMap::new(),
// last_oid: Vec::new(),
// let socket = UdpSocket::bind("0.0.0.0:0").unwrap(); };
// socket.connect(target).expect("connect function failed"); // let mut request_id: i32 = 1;
// let duration = std::time::Duration::from_millis(1000); //
// socket.set_read_timeout(Some(duration)).unwrap(); // let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
// // socket.connect(target).expect("connect function failed");
// let variable_bindings = oids_tab // let duration = std::time::Duration::from_millis(1000);
// .iter() // socket.set_read_timeout(Some(duration)).unwrap();
// .map(|x| VarBind { //
// name: ObjectIdentifier::new_unchecked(x.to_vec().into()), // let variable_bindings = oids_tab
// value: VarBindValue::Unspecified, // .iter()
// }) // .map(|x| VarBind {
// .collect::<Vec<VarBind>>(); // name: ObjectIdentifier::new_unchecked(x.to_vec().into()),
// // value: VarBindValue::Unspecified,
// let pdu = BulkPdu { // })
// request_id, // .collect::<Vec<VarBind>>();
// non_repeaters, //
// max_repetitions, // let pdu = BulkPdu {
// variable_bindings, // request_id,
// }; // non_repeaters,
// // max_repetitions,
// let get_request: GetBulkRequest = GetBulkRequest(pdu); // variable_bindings,
// // };
// let message: Message<GetBulkRequest> = Message { //
// version: 1.into(), // let get_request: GetBulkRequest = GetBulkRequest(pdu);
// community: community.to_string().into(), //
// data: get_request.into(), // let message: Message<GetBulkRequest> = Message {
// }; // version: 1.into(),
// // community: community.to_string().into(),
// // Send the message through an UDP socket // data: get_request.into(),
// let encoded: Vec<u8> = rasn::der::encode(&message).unwrap(); // };
// let res: usize = socket.send(&encoded).unwrap(); //
// assert!(res == encoded.len()); // // Send the message through an UDP socket
// // let encoded: Vec<u8> = rasn::der::encode(&message).unwrap();
// let mut buf: [u8; 1024] = [0; 1024]; // let res: usize = socket.send(&encoded).unwrap();
// let resp: (usize, std::net::SocketAddr) = socket.recv_from(buf.as_mut_slice()).unwrap(); // assert!(res == encoded.len());
// //
// trace!("Received {} bytes", resp.0); // let mut buf: [u8; 1024] = [0; 1024];
// assert!(resp.0 > 0); // let resp: (usize, std::net::SocketAddr) = socket.recv_from(buf.as_mut_slice()).unwrap();
// let decoded: Message<Pdus> = rasn::ber::decode(&buf[0..resp.0]).unwrap(); //
// let (result, _completed) = build_response(decoded, "", false); // trace!("Received {} bytes", resp.0);
// retval.concat(result); // assert!(resp.0 > 0);
// retval // let decoded: Message<Pdus> = rasn::ber::decode(&buf[0..resp.0]).unwrap();
//} // let (result, _completed) = build_response(decoded, "", false);
// retval.merge(result);
retval
}
/// ///
/// Bulk walk /// Bulk walk
@ -298,88 +342,96 @@ impl<'a> SnmpResult<'a> {
/// use snmp_rust::snmp_bulk_walk; /// use snmp_rust::snmp_bulk_walk;
/// let result = snmp_bulk_walk("127.0.0.1:161", "2c", "public", "1.3.6.1.2.1.25.3.3.1.2"); /// let result = snmp_bulk_walk("127.0.0.1:161", "2c", "public", "1.3.6.1.2.1.25.3.3.1.2");
/// ``` /// ```
//pub fn snmp_bulk_walk(target: &str, _version: &str, community: &str, oid: &str) -> SnmpResult { pub fn snmp_bulk_walk<'a>(target: &str, _version: &str, community: &str, oid: &str) -> SnmpResult {
// let mut oid_tab = oid let mut oid_tab = oid
// .split('.') .split('.')
// .map(|x| x.parse::<u32>().unwrap()) .map(|x| x.parse::<u32>().unwrap())
// .collect::<Vec<u32>>(); .collect::<Vec<u32>>();
//
// let mut retval = SnmpResult::new_simple(); let mut retval = SnmpResult {
// let mut request_id: i32 = 1; items: BTreeMap::new(),
// last_oid: Vec::new(),
// let socket = UdpSocket::bind("0.0.0.0:0").unwrap(); };
// socket.connect(target).expect("connect function failed"); // let mut request_id: i32 = 1;
// let duration = std::time::Duration::from_millis(1000); //
// socket.set_read_timeout(Some(duration)).unwrap(); // let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
// // socket.connect(target).expect("connect function failed");
// loop { // let duration = std::time::Duration::from_millis(1000);
// let variable_bindings = vec![VarBind { // socket.set_read_timeout(Some(duration)).unwrap();
// name: ObjectIdentifier::new_unchecked(oid_tab.to_vec().into()), //
// value: VarBindValue::Unspecified, // loop {
// }]; // let variable_bindings = vec![VarBind {
// // name: ObjectIdentifier::new_unchecked(oid_tab.to_vec().into()),
// let pdu = BulkPdu { // value: VarBindValue::Unspecified,
// request_id, // }];
// non_repeaters: 0, //
// max_repetitions: 10, // let pdu = BulkPdu {
// variable_bindings, // request_id,
// }; // non_repeaters: 0,
// // max_repetitions: 10,
// let get_request: GetBulkRequest = GetBulkRequest(pdu); // variable_bindings,
// // };
// let message: Message<GetBulkRequest> = Message { //
// version: 1.into(), // let get_request: GetBulkRequest = GetBulkRequest(pdu);
// community: community.to_string().into(), //
// data: get_request.into(), // let message: Message<GetBulkRequest> = Message {
// }; // version: 1.into(),
// // community: community.to_string().into(),
// // Send the message through an UDP socket // data: get_request.into(),
// let encoded: Vec<u8> = rasn::der::encode(&message).unwrap(); // };
// let res: usize = socket.send(&encoded).unwrap(); //
// assert!(res == encoded.len()); // // Send the message through an UDP socket
// // let encoded: Vec<u8> = rasn::der::encode(&message).unwrap();
// let mut buf: [u8; 1024] = [0; 1024]; // let res: usize = socket.send(&encoded).unwrap();
// let resp: (usize, std::net::SocketAddr) = socket.recv_from(buf.as_mut_slice()).unwrap(); // assert!(res == encoded.len());
// //
// trace!("Received {} bytes", resp.0); // let mut buf: [u8; 1024] = [0; 1024];
// assert!(resp.0 > 0); // let resp: (usize, std::net::SocketAddr) = socket.recv_from(buf.as_mut_slice()).unwrap();
// let decoded: Message<Pdus> = rasn::ber::decode(&buf[0..resp.0]).unwrap(); //
// if let Pdus::Response(resp) = &decoded.data { // trace!("Received {} bytes", resp.0);
// let resp_oid = &resp.0.variable_bindings[0].name; // assert!(resp.0 > 0);
// let n = resp_oid.len() - 1; // let decoded: Message<Pdus> = rasn::ber::decode(&buf[0..resp.0]).unwrap();
// } // if let Pdus::Response(resp) = &decoded.data {
// let (result, completed) = build_response(decoded, &oid, true); // let resp_oid = &resp.0.variable_bindings[0].name;
// retval.concat(result); // let n = resp_oid.len() - 1;
// if completed { // }
// break; // let (result, completed) = build_response(decoded, &oid, true);
// } // retval.merge(result);
// if !retval.variables.is_empty() { // if completed {
// oid_tab = retval // break;
// .variables // }
// .last() // if !retval.variables.is_empty() {
// .unwrap() // oid_tab = retval
// .name // .variables
// .split('.') // .last()
// .map(|x| x.parse::<u32>().unwrap()) // .unwrap()
// .collect::<Vec<u32>>(); // .name
// } // .split('.')
// } // .map(|x| x.parse::<u32>().unwrap())
// retval // .collect::<Vec<u32>>();
//} // }
// }
retval
}
pub fn snmp_bulk_walk_with_labels<'a>( pub fn snmp_bulk_walk_with_labels<'a>(
target: &str, target: &str,
_version: &str, _version: &str,
community: &str, community: &str,
oid: &str, oid: &str,
snmp_name: &str,
labels: &'a BTreeMap<String, String>, labels: &'a BTreeMap<String, String>,
) -> SnmpResult<'a> { ) -> SnmpResult {
let mut oid_tab = oid let oid_init = oid
.split('.') .split('.')
.map(|x| x.parse::<u32>().unwrap()) .map(|x| x.parse::<u32>().unwrap())
.collect::<Vec<u32>>(); .collect::<Vec<u32>>();
let mut retval = SnmpResult::new(&labels); let mut oid_tab = &oid_init;
let mut retval = SnmpResult {
items: BTreeMap::new(),
last_oid: Vec::new(),
};
let request_id: i32 = 1; let request_id: i32 = 1;
let socket = UdpSocket::bind("0.0.0.0:0").unwrap(); let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
@ -419,199 +471,224 @@ pub fn snmp_bulk_walk_with_labels<'a>(
trace!("Received {} bytes", resp.0); trace!("Received {} bytes", resp.0);
assert!(resp.0 > 0); assert!(resp.0 > 0);
let decoded: Message<Pdus> = rasn::ber::decode(&buf[0..resp.0]).unwrap(); let decoded: Message<Pdus> = rasn::ber::decode(&buf[0..resp.0]).unwrap();
if let Pdus::Response(resp) = &decoded.data { //if let Pdus::Response(resp) = &decoded.data {
let resp_oid = &resp.0.variable_bindings[0].name; // let resp_oid = &resp.0.variable_bindings[0].name;
let n = resp_oid.len() - 1; // let oid_tab = &resp.0.variable_bindings.last().unwrap().name;
oid_tab = resp.0.variable_bindings[n - 1].name.to_string().split('.') //}
.map(|x| x.parse::<u32>().unwrap()) let completed = retval.build_response_with_labels(decoded, &oid, snmp_name, labels, true);
.collect::<Vec<u32>>();
}
let (result, completed) = build_response_with_labels(decoded, &oid, labels, true);
retval.concat(result);
if completed { if completed {
break; break;
} }
oid_tab = &retval.last_oid;
} }
retval retval
} }
fn build_response_with_labels<'a>( impl SnmpResult {
decoded: Message<Pdus>, fn build_response_with_labels<'a>(
oid: &str, &mut self,
labels: &'a BTreeMap<String, String>, decoded: Message<Pdus>,
walk: bool, oid: &str,
) -> (SnmpResult<'a>, bool) { snmp_name: &str,
let mut retval = SnmpResult::new(labels); labels: &'a BTreeMap<String, String>,
let mut completed = false; walk: bool,
let mut last_oid: &str = ""; ) -> bool {
let mut completed = false;
if let Pdus::Response(resp) = &decoded.data { if let Pdus::Response(resp) = &decoded.data {
let vars = &resp.0.variable_bindings; let vars = &resp.0.variable_bindings;
for var in vars { for var in vars {
let name = var.name.to_string(); let name = var.name.to_string();
if walk { self.last_oid = name
if !name.starts_with(oid) { .split('.')
completed = true; .map(|x| x.parse::<u32>().unwrap())
last_oid = ""; .collect::<Vec<u32>>();
break; if walk {
if !name.starts_with(oid) {
completed = true;
break;
}
}
let prefix = &name[..name.rfind('.').unwrap()];
for l in labels {
if prefix.ends_with(l.0) {
let mut typ = ValueType::None(());
let value = match &var.value {
VarBindValue::Unspecified => {
warn!("Unspecified");
}
VarBindValue::NoSuchObject => {
warn!("NoSuchObject");
}
VarBindValue::NoSuchInstance => {
warn!("NoSuchInstance");
}
VarBindValue::EndOfMibView => {
warn!("EndOfMibView");
}
VarBindValue::Value(value) => {
warn!("Value {:?}", &value);
match value {
rasn_smi::v2::ObjectSyntax::Simple(value) => {
info!("Simple {:?}", value);
match value {
rasn_smi::v2::SimpleSyntax::Integer(value) => {
typ = ValueType::Integer(value.try_into().unwrap());
}
rasn_smi::v2::SimpleSyntax::String(value) => {
// We transform the value into a rust String
typ = ValueType::String(
String::from_utf8(value.to_vec()).unwrap(),
);
}
rasn_smi::v2::SimpleSyntax::ObjectId(value) => {
let oid: String = value
.iter()
.map(|&id| id.to_string() + ".")
.collect();
typ = ValueType::String(oid);
}
_ => {
typ = ValueType::String("Other".to_string());
}
};
}
rasn_smi::v2::ObjectSyntax::ApplicationWide(value) => {
info!("Application {:?}", value);
}
};
}
};
let key = format!("{}.{}", snmp_name, l.1);
self.items
.entry(key)
.and_modify(|e| match e {
SnmpItem::Nbr(v) => v.push(match &typ {
ValueType::Float(f) => *f,
ValueType::None(()) => {
panic!("Should not arrive");
}
ValueType::String(_) => {
panic!("Value should be a float");
}
ValueType::Integer(i) => *i as f32,
}),
SnmpItem::Str(v) => v.push(match &typ {
ValueType::Float(_) => {
panic!("Value should be a string");
}
ValueType::None(()) => {
panic!("Should not arrive");
}
ValueType::String(s) => s.to_string(),
ValueType::Integer(_) => {
panic!("Value should be a string");
}
}),
})
.or_insert(match typ {
ValueType::Float(f) => SnmpItem::Nbr(vec![f]),
ValueType::None(()) => {
panic!("Should not arrive");
}
ValueType::String(s) => SnmpItem::Str(vec![s]),
ValueType::Integer(i) => SnmpItem::Nbr(vec![i as f32]),
});
}
} }
} }
let mut idx: i32 = -1;
retval.labels.iter().enumerate().for_each(|label| {
if name.ends_with(label.1.label) {
idx = label.0 as i32;
return;
}
});
if idx == -1 {
continue;
}
match &var.value {
VarBindValue::Unspecified => {
warn!("Unspecified");
}
VarBindValue::NoSuchObject => {
warn!("NoSuchObject");
}
VarBindValue::NoSuchInstance => {
warn!("NoSuchInstance");
}
VarBindValue::EndOfMibView => {
warn!("EndOfMibView");
}
VarBindValue::Value(value) => {
warn!("Value {:?}", &value);
match value {
rasn_smi::v2::ObjectSyntax::Simple(value) => {
info!("Simple {:?}", value);
match value {
rasn_smi::v2::SimpleSyntax::Integer(value) => {
let v = value.try_into().unwrap();
retval.add_variable(idx as usize, name, SnmpValue::Integer(v));
last_oid = retval.get_last_oid(idx as usize);
}
rasn_smi::v2::SimpleSyntax::String(value) => {
// We transform the value into a rust String
retval.add_variable(
idx as usize,
name,
SnmpValue::String(
String::from_utf8(value.to_vec()).unwrap(),
),
);
last_oid = retval.get_last_oid(idx as usize);
}
rasn_smi::v2::SimpleSyntax::ObjectId(value) => {
let oid: String =
value.iter().map(|&id| id.to_string() + ".").collect();
retval.add_variable(idx as usize, name, SnmpValue::String(oid));
last_oid = retval.get_last_oid(idx as usize);
}
_ => {
retval
.add_variable(idx as usize, name, SnmpValue::String("Other".to_string()));
last_oid = retval.get_last_oid(idx as usize);
}
};
}
rasn_smi::v2::ObjectSyntax::ApplicationWide(value) => {
info!("Application {:?}", value);
}
};
}
};
} }
completed
} }
(retval, completed)
} }
fn build_response<'a>( //fn build_response<'a>(decoded: Message<Pdus>, oid: &str, walk: bool) -> (SnmpResult, bool) {
decoded: Message<Pdus>, // let mut retval = SnmpResult{items: BTreeMap::new(), last_oid: Vec::new()};
oid: &str, // let mut completed = false;
walk: bool, // let mut last_oid: &str = "";
) -> (SnmpResult<'a>, bool) { //
let mut retval = SnmpResult::new_simple(); // if let Pdus::Response(resp) = &decoded.data {
let mut completed = false; // let vars = &resp.0.variable_bindings;
let mut last_oid: &str = ""; // for var in vars {
// let name = var.name.to_string();
if let Pdus::Response(resp) = &decoded.data { // if walk {
let vars = &resp.0.variable_bindings; // if !name.starts_with(oid) {
for var in vars { // completed = true;
let name = var.name.to_string(); // last_oid = "";
if walk { // break;
if !name.starts_with(oid) { // }
completed = true; // }
last_oid = ""; // let mut idx: i32 = -1;
break; // retval.labels.iter().enumerate().for_each(|label| {
} // if name.ends_with(label.1.label) {
} // idx = label.0 as i32;
let mut idx: i32 = -1; // return;
retval.labels.iter().enumerate().for_each(|label| { // }
if name.ends_with(label.1.label) { // });
idx = label.0 as i32; // if idx == -1 {
return; // continue;
} // }
}); // match &var.value {
if idx == -1 { // VarBindValue::Unspecified => {
continue; // warn!("Unspecified");
} // }
match &var.value { // VarBindValue::NoSuchObject => {
VarBindValue::Unspecified => { // warn!("NoSuchObject");
warn!("Unspecified"); // }
} // VarBindValue::NoSuchInstance => {
VarBindValue::NoSuchObject => { // warn!("NoSuchInstance");
warn!("NoSuchObject"); // }
} // VarBindValue::EndOfMibView => {
VarBindValue::NoSuchInstance => { // warn!("EndOfMibView");
warn!("NoSuchInstance"); // }
} // VarBindValue::Value(value) => {
VarBindValue::EndOfMibView => { // warn!("Value {:?}", &value);
warn!("EndOfMibView"); // match value {
} // rasn_smi::v2::ObjectSyntax::Simple(value) => {
VarBindValue::Value(value) => { // info!("Simple {:?}", value);
warn!("Value {:?}", &value); // match value {
match value { // rasn_smi::v2::SimpleSyntax::Integer(value) => {
rasn_smi::v2::ObjectSyntax::Simple(value) => { // let v = value.try_into().unwrap();
info!("Simple {:?}", value); // retval.add_variable(idx as usize, name, SnmpValue::Integer(v));
match value { // last_oid = retval.get_last_oid(idx as usize);
rasn_smi::v2::SimpleSyntax::Integer(value) => { // }
let v = value.try_into().unwrap(); // rasn_smi::v2::SimpleSyntax::String(value) => {
retval.add_variable(idx as usize, name, SnmpValue::Integer(v)); // // We transform the value into a rust String
last_oid = retval.get_last_oid(idx as usize); // retval.add_variable(
} // idx as usize,
rasn_smi::v2::SimpleSyntax::String(value) => { // name,
// We transform the value into a rust String // SnmpValue::String(
retval.add_variable(idx as usize, // String::from_utf8(value.to_vec()).unwrap(),
name, // ),
SnmpValue::String( // );
String::from_utf8(value.to_vec()).unwrap(), // last_oid = retval.get_last_oid(idx as usize);
), // }
); // rasn_smi::v2::SimpleSyntax::ObjectId(value) => {
last_oid = retval.get_last_oid(idx as usize); // let oid: String =
} // value.iter().map(|&id| id.to_string() + ".").collect();
rasn_smi::v2::SimpleSyntax::ObjectId(value) => { // retval.add_variable(idx as usize, name, SnmpValue::String(oid));
let oid: String = // last_oid = retval.get_last_oid(idx as usize);
value.iter().map(|&id| id.to_string() + ".").collect(); // }
retval.add_variable(idx as usize, name, SnmpValue::String(oid)); // _ => {
last_oid = retval.get_last_oid(idx as usize); // retval.add_variable(
} // idx as usize,
_ => { // name,
retval // SnmpValue::String("Other".to_string()),
.add_variable(idx as usize, name, SnmpValue::String("Other".to_string())); // );
last_oid = retval.get_last_oid(idx as usize); // last_oid = retval.get_last_oid(idx as usize);
} // }
}; // };
} // }
rasn_smi::v2::ObjectSyntax::ApplicationWide(value) => { // rasn_smi::v2::ObjectSyntax::ApplicationWide(value) => {
info!("Application {:?}", value); // info!("Application {:?}", value);
} // }
}; // };
} // }
}; // };
} // }
} // }
(retval, completed) // (retval, completed)
} //}
//mod tests { //mod tests {
// use super::*; // use super::*;
// //
@ -619,9 +696,9 @@ fn build_response<'a>(
// fn test_snmp_get() { // fn test_snmp_get() {
// let result = r_snmp_get("127.0.0.1:161", "1.3.6.1.2.1.1.1.0", "public"); // let result = r_snmp_get("127.0.0.1:161", "1.3.6.1.2.1.1.1.0", "public");
// let expected = SnmpResult { // let expected = SnmpResult {
// variables: vec![SnmpVariable::new( // variables: vec![SnmpVariable{
// "1.3.6.1.2.1.1.1.0".to_string(), // "1.3.6.1.2.1.1.1.0".to_string(),
// "Linux CNTR-PORT-A104 6.1.0-31-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.128-1 (2025-02-07) x86_64".to_string())], // "Linux CNTR-PORT-A104 6.1.0-31-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.128-1 (2025-02-07) x86_64".to_string()}],
// }; // };
// assert_eq!(result, expected); // assert_eq!(result, expected);
// } // }