Compare commits

..

No commits in common. "f5acf44e3b7c40597b2a31baff4a15d0626978d0" and "322997932e1e1402c7cf7501929d50f32b6e8b49" have entirely different histories.

2 changed files with 52 additions and 90 deletions

View File

@ -435,17 +435,16 @@ impl ServiceCollector {
"sshd" | "ssh" => self.get_ssh_active_users().await.map(|s| vec![s]), "sshd" | "ssh" => self.get_ssh_active_users().await.map(|s| vec![s]),
"nginx" => self.get_nginx_description().await.map(|s| vec![s]), "nginx" => self.get_nginx_description().await.map(|s| vec![s]),
"apache2" | "httpd" => self.get_web_server_connections().await.map(|s| vec![s]), "apache2" | "httpd" => self.get_web_server_connections().await.map(|s| vec![s]),
"docker-registry" => self.get_docker_registry_info().await.map(|s| vec![s]), "docker" | "docker-registry" => self.get_docker_containers().await.map(|s| vec![s]),
"docker" => self.get_docker_containers().await.map(|s| vec![s]),
"postgresql" | "postgres" => self.get_postgres_connections().await.map(|s| vec![s]), "postgresql" | "postgres" => self.get_postgres_connections().await.map(|s| vec![s]),
"mysql" | "mariadb" => self.get_mysql_connections().await.map(|s| vec![s]), "mysql" | "mariadb" => self.get_mysql_connections().await.map(|s| vec![s]),
"redis" | "redis-immich" => self.get_redis_info().await.map(|s| vec![s]), "redis" | "redis-immich" => self.get_redis_info().await.map(|s| vec![s]),
"mongodb" | "mongod" => self.get_mongodb_info().await.map(|s| vec![s]),
"gitea" => self.get_gitea_info().await.map(|s| vec![s]), "gitea" => self.get_gitea_info().await.map(|s| vec![s]),
"immich-server" => self.get_immich_info().await.map(|s| vec![s]), "immich-server" | "immich" => self.get_immich_info().await.map(|s| vec![s]),
"vaultwarden" => self.get_vaultwarden_info().await.map(|s| vec![s]), "vaultwarden" => self.get_vaultwarden_info().await.map(|s| vec![s]),
"unifi" => self.get_unifi_info().await.map(|s| vec![s]), "unifi" => self.get_unifi_info().await.map(|s| vec![s]),
"mosquitto" => self.get_mosquitto_info().await.map(|s| vec![s]), "mosquitto" => self.get_mosquitto_info().await.map(|s| vec![s]),
"haasp-webgrid" => self.get_haasp_webgrid_info().await.map(|s| vec![s]),
_ => None, _ => None,
}; };
@ -507,9 +506,9 @@ impl ServiceCollector {
} }
} }
async fn get_docker_containers(&self) -> Option<Vec<String>> { async fn get_docker_containers(&self) -> Option<String> {
let output = Command::new("/run/current-system/sw/bin/docker") let output = Command::new("docker")
.args(["ps", "--format", "{{.Names}}"]) .args(["ps", "--format", "table {{.Names}}"])
.stdout(Stdio::piped()) .stdout(Stdio::piped())
.stderr(Stdio::piped()) .stderr(Stdio::piped())
.output() .output()
@ -521,16 +520,12 @@ impl ServiceCollector {
} }
let stdout = String::from_utf8_lossy(&output.stdout); let stdout = String::from_utf8_lossy(&output.stdout);
let containers: Vec<String> = stdout let container_count = stdout.lines().count().saturating_sub(1); // Subtract header line
.lines()
.filter(|line| !line.trim().is_empty())
.map(|line| line.trim().to_string())
.collect();
if containers.is_empty() { if container_count > 0 {
None Some(format!("{} running containers", container_count))
} else { } else {
Some(containers) Some("no containers running".to_string())
} }
} }
@ -578,24 +573,7 @@ impl ServiceCollector {
} }
} }
// Fallback: check MySQL unix socket connections (more common than TCP) // Fallback: check MySQL connections on port 3306
let output = Command::new("/run/current-system/sw/bin/ss")
.args(["-x", "state", "connected", "src", "*mysql*"])
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.output()
.await
.ok()?;
if output.status.success() {
let stdout = String::from_utf8_lossy(&output.stdout);
let connection_count = stdout.lines().count().saturating_sub(1);
if connection_count > 0 {
return Some(format!("{} connections", connection_count));
}
}
// Also try TCP port 3306 as final fallback
let output = Command::new("/run/current-system/sw/bin/ss") let output = Command::new("/run/current-system/sw/bin/ss")
.args(["-tn", "state", "established", "dport", "= :3306"]) .args(["-tn", "state", "established", "dport", "= :3306"])
.stdout(Stdio::piped()) .stdout(Stdio::piped())
@ -933,9 +911,9 @@ impl ServiceCollector {
} }
async fn get_immich_info(&self) -> Option<String> { async fn get_immich_info(&self) -> Option<String> {
// Check HTTP connections - Immich runs on port 8084 (from nginx proxy config) // Check upload directory for photo count estimate
let output = Command::new("/run/current-system/sw/bin/ss") let output = Command::new("find")
.args(["-tn", "state", "established", "dport", "= :8084"]) .args(["/var/lib/immich/upload", "-type", "f", "-name", "*.jpg", "-o", "-name", "*.png", "-o", "-name", "*.mp4", "-o", "-name", "*.mov"])
.stdout(Stdio::piped()) .stdout(Stdio::piped())
.stderr(Stdio::piped()) .stderr(Stdio::piped())
.output() .output()
@ -944,9 +922,25 @@ impl ServiceCollector {
if output.status.success() { if output.status.success() {
let stdout = String::from_utf8_lossy(&output.stdout); let stdout = String::from_utf8_lossy(&output.stdout);
let connection_count = stdout.lines().count().saturating_sub(1); let file_count = stdout.lines().count();
if connection_count > 0 { if file_count > 0 {
return Some(format!("{} connections", connection_count)); return Some(format!("~{} media files", file_count));
}
}
// Fallback: check storage usage
let output = Command::new("sudo")
.args(["/run/current-system/sw/bin/du", "-sh", "/var/lib/immich/upload"])
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.output()
.await
.ok()?;
if output.status.success() {
let stdout = String::from_utf8_lossy(&output.stdout);
if let Some(size) = stdout.split_whitespace().next() {
return Some(format!("Storage: {}", size));
} }
} }
@ -954,9 +948,9 @@ impl ServiceCollector {
} }
async fn get_vaultwarden_info(&self) -> Option<String> { async fn get_vaultwarden_info(&self) -> Option<String> {
// Check vaultwarden connections on port 8222 (from nginx proxy config) // Check HTTP connections - vaultwarden typically runs on port 8000 or behind nginx
let output = Command::new("/run/current-system/sw/bin/ss") let output = Command::new("/run/current-system/sw/bin/ss")
.args(["-tn", "state", "established", "dport", "= :8222"]) .args(["-tn", "state", "established", "dport", "= :8000"])
.stdout(Stdio::piped()) .stdout(Stdio::piped())
.stderr(Stdio::piped()) .stderr(Stdio::piped())
.output() .output()
@ -975,9 +969,9 @@ impl ServiceCollector {
} }
async fn get_unifi_info(&self) -> Option<String> { async fn get_unifi_info(&self) -> Option<String> {
// Check UniFi connections on port 8080 (TCP) // Check for device count via UniFi API (if accessible)
let output = Command::new("/run/current-system/sw/bin/ss") let output = Command::new("curl")
.args(["-tn", "state", "established", "dport", "= :8080"]) .args(["-s", "-f", "--insecure", "https://localhost:8443/api/self/sites"])
.stdout(Stdio::piped()) .stdout(Stdio::piped())
.stderr(Stdio::piped()) .stderr(Stdio::piped())
.output() .output()
@ -985,11 +979,12 @@ impl ServiceCollector {
.ok()?; .ok()?;
if output.status.success() { if output.status.success() {
let stdout = String::from_utf8_lossy(&output.stdout); return Some("Controller active".to_string());
let connection_count = stdout.lines().count().saturating_sub(1); }
if connection_count > 0 {
return Some(format!("{} connections", connection_count)); // Fallback: check data directory
} if tokio::fs::metadata("/var/lib/unifi/data").await.is_ok() {
return Some("Data directory exists".to_string());
} }
None None
@ -1016,10 +1011,10 @@ impl ServiceCollector {
None None
} }
async fn get_docker_registry_info(&self) -> Option<String> { async fn get_mongodb_info(&self) -> Option<String> {
// Check Docker registry connections on port 5000 (from nginx proxy config) // Check MongoDB connections on port 27017
let output = Command::new("/run/current-system/sw/bin/ss") let output = Command::new("/run/current-system/sw/bin/ss")
.args(["-tn", "state", "established", "dport", "= :5000"]) .args(["-tn", "state", "established", "dport", "= :27017"])
.stdout(Stdio::piped()) .stdout(Stdio::piped())
.stderr(Stdio::piped()) .stderr(Stdio::piped())
.output() .output()
@ -1034,13 +1029,9 @@ impl ServiceCollector {
} }
} }
None // Fallback: check data directory size
} let output = Command::new("sudo")
.args(["/run/current-system/sw/bin/du", "-sh", "/var/lib/mongodb"])
async fn get_haasp_webgrid_info(&self) -> Option<String> {
// Check HAASP webgrid connections on port 8081
let output = Command::new("/run/current-system/sw/bin/ss")
.args(["-tn", "state", "established", "dport", "= :8081"])
.stdout(Stdio::piped()) .stdout(Stdio::piped())
.stderr(Stdio::piped()) .stderr(Stdio::piped())
.output() .output()
@ -1049,9 +1040,8 @@ impl ServiceCollector {
if output.status.success() { if output.status.success() {
let stdout = String::from_utf8_lossy(&output.stdout); let stdout = String::from_utf8_lossy(&output.stdout);
let connection_count = stdout.lines().count().saturating_sub(1); if let Some(size) = stdout.split_whitespace().next() {
if connection_count > 0 { return Some(format!("Data: {}", size));
return Some(format!("{} connections", connection_count));
} }
} }
@ -1123,31 +1113,6 @@ impl Collector for ServiceCollector {
healthy += 1; healthy += 1;
} }
} }
}
// Handle docker specially - create sub-services for containers
else if service == "docker" && matches!(service_data.status, ServiceStatus::Running) {
// Clear docker description - containers will become individual sub-services
let mut docker_service = service_data;
docker_service.description = None;
services.push(docker_service);
// Add docker containers as individual sub-services
if let Some(containers) = self.get_docker_containers().await {
for container in containers.iter() {
services.push(ServiceData {
name: container.clone(),
status: ServiceStatus::Running, // Assume containers are running if docker is running
memory_used_mb: 0.0,
memory_quota_mb: 0.0,
cpu_percent: 0.0,
sandbox_limit: None,
disk_used_gb: 0.0,
description: None,
sub_service: Some("docker".to_string()),
});
healthy += 1;
}
}
} else { } else {
services.push(service_data); services.push(service_data);
} }

View File

@ -238,9 +238,6 @@ impl AutoDiscovery {
"rclone", "rclone",
// Container runtimes // Container runtimes
"docker", "docker",
// CI/CD services
"gitea-actions",
"actions-runner",
// Network services // Network services
"sshd", "sshd",
"dnsmasq", "dnsmasq",