Skip to content

Commit c3755c1

Browse files
author
Zhou Hao
authored
Merge pull request #93 from Mashimiao/runtime-test-cgroup-path-validation
runtimetest: add validation of cgroups
2 parents abb7f02 + 7c09b4c commit c3755c1

16 files changed

Lines changed: 1427 additions & 0 deletions

cgroups/cgroups.go

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package cgroups
2+
3+
import (
4+
"bufio"
5+
"fmt"
6+
"io/ioutil"
7+
"os"
8+
"path/filepath"
9+
"strings"
10+
11+
rspec "github.com/opencontainers/runtime-spec/specs-go"
12+
)
13+
14+
var (
15+
// AbsCgroupPath is absolute path for container's cgroup mount
16+
AbsCgroupPath = "/cgrouptest"
17+
// RelCgroupPath is relative path for container's cgroup mount
18+
RelCgroupPath = "testdir/cgrouptest/container"
19+
)
20+
21+
// Cgroup represents interfaces for cgroup validation
22+
type Cgroup interface {
23+
GetBlockIOData(pid int, cgPath string) (*rspec.LinuxBlockIO, error)
24+
GetCPUData(pid int, cgPath string) (*rspec.LinuxCPU, error)
25+
GetDevicesData(pid int, cgPath string) ([]rspec.LinuxDeviceCgroup, error)
26+
GetHugepageLimitData(pid int, cgPath string) ([]rspec.LinuxHugepageLimit, error)
27+
GetMemoryData(pid int, cgPath string) (*rspec.LinuxMemory, error)
28+
GetNetworkData(pid int, cgPath string) (*rspec.LinuxNetwork, error)
29+
GetPidsData(pid int, cgPath string) (*rspec.LinuxPids, error)
30+
}
31+
32+
// FindCgroup gets cgroup root mountpoint
33+
func FindCgroup() (Cgroup, error) {
34+
f, err := os.Open("/proc/self/mountinfo")
35+
if err != nil {
36+
return nil, err
37+
}
38+
defer f.Close()
39+
40+
cgroupv2 := false
41+
scanner := bufio.NewScanner(f)
42+
for scanner.Scan() {
43+
text := scanner.Text()
44+
fields := strings.Split(text, " ")
45+
// Safe as mountinfo encodes mountpoints with spaces as \040.
46+
index := strings.Index(text, " - ")
47+
postSeparatorFields := strings.Fields(text[index+3:])
48+
numPostFields := len(postSeparatorFields)
49+
50+
// This is an error as we can't detect if the mount is for "cgroup"
51+
if numPostFields == 0 {
52+
return nil, fmt.Errorf("Found no fields post '-' in %q", text)
53+
}
54+
55+
if postSeparatorFields[0] == "cgroup" {
56+
// Check that the mount is properly formated.
57+
if numPostFields < 3 {
58+
return nil, fmt.Errorf("Error found less than 3 fields post '-' in %q", text)
59+
}
60+
61+
cg := &CgroupV1{
62+
MountPath: filepath.Dir(fields[4]),
63+
}
64+
return cg, nil
65+
} else if postSeparatorFields[0] == "cgroup2" {
66+
cgroupv2 = true
67+
continue
68+
//TODO cgroupv2 unimplemented
69+
}
70+
}
71+
72+
if err := scanner.Err(); err != nil {
73+
return nil, err
74+
}
75+
76+
if cgroupv2 {
77+
return nil, fmt.Errorf("cgroupv2 is not supported yet")
78+
}
79+
return nil, fmt.Errorf("cgroup is not found")
80+
}
81+
82+
// GetSubsystemPath gets path of subsystem
83+
func GetSubsystemPath(pid int, subsystem string) (string, error) {
84+
contents, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/cgroup", pid))
85+
if err != nil {
86+
return "", err
87+
}
88+
89+
parts := strings.Split(strings.TrimSpace(string(contents)), "\n")
90+
for _, part := range parts {
91+
elem := strings.SplitN(part, ":", 3)
92+
if len(elem) < 3 {
93+
continue
94+
}
95+
subelems := strings.Split(elem[1], ",")
96+
for _, subelem := range subelems {
97+
if subelem == subsystem {
98+
return elem[2], nil
99+
}
100+
}
101+
}
102+
103+
return "", fmt.Errorf("subsystem %s not found", subsystem)
104+
}

0 commit comments

Comments
 (0)