|
@@ -1,7 +1,7 @@
|
|
|
//! `[mikrotik]` dispatch helpers for the power flow: entity-name lookup,
|
|
//! `[mikrotik]` dispatch helpers for the power flow: entity-name lookup,
|
|
|
//! dry-run lines, and the graceful RouterOS API shutdown loop.
|
|
//! dry-run lines, and the graceful RouterOS API shutdown loop.
|
|
|
|
|
|
|
|
-use tracing::warn;
|
|
|
|
|
|
|
+use tracing::{info, warn};
|
|
|
|
|
|
|
|
use crate::config::{Config, MikrotikConfig, MikrotikDevice, Node};
|
|
use crate::config::{Config, MikrotikConfig, MikrotikDevice, Node};
|
|
|
|
|
|
|
@@ -52,22 +52,52 @@ pub fn on_line(name: &str, relay: Option<&str>) {
|
|
|
|
|
|
|
|
/// Graceful RouterOS API shutdown for each named device (warns on
|
|
/// Graceful RouterOS API shutdown for each named device (warns on
|
|
|
/// failure — a router that fails to shut down must not block the rest of
|
|
/// failure — a router that fails to shut down must not block the rest of
|
|
|
-/// the power flow).
|
|
|
|
|
|
|
+/// the power flow), then a hard power cut: the `on_entity` outlet relay is
|
|
|
|
|
+/// switched off via HA when configured. Without it the API shutdown is not
|
|
|
|
|
+/// final — the router keeps power (fans spinning, can boot back up) and
|
|
|
|
|
+/// `power on`, which is just the relay, would be a no-op on an
|
|
|
|
|
+/// already-energized outlet.
|
|
|
pub async fn shutdown_named(config: &Config, names: &[String]) {
|
|
pub async fn shutdown_named(config: &Config, names: &[String]) {
|
|
|
for name in names {
|
|
for name in names {
|
|
|
- if let Some(dev) = device(config.mikrotik.as_ref(), name)
|
|
|
|
|
- && let Err(e) = crate::mikrotik::shutdown_device(dev).await
|
|
|
|
|
- {
|
|
|
|
|
- warn!(
|
|
|
|
|
- "{}",
|
|
|
|
|
- fluent_i18n::t!("power-off-mikrotik-failed", { "name" => &dev.name, "error" => e.to_string() })
|
|
|
|
|
- );
|
|
|
|
|
|
|
+ let Some(dev) = device(config.mikrotik.as_ref(), name) else {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ };
|
|
|
|
|
+ if let Err(e) = crate::mikrotik::shutdown_device(dev).await {
|
|
|
|
|
+ warn!("{}", fluent_i18n::t!("power-off-mikrotik-failed", { "name" => &dev.name, "error" => e.to_string() }));
|
|
|
|
|
+ }
|
|
|
|
|
+ let Some(relay) = &dev.on_entity else {
|
|
|
|
|
+ continue; // no relay configured: the API shutdown is all we have
|
|
|
|
|
+ };
|
|
|
|
|
+ match &config.home_assistant {
|
|
|
|
|
+ Some(ha_cfg) => match crate::home_assistant::Client::new(ha_cfg) {
|
|
|
|
|
+ Ok(ha) => match ha.turn_off(relay).await {
|
|
|
|
|
+ Ok(()) => info!("{}", fluent_i18n::t!("power-off-mikrotik-relay", { "name" => &dev.name, "relay" => relay })),
|
|
|
|
|
+ Err(e) => warn!("{}", fluent_i18n::t!("power-off-mikrotik-relay-failed", { "name" => &dev.name, "relay" => relay, "error" => e.to_string() })),
|
|
|
|
|
+ },
|
|
|
|
|
+ Err(e) => warn!("{}", fluent_i18n::t!("power-off-mikrotik-relay-failed", { "name" => &dev.name, "relay" => relay, "error" => e.to_string() })),
|
|
|
|
|
+ },
|
|
|
|
|
+ None => warn!("{}", fluent_i18n::t!("power-off-mikrotik-relay-failed", { "name" => &dev.name, "relay" => relay, "error" => "no HA configured" })),
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// Dry-run lines for `power off`: the ssh line per node plus the entity
|
|
/// Dry-run lines for `power off`: the ssh line per node plus the entity
|
|
|
/// line (RouterOS API line for configured devices).
|
|
/// line (RouterOS API line for configured devices).
|
|
|
|
|
+/// Dry-run "power off" line set for one mikrotik device: RouterOS API
|
|
|
|
|
+/// shutdown plus the outlet relay cut when one is configured.
|
|
|
|
|
+fn dry_off_device(dev: &MikrotikDevice) {
|
|
|
|
|
+ println!(
|
|
|
|
|
+ "{}",
|
|
|
|
|
+ fluent_i18n::t!("power-off-mikrotik-would", { "name" => &dev.name, "address" => &dev.address })
|
|
|
|
|
+ );
|
|
|
|
|
+ if let Some(relay) = &dev.on_entity {
|
|
|
|
|
+ println!(
|
|
|
|
|
+ "{}",
|
|
|
|
|
+ fluent_i18n::t!("power-off-mikrotik-relay-would", { "name" => &dev.name, "relay" => relay })
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
pub fn dry_off(config: &Config, targets: &[Node], extras: &[String]) {
|
|
pub fn dry_off(config: &Config, targets: &[Node], extras: &[String]) {
|
|
|
for node in targets {
|
|
for node in targets {
|
|
|
println!(
|
|
println!(
|
|
@@ -76,10 +106,7 @@ pub fn dry_off(config: &Config, targets: &[Node], extras: &[String]) {
|
|
|
);
|
|
);
|
|
|
if let Some(entity) = &node.entity {
|
|
if let Some(entity) = &node.entity {
|
|
|
match device(config.mikrotik.as_ref(), entity) {
|
|
match device(config.mikrotik.as_ref(), entity) {
|
|
|
- Some(dev) => println!(
|
|
|
|
|
- "{}",
|
|
|
|
|
- fluent_i18n::t!("power-off-mikrotik-would", { "name" => &dev.name, "address" => &dev.address })
|
|
|
|
|
- ),
|
|
|
|
|
|
|
+ Some(dev) => dry_off_device(dev),
|
|
|
None => println!(
|
|
None => println!(
|
|
|
"{}",
|
|
"{}",
|
|
|
fluent_i18n::t!("power-off-entity-would", { "entity" => entity.to_string() })
|
|
fluent_i18n::t!("power-off-entity-would", { "entity" => entity.to_string() })
|
|
@@ -89,10 +116,7 @@ pub fn dry_off(config: &Config, targets: &[Node], extras: &[String]) {
|
|
|
}
|
|
}
|
|
|
for id in extras {
|
|
for id in extras {
|
|
|
match device(config.mikrotik.as_ref(), id) {
|
|
match device(config.mikrotik.as_ref(), id) {
|
|
|
- Some(dev) => println!(
|
|
|
|
|
- "{}",
|
|
|
|
|
- fluent_i18n::t!("power-off-mikrotik-would", { "name" => &dev.name, "address" => &dev.address })
|
|
|
|
|
- ),
|
|
|
|
|
|
|
+ Some(dev) => dry_off_device(dev),
|
|
|
None => println!(
|
|
None => println!(
|
|
|
"{}",
|
|
"{}",
|
|
|
fluent_i18n::t!("power-switch-would-off-extra", { "extra" => id.to_string() })
|
|
fluent_i18n::t!("power-switch-would-off-extra", { "extra" => id.to_string() })
|
|
@@ -147,10 +171,7 @@ pub fn dry_switch_off(config: &Config, nodes: &[Node], extras: &[String]) {
|
|
|
);
|
|
);
|
|
|
if let Some(entity) = &node.entity {
|
|
if let Some(entity) = &node.entity {
|
|
|
match device(config.mikrotik.as_ref(), entity) {
|
|
match device(config.mikrotik.as_ref(), entity) {
|
|
|
- Some(dev) => println!(
|
|
|
|
|
- "{}",
|
|
|
|
|
- fluent_i18n::t!("power-off-mikrotik-would", { "name" => &dev.name, "address" => &dev.address })
|
|
|
|
|
- ),
|
|
|
|
|
|
|
+ Some(dev) => dry_off_device(dev),
|
|
|
None => println!(
|
|
None => println!(
|
|
|
"{}",
|
|
"{}",
|
|
|
fluent_i18n::t!("power-switch-would-off", { "entity" => entity.to_string() })
|
|
fluent_i18n::t!("power-switch-would-off", { "entity" => entity.to_string() })
|
|
@@ -160,10 +181,7 @@ pub fn dry_switch_off(config: &Config, nodes: &[Node], extras: &[String]) {
|
|
|
}
|
|
}
|
|
|
for id in extras {
|
|
for id in extras {
|
|
|
match device(config.mikrotik.as_ref(), id) {
|
|
match device(config.mikrotik.as_ref(), id) {
|
|
|
- Some(dev) => println!(
|
|
|
|
|
- "{}",
|
|
|
|
|
- fluent_i18n::t!("power-off-mikrotik-would", { "name" => &dev.name, "address" => &dev.address })
|
|
|
|
|
- ),
|
|
|
|
|
|
|
+ Some(dev) => dry_off_device(dev),
|
|
|
None => println!(
|
|
None => println!(
|
|
|
"{}",
|
|
"{}",
|
|
|
fluent_i18n::t!("power-switch-would-off-extra", { "extra" => id.to_string() })
|
|
fluent_i18n::t!("power-switch-would-off-extra", { "extra" => id.to_string() })
|