cgroups 0.1.0

Native Rust crate for managing control groups on Linux
Documentation
//! This module allows the user to create a control group using the Builder pattern.
//! # Example
//!
//! The following example demonstrates how the control group builder looks like.  The user
//! specifies the name of the control group (here: "hello") and the hierarchy it belongs to (here:
//! a V1 hierarchy). Next, the user selects a subsystem by calling functions like `memory()`,
//! `cpu()` and `devices()`. The user can then add restrictions and details via subsystem-specific
//! calls. To finalize a subsystem, the user may call `done()`. Finally, if the control group build
//! is done and all requirements/restrictions have been specified, the control group can be created
//! by a call to `build()`.
//!
//! ```rust,no_run
//! # use cgroups::*;
//! # use cgroups::devices::*;
//! # use cgroups::cgroup_builder::*;
//! let v1 = cgroups::hierarchies::V1::new();
//! let cgroup: Cgroup = CgroupBuilder::new("hello", &v1)
//!      .memory()
//!          .kernel_memory_limit(1024 * 1024)
//!          .memory_hard_limit(1024 * 1024)
//!          .done()
//!      .cpu()
//!          .shares(100)
//!          .done()
//!      .devices()
//!          .device(1000, 10, DeviceType::Block, true,
//!             vec![DevicePermissions::Read,
//!                  DevicePermissions::Write,
//!                  DevicePermissions::MkNod])
//!          .device(6, 1, DeviceType::Char, false, vec![])
//!          .done()
//!      .network()
//!          .class_id(1337)
//!          .priority("eth0".to_string(), 100)
//!          .priority("wl0".to_string(), 200)
//!          .done()
//!      .hugepages()
//!          .limit("2M".to_string(), 0)
//!          .limit("4M".to_string(), 4 * 1024 * 1024 * 100)
//!          .limit("2G".to_string(), 2 * 1024 * 1024 * 1024)
//!          .done()
//!      .blkio()
//!          .weight(123)
//!          .leaf_weight(99)
//!          .weight_device(6, 1, 100, 55)
//!          .weight_device(6, 1, 100, 55)
//!          .throttle_iops()
//!              .read(6, 1, 10)
//!              .write(11, 1, 100)
//!          .throttle_bps()
//!              .read(6, 1, 10)
//!              .write(11, 1, 100)
//!          .done()
//!      .build();
//! ```
use error::*;

use {pid, BlkIoDeviceResource, BlkIoDeviceThrottleResource,  Cgroup, DeviceResource, Hierarchy, HugePageResource, NetworkPriority, Resources};

macro_rules! gen_setter {
    ($res:ident, $cont:ident, $func:ident, $name:ident, $ty:ty) => {
        /// See the similarly named function in the respective controller.
        pub fn $name(mut self, $name: $ty) -> Self {
            self.cgroup.resources.$res.update_values = true;
            self.cgroup.resources.$res.$name = $name;
            self
        }
    }
}

/// A control group builder instance
pub struct CgroupBuilder<'a> {
    name: String,
    hierarchy: &'a Hierarchy,
    /// Internal, unsupported field: use the associated builders instead.
    resources: Resources,
}

impl<'a> CgroupBuilder<'a> {
    /// Start building a control group with the supplied hierarchy and name pair.
    ///
    /// Note that this does not actually create the control group until `build()` is called.
    pub fn new(name: &'a str, hierarchy: &'a Hierarchy) -> CgroupBuilder<'a> {
        CgroupBuilder {
            name: name.to_owned(),
            hierarchy: hierarchy,
            resources: Resources::default(),
        }
    }

    /// Builds the memory resources of the control group.
    pub fn memory(self) -> MemoryResourceBuilder<'a> {
        MemoryResourceBuilder {
            cgroup: self,
        }
    }

    /// Builds the pid resources of the control group.
    pub fn pid(self) -> PidResourceBuilder<'a> {
        PidResourceBuilder {
            cgroup: self,
        }
    }

    /// Builds the cpu resources of the control group.
    pub fn cpu(self) -> CpuResourceBuilder<'a> {
        CpuResourceBuilder {
            cgroup: self,
        }
    }

    /// Builds the devices resources of the control group, disallowing or
    /// allowing access to certain devices in the system.
    pub fn devices(self) -> DeviceResourceBuilder<'a> {
        DeviceResourceBuilder {
            cgroup: self,
        }
    }

    /// Builds the network resources of the control group, setting class id, or
    /// various priorities on networking interfaces.
    pub fn network(self) -> NetworkResourceBuilder<'a> {
        NetworkResourceBuilder {
            cgroup: self,
        }
    }

    /// Builds the hugepage/hugetlb resources available to the control group.
    pub fn hugepages(self) -> HugepagesResourceBuilder<'a> {
        HugepagesResourceBuilder {
            cgroup: self,
        }
    }

    /// Builds the block I/O resources available for the control group.
    pub fn blkio(self) -> BlkIoResourcesBuilder<'a> {
        BlkIoResourcesBuilder {
            cgroup: self,
            throttling_iops: false,
        }
    }

    /// Finalize the control group, consuming the builder and creating the control group.
    pub fn build(self) -> Cgroup<'a> {
        let cg = Cgroup::new(self.hierarchy, self.name);
        cg.apply(&self.resources);
        cg
    }
}

/// A builder that configures the memory controller of a control group.
pub struct MemoryResourceBuilder<'a> {
    cgroup: CgroupBuilder<'a>,
}

impl<'a> MemoryResourceBuilder<'a> {

    gen_setter!(memory, MemController, set_kmem_limit, kernel_memory_limit, u64);
    gen_setter!(memory, MemController, set_limit, memory_hard_limit, u64);
    gen_setter!(memory, MemController, set_soft_limit, memory_soft_limit, u64);
    gen_setter!(memory, MemController, set_tcp_limit, kernel_tcp_memory_limit, u64);
    gen_setter!(memory, MemController, set_memswap_limit, memory_swap_limit, u64);
    gen_setter!(memory, MemController, set_swappiness, swappiness, u64);

    /// Finish the construction of the memory resources of a control group.
    pub fn done(self) -> CgroupBuilder<'a> {
        self.cgroup
    }
}

/// A builder that configures the pid controller of a control group.
pub struct PidResourceBuilder<'a> {
    cgroup: CgroupBuilder<'a>,
}

impl<'a> PidResourceBuilder<'a> {

    gen_setter!(pid, PidController, set_pid_max, maximum_number_of_processes, pid::PidMax);

    /// Finish the construction of the pid resources of a control group.
    pub fn done(self) -> CgroupBuilder<'a> {
        self.cgroup
    }
}

/// A builder that configures the cpuset & cpu controllers of a control group.
pub struct CpuResourceBuilder<'a> {
    cgroup: CgroupBuilder<'a>,
}

impl<'a> CpuResourceBuilder<'a> {

    gen_setter!(cpu, CpuSetController, set_cpus, cpus, String);
    gen_setter!(cpu, CpuSetController, set_mems, mems, String);
    gen_setter!(cpu, CpuController, set_shares, shares, u64);
    gen_setter!(cpu, CpuController, set_cfs_quota, quota, i64);
    gen_setter!(cpu, CpuController, set_cfs_period, period, u64);
    gen_setter!(cpu, CpuController, set_rt_runtime, realtime_runtime, i64);
    gen_setter!(cpu, CpuController, set_rt_period, realtime_period, u64);

    /// Finish the construction of the cpu resources of a control group.
    pub fn done(self) -> CgroupBuilder<'a> {
        self.cgroup
    }
}

/// A builder that configures the devices controller of a control group.
pub struct DeviceResourceBuilder<'a> {
    cgroup: CgroupBuilder<'a>,
}

impl<'a> DeviceResourceBuilder<'a> {

    /// Restrict (or allow) a device to the tasks inside the control group.
    pub fn device(mut self,
                  major: i64,
                  minor: i64,
                  devtype: ::devices::DeviceType,
                  allow: bool,
                  access: Vec<::devices::DevicePermissions>)
            -> DeviceResourceBuilder<'a> {
        self.cgroup.resources.devices.update_values = true;
        self.cgroup.resources.devices.devices.push(DeviceResource {
            major,
            minor,
            devtype,
            allow,
            access
        });
        self
    }

    /// Finish the construction of the devices resources of a control group.
    pub fn done(self) -> CgroupBuilder<'a> {
        self.cgroup
    }
}

/// A builder that configures the net_cls & net_prio controllers of a control group.
pub struct NetworkResourceBuilder<'a> {
    cgroup: CgroupBuilder<'a>,
}

impl<'a> NetworkResourceBuilder<'a> {

    gen_setter!(network, NetclsController, set_class, class_id, u64);

    /// Set the priority of the tasks when operating on a networking device defined by `name` to be
    /// `priority`.
    pub fn priority(mut self, name: String, priority: u64)
        -> NetworkResourceBuilder<'a> {
        self.cgroup.resources.network.update_values = true;
        self.cgroup.resources.network.priorities.push(NetworkPriority {
            name,
            priority,
        });
        self
    }

    /// Finish the construction of the network resources of a control group.
    pub fn done(self) -> CgroupBuilder<'a> {
        self.cgroup
    }
}

/// A builder that configures the hugepages controller of a control group.
pub struct HugepagesResourceBuilder<'a> {
    cgroup: CgroupBuilder<'a>,
}

impl<'a> HugepagesResourceBuilder<'a> {

    /// Limit the usage of certain hugepages (determined by `size`) to be at most `limit` bytes.
    pub fn limit(mut self, size: String, limit: u64)
        -> HugepagesResourceBuilder<'a> {
        self.cgroup.resources.hugepages.update_values = true;
        self.cgroup.resources.hugepages.limits.push(HugePageResource {
            size,
            limit,
        });
        self
    }

    /// Finish the construction of the network resources of a control group.
    pub fn done(self) -> CgroupBuilder<'a> {
        self.cgroup
    }
}

/// A builder that configures the blkio controller of a control group.
pub struct BlkIoResourcesBuilder<'a> {
    cgroup: CgroupBuilder<'a>,
    throttling_iops: bool,
}

impl<'a> BlkIoResourcesBuilder<'a> {

    gen_setter!(blkio, BlkIoController, set_weight, weight, u16);
    gen_setter!(blkio, BlkIoController, set_leaf_weight, leaf_weight, u16);

    /// Set the weight of a certain device.
    pub fn weight_device(mut self,
                         major: u64,
                         minor: u64,
                         weight: u16,
                         leaf_weight: u16)
        -> BlkIoResourcesBuilder<'a> {
        self.cgroup.resources.blkio.update_values = true;
        self.cgroup.resources.blkio.weight_device.push(BlkIoDeviceResource {
            major,
            minor,
            weight,
            leaf_weight,
        });
        self
    }

    /// Start configuring the I/O operations per second metric.
    pub fn throttle_iops(mut self) -> BlkIoResourcesBuilder<'a> {
        self.throttling_iops = true;
        self
    }

    /// Start configuring the bytes per second metric.
    pub fn throttle_bps(mut self) -> BlkIoResourcesBuilder<'a> {
        self.throttling_iops = false;
        self
    }

    /// Limit the read rate of the current metric for a certain device.
    pub fn read(mut self, major: u64, minor: u64, rate: u64)
        -> BlkIoResourcesBuilder<'a> {
        self.cgroup.resources.blkio.update_values = true;
        let throttle = BlkIoDeviceThrottleResource {
            major,
            minor,
            rate,
        };
        if self.throttling_iops {
            self.cgroup.resources.blkio.throttle_read_iops_device.push(throttle);
        } else {
            self.cgroup.resources.blkio.throttle_read_bps_device.push(throttle);
        }
        self
    }

    /// Limit the write rate of the current metric for a certain device.
    pub fn write(mut self, major: u64, minor: u64, rate: u64)
        -> BlkIoResourcesBuilder<'a> {
        self.cgroup.resources.blkio.update_values = true;
        let throttle = BlkIoDeviceThrottleResource {
            major,
            minor,
            rate,
        };
        if self.throttling_iops {
            self.cgroup.resources.blkio.throttle_write_iops_device.push(throttle);
        } else {
            self.cgroup.resources.blkio.throttle_write_bps_device.push(throttle);
        }
        self
    }

    /// Finish the construction of the blkio resources of a control group.
    pub fn done(self) -> CgroupBuilder<'a> {
        self.cgroup
    }
}