File: linux_cgroups_cpus.go

package info (click to toggle)
golang-github-opencontainers-runtime-tools 0.9.0%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 1,108 kB
  • sloc: sh: 557; makefile: 104
file content (133 lines) | stat: -rw-r--r-- 3,377 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package main

import (
	"fmt"
	"os"
	"path/filepath"
	"runtime"

	"github.com/mndrix/tap-go"
	"github.com/opencontainers/runtime-tools/cgroups"
	"github.com/opencontainers/runtime-tools/validation/util"
)

const (
	defaultRealtimePeriod  uint64 = 1000000
	defaultRealtimeRuntime int64  = 950000
)

func testCPUCgroups() error {
	t := tap.New()
	t.Header(0)
	defer t.AutoPlan()

	CPUrange := fmt.Sprintf("0-%d", runtime.NumCPU()-1)

	// Test with different combinations of values.
	// NOTE: most systems have only one memory node (mems=="0"), so we cannot
	// simply test with multiple values of mems.
	cases := []struct {
		shares uint64
		period uint64
		quota  int64
		cpus   string
		mems   string
	}{
		{1024, 100000, 50000, "0", "0"},
		{1024, 100000, 50000, CPUrange, "0"},
		{1024, 100000, 200000, "0", "0"},
		{1024, 100000, 200000, CPUrange, "0"},
		{1024, 500000, 50000, "0", "0"},
		{1024, 500000, 50000, CPUrange, "0"},
		{1024, 500000, 200000, "0", "0"},
		{1024, 500000, 200000, CPUrange, "0"},
		{2048, 100000, 50000, "0", "0"},
		{2048, 100000, 50000, CPUrange, "0"},
		{2048, 100000, 200000, "0", "0"},
		{2048, 100000, 200000, CPUrange, "0"},
		{2048, 500000, 50000, "0", "0"},
		{2048, 500000, 50000, CPUrange, "0"},
		{2048, 500000, 200000, "0", "0"},
		{2048, 500000, 200000, CPUrange, "0"},
	}

	for _, c := range cases {
		g, err := util.GetDefaultGenerator()
		if err != nil {
			return fmt.Errorf("cannot get default config from generator: %v", err)
		}

		g.SetLinuxCgroupsPath(cgroups.AbsCgroupPath)

		if c.shares > 0 {
			g.SetLinuxResourcesCPUShares(c.shares)
		}

		if c.period > 0 {
			g.SetLinuxResourcesCPUPeriod(c.period)
		}

		if c.quota > 0 {
			g.SetLinuxResourcesCPUQuota(c.quota)
		}

		if c.cpus != "" {
			g.SetLinuxResourcesCPUCpus(c.cpus)
		}

		if c.mems != "" {
			g.SetLinuxResourcesCPUMems(c.mems)
		}

		// NOTE: On most systems where CONFIG_RT_GROUP & CONFIG_RT_GROUP_SCHED are not enabled,
		// the following tests will fail, because sysfs knobs like
		// /sys/fs/cgroup/cpu,cpuacct/cpu.rt_{period,runtime}_us do not exist.
		// So we need to check if the sysfs knobs exist before setting the variables.
		if _, err := os.Stat(filepath.Join(util.CPUCgroupPrefix, "cpu.rt_period_us")); !os.IsNotExist(err) {
			g.SetLinuxResourcesCPURealtimePeriod(defaultRealtimePeriod)
		}

		if _, err := os.Stat(filepath.Join(util.CPUCgroupPrefix, "cpu.rt_runtime_us")); !os.IsNotExist(err) {
			g.SetLinuxResourcesCPURealtimeRuntime(defaultRealtimeRuntime)
		}

		if err := util.RuntimeOutsideValidate(g, t, util.ValidateLinuxResourcesCPU); err != nil {
			return fmt.Errorf("cannot validate CPU cgroups: %v", err)
		}
	}

	return nil
}

func testEmptyCPU() error {
	t := tap.New()
	t.Header(0)
	defer t.AutoPlan()

	g, err := util.GetDefaultGenerator()
	if err != nil {
		return fmt.Errorf("cannot get default config from generator: %v", err)
	}
	g.InitConfigLinuxResourcesCPU()
	g.SetLinuxCgroupsPath(cgroups.AbsCgroupPath)

	if err := util.RuntimeOutsideValidate(g, t, util.ValidateLinuxResourcesCPUEmpty); err != nil {
		return fmt.Errorf("cannot validate empty CPU cgroups: %v", err)
	}

	return nil
}

func main() {
	if "linux" != runtime.GOOS {
		util.Fatal(fmt.Errorf("linux-specific cgroup test"))
	}

	if err := testCPUCgroups(); err != nil {
		util.Fatal(err)
	}

	if err := testEmptyCPU(); err != nil {
		util.Fatal(err)
	}
}