...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package cgroups
17
18 import (
19 "bufio"
20 "bytes"
21 "fmt"
22 "io"
23 "os"
24 "os/exec"
25 "strings"
26
27 "github.com/containerd/cgroups"
28 "github.com/pkg/errors"
29 )
30
31 func V1() ([]cgroups.Subsystem, error) {
32 subsystems, err := defaults("/host-sys/fs/cgroup")
33 if err != nil {
34 return nil, err
35 }
36 var enabled []cgroups.Subsystem
37 for _, s := range pathers(subsystems) {
38
39 if _, err := os.Lstat(s.Path("/")); err == nil {
40 enabled = append(enabled, s)
41 }
42 }
43 return enabled, nil
44 }
45
46 func PidPath(pid int) cgroups.Path {
47 p := fmt.Sprintf("/proc/%d/cgroup", pid)
48 paths, err := cgroups.ParseCgroupFile(p)
49 if err != nil {
50 return func(_ cgroups.Name) (string, error) {
51 return "", errors.Wrapf(err, "parse cgroup file %s", p)
52 }
53 }
54
55 return func(name cgroups.Name) (string, error) {
56 root, ok := paths[string(name)]
57 if !ok {
58 if root, ok = paths["name="+string(name)]; !ok {
59 return "", errors.New("controller is not supported")
60 }
61 }
62
63 return root, nil
64 }
65 }
66
67 func V2PidGroupPath(pid int) (string, error) {
68
69
70 command := exec.Command("nsenter", "-C", "-t", "1", "cat", fmt.Sprintf("/proc/%d/cgroup", pid))
71 var buffer bytes.Buffer
72 command.Stdout = &buffer
73
74 err := command.Run()
75 if err != nil {
76 return "", errors.Wrapf(err, "get cgroup path of pid %d", pid)
77 }
78 return parseCgroupFromReader(&buffer)
79 }
80
81
82 func parseCgroupFromReader(r io.Reader) (string, error) {
83 var (
84 s = bufio.NewScanner(r)
85 )
86 for s.Scan() {
87 var (
88 text = s.Text()
89 parts = strings.SplitN(text, ":", 3)
90 )
91 if len(parts) < 3 {
92 return "", fmt.Errorf("invalid cgroup entry: %q", text)
93 }
94
95 if parts[0] == "0" && parts[1] == "" {
96 return parts[2], nil
97 }
98 }
99 if err := s.Err(); err != nil {
100 return "", err
101 }
102 return "", fmt.Errorf("cgroup path not found")
103 }
104