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