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)
}
}
|