diff --git a/src/main.rs b/src/main.rs index 28486215a0799372d969f4fe7f32ae6df785be09..db3cb19caf27d466faf3f0a4ad972d274edd6539 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,13 +1,10 @@ -use lettre::message::header::ContentType; -use lettre::transport::smtp::authentication::Credentials; -use lettre::{Message, SmtpTransport, Transport}; +use core::time; use ssh::GetSshSession; -use ssh2::Session; -use std::net::TcpStream; +use std::thread; use std::{fs::File, io::Read}; -use struct_set::MailAgent; +use struct_set::{MailAgent, WarningMsg}; -mod metrics{ +mod metrics { pub mod disk; } mod ssh; @@ -21,19 +18,27 @@ fn main() { let mail_agent = MailAgent::new(&config); - for moniter_target in config.target_list { - let session = GetSshSession( - &moniter_target.ip, - &moniter_target.user, - &moniter_target.password, - ).unwrap(); + loop { + let mut warning_vec = Vec::::new(); - metrics::disk::disk_checker(&session); + for moniter_target in &config.target_list { + let session = GetSshSession( + &moniter_target.ip, + &moniter_target.user, + &moniter_target.password, + ) + .unwrap(); - if (false) { + // check and add server issue(warning) + warning_vec = metrics::disk::disk_checker(&session, warning_vec); + } + if !warning_vec.is_empty() { + // warning_vec의 데이터를 모두 가공해서 string화 시켜서 string에 concat 하기 let _ = mail_agent .clone() - .send(moniter_target.ip, "내용".to_string()); + .send("Disk Warnning report".to_string(), "내용".to_string()); } + + thread::sleep(time::Duration::from_secs(60)); } -} \ No newline at end of file +} diff --git a/src/metrics/disk.rs b/src/metrics/disk.rs index 1d03e55d7f2a7eee4263ec4120aaadd993da065c..4a7e52b5e62aca00b4ea0aa3eb86946dbb325066 100644 --- a/src/metrics/disk.rs +++ b/src/metrics/disk.rs @@ -1,12 +1,66 @@ use std::io::Read; +use crate::struct_set::WarningMsg; use ssh2::Session; +use std::str::FromStr; -pub fn disk_checker(sess: &Session) { +#[derive(Debug)] +struct DfResultInfo { + filesystem: String, + size: u64, + used: u64, + available: u64, + use_percentage: String, + mounted_on: String, +} + +impl FromStr for DfResultInfo { + type Err = String; + + fn from_str(line: &str) -> Result { + let parts: Vec<&str> = line.split_whitespace().collect(); + + if parts.len() != 6 { + return Err("Line does not have exactly 6 columns".to_string()); + } + + Ok(DfResultInfo { + filesystem: parts[0].to_string(), + size: parts[1] + .parse() + .map_err(|_| "Invalid size value".to_string())?, + used: parts[2] + .parse() + .map_err(|_| "Invalid used value".to_string())?, + available: parts[3] + .parse() + .map_err(|_| "Invalid available value".to_string())?, + use_percentage: parts[4].to_string(), + mounted_on: parts[5].to_string(), + }) + } +} + +pub fn disk_checker(sess: &Session, warning_vec: Vec) -> Vec { let mut channel = sess.channel_session().unwrap(); channel.exec("df --total | tail -n +2").unwrap(); - let mut result = String::new(); - channel.read_to_string(&mut result).unwrap(); - println!("{}", result); //이제 이걸 가공하면 되는데 - channel.wait_close(); + let mut df_result = String::new(); + channel.read_to_string(&mut df_result).unwrap(); + + let mut df_result_infos: Vec = Vec::new(); + for line in df_result.lines() { + match line.parse::() { + Ok(info) => df_result_infos.push(info), + Err(e) => println!("Failed to parse line: {}, error: {}", line, e), + } + } + + println!("{:?}", df_result_infos); // todo: 이제 이걸 가공하면 되는데 가공해서 일정수치 넘으면 warning_vec 에 넣기 + for df_result_info in df_result_infos { + df_result_info.use_percentage // todo : string percentage 조건을 걸고 삭제 + } + + let _ = channel.wait_close(); + + return warning_vec; } diff --git a/src/struct_set.rs b/src/struct_set.rs index 31cb6152c5eb7da55178425bda3d1e6580221c58..8ba8e5dad74ad1372b1518f76193e01e22b3b1f4 100644 --- a/src/struct_set.rs +++ b/src/struct_set.rs @@ -8,6 +8,18 @@ use lettre::Transport; use lettre::{message::header::Subject, transport::smtp::authentication::Credentials}; use serde::{Deserialize, Serialize}; +pub enum WarningType { + DiskFull, + CpuUseageHigh, + MemUseageHigh, +} + +pub(crate) struct WarningMsg { + war_type: WarningType, + target: ServerInfo, + msg: String, +} + #[derive(Serialize, Deserialize, Debug, Clone)] pub struct ServerInfo { pub ip: String,