feat(#2290): ConditionPathIsDirectory= in container service drop-in
Add a [Unit] section to hyperhive-limits.conf (the drop-in written by write_resource_limits) with: ConditionPathIsDirectory=/run/hyperhive/agents/<name> When this condition is not met, systemd skips the unit with result "condition" — NOT a failure, so the start-limit counter is not incremented. Belt-and-braces on top of the tmpfiles.d fix (subtask 2): if a dir is somehow absent at start time, the container idles instead of restart-looping into start-limit-hit. Also promote AGENT_RUNTIME_ROOT to a module-level const (was duplicated inside two functions) and remove the duplicates.
This commit is contained in:
parent
f32fba0238
commit
14c2c6d4a5
1 changed files with 29 additions and 3 deletions
|
|
@ -33,6 +33,10 @@ use tokio::process::Command;
|
|||
/// Root of the per-agent unix-socket dirs on the host.
|
||||
const SOCKET_DIR_ROOT: &str = "/run/hive-agent";
|
||||
|
||||
/// Root of the per-agent MCP socket dirs on the host.
|
||||
/// Matches `coordinator::AGENT_RUNTIME_ROOT` in hive-c0re.
|
||||
const AGENT_RUNTIME_ROOT: &str = "/run/hyperhive/agents";
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
tracing_subscriber::fmt()
|
||||
|
|
@ -422,17 +426,40 @@ fn chmod_socket_dir(agent_name: &str, mode: u32) -> Result<(String, String)> {
|
|||
}
|
||||
|
||||
/// `WriteResourceLimits` — drop a systemd `MemoryMax`/`CPUQuota`
|
||||
/// override into the container service's drop-in dir.
|
||||
/// override into the container service's drop-in dir, together with a
|
||||
/// `ConditionPathIsDirectory=` guard on the agent's MCP runtime dir.
|
||||
///
|
||||
/// The condition causes systemd to *skip* (not *fail*) the unit when the
|
||||
/// bind-mount source dir is absent — result is `condition`, which does not
|
||||
/// increment the start-limit counter. This is belt-and-braces on top of
|
||||
/// the tmpfiles.d entries written by `SyncAgentTmpfiles`: in the unlikely
|
||||
/// event the dir is missing at start time, the unit idles rather than
|
||||
/// restart-looping into `start-limit-hit`.
|
||||
fn write_resource_limits(
|
||||
container: &str,
|
||||
memory_max: &str,
|
||||
cpu_quota: &str,
|
||||
) -> Result<(String, String)> {
|
||||
validate_container_system_name(container)?;
|
||||
// Derive the logical agent name (strip h- prefix) to form the runtime
|
||||
// dir path. Falls back to the full container name for infra containers
|
||||
// that don't use the h- prefix.
|
||||
let logical = container.strip_prefix(AGENT_PREFIX).unwrap_or(container);
|
||||
let runtime_dir = format!("{AGENT_RUNTIME_ROOT}/{logical}");
|
||||
let dir = format!("/run/systemd/system/container@{container}.service.d");
|
||||
std::fs::create_dir_all(&dir).with_context(|| format!("create {dir}"))?;
|
||||
let path = format!("{dir}/hyperhive-limits.conf");
|
||||
let content = format!("[Service]\nMemoryMax={memory_max}\nCPUQuota={cpu_quota}\n");
|
||||
// [Unit] section: condition checked at start time — skips (not fails)
|
||||
// the unit when the MCP socket dir is absent, avoiding restart loops.
|
||||
// [Service] section: resource caps.
|
||||
let content = format!(
|
||||
"[Unit]\n\
|
||||
ConditionPathIsDirectory={runtime_dir}\n\
|
||||
\n\
|
||||
[Service]\n\
|
||||
MemoryMax={memory_max}\n\
|
||||
CPUQuota={cpu_quota}\n"
|
||||
);
|
||||
std::fs::write(&path, content).with_context(|| format!("write {path}"))?;
|
||||
Ok((String::new(), String::new()))
|
||||
}
|
||||
|
|
@ -1512,7 +1539,6 @@ fn write_bridge_dns_marker(container: &str, isolation: Option<&NetworkIsolation>
|
|||
/// as `/run/hive`)
|
||||
/// - `/run/hive-agent/<name>` (web socket dir, bind-mounted into container)
|
||||
const TMPFILES_PATH: &str = "/etc/tmpfiles.d/hyperhive-agents.conf";
|
||||
const AGENT_RUNTIME_ROOT: &str = "/run/hyperhive/agents";
|
||||
|
||||
async fn sync_agent_tmpfiles(agents: &[String]) -> Result<(String, String)> {
|
||||
for name in agents {
|
||||
|
|
|
|||
Loading…
Reference in a new issue