balena-supervisor/gosuper/psutils/psutils.go

95 lines
2.9 KiB
Go

package psutils
import (
"bufio"
"fmt"
"os"
"path"
"regexp"
"strconv"
"resin-supervisor/gosuper/Godeps/_workspace/src/github.com/samalba/dockerclient"
"resin-supervisor/gosuper/Godeps/_workspace/src/github.com/shirou/gopsutil/process"
)
//AdjustOOMPriorityByName Adjust the OOM adj value for the process' with the given name regexp
func AdjustOOMPriorityByName(procPath string, processName string, value int64, ignoreIfNonZero bool) error {
runningProcess, err := process.Pids()
if err != nil {
return err
}
var processMatch = regexp.MustCompile(processName)
processFound := false
for _, pid := range runningProcess {
// Find the process with the given name
pidProcess, _ := process.NewProcess(pid)
pidName, _ := pidProcess.Name()
if processMatch.MatchString(pidName) {
processFound = true
err := AdjustOOMPriority(procPath, int64(pid), value, ignoreIfNonZero)
if err != nil {
return err
}
}
}
if processFound {
return nil
}
return fmt.Errorf("No process matches: %s\n", processName)
}
//AdjustOOMPriority Adjust the OOM adj value for the process with the given pid.
func AdjustOOMPriority(procPath string, pid int64, value int64, ignoreIfNonZero bool) error {
// Open the oom_score_adj file for the pid
oomAdjFile, err := os.OpenFile(path.Clean(procPath)+"/"+strconv.FormatInt(pid, 10)+"/oom_score_adj", os.O_RDWR, os.ModeType)
if err != nil {
return fmt.Errorf("Unable to open OOM adjust proc file for pid: %d\n", pid)
}
defer oomAdjFile.Close()
// Read the oom_score_adj value currently set
scanner := bufio.NewScanner(oomAdjFile)
scanner.Split(bufio.ScanLines)
var currentOOMString string
for scanner.Scan() {
currentOOMString = scanner.Text() // Read the OOMString
}
currentOOMValue, err := strconv.ParseInt(currentOOMString, 10, 64)
if err != nil {
return fmt.Errorf("Unable to read OOM adjust for pid: %d\n", pid)
}
if ignoreIfNonZero && currentOOMValue != 0 {
return nil
}
// Write to the procfile to adjust the OOM adj value.
_, err = oomAdjFile.WriteString(strconv.FormatInt(value, 10))
if err != nil {
return fmt.Errorf("Unable to OOM adjust for pid: %d\n", pid)
}
return nil
}
//AdjustDockerOOMPriority Adjusts the OOM Adj value for the entire docker container specified by the name. This should point to root proc filesystem
func AdjustDockerOOMPriority(procPath string, connection string, containerName string, value int64, ignoreIfNonZero bool) error {
// Connect to the docker host with the connection string
docker, err := dockerclient.NewDockerClient(connection, nil)
if err != nil {
return err
}
// Get the running containers
containers, err := docker.ListContainers(false, false, "")
if err != nil {
return err
}
for _, container := range containers {
containerInfo, err := docker.InspectContainer(container.Id)
if err != nil {
return err
}
err = AdjustOOMPriority(procPath, int64(containerInfo.State.Pid), value, ignoreIfNonZero)
if err != nil {
return err
}
}
return nil
}