feat: socket-activate the hive-c0re admin socket
Add a systemd.sockets.hive-c0re unit that holds /run/hyperhive/host.sock before hive-c0re starts. hive-c0re serve() detects LISTEN_FDS via the listenfd crate and accepts the systemd-handed fd instead of calling bind(). Falls back to the existing bind path when LISTEN_FDS is absent so direct invocation and CI are unaffected. Benefits: hivectl can connect the moment the socket unit activates (no racy window), and a hive-c0re restart never drops the socket inode.
This commit is contained in:
parent
19e7d8d5d3
commit
f8c0f64fd4
3 changed files with 54 additions and 10 deletions
|
|
@ -13,6 +13,7 @@ reqwest.workspace = true
|
|||
clap.workspace = true
|
||||
hive-sh4re.workspace = true
|
||||
libc = "0.2"
|
||||
listenfd = "1"
|
||||
rusqlite.workspace = true
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
|
|
|
|||
|
|
@ -11,16 +11,33 @@ use crate::coordinator::Coordinator;
|
|||
use crate::lifecycle;
|
||||
|
||||
pub async fn serve(socket: &Path, coord: Arc<Coordinator>) -> Result<()> {
|
||||
if let Some(parent) = socket.parent() {
|
||||
std::fs::create_dir_all(parent)
|
||||
.with_context(|| format!("create socket parent {}", parent.display()))?;
|
||||
}
|
||||
if socket.exists() {
|
||||
std::fs::remove_file(socket).context("remove stale socket")?;
|
||||
}
|
||||
|
||||
let listener = UnixListener::bind(socket)
|
||||
.with_context(|| format!("bind admin socket {}", socket.display()))?;
|
||||
// Prefer a socket passed by systemd socket-activation (LISTEN_FDS).
|
||||
// When running under a `.socket` unit, systemd has already created,
|
||||
// bound, and chmod-ed the socket for us — we just accept on it.
|
||||
// Fall back to the traditional bind path when not socket-activated
|
||||
// (direct invocation, dev, tests).
|
||||
let listener = {
|
||||
let mut listenfd = listenfd::ListenFd::from_env();
|
||||
if let Some(std_listener) = listenfd
|
||||
.take_unix_listener(0)
|
||||
.context("take socket-activated unix listener")?
|
||||
{
|
||||
std_listener.set_nonblocking(true)?;
|
||||
UnixListener::from_std(std_listener)
|
||||
.context("convert socket-activated listener to tokio")?
|
||||
} else {
|
||||
// Standalone: create parent dir, remove any stale socket, bind.
|
||||
if let Some(parent) = socket.parent() {
|
||||
std::fs::create_dir_all(parent)
|
||||
.with_context(|| format!("create socket parent {}", parent.display()))?;
|
||||
}
|
||||
if socket.exists() {
|
||||
std::fs::remove_file(socket).context("remove stale socket")?;
|
||||
}
|
||||
UnixListener::bind(socket)
|
||||
.with_context(|| format!("bind admin socket {}", socket.display()))?
|
||||
}
|
||||
};
|
||||
tracing::info!(socket = %socket.display(), hyperhive_flake = %coord.hyperhive_flake, "hive-c0re admin listening");
|
||||
|
||||
loop {
|
||||
|
|
|
|||
|
|
@ -370,5 +370,31 @@ in
|
|||
StateDirectory = "hyperhive";
|
||||
};
|
||||
};
|
||||
|
||||
# Socket unit for the hive-c0re admin socket. systemd creates and holds
|
||||
# `/run/hyperhive/host.sock` before hive-c0re starts, then passes the fd
|
||||
# via LISTEN_FDS (socket activation). Benefits: `hivectl` can connect
|
||||
# the moment the socket unit is active — no racy retry window — and a
|
||||
# hive-c0re restart never drops the socket inode, so queued commands
|
||||
# drain cleanly.
|
||||
#
|
||||
# `hive-c0re serve` reads LISTEN_FDS via the `listenfd` crate and
|
||||
# accepts the fd in preference to its own `bind()` path. When invoked
|
||||
# directly (dev, CI, without the socket unit) LISTEN_FDS is absent and
|
||||
# the traditional bind path runs unchanged — no regression.
|
||||
systemd.sockets.hive-c0re = {
|
||||
description = "hive-c0re admin socket";
|
||||
wantedBy = [ "sockets.target" ];
|
||||
socketConfig = {
|
||||
# Must match the `--socket` arg passed to `hive-c0re serve`.
|
||||
ListenStream = "/run/hyperhive/host.sock";
|
||||
# 0660 root:root — `hivectl` is a host-only tool run as root.
|
||||
SocketMode = "0660";
|
||||
# Parent dir inherits the RuntimeDirectory mode (0750) set on the
|
||||
# service unit; DirectoryMode is only consulted when the dir is
|
||||
# absent at socket-unit activation.
|
||||
DirectoryMode = "0750";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue