improve ping behaviour

This commit is contained in:
Empire 2024-09-06 20:12:17 +02:00
parent d71e515050
commit fa04e70d44
3 changed files with 1011 additions and 112 deletions

1002
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,8 @@ anyhow = "1.0.86"
dns-lookup = "2.0.4"
mountinfo = "0.2.0"
ping = "0.5.2"
sys-mount = "3.0.1"
sys-mount = {version="3.0.1", default-features = false}
notify-rust = "4"
[[bin]]
name = "automount"

View File

@ -1,64 +1,96 @@
use anyhow::Result;
use dns_lookup::lookup_host;
use mountinfo::{MountInfo, ReadWrite, MountPoint};
use notify_rust::Notification;
use ping::{dgramsock, rawsock::ping};
use std::{ffi::OsStr, fs, path::PathBuf, sync::mpsc::{self, Receiver, Sender}, thread, time::Duration};
use std::{ffi::OsStr, fs, net::IpAddr, path::PathBuf, sync::mpsc::{self, Receiver, Sender}, thread::{self, sleep}, time::Duration};
use sys_mount::{unmount, UnmountFlags};
fn main() {
let mtab = MountInfo::new().unwrap();
let mounting_points = mtab.mounting_points;
let relevant_mounts = mounting_points.iter().filter(|&mount_point| {
match &mount_point.fstype {
mountinfo::FsType::Other(fsstring) => match fsstring.as_str() {
"cifs" => {
true
loop {
let mtab = MountInfo::new().unwrap();
let mounting_points = mtab.mounting_points;
let relevant_mounts = mounting_points.iter().filter(|&mount_point| {
match &mount_point.fstype {
mountinfo::FsType::Other(fsstring) => match fsstring.as_str() {
"cifs" => {
true
},
_ => false
},
_ => false
},
_ => false
}
});
for mount_point in relevant_mounts {
let path = mount_point.path.to_owned();
let fstype = match &mount_point.fstype {
mountinfo::FsType::Other(fsstring) => fsstring,
_ => ""
};
let what = &mount_point.what;
//println!("Processing {fstype} @ {path:?} from {what}");
process_mount(fstype, what, path);
}
});
println!("Scanning for hanging mounts");
for mount_point in relevant_mounts {
let path = mount_point.path.to_owned();
let fstype = match &mount_point.fstype {
mountinfo::FsType::Other(fsstring) => fsstring,
_ => ""
};
let what = &mount_point.what;
println!("Processing {fstype} @ {path:?} from {what}");
process_mount(fstype, what, path);
sleep(Duration::from_secs(5));
}
}
fn ping_unreachable(host: &IpAddr, repeat:u8 ) -> bool{
for _attempt in 0..repeat {
match ping::ping(host.to_owned(),Some(Duration::from_millis(100)),Some(10),None, None, None) {
Ok(_) => {
return false
},
Err(_) => {
},
}
}
println!("All ping failed with error -> unmount");
return true;
}
fn process_mount(fstype: &str, what: &String, path: PathBuf) {
let mut higher_timeout = false;
let mut failed_initial_check = false;
match fstype {
"cifs" => {
let path_parts = what.replace("//","/");
let host = path_parts.split("/").nth(1).unwrap();
println!("Checking ping to host {host}");
let ips = lookup_host(host).unwrap();
let ip = ips.first().unwrap();
println!("Using ip {ip:?}");
match ping::ping(ip.to_owned(),Some(Duration::from_millis(100)),Some(10),None, None, None) {
Ok(_) => {
println!("Ping ok, proceeding")
},
Err(err) => {
println!("Ping failed with errror {err:?} -> unmount");
remove_mount(path.as_os_str());
},
}
failed_initial_check = ping_unreachable(&ip, 5);
higher_timeout = true;
},
_ => {}
}
if failed_initial_check {
let path_utf8 = path.as_os_str().to_string_lossy();
let body = format!("Unmounted {} due to fail online check", path_utf8);
let timeout = Duration::from_millis(500);
println!("Checking file access timeout {timeout:?}");
let _ = Notification::new()
.summary("Autounmount")
.body(body.as_str())
.icon("firefox")
.show();
remove_mount(path.as_os_str());
return;
}
let timeout = if higher_timeout {
Duration::from_millis(10000)
} else {
Duration::from_millis(1000)
};
let (sender, receiver) = mpsc::channel();
let path_copy = path.clone();
thread::spawn(move || {
@ -79,15 +111,25 @@ fn process_mount(fstype: &str, what: &String, path: PathBuf) {
let read_successful = receiver.recv_timeout(timeout);
match read_successful {
Ok(_) => {
println!("passed, mount still valid")
},
Err(err) => {
println!("Listing failed with errror {err:?} -> unmount");
let path_utf8 = path.as_os_str().to_string_lossy();
let body = format!("Unmounted {} due to fs operation check timeout out after {}s", path_utf8, timeout.as_secs());
let _ = Notification::new()
.summary("Autounmount")
.body(body.as_str())
.icon("firefox")
.show();
remove_mount(path.as_os_str());
},
}
}
fn remove_mount(path: &OsStr){
//unmount(path, UnmountFlags::FORCE | UnmountFlags::DETACH).unwrap()
unmount(path, UnmountFlags::FORCE | UnmountFlags::DETACH).unwrap()
}