github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/client/lib/cgutil/cpuset_manager_v2_test.go (about) 1 //go:build linux 2 3 package cgutil 4 5 import ( 6 "path/filepath" 7 "strings" 8 "testing" 9 10 "github.com/hashicorp/nomad/client/testutil" 11 "github.com/hashicorp/nomad/helper/testlog" 12 "github.com/hashicorp/nomad/helper/uuid" 13 "github.com/hashicorp/nomad/lib/cpuset" 14 "github.com/hashicorp/nomad/nomad/mock" 15 "github.com/opencontainers/runc/libcontainer/cgroups" 16 "github.com/stretchr/testify/require" 17 ) 18 19 // Note: these tests need to run on GitHub Actions runners with only 2 cores. 20 // It is not possible to write more cores to a cpuset than are actually available, 21 // so make sure tests account for that by setting systemCores as the full set of 22 // usable cores. 23 var systemCores = []uint16{0, 1} 24 25 func TestCpusetManager_V2_AddAlloc(t *testing.T) { 26 testutil.CgroupsCompatibleV2(t) 27 testutil.MinimumCores(t, 2) 28 29 logger := testlog.HCLogger(t) 30 parent := uuid.Short() + ".scope" 31 create(t, parent) 32 cleanup(t, parent) 33 34 // setup the cpuset manager 35 manager := NewCpusetManagerV2(parent, systemCores, logger) 36 manager.Init() 37 38 // add our first alloc, isolating 1 core 39 t.Run("first", func(t *testing.T) { 40 alloc := mock.Alloc() 41 alloc.AllocatedResources.Tasks["web"].Cpu.ReservedCores = cpuset.New(0).ToSlice() 42 manager.AddAlloc(alloc) 43 cpusetIs(t, "0-1", parent, alloc.ID, "web") 44 }) 45 46 // add second alloc, isolating 1 core 47 t.Run("second", func(t *testing.T) { 48 alloc := mock.Alloc() 49 alloc.AllocatedResources.Tasks["web"].Cpu.ReservedCores = cpuset.New(1).ToSlice() 50 manager.AddAlloc(alloc) 51 cpusetIs(t, "1", parent, alloc.ID, "web") 52 }) 53 54 // note that the scheduler, not the cpuset manager, is what prevents over-subscription 55 // and as such no logic exists here to prevent that 56 } 57 58 func cpusetIs(t *testing.T, exp, parent, allocID, task string) { 59 scope := makeScope(makeID(allocID, task)) 60 value, err := cgroups.ReadFile(filepath.Join(CgroupRoot, parent, scope), "cpuset.cpus") 61 require.NoError(t, err) 62 require.Equal(t, exp, strings.TrimSpace(value)) 63 } 64 65 func TestCpusetManager_V2_RemoveAlloc(t *testing.T) { 66 testutil.CgroupsCompatibleV2(t) 67 testutil.MinimumCores(t, 2) 68 69 logger := testlog.HCLogger(t) 70 parent := uuid.Short() + ".scope" 71 create(t, parent) 72 cleanup(t, parent) 73 74 // setup the cpuset manager 75 manager := NewCpusetManagerV2(parent, systemCores, logger) 76 manager.Init() 77 78 // alloc1 gets core 0 79 alloc1 := mock.Alloc() 80 alloc1.AllocatedResources.Tasks["web"].Cpu.ReservedCores = cpuset.New(0).ToSlice() 81 manager.AddAlloc(alloc1) 82 83 // alloc2 gets core 1 84 alloc2 := mock.Alloc() 85 alloc2.AllocatedResources.Tasks["web"].Cpu.ReservedCores = cpuset.New(1).ToSlice() 86 manager.AddAlloc(alloc2) 87 cpusetIs(t, "1", parent, alloc2.ID, "web") 88 89 // with alloc1 gone, alloc2 gets the now shared core 90 manager.RemoveAlloc(alloc1.ID) 91 cpusetIs(t, "0-1", parent, alloc2.ID, "web") 92 }