|
3 | 3 | package generate |
4 | 4 |
|
5 | 5 | import ( |
6 | | - "errors" |
7 | | - "fmt" |
8 | 6 | "os" |
9 | 7 | "path/filepath" |
10 | | - "reflect" |
11 | 8 |
|
12 | | - "github.com/containers/podman/v5/pkg/rootless" |
13 | 9 | "github.com/containers/podman/v5/pkg/specgen" |
14 | | - "github.com/opencontainers/runtime-spec/specs-go" |
15 | 10 | "go.podman.io/common/pkg/cgroups" |
16 | | - "go.podman.io/common/pkg/sysinfo" |
17 | 11 | "go.podman.io/storage/pkg/fileutils" |
18 | 12 | ) |
19 | 13 |
|
20 | | -// Verify resource limits are sanely set when running on cgroup v1. |
21 | | -func verifyContainerResourcesCgroupV1(s *specgen.SpecGenerator) ([]string, error) { |
22 | | - warnings := []string{} |
23 | | - |
24 | | - sysInfo := sysinfo.New(true) |
25 | | - |
26 | | - // If ResourceLimits is nil, return without warning |
27 | | - resourceNil := &specgen.SpecGenerator{} |
28 | | - resourceNil.ResourceLimits = &specs.LinuxResources{} |
29 | | - if s.ResourceLimits == nil || reflect.DeepEqual(s.ResourceLimits, resourceNil.ResourceLimits) { |
30 | | - return nil, nil |
31 | | - } |
32 | | - |
33 | | - // Cgroups V1 rootless system does not support Resource limits |
34 | | - if rootless.IsRootless() { |
35 | | - s.ResourceLimits = nil |
36 | | - return []string{"Resource limits are not supported and ignored on cgroups V1 rootless systems"}, nil |
37 | | - } |
38 | | - |
39 | | - if s.ResourceLimits.Unified != nil { |
40 | | - return nil, errors.New("cannot use --cgroup-conf without cgroup v2") |
41 | | - } |
42 | | - |
43 | | - // Memory checks |
44 | | - if s.ResourceLimits.Memory != nil { |
45 | | - memory := s.ResourceLimits.Memory |
46 | | - if memory.Limit != nil && !sysInfo.MemoryLimit { |
47 | | - warnings = append(warnings, "Your kernel does not support memory limit capabilities or the cgroup is not mounted. Limitation discarded.") |
48 | | - memory.Limit = nil |
49 | | - memory.Swap = nil |
50 | | - } |
51 | | - if memory.Limit != nil && memory.Swap != nil && !sysInfo.SwapLimit { |
52 | | - warnings = append(warnings, "Your kernel does not support swap limit capabilities or the cgroup is not mounted. Memory limited without swap.") |
53 | | - memory.Swap = nil |
54 | | - } |
55 | | - if memory.Limit != nil && memory.Swap != nil && *memory.Swap < *memory.Limit { |
56 | | - return warnings, errors.New("minimum memoryswap limit should be larger than memory limit, see usage") |
57 | | - } |
58 | | - if memory.Limit == nil && memory.Swap != nil { |
59 | | - return warnings, errors.New("you should always set a memory limit when using a memoryswap limit, see usage") |
60 | | - } |
61 | | - if memory.Swappiness != nil { |
62 | | - if !sysInfo.MemorySwappiness { |
63 | | - warnings = append(warnings, "Your kernel does not support memory swappiness capabilities, or the cgroup is not mounted. Memory swappiness discarded.") |
64 | | - memory.Swappiness = nil |
65 | | - } else if *memory.Swappiness > 100 { |
66 | | - return warnings, fmt.Errorf("invalid value: %v, valid memory swappiness range is 0-100", *memory.Swappiness) |
67 | | - } |
68 | | - } |
69 | | - if memory.Reservation != nil && !sysInfo.MemoryReservation { |
70 | | - warnings = append(warnings, "Your kernel does not support memory soft limit capabilities or the cgroup is not mounted. Limitation discarded.") |
71 | | - memory.Reservation = nil |
72 | | - } |
73 | | - if memory.Limit != nil && memory.Reservation != nil && *memory.Limit < *memory.Reservation { |
74 | | - return warnings, errors.New("minimum memory limit cannot be less than memory reservation limit, see usage") |
75 | | - } |
76 | | - if memory.DisableOOMKiller != nil && *memory.DisableOOMKiller && !sysInfo.OomKillDisable { |
77 | | - warnings = append(warnings, "Your kernel does not support OomKillDisable. OomKillDisable discarded.") |
78 | | - memory.DisableOOMKiller = nil |
79 | | - } |
80 | | - } |
81 | | - |
82 | | - // Pids checks |
83 | | - if s.ResourceLimits.Pids != nil { |
84 | | - // TODO: Should this be 0, or checking that ResourceLimits.Pids |
85 | | - // is set at all? |
86 | | - if s.ResourceLimits.Pids.Limit >= 0 && !sysInfo.PidsLimit { |
87 | | - warnings = append(warnings, "Your kernel does not support pids limit capabilities or the cgroup is not mounted. PIDs limit discarded.") |
88 | | - s.ResourceLimits.Pids = nil |
89 | | - } |
90 | | - } |
91 | | - |
92 | | - // CPU checks |
93 | | - if s.ResourceLimits.CPU != nil { |
94 | | - cpu := s.ResourceLimits.CPU |
95 | | - if cpu.Shares != nil && !sysInfo.CPUShares { |
96 | | - warnings = append(warnings, "Your kernel does not support CPU shares or the cgroup is not mounted. Shares discarded.") |
97 | | - cpu.Shares = nil |
98 | | - } |
99 | | - if cpu.Period != nil && !sysInfo.CPUCfsPeriod { |
100 | | - warnings = append(warnings, "Your kernel does not support CPU cfs period or the cgroup is not mounted. Period discarded.") |
101 | | - cpu.Period = nil |
102 | | - } |
103 | | - if cpu.Period != nil && (*cpu.Period < 1000 || *cpu.Period > 1000000) { |
104 | | - return warnings, errors.New("CPU cfs period cannot be less than 1ms (i.e. 1000) or larger than 1s (i.e. 1000000)") |
105 | | - } |
106 | | - if cpu.Quota != nil && !sysInfo.CPUCfsQuota { |
107 | | - warnings = append(warnings, "Your kernel does not support CPU cfs quota or the cgroup is not mounted. Quota discarded.") |
108 | | - cpu.Quota = nil |
109 | | - } |
110 | | - if cpu.Quota != nil && *cpu.Quota < 1000 { |
111 | | - return warnings, errors.New("CPU cfs quota cannot be less than 1ms (i.e. 1000)") |
112 | | - } |
113 | | - if (cpu.Cpus != "" || cpu.Mems != "") && !sysInfo.Cpuset { |
114 | | - warnings = append(warnings, "Your kernel does not support cpuset or the cgroup is not mounted. CPUset discarded.") |
115 | | - cpu.Cpus = "" |
116 | | - cpu.Mems = "" |
117 | | - } |
118 | | - |
119 | | - cpusAvailable, err := sysInfo.IsCpusetCpusAvailable(cpu.Cpus) |
120 | | - if err != nil { |
121 | | - return warnings, fmt.Errorf("invalid value %s for cpuset cpus", cpu.Cpus) |
122 | | - } |
123 | | - if !cpusAvailable { |
124 | | - return warnings, fmt.Errorf("requested CPUs are not available - requested %s, available: %s", cpu.Cpus, sysInfo.Cpus) |
125 | | - } |
126 | | - |
127 | | - memsAvailable, err := sysInfo.IsCpusetMemsAvailable(cpu.Mems) |
128 | | - if err != nil { |
129 | | - return warnings, fmt.Errorf("invalid value %s for cpuset mems", cpu.Mems) |
130 | | - } |
131 | | - if !memsAvailable { |
132 | | - return warnings, fmt.Errorf("requested memory nodes are not available - requested %s, available: %s", cpu.Mems, sysInfo.Mems) |
133 | | - } |
134 | | - } |
135 | | - |
136 | | - // Blkio checks |
137 | | - if s.ResourceLimits.BlockIO != nil { |
138 | | - blkio := s.ResourceLimits.BlockIO |
139 | | - if blkio.Weight != nil && !sysInfo.BlkioWeight { |
140 | | - warnings = append(warnings, "Your kernel does not support Block I/O weight or the cgroup is not mounted. Weight discarded.") |
141 | | - blkio.Weight = nil |
142 | | - } |
143 | | - if blkio.Weight != nil && (*blkio.Weight > 1000 || *blkio.Weight < 10) { |
144 | | - return warnings, errors.New("range of blkio weight is from 10 to 1000") |
145 | | - } |
146 | | - if len(blkio.WeightDevice) > 0 && !sysInfo.BlkioWeightDevice { |
147 | | - warnings = append(warnings, "Your kernel does not support Block I/O weight_device or the cgroup is not mounted. Weight-device discarded.") |
148 | | - blkio.WeightDevice = nil |
149 | | - } |
150 | | - if len(blkio.ThrottleReadBpsDevice) > 0 && !sysInfo.BlkioReadBpsDevice { |
151 | | - warnings = append(warnings, "Your kernel does not support BPS Block I/O read limit or the cgroup is not mounted. Block I/O BPS read limit discarded") |
152 | | - blkio.ThrottleReadBpsDevice = nil |
153 | | - } |
154 | | - if len(blkio.ThrottleWriteBpsDevice) > 0 && !sysInfo.BlkioWriteBpsDevice { |
155 | | - warnings = append(warnings, "Your kernel does not support BPS Block I/O write limit or the cgroup is not mounted. Block I/O BPS write limit discarded.") |
156 | | - blkio.ThrottleWriteBpsDevice = nil |
157 | | - } |
158 | | - if len(blkio.ThrottleReadIOPSDevice) > 0 && !sysInfo.BlkioReadIOpsDevice { |
159 | | - warnings = append(warnings, "Your kernel does not support IOPS Block read limit or the cgroup is not mounted. Block I/O IOPS read limit discarded.") |
160 | | - blkio.ThrottleReadIOPSDevice = nil |
161 | | - } |
162 | | - if len(blkio.ThrottleWriteIOPSDevice) > 0 && !sysInfo.BlkioWriteIOpsDevice { |
163 | | - warnings = append(warnings, "Your kernel does not support IOPS Block I/O write limit or the cgroup is not mounted. Block I/O IOPS write limit discarded.") |
164 | | - blkio.ThrottleWriteIOPSDevice = nil |
165 | | - } |
166 | | - } |
167 | | - |
168 | | - return warnings, nil |
169 | | -} |
170 | | - |
171 | 14 | // Verify resource limits are sanely set when running on cgroup v2. |
172 | 15 | func verifyContainerResourcesCgroupV2(s *specgen.SpecGenerator) ([]string, error) { |
173 | 16 | warnings := []string{} |
@@ -225,12 +68,9 @@ func verifyContainerResourcesCgroupV2(s *specgen.SpecGenerator) ([]string, error |
225 | 68 | // Verify resource limits are sanely set, removing any limits that are not |
226 | 69 | // possible with the current cgroups config. |
227 | 70 | func verifyContainerResources(s *specgen.SpecGenerator) ([]string, error) { |
228 | | - cgroup2, err := cgroups.IsCgroup2UnifiedMode() |
| 71 | + _, err := cgroups.IsCgroup2UnifiedMode() |
229 | 72 | if err != nil { |
230 | 73 | return []string{}, err |
231 | 74 | } |
232 | | - if cgroup2 { |
233 | | - return verifyContainerResourcesCgroupV2(s) |
234 | | - } |
235 | | - return verifyContainerResourcesCgroupV1(s) |
| 75 | + return verifyContainerResourcesCgroupV2(s) |
236 | 76 | } |
0 commit comments