...

Text file src/github.com/opencontainers/runc/tests/integration/update.bats

Documentation: github.com/opencontainers/runc/tests/integration

     1#!/usr/bin/env bats
     2
     3load helpers
     4
     5function teardown() {
     6	rm -f "$BATS_RUN_TMPDIR"/runc-cgroups-integration-test.json
     7	teardown_bundle
     8}
     9
    10function setup() {
    11	setup_busybox
    12
    13	set_cgroups_path
    14
    15	# Set some initial known values
    16	update_config ' .linux.resources.memory |= {"limit": 33554432, "reservation": 25165824}
    17			| .linux.resources.cpu |= {"shares": 100, "quota": 500000, "period": 1000000}
    18			| .linux.resources.pids |= {"limit": 20}'
    19}
    20
    21# Tests whatever limits are (more or less) common between cgroup
    22# v1 and v2: memory/swap, pids, and cpuset.
    23@test "update cgroup v1/v2 common limits" {
    24	[[ "$ROOTLESS" -ne 0 ]] && requires rootless_cgroup
    25	requires cgroups_memory cgroups_pids cgroups_cpuset
    26	init_cgroup_paths
    27
    28	# run a few busyboxes detached
    29	runc run -d --console-socket "$CONSOLE_SOCKET" test_update
    30	[ "$status" -eq 0 ]
    31
    32	# Set a few variables to make the code below work for both v1 and v2
    33	case $CGROUP_UNIFIED in
    34	no)
    35		MEM_LIMIT="memory.limit_in_bytes"
    36		SD_MEM_LIMIT="MemoryLimit"
    37		MEM_RESERVE="memory.soft_limit_in_bytes"
    38		SD_MEM_RESERVE="unsupported"
    39		MEM_SWAP="memory.memsw.limit_in_bytes"
    40		SD_MEM_SWAP="unsupported"
    41		SYSTEM_MEM=$(cat "${CGROUP_MEMORY_BASE_PATH}/${MEM_LIMIT}")
    42		HAVE_SWAP="no"
    43		if [ -f "${CGROUP_MEMORY_BASE_PATH}/${MEM_SWAP}" ]; then
    44			HAVE_SWAP="yes"
    45		fi
    46		;;
    47	yes)
    48		MEM_LIMIT="memory.max"
    49		SD_MEM_LIMIT="MemoryMax"
    50		MEM_RESERVE="memory.low"
    51		SD_MEM_RESERVE="MemoryLow"
    52		MEM_SWAP="memory.swap.max"
    53		SD_MEM_SWAP="MemorySwapMax"
    54		SYSTEM_MEM="max"
    55		HAVE_SWAP="yes"
    56		;;
    57	esac
    58	SD_UNLIMITED="infinity"
    59	SD_VERSION=$(systemctl --version | awk '{print $2; exit}')
    60	if [ "$SD_VERSION" -lt 227 ]; then
    61		SD_UNLIMITED="18446744073709551615"
    62	fi
    63
    64	# check that initial values were properly set
    65	check_cgroup_value $MEM_LIMIT 33554432
    66	check_systemd_value $SD_MEM_LIMIT 33554432
    67
    68	check_cgroup_value $MEM_RESERVE 25165824
    69	check_systemd_value $SD_MEM_RESERVE 25165824
    70
    71	check_cgroup_value "pids.max" 20
    72	check_systemd_value "TasksMax" 20
    73
    74	# update cpuset if possible (i.e. we're running on a multicore cpu)
    75	cpu_count=$(grep -c '^processor' /proc/cpuinfo)
    76	if [ "$cpu_count" -gt 1 ]; then
    77		runc update test_update --cpuset-cpus "1"
    78		[ "$status" -eq 0 ]
    79		check_cgroup_value "cpuset.cpus" 1
    80	fi
    81
    82	# update memory limit
    83	runc update test_update --memory 67108864
    84	[ "$status" -eq 0 ]
    85	check_cgroup_value $MEM_LIMIT 67108864
    86	check_systemd_value $SD_MEM_LIMIT 67108864
    87
    88	runc update test_update --memory 50M
    89	[ "$status" -eq 0 ]
    90	check_cgroup_value $MEM_LIMIT 52428800
    91	check_systemd_value $SD_MEM_LIMIT 52428800
    92
    93	# update memory soft limit
    94	runc update test_update --memory-reservation 33554432
    95	[ "$status" -eq 0 ]
    96	check_cgroup_value "$MEM_RESERVE" 33554432
    97	check_systemd_value "$SD_MEM_RESERVE" 33554432
    98
    99	# Run swap memory tests if swap is available
   100	if [ "$HAVE_SWAP" = "yes" ]; then
   101		# try to remove memory swap limit
   102		runc update test_update --memory-swap -1
   103		[ "$status" -eq 0 ]
   104		check_cgroup_value "$MEM_SWAP" $SYSTEM_MEM
   105		check_systemd_value "$SD_MEM_SWAP" $SD_UNLIMITED
   106
   107		# update memory swap
   108		if [ "$CGROUP_UNIFIED" = "yes" ]; then
   109			# for cgroupv2, memory and swap can only be set together
   110			runc update test_update --memory 52428800 --memory-swap 96468992
   111			[ "$status" -eq 0 ]
   112			# for cgroupv2, swap is a separate limit (it does not include mem)
   113			check_cgroup_value "$MEM_SWAP" $((96468992 - 52428800))
   114			check_systemd_value "$SD_MEM_SWAP" $((96468992 - 52428800))
   115		else
   116			runc update test_update --memory-swap 96468992
   117			[ "$status" -eq 0 ]
   118			check_cgroup_value "$MEM_SWAP" 96468992
   119			check_systemd_value "$SD_MEM_SWAP" 96468992
   120		fi
   121	fi
   122
   123	# try to remove memory limit
   124	runc update test_update --memory -1
   125	[ "$status" -eq 0 ]
   126
   127	# check memory limit is gone
   128	check_cgroup_value $MEM_LIMIT $SYSTEM_MEM
   129	check_systemd_value $SD_MEM_LIMIT $SD_UNLIMITED
   130
   131	# check swap memory limited is gone
   132	if [ "$HAVE_SWAP" = "yes" ]; then
   133		check_cgroup_value $MEM_SWAP $SYSTEM_MEM
   134		check_systemd_value "$SD_MEM_SWAP" $SD_UNLIMITED
   135	fi
   136
   137	# update pids limit
   138	runc update test_update --pids-limit 10
   139	[ "$status" -eq 0 ]
   140	check_cgroup_value "pids.max" 10
   141	check_systemd_value "TasksMax" 10
   142
   143	# unlimited
   144	runc update test_update --pids-limit -1
   145	[ "$status" -eq 0 ]
   146	check_cgroup_value "pids.max" max
   147	check_systemd_value "TasksMax" $SD_UNLIMITED
   148
   149	# Revert to the test initial value via json on stdin
   150	runc update -r - test_update <<EOF
   151{
   152  "memory": {
   153    "limit": 33554432,
   154    "reservation": 25165824
   155  },
   156  "cpu": {
   157    "shares": 100,
   158    "quota": 500000,
   159    "period": 1000000,
   160    "cpus": "0"
   161  },
   162  "pids": {
   163    "limit": 20
   164  }
   165}
   166EOF
   167	[ "$status" -eq 0 ]
   168	check_cgroup_value "cpuset.cpus" 0
   169
   170	check_cgroup_value $MEM_LIMIT 33554432
   171	check_systemd_value $SD_MEM_LIMIT 33554432
   172
   173	check_cgroup_value $MEM_RESERVE 25165824
   174	check_systemd_value $SD_MEM_RESERVE 25165824
   175
   176	check_cgroup_value "pids.max" 20
   177	check_systemd_value "TasksMax" 20
   178
   179	# redo all the changes at once
   180	runc update test_update \
   181		--cpu-period 900000 --cpu-quota 600000 --cpu-share 200 \
   182		--memory 67108864 --memory-reservation 33554432 \
   183		--pids-limit 10
   184	[ "$status" -eq 0 ]
   185	check_cgroup_value $MEM_LIMIT 67108864
   186	check_systemd_value $SD_MEM_LIMIT 67108864
   187
   188	check_cgroup_value $MEM_RESERVE 33554432
   189	check_systemd_value $SD_MEM_RESERVE 33554432
   190
   191	check_cgroup_value "pids.max" 10
   192	check_systemd_value "TasksMax" 10
   193
   194	# reset to initial test value via json file
   195	cat <<EOF >"$BATS_RUN_TMPDIR"/runc-cgroups-integration-test.json
   196{
   197  "memory": {
   198    "limit": 33554432,
   199    "reservation": 25165824
   200  },
   201  "cpu": {
   202    "shares": 100,
   203    "quota": 500000,
   204    "period": 1000000,
   205    "cpus": "0"
   206  },
   207  "pids": {
   208    "limit": 20
   209  }
   210}
   211EOF
   212
   213	runc update -r "$BATS_RUN_TMPDIR"/runc-cgroups-integration-test.json test_update
   214	[ "$status" -eq 0 ]
   215	check_cgroup_value "cpuset.cpus" 0
   216
   217	check_cgroup_value $MEM_LIMIT 33554432
   218	check_systemd_value $SD_MEM_LIMIT 33554432
   219
   220	check_cgroup_value $MEM_RESERVE 25165824
   221	check_systemd_value $SD_MEM_RESERVE 25165824
   222
   223	check_cgroup_value "pids.max" 20
   224	check_systemd_value "TasksMax" 20
   225
   226	if [ "$HAVE_SWAP" = "yes" ]; then
   227		# Test case for https://github.com/opencontainers/runc/pull/592,
   228		# checking libcontainer/cgroups/fs/memory.go:setMemoryAndSwap.
   229
   230		runc update test_update --memory 30M --memory-swap 50M
   231		[ "$status" -eq 0 ]
   232
   233		check_cgroup_value $MEM_LIMIT $((30 * 1024 * 1024))
   234		check_systemd_value $SD_MEM_LIMIT $((30 * 1024 * 1024))
   235
   236		if [ "$CGROUP_UNIFIED" = "yes" ]; then
   237			# for cgroupv2, swap does not include mem
   238			check_cgroup_value "$MEM_SWAP" $((20 * 1024 * 1024))
   239			check_systemd_value "$SD_MEM_SWAP" $((20 * 1024 * 1024))
   240		else
   241			check_cgroup_value "$MEM_SWAP" $((50 * 1024 * 1024))
   242			check_systemd_value "$SD_MEM_SWAP" $((50 * 1024 * 1024))
   243		fi
   244
   245		# Now, set new memory to more than old swap
   246		runc update test_update --memory 60M --memory-swap 80M
   247		[ "$status" -eq 0 ]
   248
   249		check_cgroup_value $MEM_LIMIT $((60 * 1024 * 1024))
   250		check_systemd_value $SD_MEM_LIMIT $((60 * 1024 * 1024))
   251
   252		if [ "$CGROUP_UNIFIED" = "yes" ]; then
   253			# for cgroupv2, swap does not include mem
   254			check_cgroup_value "$MEM_SWAP" $((20 * 1024 * 1024))
   255			check_systemd_value "$SD_MEM_SWAP" $((20 * 1024 * 1024))
   256		else
   257			check_cgroup_value "$MEM_SWAP" $((80 * 1024 * 1024))
   258			check_systemd_value "$SD_MEM_SWAP" $((80 * 1024 * 1024))
   259		fi
   260	fi
   261}
   262
   263@test "update cgroup cpu limits" {
   264	[[ "$ROOTLESS" -ne 0 ]] && requires rootless_cgroup
   265
   266	# run a few busyboxes detached
   267	runc run -d --console-socket "$CONSOLE_SOCKET" test_update
   268	[ "$status" -eq 0 ]
   269
   270	# check that initial values were properly set
   271	check_cpu_quota 500000 1000000 "500ms"
   272	check_cpu_shares 100
   273
   274	# update cpu period
   275	runc update test_update --cpu-period 900000
   276	[ "$status" -eq 0 ]
   277	check_cpu_quota 500000 900000 "560ms"
   278
   279	# update cpu quota
   280	runc update test_update --cpu-quota 600000
   281	[ "$status" -eq 0 ]
   282	check_cpu_quota 600000 900000 "670ms"
   283
   284	# remove cpu quota
   285	runc update test_update --cpu-quota -1
   286	[ "$status" -eq 0 ]
   287	check_cpu_quota -1 900000 "infinity"
   288
   289	# update cpu-shares
   290	runc update test_update --cpu-share 200
   291	[ "$status" -eq 0 ]
   292	check_cpu_shares 200
   293
   294	# Revert to the test initial value via json on stding
   295	runc update -r - test_update <<EOF
   296{
   297  "cpu": {
   298    "shares": 100,
   299    "quota": 500000,
   300    "period": 1000000
   301  }
   302}
   303EOF
   304	[ "$status" -eq 0 ]
   305	check_cpu_quota 500000 1000000 "500ms"
   306
   307	# redo all the changes at once
   308	runc update test_update \
   309		--cpu-period 900000 --cpu-quota 600000 --cpu-share 200
   310	[ "$status" -eq 0 ]
   311	check_cpu_quota 600000 900000 "670ms"
   312	check_cpu_shares 200
   313
   314	# remove cpu quota and reset the period
   315	runc update test_update --cpu-quota -1 --cpu-period 100000
   316	[ "$status" -eq 0 ]
   317	check_cpu_quota -1 100000 "infinity"
   318
   319	# reset to initial test value via json file
   320	cat <<EOF >"$BATS_RUN_TMPDIR"/runc-cgroups-integration-test.json
   321{
   322  "cpu": {
   323    "shares": 100,
   324    "quota": 500000,
   325    "period": 1000000
   326  }
   327}
   328EOF
   329	[ "$status" -eq 0 ]
   330
   331	runc update -r "$BATS_RUN_TMPDIR"/runc-cgroups-integration-test.json test_update
   332	[ "$status" -eq 0 ]
   333	check_cpu_quota 500000 1000000 "500ms"
   334	check_cpu_shares 100
   335}
   336
   337@test "set cpu period with no quota" {
   338	[[ "$ROOTLESS" -ne 0 ]] && requires rootless_cgroup
   339
   340	update_config '.linux.resources.cpu |= { "period": 1000000 }'
   341
   342	runc run -d --console-socket "$CONSOLE_SOCKET" test_update
   343	[ "$status" -eq 0 ]
   344
   345	check_cpu_quota -1 1000000 "infinity"
   346}
   347
   348@test "set cpu period with no quota (invalid period)" {
   349	[[ "$ROOTLESS" -ne 0 ]] && requires rootless_cgroup
   350
   351	update_config '.linux.resources.cpu |= { "period": 100 }'
   352
   353	runc run -d --console-socket "$CONSOLE_SOCKET" test_update
   354	[ "$status" -eq 1 ]
   355}
   356
   357@test "set cpu quota with no period" {
   358	[[ "$ROOTLESS" -ne 0 ]] && requires rootless_cgroup
   359
   360	update_config '.linux.resources.cpu |= { "quota": 5000 }'
   361
   362	runc run -d --console-socket "$CONSOLE_SOCKET" test_update
   363	[ "$status" -eq 0 ]
   364	check_cpu_quota 5000 100000 "50ms"
   365}
   366
   367@test "update cpu period with no previous period/quota set" {
   368	[[ "$ROOTLESS" -ne 0 ]] && requires rootless_cgroup
   369
   370	update_config '.linux.resources.cpu |= {}'
   371
   372	runc run -d --console-socket "$CONSOLE_SOCKET" test_update
   373	[ "$status" -eq 0 ]
   374
   375	# update the period alone, no old values were set
   376	runc update --cpu-period 50000 test_update
   377	[ "$status" -eq 0 ]
   378	check_cpu_quota -1 50000 "infinity"
   379}
   380
   381@test "update cpu quota with no previous period/quota set" {
   382	[[ "$ROOTLESS" -ne 0 ]] && requires rootless_cgroup
   383
   384	update_config '.linux.resources.cpu |= {}'
   385
   386	runc run -d --console-socket "$CONSOLE_SOCKET" test_update
   387	[ "$status" -eq 0 ]
   388
   389	# update the quota alone, no old values were set
   390	runc update --cpu-quota 30000 test_update
   391	[ "$status" -eq 0 ]
   392	check_cpu_quota 30000 100000 "300ms"
   393}
   394
   395@test "update cpu period in a pod cgroup with pod limit set" {
   396	requires cgroups_v1
   397	[[ "$ROOTLESS" -ne 0 ]] && requires rootless_cgroup
   398
   399	set_cgroups_path "pod_${RANDOM}"
   400
   401	# Set parent/pod CPU quota limit to 50%.
   402	if [ -n "${RUNC_USE_SYSTEMD}" ]; then
   403		set_parent_systemd_properties CPUQuota="50%"
   404	else
   405		echo 50000 >"/sys/fs/cgroup/cpu/$REL_PARENT_PATH/cpu.cfs_quota_us"
   406	fi
   407	# Sanity checks.
   408	run cat "/sys/fs/cgroup/cpu$REL_PARENT_PATH/cpu.cfs_period_us"
   409	[ "$output" -eq 100000 ]
   410	run cat "/sys/fs/cgroup/cpu$REL_PARENT_PATH/cpu.cfs_quota_us"
   411	[ "$output" -eq 50000 ]
   412
   413	runc run -d --console-socket "$CONSOLE_SOCKET" test_update
   414	[ "$status" -eq 0 ]
   415	# Get the current period.
   416	local cur
   417	cur=$(get_cgroup_value cpu.cfs_period_us)
   418
   419	# Sanity check: as the parent cgroup sets the limit to 50%,
   420	# setting a higher limit (e.g. 60%) is expected to fail.
   421	runc update --cpu-quota $((cur * 6 / 10)) test_update
   422	[ "$status" -eq 1 ]
   423
   424	# Finally, the test itself: set 30% limit but with lower period.
   425	runc update --cpu-period 10000 --cpu-quota 3000 test_update
   426	[ "$status" -eq 0 ]
   427	check_cpu_quota 3000 10000 "300ms"
   428}
   429
   430@test "update cgroup v2 resources via unified map" {
   431	[[ "$ROOTLESS" -ne 0 ]] && requires rootless_cgroup
   432	requires cgroups_v2
   433
   434	runc run -d --console-socket "$CONSOLE_SOCKET" test_update
   435	[ "$status" -eq 0 ]
   436
   437	# check that initial values were properly set
   438	check_cpu_quota 500000 1000000 "500ms"
   439	# initial cpu shares of 100 corresponds to weight of 4
   440	check_cpu_weight 4
   441	check_systemd_value "TasksMax" 20
   442
   443	runc update -r - test_update <<EOF
   444{
   445  "unified": {
   446    "cpu.max": "max 100000",
   447    "cpu.weight": "16",
   448    "pids.max": "10"
   449  }
   450}
   451EOF
   452
   453	# check the updated systemd unit properties
   454	check_cpu_quota -1 100000 "infinity"
   455	check_cpu_weight 16
   456	check_systemd_value "TasksMax" 10
   457}
   458
   459@test "update cpuset parameters via resources.CPU" {
   460	[[ "$ROOTLESS" -ne 0 ]] && requires rootless_cgroup
   461	requires smp cgroups_cpuset
   462
   463	local AllowedCPUs='AllowedCPUs' AllowedMemoryNodes='AllowedMemoryNodes'
   464	# these properties require systemd >= v244
   465	if [ "$(systemd_version)" -lt 244 ]; then
   466		# a hack to skip checks, see check_systemd_value()
   467		AllowedCPUs='unsupported'
   468		AllowedMemoryNodes='unsupported'
   469	fi
   470
   471	update_config ' .linux.resources.CPU |= {
   472				"Cpus": "0",
   473				"Mems": "0"
   474			}'
   475	runc run -d --console-socket "$CONSOLE_SOCKET" test_update
   476	[ "$status" -eq 0 ]
   477
   478	# check that initial values were properly set
   479	check_systemd_value "$AllowedCPUs" 0
   480	check_systemd_value "$AllowedMemoryNodes" 0
   481
   482	runc update -r - test_update <<EOF
   483{
   484  "CPU": {
   485    "Cpus": "1"
   486  }
   487}
   488EOF
   489	[ "$status" -eq 0 ]
   490
   491	# check the updated systemd unit properties
   492	check_systemd_value "$AllowedCPUs" 1
   493
   494	# More than 1 numa memory node is required to test this
   495	file="/sys/fs/cgroup/cpuset.mems.effective"
   496	if ! test -r $file || grep -q '^0$' $file; then
   497		# skip the rest of it
   498		return 0
   499	fi
   500
   501	runc update -r - test_update <<EOF
   502{
   503  "CPU": {
   504    "Mems": "1"
   505  }
   506}
   507EOF
   508	[ "$status" -eq 0 ]
   509
   510	# check the updated systemd unit properties
   511	check_systemd_value "$AllowedMemoryNodes" 1
   512}
   513
   514@test "update cpuset parameters via v2 unified map" {
   515	# This test assumes systemd >= v244
   516	[[ "$ROOTLESS" -ne 0 ]] && requires rootless_cgroup
   517	requires cgroups_v2 smp cgroups_cpuset
   518
   519	update_config ' .linux.resources.unified |= {
   520				"cpuset.cpus": "0",
   521				"cpuset.mems": "0"
   522			}'
   523	runc run -d --console-socket "$CONSOLE_SOCKET" test_update
   524	[ "$status" -eq 0 ]
   525
   526	# check that initial values were properly set
   527	check_systemd_value "AllowedCPUs" 0
   528	check_systemd_value "AllowedMemoryNodes" 0
   529
   530	runc update -r - test_update <<EOF
   531{
   532  "unified": {
   533    "cpuset.cpus": "1"
   534  }
   535}
   536EOF
   537	[ "$status" -eq 0 ]
   538
   539	# check the updated systemd unit properties
   540	check_systemd_value "AllowedCPUs" 1
   541
   542	# More than 1 numa memory node is required to test this
   543	file="/sys/fs/cgroup/cpuset.mems.effective"
   544	if ! test -r $file || grep -q '^0$' $file; then
   545		# skip the rest of it
   546		return 0
   547	fi
   548
   549	runc update -r - test_update <<EOF
   550{
   551  "unified": {
   552    "cpuset.mems": "1"
   553  }
   554}
   555EOF
   556	[ "$status" -eq 0 ]
   557
   558	# check the updated systemd unit properties
   559	check_systemd_value "AllowedMemoryNodes" 1
   560}
   561
   562@test "update cpuset cpus range via v2 unified map" {
   563	# This test assumes systemd >= v244
   564	[ $EUID -ne 0 ] && requires rootless_cgroup
   565	requires systemd cgroups_v2 more_than_8_core cgroups_cpuset
   566
   567	update_config ' .linux.resources.unified |= {
   568				"cpuset.cpus": "0-5",
   569			}'
   570	runc run -d --console-socket "$CONSOLE_SOCKET" test_update
   571	[ "$status" -eq 0 ]
   572
   573	# check that the initial value was properly set
   574	check_systemd_value "AllowedCPUs" "0-5"
   575
   576	runc update -r - test_update <<EOF
   577{
   578  "unified": {
   579    "cpuset.cpus": "5-8"
   580  }
   581}
   582EOF
   583	[ "$status" -eq 0 ]
   584
   585	# check the updated systemd unit property, the value should not be affected by byte order
   586	check_systemd_value "AllowedCPUs" "5-8"
   587}
   588
   589@test "update rt period and runtime" {
   590	[[ "$ROOTLESS" -ne 0 ]] && requires rootless_cgroup
   591	requires cgroups_v1 cgroups_rt no_systemd
   592
   593	local cgroup_cpu="${CGROUP_CPU_BASE_PATH}/${REL_CGROUPS_PATH}"
   594
   595	# By default, "${cgroup_cpu}/cpu.rt_runtime_us" is set to 0, which inhibits
   596	# setting the container's realtimeRuntime. (#2046)
   597	#
   598	# When ${cgroup_cpu} is "/sys/fs/cgroup/cpu,cpuacct/runc-cgroups-integration-test/test-cgroup",
   599	# we write the values of /sys/fs/cgroup/cpu,cpuacct/cpu.rt_{period,runtime}_us to:
   600	# - sys/fs/cgroup/cpu,cpuacct/runc-cgroups-integration-test/cpu.rt_{period,runtime}_us
   601	# - sys/fs/cgroup/cpu,cpuacct/runc-cgroups-integration-test/test-cgroup/cpu.rt_{period,runtime}_us
   602	#
   603	# Typically period=1000000 runtime=950000 .
   604	#
   605	# TODO: support systemd
   606	mkdir -p "$cgroup_cpu"
   607	local root_period root_runtime
   608	root_period=$(cat "${CGROUP_CPU_BASE_PATH}/cpu.rt_period_us")
   609	root_runtime=$(cat "${CGROUP_CPU_BASE_PATH}/cpu.rt_runtime_us")
   610	# the following IFS magic sets dirs=("runc-cgroups-integration-test" "test-cgroup")
   611	IFS='/' read -r -a dirs <<<"${REL_CGROUPS_PATH#/}"
   612	for ((i = 0; i < ${#dirs[@]}; i++)); do
   613		local target="$CGROUP_CPU_BASE_PATH"
   614		for ((j = 0; j <= i; j++)); do
   615			target="${target}/${dirs[$j]}"
   616		done
   617		target_period="${target}/cpu.rt_period_us"
   618		echo "Writing ${root_period} to ${target_period}"
   619		echo "$root_period" >"$target_period"
   620		target_runtime="${target}/cpu.rt_runtime_us"
   621		echo "Writing ${root_runtime} to ${target_runtime}"
   622		echo "$root_runtime" >"$target_runtime"
   623	done
   624
   625	# run a detached busybox
   626	runc run -d --console-socket "$CONSOLE_SOCKET" test_update_rt
   627	[ "$status" -eq 0 ]
   628
   629	runc update -r - test_update_rt <<EOF
   630{
   631  "cpu": {
   632    "realtimeRuntime": 500001
   633  }
   634}
   635EOF
   636	[ "$status" -eq 0 ]
   637	check_cgroup_value "cpu.rt_period_us" "$root_period"
   638	check_cgroup_value "cpu.rt_runtime_us" 500001
   639
   640	runc update -r - test_update_rt <<EOF
   641{
   642  "cpu": {
   643    "realtimePeriod": 800001,
   644    "realtimeRuntime": 500001
   645  }
   646}
   647EOF
   648	check_cgroup_value "cpu.rt_period_us" 800001
   649	check_cgroup_value "cpu.rt_runtime_us" 500001
   650
   651	runc update test_update_rt --cpu-rt-period 900001 --cpu-rt-runtime 600001
   652	[ "$status" -eq 0 ]
   653
   654	check_cgroup_value "cpu.rt_period_us" 900001
   655	check_cgroup_value "cpu.rt_runtime_us" 600001
   656}
   657
   658@test "update devices [minimal transition rules]" {
   659	[[ "$ROOTLESS" -ne 0 ]] && requires rootless_cgroup
   660
   661	requires root
   662
   663	# Run a basic shell script that tries to read from /dev/kmsg, but
   664	# due to lack of permissions, it prints the error message to /dev/null.
   665	# If any data is read from /dev/kmsg, it will be printed to stdout, and the
   666	# test will fail. In the same way, if access to /dev/null is denied, the
   667	# error will be printed to stderr, and the test will also fail.
   668	#
   669	# "runc update" makes use of minimal transition rules, updates should not cause
   670	# writes to fail at any point. For systemd cgroup driver on cgroup v1, the cgroup
   671	# is frozen to ensure this.
   672	update_config ' .linux.resources.devices = [{"allow": false, "access": "rwm"}, {"allow": false, "type": "c", "major": 1, "minor": 11, "access": "rwa"}]
   673			| .linux.devices = [{"path": "/dev/kmsg", "type": "c", "major": 1, "minor": 11}]
   674			| .process.capabilities.bounding += ["CAP_SYSLOG"]
   675			| .process.capabilities.effective += ["CAP_SYSLOG"]
   676			| .process.capabilities.inheritable += ["CAP_SYSLOG"]
   677			| .process.capabilities.permitted += ["CAP_SYSLOG"]
   678			| .process.args |= ["sh", "-c", "while true; do head -c 100 /dev/kmsg 2> /dev/null; done"]'
   679
   680	# Set up a temporary console socket and recvtty so we can get the stdio.
   681	TMP_RECVTTY_DIR="$(mktemp -d "$BATS_RUN_TMPDIR/runc-tmp-recvtty.XXXXXX")"
   682	TMP_RECVTTY_PID="$TMP_RECVTTY_DIR/recvtty.pid"
   683	TMP_CONSOLE_SOCKET="$TMP_RECVTTY_DIR/console.sock"
   684	CONTAINER_OUTPUT="$TMP_RECVTTY_DIR/output"
   685	("$RECVTTY" --no-stdin --pid-file "$TMP_RECVTTY_PID" \
   686		--mode single "$TMP_CONSOLE_SOCKET" &>"$CONTAINER_OUTPUT") &
   687	retry 10 0.1 [ -e "$TMP_CONSOLE_SOCKET" ]
   688
   689	# Run the container in the background.
   690	runc run -d --console-socket "$TMP_CONSOLE_SOCKET" test_update
   691	cat "$CONTAINER_OUTPUT"
   692	[ "$status" -eq 0 ]
   693
   694	# Trigger an update. This update doesn't actually change the device rules,
   695	# but it will trigger the devices cgroup code to reapply the current rules.
   696	# We trigger the update a few times to make sure we hit the race.
   697	for _ in {1..30}; do
   698		# TODO: Update "runc update" so we can change the device rules.
   699		runc update --pids-limit 30 test_update
   700		[ "$status" -eq 0 ]
   701	done
   702
   703	# Kill recvtty.
   704	kill -9 "$(<"$TMP_RECVTTY_PID")"
   705
   706	# There should've been no output from the container.
   707	cat "$CONTAINER_OUTPUT"
   708	[ -z "$(<"$CONTAINER_OUTPUT")" ]
   709}
   710
   711@test "update paused container" {
   712	[[ "$ROOTLESS" -ne 0 ]] && requires rootless_cgroup
   713	requires cgroups_freezer
   714
   715	# Run the container in the background.
   716	runc run -d --console-socket "$CONSOLE_SOCKET" test_update
   717	[ "$status" -eq 0 ]
   718
   719	# Pause the container.
   720	runc pause test_update
   721	[ "$status" -eq 0 ]
   722
   723	# Trigger an unrelated update.
   724	runc update --pids-limit 30 test_update
   725	[ "$status" -eq 0 ]
   726
   727	# The container should still be paused.
   728	testcontainer test_update paused
   729
   730	# Resume the container.
   731	runc resume test_update
   732	[ "$status" -eq 0 ]
   733}

View as plain text