diff options
author | Fabricio Voznika <fvoznika@google.com> | 2018-10-11 11:56:42 -0700 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2018-10-11 11:58:15 -0700 |
commit | d40d80106988e9302aaa354d4f58caa6c31429b4 (patch) | |
tree | 8542738ab1a4c879b431dd5966f3d9940c650ecc | |
parent | f413e4b11794cd71cc3b2b64c8f6861f5394a3f1 (diff) |
Sandbox cgroup tests
Verify that cgroup is being properly set.
PiperOrigin-RevId: 216736137
Change-Id: I0e27fd604eca67e7dd2e3548dc372ca9cc416309
-rw-r--r-- | runsc/cgroup/cgroup.go | 2 | ||||
-rw-r--r-- | runsc/test/integration/integration_test.go | 32 | ||||
-rw-r--r-- | runsc/test/root/BUILD | 5 | ||||
-rw-r--r-- | runsc/test/root/cgroup_test.go | 140 | ||||
-rw-r--r-- | runsc/test/testutil/docker.go | 9 |
5 files changed, 155 insertions, 33 deletions
diff --git a/runsc/cgroup/cgroup.go b/runsc/cgroup/cgroup.go index 6a0092be8..af0252bb3 100644 --- a/runsc/cgroup/cgroup.go +++ b/runsc/cgroup/cgroup.go @@ -123,6 +123,8 @@ func fillFromAncestor(path string) (string, error) { return val, nil } +// countCpuset returns the number of CPU in a string formatted like: +// "0-2,7,12-14 # bits 0, 1, 2, 7, 12, 13, and 14 set" - man 7 cpuset func countCpuset(cpuset string) (int, error) { var count int for _, p := range strings.Split(cpuset, ",") { diff --git a/runsc/test/integration/integration_test.go b/runsc/test/integration/integration_test.go index 5480c5bbe..e93171b8a 100644 --- a/runsc/test/integration/integration_test.go +++ b/runsc/test/integration/integration_test.go @@ -231,38 +231,6 @@ func TestNumCPU(t *testing.T) { } } -// TestCgroup sets cgroup options and checks that container can start. -// TODO: Verify that these were set to cgroup on the host. -func TestCgroup(t *testing.T) { - if err := testutil.Pull("alpine"); err != nil { - t.Fatal("docker pull failed:", err) - } - d := testutil.MakeDocker("cgroup-test") - - var args []string - args = append(args, "--cpu-shares=1000") - args = append(args, "--cpu-period=2000") - args = append(args, "--cpu-quota=3000") - args = append(args, "--cpuset-cpus=0") - args = append(args, "--cpuset-mems=0") - args = append(args, "--kernel-memory=100MB") - args = append(args, "--memory=1GB") - args = append(args, "--memory-reservation=500MB") - args = append(args, "--memory-swap=2GB") - args = append(args, "--memory-swappiness=5") - args = append(args, "--blkio-weight=750") - - args = append(args, "hello-world") - if err := d.Run(args...); err != nil { - t.Fatal("docker create failed:", err) - } - defer d.CleanUp() - - if _, err := d.WaitForOutput("Hello from Docker!", 5*time.Second); err != nil { - t.Fatalf("docker didn't say hello: %v", err) - } -} - func TestMain(m *testing.M) { testutil.EnsureSupportedDockerVersion() os.Exit(m.Run()) diff --git a/runsc/test/root/BUILD b/runsc/test/root/BUILD index dbc0f1d26..c69249b52 100644 --- a/runsc/test/root/BUILD +++ b/runsc/test/root/BUILD @@ -11,7 +11,10 @@ go_library( go_test( name = "root_test", size = "small", - srcs = ["chroot_test.go"], + srcs = [ + "cgroup_test.go", + "chroot_test.go", + ], embed = [":root"], tags = [ # Requires docker and runsc to be configured before the test runs. diff --git a/runsc/test/root/cgroup_test.go b/runsc/test/root/cgroup_test.go new file mode 100644 index 000000000..5cb4b794f --- /dev/null +++ b/runsc/test/root/cgroup_test.go @@ -0,0 +1,140 @@ +// Copyright 2018 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package root + +import ( + "io/ioutil" + "os" + "path/filepath" + "strings" + "testing" + + "gvisor.googlesource.com/gvisor/runsc/test/testutil" +) + +// TestCgroup sets cgroup options and checks that cgroup was properly configured. +func TestCgroup(t *testing.T) { + if err := testutil.Pull("alpine"); err != nil { + t.Fatal("docker pull failed:", err) + } + d := testutil.MakeDocker("cgroup-test") + + attrs := []struct { + arg string + ctrl string + file string + want string + skipIfNotFound bool + }{ + { + arg: "--cpu-shares=1000", + ctrl: "cpu", + file: "cpu.shares", + want: "1000", + }, + { + arg: "--cpu-period=2000", + ctrl: "cpu", + file: "cpu.cfs_period_us", + want: "2000", + }, + { + arg: "--cpu-quota=3000", + ctrl: "cpu", + file: "cpu.cfs_quota_us", + want: "3000", + }, + { + arg: "--cpuset-cpus=0", + ctrl: "cpuset", + file: "cpuset.cpus", + want: "0", + }, + { + arg: "--cpuset-mems=0", + ctrl: "cpuset", + file: "cpuset.mems", + want: "0", + }, + { + arg: "--kernel-memory=100MB", + ctrl: "memory", + file: "memory.kmem.limit_in_bytes", + want: "104857600", + }, + { + arg: "--memory=1GB", + ctrl: "memory", + file: "memory.limit_in_bytes", + want: "1073741824", + }, + { + arg: "--memory-reservation=500MB", + ctrl: "memory", + file: "memory.soft_limit_in_bytes", + want: "524288000", + }, + { + arg: "--memory-swap=2GB", + ctrl: "memory", + file: "memory.memsw.limit_in_bytes", + want: "2147483648", + skipIfNotFound: true, // swap may be disabled on the machine. + }, + { + arg: "--memory-swappiness=5", + ctrl: "memory", + file: "memory.swappiness", + want: "5", + }, + { + arg: "--blkio-weight=750", + ctrl: "blkio", + file: "blkio.weight", + want: "750", + }, + } + + args := make([]string, 0, len(attrs)) + for _, attr := range attrs { + args = append(args, attr.arg) + } + + args = append(args, "alpine", "sleep", "10000") + if err := d.Run(args...); err != nil { + t.Fatal("docker create failed:", err) + } + defer d.CleanUp() + + gid, err := d.ID() + if err != nil { + t.Fatalf("Docker.ID() failed: %v", err) + } + t.Logf("cgroup ID: %s", gid) + for _, attr := range attrs { + path := filepath.Join("/sys/fs/cgroup", attr.ctrl, "docker", gid, attr.file) + out, err := ioutil.ReadFile(path) + if err != nil { + if os.IsNotExist(err) && attr.skipIfNotFound { + t.Logf("skipped %s/%s", attr.ctrl, attr.file) + continue + } + t.Fatalf("failed to read %q: %v", path, err) + } + if got := strings.TrimSpace(string(out)); got != attr.want { + t.Errorf("arg: %q, cgroup attribute %s/%s, got: %q, want: %q", attr.arg, attr.ctrl, attr.file, got, attr.want) + } + } +} diff --git a/runsc/test/testutil/docker.go b/runsc/test/testutil/docker.go index 2f15ab818..8a51d3eed 100644 --- a/runsc/test/testutil/docker.go +++ b/runsc/test/testutil/docker.go @@ -298,6 +298,15 @@ func (d *Docker) RootDirInHost() (string, error) { return strings.TrimSuffix(string(out), "\n"), nil } +// ID returns the container ID. +func (d *Docker) ID() (string, error) { + out, err := do("inspect", "-f={{.Id}}", d.Name) + if err != nil { + return "", fmt.Errorf("error retrieving ID: %v", err) + } + return strings.TrimSpace(string(out)), nil +} + // WaitForOutput calls 'docker logs' to retrieve containers output and searches // for the given pattern. func (d *Docker) WaitForOutput(pattern string, timeout time.Duration) (string, error) { |