diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6b90db9..7ffe044 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -5,13 +5,13 @@ rust-latest: stage: build image: rust:latest script: - - cargo build --verbose - - cargo test --verbose + - cargo build --release + - cargo test rust-nightly: stage: build image: rustlang/rust:nightly script: - - cargo build --verbose - - cargo test --verbose + - cargo build --release + - cargo test allow_failure: true \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index a0a93f3..38c6863 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -814,6 +814,7 @@ dependencies = [ name = "raid_manager" version = "0.1.0" dependencies = [ + "lazy_static", "regex", "rocket", ] diff --git a/Cargo.toml b/Cargo.toml index 9b2699d..f5a8ff1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,4 +7,5 @@ edition = "2021" [dependencies] rocket = {version = "0.5.0-rc.2", features = ["json"]} -regex = "1" \ No newline at end of file +regex = "1" +lazy_static = "1.4.0" \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index ea9180f..8d15410 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,6 +13,7 @@ fn get_raid_devices() -> Json { #[rocket::main] async fn main() -> Result<(), rocket::Error> { + println!("init"); let _rocket = rocket::build() .mount("/api", routes![get_raid_devices]) .launch() diff --git a/src/mdstat_parser.rs b/src/mdstat_parser.rs index 4ae65c9..8cc7005 100644 --- a/src/mdstat_parser.rs +++ b/src/mdstat_parser.rs @@ -1,6 +1,7 @@ use std::fs; use regex::{Regex}; use rocket::serde::{Serialize}; +use lazy_static::lazy_static; #[derive(Serialize)] #[serde(crate = "rocket::serde")] @@ -33,11 +34,12 @@ pub fn parse_mdstat() -> MdRaidSystem { fn parse_mdstat_str(contents: String) -> MdRaidSystem { let mut md_raids = Vec::new(); - // todo avoid recompiling regex every time - let re = Regex::new(r"([a-z_]{2,5}[0-9]{1,3})\s:\s(active|started|faulty)\s(raid[0-9])\s((?:\s?[a-z]{1,10}[0-9]{0,2}\[[0-9]])+)").unwrap(); - let re_personalities = Regex::new(r"Personalities\s:\s((?:\s?\[(?:raid[0-9]|linear|multipath|faulty)])+)").unwrap(); + lazy_static! { + static ref RE: Regex = Regex::new(r"([a-z_]{2,5}[0-9]{1,3})\s:\s(active|started|faulty)\s(raid[0-9])\s((?:\s?[a-z]{1,10}[0-9]{0,2}\[[0-9]])+)").unwrap(); + static ref RE_PERSONALITIES: Regex = Regex::new(r"Personalities\s:\s((?:\s?\[(?:raid[0-9]|linear|multipath|faulty)])+)").unwrap(); + } - for cap in re.captures_iter(&contents) { + for cap in RE.captures_iter(&contents) { if cap.len() != 5 { // todo error handling continue @@ -45,6 +47,7 @@ fn parse_mdstat_str(contents: String) -> MdRaidSystem { let devicesplit = cap[4].split(" "); let mut devices = Vec::new(); for i in devicesplit { + let i = format!("/dev/{i}"); // remove brackets match i.split("[").next() { None => println!("no [ in device string!?"), @@ -53,7 +56,7 @@ fn parse_mdstat_str(contents: String) -> MdRaidSystem { } let raid = MdRaid { - name: cap[1].to_string(), + name: format!("/dev/{}", cap[1].to_string()), faulty: &cap[2] == "faulty", level: cap[3].to_string(), devices, @@ -63,7 +66,7 @@ fn parse_mdstat_str(contents: String) -> MdRaidSystem { } let mut supp_levels: Vec = Vec::new(); - match re_personalities.captures(&contents) { + match RE_PERSONALITIES.captures(&contents) { None => {} Some(res) => { if res.len() == 2 { @@ -102,6 +105,7 @@ unused devices: #[test] fn single_special_name() { + let exp = r#"{"raids":[{"devices":["/dev/sde1","/dev/sdf1","/dev/sdb1","/dev/sdd1","/dev/sdc1"],"faulty":false,"level":"raid5","name":"/dev/md_d0"}],"supported_levels":["raid1","raid6","raid5","raid4"]}"#; assert_eq!(json!(parse_mdstat_str(r#" Personalities : [raid1] [raid6] [raid5] [raid4] md_d0 : active raid5 sde1[0] sdf1[4] sdb1[5] sdd1[2] sdc1[1] @@ -109,11 +113,12 @@ md_d0 : active raid5 sde1[0] sdf1[4] sdb1[5] sdd1[2] sdc1[1] bitmap: 0/10 pages [0KB], 16384KB chunk unused devices: - "#.to_string())).to_string(), r#"{"raids":[{"devices":["sde1","sdf1","sdb1","sdd1","sdc1"],"faulty":false,"level":"raid5","name":"md_d0"}],"supported_levels":["raid1","raid6","raid5","raid4"]}"#); + "#.to_string())).to_string(), exp); } #[test] fn rebuilding_array() { + let exp = r#"{"raids":[{"devices":["/dev/sdh1","/dev/sdg1","/dev/sdf1","/dev/sde1","/dev/sdd1","/dev/sdc1"],"faulty":false,"level":"raid5","name":"/dev/md127"}],"supported_levels":["raid1","raid6","raid5","raid4"]}"#; assert_eq!(json!(parse_mdstat_str(r#" Personalities : [raid1] [raid6] [raid5] [raid4] md127 : active raid5 sdh1[6] sdg1[4] sdf1[3] sde1[2] sdd1[1] sdc1[0] @@ -121,12 +126,13 @@ md127 : active raid5 sdh1[6] sdg1[4] sdf1[3] sde1[2] sdd1[1] sdc1[0] [==>..................] recovery = 12.6% (37043392/292945152) finish=127.5min speed=33440K/sec unused devices: - "#.to_string())).to_string(), r#"{"raids":[{"devices":["sdh1","sdg1","sdf1","sde1","sdd1","sdc1"],"faulty":false,"level":"raid5","name":"md127"}],"supported_levels":["raid1","raid6","raid5","raid4"]}"#); + "#.to_string())).to_string(), exp); } #[test] fn test3() { + let exp = r#"{"raids":[{"devices":["/dev/sda3","/dev/sdb3"],"faulty":false,"level":"raid0","name":"/dev/md2"},{"devices":["/dev/sda2","/dev/sdb2"],"faulty":false,"level":"raid1","name":"/dev/md1"},{"devices":["/dev/sda1","/dev/sdb1"],"faulty":false,"level":"raid1","name":"/dev/md0"}],"supported_levels":["linear","raid0","raid1"]}"#; assert_eq!(json!(parse_mdstat_str(r#" Personalities : [linear] [raid0] [raid1] [raid10] [raid6] [raid5] [raid4] md2 : active raid0 sda3[0] sdb3[1] @@ -137,11 +143,12 @@ md1 : active raid1 sda2[0] sdb2[1] md0 : active raid1 sda1[0] sdb1[1] 2490176 blocks [2/2] [UU] - "#.to_string())).to_string(), r#"{"raids":[{"devices":["sda3","sdb3"],"faulty":false,"level":"raid0","name":"md2"},{"devices":["sda2","sdb2"],"faulty":false,"level":"raid1","name":"md1"},{"devices":["sda1","sdb1"],"faulty":false,"level":"raid1","name":"md0"}],"supported_levels":["linear","raid0","raid1"]}"#); + "#.to_string())).to_string(), exp); } #[test] fn lots_of_devices() { + let exp = r#"{"raids":[{"devices":["/dev/sdb2","/dev/sda2"],"faulty":false,"level":"raid1","name":"/dev/md1"},{"devices":["/dev/sdb3","/dev/sda3"],"faulty":false,"level":"raid1","name":"/dev/md2"},{"devices":["/dev/sdl1","/dev/sdk1","/dev/sdj1","/dev/sdi1","/dev/sdh1","/dev/sdg1","/dev/sdf1","/dev/sde1","/dev/sdd1","/dev/sdc1"],"faulty":false,"level":"raid5","name":"/dev/md3"},{"devices":["/dev/sdb1","/dev/sda1"],"faulty":false,"level":"raid1","name":"/dev/md0"}],"supported_levels":["raid1","raid6","raid5","raid4"]}"#; assert_eq!(json!(parse_mdstat_str(r#" Personalities : [raid1] [raid6] [raid5] [raid4] md1 : active raid1 sdb2[1] sda2[0] @@ -157,6 +164,6 @@ md0 : active raid1 sdb1[1] sda1[0] 16787776 blocks [2/2] [UU] unused devices: - "#.to_string())).to_string(), r#"{"raids":[{"devices":["sdb2","sda2"],"faulty":false,"level":"raid1","name":"md1"},{"devices":["sdb3","sda3"],"faulty":false,"level":"raid1","name":"md2"},{"devices":["sdl1","sdk1","sdj1","sdi1","sdh1","sdg1","sdf1","sde1","sdd1","sdc1"],"faulty":false,"level":"raid5","name":"md3"},{"devices":["sdb1","sda1"],"faulty":false,"level":"raid1","name":"md0"}],"supported_levels":["raid1","raid6","raid5","raid4"]}"#); + "#.to_string())).to_string(), exp); } } \ No newline at end of file