mirror of
https://github.com/kemko/nomad.git
synced 2026-01-02 16:35:44 +03:00
110 lines
3.2 KiB
Go
110 lines
3.2 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
//go:build linux
|
|
|
|
package cgroupslib
|
|
|
|
import (
|
|
"bytes"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/hashicorp/go-hclog"
|
|
"github.com/hashicorp/go-set"
|
|
)
|
|
|
|
func Init(log hclog.Logger) {
|
|
switch GetMode() {
|
|
case CG1:
|
|
// create the /nomad cgroup (or whatever the name is configured to be)
|
|
// for each cgroup controller we are going to use
|
|
controllers := []string{"freezer", "memory", "cpu", "cpuset"}
|
|
for _, ctrl := range controllers {
|
|
p := filepath.Join(root, ctrl, NomadCgroupParent)
|
|
if err := os.MkdirAll(p, 0755); err != nil {
|
|
log.Error("failed to create nomad cgroup", "controller", ctrl, "error", err)
|
|
}
|
|
}
|
|
case CG2:
|
|
// minimum controllers must be set first
|
|
s, err := readRootCG2("cgroup.subtree_control")
|
|
if err != nil {
|
|
log.Error("failed to create nomad cgroup", "error", err)
|
|
return
|
|
}
|
|
|
|
required := set.From([]string{"cpuset", "cpu", "io", "memory", "pids"})
|
|
enabled := set.From(strings.Fields(s))
|
|
needed := required.Difference(enabled)
|
|
|
|
if needed.Size() == 0 {
|
|
log.Debug("top level nomad.slice cgroup already exists")
|
|
return // already setup
|
|
}
|
|
|
|
sb := new(strings.Builder)
|
|
for _, controller := range needed.List() {
|
|
sb.WriteString("+" + controller + " ")
|
|
}
|
|
|
|
activation := strings.TrimSpace(sb.String())
|
|
if err = writeRootCG2("cgroup.subtree_control", activation); err != nil {
|
|
log.Error("failed to create nomad cgroup", "error", err)
|
|
return
|
|
}
|
|
|
|
nomadSlice := filepath.Join("/sys/fs/cgroup", NomadCgroupParent)
|
|
if err := os.MkdirAll(nomadSlice, 0755); err != nil {
|
|
log.Error("failed to create nomad cgroup", "error", err)
|
|
return
|
|
}
|
|
|
|
log.Debug("top level nomad.slice cgroup initialized", "controllers", needed)
|
|
}
|
|
}
|
|
|
|
func readRootCG2(filename string) (string, error) {
|
|
p := filepath.Join(root, filename)
|
|
b, err := os.ReadFile(p)
|
|
return string(bytes.TrimSpace(b)), err
|
|
}
|
|
|
|
func writeRootCG2(filename, content string) error {
|
|
p := filepath.Join(root, filename)
|
|
return os.WriteFile(p, []byte(content), 0644)
|
|
}
|
|
|
|
// ReadNomadCG2 reads an interface file under the nomad.slice parent cgroup
|
|
// (or whatever its name is configured to be)
|
|
func ReadNomadCG2(filename string) (string, error) {
|
|
p := filepath.Join(root, NomadCgroupParent, filename)
|
|
b, err := os.ReadFile(p)
|
|
return string(bytes.TrimSpace(b)), err
|
|
}
|
|
|
|
// ReadNomadCG1 reads an interface file under the /nomad cgroup of the given
|
|
// cgroup interface.
|
|
func ReadNomadCG1(iface, filename string) (string, error) {
|
|
p := filepath.Join(root, iface, NomadCgroupParent, filename)
|
|
b, err := os.ReadFile(p)
|
|
return string(bytes.TrimSpace(b)), err
|
|
}
|
|
|
|
func WriteNomadCG1(iface, filename, content string) error {
|
|
p := filepath.Join(root, iface, NomadCgroupParent, filename)
|
|
return os.WriteFile(p, []byte(content), 0644)
|
|
}
|
|
|
|
// LinuxResourcesPath returns the filepath to the directory that the field
|
|
// x.Resources.LinuxResources.CpusetCgroupPath is expected to hold on to
|
|
func LinuxResourcesPath(allocID, task string) string {
|
|
switch GetMode() {
|
|
case CG1:
|
|
return filepath.Join(root, "cpuset", NomadCgroupParent, scopeCG1(allocID, task))
|
|
default:
|
|
return filepath.Join(root, NomadCgroupParent, scopeCG2(allocID, task))
|
|
}
|
|
}
|