gateway: fix nginx reload — trigger from host via systemd-run (#889)
The #872 path-unit approach was silently broken: IN_MOVED_TO from an atomic rename on the host does not propagate across the nspawn mount-namespace boundary into the container, so the watcher inside the gateway container never fired. Fix: after each agents.conf write, c0re calls `systemd-run --machine=hive-gateway -- nginx -s reload` from the host. The reload is best-effort (logged on failure, not fatal). Remove the now-unused `hive-gateway-agents-conf.path` + `hive-gateway-nginx-reload.service` from the gateway container config. Update docs/gateway.md + comments to reflect the host-side approach.
This commit is contained in:
parent
21213be1b6
commit
01d7c37af2
3 changed files with 91 additions and 60 deletions
|
|
@ -1,7 +1,7 @@
|
|||
//! Runtime nginx include-file generator for the gateway's per-agent
|
||||
//! `/agent/<name>/` location blocks (#869).
|
||||
//!
|
||||
//! Writes `/var/lib/hyperhive/agents.conf` on every topology change.
|
||||
//! Writes `/var/lib/hyperhive/gateway/agents.conf` on every topology change.
|
||||
//! The gateway container bind-mounts the whole `/var/lib/hyperhive/`
|
||||
//! directory at `/run/hive-state/` and nginx includes
|
||||
//! `/run/hive-state/agents.conf`. A systemd path unit inside the
|
||||
|
|
@ -105,11 +105,23 @@ fn render(names: &[String]) -> String {
|
|||
}
|
||||
|
||||
/// Atomically write the nginx include file for `names` to
|
||||
/// [`host_conf_path()`]. Skips the rename when the rendered body
|
||||
/// matches what's already on disk (idempotent; avoids spurious
|
||||
/// gateway reloads on a quiet tick). On a fresh install where the
|
||||
/// file doesn't exist yet, writes an empty-but-valid config so nginx
|
||||
/// can start before any agents have registered.
|
||||
/// [`host_conf_path()`]. Skips the write + reload when the rendered
|
||||
/// body matches what's already on disk (idempotent; avoids spurious
|
||||
/// gateway reloads on a quiet tick).
|
||||
///
|
||||
/// After a successful write, triggers an nginx reload inside the
|
||||
/// gateway container from the HOST side via
|
||||
/// `systemd-run --machine=hive-gateway nginx -s reload`. This is
|
||||
/// intentionally host-side rather than relying on a systemd path unit
|
||||
/// inside the container watching the bind-mounted file: `IN_MOVED_TO`
|
||||
/// (fired by the atomic rename) does not reliably propagate across the
|
||||
/// nspawn mount-namespace boundary, so the path-unit approach was
|
||||
/// silently broken after #872 merged (#889).
|
||||
///
|
||||
/// The `systemd-run` call is best-effort — a failed reload is logged
|
||||
/// but not fatal. nginx will pick up the new include on its next
|
||||
/// housekeeping restart or the next manual reload; the host's agent
|
||||
/// topology has already been written correctly.
|
||||
pub fn write(names: &[String]) -> Result<()> {
|
||||
let body = render(names);
|
||||
let path = host_conf_path();
|
||||
|
|
@ -130,9 +142,49 @@ pub fn write(names: &[String]) -> Result<()> {
|
|||
path.display()
|
||||
)
|
||||
})?;
|
||||
// Trigger nginx reload from the host. Ignore errors — a failed
|
||||
// reload is recoverable (nginx keeps serving the previous config).
|
||||
reload_gateway_nginx();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Send `nginx -s reload` to the gateway container via systemd-run.
|
||||
/// Runs non-interactively in a transient scope so it doesn't block
|
||||
/// c0re's polling loop. Best-effort: errors are logged, not bubbled.
|
||||
fn reload_gateway_nginx() {
|
||||
// `--machine=hive-gateway` targets the container by its nspawn
|
||||
// machine name (same as the nixos-container name). `--quiet`
|
||||
// suppresses the transient unit name echo. `--` separates
|
||||
// systemd-run args from the command.
|
||||
let status = std::process::Command::new("systemd-run")
|
||||
.args([
|
||||
"--machine=hive-gateway",
|
||||
"--quiet",
|
||||
"--",
|
||||
"nginx",
|
||||
"-s",
|
||||
"reload",
|
||||
])
|
||||
.status();
|
||||
match status {
|
||||
Ok(s) if s.success() => {
|
||||
tracing::debug!("gateway nginx reloaded successfully");
|
||||
}
|
||||
Ok(s) => {
|
||||
tracing::warn!(
|
||||
exit_code = ?s.code(),
|
||||
"gateway nginx reload exited non-zero; will pick up on next restart"
|
||||
);
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::warn!(
|
||||
error = %e,
|
||||
"failed to invoke systemd-run for gateway nginx reload"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
|||
Loading…
Reference in a new issue