From b174d743c0c5e0acf39809285c06d835579e2e4b Mon Sep 17 00:00:00 2001 From: jochen Date: Thu, 22 Oct 2026 00:56:48 +0200 Subject: [PATCH] Name the build slice without a dash so it sits beside user.slice, and restart it when its limits change (issue 1798) --- internal/builder/kill_test.go | 4 ++-- modules/build-agent/files/build-agent.env | 2 +- .../{mesh-build.slice => meshbuild.slice} | 2 +- modules/build-agent/manifest_test.go | 22 +++++++++++++++---- modules/build-agent/module.json | 11 ++++++---- 5 files changed, 29 insertions(+), 12 deletions(-) rename modules/build-agent/files/{mesh-build.slice => meshbuild.slice} (80%) diff --git a/internal/builder/kill_test.go b/internal/builder/kill_test.go index 7e50027c..a963586d 100644 --- a/internal/builder/kill_test.go +++ b/internal/builder/kill_test.go @@ -150,9 +150,9 @@ func TestAVolumeAlreadyGoneIsNoFailure(t *testing.T) { func TestEveryContainerJoinsTheNodesBuildSlice(t *testing.T) { was := CgroupParent defer func() { CgroupParent = was }() - CgroupParent = "mesh-build.slice" + CgroupParent = "meshbuild.slice" got := LabelledArgs("docker", []string{"run", "--rm", "img", "sh"}, "build-1") - want := []string{"run", "--label", "mesh.build=build-1", "--cgroup-parent", "mesh-build.slice", "--rm", "img", "sh"} + want := []string{"run", "--label", "mesh.build=build-1", "--cgroup-parent", "meshbuild.slice", "--rm", "img", "sh"} if !reflect.DeepEqual(got, want) { t.Errorf("1798/AC1: docker run became %v", got) } diff --git a/modules/build-agent/files/build-agent.env b/modules/build-agent/files/build-agent.env index 2edbdf6a..819098b4 100644 --- a/modules/build-agent/files/build-agent.env +++ b/modules/build-agent/files/build-agent.env @@ -6,4 +6,4 @@ MESH_NPM_TOKEN_FILE=/run/mesh/package-registry.secret MESH_GENESIS_PACKAGE_REGISTRY=/run/mesh/genesis-package-registry.json MESH_WORKSPACE=${dir:workspace} MESH_JUDGE_CACHE=${dir:judge-cache} -MESH_BUILD_CGROUP_PARENT=mesh-build.slice +MESH_BUILD_CGROUP_PARENT=meshbuild.slice diff --git a/modules/build-agent/files/mesh-build.slice b/modules/build-agent/files/meshbuild.slice similarity index 80% rename from modules/build-agent/files/mesh-build.slice rename to modules/build-agent/files/meshbuild.slice index 6c8b417a..6258a1af 100644 --- a/modules/build-agent/files/mesh-build.slice +++ b/modules/build-agent/files/meshbuild.slice @@ -1,7 +1,7 @@ # Managed by the mesh (module build-agent). Replaced on every push; edit the module's settings instead. # # Everything a build or check starts on this machine runs in this slice (novox/hq issue 1798): the build -# agent starts every container with --cgroup-parent=mesh-build.slice. The weights only bind while the machine +# agent starts every container with --cgroup-parent=meshbuild.slice. The weights only bind while the machine # is busy, so an idle machine still builds at full speed; the memory limits are the part that always binds. [Slice] CPUWeight=${setting:cpu-weight} diff --git a/modules/build-agent/manifest_test.go b/modules/build-agent/manifest_test.go index 388494d5..06d0f7ff 100644 --- a/modules/build-agent/manifest_test.go +++ b/modules/build-agent/manifest_test.go @@ -203,7 +203,7 @@ func TestTheBuildSliceCarriesTheMachinesLimits(t *testing.T) { if err := json.Unmarshal(raw, &m); err != nil { t.Fatal(err) } - slice, err := os.ReadFile("files/mesh-build.slice") + slice, err := os.ReadFile("files/meshbuild.slice") if err != nil { t.Fatal(err) } @@ -217,17 +217,31 @@ func TestTheBuildSliceCarriesTheMachinesLimits(t *testing.T) { } var placed, running bool for _, r := range read(t).Resources { - placed = placed || (r["type"] == "file" && r["path"] == "/etc/systemd/system/mesh-build.slice") - running = running || (r["type"] == "service" && r["unit"] == "mesh-build.slice" && r["state"] == "running") + placed = placed || (r["type"] == "file" && r["path"] == "/etc/systemd/system/meshbuild.slice") + running = running || (r["type"] == "service" && r["unit"] == "meshbuild.slice" && r["state"] == "running") } if !placed || !running { t.Errorf("1798/AC2: the slice must be placed (%v) and running (%v)", placed, running) } + // 1798/AC3: a dash in a slice's name nests it in the slice named before the dash, and cgroup v2 weights only + // compare siblings, so the name has none and the slice sits at the top level beside user.slice. + for _, r := range read(t).Resources { + if r["type"] == "service" && r["unit"] == "meshbuild.slice" { + if strings.Contains(strings.TrimSuffix(r["unit"].(string), ".slice"), "-") { + t.Errorf("1798/AC3: slice name %v nests", r["unit"]) + } + // 1798/AC4: a changed limit reaches systemd only if the unit restarts when its file changes. + restart, _ := r["restart-on"].([]any) + if len(restart) != 1 || restart[0] != "build-slice" { + t.Errorf("1798/AC4: the slice unit does not restart on its file: %v", restart) + } + } + } env, err := os.ReadFile("files/build-agent.env") if err != nil { t.Fatal(err) } - if !strings.Contains(string(env), "MESH_BUILD_CGROUP_PARENT=mesh-build.slice") { + if !strings.Contains(string(env), "MESH_BUILD_CGROUP_PARENT=meshbuild.slice") { t.Error("1798/AC1: the agent is not told the slice's name") } } diff --git a/modules/build-agent/module.json b/modules/build-agent/module.json index a85ebd1a..09a4dd32 100644 --- a/modules/build-agent/module.json +++ b/modules/build-agent/module.json @@ -105,16 +105,19 @@ { "id": "build-slice", "type": "file", - "path": "/etc/systemd/system/mesh-build.slice", + "path": "/etc/systemd/system/meshbuild.slice", "mode": "0644", "trusted": false, - "template": "files/mesh-build.slice" + "template": "files/meshbuild.slice" }, { "id": "build-slice-unit", "type": "service", - "unit": "mesh-build.slice", - "state": "running" + "unit": "meshbuild.slice", + "state": "running", + "restart-on": [ + "build-slice" + ] }, { "id": "agent-env",