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}