mirror of
https://github.com/kemko/nomad.git
synced 2026-01-01 16:05:42 +03:00
88 lines
2.0 KiB
Go
88 lines
2.0 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
package docker
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
"github.com/hashicorp/nomad/client/lib/cgroupslib"
|
|
"github.com/hashicorp/nomad/helper"
|
|
)
|
|
|
|
const (
|
|
// cpusetSyncPeriod is how often we check to see if the cpuset of a task
|
|
// needs to be updated - if there is no work to do, no action is taken
|
|
cpusetSyncPeriod = 3 * time.Second
|
|
)
|
|
|
|
// cpuset is used to manage the cpuset.cpus interface file in the cgroup that
|
|
// docker daemon creates for the container being run by the task driver. we
|
|
// must do this hack because docker does not allow specifying a pre-existing
|
|
// cgroup in which to run the container (i.e. one that we control).
|
|
type cpuset struct {
|
|
doneCh <-chan bool
|
|
source string
|
|
destination string
|
|
previous string
|
|
sync func(string, string)
|
|
}
|
|
|
|
func (c *cpuset) watch() {
|
|
if c.sync == nil {
|
|
// use the real thing if we are not doing tests
|
|
c.sync = c.copyCpuset
|
|
}
|
|
|
|
ticks, cancel := helper.NewSafeTimer(cpusetSyncPeriod)
|
|
defer cancel()
|
|
|
|
for {
|
|
select {
|
|
case <-c.doneCh:
|
|
return
|
|
case <-ticks.C:
|
|
c.sync(c.source, c.destination)
|
|
ticks.Reset(cpusetSyncPeriod)
|
|
}
|
|
}
|
|
}
|
|
|
|
func effectiveCpusetFile() string {
|
|
switch cgroupslib.GetMode() {
|
|
case cgroupslib.CG1:
|
|
return "cpuset.effective_cpus"
|
|
default:
|
|
return "cpuset.cpus.effective"
|
|
}
|
|
}
|
|
|
|
func (c *cpuset) copyCpuset(source, destination string) {
|
|
source = filepath.Join(source, effectiveCpusetFile())
|
|
destination = filepath.Join(destination, "cpuset.cpus")
|
|
|
|
// read the current value of usable cores
|
|
b, err := os.ReadFile(source)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
// if the current value is the same as the value we wrote last,
|
|
// there is nothing to do
|
|
current := string(b)
|
|
if current == c.previous {
|
|
return
|
|
}
|
|
|
|
// otherwise write the new value
|
|
err = os.WriteFile(destination, b, 0o644)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
// we wrote a new value; store that value so we do not write it again
|
|
c.previous = current
|
|
}
|