Skip to content
Merged
Show file tree
Hide file tree
Changes from 42 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
1133edf
fix(portable): preflight CPU delegation
prekshivyas Aug 15, 2026
068edc4
merge: update branch from main
cv Aug 15, 2026
a5fd107
fix(ci): run CPU delegation proof through Vitest
cv Aug 15, 2026
a55ddba
test(e2e): declare CPU delegation proof phases
cv Aug 15, 2026
bd8d014
fix(ci): run CPU delegation through live E2E
prekshivyas Aug 15, 2026
f158149
fix(ci): start proof after delegation setup
prekshivyas Aug 15, 2026
cf23f62
fix(ci): complete CPU delegation proof gates
prekshivyas Aug 15, 2026
6918d55
fix(ci): build shared contract before live proof
prekshivyas Aug 15, 2026
f943a48
fix(ci): activate CPU controller for proof user
prekshivyas Aug 15, 2026
34e0ffb
fix(ci): inspect the managed application slice
prekshivyas Aug 15, 2026
8b206d8
fix(ci): configure active proof user slice
prekshivyas Aug 15, 2026
f821404
merge: reconcile CPU delegation proof fixes
prekshivyas Aug 15, 2026
1f2a666
merge: preserve reviewed CPU delegation proof
prekshivyas Aug 15, 2026
7e20cb2
fix(ci): activate proof slice CPU controller
prekshivyas Aug 15, 2026
34e0800
fix(portable): harden CPU delegation recovery
prekshivyas Aug 15, 2026
8da8055
merge: combine protected CPU proof fixes
prekshivyas Aug 15, 2026
b0d5812
fix(ci): grant proof user checkout traversal
prekshivyas Aug 15, 2026
38e045b
fix(ci): stabilize CPU delegation proof
prekshivyas Aug 15, 2026
e756155
merge: preserve reviewed CPU proof
prekshivyas Aug 15, 2026
282fb72
merge: update branch from main
cv Aug 15, 2026
9c5a106
fix(ci): prepare writable CPU proof cache
cv Aug 15, 2026
afc0aec
docs(portable): stop failed delegation sequences
cv Aug 15, 2026
cd20a45
docs(portable): define rollback verification path
cv Aug 15, 2026
6d303ef
fix(portable): activate app slice CPU controller
cv Aug 15, 2026
5a50252
docs(portable): describe default CPU weight
cv Aug 15, 2026
4e458a9
fix(portable): complete CPU recovery guidance
cv Aug 15, 2026
decacce
merge(main): incorporate current CI requirements
cv Aug 15, 2026
7fc0121
merge(main): incorporate current CI requirements
cv Aug 15, 2026
527672c
fix(portable): create delegation drop-ins exclusively
cv Aug 15, 2026
b921d44
fix(portable): preserve drop-in failure boundaries
cv Aug 15, 2026
fee1582
fix(portable): publish delegation drop-ins atomically
cv Aug 15, 2026
c3c53cc
test(portable): keep drop-in helper linear
cv Aug 15, 2026
d83a458
merge(main): incorporate current CI requirements
prekshivyas Aug 15, 2026
775edee
merge: preserve reviewed CPU proof
prekshivyas Aug 15, 2026
9295c16
merge(main): incorporate current CI requirements
prekshivyas Aug 15, 2026
36ae5d1
merge: restore passing CPU delegation proof
prekshivyas Aug 15, 2026
03061bf
fix(ci): harden CPU proof cleanup receipts
prekshivyas Aug 15, 2026
97b2588
fix(ci): retain workspace mode receipts
prekshivyas Aug 15, 2026
e88c573
test(portable): execute rollback guidance
cv Aug 15, 2026
2e6770c
Merge branch 'codex/replace-pr9195-cpu-delegation' of github.com:NVID…
cv Aug 15, 2026
4286eb8
test(portable): cite CPU delegation issue
cv Aug 15, 2026
dfdcf71
test(docs): emulate Linux rollback tools
prekshivyas Aug 15, 2026
1c533a5
fix(portable): complete CPU delegation recovery
prekshivyas Aug 15, 2026
b47894a
test(docs): keep replaced inode allocated
prekshivyas Aug 15, 2026
3428aaa
ci(portable): extract CPU proof preparation
prekshivyas Aug 15, 2026
e820630
fix(onboard): harden portable CPU delegation admission
senthilr-nv Aug 16, 2026
c401745
fix(portable): activate the per-user CPU controller
senthilr-nv Aug 16, 2026
fc3e321
docs(portable): clarify CPU hierarchy verification
senthilr-nv Aug 16, 2026
3f053be
docs(portable): isolate CPU delegation guidance
senthilr-nv Aug 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
703 changes: 703 additions & 0 deletions .github/workflows/podman-cpu-proof.yaml

Large diffs are not rendered by default.

403 changes: 403 additions & 0 deletions docs/reference/troubleshooting.mdx

Large diffs are not rendered by default.

218 changes: 218 additions & 0 deletions src/lib/onboard/experimental/portable-cpu-delegation-preflight.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

import { describe, expect, it } from "vitest";
import {
cpuDelegationControllerPaths,
inspectPortableCpuDelegation,
portableCpuDelegationError,
} from "./portable-cpu-delegation-preflight";

function files(contents: Record<string, string>): (file: string) => string {
return (file: string) => {
const value = contents[file];
return (
value ??
(() => {
throw Object.assign(new Error(`ENOENT: no such file or directory, open '${file}'`), {
code: "ENOENT",
});
})()
);
};
}

function unreadableAt(
unreadableFile: string,
contents: Record<string, string>,
): (file: string) => string {
const readFile = files(contents);
const throwUnreadable = (file: string): never => {
throw Object.assign(new Error(`EACCES: permission denied, open '${file}'`), {
code: "EACCES",
});
};
return (file: string) => (file === unreadableFile ? throwUnreadable(file) : readFile(file));
}

const UID = 1001;
const PATHS = cpuDelegationControllerPaths(UID);

const CPU_FULL = "cpuset cpu io memory pids";
const NO_CPU = "cpuset io memory pids";

describe("inspectPortableCpuDelegation", () => {
it("skips the check on non-Linux platforms", () => {
const preflight = inspectPortableCpuDelegation({
platform: "darwin",
uid: UID,
});
expect(preflight.ok).toBe(true);
});

it("reports cgroups v2 unavailable when the root controllers file is missing", () => {
const preflight = inspectPortableCpuDelegation({
platform: "linux",
uid: UID,
readFileSync: files({}),
});
expect(preflight.ok).toBe(false);
expect(preflight.failure).toBe("cgroups-v2-unavailable");
expect(preflight.detail).toContain("cgroups v2");
});

it("reports access recovery when the root controllers file is unreadable", () => {
const preflight = inspectPortableCpuDelegation({
platform: "linux",
uid: UID,
readFileSync: unreadableAt(PATHS.root, {}),
});
expect(preflight.ok).toBe(false);
expect(preflight.failure).toBe("cgroup-controllers-unreadable");
expect(preflight.detail).toContain("EACCES");
expect(preflight.detail).toContain("mount permissions");
expect(preflight.detail).toContain("security policy");
expect(preflight.detail).not.toContain("Boot a cgroups v2 host");
});

it("reports when the kernel hierarchy does not expose the cpu controller", () => {
const preflight = inspectPortableCpuDelegation({
platform: "linux",
uid: UID,
readFileSync: files({
[PATHS.root]: NO_CPU,
[PATHS.userManager]: CPU_FULL,
[PATHS.appSlice]: CPU_FULL,
}),
});
expect(preflight.ok).toBe(false);
expect(preflight.failure).toBe("cpu-controller-unavailable");
expect(preflight.detail).toContain('no "cpu"');
});

it("reports when systemd did not delegate cpu to the user manager (missing file)", () => {
const preflight = inspectPortableCpuDelegation({
platform: "linux",
uid: UID,
readFileSync: files({
[PATHS.root]: CPU_FULL,
}),
});
expect(preflight.ok).toBe(false);
expect(preflight.failure).toBe("systemd-user-delegation-missing");
expect(preflight.detail).toContain("`Delegate=cpu memory pids` for `user@.service`");
expect(preflight.detail).toContain("`CPUWeight=100` for `app.slice`");
});

it("reports access recovery when the user manager controllers file is unreadable", () => {
const preflight = inspectPortableCpuDelegation({
platform: "linux",
uid: UID,
readFileSync: unreadableAt(PATHS.userManager, {
[PATHS.root]: CPU_FULL,
}),
});
expect(preflight.ok).toBe(false);
expect(preflight.failure).toBe("cgroup-controllers-unreadable");
expect(preflight.detail).toContain("EACCES");
expect(preflight.detail).toContain("Do not change systemd delegation");
expect(preflight.detail).not.toContain("restart the user manager");
});

it("reports when systemd did not delegate cpu to the user manager (no cpu token)", () => {
const preflight = inspectPortableCpuDelegation({
platform: "linux",
uid: UID,
readFileSync: files({
[PATHS.root]: CPU_FULL,
[PATHS.userManager]: NO_CPU,
[PATHS.appSlice]: CPU_FULL,
}),
});
expect(preflight.ok).toBe(false);
expect(preflight.failure).toBe("systemd-user-delegation-missing");
expect(preflight.detail).toContain("`Delegate=cpu memory pids` for `user@.service`");
expect(preflight.detail).toContain("`CPUWeight=100` for `app.slice`");
});

it("reports when the cpu controller is not available to app.slice for this boot", () => {
const preflight = inspectPortableCpuDelegation({
platform: "linux",
uid: UID,
readFileSync: files({
[PATHS.root]: CPU_FULL,
[PATHS.userManager]: CPU_FULL,
[PATHS.appSlice]: NO_CPU,
}),
});
expect(preflight.ok).toBe(false);
expect(preflight.failure).toBe("app-slice-cpu-unavailable");
expect(preflight.detail).toContain("app.slice");
expect(preflight.detail).toContain("CPU controller setting");
});

it("reports when the app.slice controllers file is missing", () => {
const preflight = inspectPortableCpuDelegation({
platform: "linux",
uid: UID,
readFileSync: files({
[PATHS.root]: CPU_FULL,
[PATHS.userManager]: CPU_FULL,
}),
});
expect(preflight.ok).toBe(false);
expect(preflight.failure).toBe("app-slice-cpu-unavailable");
expect(preflight.detail).toContain("CPU controller setting");
});

it("reports access recovery when the app.slice controllers file is unreadable", () => {
const preflight = inspectPortableCpuDelegation({
platform: "linux",
uid: UID,
readFileSync: unreadableAt(PATHS.appSlice, {
[PATHS.root]: CPU_FULL,
[PATHS.userManager]: CPU_FULL,
}),
});
expect(preflight.ok).toBe(false);
expect(preflight.failure).toBe("cgroup-controllers-unreadable");
expect(preflight.detail).toContain("EACCES");
expect(preflight.detail).toContain("Do not change systemd delegation");
expect(preflight.detail).not.toContain("Restart the user manager");
});

it("passes when cpu is delegated through the whole current-user hierarchy", () => {
const preflight = inspectPortableCpuDelegation({
platform: "linux",
uid: UID,
readFileSync: files({
[PATHS.root]: CPU_FULL,
[PATHS.userManager]: CPU_FULL,
[PATHS.appSlice]: CPU_FULL,
}),
});
expect(preflight.ok).toBe(true);
expect(preflight.failure).toBeUndefined();
expect(preflight.detail).toContain("cpu controller");
});

it("skips when the user id cannot be resolved", () => {
const preflight = inspectPortableCpuDelegation({
platform: "linux",
uid: Number.NaN,
readFileSync: files({}),
});
expect(preflight.ok).toBe(true);
});

it("formats a throwable error from a failed inspection", () => {
const preflight = inspectPortableCpuDelegation({
platform: "linux",
uid: UID,
readFileSync: files({}),
});
const error = portableCpuDelegationError(preflight);
expect(error.message).toContain("Portable CPU-delegation preflight failed");
expect(error.message).toContain("cgroups v2");
});
});
Loading
Loading