22185: Check for cgroup v1 support if running as root.
[arvados.git] / lib / crunchrun / cgroup_test.go
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 package crunchrun
6
7 import (
8         "bytes"
9         "os"
10         "os/exec"
11         "strings"
12
13         "github.com/sirupsen/logrus"
14         . "gopkg.in/check.v1"
15 )
16
17 type CgroupSuite struct{}
18
19 var _ = Suite(&CgroupSuite{})
20
21 func (s *CgroupSuite) TestFindCgroup(c *C) {
22         var testfiles []string
23         buf, err := exec.Command("find", "../crunchstat/testdata", "-name", "cgroup", "-type", "f").Output()
24         c.Assert(err, IsNil)
25         for _, testfile := range bytes.Split(buf, []byte{'\n'}) {
26                 if len(testfile) > 0 {
27                         testfiles = append(testfiles, string(testfile))
28                 }
29         }
30         testfiles = append(testfiles, "/proc/self/cgroup")
31
32         tmpdir := c.MkDir()
33         err = os.MkdirAll(tmpdir+"/proc/self", 0777)
34         c.Assert(err, IsNil)
35         fsys := os.DirFS(tmpdir)
36
37         for _, trial := range []struct {
38                 match  string // if non-empty, only check testfiles containing this string
39                 subsys string
40                 expect string // empty means "any" (we never actually expect empty string)
41         }{
42                 {"debian11", "blkio", "/user.slice/user-1000.slice/session-5424.scope"},
43                 {"debian12", "cpuacct", "/user.slice/user-1000.slice/session-4.scope"},
44                 {"debian12", "bogus-does-not-matter", "/user.slice/user-1000.slice/session-4.scope"},
45                 {"ubuntu1804", "blkio", "/user.slice"},
46                 {"ubuntu1804", "cpuacct", "/user.slice"},
47                 {"", "cpu", ""},
48                 {"", "cpuset", ""},
49                 {"", "devices", ""},
50                 {"", "bogus-does-not-matter", ""},
51         } {
52                 for _, testfile := range testfiles {
53                         if !strings.Contains(testfile, trial.match) {
54                                 continue
55                         }
56                         c.Logf("trial %+v testfile %s", trial, testfile)
57
58                         // Copy cgroup file into our fake proc/self/ dir
59                         buf, err := os.ReadFile(testfile)
60                         c.Assert(err, IsNil)
61                         err = os.WriteFile(tmpdir+"/proc/self/cgroup", buf, 0777)
62                         c.Assert(err, IsNil)
63
64                         cgroup, err := findCgroup(fsys, trial.subsys)
65                         if !c.Check(err, IsNil) {
66                                 continue
67                         }
68                         c.Logf("\tcgroup = %q", cgroup)
69                         c.Check(cgroup, Not(Equals), "")
70                         if trial.expect != "" {
71                                 c.Check(cgroup, Equals, trial.expect)
72                         }
73                 }
74         }
75 }
76
77 func (s *CgroupSuite) TestCgroupSupport(c *C) {
78         var logbuf bytes.Buffer
79         logger := logrus.New()
80         logger.Out = &logbuf
81         checkCgroupSupport(logger.Printf)
82         c.Check(logbuf.String(), Equals, "")
83         c.Check(cgroupSupport, NotNil)
84         c.Check(cgroupSupport["memory"], Equals, true)
85         c.Check(cgroupSupport["entropy"], Equals, false)
86 }
87
88 func (s *CgroupSuite) TestCgroup1Support(c *C) {
89         tmpdir := c.MkDir()
90         err := os.MkdirAll(tmpdir+"/proc/self", 0777)
91         c.Assert(err, IsNil)
92         err = os.WriteFile(tmpdir+"/proc/self/cgroup", []byte(`12:blkio:/user.slice
93 11:perf_event:/
94 10:freezer:/
95 9:pids:/user.slice/user-1000.slice/session-5.scope
96 8:hugetlb:/
97 7:rdma:/
98 6:cpu,cpuacct:/user.slice
99 5:devices:/user.slice
100 4:memory:/user.slice/user-1000.slice/session-5.scope
101 3:net_cls,net_prio:/
102 2:cpuset:/
103 1:name=systemd:/user.slice/user-1000.slice/session-5.scope
104 0::/user.slice/user-1000.slice/session-5.scope
105 `), 0777)
106         c.Assert(err, IsNil)
107         cgroupSupport = map[string]bool{}
108         ok := checkCgroup1Support(os.DirFS(tmpdir), c.Logf)
109         c.Check(ok, Equals, true)
110         c.Check(cgroupSupport, DeepEquals, map[string]bool{
111                 "blkio":        true,
112                 "cpu":          true,
113                 "cpuacct":      true,
114                 "cpuset":       true,
115                 "devices":      true,
116                 "freezer":      true,
117                 "hugetlb":      true,
118                 "memory":       true,
119                 "name=systemd": true,
120                 "net_cls":      true,
121                 "net_prio":     true,
122                 "perf_event":   true,
123                 "pids":         true,
124                 "rdma":         true,
125         })
126 }