github.com/cloud-foundations/dominator@v0.0.0-20221004181915-6e4fee580046/hypervisor/manager/memory.go (about) 1 package manager 2 3 import ( 4 "errors" 5 "os" 6 "os/exec" 7 "strconv" 8 9 "github.com/Cloud-Foundations/Dominator/lib/meminfo" 10 ) 11 12 var ( 13 errorInsufficientAvailableMemory = errors.New( 14 "insufficient available memory") 15 errorInsufficientUnallocatedMemory = errors.New( 16 "insufficient unallocated memory") 17 errorUnableToAllocatedMemory = errors.New("unable to allocate memory") 18 ) 19 20 func checkAvailableMemory(memoryInMiB uint64) error { 21 if memInfo, err := meminfo.GetMemInfo(); err != nil { 22 return err 23 } else { 24 if memoryInMiB >= memInfo.Available>>20 { 25 return errorInsufficientAvailableMemory 26 } 27 return nil 28 } 29 } 30 31 func tryAllocateMemory(memoryInMiB uint64) <-chan error { 32 channel := make(chan error, 1) 33 executable, err := os.Executable() 34 if err != nil { 35 channel <- err 36 return channel 37 } 38 cmd := exec.Command(executable, "-testMemoryAvailable", 39 strconv.FormatUint(memoryInMiB, 10)) 40 go func() { 41 if err := cmd.Run(); err != nil { 42 if _, ok := err.(*exec.ExitError); ok { 43 channel <- errorUnableToAllocatedMemory 44 } else { 45 channel <- err 46 } 47 } else { 48 channel <- nil 49 } 50 }() 51 return channel 52 } 53 54 func (m *Manager) getUnallocatedMemoryInMiB() uint64 { 55 m.mutex.RLock() 56 defer m.mutex.RUnlock() 57 return m.getUnallocatedMemoryInMiBWithLock() 58 } 59 60 func (m *Manager) getUnallocatedMemoryInMiBWithLock() uint64 { 61 unallocated := int64(m.memTotalInMiB) 62 for _, vm := range m.vms { 63 unallocated -= int64(vm.MemoryInMiB) 64 } 65 if unallocated < 0 { 66 return 0 67 } 68 return uint64(unallocated) 69 } 70 71 func (m *Manager) checkSufficientMemoryWithLock(memoryInMiB uint64) error { 72 if memoryInMiB > m.getUnallocatedMemoryInMiBWithLock() { 73 return errorInsufficientUnallocatedMemory 74 } 75 return checkAvailableMemory(memoryInMiB) 76 }