hive-c0re: fail on an unparseable resource-limits or topology file, write both atomically
resource-limits.json and topology.json were read with parse errors folded into an empty map, and written in place with std::fs::write. One truncated resource-limits.json followed by a single set_limits call rewrote the file with only that agent's entry, erasing every other agent's CPU and memory overrides without a log line. topology.json had the same shape: reconcile rebuilt it from the live set, losing pending (provisioned, never spawned) names. - agent_config::read_map / write_map are generic over the stored type. tool-groups and capabilities behave as before. - resource_limits::read / effective return an error for an existing but unreadable file; a missing file is still the empty map. set_limits fails without writing on such a file, and writes atomically. - topology: reconcile fails without writing on an unreadable file and writes atomically. all_agents logs the error and returns no agents, so a ManageRootAgent holder starts without cross-agent mounts. Read-path behaviour on an unreadable resource-limits.json, per caller: - write_dropins (every spawn / swap / WriteDropin): logs the error and keeps the limits drop-in already under /run; the agent still starts. With no drop-in yet (first start since boot) it writes the hive defaults, because no drop-in means an uncapped container. - render_flake: propagates, so sync_agents (and spawn/rebuild/destroy jobs) fail. An empty map would give tighter-capped agents the hive memoryMaxBytes. - container_view::build_all: logs the error each scan and renders the rows at the hive defaults (no ContainerView wire change). - set_resource_limits reply: propagates. Closes #4731
This commit is contained in:
parent
97cf8a1b2b
commit
6fac00dcc5
8 changed files with 332 additions and 119 deletions
|
|
@ -156,8 +156,17 @@ pub async fn build_all(hive: &crate::coordinator::HiveEnv) -> Vec<ContainerView>
|
|||
let raw = lifecycle::list().await.unwrap_or_default();
|
||||
let locked = read_meta_locked_revs();
|
||||
// Read once per scan rather than re-read for every container on every
|
||||
// SSE scan.
|
||||
let limits = crate::resource_limits::read();
|
||||
// SSE scan. An unreadable file shows every row at the hive defaults;
|
||||
// the error log is the only signal, as `ContainerView` has no field
|
||||
// to carry it.
|
||||
let limits = crate::resource_limits::read().unwrap_or_else(|e| {
|
||||
tracing::error!(
|
||||
path = %crate::resource_limits::resource_limits_path().display(),
|
||||
error = ?e,
|
||||
"resource limits unreadable — container rows show hive defaults"
|
||||
);
|
||||
std::collections::BTreeMap::new()
|
||||
});
|
||||
let mut out = Vec::new();
|
||||
for c in &raw {
|
||||
let Some(logical) = c.strip_prefix(AGENT_PREFIX) else {
|
||||
|
|
|
|||
Loading…
Reference in a new issue