in internal/resource/resource_linux.go [229:306]
func (c cgroupv2Client) Apply(constraint Constraint) error {
// Check that the controller we need are actually enabled.
// The controllers file should contain both the cpu and memory controllers.
controlContents, err := os.ReadFile(filepath.Join(c.cgroupsDir, "cgroup.controllers"))
if err != nil {
return fmt.Errorf("failed to read cgroup.controllers file: %w", err)
}
controlContentsSplit := strings.Fields(string(controlContents))
cpuEnabled := slices.Contains(controlContentsSplit, "cpu")
memoryEnabled := slices.Contains(controlContentsSplit, "memory")
// Now check that the subtree_control file enables cpu and memory controllers.
subtreeControlContents, err := os.ReadFile(filepath.Join(c.cgroupsDir, "cgroup.subtree_control"))
if err != nil {
return fmt.Errorf("failed to read cgroup.subtree_control file: %w", err)
}
subtreeControlContentsSplit := strings.Fields(string(subtreeControlContents))
cpuEnabled = cpuEnabled && !slices.Contains(subtreeControlContentsSplit, "-cpu") && slices.Contains(subtreeControlContentsSplit, "cpu")
memoryEnabled = memoryEnabled && !slices.Contains(subtreeControlContentsSplit, "-memory") && slices.Contains(subtreeControlContentsSplit, "memory")
// Make the guest_agent cgroup dir.
// Only make and setup the directory if one of the controllers are enabled.
if cpuEnabled || memoryEnabled {
guestAgentDir := filepath.Join(c.cgroupsDir, guestAgentCgroupDir)
// Only try to create the guest-agent directory if it doesn't exist.
if !file.Exists(guestAgentDir, file.TypeDir) {
if err := os.MkdirAll(filepath.Join(c.cgroupsDir, guestAgentCgroupDir), 0755); err != nil {
return fmt.Errorf("failed to create guest_agent cgroup: %w", err)
}
subtreeControl := make([]string, 0)
if cpuEnabled {
subtreeControl = append(subtreeControl, "+cpu")
}
if memoryEnabled {
subtreeControl = append(subtreeControl, "+memory")
}
// Ensure the proper controllers are enabled.
guestAgentControlFile := filepath.Join(c.cgroupsDir, guestAgentCgroupDir, "cgroup.subtree_control")
if err := os.WriteFile(guestAgentControlFile, []byte(strings.Join(subtreeControl, " ")), 0755); err != nil {
return fmt.Errorf("failed to write cgroup.subtree_control file: %w", err)
}
}
}
if constraint.MaxCPUUsage != 0 && constraint.MaxMemoryUsage != 0 {
if !cpuEnabled && !memoryEnabled {
return fmt.Errorf("both cpu and memory controllers disabled")
}
}
if constraint.MaxCPUUsage != 0 || constraint.MaxMemoryUsage != 0 {
// Create a cgroup directory for all things guest-agent related.
pluginPath := filepath.Join(c.cgroupsDir, guestAgentCgroupDir, constraint.Name)
if err := os.MkdirAll(pluginPath, 0755); err != nil {
return fmt.Errorf("failed to create cgroup directory for %s: %v", constraint.Name, err)
}
if constraint.MaxCPUUsage != 0 {
if !cpuEnabled {
return fmt.Errorf("cpu controller disabled")
}
if err := writeCPUControllerConfig(pluginPath, constraint, cgroupv2); err != nil {
return err
}
}
if constraint.MaxMemoryUsage != 0 {
if !memoryEnabled {
return fmt.Errorf("memory controller disabled")
}
if err := writeMemoryControllerConfig(pluginPath, constraint, c.memoryLimitFile); err != nil {
return err
}
}
}
return nil
}