github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/e2e/oversubscription/oversubscription.go (about) 1 package oversubscription 2 3 import ( 4 "fmt" 5 "strings" 6 "time" 7 8 "github.com/hashicorp/nomad/api" 9 "github.com/hashicorp/nomad/e2e/e2eutil" 10 "github.com/hashicorp/nomad/e2e/framework" 11 "github.com/hashicorp/nomad/helper/uuid" 12 ) 13 14 type OversubscriptionTest struct { 15 framework.TC 16 jobIDs []string 17 initialSchedulerConfig *api.SchedulerConfiguration 18 } 19 20 func init() { 21 framework.AddSuites(&framework.TestSuite{ 22 Component: "oversubscription", 23 CanRunLocal: true, 24 Cases: []framework.TestCase{ 25 new(OversubscriptionTest), 26 }, 27 }) 28 } 29 30 func (tc *OversubscriptionTest) BeforeAll(f *framework.F) { 31 // Ensure cluster has leader before running tests 32 e2eutil.WaitForLeader(f.T(), tc.Nomad()) 33 e2eutil.WaitForNodesReady(f.T(), tc.Nomad(), 1) 34 35 tc.enableMemoryOversubscription(f) 36 } 37 38 func (tc *OversubscriptionTest) AfterAll(f *framework.F) { 39 tc.restoreSchedulerConfig(f) 40 } 41 42 func (tc *OversubscriptionTest) enableMemoryOversubscription(f *framework.F) { 43 resp, _, err := tc.Nomad().Operator().SchedulerGetConfiguration(nil) 44 f.NoError(err) 45 46 tc.initialSchedulerConfig = resp.SchedulerConfig 47 48 conf := *resp.SchedulerConfig 49 conf.MemoryOversubscriptionEnabled = true 50 _, _, err = tc.Nomad().Operator().SchedulerSetConfiguration(&conf, nil) 51 f.NoError(err) 52 } 53 54 func (tc *OversubscriptionTest) restoreSchedulerConfig(f *framework.F) { 55 if tc.initialSchedulerConfig != nil { 56 _, _, err := tc.Nomad().Operator().SchedulerSetConfiguration(tc.initialSchedulerConfig, nil) 57 f.NoError(err) 58 } 59 } 60 61 func (tc *OversubscriptionTest) AfterEach(f *framework.F) { 62 nomadClient := tc.Nomad() 63 j := nomadClient.Jobs() 64 65 for _, id := range tc.jobIDs { 66 j.Deregister(id, true, nil) 67 } 68 tc.Nomad().System().GarbageCollect() 69 } 70 71 func (tc *OversubscriptionTest) TestDocker(f *framework.F) { 72 alloc := tc.runTest(f, "oversubscription-docker-", "docker.nomad") 73 74 // check that cgroup reports the memoryMaxMB as the limit within he container 75 stdout, err := e2eutil.AllocLogs(alloc.ID, e2eutil.LogsStdOut) 76 f.NoError(err) 77 f.Equal(fmt.Sprintf("%d\n", 30*1024*1024), stdout) 78 } 79 80 func (tc *OversubscriptionTest) TestExec(f *framework.F) { 81 alloc := tc.runTest(f, "oversubscription-exec-", "exec.nomad") 82 83 // check the the cgroup is configured with the memoryMaxMB 84 var err error 85 expected := fmt.Sprintf("%d\n", 30*1024*1024) 86 e2eutil.WaitForAllocFile(alloc.ID, "/alloc/tmp/memory.limit_in_bytes", func(s string) bool { 87 if s != expected { 88 err = fmt.Errorf("expected %v got %v", expected, s) 89 return false 90 } 91 err = nil 92 return true 93 }, nil) 94 f.NoError(err) 95 } 96 97 func (tc *OversubscriptionTest) runTest(f *framework.F, jobPrefix, jobfile string) *api.Allocation { 98 // register a job 99 jobID := jobPrefix + uuid.Generate()[:8] 100 tc.jobIDs = append(tc.jobIDs, jobID) 101 102 allocs := e2eutil.RegisterAndWaitForAllocs(f.T(), tc.Nomad(), "oversubscription/testdata/"+jobfile, jobID, "") 103 f.Len(allocs, 1) 104 105 e2eutil.WaitForAllocRunning(f.T(), tc.Nomad(), allocs[0].ID) 106 107 alloc, _, err := tc.Nomad().Allocations().Info(allocs[0].ID, nil) 108 f.NoError(err) 109 110 // assert the resources info 111 resources := alloc.AllocatedResources.Tasks["task"] 112 f.Equal(int64(20), resources.Memory.MemoryMB) 113 f.Equal(int64(30), resources.Memory.MemoryMaxMB) 114 115 // assert the status API reports memory, we need to wait for the 116 // for metrics to be written before we can assert the entire 117 // command line 118 var allocInfo string 119 f.Eventually(func() bool { 120 allocInfo, err = e2eutil.Command("nomad", "alloc", "status", alloc.ID) 121 if err != nil { 122 return false 123 } 124 return strings.Contains(allocInfo, "/20 MiB") && // memory reserve 125 strings.Contains(allocInfo, "Max: 30 MiB") // memory max 126 }, 10*time.Second, 200*time.Millisecond, "unexpected memory output") 127 128 return alloc 129 }