priv: derive flake ref from agent name; WriteNspawnFlags takes flags only
This commit is contained in:
parent
8d5e97ce9f
commit
89d0937473
3 changed files with 64 additions and 31 deletions
|
|
@ -42,18 +42,12 @@ pub async fn kill_container(name: &str) -> Result<()> {
|
||||||
ok(call(&PrivRequest::KillContainer { name: name.to_owned() }).await?)
|
ok(call(&PrivRequest::KillContainer { name: name.to_owned() }).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn update_container(name: &str, flake_ref: &str) -> Result<(String, String)> {
|
pub async fn update_container(name: &str) -> Result<(String, String)> {
|
||||||
check(call(&PrivRequest::UpdateContainer {
|
check(call(&PrivRequest::UpdateContainer { name: name.to_owned() }).await?)
|
||||||
name: name.to_owned(),
|
|
||||||
flake_ref: flake_ref.to_owned(),
|
|
||||||
}).await?)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn create_container(name: &str, flake_ref: &str) -> Result<(String, String)> {
|
pub async fn create_container(name: &str) -> Result<(String, String)> {
|
||||||
check(call(&PrivRequest::CreateContainer {
|
check(call(&PrivRequest::CreateContainer { name: name.to_owned() }).await?)
|
||||||
name: name.to_owned(),
|
|
||||||
flake_ref: flake_ref.to_owned(),
|
|
||||||
}).await?)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn destroy_container(name: &str) -> Result<()> {
|
pub async fn destroy_container(name: &str) -> Result<()> {
|
||||||
|
|
@ -65,10 +59,10 @@ pub async fn list_containers() -> Result<String> {
|
||||||
Ok(stdout)
|
Ok(stdout)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn write_nspawn_conf(container: &str, content: &str) -> Result<()> {
|
pub async fn write_nspawn_flags(container: &str, extra_nspawn_flags: &str) -> Result<()> {
|
||||||
ok(call(&PrivRequest::WriteNspawnConf {
|
ok(call(&PrivRequest::WriteNspawnFlags {
|
||||||
container: container.to_owned(),
|
container: container.to_owned(),
|
||||||
content: content.to_owned(),
|
extra_nspawn_flags: extra_nspawn_flags.to_owned(),
|
||||||
}).await?)
|
}).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,10 @@ const SIBLING_CONTAINERS: &[&str] = &["hive-forge", "hive-matrix", "hive-gateway
|
||||||
/// Root of the per-agent unix-socket dirs on the host.
|
/// Root of the per-agent unix-socket dirs on the host.
|
||||||
const SOCKET_DIR_ROOT: &str = "/run/hive-agent";
|
const SOCKET_DIR_ROOT: &str = "/run/hive-agent";
|
||||||
|
|
||||||
|
/// Host path of the meta flake (mirrors `meta::meta_dir()`).
|
||||||
|
/// The flake ref for agent `<name>` is `{META_DIR}#{name}`.
|
||||||
|
const META_DIR: &str = "/var/lib/hyperhive/meta";
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
tracing_subscriber::fmt()
|
tracing_subscriber::fmt()
|
||||||
|
|
@ -163,16 +167,16 @@ async fn exec(req: PrivRequest) -> Result<(String, String)> {
|
||||||
container_run(&["kill", &container_system_name(name)]).await
|
container_run(&["kill", &container_system_name(name)]).await
|
||||||
}
|
}
|
||||||
|
|
||||||
PrivRequest::UpdateContainer { ref name, ref flake_ref } => {
|
PrivRequest::UpdateContainer { ref name } => {
|
||||||
validate_container_name(name)?;
|
validate_container_name(name)?;
|
||||||
validate_flake_ref(flake_ref)?;
|
let flake_ref = agent_flake_ref(name);
|
||||||
container_run(&["update", &container_system_name(name), "--flake", flake_ref]).await
|
container_run(&["update", &container_system_name(name), "--flake", &flake_ref]).await
|
||||||
}
|
}
|
||||||
|
|
||||||
PrivRequest::CreateContainer { ref name, ref flake_ref } => {
|
PrivRequest::CreateContainer { ref name } => {
|
||||||
validate_container_name(name)?;
|
validate_container_name(name)?;
|
||||||
validate_flake_ref(flake_ref)?;
|
let flake_ref = agent_flake_ref(name);
|
||||||
container_run(&["create", &container_system_name(name), "--flake", flake_ref]).await
|
container_run(&["create", &container_system_name(name), "--flake", &flake_ref]).await
|
||||||
}
|
}
|
||||||
|
|
||||||
PrivRequest::DestroyContainer { ref name } => {
|
PrivRequest::DestroyContainer { ref name } => {
|
||||||
|
|
@ -182,10 +186,9 @@ async fn exec(req: PrivRequest) -> Result<(String, String)> {
|
||||||
|
|
||||||
PrivRequest::ListContainers => container_run(&["list"]).await,
|
PrivRequest::ListContainers => container_run(&["list"]).await,
|
||||||
|
|
||||||
PrivRequest::WriteNspawnConf { ref container, ref content } => {
|
PrivRequest::WriteNspawnFlags { ref container, ref extra_nspawn_flags } => {
|
||||||
validate_container_system_name(container)?;
|
validate_container_system_name(container)?;
|
||||||
let path = format!("/etc/nixos-containers/{container}.conf");
|
write_nspawn_flags(container, extra_nspawn_flags)?;
|
||||||
std::fs::write(&path, content).with_context(|| format!("write {path}"))?;
|
|
||||||
Ok((String::new(), String::new()))
|
Ok((String::new(), String::new()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -354,9 +357,42 @@ fn validate_name_chars(name: &str) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_flake_ref(flake_ref: &str) -> Result<()> {
|
/// Derive the meta-flake ref for an agent by name.
|
||||||
if flake_ref.is_empty() || flake_ref.contains('\n') || flake_ref.contains('\0') {
|
fn agent_flake_ref(name: &str) -> String {
|
||||||
bail!("invalid flake_ref {flake_ref:?}");
|
format!("{META_DIR}#{name}")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Update `/etc/nixos-containers/<container>.conf`: strips network-isolation
|
||||||
|
/// vars (`PRIVATE_NETWORK`, `HOST_ADDRESS*`, `LOCAL_ADDRESS*`, `HOST_BRIDGE`,
|
||||||
|
/// `EXTRA_NSPAWN_FLAGS`), forces `PRIVATE_NETWORK=0` and blank network vars,
|
||||||
|
/// then appends `EXTRA_NSPAWN_FLAGS="<flags>"`.
|
||||||
|
fn write_nspawn_flags(container: &str, extra_nspawn_flags: &str) -> Result<()> {
|
||||||
|
let path = format!("/etc/nixos-containers/{container}.conf");
|
||||||
|
let original = std::fs::read_to_string(&path)
|
||||||
|
.with_context(|| format!("read {path}"))?;
|
||||||
|
let mut lines: Vec<&str> = original
|
||||||
|
.lines()
|
||||||
|
.filter(|line| {
|
||||||
|
let t = line.trim_start();
|
||||||
|
!t.starts_with("EXTRA_NSPAWN_FLAGS=")
|
||||||
|
&& !t.starts_with("PRIVATE_NETWORK=")
|
||||||
|
&& !t.starts_with("HOST_ADDRESS=")
|
||||||
|
&& !t.starts_with("LOCAL_ADDRESS=")
|
||||||
|
&& !t.starts_with("HOST_ADDRESS6=")
|
||||||
|
&& !t.starts_with("LOCAL_ADDRESS6=")
|
||||||
|
&& !t.starts_with("HOST_BRIDGE=")
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
let mut out = lines.join("\n");
|
||||||
|
if !out.is_empty() {
|
||||||
|
out.push('\n');
|
||||||
}
|
}
|
||||||
Ok(())
|
out.push_str("PRIVATE_NETWORK=0\n");
|
||||||
|
out.push_str("HOST_ADDRESS=\n");
|
||||||
|
out.push_str("LOCAL_ADDRESS=\n");
|
||||||
|
out.push_str("HOST_ADDRESS6=\n");
|
||||||
|
out.push_str("LOCAL_ADDRESS6=\n");
|
||||||
|
out.push_str("HOST_BRIDGE=\n");
|
||||||
|
out.push_str(&format!("EXTRA_NSPAWN_FLAGS=\"{extra_nspawn_flags}\"\n"));
|
||||||
|
std::fs::write(&path, out).with_context(|| format!("write {path}"))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,10 +29,12 @@ pub enum PrivRequest {
|
||||||
KillContainer { name: String },
|
KillContainer { name: String },
|
||||||
|
|
||||||
/// `nixos-container update <name> --flake <flake_ref>`
|
/// `nixos-container update <name> --flake <flake_ref>`
|
||||||
UpdateContainer { name: String, flake_ref: String },
|
/// The flake ref is derived from `name` by hive-priv.
|
||||||
|
UpdateContainer { name: String },
|
||||||
|
|
||||||
/// `nixos-container create <name> --flake <flake_ref>`
|
/// `nixos-container create <name> --flake <flake_ref>`
|
||||||
CreateContainer { name: String, flake_ref: String },
|
/// The flake ref is derived from `name` by hive-priv.
|
||||||
|
CreateContainer { name: String },
|
||||||
|
|
||||||
/// `nixos-container destroy <name>`
|
/// `nixos-container destroy <name>`
|
||||||
DestroyContainer { name: String },
|
DestroyContainer { name: String },
|
||||||
|
|
@ -42,9 +44,10 @@ pub enum PrivRequest {
|
||||||
|
|
||||||
// --- Config file writes ---
|
// --- Config file writes ---
|
||||||
|
|
||||||
/// Overwrite `/etc/nixos-containers/<container>.conf` with new content.
|
/// Update `/etc/nixos-containers/<container>.conf`: strip network-isolation
|
||||||
/// Written by `lifecycle::set_nspawn_flags` to inject `EXTRA_NSPAWN_FLAGS`.
|
/// vars, force `PRIVATE_NETWORK=0`, and set `EXTRA_NSPAWN_FLAGS`.
|
||||||
WriteNspawnConf { container: String, content: String },
|
/// Written by `lifecycle::set_nspawn_flags`.
|
||||||
|
WriteNspawnFlags { container: String, extra_nspawn_flags: String },
|
||||||
|
|
||||||
/// Write `/run/systemd/system/container@<container>.service.d/hyperhive-limits.conf`
|
/// Write `/run/systemd/system/container@<container>.service.d/hyperhive-limits.conf`
|
||||||
/// with `[Service]\nMemoryMax=<memory_max>\nCPUQuota=<cpu_quota>\n`.
|
/// with `[Service]\nMemoryMax=<memory_max>\nCPUQuota=<cpu_quota>\n`.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue