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  })