WIP: Start implementing automatic node discovery from the K8s API

This commit is contained in:
Garrett Mills 2025-04-22 10:55:32 -04:00
parent 6e676c49d1
commit f6b5fef439
2 changed files with 74 additions and 2 deletions

View File

@ -1,16 +1,79 @@
use std::time::Duration;
use k8s_openapi::api::core::v1::Node;
use kube::{Api, Client};
use kube::api::ListParams;
use proxmox_api::nodes::node::lxc::vmid::migrate;
use proxmox_api::nodes::node::tasks::upid;
use sea_orm::*;
use tokio::time::sleep;
use log::{info};
use log::{info, debug};
use proxmox_api::types::VmId;
use crate::api::entity::{locks, nodes};
use crate::api::entity::nodes::{NodeParams, P5xError};
use crate::api::entity::nodes::{Model as NodeModel, NodeParams, P5xError};
use crate::api::entity::oplogs::Op;
use crate::api::services::Services;
/** WIP: Read nodes from the K8s API and register them w/ P5x based on metadata labels. */
pub async fn discover_nodes(
svc: &Services<'_>,
) -> Result<(), P5xError> {
debug!(target: "p5x", "Attempting to discover K8s cluster nodes...");
let client = Client::try_default().await.map_err(P5xError::KubeError)?;
let nodes: Api<Node> = Api::all(client);
let lp = ListParams::default();
let nodes = nodes.list(&lp).await.map_err(P5xError::KubeError)?;
for node in nodes {
let name = node.metadata.name.unwrap_or("(unknown)".to_string());
// Get the labels for the node
let labels = node.metadata.labels;
if labels.is_none() {
debug!(target: "p5x", "Skipping node {name}: could not load labels");
continue;
}
let labels = labels.unwrap();
// Check if it has the required pve_host and pve_id labels:
let pve_host = labels.get("p5x.garrettmills.dev/pve-host");
let pve_id = labels.get("p5x.garrettmills.dev/pve-id");
if pve_host.is_none() || pve_id.is_none() {
debug!(target: "p5x", "Skipping node {name}: missing required pve-host or pve-id label(s)");
continue;
}
let pve_host = pve_host.unwrap();
let pve_id: Result<i32, _> = pve_id.unwrap().parse();
if pve_id.is_err() {
debug!(target: "p5x", "Skipping node {name}: could not parse pve-id into i32");
continue;
}
let pve_id = pve_id.unwrap();
// Check if the node has been explicitly excluded from p5x management
let ignore = labels.get("p5x.garrettmills.dev/ignore");
if ignore.is_some() {
debug!(target: "p5x", "Skipping node {name}: found explicit ignore label");
continue;
}
// Check if the node is already registered
let existing = NodeModel::from_pve(svc, pve_host, pve_id).await?;
if existing.is_some() {
debug!(target: "p5x", "Skipping node {name}: already registered");
continue;
}
info!(target: "p5x", "Discovered node {name} ({pve_host}:{pve_id}). Attempting to register it.");
// fixme: WIP
}
Ok(())
}
/** Register an existing LXC container with P5x. */
pub async fn register_node(
svc: &Services<'_>,

View File

@ -301,6 +301,15 @@ pub struct Model {
}
impl Model {
pub async fn from_pve(svc: &Services<'_>, pve_host: &str, pve_id: i32) -> Result<Option<Model>, P5xError> {
Entity::find()
.filter(Column::PveHost.eq(pve_host))
.filter(Column::PveId.eq(pve_id))
.one(svc.db)
.await
.map_err(P5xError::DbErr)
}
/** Get the VM ID used by the Proxmox API library. */
pub fn vm_id(&self) -> VmId {
VmId::new(i64::from(self.pve_id)).unwrap()