1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package server
17
18 import (
19 "context"
20 "fmt"
21 "regexp"
22 "strconv"
23 "strings"
24
25 "github.com/pkg/errors"
26 v1 "k8s.io/api/core/v1"
27
28 "github.com/chaos-mesh/chaos-mesh/pkg/bpm"
29 "github.com/chaos-mesh/chaos-mesh/pkg/ctrl/server/model"
30 )
31
32
33 func (r *Resolver) GetCgroups(ctx context.Context, obj *model.PodStressChaos) (*model.Cgroups, error) {
34 cmd := "cat /proc/cgroups"
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 raw, err := r.ExecBypass(ctx, obj.Pod, cmd, bpm.PidNS, bpm.MountNS)
55
56 if err != nil {
57 return nil, err
58 }
59
60 cgroups := &model.Cgroups{
61 Raw: raw,
62 }
63
64
65 if obj.StressChaos.Spec.StressngStressors != "" || obj.StressChaos.Spec.Stressors == nil {
66 return cgroups, nil
67 }
68
69 isCPU := true
70 if obj.StressChaos.Spec.Stressors.CPUStressor == nil {
71 isCPU = false
72 }
73
74 if isCPU {
75 var cpuMountType string
76 if regexp.MustCompile("(cpu,cpuacct)").MatchString(string(raw)) {
77 cpuMountType = "cpu,cpuacct"
78 } else {
79
80 cpuMountType = "cpu"
81 }
82 cgroups.CPU = &model.CgroupsCPU{}
83 cgroups.CPU.Quota, err = r.GetCPUQuota(ctx, obj.Pod, cpuMountType)
84 if err != nil {
85 return nil, err
86 }
87 cgroups.CPU.Period, err = r.GetCPUPeriod(ctx, obj.Pod, cpuMountType)
88 if err != nil {
89 return nil, err
90 }
91 } else {
92 cgroups.Memory = &model.CgroupsMemory{}
93 cgroups.Memory.Limit, err = r.GetMemoryLimit(ctx, obj.Pod)
94 if err != nil {
95 return nil, err
96 }
97 }
98
99 return cgroups, nil
100 }
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117 func (r *Resolver) GetCgroup(ctx context.Context, obj *v1.Pod, pid string) (string, error) {
118 cmd := fmt.Sprintf("cat /proc/%s/cgroup", pid)
119 return r.ExecBypass(ctx, obj, cmd, bpm.PidNS, bpm.MountNS)
120 }
121
122
123 func (r *Resolver) GetCPUQuota(ctx context.Context, obj *v1.Pod, cpuMountType string) (int, error) {
124 cmd := fmt.Sprintf("cat /sys/fs/cgroup/%s/cpu.cfs_quota_us", cpuMountType)
125 out, err := r.ExecBypass(ctx, obj, cmd, bpm.PidNS, bpm.MountNS)
126 if err != nil {
127 return 0, err
128 }
129 return strconv.Atoi(strings.TrimSuffix(string(out), "\n"))
130 }
131
132
133 func (r *Resolver) GetCPUPeriod(ctx context.Context, obj *v1.Pod, cpuMountType string) (int, error) {
134 cmd := fmt.Sprintf("cat /sys/fs/cgroup/%s/cpu.cfs_period_us", cpuMountType)
135 out, err := r.ExecBypass(ctx, obj, cmd, bpm.PidNS, bpm.MountNS)
136 if err != nil {
137 return 0, err
138 }
139 return strconv.Atoi(strings.TrimSuffix(string(out), "\n"))
140 }
141
142
143 func (r *Resolver) GetMemoryLimit(ctx context.Context, obj *v1.Pod) (int64, error) {
144 cmd := "cat /sys/fs/cgroup/memory/memory.limit_in_bytes"
145 rawLimit, err := r.ExecBypass(ctx, obj, cmd, bpm.PidNS, bpm.MountNS)
146 if err != nil {
147 return 0, errors.Wrap(err, "could not get memory.limit_in_bytes")
148 }
149 limit, err := strconv.ParseUint(strings.TrimSuffix(rawLimit, "\n"), 10, 64)
150 if err != nil {
151 return 0, errors.Wrap(err, "could not parse memory.limit_in_bytes")
152 }
153 return int64(limit), nil
154 }
155