فهرست منبع

web: flare groups fold into the controller node only (split helpers to stay under the line cap)

Alexander Korolev 18 ساعت پیش
والد
کامیت
5eaec401fd
6فایلهای تغییر یافته به همراه49 افزوده شده و 33 حذف شده
  1. 1 0
      src/config.rs
  2. 19 0
      src/config/hf_cache.rs
  3. 0 28
      src/config/types.rs
  4. 25 0
      src/web/flare_nodes.rs
  5. 1 0
      src/web/mod.rs
  6. 3 5
      src/web/probe.rs

+ 1 - 0
src/config.rs

@@ -56,6 +56,7 @@ mod staging;
 pub use staging::{Staging, StagingFormat, StagingKind, StagingVerify};
 mod types;
 pub use types::*;
+mod hf_cache;
 
 impl Node {
     /// Host IP for engine exports; falls back to `ssh_ip` when `ib_ip` unset

+ 19 - 0
src/config/hf_cache.rs

@@ -0,0 +1,19 @@
+//! Host-side HF cache resolution.
+
+use super::types::Config;
+
+impl Config {
+    /// Host-side HF cache dir (config `hf_cache_dir`, else the ssh user's
+    /// `~/.cache/huggingface`).
+    pub fn resolved_hf_cache_dir(&self) -> std::path::PathBuf {
+        if let Some(ref dir) = self.hf_cache_dir {
+            return std::path::PathBuf::from(dir);
+        }
+        let home = if self.ssh_user == "root" {
+            "/root".to_string()
+        } else {
+            format!("/home/{}", self.ssh_user)
+        };
+        std::path::PathBuf::from(format!("{home}/.cache/huggingface"))
+    }
+}

+ 0 - 28
src/config/types.rs

@@ -274,34 +274,6 @@ pub struct ComposedFile {
     pub content: String,
 }
 
-impl Config {
-    /// The node that runs `flare orbit` (the `[flare].controller_node` when
-    /// set, else the first cluster's rank-0 node).
-    pub fn flake_controller_node(&self) -> Option<&Node> {
-        let want = self.flare.as_ref().and_then(|f| f.controller_node.clone());
-        let all = self.clusters.iter().flat_map(|c| c.nodes.iter());
-        match want {
-            Some(name) => all.clone().find(|n| n.name == name),
-            None => all
-                .clone()
-                .find(|n| n.rank == 0)
-                .or_else(|| all.into_iter().next()),
-        }
-    }
-
-    pub fn resolved_hf_cache_dir(&self) -> std::path::PathBuf {
-        if let Some(ref dir) = self.hf_cache_dir {
-            return std::path::PathBuf::from(dir);
-        }
-        let home = if self.ssh_user == "root" {
-            "/root".to_string()
-        } else {
-            format!("/home/{}", self.ssh_user)
-        };
-        std::path::PathBuf::from(format!("{home}/.cache/huggingface"))
-    }
-}
-
 /// A recipe-level extra bind-mount for `docker run`.
 ///
 /// Two mutually exclusive kinds:

+ 25 - 0
src/web/flare_nodes.rs

@@ -0,0 +1,25 @@
+//! Which of our nodes runs the `flare orbit` CLI.
+//!
+//! The orbit cluster is FLARE's own naming (`gx10-dgx5`…), so the controller
+//! is configured explicitly (`[flare].controller_node = "dgx5.lan"`); without
+//! it we fall back to the first cluster's rank-0 node — right for a single
+//! cluster, wrong for a multi-cluster config, which is why the explicit field
+//! exists.
+
+use crate::config::{Config, Node};
+
+/// The node that runs `flare orbit`.
+pub fn controller_node(config: &Config) -> Option<&Node> {
+    let want = config
+        .flare
+        .as_ref()
+        .and_then(|f| f.controller_node.clone());
+    let all = config.clusters.iter().flat_map(|c| c.nodes.iter());
+    match want {
+        Some(name) => all.clone().find(|n| n.name == name),
+        None => all
+            .clone()
+            .find(|n| n.rank == 0)
+            .or_else(|| all.into_iter().next()),
+    }
+}

+ 1 - 0
src/web/mod.rs

@@ -10,6 +10,7 @@
 
 mod api;
 pub mod events;
+pub(crate) mod flare_nodes;
 pub mod jobs;
 pub mod logs;
 pub mod model_settings;

+ 3 - 5
src/web/probe.rs

@@ -177,7 +177,7 @@ pub async fn flare_groups(config: &crate::config::Config) -> Vec<(String, Option
         .orbit_cluster
         .clone()
         .unwrap_or_else(|| "sparks".to_string());
-    let Some(controller) = config.flake_controller_node() else {
+    let Some(controller) = crate::web::flare_nodes::controller_node(config) else {
         return Vec::new();
     };
     let cmd = format!("{binary} orbit status --cluster {orbit_cluster} 2>/dev/null");
@@ -288,8 +288,7 @@ pub async fn probe(config: &Config) -> Fleet {
         .clusters
         .iter()
         .find(|c| {
-            config
-                .flake_controller_node()
+            crate::web::flare_nodes::controller_node(config)
                 .is_some_and(|n| c.nodes.iter().any(|x| x.name == n.name))
         })
         .map(|c| c.name.clone())
@@ -315,8 +314,7 @@ pub async fn probe(config: &Config) -> Fleet {
                 // Only the controller node hosts the orbit groups (the fold
                 // below runs per node — without this guard every node would
                 // report the same group).
-                let is_controller = config
-                    .flake_controller_node()
+                let is_controller = crate::web::flare_nodes::controller_node(config)
                     .is_some_and(|c| c.ssh_ip == *node_ip_of(config, &name));
                 for (group, created) in flare.iter().filter(|_| is_controller) {
                     containers.push(ContainerSnap {