func()

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
}