From dca3642e464d32d2be08c4d68287d01677c8e9ea Mon Sep 17 00:00:00 2001 From: Christoffer Martinsson Date: Tue, 14 Oct 2025 00:44:38 +0200 Subject: [PATCH] Implement multi-host autoconnect with consolidated host configuration - Add DEFAULT_HOSTS constant in config.rs for centralized host management - Update ZMQ endpoint generation to connect to all configured hosts - Implement graceful connection handling for unreachable endpoints - Dashboard now auto-discovers and connects to available agents on cmbox, labbox, simonbox, steambox, srv01 --- dashboard/src/app.rs | 24 ++++++++++++++++-------- dashboard/src/data/config.rs | 14 +++++++++++++- dashboard/src/main.rs | 21 +++++++++++++++++---- 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/dashboard/src/app.rs b/dashboard/src/app.rs index 06f9815..b56fd74 100644 --- a/dashboard/src/app.rs +++ b/dashboard/src/app.rs @@ -8,7 +8,7 @@ use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use gethostname::gethostname; use crate::config; -use crate::data::config::{AppConfig, DataSourceKind, HostTarget, ZmqConfig}; +use crate::data::config::{AppConfig, DataSourceKind, HostTarget, ZmqConfig, DEFAULT_HOSTS}; use crate::data::history::MetricsHistory; use crate::data::metrics::{BackupMetrics, ServiceMetrics, SmartMetrics, SystemMetrics}; @@ -420,10 +420,7 @@ impl App { fn select_hosts(host: Option<&String>, _config: Option<&AppConfig>) -> Vec { let mut targets = Vec::new(); - // Known CMTEC infrastructure hosts for auto-discovery - let known_hosts = vec![ - "cmbox", "labbox", "simonbox", "steambox", "srv01" - ]; + // Use default hosts for auto-discovery if let Some(filter) = host { // If specific host requested, only connect to that one @@ -437,8 +434,8 @@ impl App { targets.push(HostTarget::from_name(local.clone())); } - // Add all known hosts for auto-discovery - for hostname in known_hosts { + // Add all default hosts for auto-discovery + for hostname in DEFAULT_HOSTS { if targets .iter() .any(|existing| existing.name.eq_ignore_ascii_case(hostname)) @@ -562,7 +559,18 @@ impl App { .unwrap_or(default); let endpoints = if zmq_config.endpoints.is_empty() { - ZmqConfig::default().endpoints + // Generate endpoints for all default hosts + let mut endpoints = Vec::new(); + + // Always include localhost + endpoints.push("tcp://127.0.0.1:6130".to_string()); + + // Add endpoint for each default host + for host in DEFAULT_HOSTS { + endpoints.push(format!("tcp://{}:6130", host)); + } + + endpoints } else { zmq_config.endpoints.clone() }; diff --git a/dashboard/src/data/config.rs b/dashboard/src/data/config.rs index 21c18cc..e7f6425 100644 --- a/dashboard/src/data/config.rs +++ b/dashboard/src/data/config.rs @@ -129,10 +129,22 @@ const fn default_tick_rate_ms() -> u64 { 500 } +/// Default hosts for auto-discovery +pub const DEFAULT_HOSTS: &[&str] = &[ + "cmbox", "labbox", "simonbox", "steambox", "srv01" +]; + fn default_data_source_config() -> DataSourceConfig { DataSourceConfig::default() } fn default_zmq_endpoints() -> Vec { - vec!["tcp://127.0.0.1:6130".to_string()] + // Default endpoints include localhost and all known CMTEC hosts + let mut endpoints = vec!["tcp://127.0.0.1:6130".to_string()]; + + for host in DEFAULT_HOSTS { + endpoints.push(format!("tcp://{}:6130", host)); + } + + endpoints } diff --git a/dashboard/src/main.rs b/dashboard/src/main.rs index 2040f80..b01ecd0 100644 --- a/dashboard/src/main.rs +++ b/dashboard/src/main.rs @@ -249,12 +249,25 @@ fn metrics_blocking_loop( .set_rcvtimeo(1_000) .context("failed to configure ZMQ receive timeout")?; + let mut connected_endpoints = 0; for endpoint in context.endpoints() { - debug!(%endpoint, "connecting to ZMQ endpoint"); - socket - .connect(endpoint) - .with_context(|| format!("failed to connect to {endpoint}"))?; + debug!(%endpoint, "attempting to connect to ZMQ endpoint"); + match socket.connect(endpoint) { + Ok(()) => { + debug!(%endpoint, "successfully connected to ZMQ endpoint"); + connected_endpoints += 1; + } + Err(error) => { + warn!(%endpoint, %error, "failed to connect to ZMQ endpoint, continuing with others"); + } + } } + + if connected_endpoints == 0 { + return Err(anyhow!("failed to connect to any ZMQ endpoints")); + } + + debug!("connected to {}/{} ZMQ endpoints", connected_endpoints, context.endpoints().len()); if let Some(prefix) = context.subscription() { socket