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