Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
68 changes: 68 additions & 0 deletions src/lib/onboard/preflight.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -843,6 +843,38 @@ describe("getNvidiaCdiSpecPath", () => {
});

describe("planHostRemediation", () => {
function baseAssessment(
overrides: Partial<Parameters<typeof planHostRemediation>[0]> = {},
): Parameters<typeof planHostRemediation>[0] {
return {
platform: "linux",
isWsl: false,
runtime: "unknown",
packageManager: "apt",
systemctlAvailable: true,
dockerServiceActive: null,
dockerServiceEnabled: null,
dockerInstalled: true,
dockerRunning: false,
dockerReachable: false,
nodeInstalled: true,
openshellInstalled: true,
dockerCgroupVersion: "unknown",
dockerDefaultCgroupnsMode: "unknown",
isContainerRuntimeUnderProvisioned: false,
hasNestedOverlayConflict: false,
requiresHostCgroupnsFix: false,
isUnsupportedRuntime: false,
isHeadlessLikely: false,
hasNvidiaGpu: false,
dockerCdiSpecDirs: [],
cdiNvidiaGpuSpecMissing: false,
nvidiaContainerToolkitInstalled: true,
notes: [],
...overrides,
};
}

it("recommends starting docker when installed but unreachable and service inactive", () => {
const actions = planHostRemediation({
platform: "linux",
Expand Down Expand Up @@ -876,6 +908,42 @@ describe("planHostRemediation", () => {
expect(actions[0].commands).toContain("sudo systemctl start docker");
});

it("recommends Docker Desktop WSL integration when docker is missing inside WSL", () => {
const actions = planHostRemediation(
baseAssessment({
isWsl: true,
dockerInstalled: false,
systemctlAvailable: false,
}),
);

expect(actions[0].id).toBe("enable_docker_desktop_wsl_integration");
expect(actions[0].title).toBe("Enable Docker Desktop WSL integration");
expect(actions[0].blocking).toBe(true);
expect(actions[0].commands.join("\n")).toContain(
"Docker Desktop → Settings → Resources → WSL integration",
);
expect(actions[0].commands.join("\n")).toContain("wsl --shutdown");
expect(actions[0].commands.join("\n")).toContain("docker info");
});

it("recommends Docker Desktop WSL integration when docker is unreachable inside WSL", () => {
const actions = planHostRemediation(
baseAssessment({
isWsl: true,
dockerInstalled: true,
dockerServiceActive: true,
systemctlAvailable: false,
}),
);

expect(actions[0].id).toBe("enable_docker_desktop_wsl_integration");
expect(actions[0].reason).toContain("WSL distro cannot reach the Docker daemon");
expect(actions[0].commands.join("\n")).toContain("Start Docker Desktop");
expect(actions[0].commands.join("\n")).toContain("wsl --shutdown");
expect(actions[0].commands.join("\n")).not.toContain("sudo systemctl start docker");
});

it("suggests usermod when docker service is active but daemon is unreachable", () => {
const actions = planHostRemediation({
platform: "linux",
Expand Down
37 changes: 33 additions & 4 deletions src/lib/onboard/preflight.ts
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,23 @@ export function planHostRemediation(assessment: HostAssessment): RemediationActi
const actions: RemediationAction[] = [];

if (!assessment.dockerInstalled) {
if (assessment.isWsl) {
actions.push({
id: "enable_docker_desktop_wsl_integration",
title: "Enable Docker Desktop WSL integration",
kind: "manual",
reason:
"Docker is not available inside this WSL distro. When using Docker Desktop on Windows, WSL integration must be enabled for the Ubuntu distro before NemoClaw can create a gateway or sandbox.",
commands: [
"Open Docker Desktop → Settings → Resources → WSL integration.",
"Enable integration for this Ubuntu distro, apply the change, then run `wsl --shutdown` from Windows PowerShell.",
"Reopen Ubuntu, verify `docker info`, then rerun `nemoclaw onboard`.",
],
blocking: true,
});
return actions;
}

const installCommands: Record<PackageManager, string> = {
apt: "Install Docker Engine, then rerun `nemoclaw onboard`.",
dnf: "Install Docker Engine with your package manager, then rerun `nemoclaw onboard`.",
Expand All @@ -684,15 +701,27 @@ export function planHostRemediation(assessment: HostAssessment): RemediationActi
const likelyGroupIssue =
assessment.platform === "linux" && assessment.dockerServiceActive === true;

if (likelyGroupIssue) {
if (assessment.isWsl) {
actions.push({
id: "enable_docker_desktop_wsl_integration",
title: "Enable Docker Desktop WSL integration",
kind: "manual",
reason:
"Docker is installed but this WSL distro cannot reach the Docker daemon. Docker Desktop may not be running, or WSL integration may be disabled for this distro.",
commands: [
"Start Docker Desktop on Windows.",
"Open Docker Desktop → Settings → Resources → WSL integration and enable integration for this Ubuntu distro.",
"Apply the change, run `wsl --shutdown` from Windows PowerShell, reopen Ubuntu, verify `docker info`, then rerun `nemoclaw onboard`.",
],
blocking: true,
});
return actions;
} else if (likelyGroupIssue) {
Comment thread
coderabbitai[bot] marked this conversation as resolved.
const commands = [
"sudo usermod -aG docker $USER",
"newgrp docker # or log out and back in",
"nemoclaw onboard",
];
if (assessment.isWsl) {
commands.unshift(DOCKER_DESKTOP_WSL_INTEGRATION_HINT);
}
actions.push({
id: "docker_group_permission",
title: "Add user to docker group",
Expand Down