@@ -1298,6 +1298,62 @@ docker_e2e_docker_cmd run second
12981298 }
12991299 } ) ;
13001300
1301+ it ( "retries Docker runs when rootless daemons reject NanoCPUs" , ( ) => {
1302+ const workDir = mkdtempSync ( join ( tmpdir ( ) , "openclaw-docker-rootless-nanocpus-" ) ) ;
1303+
1304+ try {
1305+ const binDir = join ( workDir , "bin" ) ;
1306+ mkdirSync ( binDir ) ;
1307+ writeFileSync (
1308+ join ( binDir , "timeout" ) ,
1309+ `#!/bin/bash
1310+ set -euo pipefail
1311+ if [[ "$1" = "--kill-after=1s" ]]; then
1312+ exit 0
1313+ fi
1314+ shift 2
1315+ "$@"
1316+ ` ,
1317+ ) ;
1318+ chmodSync ( join ( binDir , "timeout" ) , 0o755 ) ;
1319+ const rootDir = process . cwd ( ) ;
1320+ const script = `
1321+ set -euo pipefail
1322+ ROOT_DIR=${ shellQuote ( rootDir ) }
1323+ TMPDIR=${ shellQuote ( workDir ) }
1324+ export ROOT_DIR TMPDIR
1325+ export PATH="$TMPDIR/bin:$PATH"
1326+ unset OPENCLAW_DOCKER_E2E_DISABLE_RESOURCE_LIMITS
1327+ unset OPENCLAW_DOCKER_E2E_MEMORY OPENCLAW_DOCKER_E2E_CPUS OPENCLAW_DOCKER_E2E_PIDS_LIMIT
1328+ export OPENCLAW_DOCKER_E2E_AVAILABLE_CPUS=32
1329+
1330+ docker() {
1331+ printf "%s\\n" "$*" >>"$TMPDIR/docker-seen"
1332+ if [[ "$*" == *"--cpus"* ]]; then
1333+ echo "docker: Error response from daemon: NanoCPUs can not be set, as your kernel does not support CPU CFS scheduler or the cgroup is not mounted" >&2
1334+ return 125
1335+ fi
1336+ }
1337+ export -f docker
1338+
1339+ source "$ROOT_DIR/scripts/lib/docker-e2e-container.sh"
1340+
1341+ docker_e2e_docker_cmd run demo 2>"$TMPDIR/stderr"
1342+
1343+ mapfile -t docker_seen <"$TMPDIR/docker-seen"
1344+ [[ "\${docker_seen[0]}" = "run --memory 8g --cpus 16 --pids-limit 2048 demo" ]]
1345+ [[ "\${docker_seen[1]}" = "run demo" ]]
1346+ [[ "\${#docker_seen[@]}" = "2" ]]
1347+ grep -Fq "NanoCPUs can not be set" "$TMPDIR/stderr"
1348+ grep -Fq "retrying without default" "$TMPDIR/stderr"
1349+ ` ;
1350+
1351+ execFileSync ( "bash" , [ "-lc" , script ] , { encoding : "utf8" } ) ;
1352+ } finally {
1353+ rmSync ( workDir , { recursive : true , force : true } ) ;
1354+ }
1355+ } ) ;
1356+
13011357 it ( "ignores Docker-like command arguments after the image when cleaning up a resource-limit retry" , ( ) => {
13021358 const workDir = mkdtempSync ( join ( tmpdir ( ) , "openclaw-docker-cgroup-image-boundary-" ) ) ;
13031359
@@ -1884,6 +1940,72 @@ mapfile -t docker_seen <"$TMPDIR/docker-seen"
18841940 }
18851941 } ) ;
18861942
1943+ it ( "retries package-backed Docker runs when rootless daemons reject NanoCPUs" , ( ) => {
1944+ const workDir = mkdtempSync ( join ( tmpdir ( ) , "openclaw-docker-package-rootless-nanocpus-" ) ) ;
1945+
1946+ try {
1947+ const binDir = join ( workDir , "bin" ) ;
1948+ mkdirSync ( binDir ) ;
1949+ writeFileSync (
1950+ join ( binDir , "gtimeout" ) ,
1951+ `#!/bin/bash
1952+ set -euo pipefail
1953+ if [[ "$1" = "--kill-after=1s" ]]; then
1954+ exit 0
1955+ fi
1956+ shift 2
1957+ "$@"
1958+ ` ,
1959+ ) ;
1960+ chmodSync ( join ( binDir , "gtimeout" ) , 0o755 ) ;
1961+ const rootDir = process . cwd ( ) ;
1962+ const script = `
1963+ set -euo pipefail
1964+ ROOT_DIR=${ shellQuote ( rootDir ) }
1965+ TMPDIR=${ shellQuote ( workDir ) }
1966+ export ROOT_DIR TMPDIR
1967+ export PATH="$TMPDIR/bin"
1968+ export OPENCLAW_DOCKER_E2E_RUN_TIMEOUT=15s
1969+ export OPENCLAW_DOCKER_E2E_AVAILABLE_CPUS=8
1970+ unset OPENCLAW_DOCKER_E2E_DISABLE_RESOURCE_LIMITS
1971+ unset OPENCLAW_DOCKER_E2E_MEMORY OPENCLAW_DOCKER_E2E_CPUS OPENCLAW_DOCKER_E2E_PIDS_LIMIT
1972+
1973+ dirname() {
1974+ /usr/bin/dirname "$@"
1975+ }
1976+
1977+ docker_e2e_docker_cmd() {
1978+ return 0
1979+ }
1980+
1981+ docker() {
1982+ printf "%s\\n" "$*" >>"$TMPDIR/docker-seen"
1983+ if [[ "$*" == *"--cpus"* ]]; then
1984+ echo "docker: Error response from daemon: NanoCPUs can not be set, as your kernel does not support CPU CFS scheduler or the cgroup is not mounted" >&2
1985+ return 125
1986+ fi
1987+ }
1988+ export -f docker_e2e_docker_cmd docker
1989+
1990+ source "$ROOT_DIR/scripts/lib/docker-e2e-package.sh"
1991+
1992+ docker_e2e_docker_run_cmd run demo 2>"$TMPDIR/stderr"
1993+
1994+ mapfile -t docker_seen <"$TMPDIR/docker-seen"
1995+ [[ "\${docker_seen[0]}" = "run --memory 8g --cpus 8 --pids-limit 2048 demo" ]]
1996+ [[ "\${docker_seen[1]}" = "run demo" ]]
1997+ [[ "\${#docker_seen[@]}" = "2" ]]
1998+ stderr="$(<"$TMPDIR/stderr")"
1999+ [[ "$stderr" = *"NanoCPUs can not be set"* ]]
2000+ [[ "$stderr" = *"retrying without default"* ]]
2001+ ` ;
2002+
2003+ execFileSync ( "bash" , [ "-lc" , script ] , { encoding : "utf8" } ) ;
2004+ } finally {
2005+ rmSync ( workDir , { recursive : true , force : true } ) ;
2006+ }
2007+ } ) ;
2008+
18872009 it ( "ignores package-backed Docker-like command arguments after the image when cleaning up a resource-limit retry" , ( ) => {
18882010 const workDir = mkdtempSync ( join ( tmpdir ( ) , "openclaw-docker-package-image-boundary-" ) ) ;
18892011
0 commit comments