cgroups_rs/fs/cgroup_builder.rs
1// Copyright (c) 2018 Levente Kurusa
2// Copyright (c) 2020 Ant Group
3//
4// SPDX-License-Identifier: Apache-2.0 or MIT
5//
6
7//! This module allows the user to create a control group using the Builder pattern.
8//! # Example
9//!
10//! The following example demonstrates how the control group builder looks like. The user
11//! specifies the name of the control group (here: "hello") and the hierarchy it belongs to (here:
12//! a V1 hierarchy). Next, the user selects a subsystem by calling functions like `memory()`,
13//! `cpu()` and `devices()`. The user can then add restrictions and details via subsystem-specific
14//! calls. To finalize a subsystem, the user may call `done()`. Finally, if the control group build
15//! is done and all requirements/restrictions have been specified, the control group can be created
16//! by a call to `build()`.
17//!
18//! ```rust,no_run
19//! # use cgroups_rs::fs::*;
20//! # use cgroups_rs::fs::devices::*;
21//! # use cgroups_rs::fs::cgroup_builder::*;
22//! let h = cgroups_rs::fs::hierarchies::auto();
23//! let cgroup: Cgroup = CgroupBuilder::new("hello")
24//! .memory()
25//! .kernel_memory_limit(1024 * 1024)
26//! .memory_hard_limit(1024 * 1024)
27//! .done()
28//! .cpu()
29//! .shares(100)
30//! .done()
31//! .devices()
32//! .device(1000, 10, DeviceType::Block, true,
33//! vec![DevicePermissions::Read,
34//! DevicePermissions::Write,
35//! DevicePermissions::MkNod])
36//! .device(6, 1, DeviceType::Char, false, vec![])
37//! .done()
38//! .network()
39//! .class_id(1337)
40//! .priority("eth0".to_string(), 100)
41//! .priority("wl0".to_string(), 200)
42//! .done()
43//! .hugepages()
44//! .limit("2M".to_string(), 0)
45//! .limit("4M".to_string(), 4 * 1024 * 1024 * 100)
46//! .limit("2G".to_string(), 2 * 1024 * 1024 * 1024)
47//! .done()
48//! .blkio()
49//! .weight(123)
50//! .leaf_weight(99)
51//! .weight_device(6, 1, Some(100), Some(55))
52//! .weight_device(6, 1, Some(100), Some(55))
53//! .throttle_iops()
54//! .read(6, 1, 10)
55//! .write(11, 1, 100)
56//! .throttle_bps()
57//! .read(6, 1, 10)
58//! .write(11, 1, 100)
59//! .done()
60//! .build(h).unwrap();
61//! ```
62
63use crate::fs::{
64 BlkIoDeviceResource, BlkIoDeviceThrottleResource, Cgroup, DeviceResource, Error, Hierarchy,
65 HugePageResource, MaxValue, NetworkPriority, Resources,
66};
67
68macro_rules! gen_setter {
69 ($res:ident, $cont:ident, $func:ident, $name:ident, $ty:ty) => {
70 /// See the similarly named function in the respective controller.
71 pub fn $name(mut self, $name: $ty) -> Self {
72 self.cgroup.resources.$res.$name = Some($name);
73 self
74 }
75 };
76}
77
78/// A control group builder instance
79pub struct CgroupBuilder {
80 name: String,
81 /// Internal, unsupported field: use the associated builders instead.
82 resources: Resources,
83 /// List of controllers specifically enabled in the control group.
84 specified_controllers: Option<Vec<String>>,
85}
86
87impl CgroupBuilder {
88 /// Start building a control group with the supplied hierarchy and name pair.
89 ///
90 /// Note that this does not actually create the control group until `build()` is called.
91 pub fn new(name: &str) -> CgroupBuilder {
92 CgroupBuilder {
93 name: name.to_owned(),
94 resources: Resources::default(),
95 specified_controllers: None,
96 }
97 }
98
99 /// Builds the memory resources of the control group.
100 pub fn memory(self) -> MemoryResourceBuilder {
101 MemoryResourceBuilder { cgroup: self }
102 }
103
104 /// Builds the pid resources of the control group.
105 pub fn pid(self) -> PidResourceBuilder {
106 PidResourceBuilder { cgroup: self }
107 }
108
109 /// Builds the cpu resources of the control group.
110 pub fn cpu(self) -> CpuResourceBuilder {
111 CpuResourceBuilder { cgroup: self }
112 }
113
114 /// Builds the devices resources of the control group, disallowing or
115 /// allowing access to certain devices in the system.
116 pub fn devices(self) -> DeviceResourceBuilder {
117 DeviceResourceBuilder { cgroup: self }
118 }
119
120 /// Builds the network resources of the control group, setting class id, or
121 /// various priorities on networking interfaces.
122 pub fn network(self) -> NetworkResourceBuilder {
123 NetworkResourceBuilder { cgroup: self }
124 }
125
126 /// Builds the hugepage/hugetlb resources available to the control group.
127 pub fn hugepages(self) -> HugepagesResourceBuilder {
128 HugepagesResourceBuilder { cgroup: self }
129 }
130
131 /// Builds the block I/O resources available for the control group.
132 pub fn blkio(self) -> BlkIoResourcesBuilder {
133 BlkIoResourcesBuilder {
134 cgroup: self,
135 throttling_iops: false,
136 }
137 }
138
139 /// Finalize the control group, consuming the builder and creating the control group.
140 pub fn build(self, hier: Box<dyn Hierarchy>) -> Result<Cgroup, Error> {
141 if let Some(controllers) = self.specified_controllers {
142 let cg = Cgroup::new_with_specified_controllers(hier, self.name, Some(controllers))?;
143 cg.apply(&self.resources)?;
144 Ok(cg)
145 } else {
146 let cg = Cgroup::new(hier, self.name)?;
147 cg.apply(&self.resources)?;
148 Ok(cg)
149 }
150 }
151
152 /// Specifically enable some controllers in the control group.
153 pub fn set_specified_controllers(mut self, specified_controllers: Vec<String>) -> Self {
154 self.specified_controllers = Some(specified_controllers);
155 self
156 }
157}
158
159/// A builder that configures the memory controller of a control group.
160pub struct MemoryResourceBuilder {
161 cgroup: CgroupBuilder,
162}
163
164impl MemoryResourceBuilder {
165 gen_setter!(
166 memory,
167 MemController,
168 set_kmem_limit,
169 kernel_memory_limit,
170 i64
171 );
172 gen_setter!(memory, MemController, set_limit, memory_hard_limit, i64);
173 gen_setter!(
174 memory,
175 MemController,
176 set_soft_limit,
177 memory_soft_limit,
178 i64
179 );
180 gen_setter!(
181 memory,
182 MemController,
183 set_tcp_limit,
184 kernel_tcp_memory_limit,
185 i64
186 );
187 gen_setter!(
188 memory,
189 MemController,
190 set_memswap_limit,
191 memory_swap_limit,
192 i64
193 );
194 gen_setter!(memory, MemController, set_swappiness, swappiness, u64);
195
196 /// Finish the construction of the memory resources of a control group.
197 pub fn done(self) -> CgroupBuilder {
198 self.cgroup
199 }
200}
201
202/// A builder that configures the pid controller of a control group.
203pub struct PidResourceBuilder {
204 cgroup: CgroupBuilder,
205}
206
207impl PidResourceBuilder {
208 gen_setter!(
209 pid,
210 PidController,
211 set_pid_max,
212 maximum_number_of_processes,
213 MaxValue
214 );
215
216 /// Finish the construction of the pid resources of a control group.
217 pub fn done(self) -> CgroupBuilder {
218 self.cgroup
219 }
220}
221
222/// A builder that configures the cpuset & cpu controllers of a control group.
223pub struct CpuResourceBuilder {
224 cgroup: CgroupBuilder,
225}
226
227impl CpuResourceBuilder {
228 gen_setter!(cpu, CpuSetController, set_cpus, cpus, String);
229 gen_setter!(cpu, CpuSetController, set_mems, mems, String);
230 gen_setter!(cpu, CpuController, set_shares, shares, u64);
231 gen_setter!(cpu, CpuController, set_cfs_quota, quota, i64);
232 gen_setter!(cpu, CpuController, set_cfs_period, period, u64);
233 gen_setter!(cpu, CpuController, set_rt_runtime, realtime_runtime, i64);
234 gen_setter!(cpu, CpuController, set_rt_period, realtime_period, u64);
235
236 /// Finish the construction of the cpu resources of a control group.
237 pub fn done(self) -> CgroupBuilder {
238 self.cgroup
239 }
240}
241
242/// A builder that configures the devices controller of a control group.
243pub struct DeviceResourceBuilder {
244 cgroup: CgroupBuilder,
245}
246
247impl DeviceResourceBuilder {
248 /// Restrict (or allow) a device to the tasks inside the control group.
249 pub fn device(
250 mut self,
251 major: i64,
252 minor: i64,
253 devtype: crate::fs::devices::DeviceType,
254 allow: bool,
255 access: Vec<crate::fs::devices::DevicePermissions>,
256 ) -> DeviceResourceBuilder {
257 self.cgroup.resources.devices.devices.push(DeviceResource {
258 allow,
259 devtype,
260 major,
261 minor,
262 access,
263 });
264 self
265 }
266
267 /// Finish the construction of the devices resources of a control group.
268 pub fn done(self) -> CgroupBuilder {
269 self.cgroup
270 }
271}
272
273/// A builder that configures the net_cls & net_prio controllers of a control group.
274pub struct NetworkResourceBuilder {
275 cgroup: CgroupBuilder,
276}
277
278impl NetworkResourceBuilder {
279 gen_setter!(network, NetclsController, set_class, class_id, u64);
280
281 /// Set the priority of the tasks when operating on a networking device defined by `name` to be
282 /// `priority`.
283 pub fn priority(mut self, name: String, priority: u64) -> NetworkResourceBuilder {
284 self.cgroup
285 .resources
286 .network
287 .priorities
288 .push(NetworkPriority { name, priority });
289 self
290 }
291
292 /// Finish the construction of the network resources of a control group.
293 pub fn done(self) -> CgroupBuilder {
294 self.cgroup
295 }
296}
297
298/// A builder that configures the hugepages controller of a control group.
299pub struct HugepagesResourceBuilder {
300 cgroup: CgroupBuilder,
301}
302
303impl HugepagesResourceBuilder {
304 /// Limit the usage of certain hugepages (determined by `size`) to be at most `limit` bytes.
305 pub fn limit(mut self, size: String, limit: u64) -> HugepagesResourceBuilder {
306 self.cgroup
307 .resources
308 .hugepages
309 .limits
310 .push(HugePageResource { size, limit });
311 self
312 }
313
314 /// Finish the construction of the network resources of a control group.
315 pub fn done(self) -> CgroupBuilder {
316 self.cgroup
317 }
318}
319
320/// A builder that configures the blkio controller of a control group.
321pub struct BlkIoResourcesBuilder {
322 cgroup: CgroupBuilder,
323 throttling_iops: bool,
324}
325
326impl BlkIoResourcesBuilder {
327 gen_setter!(blkio, BlkIoController, set_weight, weight, u16);
328 gen_setter!(blkio, BlkIoController, set_leaf_weight, leaf_weight, u16);
329
330 /// Set the weight of a certain device.
331 pub fn weight_device(
332 mut self,
333 major: u64,
334 minor: u64,
335 weight: Option<u16>,
336 leaf_weight: Option<u16>,
337 ) -> BlkIoResourcesBuilder {
338 self.cgroup
339 .resources
340 .blkio
341 .weight_device
342 .push(BlkIoDeviceResource {
343 major,
344 minor,
345 weight,
346 leaf_weight,
347 });
348 self
349 }
350
351 /// Start configuring the I/O operations per second metric.
352 pub fn throttle_iops(mut self) -> BlkIoResourcesBuilder {
353 self.throttling_iops = true;
354 self
355 }
356
357 /// Start configuring the bytes per second metric.
358 pub fn throttle_bps(mut self) -> BlkIoResourcesBuilder {
359 self.throttling_iops = false;
360 self
361 }
362
363 /// Limit the read rate of the current metric for a certain device.
364 pub fn read(mut self, major: u64, minor: u64, rate: u64) -> BlkIoResourcesBuilder {
365 let throttle = BlkIoDeviceThrottleResource { major, minor, rate };
366 if self.throttling_iops {
367 self.cgroup
368 .resources
369 .blkio
370 .throttle_read_iops_device
371 .push(throttle);
372 } else {
373 self.cgroup
374 .resources
375 .blkio
376 .throttle_read_bps_device
377 .push(throttle);
378 }
379 self
380 }
381
382 /// Limit the write rate of the current metric for a certain device.
383 pub fn write(mut self, major: u64, minor: u64, rate: u64) -> BlkIoResourcesBuilder {
384 let throttle = BlkIoDeviceThrottleResource { major, minor, rate };
385 if self.throttling_iops {
386 self.cgroup
387 .resources
388 .blkio
389 .throttle_write_iops_device
390 .push(throttle);
391 } else {
392 self.cgroup
393 .resources
394 .blkio
395 .throttle_write_bps_device
396 .push(throttle);
397 }
398 self
399 }
400
401 /// Finish the construction of the blkio resources of a control group.
402 pub fn done(self) -> CgroupBuilder {
403 self.cgroup
404 }
405}