lisuerhg
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1 +1,2 @@
|
|||||||
/target
|
/target
|
||||||
|
config.toml
|
||||||
|
|||||||
92
Cargo.lock
generated
92
Cargo.lock
generated
@@ -79,6 +79,12 @@ version = "1.3.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "2.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytes"
|
name = "bytes"
|
||||||
version = "1.12.0"
|
version = "1.12.0"
|
||||||
@@ -162,7 +168,7 @@ version = "1.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a6e524506490a1953d237cb87b1cfc1e46f88c18f10a22dfe0f507dc6bfc7f7f"
|
checksum = "a6e524506490a1953d237cb87b1cfc1e46f88c18f10a22dfe0f507dc6bfc7f7f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
"defmt-macros",
|
"defmt-macros",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -217,6 +223,16 @@ version = "1.0.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "errno"
|
||||||
|
version = "0.3.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "find-msvc-tools"
|
name = "find-msvc-tools"
|
||||||
version = "0.1.9"
|
version = "0.1.9"
|
||||||
@@ -309,12 +325,27 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.186"
|
version = "0.2.186"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
|
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lock_api"
|
||||||
|
version = "0.4.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
|
||||||
|
dependencies = [
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.33"
|
version = "0.4.33"
|
||||||
@@ -384,6 +415,29 @@ version = "1.70.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
|
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot"
|
||||||
|
version = "0.12.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
"parking_lot_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot_core"
|
||||||
|
version = "0.9.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"redox_syscall",
|
||||||
|
"smallvec",
|
||||||
|
"windows-link",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project-lite"
|
name = "pin-project-lite"
|
||||||
version = "0.2.17"
|
version = "0.2.17"
|
||||||
@@ -451,6 +505,15 @@ version = "6.0.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
|
checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_syscall"
|
||||||
|
version = "0.5.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.13.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.12.4"
|
version = "1.12.4"
|
||||||
@@ -527,6 +590,12 @@ dependencies = [
|
|||||||
"untrusted",
|
"untrusted",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.228"
|
version = "1.0.228"
|
||||||
@@ -572,6 +641,22 @@ version = "1.3.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "signal-hook-registry"
|
||||||
|
version = "1.4.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b"
|
||||||
|
dependencies = [
|
||||||
|
"errno",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smallvec"
|
||||||
|
version = "1.15.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
version = "0.6.4"
|
version = "0.6.4"
|
||||||
@@ -634,7 +719,9 @@ dependencies = [
|
|||||||
"bytes",
|
"bytes",
|
||||||
"libc",
|
"libc",
|
||||||
"mio",
|
"mio",
|
||||||
|
"parking_lot",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
|
"signal-hook-registry",
|
||||||
"socket2",
|
"socket2",
|
||||||
"tokio-macros",
|
"tokio-macros",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.61.2",
|
||||||
@@ -735,9 +822,12 @@ dependencies = [
|
|||||||
"camino",
|
"camino",
|
||||||
"clap",
|
"clap",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
|
"lazy_static",
|
||||||
"log",
|
"log",
|
||||||
"mikrotik-rs",
|
"mikrotik-rs",
|
||||||
|
"regex",
|
||||||
"serde",
|
"serde",
|
||||||
|
"tokio",
|
||||||
"toml",
|
"toml",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,10 @@ anyhow = "1.0.103"
|
|||||||
camino = { version = "1.2.4", features = ["serde1"] }
|
camino = { version = "1.2.4", features = ["serde1"] }
|
||||||
clap = { version = "4.6.1", features = ["derive"] }
|
clap = { version = "4.6.1", features = ["derive"] }
|
||||||
env_logger = "0.11.11"
|
env_logger = "0.11.11"
|
||||||
|
lazy_static = "1.5.0"
|
||||||
log = "0.4.33"
|
log = "0.4.33"
|
||||||
mikrotik-rs = { version = "0.8.0", features = ["tokio-tls"] }
|
mikrotik-rs = { version = "0.8.0", features = ["tokio-tls"] }
|
||||||
|
regex = "1.12.4"
|
||||||
serde = { version = "1.0.228", features = ["derive"] }
|
serde = { version = "1.0.228", features = ["derive"] }
|
||||||
|
tokio = { version = "1.52.3", features = ["full"] }
|
||||||
toml = "1.1.2"
|
toml = "1.1.2"
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ pub struct ConfigDefaultLogins {
|
|||||||
pub password: String,
|
pub password: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub struct ConfigHost {
|
pub struct ConfigHost {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub ip: IpAddr,
|
pub ip: IpAddr,
|
||||||
|
|||||||
@@ -0,0 +1,126 @@
|
|||||||
|
use core::panic;
|
||||||
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
hash::Hash,
|
||||||
|
sync::{Arc, Mutex},
|
||||||
|
};
|
||||||
|
|
||||||
|
use mikrotik_rs::{Command, CommandBuilder, Event, MikrotikDevice};
|
||||||
|
use regex::Regex;
|
||||||
|
|
||||||
|
use crate::config::{Config, ConfigHost};
|
||||||
|
|
||||||
|
lazy_static::lazy_static! {
|
||||||
|
static ref MTC: Arc<Mutex<MtCommanderInternal>> = MtCommanderInternal::new_mutex();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MtCommander;
|
||||||
|
struct MtCommanderInternal {
|
||||||
|
cfg: Option<Config>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MtCommander {
|
||||||
|
pub fn init(cfg: Config) -> anyhow::Result<()> {
|
||||||
|
let mut mtc = MTC.lock().map_err(|e| anyhow::anyhow!(e.to_string()))?;
|
||||||
|
mtc.cfg = Some(cfg);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn run_command_on_hosts(
|
||||||
|
hosts: &[ConfigHost],
|
||||||
|
command: &str,
|
||||||
|
) -> anyhow::Result<HashMap<ConfigHost, String>> {
|
||||||
|
let mut res_map = HashMap::new();
|
||||||
|
for host in hosts {
|
||||||
|
let res = Self::run_command_on_host(host, command).await?;
|
||||||
|
res_map.insert(host.clone(), res);
|
||||||
|
}
|
||||||
|
Ok(res_map)
|
||||||
|
}
|
||||||
|
pub async fn run_command_on_host(host: &ConfigHost, command: &str) -> anyhow::Result<String> {
|
||||||
|
let mtc = MTC.lock().map_err(|e| anyhow::anyhow!(e.to_string()))?;
|
||||||
|
mtc.run_command(host, &command).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn run_command_on_hosts_and_parse_re(
|
||||||
|
hosts: &[ConfigHost],
|
||||||
|
command: &str,
|
||||||
|
parse_re: &Regex,
|
||||||
|
) -> anyhow::Result<HashMap<ConfigHost, Vec<String>>> {
|
||||||
|
let mut res_map = HashMap::new();
|
||||||
|
for host in hosts {
|
||||||
|
let res = Self::run_command_on_host_and_parse_re(host, command, parse_re).await?;
|
||||||
|
res_map.insert(host.clone(), res);
|
||||||
|
}
|
||||||
|
Ok(res_map)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn run_command_on_host_and_parse_re(
|
||||||
|
host: &ConfigHost,
|
||||||
|
command: &str,
|
||||||
|
parse_re: &Regex,
|
||||||
|
) -> anyhow::Result<Vec<String>> {
|
||||||
|
let mtc = MTC.lock().map_err(|e| anyhow::anyhow!(e.to_string()))?;
|
||||||
|
let res = mtc.run_command(host, &command).await?;
|
||||||
|
let out = parse_re
|
||||||
|
.find_iter(&res)
|
||||||
|
.map(|s| s.as_str().to_string())
|
||||||
|
.collect();
|
||||||
|
Ok(out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MtCommanderInternal {
|
||||||
|
fn new(cfg: Config) -> Self {
|
||||||
|
Self { cfg: Some(cfg) }
|
||||||
|
}
|
||||||
|
fn new_mutex() -> Arc<Mutex<Self>> {
|
||||||
|
Arc::new(Mutex::new(Self { cfg: None }))
|
||||||
|
}
|
||||||
|
fn init(&mut self, cfg: Config) -> anyhow::Result<()> {
|
||||||
|
self.cfg = Some(cfg);
|
||||||
|
self.spawn_watcher_thread()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn cfg(&self) -> &Config {
|
||||||
|
if let Some(cfg) = &self.cfg {
|
||||||
|
cfg
|
||||||
|
} else {
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn spawn_watcher_thread(&mut self) -> anyhow::Result<()> {
|
||||||
|
async fn watcher() {}
|
||||||
|
|
||||||
|
tokio::spawn(watcher());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
async fn run_command(&self, host: &ConfigHost, cmd: &str) -> anyhow::Result<String> {
|
||||||
|
let dev = MikrotikDevice::connect(
|
||||||
|
format!("{}", &host.ip),
|
||||||
|
&host.username(self.cfg()),
|
||||||
|
Some(&host.password(self.cfg())),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let mut rx = dev
|
||||||
|
.send_command(CommandBuilder::new().command(cmd).build())
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let mut res = String::new();
|
||||||
|
|
||||||
|
while let Some(event) = rx.recv().await {
|
||||||
|
match event {
|
||||||
|
Event::Reply { response, .. } => {
|
||||||
|
log::debug!("({}) {:?}", &host.ip, response.attributes);
|
||||||
|
}
|
||||||
|
Event::Done { .. } => break,
|
||||||
|
Event::Trap { response, .. } => {
|
||||||
|
log::error!("({}) {:?}", &host.ip, response.message);
|
||||||
|
}
|
||||||
|
other => println!("{other:?}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user