github.com/cloudfoundry-attic/garden-linux@v0.333.2-candidate/linux_container/cgroups_manager/container_cgroups_manager_test.go (about)

     1  package cgroups_manager_test
     2  
     3  import (
     4  	"errors"
     5  	"io/ioutil"
     6  	"os"
     7  	"path"
     8  	"strings"
     9  
    10  	. "github.com/onsi/ginkgo"
    11  	. "github.com/onsi/gomega"
    12  
    13  	"github.com/cloudfoundry-incubator/garden-linux/linux_container/cgroups_manager"
    14  	"github.com/cloudfoundry-incubator/garden-linux/linux_container/cgroups_manager/fake_cgroup_reader"
    15  )
    16  
    17  var _ = Describe("Container cgroups", func() {
    18  	var (
    19  		cgroupsPath    string
    20  		cgroupsManager *cgroups_manager.ContainerCgroupsManager
    21  		cgroupReader   *fake_cgroup_reader.FakeCgroupReader
    22  	)
    23  
    24  	BeforeEach(func() {
    25  		cgroupReader = new(fake_cgroup_reader.FakeCgroupReader)
    26  		tmpdir, err := ioutil.TempDir(os.TempDir(), "some-cgroups")
    27  		Expect(err).ToNot(HaveOccurred())
    28  
    29  		cgroupsPath = tmpdir
    30  
    31  		cgroupsManager = cgroups_manager.New(cgroupsPath, "some-container-id", cgroupReader)
    32  	})
    33  
    34  	Describe("setup cgroups", func() {
    35  		It("creates a cgroups directory for each subsystem", func() {
    36  			err := cgroupsManager.Setup("memory", "cpu")
    37  			Expect(err).ToNot(HaveOccurred())
    38  
    39  			Expect(path.Join(cgroupsPath, "memory", "instance-some-container-id")).To(BeADirectory())
    40  			Expect(path.Join(cgroupsPath, "cpu", "instance-some-container-id")).To(BeADirectory())
    41  		})
    42  
    43  		Context("when the subsystems contain cpuset", func() {
    44  			It("initializes the cpuset.cpus and cpuset.mems based on the system cgroup", func() {
    45  				Expect(os.MkdirAll(path.Join(cgroupsPath, "cpuset"), 0755)).To(Succeed())
    46  
    47  				Expect(ioutil.WriteFile(path.Join(cgroupsPath, "cpuset", "cpuset.cpus"), []byte("the cpuset cpus"), 0600)).To(Succeed())
    48  				Expect(ioutil.WriteFile(path.Join(cgroupsPath, "cpuset", "cpuset.mems"), []byte("the cpuset mems"), 0600)).To(Succeed())
    49  
    50  				err := cgroupsManager.Setup("memory", "cpu", "cpuset")
    51  				Expect(err).ToNot(HaveOccurred())
    52  
    53  				Expect(ioutil.ReadFile(path.Join(
    54  					cgroupsPath,
    55  					"cpuset",
    56  					"instance-some-container-id",
    57  					"cpuset.cpus"))).
    58  					To(Equal([]byte("the cpuset cpus")))
    59  
    60  				Expect(ioutil.ReadFile(path.Join(
    61  					cgroupsPath,
    62  					"cpuset",
    63  					"instance-some-container-id",
    64  					"cpuset.mems"))).
    65  					To(Equal([]byte("the cpuset mems")))
    66  			})
    67  		})
    68  	})
    69  
    70  	Describe("adding a process", func() {
    71  		It("writes the process to the tasks file", func() {
    72  			containerMemoryCgroupsPath := path.Join(cgroupsPath, "memory", "instance-some-container-id")
    73  			err := os.MkdirAll(containerMemoryCgroupsPath, 0755)
    74  			Expect(err).ToNot(HaveOccurred())
    75  
    76  			err = cgroupsManager.Add(1235, "memory")
    77  			Expect(err).ToNot(HaveOccurred())
    78  
    79  			err = cgroupsManager.Add(1237, "memory")
    80  			Expect(err).ToNot(HaveOccurred())
    81  
    82  			value, err := ioutil.ReadFile(path.Join(containerMemoryCgroupsPath, "tasks"))
    83  			Expect(err).ToNot(HaveOccurred())
    84  			Expect(strings.Split(string(value), "\n")).To(ContainElement("1235"))
    85  			Expect(strings.Split(string(value), "\n")).To(ContainElement("1237"))
    86  		})
    87  
    88  		Context("when multiple subsystem are provided", func() {
    89  			It("writes the process to task file for each subsystem", func() {
    90  				containerMemoryCgroupsPath := path.Join(cgroupsPath, "memory", "instance-some-container-id")
    91  				err := os.MkdirAll(containerMemoryCgroupsPath, 0755)
    92  				Expect(err).ToNot(HaveOccurred())
    93  
    94  				containerCpuCgroupsPath := path.Join(cgroupsPath, "cpu", "instance-some-container-id")
    95  				err = os.MkdirAll(containerCpuCgroupsPath, 0755)
    96  				Expect(err).ToNot(HaveOccurred())
    97  
    98  				err = cgroupsManager.Add(1235, "memory", "cpu")
    99  				Expect(err).ToNot(HaveOccurred())
   100  
   101  				value, err := ioutil.ReadFile(path.Join(containerMemoryCgroupsPath, "tasks"))
   102  				Expect(err).ToNot(HaveOccurred())
   103  				Expect(strings.Split(string(value), "\n")).To(ContainElement("1235"))
   104  
   105  				value, err = ioutil.ReadFile(path.Join(containerCpuCgroupsPath, "tasks"))
   106  				Expect(err).ToNot(HaveOccurred())
   107  				Expect(strings.Split(string(value), "\n")).To(ContainElement("1235"))
   108  			})
   109  		})
   110  	})
   111  
   112  	Describe("setting", func() {
   113  		It("writes the value to the name under the subsytem", func() {
   114  			cgroupReader.CgroupNodeReturns("/somenestedpath3/somenestedpath4", nil)
   115  			containerMemoryCgroupsPath := path.Join(cgroupsPath, "memory", "somenestedpath3", "somenestedpath4", "instance-some-container-id")
   116  			err := os.MkdirAll(containerMemoryCgroupsPath, 0755)
   117  			Expect(err).ToNot(HaveOccurred())
   118  
   119  			err = cgroupsManager.Set("memory", "memory.limit_in_bytes", "42")
   120  			Expect(err).ToNot(HaveOccurred())
   121  
   122  			value, err := ioutil.ReadFile(path.Join(containerMemoryCgroupsPath, "memory.limit_in_bytes"))
   123  			Expect(err).ToNot(HaveOccurred())
   124  			Expect(string(value)).To(Equal("42"))
   125  
   126  			Expect(cgroupReader.CgroupNodeArgsForCall(0)).To(Equal("memory"))
   127  		})
   128  
   129  		Context("when the cgroups directory does not exist", func() {
   130  			BeforeEach(func() {
   131  				err := os.RemoveAll(cgroupsPath)
   132  				Expect(err).ToNot(HaveOccurred())
   133  			})
   134  
   135  			It("returns an error", func() {
   136  				err := cgroupsManager.Set("memory", "memory.limit_in_bytes", "42")
   137  				Expect(err).To(HaveOccurred())
   138  			})
   139  		})
   140  
   141  		Context("when the cgroup node is not found", func() {
   142  			It("returns an error", func() {
   143  				cgroupReader.CgroupNodeReturns("", errors.New("banana"))
   144  
   145  				err := cgroupsManager.Set("memory", "memory.limit_in_bytes", "42")
   146  				Expect(err).To(MatchError(ContainSubstring("banana")))
   147  			})
   148  		})
   149  	})
   150  
   151  	Describe("getting", func() {
   152  		It("reads the current value from the name under the subsystem", func() {
   153  			cgroupReader.CgroupNodeReturns("/somenestedpath/somenestedpath2", nil)
   154  			containerMemoryCgroupsPath := path.Join(cgroupsPath, "memory", "somenestedpath", "somenestedpath2", "instance-some-container-id")
   155  
   156  			err := os.MkdirAll(containerMemoryCgroupsPath, 0755)
   157  			Expect(err).ToNot(HaveOccurred())
   158  
   159  			err = ioutil.WriteFile(path.Join(containerMemoryCgroupsPath, "memory.limit_in_bytes"), []byte("123\n"), 0644)
   160  			Expect(err).ToNot(HaveOccurred())
   161  
   162  			val, err := cgroupsManager.Get("memory", "memory.limit_in_bytes")
   163  			Expect(err).ToNot(HaveOccurred())
   164  			Expect(val).To(Equal("123"))
   165  
   166  			Expect(cgroupReader.CgroupNodeArgsForCall(0)).To(Equal("memory"))
   167  		})
   168  
   169  		Context("when the cgroup node is not found", func() {
   170  			It("returns an error", func() {
   171  				cgroupReader.CgroupNodeReturns("", errors.New("pineapple"))
   172  
   173  				_, err := cgroupsManager.Get("memory", "memory.limit_in_bytes")
   174  				Expect(err).To(MatchError(ContainSubstring("pineapple")))
   175  			})
   176  		})
   177  	})
   178  
   179  	Describe("retrieving a subsystem path", func() {
   180  		It("returns <path>/<subsytem>/instance-<container-id>", func() {
   181  			Expect(cgroupsManager.SubsystemPath("memory")).To(Equal(
   182  				path.Join(cgroupsPath, "memory", "instance-some-container-id"),
   183  			))
   184  		})
   185  
   186  		Context("when there is an error reading cgroup node path", func() {
   187  
   188  			It("returns an error", func() {
   189  				cgroupReader.CgroupNodeReturns("", errors.New("o no!"))
   190  				_, err := cgroupsManager.SubsystemPath("memory")
   191  				Expect(err).To(MatchError("o no!"))
   192  			})
   193  		})
   194  	})
   195  })