github.com/dmaizel/tests@v0.0.0-20210728163746-cae6a2d9cee8/integration/docker/mem_test.go (about) 1 // Copyright (c) 2018 Intel Corporation 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 5 package docker 6 7 import ( 8 "fmt" 9 "math" 10 "os" 11 "strconv" 12 "strings" 13 14 . "github.com/kata-containers/tests" 15 . "github.com/onsi/ginkgo" 16 . "github.com/onsi/ginkgo/extensions/table" 17 . "github.com/onsi/gomega" 18 ) 19 20 const ( 21 memLimitPath = "/sys/fs/cgroup/memory/memory.limit_in_bytes" 22 memSoftLimitPath = "/sys/fs/cgroup/memory/memory.soft_limit_in_bytes" 23 memSWLimitPath = "/sys/fs/cgroup/memory/memory.memsw.limit_in_bytes" 24 memSwappinessPath = "/sys/fs/cgroup/memory/memory.swappiness" 25 memKmemLimitPath = "/sys/fs/cgroup/memory/memory.kmem.limit_in_bytes" 26 memBlockSizePath = "/sys/devices/system/memory/block_size_bytes" 27 sysfsMemPath = "/sys/devices/system/memory/" 28 ) 29 30 func withDockerMemory(dockerMem int64) TableEntry { 31 msg := "hotplug memory when create containers should not fail" 32 return Entry(msg, dockerMem) 33 } 34 35 func withUpdateMemoryConstraints(dockerMem int64, updateMem int64, fail bool) TableEntry { 36 var msg string 37 38 if fail { 39 msg = "update memory constraints should fail" 40 } else { 41 msg = "update memory constraints should not fail" 42 } 43 44 return Entry(msg, dockerMem, updateMem, fail) 45 } 46 47 var _ = Describe("Hotplug memory when create containers", func() { 48 var ( 49 args []string 50 id string 51 defaultMemSz int64 52 memBlockSize int64 53 exitCode int 54 stdout string 55 err error 56 data string 57 memBlockNum int 58 ) 59 60 BeforeEach(func() { 61 id = randomDockerName() 62 defaultMemSz = int64(KataConfig.Hypervisor[KataHypervisor].DefaultMemSz) << 20 63 Expect(defaultMemSz).To(BeNumerically(">", int64(0))) 64 }) 65 66 AfterEach(func() { 67 Expect(ExistDockerContainer(id)).NotTo(BeTrue()) 68 }) 69 70 DescribeTable("Hotplug memory when create containers", 71 func(dockerMem int64) { 72 args = []string{"--name", id, "-tid", "--rm", "-m", fmt.Sprintf("%d", dockerMem), Image} 73 _, _, exitCode = dockerRun(args...) 74 Expect(exitCode).To(BeZero()) 75 76 stdout, _, exitCode = dockerExec(id, "cat", memBlockSizePath) 77 Expect(exitCode).To(BeZero()) 78 data = strings.Trim(stdout, "\n\t ") 79 memBlockSize, err = strconv.ParseInt(data, 16, 64) 80 Expect(err).ToNot(HaveOccurred()) 81 82 stdout, _, exitCode = dockerExec(id, "sh", "-c", fmt.Sprintf("find %v -name memory* | wc -l", sysfsMemPath)) 83 Expect(exitCode).To(BeZero()) 84 memBlockNum, err = strconv.Atoi(strings.Trim(stdout, "\n\t ")) 85 Expect(err).ToNot(HaveOccurred()) 86 memBlockNum-- 87 88 mem := int64(math.Ceil(float64(dockerMem)/float64(memBlockSize))) * memBlockSize 89 Expect(int64(memBlockNum) * memBlockSize).To(Equal(mem + defaultMemSz)) 90 91 Expect(RemoveDockerContainer(id)).To(BeTrue()) 92 }, 93 withDockerMemory(500*1024*1024), 94 withDockerMemory(640*1024*1024), 95 withDockerMemory(768*1024*1024), 96 withDockerMemory(1024*1024*1024), 97 ) 98 }) 99 100 var _ = Describe("memory constraints", func() { 101 var ( 102 args []string 103 id string 104 memSize string 105 kmemSize string 106 limSize string 107 stderr string 108 stdout string 109 exitCode int 110 memSwappiness string 111 useSwappiness bool 112 useSwap bool 113 useKmem bool 114 err error 115 defaultMemSz int 116 hotMemSz int 117 ) 118 119 BeforeEach(func() { 120 useSwappiness = true 121 useSwap = true 122 useKmem = true 123 if _, err = os.Stat(memSWLimitPath); err != nil { 124 useSwap = false 125 } 126 127 if _, err = os.Stat(memSwappinessPath); err != nil { 128 useSwappiness = false 129 } 130 131 if _, err = os.Stat(memKmemLimitPath); err != nil { 132 useKmem = false 133 } 134 135 id = randomDockerName() 136 137 defaultMemSz = int(KataConfig.Hypervisor[KataHypervisor].DefaultMemSz) 138 Expect(defaultMemSz).To(BeNumerically(">", 0)) 139 }) 140 141 AfterEach(func() { 142 Expect(ExistDockerContainer(id)).NotTo(BeTrue()) 143 }) 144 145 Context("run container exceeding memory constraints", func() { 146 It("should ran out of memory", func() { 147 hotMemSz = 256 148 memSize = fmt.Sprintf("%dMB", hotMemSz) 149 limSize = fmt.Sprintf("%dM", (hotMemSz*2)+defaultMemSz) 150 args = []string{"--name", id, "--rm", "-m", memSize, StressImage, "-mem-total", limSize, "-mem-alloc-size", limSize} 151 _, stderr, exitCode = dockerRun(args...) 152 Expect(exitCode).NotTo(Equal(0)) 153 Expect(stderr).To(ContainSubstring("fatal error: runtime: out of memory")) 154 }) 155 }) 156 157 Context("run container using memory constraints", func() { 158 It("should have applied the constraints", func() { 159 // 512MB 160 memSize = fmt.Sprintf("%d", 512*1024*1024) 161 // 10 MB 162 kmemSize = fmt.Sprintf("%d", 10*1024*1024) 163 memSwappiness = "60" 164 args = []string{"--name", id, "-dti", "--rm", "-m", memSize, "--memory-reservation", memSize} 165 166 if useSwap { 167 args = append(args, "--memory-swap", memSize) 168 } 169 170 if useSwappiness { 171 args = append(args, "--memory-swappiness", memSwappiness) 172 } 173 174 if useKmem { 175 args = append(args, "--kernel-memory", kmemSize) 176 } 177 178 args = append(args, Image) 179 180 _, _, exitCode = dockerRun(args...) 181 Expect(exitCode).To(BeZero()) 182 183 // check memory limit 184 stdout, _, exitCode = dockerExec(id, "cat", memLimitPath) 185 Expect(exitCode).To(BeZero()) 186 Expect(memSize).To(Equal(strings.Trim(stdout, " \n\t"))) 187 188 // check memory soft limit 189 stdout, _, exitCode = dockerExec(id, "cat", memSoftLimitPath) 190 Expect(exitCode).To(BeZero()) 191 Expect(memSize).To(Equal(strings.Trim(stdout, " \n\t"))) 192 193 // check memory swap limit 194 if useSwap { 195 stdout, _, exitCode = dockerExec(id, "cat", memSWLimitPath) 196 Expect(exitCode).To(BeZero()) 197 Expect(memSize).To(Equal(strings.Trim(stdout, " \n\t"))) 198 } 199 200 // check memory swappiness 201 if useSwappiness { 202 stdout, _, exitCode = dockerExec(id, "cat", memSwappinessPath) 203 Expect(exitCode).To(BeZero()) 204 Expect(memSwappiness).To(Equal(strings.Trim(stdout, " \n\t"))) 205 } 206 207 // check kernel memory 208 if useKmem { 209 stdout, _, exitCode = dockerExec(id, "cat", memKmemLimitPath) 210 Expect(exitCode).To(BeZero()) 211 Expect(kmemSize).To(Equal(strings.Trim(stdout, " \n\t"))) 212 } 213 214 Expect(RemoveDockerContainer(id)).To(BeTrue()) 215 }) 216 }) 217 }) 218 219 var _ = Describe("run container and update its memory constraints", func() { 220 var ( 221 args []string 222 id string 223 memSize string 224 stdout string 225 exitCode int 226 useSwap bool 227 err error 228 ) 229 230 BeforeEach(func() { 231 useSwap = true 232 if _, err = os.Stat(memSWLimitPath); err != nil { 233 useSwap = false 234 } 235 236 id = randomDockerName() 237 }) 238 239 AfterEach(func() { 240 Expect(ExistDockerContainer(id)).NotTo(BeTrue()) 241 }) 242 243 DescribeTable("should have applied the memory constraints", 244 func(dockerMem int64, updateMem int64, fail bool) { 245 memSize = fmt.Sprintf("%d", dockerMem) 246 args = []string{"--name", id, "-dti", "--rm", "-m", memSize, Image} 247 248 _, _, exitCode = dockerRun(args...) 249 Expect(exitCode).To(BeZero()) 250 251 memSize = fmt.Sprintf("%d", updateMem) 252 args = []string{"--memory", memSize, "--memory-reservation", memSize} 253 if useSwap { 254 args = append(args, "--memory-swap", memSize) 255 } 256 257 args = append(args, id) 258 259 // update memory constraints 260 _, _, exitCode = dockerUpdate(args...) 261 Expect(exitCode).To(BeZero()) 262 263 // check memory limit 264 stdout, _, exitCode = dockerExec(id, "cat", memLimitPath) 265 Expect(exitCode).To(BeZero()) 266 if fail { 267 Expect(memSize).ToNot(Equal(strings.Trim(stdout, " \n\t"))) 268 } else { 269 Expect(memSize).To(Equal(strings.Trim(stdout, " \n\t"))) 270 } 271 272 // check memory soft limit 273 stdout, _, exitCode = dockerExec(id, "cat", memSoftLimitPath) 274 Expect(exitCode).To(BeZero()) 275 if fail { 276 Expect(memSize).ToNot(Equal(strings.Trim(stdout, " \n\t"))) 277 } else { 278 Expect(memSize).To(Equal(strings.Trim(stdout, " \n\t"))) 279 } 280 281 if useSwap { 282 // check memory swap limit 283 stdout, _, exitCode = dockerExec(id, "cat", memSWLimitPath) 284 Expect(exitCode).To(BeZero()) 285 if fail { 286 Expect(memSize).ToNot(Equal(strings.Trim(stdout, " \n\t"))) 287 } else { 288 Expect(memSize).To(Equal(strings.Trim(stdout, " \n\t"))) 289 } 290 } 291 292 Expect(RemoveDockerContainer(id)).To(BeTrue()) 293 }, 294 withUpdateMemoryConstraints(500*1024*1024, 400*1024*1024, shouldNotFail), 295 withUpdateMemoryConstraints(500*1024*1024, 500*1024*1024, shouldNotFail), 296 withUpdateMemoryConstraints(500*1024*1024, 600*1024*1024, shouldNotFail), 297 withUpdateMemoryConstraints(500*1024*1024, 500*1024*1024+1, shouldFail), 298 withUpdateMemoryConstraints(500*1024*1024, 500*1024*1024+4096, shouldNotFail), 299 ) 300 })