tftsr-devops_investigation/src-tauri/src/proxmox/cluster.rs
Shaun Arman a438e313a6 feat: Implement Proxmox Datacenter Manager feature parity - Phases 1-11
- Phase 1: Dashboard Widget System (11 widgets)
- Phase 2: Resource Tree View (ResourceTree + ResourceFilter)
- Phase 3: VM Manager UI (VMList + SnapshotForm + MigrationForm)
- Phase 4: Backup Manager UI (BackupJobList)
- Phase 5: Ceph Manager UI (CephHealthWidget + PoolList + OSDList + MonitorList)
- Phase 6: SDN Manager UI (EVPNZoneList)
- Phase 7: Firewall Manager UI (FirewallRuleList)
- Phase 8: HA Groups Manager UI (HAGroupsList + HAResourcesList)
- Phase 9: User Management UI (RealmList + UserList)
- Phase 10: Certificate Manager UI (CertificateList)
- Phase 11: Subscription Registry UI (SubscriptionList)

All components pass TypeScript, ESLint, and existing tests.
All Rust code passes clippy and format checks.
2026-06-11 09:38:36 -05:00

176 lines
4.9 KiB
Rust

use serde::{Deserialize, Serialize};
use std::collections::HashMap;
/// Cluster information
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ClusterInfo {
pub id: String,
pub name: String,
pub cluster_type: ClusterType,
pub url: String,
pub port: u16,
pub username: String,
pub created_at: String,
pub updated_at: String,
}
/// Cluster type
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
#[serde(rename_all = "lowercase")]
pub enum ClusterType {
#[default]
VE, // Proxmox VE
PBS, // Proxmox Backup Server
}
/// Cluster registry for managing multiple clusters
pub struct ClusterRegistry {
clusters: HashMap<String, ClusterInfo>,
}
impl ClusterRegistry {
/// Create a new cluster registry
pub fn new() -> Self {
Self {
clusters: HashMap::new(),
}
}
/// Add a cluster
pub fn add_cluster(&mut self, cluster: ClusterInfo) {
self.clusters.insert(cluster.id.clone(), cluster);
}
/// Remove a cluster
pub fn remove_cluster(&mut self, id: &str) -> Option<ClusterInfo> {
self.clusters.remove(id)
}
/// Get a cluster by ID
pub fn get_cluster(&self, id: &str) -> Option<&ClusterInfo> {
self.clusters.get(id)
}
/// Get all clusters
pub fn list_clusters(&self) -> Vec<&ClusterInfo> {
self.clusters.values().collect()
}
/// Get clusters by type
pub fn list_clusters_by_type(&self, cluster_type: &ClusterType) -> Vec<&ClusterInfo> {
self.clusters
.values()
.filter(|c| &c.cluster_type == cluster_type)
.collect()
}
/// Get cluster count
pub fn cluster_count(&self) -> usize {
self.clusters.len()
}
/// Check if a cluster exists
pub fn has_cluster(&self, id: &str) -> bool {
self.clusters.contains_key(id)
}
}
impl Default for ClusterRegistry {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_cluster_registry_new() {
let registry = ClusterRegistry::new();
assert_eq!(registry.cluster_count(), 0);
}
#[test]
fn test_cluster_registry_add_and_get() {
let mut registry = ClusterRegistry::new();
let cluster = ClusterInfo {
id: "cluster-1".to_string(),
name: "Production".to_string(),
cluster_type: ClusterType::VE,
url: "https://pve.example.com".to_string(),
port: 8006,
username: "root@pam".to_string(),
created_at: "2026-06-10 12:00:00".to_string(),
updated_at: "2026-06-10 12:00:00".to_string(),
};
registry.add_cluster(cluster.clone());
assert_eq!(registry.cluster_count(), 1);
let retrieved = registry.get_cluster("cluster-1");
assert!(retrieved.is_some());
assert_eq!(retrieved.unwrap().name, "Production");
}
#[test]
fn test_cluster_registry_remove() {
let mut registry = ClusterRegistry::new();
let cluster = ClusterInfo {
id: "cluster-1".to_string(),
name: "Production".to_string(),
cluster_type: ClusterType::VE,
url: "https://pve.example.com".to_string(),
port: 8006,
username: "root@pam".to_string(),
created_at: "2026-06-10 12:00:00".to_string(),
updated_at: "2026-06-10 12:00:00".to_string(),
};
registry.add_cluster(cluster);
assert_eq!(registry.cluster_count(), 1);
let removed = registry.remove_cluster("cluster-1");
assert!(removed.is_some());
assert_eq!(registry.cluster_count(), 0);
}
#[test]
fn test_cluster_registry_list_by_type() {
let mut registry = ClusterRegistry::new();
let ve_cluster = ClusterInfo {
id: "ve-1".to_string(),
name: "VE Cluster".to_string(),
cluster_type: ClusterType::VE,
url: "https://pve.example.com".to_string(),
port: 8006,
username: "root@pam".to_string(),
created_at: "2026-06-10 12:00:00".to_string(),
updated_at: "2026-06-10 12:00:00".to_string(),
};
let pbs_cluster = ClusterInfo {
id: "pbs-1".to_string(),
name: "PBS Cluster".to_string(),
cluster_type: ClusterType::PBS,
url: "https://pbs.example.com".to_string(),
port: 8007,
username: "root@pam".to_string(),
created_at: "2026-06-10 12:00:00".to_string(),
updated_at: "2026-06-10 12:00:00".to_string(),
};
registry.add_cluster(ve_cluster);
registry.add_cluster(pbs_cluster);
let ve_clusters = registry.list_clusters_by_type(&ClusterType::VE);
assert_eq!(ve_clusters.len(), 1);
let pbs_clusters = registry.list_clusters_by_type(&ClusterType::PBS);
assert_eq!(pbs_clusters.len(), 1);
}
}