mirror of
https://github.com/opencontainers/runc.git
synced 2026-07-11 06:03:57 +08:00
b82ae3afdc
The "runc delete --force [paused container]" test case does not check runc pause exit code, and if added, the test fails in rootless tests, because: - not all rootless tests have access to cgroups; - rootless containers doesn't have default cgroups path. To fix, add: - setup for rootless case; - require cgroups_freezer; - runc pause exit code check. Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
282 lines
7.3 KiB
Bash
282 lines
7.3 KiB
Bash
#!/usr/bin/env bats
|
|
|
|
load helpers
|
|
|
|
function setup() {
|
|
setup_busybox
|
|
}
|
|
|
|
function teardown() {
|
|
teardown_bundle
|
|
}
|
|
|
|
# See also: "kill KILL [host pidns + init gone]" test in kill.bats.
|
|
#
|
|
# This needs to be placed at the top of the bats file to work around
|
|
# a shellcheck bug. See <https://github.com/koalaman/shellcheck/issues/2873>.
|
|
function test_runc_delete_host_pidns() {
|
|
requires cgroups_freezer
|
|
|
|
update_config ' .linux.namespaces -= [{"type": "pid"}]'
|
|
set_cgroups_path
|
|
if [ $EUID -ne 0 ]; then
|
|
requires rootless_cgroup
|
|
# Apparently, for rootless test, when using systemd cgroup manager,
|
|
# newer versions of systemd clean up the container as soon as its init
|
|
# process is gone. This is all fine and dandy, except it prevents us to
|
|
# test this case, thus we skip the test.
|
|
#
|
|
# It is not entirely clear which systemd version got this feature:
|
|
# v245 works fine, and v249 does not.
|
|
if [ -v RUNC_USE_SYSTEMD ] && [ "$(systemd_version)" -gt 245 ]; then
|
|
skip "rootless+systemd conflicts with systemd > 245"
|
|
fi
|
|
# Can't mount real /proc when rootless + no pidns,
|
|
# so change it to a bind-mounted one from the host.
|
|
update_config ' .mounts |= map((select(.type == "proc")
|
|
| .type = "none"
|
|
| .source = "/proc"
|
|
| .options = ["rbind", "nosuid", "nodev", "noexec"]
|
|
) // .)'
|
|
fi
|
|
|
|
runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox
|
|
[ "$status" -eq 0 ]
|
|
cgpath=$(get_cgroup_path "pids")
|
|
init_pid=$(cat "$cgpath"/cgroup.procs)
|
|
|
|
# Start a few more processes.
|
|
for _ in 1 2 3 4 5; do
|
|
__runc exec -d test_busybox sleep 1h
|
|
done
|
|
|
|
# Now kill the container's init process. Since the container do
|
|
# not have own PID ns, its init is no special and the container
|
|
# will still be up and running.
|
|
kill -9 "$init_pid"
|
|
wait_pids_gone 10 0.2 "$init_pid"
|
|
|
|
# Get the list of all container processes.
|
|
mapfile -t pids < <(cat "$cgpath"/cgroup.procs)
|
|
echo "pids:" "${pids[@]}"
|
|
# Sanity check -- make sure all processes exist.
|
|
for p in "${pids[@]}"; do
|
|
kill -0 "$p"
|
|
done
|
|
|
|
# Must kill those processes and remove container.
|
|
runc delete "$@" test_busybox
|
|
[ "$status" -eq 0 ]
|
|
|
|
runc state test_busybox
|
|
[ "$status" -ne 0 ] # "Container does not exist"
|
|
|
|
# Wait and check that all the processes are gone.
|
|
wait_pids_gone 10 0.2 "${pids[@]}"
|
|
|
|
# Make sure cgroup.procs is empty.
|
|
mapfile -t pids < <(cat "$cgpath"/cgroup.procs || true)
|
|
if [ ${#pids[@]} -gt 0 ]; then
|
|
echo "expected empty cgroup.procs, got:" "${pids[@]}" 1>&2
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
@test "runc delete" {
|
|
# Need a permission to create a cgroup.
|
|
# XXX(@kolyshkin): currently this test does not handle rootless when
|
|
# fs cgroup driver is used, because in this case cgroup (with a
|
|
# predefined name) is created by tests/rootless.sh, not by runc.
|
|
[ $EUID -ne 0 ] && requires systemd
|
|
set_resources_limit
|
|
|
|
runc run -d --console-socket "$CONSOLE_SOCKET" testbusyboxdelete
|
|
[ "$status" -eq 0 ]
|
|
|
|
testcontainer testbusyboxdelete running
|
|
# Ensure the find statement used later is correct.
|
|
output=$(find /sys/fs/cgroup -name testbusyboxdelete -o -name \*-testbusyboxdelete.scope 2>/dev/null || true)
|
|
if [ -z "$output" ]; then
|
|
fail "expected cgroup not found"
|
|
fi
|
|
|
|
runc kill testbusyboxdelete KILL
|
|
[ "$status" -eq 0 ]
|
|
wait_for_container 10 1 testbusyboxdelete stopped
|
|
|
|
runc delete testbusyboxdelete
|
|
[ "$status" -eq 0 ]
|
|
|
|
runc state testbusyboxdelete
|
|
[ "$status" -ne 0 ]
|
|
|
|
output=$(find /sys/fs/cgroup -name testbusyboxdelete -o -name \*-testbusyboxdelete.scope 2>/dev/null || true)
|
|
[ "$output" = "" ] || fail "cgroup not cleaned up correctly: $output"
|
|
}
|
|
|
|
@test "runc delete --force" {
|
|
runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox
|
|
[ "$status" -eq 0 ]
|
|
|
|
testcontainer test_busybox running
|
|
|
|
runc delete --force test_busybox
|
|
|
|
runc state test_busybox
|
|
[ "$status" -ne 0 ]
|
|
}
|
|
|
|
@test "runc delete --force ignore not exist" {
|
|
runc delete --force notexists
|
|
[ "$status" -eq 0 ]
|
|
}
|
|
|
|
# Issue 4047, case "runc delete".
|
|
@test "runc delete [host pidns + init gone]" {
|
|
test_runc_delete_host_pidns
|
|
}
|
|
|
|
# Issue 4047, case "runc delete --force" (different code path).
|
|
@test "runc delete --force [host pidns + init gone]" {
|
|
test_runc_delete_host_pidns --force
|
|
}
|
|
|
|
@test "runc delete --force [paused container]" {
|
|
requires cgroups_freezer
|
|
if [ $EUID -ne 0 ]; then
|
|
requires rootless_cgroup
|
|
# Rootless containers have no default cgroup path.
|
|
set_cgroups_path
|
|
fi
|
|
|
|
runc run -d --console-socket "$CONSOLE_SOCKET" ct1
|
|
[ "$status" -eq 0 ]
|
|
testcontainer ct1 running
|
|
|
|
runc pause ct1
|
|
[ "$status" -eq 0 ]
|
|
runc delete --force ct1
|
|
[ "$status" -eq 0 ]
|
|
}
|
|
|
|
@test "runc delete --force in cgroupv1 with subcgroups" {
|
|
requires cgroups_v1 root cgroupns
|
|
set_cgroups_path
|
|
set_cgroup_mount_writable
|
|
# enable cgroupns
|
|
update_config '.linux.namespaces += [{"type": "cgroup"}]'
|
|
|
|
local subsystems="memory freezer"
|
|
|
|
runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox
|
|
[ "$status" -eq 0 ]
|
|
|
|
testcontainer test_busybox running
|
|
|
|
__runc exec -d test_busybox sleep 1d
|
|
|
|
# find the pid of sleep
|
|
pid=$(__runc exec test_busybox ps -a | grep 1d | awk '{print $1}')
|
|
[[ ${pid} =~ [0-9]+ ]]
|
|
|
|
# create a sub-cgroup
|
|
cat <<EOF | runc exec test_busybox sh
|
|
set -e -u -x
|
|
for s in ${subsystems}; do
|
|
cd /sys/fs/cgroup/\$s
|
|
mkdir foo
|
|
cd foo
|
|
echo ${pid} > tasks
|
|
cat tasks
|
|
done
|
|
EOF
|
|
[ "$status" -eq 0 ]
|
|
[[ "$output" =~ [0-9]+ ]]
|
|
|
|
for s in ${subsystems}; do
|
|
name=CGROUP_${s^^}_BASE_PATH
|
|
eval path=\$"${name}${REL_CGROUPS_PATH}/foo"
|
|
# shellcheck disable=SC2154
|
|
[ -d "${path}" ] || fail "test failed to create memory sub-cgroup ($path not found)"
|
|
done
|
|
|
|
runc delete --force test_busybox
|
|
|
|
runc state test_busybox
|
|
[ "$status" -ne 0 ]
|
|
|
|
output=$(find /sys/fs/cgroup -wholename '*testbusyboxdelete*' -type d 2>/dev/null || true)
|
|
[ "$output" = "" ] || fail "cgroup not cleaned up correctly: $output"
|
|
}
|
|
|
|
@test "runc delete --force in cgroupv2 with subcgroups" {
|
|
requires cgroups_v2 root
|
|
set_cgroups_path
|
|
set_cgroup_mount_writable
|
|
|
|
runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox
|
|
[ "$status" -eq 0 ]
|
|
|
|
testcontainer test_busybox running
|
|
|
|
# create a sub process
|
|
__runc exec -d test_busybox sleep 1d
|
|
|
|
# find the pid of sleep
|
|
pid=$(__runc exec test_busybox ps -a | grep 1d | awk '{print $1}')
|
|
[[ ${pid} =~ [0-9]+ ]]
|
|
|
|
# create subcgroups
|
|
cat <<EOF >nest.sh
|
|
set -e -u -x
|
|
cd /sys/fs/cgroup
|
|
echo +pids > cgroup.subtree_control
|
|
mkdir foo
|
|
cd foo
|
|
echo threaded > cgroup.type
|
|
echo ${pid} > cgroup.threads
|
|
cat cgroup.threads
|
|
EOF
|
|
runc exec test_busybox sh <nest.sh
|
|
[ "$status" -eq 0 ]
|
|
[[ "$output" =~ [0-9]+ ]]
|
|
|
|
# check create subcgroups success
|
|
[ -d "$CGROUP_V2_PATH"/foo ]
|
|
|
|
# force delete test_busybox
|
|
runc delete --force test_busybox
|
|
|
|
runc state test_busybox
|
|
[ "$status" -ne 0 ]
|
|
|
|
# check delete subcgroups success
|
|
[ ! -d "$CGROUP_V2_PATH"/foo ]
|
|
}
|
|
|
|
@test "runc delete removes failed systemd unit" {
|
|
requires systemd_v244 # Older systemd lacks RuntimeMaxSec support.
|
|
|
|
set_cgroups_path
|
|
update_config ' .annotations += {
|
|
"org.systemd.property.RuntimeMaxSec": "2",
|
|
"org.systemd.property.TimeoutStopSec": "1"
|
|
}
|
|
| .process.args |= ["/bin/sleep", "10"]'
|
|
|
|
runc run -d --console-socket "$CONSOLE_SOCKET" test-failed-unit
|
|
[ "$status" -eq 0 ]
|
|
|
|
wait_for_container 10 1 test-failed-unit stopped
|
|
|
|
local user=""
|
|
[ $EUID -ne 0 ] && user="--user"
|
|
|
|
# Expect "unit is not active" exit code.
|
|
run -3 systemctl status $user "$SD_UNIT_NAME"
|
|
|
|
runc delete test-failed-unit
|
|
# Expect "no such unit" exit code.
|
|
run -4 systemctl status $user "$SD_UNIT_NAME"
|
|
}
|