diff --git a/events.go b/events.go index 47aa1abe2..72a808a3d 100644 --- a/events.go +++ b/events.go @@ -8,8 +8,8 @@ import ( "sync" "time" + "github.com/opencontainers/cgroups" "github.com/opencontainers/runc/libcontainer" - "github.com/opencontainers/runc/libcontainer/cgroups" "github.com/opencontainers/runc/libcontainer/intelrdt" "github.com/opencontainers/runc/types" diff --git a/go.mod b/go.mod index e14d042e4..ab77936b1 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,6 @@ go 1.23.0 require ( github.com/checkpoint-restore/go-criu/v6 v6.3.0 - github.com/cilium/ebpf v0.17.3 github.com/containerd/console v1.0.4 github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.4.1 @@ -15,6 +14,7 @@ require ( github.com/moby/sys/user v0.3.0 github.com/moby/sys/userns v0.1.0 github.com/mrunalp/fileutils v0.5.1 + github.com/opencontainers/cgroups v0.0.1 github.com/opencontainers/runtime-spec v1.2.1 github.com/opencontainers/selinux v1.11.1 github.com/seccomp/libseccomp-golang v0.10.0 @@ -34,6 +34,7 @@ exclude ( ) require ( + github.com/cilium/ebpf v0.17.3 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/vishvananda/netns v0.0.4 // indirect diff --git a/go.sum b/go.sum index c3bcace27..1503380ce 100644 --- a/go.sum +++ b/go.sum @@ -49,6 +49,8 @@ github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= github.com/mrunalp/fileutils v0.5.1 h1:F+S7ZlNKnrwHfSwdlgNSkKo67ReVf8o9fel6C3dkm/Q= github.com/mrunalp/fileutils v0.5.1/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= +github.com/opencontainers/cgroups v0.0.1 h1:MXjMkkFpKv6kpuirUa4USFBas573sSAY082B4CiHEVA= +github.com/opencontainers/cgroups v0.0.1/go.mod h1:s8lktyhlGUqM7OSRL5P7eAW6Wb+kWPNvt4qvVfzA5vs= github.com/opencontainers/runtime-spec v1.2.1 h1:S4k4ryNgEpxW1dzyqffOmhI1BHYcjzU8lpJfSlR0xww= github.com/opencontainers/runtime-spec v1.2.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/selinux v1.11.1 h1:nHFvthhM0qY8/m+vfhJylliSshm8G1jJ2jDMcgULaH8= diff --git a/libcontainer/README.md b/libcontainer/README.md index b1e7b0cd1..901351edb 100644 --- a/libcontainer/README.md +++ b/libcontainer/README.md @@ -36,7 +36,7 @@ this package into your code: ```go import ( - _ "github.com/opencontainers/runc/libcontainer/cgroups/devices" + _ "github.com/opencontainers/cgroups/devices" ) ``` diff --git a/libcontainer/cgroups/cgroups_test.go b/libcontainer/cgroups/cgroups_test.go deleted file mode 100644 index b7ca7b183..000000000 --- a/libcontainer/cgroups/cgroups_test.go +++ /dev/null @@ -1,21 +0,0 @@ -package cgroups - -import ( - "testing" -) - -func TestParseCgroups(t *testing.T) { - // We don't need to use /proc/thread-self here because runc always runs - // with every thread in the same cgroup. This lets us avoid having to do - // runtime.LockOSThread. - cgroups, err := ParseCgroupFile("/proc/self/cgroup") - if err != nil { - t.Fatal(err) - } - if IsCgroup2UnifiedMode() { - return - } - if _, ok := cgroups["cpu"]; !ok { - t.Fail() - } -} diff --git a/libcontainer/cgroups/devices/devicefilter_test.go b/libcontainer/cgroups/devices/devicefilter_test.go deleted file mode 100644 index 912e8d8cd..000000000 --- a/libcontainer/cgroups/devices/devicefilter_test.go +++ /dev/null @@ -1,336 +0,0 @@ -package devices - -import ( - "strings" - "testing" - - devices "github.com/opencontainers/runc/libcontainer/cgroups/devices/config" -) - -func hash(s, comm string) string { - var res []string - for _, l := range strings.Split(s, "\n") { - trimmed := strings.TrimSpace(l) - if trimmed == "" || strings.HasPrefix(trimmed, comm) { - continue - } - res = append(res, trimmed) - } - return strings.Join(res, "\n") -} - -func testDeviceFilter(t testing.TB, devices []*devices.Rule, expectedStr string) { - insts, _, err := deviceFilter(devices) - if err != nil { - t.Fatalf("%s: %v (devices: %+v)", t.Name(), err, devices) - } - s := insts.String() - if expectedStr != "" { - hashed := hash(s, "//") - expectedHashed := hash(expectedStr, "//") - if expectedHashed != hashed { - t.Fatalf("expected:\n%q\ngot\n%q", expectedHashed, hashed) - } - } -} - -func TestDeviceFilter_Nil(t *testing.T) { - expected := ` -// load parameters into registers - 0: LdXMemW dst: r2 src: r1 off: 0 imm: 0 - 1: AndImm32 dst: r2 imm: 65535 - 2: LdXMemW dst: r3 src: r1 off: 0 imm: 0 - 3: RShImm32 dst: r3 imm: 16 - 4: LdXMemW dst: r4 src: r1 off: 4 imm: 0 - 5: LdXMemW dst: r5 src: r1 off: 8 imm: 0 -block-0: -// return 0 (reject) - 6: MovImm32 dst: r0 imm: 0 - 7: Exit - ` - testDeviceFilter(t, nil, expected) -} - -func TestDeviceFilter_BuiltInAllowList(t *testing.T) { - // This is a copy of all rules from - // github.com/opencontainers/runc/libcontainer/specconv.AllowedDevices. - devices := []*devices.Rule{ - { - Type: devices.CharDevice, - Major: devices.Wildcard, - Minor: devices.Wildcard, - Permissions: "m", - Allow: true, - }, - { - Type: devices.BlockDevice, - Major: devices.Wildcard, - Minor: devices.Wildcard, - Permissions: "m", - Allow: true, - }, - { - Type: devices.CharDevice, - Major: 1, - Minor: 3, - Permissions: "rwm", - Allow: true, - }, - { - Type: devices.CharDevice, - Major: 1, - Minor: 8, - Permissions: "rwm", - Allow: true, - }, - { - Type: devices.CharDevice, - Major: 1, - Minor: 7, - Permissions: "rwm", - Allow: true, - }, - { - Type: devices.CharDevice, - Major: 5, - Minor: 0, - Permissions: "rwm", - Allow: true, - }, - { - Type: devices.CharDevice, - Major: 1, - Minor: 5, - Permissions: "rwm", - Allow: true, - }, - { - Type: devices.CharDevice, - Major: 1, - Minor: 9, - Permissions: "rwm", - Allow: true, - }, - { - Type: devices.CharDevice, - Major: 136, - Minor: devices.Wildcard, - Permissions: "rwm", - Allow: true, - }, - { - Type: devices.CharDevice, - Major: 5, - Minor: 2, - Permissions: "rwm", - Allow: true, - }, - { - Type: devices.CharDevice, - Major: 10, - Minor: 200, - Permissions: "rwm", - Allow: true, - }, - } - - expected := ` -// load parameters into registers - 0: LdXMemW dst: r2 src: r1 off: 0 imm: 0 - 1: AndImm32 dst: r2 imm: 65535 - 2: LdXMemW dst: r3 src: r1 off: 0 imm: 0 - 3: RShImm32 dst: r3 imm: 16 - 4: LdXMemW dst: r4 src: r1 off: 4 imm: 0 - 5: LdXMemW dst: r5 src: r1 off: 8 imm: 0 -block-0: -// (b, wildcard, wildcard, m, true) - 6: JNEImm dst: r2 off: -1 imm: 1 - 7: MovReg32 dst: r1 src: r3 - 8: AndImm32 dst: r1 imm: 1 - 9: JNEReg dst: r1 off: -1 src: r3 - 10: MovImm32 dst: r0 imm: 1 - 11: Exit -block-1: -// (c, wildcard, wildcard, m, true) - 12: JNEImm dst: r2 off: -1 imm: 2 - 13: MovReg32 dst: r1 src: r3 - 14: AndImm32 dst: r1 imm: 1 - 15: JNEReg dst: r1 off: -1 src: r3 - 16: MovImm32 dst: r0 imm: 1 - 17: Exit -block-2: - 18: JNEImm dst: r2 off: -1 imm: 2 - 19: JNEImm dst: r4 off: -1 imm: 1 - 20: JNEImm dst: r5 off: -1 imm: 3 - 21: MovImm32 dst: r0 imm: 1 - 22: Exit -block-3: - 23: JNEImm dst: r2 off: -1 imm: 2 - 24: JNEImm dst: r4 off: -1 imm: 1 - 25: JNEImm dst: r5 off: -1 imm: 5 - 26: MovImm32 dst: r0 imm: 1 - 27: Exit -block-4: - 28: JNEImm dst: r2 off: -1 imm: 2 - 29: JNEImm dst: r4 off: -1 imm: 1 - 30: JNEImm dst: r5 off: -1 imm: 7 - 31: MovImm32 dst: r0 imm: 1 - 32: Exit -block-5: - 33: JNEImm dst: r2 off: -1 imm: 2 - 34: JNEImm dst: r4 off: -1 imm: 1 - 35: JNEImm dst: r5 off: -1 imm: 8 - 36: MovImm32 dst: r0 imm: 1 - 37: Exit -block-6: - 38: JNEImm dst: r2 off: -1 imm: 2 - 39: JNEImm dst: r4 off: -1 imm: 1 - 40: JNEImm dst: r5 off: -1 imm: 9 - 41: MovImm32 dst: r0 imm: 1 - 42: Exit -block-7: - 43: JNEImm dst: r2 off: -1 imm: 2 - 44: JNEImm dst: r4 off: -1 imm: 5 - 45: JNEImm dst: r5 off: -1 imm: 0 - 46: MovImm32 dst: r0 imm: 1 - 47: Exit -block-8: - 48: JNEImm dst: r2 off: -1 imm: 2 - 49: JNEImm dst: r4 off: -1 imm: 5 - 50: JNEImm dst: r5 off: -1 imm: 2 - 51: MovImm32 dst: r0 imm: 1 - 52: Exit -block-9: -// tuntap (c, 10, 200, rwm, true) - 53: JNEImm dst: r2 off: -1 imm: 2 - 54: JNEImm dst: r4 off: -1 imm: 10 - 55: JNEImm dst: r5 off: -1 imm: 200 - 56: MovImm32 dst: r0 imm: 1 - 57: Exit -block-10: -// /dev/pts (c, 136, wildcard, rwm, true) - 58: JNEImm dst: r2 off: -1 imm: 2 - 59: JNEImm dst: r4 off: -1 imm: 136 - 60: MovImm32 dst: r0 imm: 1 - 61: Exit -block-11: - 62: MovImm32 dst: r0 imm: 0 - 63: Exit -` - testDeviceFilter(t, devices, expected) -} - -func TestDeviceFilter_Privileged(t *testing.T) { - devices := []*devices.Rule{ - { - Type: 'a', - Major: -1, - Minor: -1, - Permissions: "rwm", - Allow: true, - }, - } - expected := ` -// load parameters into registers - 0: LdXMemW dst: r2 src: r1 off: 0 imm: 0 - 1: AndImm32 dst: r2 imm: 65535 - 2: LdXMemW dst: r3 src: r1 off: 0 imm: 0 - 3: RShImm32 dst: r3 imm: 16 - 4: LdXMemW dst: r4 src: r1 off: 4 imm: 0 - 5: LdXMemW dst: r5 src: r1 off: 8 imm: 0 -block-0: -// return 1 (accept) - 6: MovImm32 dst: r0 imm: 1 - 7: Exit - ` - testDeviceFilter(t, devices, expected) -} - -func TestDeviceFilter_PrivilegedExceptSingleDevice(t *testing.T) { - devices := []*devices.Rule{ - { - Type: 'a', - Major: -1, - Minor: -1, - Permissions: "rwm", - Allow: true, - }, - { - Type: 'b', - Major: 8, - Minor: 0, - Permissions: "rwm", - Allow: false, - }, - } - expected := ` -// load parameters into registers - 0: LdXMemW dst: r2 src: r1 off: 0 imm: 0 - 1: AndImm32 dst: r2 imm: 65535 - 2: LdXMemW dst: r3 src: r1 off: 0 imm: 0 - 3: RShImm32 dst: r3 imm: 16 - 4: LdXMemW dst: r4 src: r1 off: 4 imm: 0 - 5: LdXMemW dst: r5 src: r1 off: 8 imm: 0 -block-0: -// return 0 (reject) if type==b && major == 8 && minor == 0 - 6: JNEImm dst: r2 off: -1 imm: 1 - 7: JNEImm dst: r4 off: -1 imm: 8 - 8: JNEImm dst: r5 off: -1 imm: 0 - 9: MovImm32 dst: r0 imm: 0 - 10: Exit -block-1: -// return 1 (accept) - 11: MovImm32 dst: r0 imm: 1 - 12: Exit -` - testDeviceFilter(t, devices, expected) -} - -func TestDeviceFilter_Weird(t *testing.T) { - devices := []*devices.Rule{ - { - Type: 'b', - Major: 8, - Minor: 1, - Permissions: "rwm", - Allow: false, - }, - { - Type: 'a', - Major: -1, - Minor: -1, - Permissions: "rwm", - Allow: true, - }, - { - Type: 'b', - Major: 8, - Minor: 2, - Permissions: "rwm", - Allow: false, - }, - } - // 8/1 is allowed, 8/2 is not allowed. - // This conforms to runc v1.0.0-rc.9 (cgroup1) behavior. - expected := ` -// load parameters into registers - 0: LdXMemW dst: r2 src: r1 off: 0 imm: 0 - 1: AndImm32 dst: r2 imm: 65535 - 2: LdXMemW dst: r3 src: r1 off: 0 imm: 0 - 3: RShImm32 dst: r3 imm: 16 - 4: LdXMemW dst: r4 src: r1 off: 4 imm: 0 - 5: LdXMemW dst: r5 src: r1 off: 8 imm: 0 -block-0: -// return 0 (reject) if type==b && major == 8 && minor == 2 - 6: JNEImm dst: r2 off: -1 imm: 1 - 7: JNEImm dst: r4 off: -1 imm: 8 - 8: JNEImm dst: r5 off: -1 imm: 2 - 9: MovImm32 dst: r0 imm: 0 - 10: Exit -block-1: -// return 1 (accept) - 11: MovImm32 dst: r0 imm: 1 - 12: Exit -` - testDeviceFilter(t, devices, expected) -} diff --git a/libcontainer/cgroups/devices/devices_emulator_test.go b/libcontainer/cgroups/devices/devices_emulator_test.go deleted file mode 100644 index c107618cc..000000000 --- a/libcontainer/cgroups/devices/devices_emulator_test.go +++ /dev/null @@ -1,1144 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -/* - * Copyright (C) 2020 Aleksa Sarai - * Copyright (C) 2020 SUSE LLC - * - * 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 devices - -import ( - "bufio" - "bytes" - "reflect" - "strings" - "testing" - - devices "github.com/opencontainers/runc/libcontainer/cgroups/devices/config" -) - -func TestDeviceEmulatorLoad(t *testing.T) { - tests := []struct { - name, list string - expected *emulator - }{ - { - name: "BlacklistMode", - list: `a *:* rwm`, - expected: &emulator{ - defaultAllow: true, - }, - }, - { - name: "WhitelistBasic", - list: `c 4:2 rw`, - expected: &emulator{ - defaultAllow: false, - rules: deviceRules{ - { - node: devices.CharDevice, - major: 4, - minor: 2, - }: devices.Permissions("rw"), - }, - }, - }, - { - name: "WhitelistWildcard", - list: `b 0:* m`, - expected: &emulator{ - defaultAllow: false, - rules: deviceRules{ - { - node: devices.BlockDevice, - major: 0, - minor: devices.Wildcard, - }: devices.Permissions("m"), - }, - }, - }, - { - name: "WhitelistDuplicate", - list: `c *:* rwm -c 1:1 r`, - expected: &emulator{ - defaultAllow: false, - rules: deviceRules{ - { - node: devices.CharDevice, - major: devices.Wildcard, - minor: devices.Wildcard, - }: devices.Permissions("rwm"), - // To match the kernel, we allow redundant rules. - { - node: devices.CharDevice, - major: 1, - minor: 1, - }: devices.Permissions("r"), - }, - }, - }, - { - name: "WhitelistComplicated", - list: `c *:* m -b *:* m -c 1:3 rwm -c 1:5 rwm -c 1:7 rwm -c 1:8 rwm -c 1:9 rwm -c 5:0 rwm -c 5:2 rwm -c 136:* rwm -c 10:200 rwm`, - expected: &emulator{ - defaultAllow: false, - rules: deviceRules{ - { - node: devices.CharDevice, - major: devices.Wildcard, - minor: devices.Wildcard, - }: devices.Permissions("m"), - { - node: devices.BlockDevice, - major: devices.Wildcard, - minor: devices.Wildcard, - }: devices.Permissions("m"), - { - node: devices.CharDevice, - major: 1, - minor: 3, - }: devices.Permissions("rwm"), - { - node: devices.CharDevice, - major: 1, - minor: 5, - }: devices.Permissions("rwm"), - { - node: devices.CharDevice, - major: 1, - minor: 7, - }: devices.Permissions("rwm"), - { - node: devices.CharDevice, - major: 1, - minor: 8, - }: devices.Permissions("rwm"), - { - node: devices.CharDevice, - major: 1, - minor: 9, - }: devices.Permissions("rwm"), - { - node: devices.CharDevice, - major: 5, - minor: 0, - }: devices.Permissions("rwm"), - { - node: devices.CharDevice, - major: 5, - minor: 2, - }: devices.Permissions("rwm"), - { - node: devices.CharDevice, - major: 136, - minor: devices.Wildcard, - }: devices.Permissions("rwm"), - { - node: devices.CharDevice, - major: 10, - minor: 200, - }: devices.Permissions("rwm"), - }, - }, - }, - // Some invalid lists. - { - name: "InvalidFieldNumber", - list: `b 1:0`, - expected: nil, - }, - { - name: "InvalidDeviceType", - list: `p *:* rwm`, - expected: nil, - }, - { - name: "InvalidMajorNumber1", - list: `p -1:3 rwm`, - expected: nil, - }, - { - name: "InvalidMajorNumber2", - list: `c foo:27 rwm`, - expected: nil, - }, - { - name: "InvalidMinorNumber1", - list: `b 1:-4 rwm`, - expected: nil, - }, - { - name: "InvalidMinorNumber2", - list: `b 1:foo rwm`, - expected: nil, - }, - { - name: "InvalidPermissions", - list: `b 1:7 rwk`, - expected: nil, - }, - } - - for _, test := range tests { - test := test // capture range variable - t.Run(test.name, func(t *testing.T) { - list := bytes.NewBufferString(test.list) - emu, err := emulatorFromList(list) - if err != nil && test.expected != nil { - t.Fatalf("unexpected failure when creating emulator: %v", err) - } else if err == nil && test.expected == nil { - t.Fatalf("unexpected success when creating emulator: %#v", emu) - } - - if !reflect.DeepEqual(emu, test.expected) { - t.Errorf("final emulator state mismatch: %#v != %#v", emu, test.expected) - } - }) - } -} - -func testDeviceEmulatorApply(t *testing.T, baseDefaultAllow bool) { - tests := []struct { - name string - rule devices.Rule - base, expected *emulator - }{ - // Switch between default modes. - { - name: "SwitchToOtherMode", - rule: devices.Rule{ - Type: devices.WildcardDevice, - Major: devices.Wildcard, - Minor: devices.Wildcard, - Permissions: devices.Permissions("rwm"), - Allow: !baseDefaultAllow, - }, - base: &emulator{ - defaultAllow: baseDefaultAllow, - rules: deviceRules{ - { - node: devices.CharDevice, - major: devices.Wildcard, - minor: devices.Wildcard, - }: devices.Permissions("rwm"), - { - node: devices.CharDevice, - major: 1, - minor: 1, - }: devices.Permissions("r"), - }, - }, - expected: &emulator{ - defaultAllow: !baseDefaultAllow, - rules: nil, - }, - }, - { - name: "SwitchToSameModeNoop", - rule: devices.Rule{ - Type: devices.WildcardDevice, - Major: devices.Wildcard, - Minor: devices.Wildcard, - Permissions: devices.Permissions("rwm"), - Allow: baseDefaultAllow, - }, - base: &emulator{ - defaultAllow: baseDefaultAllow, - rules: nil, - }, - expected: &emulator{ - defaultAllow: baseDefaultAllow, - rules: nil, - }, - }, - { - name: "SwitchToSameMode", - rule: devices.Rule{ - Type: devices.WildcardDevice, - Major: devices.Wildcard, - Minor: devices.Wildcard, - Permissions: devices.Permissions("rwm"), - Allow: baseDefaultAllow, - }, - base: &emulator{ - defaultAllow: baseDefaultAllow, - rules: deviceRules{ - { - node: devices.CharDevice, - major: devices.Wildcard, - minor: devices.Wildcard, - }: devices.Permissions("rwm"), - { - node: devices.CharDevice, - major: 1, - minor: 1, - }: devices.Permissions("r"), - }, - }, - expected: &emulator{ - defaultAllow: baseDefaultAllow, - rules: nil, - }, - }, - // Rule addition logic. - { - name: "RuleAdditionBasic", - rule: devices.Rule{ - Type: devices.CharDevice, - Major: 42, - Minor: 1337, - Permissions: devices.Permissions("rm"), - Allow: !baseDefaultAllow, - }, - base: &emulator{ - defaultAllow: baseDefaultAllow, - rules: deviceRules{ - { - node: devices.CharDevice, - major: 2, - minor: 1, - }: devices.Permissions("rwm"), - { - node: devices.BlockDevice, - major: 1, - minor: 5, - }: devices.Permissions("r"), - }, - }, - expected: &emulator{ - defaultAllow: baseDefaultAllow, - rules: deviceRules{ - { - node: devices.CharDevice, - major: 2, - minor: 1, - }: devices.Permissions("rwm"), - { - node: devices.BlockDevice, - major: 1, - minor: 5, - }: devices.Permissions("r"), - { - node: devices.CharDevice, - major: 42, - minor: 1337, - }: devices.Permissions("rm"), - }, - }, - }, - { - name: "RuleAdditionBasicDuplicate", - rule: devices.Rule{ - Type: devices.CharDevice, - Major: 42, - Minor: 1337, - Permissions: devices.Permissions("rm"), - Allow: !baseDefaultAllow, - }, - base: &emulator{ - defaultAllow: baseDefaultAllow, - rules: deviceRules{ - { - node: devices.CharDevice, - major: 42, - minor: devices.Wildcard, - }: devices.Permissions("rwm"), - }, - }, - expected: &emulator{ - defaultAllow: baseDefaultAllow, - rules: deviceRules{ - { - node: devices.CharDevice, - major: 42, - minor: devices.Wildcard, - }: devices.Permissions("rwm"), - // To match the kernel, we allow redundant rules. - { - node: devices.CharDevice, - major: 42, - minor: 1337, - }: devices.Permissions("rm"), - }, - }, - }, - { - name: "RuleAdditionBasicDuplicateNoop", - rule: devices.Rule{ - Type: devices.CharDevice, - Major: 42, - Minor: 1337, - Permissions: devices.Permissions("rm"), - Allow: !baseDefaultAllow, - }, - base: &emulator{ - defaultAllow: baseDefaultAllow, - rules: deviceRules{ - { - node: devices.CharDevice, - major: 42, - minor: 1337, - }: devices.Permissions("rm"), - }, - }, - expected: &emulator{ - defaultAllow: baseDefaultAllow, - rules: deviceRules{ - { - node: devices.CharDevice, - major: 42, - minor: 1337, - }: devices.Permissions("rm"), - }, - }, - }, - { - name: "RuleAdditionMerge", - rule: devices.Rule{ - Type: devices.BlockDevice, - Major: 5, - Minor: 12, - Permissions: devices.Permissions("rm"), - Allow: !baseDefaultAllow, - }, - base: &emulator{ - defaultAllow: baseDefaultAllow, - rules: deviceRules{ - { - node: devices.CharDevice, - major: 2, - minor: 1, - }: devices.Permissions("rwm"), - { - node: devices.BlockDevice, - major: 5, - minor: 12, - }: devices.Permissions("rw"), - }, - }, - expected: &emulator{ - defaultAllow: baseDefaultAllow, - rules: deviceRules{ - { - node: devices.CharDevice, - major: 2, - minor: 1, - }: devices.Permissions("rwm"), - { - node: devices.BlockDevice, - major: 5, - minor: 12, - }: devices.Permissions("rwm"), - }, - }, - }, - { - name: "RuleAdditionMergeWildcard", - rule: devices.Rule{ - Type: devices.BlockDevice, - Major: 5, - Minor: devices.Wildcard, - Permissions: devices.Permissions("rm"), - Allow: !baseDefaultAllow, - }, - base: &emulator{ - defaultAllow: baseDefaultAllow, - rules: deviceRules{ - { - node: devices.CharDevice, - major: 2, - minor: 1, - }: devices.Permissions("rwm"), - { - node: devices.BlockDevice, - major: 5, - minor: devices.Wildcard, - }: devices.Permissions("rw"), - }, - }, - expected: &emulator{ - defaultAllow: baseDefaultAllow, - rules: deviceRules{ - { - node: devices.CharDevice, - major: 2, - minor: 1, - }: devices.Permissions("rwm"), - { - node: devices.BlockDevice, - major: 5, - minor: devices.Wildcard, - }: devices.Permissions("rwm"), - }, - }, - }, - { - name: "RuleAdditionMergeNoop", - rule: devices.Rule{ - Type: devices.BlockDevice, - Major: 5, - Minor: 12, - Permissions: devices.Permissions("r"), - Allow: !baseDefaultAllow, - }, - base: &emulator{ - defaultAllow: baseDefaultAllow, - rules: deviceRules{ - { - node: devices.CharDevice, - major: 2, - minor: 1, - }: devices.Permissions("rwm"), - { - node: devices.BlockDevice, - major: 5, - minor: 12, - }: devices.Permissions("rw"), - }, - }, - expected: &emulator{ - defaultAllow: baseDefaultAllow, - rules: deviceRules{ - { - node: devices.CharDevice, - major: 2, - minor: 1, - }: devices.Permissions("rwm"), - { - node: devices.BlockDevice, - major: 5, - minor: 12, - }: devices.Permissions("rw"), - }, - }, - }, - // Rule removal logic. - { - name: "RuleRemovalBasic", - rule: devices.Rule{ - Type: devices.CharDevice, - Major: 42, - Minor: 1337, - Permissions: devices.Permissions("rm"), - Allow: baseDefaultAllow, - }, - base: &emulator{ - defaultAllow: baseDefaultAllow, - rules: deviceRules{ - { - node: devices.CharDevice, - major: 42, - minor: 1337, - }: devices.Permissions("rm"), - { - node: devices.BlockDevice, - major: 1, - minor: 5, - }: devices.Permissions("r"), - }, - }, - expected: &emulator{ - defaultAllow: baseDefaultAllow, - rules: deviceRules{ - { - node: devices.BlockDevice, - major: 1, - minor: 5, - }: devices.Permissions("r"), - }, - }, - }, - { - name: "RuleRemovalNonexistent", - rule: devices.Rule{ - Type: devices.CharDevice, - Major: 4, - Minor: 1, - Permissions: devices.Permissions("rw"), - Allow: baseDefaultAllow, - }, - base: &emulator{ - defaultAllow: baseDefaultAllow, - rules: deviceRules{ - { - node: devices.BlockDevice, - major: 1, - minor: 5, - }: devices.Permissions("r"), - }, - }, - expected: &emulator{ - defaultAllow: baseDefaultAllow, - rules: deviceRules{ - { - node: devices.BlockDevice, - major: 1, - minor: 5, - }: devices.Permissions("r"), - }, - }, - }, - { - name: "RuleRemovalFull", - rule: devices.Rule{ - Type: devices.CharDevice, - Major: 42, - Minor: 1337, - Permissions: devices.Permissions("rw"), - Allow: baseDefaultAllow, - }, - base: &emulator{ - defaultAllow: baseDefaultAllow, - rules: deviceRules{ - { - node: devices.CharDevice, - major: 42, - minor: 1337, - }: devices.Permissions("w"), - { - node: devices.BlockDevice, - major: 1, - minor: 5, - }: devices.Permissions("r"), - }, - }, - expected: &emulator{ - defaultAllow: baseDefaultAllow, - rules: deviceRules{ - { - node: devices.BlockDevice, - major: 1, - minor: 5, - }: devices.Permissions("r"), - }, - }, - }, - { - name: "RuleRemovalPartial", - rule: devices.Rule{ - Type: devices.CharDevice, - Major: 42, - Minor: 1337, - Permissions: devices.Permissions("r"), - Allow: baseDefaultAllow, - }, - base: &emulator{ - defaultAllow: baseDefaultAllow, - rules: deviceRules{ - { - node: devices.CharDevice, - major: 42, - minor: 1337, - }: devices.Permissions("rm"), - { - node: devices.BlockDevice, - major: 1, - minor: 5, - }: devices.Permissions("r"), - }, - }, - expected: &emulator{ - defaultAllow: baseDefaultAllow, - rules: deviceRules{ - { - node: devices.CharDevice, - major: 42, - minor: 1337, - }: devices.Permissions("m"), - { - node: devices.BlockDevice, - major: 1, - minor: 5, - }: devices.Permissions("r"), - }, - }, - }, - // Check our non-canonical behaviour when it comes to try to "punch - // out" holes in a wildcard rule. - { - name: "RuleRemovalWildcardPunchoutImpossible", - rule: devices.Rule{ - Type: devices.CharDevice, - Major: 42, - Minor: 1337, - Permissions: devices.Permissions("r"), - Allow: baseDefaultAllow, - }, - base: &emulator{ - defaultAllow: baseDefaultAllow, - rules: deviceRules{ - { - node: devices.CharDevice, - major: 42, - minor: devices.Wildcard, - }: devices.Permissions("rm"), - { - node: devices.CharDevice, - major: 42, - minor: 1337, - }: devices.Permissions("r"), - }, - }, - expected: nil, - }, - { - name: "RuleRemovalWildcardPunchoutPossible", - rule: devices.Rule{ - Type: devices.CharDevice, - Major: 42, - Minor: 1337, - Permissions: devices.Permissions("r"), - Allow: baseDefaultAllow, - }, - base: &emulator{ - defaultAllow: baseDefaultAllow, - rules: deviceRules{ - { - node: devices.CharDevice, - major: 42, - minor: devices.Wildcard, - }: devices.Permissions("wm"), - { - node: devices.CharDevice, - major: 42, - minor: 1337, - }: devices.Permissions("r"), - }, - }, - expected: &emulator{ - defaultAllow: baseDefaultAllow, - rules: deviceRules{ - { - node: devices.CharDevice, - major: 42, - minor: devices.Wildcard, - }: devices.Permissions("wm"), - }, - }, - }, - } - - for _, test := range tests { - test := test - t.Run(test.name, func(t *testing.T) { - err := test.base.Apply(test.rule) - if err != nil && test.expected != nil { - t.Fatalf("unexpected failure when applying apply rule: %v", err) - } else if err == nil && test.expected == nil { - t.Fatalf("unexpected success when applying apply rule: %#v", test.base) - } - - if test.expected != nil && !reflect.DeepEqual(test.base, test.expected) { - t.Errorf("final emulator state mismatch: %#v != %#v", test.base, test.expected) - } - }) - } -} - -func TestDeviceEmulatorWhitelistApply(t *testing.T) { - testDeviceEmulatorApply(t, false) -} - -func TestDeviceEmulatorBlacklistApply(t *testing.T) { - testDeviceEmulatorApply(t, true) -} - -func testDeviceEmulatorTransition(t *testing.T, sourceDefaultAllow bool) { - tests := []struct { - name string - source, target *emulator - expected []*devices.Rule - }{ - // No-op changes. - { - name: "Noop", - source: &emulator{ - defaultAllow: sourceDefaultAllow, - rules: deviceRules{ - { - node: devices.CharDevice, - major: 42, - minor: devices.Wildcard, - }: devices.Permissions("wm"), - }, - }, - target: &emulator{ - defaultAllow: sourceDefaultAllow, - rules: deviceRules{ - { - node: devices.CharDevice, - major: 42, - minor: devices.Wildcard, - }: devices.Permissions("wm"), - }, - }, - // Identical white-lists produce no extra rules. - expected: nil, - }, - // Switching modes. - { - name: "SwitchToOtherMode", - source: &emulator{ - defaultAllow: sourceDefaultAllow, - rules: deviceRules{ - { - node: devices.CharDevice, - major: 1, - minor: 2, - }: devices.Permissions("rwm"), - }, - }, - target: &emulator{ - defaultAllow: !sourceDefaultAllow, - rules: deviceRules{ - { - node: devices.BlockDevice, - major: 42, - minor: devices.Wildcard, - }: devices.Permissions("wm"), - }, - }, - expected: []*devices.Rule{ - // Clear-all rule. - { - Type: devices.WildcardDevice, - Major: devices.Wildcard, - Minor: devices.Wildcard, - Permissions: devices.Permissions("rwm"), - Allow: !sourceDefaultAllow, - }, - // The actual rule-set. - { - Type: devices.BlockDevice, - Major: 42, - Minor: devices.Wildcard, - Permissions: devices.Permissions("wm"), - Allow: sourceDefaultAllow, - }, - }, - }, - // Rule changes. - { - name: "RuleAddition", - source: &emulator{ - defaultAllow: sourceDefaultAllow, - rules: deviceRules{ - { - node: devices.CharDevice, - major: 1, - minor: 2, - }: devices.Permissions("rwm"), - }, - }, - target: &emulator{ - defaultAllow: sourceDefaultAllow, - rules: deviceRules{ - { - node: devices.CharDevice, - major: 1, - minor: 2, - }: devices.Permissions("rwm"), - { - node: devices.BlockDevice, - major: 42, - minor: 1337, - }: devices.Permissions("rwm"), - }, - }, - expected: []*devices.Rule{ - { - Type: devices.BlockDevice, - Major: 42, - Minor: 1337, - Permissions: devices.Permissions("rwm"), - Allow: !sourceDefaultAllow, - }, - }, - }, - { - name: "RuleRemoval", - source: &emulator{ - defaultAllow: sourceDefaultAllow, - rules: deviceRules{ - { - node: devices.CharDevice, - major: 1, - minor: 2, - }: devices.Permissions("rwm"), - { - node: devices.BlockDevice, - major: 42, - minor: 1337, - }: devices.Permissions("rwm"), - }, - }, - target: &emulator{ - defaultAllow: sourceDefaultAllow, - rules: deviceRules{ - { - node: devices.CharDevice, - major: 1, - minor: 2, - }: devices.Permissions("rwm"), - }, - }, - expected: []*devices.Rule{ - { - Type: devices.BlockDevice, - Major: 42, - Minor: 1337, - Permissions: devices.Permissions("rwm"), - Allow: sourceDefaultAllow, - }, - }, - }, - { - name: "RuleMultipleAdditionRemoval", - source: &emulator{ - defaultAllow: sourceDefaultAllow, - rules: deviceRules{ - { - node: devices.CharDevice, - major: 1, - minor: 2, - }: devices.Permissions("rwm"), - { - node: devices.BlockDevice, - major: 3, - minor: 9, - }: devices.Permissions("rw"), - }, - }, - target: &emulator{ - defaultAllow: sourceDefaultAllow, - rules: deviceRules{ - { - node: devices.CharDevice, - major: 1, - minor: 2, - }: devices.Permissions("rwm"), - }, - }, - expected: []*devices.Rule{ - { - Type: devices.BlockDevice, - Major: 3, - Minor: 9, - Permissions: devices.Permissions("rw"), - Allow: sourceDefaultAllow, - }, - }, - }, - // Modifying the access permissions. - { - name: "RulePartialAddition", - source: &emulator{ - defaultAllow: sourceDefaultAllow, - rules: deviceRules{ - { - node: devices.CharDevice, - major: 1, - minor: 2, - }: devices.Permissions("r"), - }, - }, - target: &emulator{ - defaultAllow: sourceDefaultAllow, - rules: deviceRules{ - { - node: devices.CharDevice, - major: 1, - minor: 2, - }: devices.Permissions("rwm"), - }, - }, - expected: []*devices.Rule{ - { - Type: devices.CharDevice, - Major: 1, - Minor: 2, - Permissions: devices.Permissions("wm"), - Allow: !sourceDefaultAllow, - }, - }, - }, - { - name: "RulePartialRemoval", - source: &emulator{ - defaultAllow: sourceDefaultAllow, - rules: deviceRules{ - { - node: devices.CharDevice, - major: 1, - minor: 2, - }: devices.Permissions("rw"), - }, - }, - target: &emulator{ - defaultAllow: sourceDefaultAllow, - rules: deviceRules{ - { - node: devices.CharDevice, - major: 1, - minor: 2, - }: devices.Permissions("w"), - }, - }, - expected: []*devices.Rule{ - { - Type: devices.CharDevice, - Major: 1, - Minor: 2, - Permissions: devices.Permissions("r"), - Allow: sourceDefaultAllow, - }, - }, - }, - { - name: "RulePartialBoth", - source: &emulator{ - defaultAllow: sourceDefaultAllow, - rules: deviceRules{ - { - node: devices.CharDevice, - major: 1, - minor: 2, - }: devices.Permissions("rw"), - }, - }, - target: &emulator{ - defaultAllow: sourceDefaultAllow, - rules: deviceRules{ - { - node: devices.CharDevice, - major: 1, - minor: 2, - }: devices.Permissions("rm"), - }, - }, - expected: []*devices.Rule{ - { - Type: devices.CharDevice, - Major: 1, - Minor: 2, - Permissions: devices.Permissions("w"), - Allow: sourceDefaultAllow, - }, - { - Type: devices.CharDevice, - Major: 1, - Minor: 2, - Permissions: devices.Permissions("m"), - Allow: !sourceDefaultAllow, - }, - }, - }, - } - - for _, test := range tests { - test := test - t.Run(test.name, func(t *testing.T) { - // If we are in black-list mode, we need to prepend the relevant - // clear-all rule (the expected rule lists are written with - // white-list mode in mind), and then make a full copy of the - // target rules. - if sourceDefaultAllow && test.source.defaultAllow == test.target.defaultAllow { - test.expected = []*devices.Rule{{ - Type: devices.WildcardDevice, - Major: devices.Wildcard, - Minor: devices.Wildcard, - Permissions: devices.Permissions("rwm"), - Allow: test.target.defaultAllow, - }} - for _, rule := range test.target.rules.orderedEntries() { - test.expected = append(test.expected, &devices.Rule{ - Type: rule.meta.node, - Major: rule.meta.major, - Minor: rule.meta.minor, - Permissions: rule.perms, - Allow: !test.target.defaultAllow, - }) - } - } - - rules, err := test.source.Transition(test.target) - if err != nil { - t.Fatalf("unexpected error while calculating transition rules: %#v", err) - } - - if !reflect.DeepEqual(rules, test.expected) { - t.Errorf("rules don't match expected set: %#v != %#v", rules, test.expected) - } - - // Apply the rules to the source to see if it actually transitions - // correctly. This is all emulated but it's a good thing to - // double-check. - for _, rule := range rules { - if err := test.source.Apply(*rule); err != nil { - t.Fatalf("error while applying transition rule [%#v]: %v", rule, err) - } - } - if !reflect.DeepEqual(test.source, test.target) { - t.Errorf("transition incomplete after applying all rules: %#v != %#v", test.source, test.target) - } - }) - } -} - -func TestDeviceEmulatorTransitionFromBlacklist(t *testing.T) { - testDeviceEmulatorTransition(t, true) -} - -func TestDeviceEmulatorTransitionFromWhitelist(t *testing.T) { - testDeviceEmulatorTransition(t, false) -} - -func BenchmarkParseLine(b *testing.B) { - list := `c *:* m -b *:* m -c 1:3 rwm -c 1:5 rwm -c 1:7 rwm -c 1:8 rwm -c 1:9 rwm -c 5:0 rwm -c 5:2 rwm -c 136:* rwm -c 10:200 rwm` - - var r *deviceRule - var err error - for i := 0; i < b.N; i++ { - s := bufio.NewScanner(strings.NewReader(list)) - for s.Scan() { - line := s.Text() - r, err = parseLine(line) - } - if err := s.Err(); err != nil { - b.Fatal(err) - } - } - b.Logf("rule: %v, err: %v", r, err) -} diff --git a/libcontainer/cgroups/devices/systemd_test.go b/libcontainer/cgroups/devices/systemd_test.go deleted file mode 100644 index 0b3e3d4e2..000000000 --- a/libcontainer/cgroups/devices/systemd_test.go +++ /dev/null @@ -1,279 +0,0 @@ -package devices - -import ( - "bytes" - "fmt" - "os" - "os/exec" - "strings" - "testing" - - "github.com/opencontainers/runc/libcontainer/cgroups" - devices "github.com/opencontainers/runc/libcontainer/cgroups/devices/config" - "github.com/opencontainers/runc/libcontainer/cgroups/systemd" -) - -// TestPodSkipDevicesUpdate checks that updating a pod having SkipDevices: true -// does not result in spurious "permission denied" errors in a container -// running under the pod. The test is somewhat similar in nature to the -// @test "update devices [minimal transition rules]" in tests/integration, -// but uses a pod. -func TestPodSkipDevicesUpdate(t *testing.T) { - if !systemd.IsRunningSystemd() { - t.Skip("Test requires systemd.") - } - if os.Geteuid() != 0 { - t.Skip("Test requires root.") - } - - podName := "system-runc_test_pod" + t.Name() + ".slice" - podConfig := &cgroups.Cgroup{ - Systemd: true, - Parent: "system.slice", - Name: podName, - Resources: &cgroups.Resources{ - PidsLimit: 42, - Memory: 32 * 1024 * 1024, - SkipDevices: true, - }, - } - // Create "pod" cgroup (a systemd slice to hold containers). - pm := newManager(t, podConfig) - if err := pm.Apply(-1); err != nil { - t.Fatal(err) - } - if err := pm.Set(podConfig.Resources); err != nil { - t.Fatal(err) - } - - containerConfig := &cgroups.Cgroup{ - Parent: podName, - ScopePrefix: "test", - Name: "PodSkipDevicesUpdate", - Resources: &cgroups.Resources{ - Devices: []*devices.Rule{ - // Allow access to /dev/null. - { - Type: devices.CharDevice, - Major: 1, - Minor: 3, - Permissions: "rwm", - Allow: true, - }, - }, - }, - } - - // Create a "container" within the "pod" cgroup. - // This is not a real container, just a process in the cgroup. - cmd := exec.Command("sleep", "infinity") - cmd.Env = append(os.Environ(), "LANG=C") - var stderr bytes.Buffer - cmd.Stderr = &stderr - if err := cmd.Start(); err != nil { - t.Fatal(err) - } - // Make sure to not leave a zombie. - defer func() { - // These may fail, we don't care. - _ = cmd.Process.Kill() - _ = cmd.Wait() - }() - - // Put the process into a cgroup. - cm := newManager(t, containerConfig) - if err := cm.Apply(cmd.Process.Pid); err != nil { - t.Fatal(err) - } - // Check that we put the "container" into the "pod" cgroup. - if !strings.HasPrefix(cm.Path("devices"), pm.Path("devices")) { - t.Fatalf("expected container cgroup path %q to be under pod cgroup path %q", - cm.Path("devices"), pm.Path("devices")) - } - if err := cm.Set(containerConfig.Resources); err != nil { - t.Fatal(err) - } - - // Now update the pod a few times. - for i := 0; i < 42; i++ { - podConfig.Resources.PidsLimit++ - podConfig.Resources.Memory += 1024 * 1024 - if err := pm.Set(podConfig.Resources); err != nil { - t.Fatal(err) - } - } - // Kill the "container". - if err := cmd.Process.Kill(); err != nil { - t.Fatal(err) - } - - _ = cmd.Wait() - - // "Container" stderr should be empty. - if stderr.Len() != 0 { - t.Fatalf("container stderr not empty: %s", stderr.String()) - } -} - -func testSkipDevices(t *testing.T, skipDevices bool, expected []string) { - if !systemd.IsRunningSystemd() { - t.Skip("Test requires systemd.") - } - if os.Geteuid() != 0 { - t.Skip("Test requires root.") - } - - podConfig := &cgroups.Cgroup{ - Parent: "system.slice", - Name: "system-runc_test_pods.slice", - Resources: &cgroups.Resources{ - SkipDevices: skipDevices, - }, - } - // Create "pods" cgroup (a systemd slice to hold containers). - pm := newManager(t, podConfig) - if err := pm.Apply(-1); err != nil { - t.Fatal(err) - } - if err := pm.Set(podConfig.Resources); err != nil { - t.Fatal(err) - } - - config := &cgroups.Cgroup{ - Parent: "system-runc_test_pods.slice", - ScopePrefix: "test", - Name: "SkipDevices", - Resources: &cgroups.Resources{ - Devices: []*devices.Rule{ - // Allow access to /dev/full only. - { - Type: devices.CharDevice, - Major: 1, - Minor: 7, - Permissions: "rwm", - Allow: true, - }, - }, - }, - } - - // Create a "container" within the "pods" cgroup. - // This is not a real container, just a process in the cgroup. - cmd := exec.Command("bash", "-c", "read; echo > /dev/full; cat /dev/null; true") - cmd.Env = append(os.Environ(), "LANG=C") - stdinR, stdinW, err := os.Pipe() - if err != nil { - t.Fatal(err) - } - cmd.Stdin = stdinR - var stderr bytes.Buffer - cmd.Stderr = &stderr - err = cmd.Start() - stdinR.Close() - defer stdinW.Close() - if err != nil { - t.Fatal(err) - } - // Make sure to not leave a zombie. - defer func() { - // These may fail, we don't care. - _, _ = stdinW.WriteString("hey\n") - _ = cmd.Wait() - }() - - // Put the process into a cgroup. - m := newManager(t, config) - if err := m.Apply(cmd.Process.Pid); err != nil { - t.Fatal(err) - } - // Check that we put the "container" into the "pod" cgroup. - if !strings.HasPrefix(m.Path("devices"), pm.Path("devices")) { - t.Fatalf("expected container cgroup path %q to be under pod cgroup path %q", - m.Path("devices"), pm.Path("devices")) - } - if err := m.Set(config.Resources); err != nil { - // failed to write "c 1:7 rwm": write /sys/fs/cgroup/devices/system.slice/system-runc_test_pods.slice/test-SkipDevices.scope/devices.allow: operation not permitted - if skipDevices == false && strings.HasSuffix(err.Error(), "/devices.allow: operation not permitted") { - // Cgroup v1 devices controller gives EPERM on trying - // to enable devices that are not enabled - // (skipDevices=false) in a parent cgroup. - // If this happens, test is passing. - return - } - t.Fatal(err) - } - - // Check that we can access /dev/full but not /dev/zero. - if _, err := stdinW.WriteString("wow\n"); err != nil { - t.Fatal(err) - } - if err := cmd.Wait(); err != nil { - t.Fatal(err) - } - for _, exp := range expected { - if !strings.Contains(stderr.String(), exp) { - t.Errorf("expected %q, got: %s", exp, stderr.String()) - } - } -} - -func TestSkipDevicesTrue(t *testing.T) { - testSkipDevices(t, true, []string{ - "echo: write error: No space left on device", - "cat: /dev/null: Operation not permitted", - }) -} - -func TestSkipDevicesFalse(t *testing.T) { - // If SkipDevices is not set for the parent slice, access to both - // devices should fail. This is done to assess the test correctness. - // For cgroup v1, we check for m.Set returning EPERM. - // For cgroup v2, we check for the errors below. - testSkipDevices(t, false, []string{ - "/dev/full: Operation not permitted", - "cat: /dev/null: Operation not permitted", - }) -} - -func testFindDeviceGroup() error { - const ( - major = 136 - group = "char-pts" - ) - res, err := findDeviceGroup(devices.CharDevice, major) - if res != group || err != nil { - return fmt.Errorf("expected %v, nil, got %v, %w", group, res, err) - } - return nil -} - -func TestFindDeviceGroup(t *testing.T) { - if err := testFindDeviceGroup(); err != nil { - t.Fatal(err) - } -} - -func BenchmarkFindDeviceGroup(b *testing.B) { - for i := 0; i < b.N; i++ { - if err := testFindDeviceGroup(); err != nil { - b.Fatal(err) - } - } -} - -func newManager(t *testing.T, config *cgroups.Cgroup) (m cgroups.Manager) { - t.Helper() - var err error - - if cgroups.IsCgroup2UnifiedMode() { - m, err = systemd.NewUnifiedManager(config, "") - } else { - m, err = systemd.NewLegacyManager(config, nil) - } - if err != nil { - t.Fatal(err) - } - t.Cleanup(func() { _ = m.Destroy() }) - - return m -} diff --git a/libcontainer/cgroups/devices/v1_test.go b/libcontainer/cgroups/devices/v1_test.go deleted file mode 100644 index 5781169be..000000000 --- a/libcontainer/cgroups/devices/v1_test.go +++ /dev/null @@ -1,68 +0,0 @@ -package devices - -import ( - "os" - "path" - "testing" - - "github.com/moby/sys/userns" - - "github.com/opencontainers/runc/libcontainer/cgroups" - devices "github.com/opencontainers/runc/libcontainer/cgroups/devices/config" - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" -) - -func init() { - testingSkipFinalCheck = true - cgroups.TestMode = true -} - -func TestSetV1Allow(t *testing.T) { - if userns.RunningInUserNS() { - t.Skip("userns detected; setV1 does nothing") - } - dir := t.TempDir() - - for file, contents := range map[string]string{ - "devices.allow": "", - "devices.deny": "", - "devices.list": "a *:* rwm", - } { - err := os.WriteFile(path.Join(dir, file), []byte(contents), 0o600) - if err != nil { - t.Fatal(err) - } - } - - r := &cgroups.Resources{ - Devices: []*devices.Rule{ - { - Type: devices.CharDevice, - Major: 1, - Minor: 5, - Permissions: devices.Permissions("rwm"), - Allow: true, - }, - }, - } - - if err := setV1(dir, r); err != nil { - t.Fatal(err) - } - - // The default deny rule must be written. - value, err := fscommon.GetCgroupParamString(dir, "devices.deny") - if err != nil { - t.Fatal(err) - } - if value[0] != 'a' { - t.Errorf("Got the wrong value (%q), set devices.deny failed.", value) - } - - // Permitted rule must be written. - if value, err := fscommon.GetCgroupParamString(dir, "devices.allow"); err != nil { - t.Fatal(err) - } else if value != "c 1:5 rwm" { - t.Errorf("Got the wrong value (%q), set devices.allow failed.", value) - } -} diff --git a/libcontainer/cgroups/file_test.go b/libcontainer/cgroups/file_test.go deleted file mode 100644 index 3a9fac329..000000000 --- a/libcontainer/cgroups/file_test.go +++ /dev/null @@ -1,93 +0,0 @@ -package cgroups - -import ( - "errors" - "fmt" - "os" - "path/filepath" - "strconv" - "testing" - "time" -) - -func TestWriteCgroupFileHandlesInterrupt(t *testing.T) { - const ( - memoryCgroupMount = "/sys/fs/cgroup/memory" - memoryLimit = "memory.limit_in_bytes" - ) - if _, err := os.Stat(memoryCgroupMount); err != nil { - // most probably cgroupv2 - t.Skip(err) - } - - cgroupName := fmt.Sprintf("test-eint-%d", time.Now().Nanosecond()) - cgroupPath := filepath.Join(memoryCgroupMount, cgroupName) - if err := os.MkdirAll(cgroupPath, 0o755); err != nil { - t.Fatal(err) - } - defer os.RemoveAll(cgroupPath) - - if _, err := os.Stat(filepath.Join(cgroupPath, memoryLimit)); err != nil { - // either cgroupv2, or memory controller is not available - t.Skip(err) - } - - for i := 0; i < 100000; i++ { - limit := 1024*1024 + i - if err := WriteFile(cgroupPath, memoryLimit, strconv.Itoa(limit)); err != nil { - t.Fatalf("Failed to write %d on attempt %d: %+v", limit, i, err) - } - } -} - -func TestOpenat2(t *testing.T) { - if !IsCgroup2UnifiedMode() { - // The reason is many test cases below test opening files from - // the top-level directory, where cgroup v1 has no files. - t.Skip("test requires cgroup v2") - } - - // Make sure we test openat2, not its fallback. - openFallback = func(_ string, _ int, _ os.FileMode) (*os.File, error) { - return nil, errors.New("fallback") - } - defer func() { openFallback = openAndCheck }() - - for _, tc := range []struct{ dir, file string }{ - {"/sys/fs/cgroup", "cgroup.controllers"}, - {"/sys/fs/cgroup", "/cgroup.controllers"}, - {"/sys/fs/cgroup/", "cgroup.controllers"}, - {"/sys/fs/cgroup/", "/cgroup.controllers"}, - {"/", "/sys/fs/cgroup/cgroup.controllers"}, - {"/", "sys/fs/cgroup/cgroup.controllers"}, - {"/sys/fs/cgroup/cgroup.controllers", ""}, - } { - fd, err := OpenFile(tc.dir, tc.file, os.O_RDONLY) - if err != nil { - t.Errorf("case %+v: %v", tc, err) - } - fd.Close() - } -} - -func BenchmarkWriteFile(b *testing.B) { - TestMode = true - defer func() { TestMode = false }() - - dir := b.TempDir() - tc := []string{ - "one", - "one\ntwo\nthree", - "10:200 foo=bar boo=far\n300:1200 something=other\ndefault 45000\n", - "\n\n\n\n\n\n\n\n", - } - - b.ResetTimer() - for i := 0; i < b.N; i++ { - for _, val := range tc { - if err := WriteFileByLine(dir, "file", val); err != nil { - b.Fatal(err) - } - } - } -} diff --git a/libcontainer/cgroups/fs/blkio_test.go b/libcontainer/cgroups/fs/blkio_test.go deleted file mode 100644 index 3e5396569..000000000 --- a/libcontainer/cgroups/fs/blkio_test.go +++ /dev/null @@ -1,862 +0,0 @@ -package fs - -import ( - "strconv" - "testing" - - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" -) - -const ( - sectorsRecursiveContents = `8:0 1024` - sectorsRecursiveContentsBFQ = `8:0 2048` - serviceBytesRecursiveContents = `8:0 Read 100 -8:0 Write 200 -8:0 Sync 300 -8:0 Async 500 -8:0 Total 500 -Total 500` - - serviceBytesRecursiveContentsBFQ = `8:0 Read 1100 -8:0 Write 1200 -8:0 Sync 1300 -8:0 Async 1500 -8:0 Total 1500 -Total 1500` - servicedRecursiveContents = `8:0 Read 10 -8:0 Write 40 -8:0 Sync 20 -8:0 Async 30 -8:0 Total 50 -Total 50` - servicedRecursiveContentsBFQ = `8:0 Read 11 -8:0 Write 41 -8:0 Sync 21 -8:0 Async 31 -8:0 Total 51 -Total 51` - queuedRecursiveContents = `8:0 Read 1 -8:0 Write 4 -8:0 Sync 2 -8:0 Async 3 -8:0 Total 5 -Total 5` - queuedRecursiveContentsBFQ = `8:0 Read 2 -8:0 Write 3 -8:0 Sync 4 -8:0 Async 5 -8:0 Total 6 -Total 6` - serviceTimeRecursiveContents = `8:0 Read 173959 -8:0 Write 0 -8:0 Sync 0 -8:0 Async 173959 -8:0 Total 17395 -Total 17395` - serviceTimeRecursiveContentsBFQ = `8:0 Read 173959 -8:0 Write 0 -8:0 Sync 0 -8:0 Async 173 -8:0 Total 174 -Total 174` - waitTimeRecursiveContents = `8:0 Read 15571 -8:0 Write 0 -8:0 Sync 0 -8:0 Async 15571 -8:0 Total 15571` - waitTimeRecursiveContentsBFQ = `8:0 Read 1557 -8:0 Write 0 -8:0 Sync 0 -8:0 Async 1557 -8:0 Total 1557` - mergedRecursiveContents = `8:0 Read 5 -8:0 Write 10 -8:0 Sync 0 -8:0 Async 0 -8:0 Total 15 -Total 15` - mergedRecursiveContentsBFQ = `8:0 Read 51 -8:0 Write 101 -8:0 Sync 0 -8:0 Async 0 -8:0 Total 151 -Total 151` - timeRecursiveContents = `8:0 8` - timeRecursiveContentsBFQ = `8:0 16` - throttleServiceBytes = `8:0 Read 11030528 -8:0 Write 23 -8:0 Sync 42 -8:0 Async 11030528 -8:0 Total 11030528 -252:0 Read 11030528 -252:0 Write 23 -252:0 Sync 42 -252:0 Async 11030528 -252:0 Total 11030528 -Total 22061056` - throttleServiceBytesRecursive = `8:0 Read 110305281 -8:0 Write 231 -8:0 Sync 421 -8:0 Async 110305281 -8:0 Total 110305281 -252:0 Read 110305281 -252:0 Write 231 -252:0 Sync 421 -252:0 Async 110305281 -252:0 Total 110305281 -Total 220610561` - throttleServiced = `8:0 Read 164 -8:0 Write 23 -8:0 Sync 42 -8:0 Async 164 -8:0 Total 164 -252:0 Read 164 -252:0 Write 23 -252:0 Sync 42 -252:0 Async 164 -252:0 Total 164 -Total 328` - throttleServicedRecursive = `8:0 Read 1641 -8:0 Write 231 -8:0 Sync 421 -8:0 Async 1641 -8:0 Total 1641 -252:0 Read 1641 -252:0 Write 231 -252:0 Sync 421 -252:0 Async 1641 -252:0 Total 1641 -Total 3281` -) - -var blkioBFQDebugStatsTestFiles = map[string]string{ - "blkio.bfq.io_service_bytes_recursive": serviceBytesRecursiveContentsBFQ, - "blkio.bfq.io_serviced_recursive": servicedRecursiveContentsBFQ, - "blkio.bfq.io_queued_recursive": queuedRecursiveContentsBFQ, - "blkio.bfq.io_service_time_recursive": serviceTimeRecursiveContentsBFQ, - "blkio.bfq.io_wait_time_recursive": waitTimeRecursiveContentsBFQ, - "blkio.bfq.io_merged_recursive": mergedRecursiveContentsBFQ, - "blkio.bfq.time_recursive": timeRecursiveContentsBFQ, - "blkio.bfq.sectors_recursive": sectorsRecursiveContentsBFQ, -} - -var blkioBFQStatsTestFiles = map[string]string{ - "blkio.bfq.io_service_bytes_recursive": serviceBytesRecursiveContentsBFQ, - "blkio.bfq.io_serviced_recursive": servicedRecursiveContentsBFQ, -} - -var blkioCFQStatsTestFiles = map[string]string{ - "blkio.io_service_bytes_recursive": serviceBytesRecursiveContents, - "blkio.io_serviced_recursive": servicedRecursiveContents, - "blkio.io_queued_recursive": queuedRecursiveContents, - "blkio.io_service_time_recursive": serviceTimeRecursiveContents, - "blkio.io_wait_time_recursive": waitTimeRecursiveContents, - "blkio.io_merged_recursive": mergedRecursiveContents, - "blkio.time_recursive": timeRecursiveContents, - "blkio.sectors_recursive": sectorsRecursiveContents, -} - -type blkioStatFailureTestCase struct { - desc string - filename string -} - -func appendBlkioStatEntry(blkioStatEntries *[]cgroups.BlkioStatEntry, major, minor, value uint64, op string) { //nolint:unparam - *blkioStatEntries = append(*blkioStatEntries, cgroups.BlkioStatEntry{Major: major, Minor: minor, Value: value, Op: op}) -} - -func TestBlkioSetWeight(t *testing.T) { - const ( - weightBefore = 100 - weightAfter = 200 - ) - - for _, legacyIOScheduler := range []bool{false, true} { - // Populate cgroup - path := tempDir(t, "blkio") - weightFilename := "blkio.bfq.weight" - if legacyIOScheduler { - weightFilename = "blkio.weight" - } - writeFileContents(t, path, map[string]string{ - weightFilename: strconv.Itoa(weightBefore), - }) - // Apply new configuration - r := &cgroups.Resources{ - BlkioWeight: weightAfter, - } - blkio := &BlkioGroup{} - if err := blkio.Set(path, r); err != nil { - t.Fatal(err) - } - // Verify results - if weightFilename != blkio.weightFilename { - t.Fatalf("weight filename detection failed: expected %q, detected %q", weightFilename, blkio.weightFilename) - } - value, err := fscommon.GetCgroupParamUint(path, weightFilename) - if err != nil { - t.Fatal(err) - } - if value != weightAfter { - t.Fatalf("Got the wrong value, set %s failed.", weightFilename) - } - } -} - -func TestBlkioSetWeightDevice(t *testing.T) { - const ( - weightDeviceBefore = "8:0 400" - ) - - for _, legacyIOScheduler := range []bool{false, true} { - // Populate cgroup - path := tempDir(t, "blkio") - weightFilename := "blkio.bfq.weight" - weightDeviceFilename := "blkio.bfq.weight_device" - if legacyIOScheduler { - weightFilename = "blkio.weight" - weightDeviceFilename = "blkio.weight_device" - } - writeFileContents(t, path, map[string]string{ - weightFilename: "", - weightDeviceFilename: weightDeviceBefore, - }) - // Apply new configuration - wd := cgroups.NewWeightDevice(8, 0, 500, 0) - weightDeviceAfter := wd.WeightString() - r := &cgroups.Resources{ - BlkioWeightDevice: []*cgroups.WeightDevice{wd}, - } - blkio := &BlkioGroup{} - if err := blkio.Set(path, r); err != nil { - t.Fatal(err) - } - // Verify results - if weightDeviceFilename != blkio.weightDeviceFilename { - t.Fatalf("weight_device filename detection failed: expected %q, detected %q", weightDeviceFilename, blkio.weightDeviceFilename) - } - value, err := fscommon.GetCgroupParamString(path, weightDeviceFilename) - if err != nil { - t.Fatal(err) - } - if value != weightDeviceAfter { - t.Fatalf("Got the wrong value, set %s failed.", weightDeviceFilename) - } - } -} - -// regression #274 -func TestBlkioSetMultipleWeightDevice(t *testing.T) { - path := tempDir(t, "blkio") - - const ( - weightDeviceBefore = "8:0 400" - ) - - wd1 := cgroups.NewWeightDevice(8, 0, 500, 0) - wd2 := cgroups.NewWeightDevice(8, 16, 500, 0) - // we cannot actually set and check both because normal os.WriteFile - // when writing to cgroup file will overwrite the whole file content instead - // of updating it as the kernel is doing. Just check the second device - // is present will suffice for the test to ensure multiple writes are done. - weightDeviceAfter := wd2.WeightString() - - blkio := &BlkioGroup{} - blkio.detectWeightFilenames(path) - if blkio.weightDeviceFilename != "blkio.bfq.weight_device" { - t.Fatalf("when blkio controller is unavailable, expected to use \"blkio.bfq.weight_device\", tried to use %q", blkio.weightDeviceFilename) - } - writeFileContents(t, path, map[string]string{ - blkio.weightDeviceFilename: weightDeviceBefore, - }) - - r := &cgroups.Resources{ - BlkioWeightDevice: []*cgroups.WeightDevice{wd1, wd2}, - } - if err := blkio.Set(path, r); err != nil { - t.Fatal(err) - } - - value, err := fscommon.GetCgroupParamString(path, blkio.weightDeviceFilename) - if err != nil { - t.Fatal(err) - } - if value != weightDeviceAfter { - t.Fatalf("Got the wrong value, set %s failed.", blkio.weightDeviceFilename) - } -} - -func TestBlkioBFQDebugStats(t *testing.T) { - path := tempDir(t, "blkio") - writeFileContents(t, path, blkioBFQDebugStatsTestFiles) - blkio := &BlkioGroup{} - actualStats := *cgroups.NewStats() - err := blkio.GetStats(path, &actualStats) - if err != nil { - t.Fatal(err) - } - - expectedStats := cgroups.BlkioStats{} - appendBlkioStatEntry(&expectedStats.SectorsRecursive, 8, 0, 2048, "") - - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 1100, "Read") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 1200, "Write") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 1300, "Sync") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 1500, "Async") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 1500, "Total") - - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 11, "Read") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 41, "Write") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 21, "Sync") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 31, "Async") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 51, "Total") - - appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 2, "Read") - appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 3, "Write") - appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 4, "Sync") - appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 5, "Async") - appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 6, "Total") - - appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 173959, "Read") - appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 0, "Write") - appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 0, "Sync") - appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 173, "Async") - appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 174, "Total") - - appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 1557, "Read") - appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 0, "Write") - appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 0, "Sync") - appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 1557, "Async") - appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 1557, "Total") - - appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 51, "Read") - appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 101, "Write") - appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 0, "Sync") - appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 0, "Async") - appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 151, "Total") - - appendBlkioStatEntry(&expectedStats.IoTimeRecursive, 8, 0, 16, "") - - expectBlkioStatsEquals(t, expectedStats, actualStats.BlkioStats) -} - -func TestBlkioMultipleStatsFiles(t *testing.T) { - path := tempDir(t, "blkio") - writeFileContents(t, path, blkioBFQDebugStatsTestFiles) - writeFileContents(t, path, blkioCFQStatsTestFiles) - blkio := &BlkioGroup{} - actualStats := *cgroups.NewStats() - err := blkio.GetStats(path, &actualStats) - if err != nil { - t.Fatal(err) - } - - expectedStats := cgroups.BlkioStats{} - appendBlkioStatEntry(&expectedStats.SectorsRecursive, 8, 0, 2048, "") - - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 1100, "Read") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 1200, "Write") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 1300, "Sync") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 1500, "Async") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 1500, "Total") - - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 11, "Read") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 41, "Write") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 21, "Sync") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 31, "Async") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 51, "Total") - - appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 2, "Read") - appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 3, "Write") - appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 4, "Sync") - appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 5, "Async") - appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 6, "Total") - - appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 173959, "Read") - appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 0, "Write") - appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 0, "Sync") - appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 173, "Async") - appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 174, "Total") - - appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 1557, "Read") - appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 0, "Write") - appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 0, "Sync") - appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 1557, "Async") - appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 1557, "Total") - - appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 51, "Read") - appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 101, "Write") - appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 0, "Sync") - appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 0, "Async") - appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 151, "Total") - - appendBlkioStatEntry(&expectedStats.IoTimeRecursive, 8, 0, 16, "") - - expectBlkioStatsEquals(t, expectedStats, actualStats.BlkioStats) -} - -func TestBlkioBFQStats(t *testing.T) { - path := tempDir(t, "blkio") - writeFileContents(t, path, blkioBFQStatsTestFiles) - blkio := &BlkioGroup{} - actualStats := *cgroups.NewStats() - err := blkio.GetStats(path, &actualStats) - if err != nil { - t.Fatal(err) - } - - expectedStats := cgroups.BlkioStats{} - - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 1100, "Read") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 1200, "Write") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 1300, "Sync") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 1500, "Async") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 1500, "Total") - - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 11, "Read") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 41, "Write") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 21, "Sync") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 31, "Async") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 51, "Total") - - expectBlkioStatsEquals(t, expectedStats, actualStats.BlkioStats) -} - -func TestBlkioStatsNoFilesBFQDebug(t *testing.T) { - if testing.Short() { - t.Skip("skipping test in short mode.") - } - testCases := []blkioStatFailureTestCase{ - { - desc: "missing blkio.bfq.io_service_bytes_recursive file", - filename: "blkio.bfq.io_service_bytes_recursive", - }, - { - desc: "missing blkio.bfq.io_serviced_recursive file", - filename: "blkio.bfq.io_serviced_recursive", - }, - { - desc: "missing blkio.bfq.io_queued_recursive file", - filename: "blkio.bfq.io_queued_recursive", - }, - { - desc: "missing blkio.bfq.sectors_recursive file", - filename: "blkio.bfq.sectors_recursive", - }, - { - desc: "missing blkio.bfq.io_service_time_recursive file", - filename: "blkio.bfq.io_service_time_recursive", - }, - { - desc: "missing blkio.bfq.io_wait_time_recursive file", - filename: "blkio.bfq.io_wait_time_recursive", - }, - { - desc: "missing blkio.bfq.io_merged_recursive file", - filename: "blkio.bfq.io_merged_recursive", - }, - { - desc: "missing blkio.bfq.time_recursive file", - filename: "blkio.bfq.time_recursive", - }, - } - - for _, testCase := range testCases { - path := tempDir(t, "cpuset") - - tempBlkioTestFiles := map[string]string{} - for i, v := range blkioBFQDebugStatsTestFiles { - tempBlkioTestFiles[i] = v - } - delete(tempBlkioTestFiles, testCase.filename) - - writeFileContents(t, path, tempBlkioTestFiles) - cpuset := &CpusetGroup{} - actualStats := *cgroups.NewStats() - err := cpuset.GetStats(path, &actualStats) - if err != nil { - t.Errorf("%s: want no error, got: %+v", testCase.desc, err) - } - } -} - -func TestBlkioCFQStats(t *testing.T) { - path := tempDir(t, "blkio") - writeFileContents(t, path, blkioCFQStatsTestFiles) - - blkio := &BlkioGroup{} - actualStats := *cgroups.NewStats() - err := blkio.GetStats(path, &actualStats) - if err != nil { - t.Fatal(err) - } - - // Verify expected stats. - expectedStats := cgroups.BlkioStats{} - appendBlkioStatEntry(&expectedStats.SectorsRecursive, 8, 0, 1024, "") - - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 100, "Read") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 200, "Write") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 300, "Sync") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 500, "Async") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 500, "Total") - - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 10, "Read") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 40, "Write") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 20, "Sync") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 30, "Async") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 50, "Total") - - appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 1, "Read") - appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 4, "Write") - appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 2, "Sync") - appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 3, "Async") - appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 5, "Total") - - appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 173959, "Read") - appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 0, "Write") - appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 0, "Sync") - appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 173959, "Async") - appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 17395, "Total") - - appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 15571, "Read") - appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 0, "Write") - appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 0, "Sync") - appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 15571, "Async") - appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 15571, "Total") - - appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 5, "Read") - appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 10, "Write") - appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 0, "Sync") - appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 0, "Async") - appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 15, "Total") - - appendBlkioStatEntry(&expectedStats.IoTimeRecursive, 8, 0, 8, "") - - expectBlkioStatsEquals(t, expectedStats, actualStats.BlkioStats) -} - -func TestBlkioStatsNoFilesCFQ(t *testing.T) { - if testing.Short() { - t.Skip("skipping test in short mode.") - } - testCases := []blkioStatFailureTestCase{ - { - desc: "missing blkio.io_service_bytes_recursive file", - filename: "blkio.io_service_bytes_recursive", - }, - { - desc: "missing blkio.io_serviced_recursive file", - filename: "blkio.io_serviced_recursive", - }, - { - desc: "missing blkio.io_queued_recursive file", - filename: "blkio.io_queued_recursive", - }, - { - desc: "missing blkio.sectors_recursive file", - filename: "blkio.sectors_recursive", - }, - { - desc: "missing blkio.io_service_time_recursive file", - filename: "blkio.io_service_time_recursive", - }, - { - desc: "missing blkio.io_wait_time_recursive file", - filename: "blkio.io_wait_time_recursive", - }, - { - desc: "missing blkio.io_merged_recursive file", - filename: "blkio.io_merged_recursive", - }, - { - desc: "missing blkio.time_recursive file", - filename: "blkio.time_recursive", - }, - } - - for _, testCase := range testCases { - path := tempDir(t, "cpuset") - - tempBlkioTestFiles := map[string]string{} - for i, v := range blkioCFQStatsTestFiles { - tempBlkioTestFiles[i] = v - } - delete(tempBlkioTestFiles, testCase.filename) - - writeFileContents(t, path, tempBlkioTestFiles) - cpuset := &CpusetGroup{} - actualStats := *cgroups.NewStats() - err := cpuset.GetStats(path, &actualStats) - if err != nil { - t.Errorf("%s: want no error, got %+v", testCase.desc, err) - } - } -} - -func TestBlkioStatsUnexpectedNumberOfFields(t *testing.T) { - path := tempDir(t, "blkio") - writeFileContents(t, path, map[string]string{ - "blkio.io_service_bytes_recursive": "8:0 Read 100 100", - "blkio.io_serviced_recursive": servicedRecursiveContents, - "blkio.io_queued_recursive": queuedRecursiveContents, - "blkio.sectors_recursive": sectorsRecursiveContents, - "blkio.io_service_time_recursive": serviceTimeRecursiveContents, - "blkio.io_wait_time_recursive": waitTimeRecursiveContents, - "blkio.io_merged_recursive": mergedRecursiveContents, - "blkio.time_recursive": timeRecursiveContents, - }) - - blkio := &BlkioGroup{} - actualStats := *cgroups.NewStats() - err := blkio.GetStats(path, &actualStats) - if err == nil { - t.Fatal("Expected to fail, but did not") - } -} - -func TestBlkioStatsUnexpectedFieldType(t *testing.T) { - path := tempDir(t, "blkio") - writeFileContents(t, path, map[string]string{ - "blkio.io_service_bytes_recursive": "8:0 Read Write", - "blkio.io_serviced_recursive": servicedRecursiveContents, - "blkio.io_queued_recursive": queuedRecursiveContents, - "blkio.sectors_recursive": sectorsRecursiveContents, - "blkio.io_service_time_recursive": serviceTimeRecursiveContents, - "blkio.io_wait_time_recursive": waitTimeRecursiveContents, - "blkio.io_merged_recursive": mergedRecursiveContents, - "blkio.time_recursive": timeRecursiveContents, - }) - - blkio := &BlkioGroup{} - actualStats := *cgroups.NewStats() - err := blkio.GetStats(path, &actualStats) - if err == nil { - t.Fatal("Expected to fail, but did not") - } -} - -func TestThrottleRecursiveBlkioStats(t *testing.T) { - path := tempDir(t, "blkio") - writeFileContents(t, path, map[string]string{ - "blkio.io_service_bytes_recursive": "", - "blkio.io_serviced_recursive": "", - "blkio.io_queued_recursive": "", - "blkio.sectors_recursive": "", - "blkio.io_service_time_recursive": "", - "blkio.io_wait_time_recursive": "", - "blkio.io_merged_recursive": "", - "blkio.time_recursive": "", - "blkio.throttle.io_service_bytes_recursive": throttleServiceBytesRecursive, - "blkio.throttle.io_serviced_recursive": throttleServicedRecursive, - }) - - blkio := &BlkioGroup{} - actualStats := *cgroups.NewStats() - err := blkio.GetStats(path, &actualStats) - if err != nil { - t.Fatal(err) - } - - // Verify expected stats. - expectedStats := cgroups.BlkioStats{} - - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 110305281, "Read") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 231, "Write") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 421, "Sync") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 110305281, "Async") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 110305281, "Total") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 110305281, "Read") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 231, "Write") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 421, "Sync") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 110305281, "Async") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 110305281, "Total") - - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 1641, "Read") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 231, "Write") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 421, "Sync") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 1641, "Async") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 1641, "Total") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 1641, "Read") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 231, "Write") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 421, "Sync") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 1641, "Async") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 1641, "Total") - - expectBlkioStatsEquals(t, expectedStats, actualStats.BlkioStats) -} - -func TestThrottleBlkioStats(t *testing.T) { - path := tempDir(t, "blkio") - writeFileContents(t, path, map[string]string{ - "blkio.io_service_bytes_recursive": "", - "blkio.io_serviced_recursive": "", - "blkio.io_queued_recursive": "", - "blkio.sectors_recursive": "", - "blkio.io_service_time_recursive": "", - "blkio.io_wait_time_recursive": "", - "blkio.io_merged_recursive": "", - "blkio.time_recursive": "", - "blkio.throttle.io_service_bytes": throttleServiceBytes, - "blkio.throttle.io_serviced": throttleServiced, - }) - - blkio := &BlkioGroup{} - actualStats := *cgroups.NewStats() - err := blkio.GetStats(path, &actualStats) - if err != nil { - t.Fatal(err) - } - - // Verify expected stats. - expectedStats := cgroups.BlkioStats{} - - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 11030528, "Read") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 23, "Write") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 42, "Sync") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 11030528, "Async") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 11030528, "Total") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 11030528, "Read") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 23, "Write") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 42, "Sync") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 11030528, "Async") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 11030528, "Total") - - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 164, "Read") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 23, "Write") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 42, "Sync") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 164, "Async") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 164, "Total") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 164, "Read") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 23, "Write") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 42, "Sync") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 164, "Async") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 164, "Total") - - expectBlkioStatsEquals(t, expectedStats, actualStats.BlkioStats) -} - -func TestBlkioSetThrottleReadBpsDevice(t *testing.T) { - path := tempDir(t, "blkio") - - const ( - throttleBefore = `8:0 1024` - ) - - td := cgroups.NewThrottleDevice(8, 0, 2048) - throttleAfter := td.String() - - writeFileContents(t, path, map[string]string{ - "blkio.throttle.read_bps_device": throttleBefore, - }) - - r := &cgroups.Resources{ - BlkioThrottleReadBpsDevice: []*cgroups.ThrottleDevice{td}, - } - blkio := &BlkioGroup{} - if err := blkio.Set(path, r); err != nil { - t.Fatal(err) - } - - value, err := fscommon.GetCgroupParamString(path, "blkio.throttle.read_bps_device") - if err != nil { - t.Fatal(err) - } - if value != throttleAfter { - t.Fatal("Got the wrong value, set blkio.throttle.read_bps_device failed.") - } -} - -func TestBlkioSetThrottleWriteBpsDevice(t *testing.T) { - path := tempDir(t, "blkio") - - const ( - throttleBefore = `8:0 1024` - ) - - td := cgroups.NewThrottleDevice(8, 0, 2048) - throttleAfter := td.String() - - writeFileContents(t, path, map[string]string{ - "blkio.throttle.write_bps_device": throttleBefore, - }) - - r := &cgroups.Resources{ - BlkioThrottleWriteBpsDevice: []*cgroups.ThrottleDevice{td}, - } - blkio := &BlkioGroup{} - if err := blkio.Set(path, r); err != nil { - t.Fatal(err) - } - - value, err := fscommon.GetCgroupParamString(path, "blkio.throttle.write_bps_device") - if err != nil { - t.Fatal(err) - } - if value != throttleAfter { - t.Fatal("Got the wrong value, set blkio.throttle.write_bps_device failed.") - } -} - -func TestBlkioSetThrottleReadIOpsDevice(t *testing.T) { - path := tempDir(t, "blkio") - - const ( - throttleBefore = `8:0 1024` - ) - - td := cgroups.NewThrottleDevice(8, 0, 2048) - throttleAfter := td.String() - - writeFileContents(t, path, map[string]string{ - "blkio.throttle.read_iops_device": throttleBefore, - }) - - r := &cgroups.Resources{ - BlkioThrottleReadIOPSDevice: []*cgroups.ThrottleDevice{td}, - } - blkio := &BlkioGroup{} - if err := blkio.Set(path, r); err != nil { - t.Fatal(err) - } - - value, err := fscommon.GetCgroupParamString(path, "blkio.throttle.read_iops_device") - if err != nil { - t.Fatal(err) - } - if value != throttleAfter { - t.Fatal("Got the wrong value, set blkio.throttle.read_iops_device failed.") - } -} - -func TestBlkioSetThrottleWriteIOpsDevice(t *testing.T) { - path := tempDir(t, "blkio") - - const ( - throttleBefore = `8:0 1024` - ) - - td := cgroups.NewThrottleDevice(8, 0, 2048) - throttleAfter := td.String() - - writeFileContents(t, path, map[string]string{ - "blkio.throttle.write_iops_device": throttleBefore, - }) - - r := &cgroups.Resources{ - BlkioThrottleWriteIOPSDevice: []*cgroups.ThrottleDevice{td}, - } - blkio := &BlkioGroup{} - if err := blkio.Set(path, r); err != nil { - t.Fatal(err) - } - - value, err := fscommon.GetCgroupParamString(path, "blkio.throttle.write_iops_device") - if err != nil { - t.Fatal(err) - } - if value != throttleAfter { - t.Fatal("Got the wrong value, set blkio.throttle.write_iops_device failed.") - } -} diff --git a/libcontainer/cgroups/fs/cpu_test.go b/libcontainer/cgroups/fs/cpu_test.go deleted file mode 100644 index 34b98f543..000000000 --- a/libcontainer/cgroups/fs/cpu_test.go +++ /dev/null @@ -1,226 +0,0 @@ -package fs - -import ( - "fmt" - "strconv" - "testing" - - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" -) - -func TestCpuSetShares(t *testing.T) { - path := tempDir(t, "cpu") - - const ( - sharesBefore = 1024 - sharesAfter = 512 - ) - - writeFileContents(t, path, map[string]string{ - "cpu.shares": strconv.Itoa(sharesBefore), - }) - - r := &cgroups.Resources{ - CpuShares: sharesAfter, - } - cpu := &CpuGroup{} - if err := cpu.Set(path, r); err != nil { - t.Fatal(err) - } - - value, err := fscommon.GetCgroupParamUint(path, "cpu.shares") - if err != nil { - t.Fatal(err) - } - if value != sharesAfter { - t.Fatal("Got the wrong value, set cpu.shares failed.") - } -} - -func TestCpuSetBandWidth(t *testing.T) { - path := tempDir(t, "cpu") - - const ( - quotaBefore = 8000 - quotaAfter = 5000 - burstBefore = 2000 - periodBefore = 10000 - periodAfter = 7000 - rtRuntimeBefore = 8000 - rtRuntimeAfter = 5000 - rtPeriodBefore = 10000 - rtPeriodAfter = 7000 - ) - burstAfter := uint64(1000) - - writeFileContents(t, path, map[string]string{ - "cpu.cfs_quota_us": strconv.Itoa(quotaBefore), - "cpu.cfs_burst_us": strconv.Itoa(burstBefore), - "cpu.cfs_period_us": strconv.Itoa(periodBefore), - "cpu.rt_runtime_us": strconv.Itoa(rtRuntimeBefore), - "cpu.rt_period_us": strconv.Itoa(rtPeriodBefore), - }) - - r := &cgroups.Resources{ - CpuQuota: quotaAfter, - CpuBurst: &burstAfter, - CpuPeriod: periodAfter, - CpuRtRuntime: rtRuntimeAfter, - CpuRtPeriod: rtPeriodAfter, - } - cpu := &CpuGroup{} - if err := cpu.Set(path, r); err != nil { - t.Fatal(err) - } - - quota, err := fscommon.GetCgroupParamUint(path, "cpu.cfs_quota_us") - if err != nil { - t.Fatal(err) - } - if quota != quotaAfter { - t.Fatal("Got the wrong value, set cpu.cfs_quota_us failed.") - } - - burst, err := fscommon.GetCgroupParamUint(path, "cpu.cfs_burst_us") - if err != nil { - t.Fatal(err) - } - if burst != burstAfter { - t.Fatal("Got the wrong value, set cpu.cfs_burst_us failed.") - } - - period, err := fscommon.GetCgroupParamUint(path, "cpu.cfs_period_us") - if err != nil { - t.Fatal(err) - } - if period != periodAfter { - t.Fatal("Got the wrong value, set cpu.cfs_period_us failed.") - } - - rtRuntime, err := fscommon.GetCgroupParamUint(path, "cpu.rt_runtime_us") - if err != nil { - t.Fatal(err) - } - if rtRuntime != rtRuntimeAfter { - t.Fatal("Got the wrong value, set cpu.rt_runtime_us failed.") - } - - rtPeriod, err := fscommon.GetCgroupParamUint(path, "cpu.rt_period_us") - if err != nil { - t.Fatal(err) - } - if rtPeriod != rtPeriodAfter { - t.Fatal("Got the wrong value, set cpu.rt_period_us failed.") - } -} - -func TestCpuStats(t *testing.T) { - path := tempDir(t, "cpu") - - const ( - nrPeriods = 2000 - nrThrottled = 200 - throttledTime = uint64(18446744073709551615) - ) - - cpuStatContent := fmt.Sprintf("nr_periods %d\nnr_throttled %d\nthrottled_time %d\n", - nrPeriods, nrThrottled, throttledTime) - writeFileContents(t, path, map[string]string{ - "cpu.stat": cpuStatContent, - }) - - cpu := &CpuGroup{} - actualStats := *cgroups.NewStats() - err := cpu.GetStats(path, &actualStats) - if err != nil { - t.Fatal(err) - } - - expectedStats := cgroups.ThrottlingData{ - Periods: nrPeriods, - ThrottledPeriods: nrThrottled, - ThrottledTime: throttledTime, - } - - expectThrottlingDataEquals(t, expectedStats, actualStats.CpuStats.ThrottlingData) -} - -func TestNoCpuStatFile(t *testing.T) { - path := tempDir(t, "cpu") - - cpu := &CpuGroup{} - actualStats := *cgroups.NewStats() - err := cpu.GetStats(path, &actualStats) - if err != nil { - t.Fatal("Expected not to fail, but did") - } -} - -func TestInvalidCpuStat(t *testing.T) { - path := tempDir(t, "cpu") - - cpuStatContent := `nr_periods 2000 - nr_throttled 200 - throttled_time fortytwo` - writeFileContents(t, path, map[string]string{ - "cpu.stat": cpuStatContent, - }) - - cpu := &CpuGroup{} - actualStats := *cgroups.NewStats() - err := cpu.GetStats(path, &actualStats) - if err == nil { - t.Fatal("Expected failed stat parsing.") - } -} - -func TestCpuSetRtSchedAtApply(t *testing.T) { - path := tempDir(t, "cpu") - - const ( - rtRuntimeBefore = 0 - rtRuntimeAfter = 5000 - rtPeriodBefore = 0 - rtPeriodAfter = 7000 - ) - - writeFileContents(t, path, map[string]string{ - "cpu.rt_runtime_us": strconv.Itoa(rtRuntimeBefore), - "cpu.rt_period_us": strconv.Itoa(rtPeriodBefore), - }) - - r := &cgroups.Resources{ - CpuRtRuntime: rtRuntimeAfter, - CpuRtPeriod: rtPeriodAfter, - } - cpu := &CpuGroup{} - - if err := cpu.Apply(path, r, 1234); err != nil { - t.Fatal(err) - } - - rtRuntime, err := fscommon.GetCgroupParamUint(path, "cpu.rt_runtime_us") - if err != nil { - t.Fatal(err) - } - if rtRuntime != rtRuntimeAfter { - t.Fatal("Got the wrong value, set cpu.rt_runtime_us failed.") - } - - rtPeriod, err := fscommon.GetCgroupParamUint(path, "cpu.rt_period_us") - if err != nil { - t.Fatal(err) - } - if rtPeriod != rtPeriodAfter { - t.Fatal("Got the wrong value, set cpu.rt_period_us failed.") - } - - pid, err := fscommon.GetCgroupParamUint(path, "cgroup.procs") - if err != nil { - t.Fatal(err) - } - if pid != 1234 { - t.Fatal("Got the wrong value, set cgroup.procs failed.") - } -} diff --git a/libcontainer/cgroups/fs/cpuacct_test.go b/libcontainer/cgroups/fs/cpuacct_test.go deleted file mode 100644 index 116454e48..000000000 --- a/libcontainer/cgroups/fs/cpuacct_test.go +++ /dev/null @@ -1,112 +0,0 @@ -package fs - -import ( - "reflect" - "testing" - - "github.com/opencontainers/runc/libcontainer/cgroups" -) - -const ( - cpuAcctUsageContents = "12262454190222160" - cpuAcctUsagePerCPUContents = "1564936537989058 1583937096487821 1604195415465681 1596445226820187 1481069084155629 1478735613864327 1477610593414743 1476362015778086" - cpuAcctStatContents = "user 452278264\nsystem 291429664" - cpuAcctUsageAll = `cpu user system - 0 962250696038415 637727786389114 - 1 981956408513304 638197595421064 - 2 1002658817529022 638956774598358 - 3 994937703492523 637985531181620 - 4 874843781648690 638837766495476 - 5 872544369885276 638763309884944 - 6 870104915696359 640081778921247 - 7 870202363887496 638716766259495 - ` -) - -func TestCpuacctStats(t *testing.T) { - path := tempDir(t, "cpuacct") - writeFileContents(t, path, map[string]string{ - "cpuacct.usage": cpuAcctUsageContents, - "cpuacct.usage_percpu": cpuAcctUsagePerCPUContents, - "cpuacct.stat": cpuAcctStatContents, - "cpuacct.usage_all": cpuAcctUsageAll, - }) - - cpuacct := &CpuacctGroup{} - actualStats := *cgroups.NewStats() - err := cpuacct.GetStats(path, &actualStats) - if err != nil { - t.Fatal(err) - } - - expectedStats := cgroups.CpuUsage{ - TotalUsage: uint64(12262454190222160), - PercpuUsage: []uint64{ - 1564936537989058, 1583937096487821, 1604195415465681, 1596445226820187, - 1481069084155629, 1478735613864327, 1477610593414743, 1476362015778086, - }, - PercpuUsageInKernelmode: []uint64{ - 637727786389114, 638197595421064, 638956774598358, 637985531181620, - 638837766495476, 638763309884944, 640081778921247, 638716766259495, - }, - PercpuUsageInUsermode: []uint64{ - 962250696038415, 981956408513304, 1002658817529022, 994937703492523, - 874843781648690, 872544369885276, 870104915696359, 870202363887496, - }, - UsageInKernelmode: (uint64(291429664) * nsInSec) / clockTicks, - UsageInUsermode: (uint64(452278264) * nsInSec) / clockTicks, - } - - if !reflect.DeepEqual(expectedStats, actualStats.CpuStats.CpuUsage) { - t.Errorf("Expected CPU usage %#v but found %#v\n", - expectedStats, actualStats.CpuStats.CpuUsage) - } -} - -func TestCpuacctStatsWithoutUsageAll(t *testing.T) { - path := tempDir(t, "cpuacct") - writeFileContents(t, path, map[string]string{ - "cpuacct.usage": cpuAcctUsageContents, - "cpuacct.usage_percpu": cpuAcctUsagePerCPUContents, - "cpuacct.stat": cpuAcctStatContents, - }) - - cpuacct := &CpuacctGroup{} - actualStats := *cgroups.NewStats() - err := cpuacct.GetStats(path, &actualStats) - if err != nil { - t.Fatal(err) - } - - expectedStats := cgroups.CpuUsage{ - TotalUsage: uint64(12262454190222160), - PercpuUsage: []uint64{ - 1564936537989058, 1583937096487821, 1604195415465681, 1596445226820187, - 1481069084155629, 1478735613864327, 1477610593414743, 1476362015778086, - }, - PercpuUsageInKernelmode: []uint64{}, - PercpuUsageInUsermode: []uint64{}, - UsageInKernelmode: (uint64(291429664) * nsInSec) / clockTicks, - UsageInUsermode: (uint64(452278264) * nsInSec) / clockTicks, - } - - if !reflect.DeepEqual(expectedStats, actualStats.CpuStats.CpuUsage) { - t.Errorf("Expected CPU usage %#v but found %#v\n", - expectedStats, actualStats.CpuStats.CpuUsage) - } -} - -func BenchmarkGetCpuUsageBreakdown(b *testing.B) { - path := tempDir(b, "cpuacct") - writeFileContents(b, path, map[string]string{ - "cpuacct.stat": cpuAcctStatContents, - }) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, _, err := getCpuUsageBreakdown(path) - if err != nil { - b.Fatal(err) - } - } -} diff --git a/libcontainer/cgroups/fs/cpuset_test.go b/libcontainer/cgroups/fs/cpuset_test.go deleted file mode 100644 index ec1c86ca6..000000000 --- a/libcontainer/cgroups/fs/cpuset_test.go +++ /dev/null @@ -1,241 +0,0 @@ -package fs - -import ( - "reflect" - "testing" - - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" -) - -const ( - cpus = "0-2,7,12-14\n" - cpuExclusive = "1\n" - mems = "1-4,6,9\n" - memHardwall = "0\n" - memExclusive = "0\n" - memoryMigrate = "1\n" - memorySpreadPage = "0\n" - memorySpeadSlab = "1\n" - memoryPressure = "34377\n" - schedLoadBalance = "1\n" - schedRelaxDomainLevel = "-1\n" -) - -var cpusetTestFiles = map[string]string{ - "cpuset.cpus": cpus, - "cpuset.cpu_exclusive": cpuExclusive, - "cpuset.mems": mems, - "cpuset.mem_hardwall": memHardwall, - "cpuset.mem_exclusive": memExclusive, - "cpuset.memory_migrate": memoryMigrate, - "cpuset.memory_spread_page": memorySpreadPage, - "cpuset.memory_spread_slab": memorySpeadSlab, - "cpuset.memory_pressure": memoryPressure, - "cpuset.sched_load_balance": schedLoadBalance, - "cpuset.sched_relax_domain_level": schedRelaxDomainLevel, -} - -func TestCPUSetSetCpus(t *testing.T) { - path := tempDir(t, "cpuset") - - const ( - cpusBefore = "0" - cpusAfter = "1-3" - ) - - writeFileContents(t, path, map[string]string{ - "cpuset.cpus": cpusBefore, - }) - - r := &cgroups.Resources{ - CpusetCpus: cpusAfter, - } - cpuset := &CpusetGroup{} - if err := cpuset.Set(path, r); err != nil { - t.Fatal(err) - } - - value, err := fscommon.GetCgroupParamString(path, "cpuset.cpus") - if err != nil { - t.Fatal(err) - } - if value != cpusAfter { - t.Fatal("Got the wrong value, set cpuset.cpus failed.") - } -} - -func TestCPUSetSetMems(t *testing.T) { - path := tempDir(t, "cpuset") - - const ( - memsBefore = "0" - memsAfter = "1" - ) - - writeFileContents(t, path, map[string]string{ - "cpuset.mems": memsBefore, - }) - - r := &cgroups.Resources{ - CpusetMems: memsAfter, - } - cpuset := &CpusetGroup{} - if err := cpuset.Set(path, r); err != nil { - t.Fatal(err) - } - - value, err := fscommon.GetCgroupParamString(path, "cpuset.mems") - if err != nil { - t.Fatal(err) - } - if value != memsAfter { - t.Fatal("Got the wrong value, set cpuset.mems failed.") - } -} - -func TestCPUSetStatsCorrect(t *testing.T) { - path := tempDir(t, "cpuset") - writeFileContents(t, path, cpusetTestFiles) - - cpuset := &CpusetGroup{} - actualStats := *cgroups.NewStats() - err := cpuset.GetStats(path, &actualStats) - if err != nil { - t.Fatal(err) - } - expectedStats := cgroups.CPUSetStats{ - CPUs: []uint16{0, 1, 2, 7, 12, 13, 14}, - CPUExclusive: 1, - Mems: []uint16{1, 2, 3, 4, 6, 9}, - MemoryMigrate: 1, - MemHardwall: 0, - MemExclusive: 0, - MemorySpreadPage: 0, - MemorySpreadSlab: 1, - MemoryPressure: 34377, - SchedLoadBalance: 1, - SchedRelaxDomainLevel: -1, - } - if !reflect.DeepEqual(expectedStats, actualStats.CPUSetStats) { - t.Fatalf("Expected Cpuset stats usage %#v but found %#v", - expectedStats, actualStats.CPUSetStats) - } -} - -func TestCPUSetStatsMissingFiles(t *testing.T) { - for _, testCase := range []struct { - desc string - filename, contents string - removeFile bool - }{ - { - desc: "empty cpus file", - filename: "cpuset.cpus", - contents: "", - removeFile: false, - }, - { - desc: "empty mems file", - filename: "cpuset.mems", - contents: "", - removeFile: false, - }, - { - desc: "corrupted cpus file", - filename: "cpuset.cpus", - contents: "0-3,*4^2", - removeFile: false, - }, - { - desc: "corrupted mems file", - filename: "cpuset.mems", - contents: "0,1,2-5,8-7", - removeFile: false, - }, - { - desc: "missing cpu_exclusive file", - filename: "cpuset.cpu_exclusive", - contents: "", - removeFile: true, - }, - { - desc: "missing memory_migrate file", - filename: "cpuset.memory_migrate", - contents: "", - removeFile: true, - }, - { - desc: "missing mem_hardwall file", - filename: "cpuset.mem_hardwall", - contents: "", - removeFile: true, - }, - { - desc: "missing mem_exclusive file", - filename: "cpuset.mem_exclusive", - contents: "", - removeFile: true, - }, - { - desc: "missing memory_spread_page file", - filename: "cpuset.memory_spread_page", - contents: "", - removeFile: true, - }, - { - desc: "missing memory_spread_slab file", - filename: "cpuset.memory_spread_slab", - contents: "", - removeFile: true, - }, - { - desc: "missing memory_pressure file", - filename: "cpuset.memory_pressure", - contents: "", - removeFile: true, - }, - { - desc: "missing sched_load_balance file", - filename: "cpuset.sched_load_balance", - contents: "", - removeFile: true, - }, - { - desc: "missing sched_relax_domain_level file", - filename: "cpuset.sched_relax_domain_level", - contents: "", - removeFile: true, - }, - } { - t.Run(testCase.desc, func(t *testing.T) { - path := tempDir(t, "cpuset") - - tempCpusetTestFiles := map[string]string{} - for i, v := range cpusetTestFiles { - tempCpusetTestFiles[i] = v - } - - if testCase.removeFile { - delete(tempCpusetTestFiles, testCase.filename) - writeFileContents(t, path, tempCpusetTestFiles) - cpuset := &CpusetGroup{} - actualStats := *cgroups.NewStats() - err := cpuset.GetStats(path, &actualStats) - if err != nil { - t.Errorf("failed unexpectedly: %q", err) - } - } else { - tempCpusetTestFiles[testCase.filename] = testCase.contents - writeFileContents(t, path, tempCpusetTestFiles) - cpuset := &CpusetGroup{} - actualStats := *cgroups.NewStats() - err := cpuset.GetStats(path, &actualStats) - - if err == nil { - t.Error("failed to return expected error") - } - } - }) - } -} diff --git a/libcontainer/cgroups/fs/freezer_test.go b/libcontainer/cgroups/fs/freezer_test.go deleted file mode 100644 index d90538084..000000000 --- a/libcontainer/cgroups/fs/freezer_test.go +++ /dev/null @@ -1,46 +0,0 @@ -package fs - -import ( - "testing" - - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" -) - -func TestFreezerSetState(t *testing.T) { - path := tempDir(t, "freezer") - - writeFileContents(t, path, map[string]string{ - "freezer.state": string(cgroups.Frozen), - }) - - r := &cgroups.Resources{ - Freezer: cgroups.Thawed, - } - freezer := &FreezerGroup{} - if err := freezer.Set(path, r); err != nil { - t.Fatal(err) - } - - value, err := fscommon.GetCgroupParamString(path, "freezer.state") - if err != nil { - t.Fatal(err) - } - if value != string(cgroups.Thawed) { - t.Fatal("Got the wrong value, set freezer.state failed.") - } -} - -func TestFreezerSetInvalidState(t *testing.T) { - path := tempDir(t, "freezer") - - const invalidArg cgroups.FreezerState = "Invalid" - - r := &cgroups.Resources{ - Freezer: invalidArg, - } - freezer := &FreezerGroup{} - if err := freezer.Set(path, r); err == nil { - t.Fatal("Failed to return invalid argument error") - } -} diff --git a/libcontainer/cgroups/fs/fs_test.go b/libcontainer/cgroups/fs/fs_test.go deleted file mode 100644 index 2d6cad1d5..000000000 --- a/libcontainer/cgroups/fs/fs_test.go +++ /dev/null @@ -1,49 +0,0 @@ -package fs - -import ( - "testing" - - "github.com/opencontainers/runc/libcontainer/cgroups" -) - -func BenchmarkGetStats(b *testing.B) { - if cgroups.IsCgroup2UnifiedMode() { - b.Skip("cgroup v2 is not supported") - } - - // Unset TestMode as we work with real cgroupfs here, - // and we want OpenFile to perform the fstype check. - cgroups.TestMode = false - defer func() { - cgroups.TestMode = true - }() - - cg := &cgroups.Cgroup{ - Path: "/some/kind/of/a/path/here", - Resources: &cgroups.Resources{}, - } - m, err := NewManager(cg, nil) - if err != nil { - b.Fatal(err) - } - err = m.Apply(-1) - if err != nil { - b.Fatal(err) - } - defer func() { - _ = m.Destroy() - }() - - var st *cgroups.Stats - - b.ResetTimer() - for i := 0; i < b.N; i++ { - st, err = m.GetStats() - if err != nil { - b.Fatal(err) - } - } - if st.CpuStats.CpuUsage.TotalUsage != 0 { - b.Fatalf("stats: %+v", st) - } -} diff --git a/libcontainer/cgroups/fs/hugetlb_test.go b/libcontainer/cgroups/fs/hugetlb_test.go deleted file mode 100644 index 92598709b..000000000 --- a/libcontainer/cgroups/fs/hugetlb_test.go +++ /dev/null @@ -1,176 +0,0 @@ -package fs - -import ( - "fmt" - "strconv" - "testing" - - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" -) - -const ( - hugetlbUsageContents = "128\n" - hugetlbMaxUsageContents = "256\n" - hugetlbFailcnt = "100\n" -) - -const ( - usage = "hugetlb.%s.usage_in_bytes" - limit = "hugetlb.%s.limit_in_bytes" - maxUsage = "hugetlb.%s.max_usage_in_bytes" - failcnt = "hugetlb.%s.failcnt" - - rsvdUsage = "hugetlb.%s.rsvd.usage_in_bytes" - rsvdLimit = "hugetlb.%s.rsvd.limit_in_bytes" - rsvdMaxUsage = "hugetlb.%s.rsvd.max_usage_in_bytes" - rsvdFailcnt = "hugetlb.%s.rsvd.failcnt" -) - -func TestHugetlbSetHugetlb(t *testing.T) { - path := tempDir(t, "hugetlb") - - const ( - hugetlbBefore = 256 - hugetlbAfter = 512 - ) - - for _, pageSize := range cgroups.HugePageSizes() { - writeFileContents(t, path, map[string]string{ - fmt.Sprintf(limit, pageSize): strconv.Itoa(hugetlbBefore), - }) - } - - r := &cgroups.Resources{} - for _, pageSize := range cgroups.HugePageSizes() { - r.HugetlbLimit = []*cgroups.HugepageLimit{ - { - Pagesize: pageSize, - Limit: hugetlbAfter, - }, - } - hugetlb := &HugetlbGroup{} - if err := hugetlb.Set(path, r); err != nil { - t.Fatal(err) - } - } - - for _, pageSize := range cgroups.HugePageSizes() { - for _, f := range []string{limit, rsvdLimit} { - limit := fmt.Sprintf(f, pageSize) - value, err := fscommon.GetCgroupParamUint(path, limit) - if err != nil { - t.Fatal(err) - } - if value != hugetlbAfter { - t.Fatalf("Set %s failed. Expected: %v, Got: %v", limit, hugetlbAfter, value) - } - } - } -} - -func TestHugetlbStats(t *testing.T) { - path := tempDir(t, "hugetlb") - for _, pageSize := range cgroups.HugePageSizes() { - writeFileContents(t, path, map[string]string{ - fmt.Sprintf(usage, pageSize): hugetlbUsageContents, - fmt.Sprintf(maxUsage, pageSize): hugetlbMaxUsageContents, - fmt.Sprintf(failcnt, pageSize): hugetlbFailcnt, - }) - } - - hugetlb := &HugetlbGroup{} - actualStats := *cgroups.NewStats() - err := hugetlb.GetStats(path, &actualStats) - if err != nil { - t.Fatal(err) - } - expectedStats := cgroups.HugetlbStats{Usage: 128, MaxUsage: 256, Failcnt: 100} - for _, pageSize := range cgroups.HugePageSizes() { - expectHugetlbStatEquals(t, expectedStats, actualStats.HugetlbStats[pageSize]) - } -} - -func TestHugetlbRStatsRsvd(t *testing.T) { - path := tempDir(t, "hugetlb") - for _, pageSize := range cgroups.HugePageSizes() { - writeFileContents(t, path, map[string]string{ - fmt.Sprintf(rsvdUsage, pageSize): hugetlbUsageContents, - fmt.Sprintf(rsvdMaxUsage, pageSize): hugetlbMaxUsageContents, - fmt.Sprintf(rsvdFailcnt, pageSize): hugetlbFailcnt, - }) - } - - hugetlb := &HugetlbGroup{} - actualStats := *cgroups.NewStats() - err := hugetlb.GetStats(path, &actualStats) - if err != nil { - t.Fatal(err) - } - expectedStats := cgroups.HugetlbStats{Usage: 128, MaxUsage: 256, Failcnt: 100} - for _, pageSize := range cgroups.HugePageSizes() { - expectHugetlbStatEquals(t, expectedStats, actualStats.HugetlbStats[pageSize]) - } -} - -func TestHugetlbStatsNoUsageFile(t *testing.T) { - path := tempDir(t, "hugetlb") - writeFileContents(t, path, map[string]string{ - maxUsage: hugetlbMaxUsageContents, - }) - - hugetlb := &HugetlbGroup{} - actualStats := *cgroups.NewStats() - err := hugetlb.GetStats(path, &actualStats) - if err == nil { - t.Fatal("Expected failure") - } -} - -func TestHugetlbStatsNoMaxUsageFile(t *testing.T) { - path := tempDir(t, "hugetlb") - for _, pageSize := range cgroups.HugePageSizes() { - writeFileContents(t, path, map[string]string{ - fmt.Sprintf(usage, pageSize): hugetlbUsageContents, - }) - } - - hugetlb := &HugetlbGroup{} - actualStats := *cgroups.NewStats() - err := hugetlb.GetStats(path, &actualStats) - if err == nil { - t.Fatal("Expected failure") - } -} - -func TestHugetlbStatsBadUsageFile(t *testing.T) { - path := tempDir(t, "hugetlb") - for _, pageSize := range cgroups.HugePageSizes() { - writeFileContents(t, path, map[string]string{ - fmt.Sprintf(usage, pageSize): "bad", - maxUsage: hugetlbMaxUsageContents, - }) - } - - hugetlb := &HugetlbGroup{} - actualStats := *cgroups.NewStats() - err := hugetlb.GetStats(path, &actualStats) - if err == nil { - t.Fatal("Expected failure") - } -} - -func TestHugetlbStatsBadMaxUsageFile(t *testing.T) { - path := tempDir(t, "hugetlb") - writeFileContents(t, path, map[string]string{ - usage: hugetlbUsageContents, - maxUsage: "bad", - }) - - hugetlb := &HugetlbGroup{} - actualStats := *cgroups.NewStats() - err := hugetlb.GetStats(path, &actualStats) - if err == nil { - t.Fatal("Expected failure") - } -} diff --git a/libcontainer/cgroups/fs/memory_test.go b/libcontainer/cgroups/fs/memory_test.go deleted file mode 100644 index 25687b6f9..000000000 --- a/libcontainer/cgroups/fs/memory_test.go +++ /dev/null @@ -1,506 +0,0 @@ -package fs - -import ( - "strconv" - "testing" - - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" -) - -const ( - memoryStatContents = `cache 512 -rss 1024` - memoryUsageContents = "2048\n" - memoryMaxUsageContents = "4096\n" - memoryFailcnt = "100\n" - memoryLimitContents = "8192\n" - memoryUseHierarchyContents = "1\n" - memoryNUMAStatContents = `total=44611 N0=32631 N1=7501 N2=1982 N3=2497 -file=44428 N0=32614 N1=7335 N2=1982 N3=2497 -anon=183 N0=17 N1=166 N2=0 N3=0 -unevictable=0 N0=0 N1=0 N2=0 N3=0 -hierarchical_total=768133 N0=509113 N1=138887 N2=20464 N3=99669 -hierarchical_file=722017 N0=496516 N1=119997 N2=20181 N3=85323 -hierarchical_anon=46096 N0=12597 N1=18890 N2=283 N3=14326 -hierarchical_unevictable=20 N0=0 N1=0 N2=0 N3=20 -` - memoryNUMAStatNoHierarchyContents = `total=44611 N0=32631 N1=7501 N2=1982 N3=2497 -file=44428 N0=32614 N1=7335 N2=1982 N3=2497 -anon=183 N0=17 N1=166 N2=0 N3=0 -unevictable=0 N0=0 N1=0 N2=0 N3=0 -` - // Some custom kernels has extra fields that should be ignored - memoryNUMAStatExtraContents = `numa_locality 0 0 0 0 0 0 0 0 0 0 -numa_exectime 0 -whatever=100 N0=0 -` -) - -func TestMemorySetMemory(t *testing.T) { - path := tempDir(t, "memory") - - const ( - memoryBefore = 314572800 // 300M - memoryAfter = 524288000 // 500M - reservationBefore = 209715200 // 200M - reservationAfter = 314572800 // 300M - ) - - writeFileContents(t, path, map[string]string{ - "memory.limit_in_bytes": strconv.Itoa(memoryBefore), - "memory.soft_limit_in_bytes": strconv.Itoa(reservationBefore), - }) - - r := &cgroups.Resources{ - Memory: memoryAfter, - MemoryReservation: reservationAfter, - } - memory := &MemoryGroup{} - if err := memory.Set(path, r); err != nil { - t.Fatal(err) - } - - value, err := fscommon.GetCgroupParamUint(path, "memory.limit_in_bytes") - if err != nil { - t.Fatal(err) - } - if value != memoryAfter { - t.Fatal("Got the wrong value, set memory.limit_in_bytes failed.") - } - - value, err = fscommon.GetCgroupParamUint(path, "memory.soft_limit_in_bytes") - if err != nil { - t.Fatal(err) - } - if value != reservationAfter { - t.Fatal("Got the wrong value, set memory.soft_limit_in_bytes failed.") - } -} - -func TestMemorySetMemoryswap(t *testing.T) { - path := tempDir(t, "memory") - - const ( - memoryswapBefore = 314572800 // 300M - memoryswapAfter = 524288000 // 500M - ) - - writeFileContents(t, path, map[string]string{ - "memory.memsw.limit_in_bytes": strconv.Itoa(memoryswapBefore), - }) - - r := &cgroups.Resources{ - MemorySwap: memoryswapAfter, - } - memory := &MemoryGroup{} - if err := memory.Set(path, r); err != nil { - t.Fatal(err) - } - - value, err := fscommon.GetCgroupParamUint(path, "memory.memsw.limit_in_bytes") - if err != nil { - t.Fatal(err) - } - if value != memoryswapAfter { - t.Fatal("Got the wrong value, set memory.memsw.limit_in_bytes failed.") - } -} - -func TestMemorySetMemoryLargerThanSwap(t *testing.T) { - path := tempDir(t, "memory") - - const ( - memoryBefore = 314572800 // 300M - memoryswapBefore = 524288000 // 500M - memoryAfter = 629145600 // 600M - memoryswapAfter = 838860800 // 800M - ) - - writeFileContents(t, path, map[string]string{ - "memory.limit_in_bytes": strconv.Itoa(memoryBefore), - "memory.memsw.limit_in_bytes": strconv.Itoa(memoryswapBefore), - // Set will call getMemoryData when memory and swap memory are - // both set, fake these fields so we don't get error. - "memory.usage_in_bytes": "0", - "memory.max_usage_in_bytes": "0", - "memory.failcnt": "0", - }) - - r := &cgroups.Resources{ - Memory: memoryAfter, - MemorySwap: memoryswapAfter, - } - memory := &MemoryGroup{} - if err := memory.Set(path, r); err != nil { - t.Fatal(err) - } - - value, err := fscommon.GetCgroupParamUint(path, "memory.limit_in_bytes") - if err != nil { - t.Fatal(err) - } - if value != memoryAfter { - t.Fatal("Got the wrong value, set memory.limit_in_bytes failed.") - } - - value, err = fscommon.GetCgroupParamUint(path, "memory.memsw.limit_in_bytes") - if err != nil { - t.Fatal(err) - } - if value != memoryswapAfter { - t.Fatal("Got the wrong value, set memory.memsw.limit_in_bytes failed.") - } -} - -func TestMemorySetSwapSmallerThanMemory(t *testing.T) { - path := tempDir(t, "memory") - - const ( - memoryBefore = 629145600 // 600M - memoryswapBefore = 838860800 // 800M - memoryAfter = 314572800 // 300M - memoryswapAfter = 524288000 // 500M - ) - - writeFileContents(t, path, map[string]string{ - "memory.limit_in_bytes": strconv.Itoa(memoryBefore), - "memory.memsw.limit_in_bytes": strconv.Itoa(memoryswapBefore), - }) - - r := &cgroups.Resources{ - Memory: memoryAfter, - MemorySwap: memoryswapAfter, - } - memory := &MemoryGroup{} - if err := memory.Set(path, r); err != nil { - t.Fatal(err) - } - - value, err := fscommon.GetCgroupParamUint(path, "memory.limit_in_bytes") - if err != nil { - t.Fatal(err) - } - if value != memoryAfter { - t.Fatalf("Got the wrong value (%d != %d), set memory.limit_in_bytes failed", value, memoryAfter) - } - - value, err = fscommon.GetCgroupParamUint(path, "memory.memsw.limit_in_bytes") - if err != nil { - t.Fatal(err) - } - if value != memoryswapAfter { - t.Fatalf("Got the wrong value (%d != %d), set memory.memsw.limit_in_bytes failed", value, memoryswapAfter) - } -} - -func TestMemorySetMemorySwappinessDefault(t *testing.T) { - path := tempDir(t, "memory") - - swappinessBefore := 60 // default is 60 - swappinessAfter := uint64(0) - - writeFileContents(t, path, map[string]string{ - "memory.swappiness": strconv.Itoa(swappinessBefore), - }) - - r := &cgroups.Resources{ - MemorySwappiness: &swappinessAfter, - } - memory := &MemoryGroup{} - if err := memory.Set(path, r); err != nil { - t.Fatal(err) - } - - value, err := fscommon.GetCgroupParamUint(path, "memory.swappiness") - if err != nil { - t.Fatal(err) - } - if value != swappinessAfter { - t.Fatalf("Got the wrong value (%d), set memory.swappiness = %d failed.", value, swappinessAfter) - } -} - -func TestMemoryStats(t *testing.T) { - path := tempDir(t, "memory") - writeFileContents(t, path, map[string]string{ - "memory.stat": memoryStatContents, - "memory.usage_in_bytes": memoryUsageContents, - "memory.limit_in_bytes": memoryLimitContents, - "memory.max_usage_in_bytes": memoryMaxUsageContents, - "memory.failcnt": memoryFailcnt, - "memory.memsw.usage_in_bytes": memoryUsageContents, - "memory.memsw.max_usage_in_bytes": memoryMaxUsageContents, - "memory.memsw.failcnt": memoryFailcnt, - "memory.memsw.limit_in_bytes": memoryLimitContents, - "memory.kmem.usage_in_bytes": memoryUsageContents, - "memory.kmem.max_usage_in_bytes": memoryMaxUsageContents, - "memory.kmem.failcnt": memoryFailcnt, - "memory.kmem.limit_in_bytes": memoryLimitContents, - "memory.use_hierarchy": memoryUseHierarchyContents, - "memory.numa_stat": memoryNUMAStatContents + memoryNUMAStatExtraContents, - }) - - memory := &MemoryGroup{} - actualStats := *cgroups.NewStats() - err := memory.GetStats(path, &actualStats) - if err != nil { - t.Fatal(err) - } - expectedStats := cgroups.MemoryStats{ - Cache: 512, - Usage: cgroups.MemoryData{Usage: 2048, MaxUsage: 4096, Failcnt: 100, Limit: 8192}, - SwapUsage: cgroups.MemoryData{Usage: 2048, MaxUsage: 4096, Failcnt: 100, Limit: 8192}, - SwapOnlyUsage: cgroups.MemoryData{Usage: 0, MaxUsage: 0, Failcnt: 0, Limit: 0}, - KernelUsage: cgroups.MemoryData{Usage: 2048, MaxUsage: 4096, Failcnt: 100, Limit: 8192}, - Stats: map[string]uint64{"cache": 512, "rss": 1024}, - UseHierarchy: true, - PageUsageByNUMA: cgroups.PageUsageByNUMA{ - PageUsageByNUMAInner: cgroups.PageUsageByNUMAInner{ - Total: cgroups.PageStats{Total: 44611, Nodes: map[uint8]uint64{0: 32631, 1: 7501, 2: 1982, 3: 2497}}, - File: cgroups.PageStats{Total: 44428, Nodes: map[uint8]uint64{0: 32614, 1: 7335, 2: 1982, 3: 2497}}, - Anon: cgroups.PageStats{Total: 183, Nodes: map[uint8]uint64{0: 17, 1: 166, 2: 0, 3: 0}}, - Unevictable: cgroups.PageStats{Total: 0, Nodes: map[uint8]uint64{0: 0, 1: 0, 2: 0, 3: 0}}, - }, - Hierarchical: cgroups.PageUsageByNUMAInner{ - Total: cgroups.PageStats{Total: 768133, Nodes: map[uint8]uint64{0: 509113, 1: 138887, 2: 20464, 3: 99669}}, - File: cgroups.PageStats{Total: 722017, Nodes: map[uint8]uint64{0: 496516, 1: 119997, 2: 20181, 3: 85323}}, - Anon: cgroups.PageStats{Total: 46096, Nodes: map[uint8]uint64{0: 12597, 1: 18890, 2: 283, 3: 14326}}, - Unevictable: cgroups.PageStats{Total: 20, Nodes: map[uint8]uint64{0: 0, 1: 0, 2: 0, 3: 20}}, - }, - }, - } - expectMemoryStatEquals(t, expectedStats, actualStats.MemoryStats) -} - -func TestMemoryStatsNoStatFile(t *testing.T) { - path := tempDir(t, "memory") - writeFileContents(t, path, map[string]string{ - "memory.usage_in_bytes": memoryUsageContents, - "memory.max_usage_in_bytes": memoryMaxUsageContents, - "memory.limit_in_bytes": memoryLimitContents, - }) - - memory := &MemoryGroup{} - actualStats := *cgroups.NewStats() - err := memory.GetStats(path, &actualStats) - if err != nil { - t.Fatal(err) - } -} - -func TestMemoryStatsNoUsageFile(t *testing.T) { - path := tempDir(t, "memory") - writeFileContents(t, path, map[string]string{ - "memory.stat": memoryStatContents, - "memory.max_usage_in_bytes": memoryMaxUsageContents, - "memory.limit_in_bytes": memoryLimitContents, - }) - - memory := &MemoryGroup{} - actualStats := *cgroups.NewStats() - err := memory.GetStats(path, &actualStats) - if err == nil { - t.Fatal("Expected failure") - } -} - -func TestMemoryStatsNoMaxUsageFile(t *testing.T) { - path := tempDir(t, "memory") - writeFileContents(t, path, map[string]string{ - "memory.stat": memoryStatContents, - "memory.usage_in_bytes": memoryUsageContents, - "memory.limit_in_bytes": memoryLimitContents, - }) - - memory := &MemoryGroup{} - actualStats := *cgroups.NewStats() - err := memory.GetStats(path, &actualStats) - if err == nil { - t.Fatal("Expected failure") - } -} - -func TestMemoryStatsNoLimitInBytesFile(t *testing.T) { - path := tempDir(t, "memory") - writeFileContents(t, path, map[string]string{ - "memory.stat": memoryStatContents, - "memory.usage_in_bytes": memoryUsageContents, - "memory.max_usage_in_bytes": memoryMaxUsageContents, - }) - - memory := &MemoryGroup{} - actualStats := *cgroups.NewStats() - err := memory.GetStats(path, &actualStats) - if err == nil { - t.Fatal("Expected failure") - } -} - -func TestMemoryStatsBadStatFile(t *testing.T) { - path := tempDir(t, "memory") - writeFileContents(t, path, map[string]string{ - "memory.stat": "rss rss", - "memory.usage_in_bytes": memoryUsageContents, - "memory.max_usage_in_bytes": memoryMaxUsageContents, - "memory.limit_in_bytes": memoryLimitContents, - }) - - memory := &MemoryGroup{} - actualStats := *cgroups.NewStats() - err := memory.GetStats(path, &actualStats) - if err == nil { - t.Fatal("Expected failure") - } -} - -func TestMemoryStatsBadUsageFile(t *testing.T) { - path := tempDir(t, "memory") - writeFileContents(t, path, map[string]string{ - "memory.stat": memoryStatContents, - "memory.usage_in_bytes": "bad", - "memory.max_usage_in_bytes": memoryMaxUsageContents, - "memory.limit_in_bytes": memoryLimitContents, - }) - - memory := &MemoryGroup{} - actualStats := *cgroups.NewStats() - err := memory.GetStats(path, &actualStats) - if err == nil { - t.Fatal("Expected failure") - } -} - -func TestMemoryStatsBadMaxUsageFile(t *testing.T) { - path := tempDir(t, "memory") - writeFileContents(t, path, map[string]string{ - "memory.stat": memoryStatContents, - "memory.usage_in_bytes": memoryUsageContents, - "memory.max_usage_in_bytes": "bad", - "memory.limit_in_bytes": memoryLimitContents, - }) - - memory := &MemoryGroup{} - actualStats := *cgroups.NewStats() - err := memory.GetStats(path, &actualStats) - if err == nil { - t.Fatal("Expected failure") - } -} - -func TestMemoryStatsBadLimitInBytesFile(t *testing.T) { - path := tempDir(t, "memory") - writeFileContents(t, path, map[string]string{ - "memory.stat": memoryStatContents, - "memory.usage_in_bytes": memoryUsageContents, - "memory.max_usage_in_bytes": memoryMaxUsageContents, - "memory.limit_in_bytes": "bad", - }) - - memory := &MemoryGroup{} - actualStats := *cgroups.NewStats() - err := memory.GetStats(path, &actualStats) - if err == nil { - t.Fatal("Expected failure") - } -} - -func TestMemorySetOomControl(t *testing.T) { - path := tempDir(t, "memory") - - const ( - oomKillDisable = 1 // disable oom killer, default is 0 - ) - - writeFileContents(t, path, map[string]string{ - "memory.oom_control": strconv.Itoa(oomKillDisable), - }) - - memory := &MemoryGroup{} - r := &cgroups.Resources{} - if err := memory.Set(path, r); err != nil { - t.Fatal(err) - } - - value, err := fscommon.GetCgroupParamUint(path, "memory.oom_control") - if err != nil { - t.Fatal(err) - } - if value != oomKillDisable { - t.Fatalf("Got the wrong value, set memory.oom_control failed.") - } -} - -func TestNoHierarchicalNumaStat(t *testing.T) { - path := tempDir(t, "memory") - writeFileContents(t, path, map[string]string{ - "memory.numa_stat": memoryNUMAStatNoHierarchyContents + memoryNUMAStatExtraContents, - }) - - actualStats, err := getPageUsageByNUMA(path) - if err != nil { - t.Fatal(err) - } - pageUsageByNUMA := cgroups.PageUsageByNUMA{ - PageUsageByNUMAInner: cgroups.PageUsageByNUMAInner{ - Total: cgroups.PageStats{Total: 44611, Nodes: map[uint8]uint64{0: 32631, 1: 7501, 2: 1982, 3: 2497}}, - File: cgroups.PageStats{Total: 44428, Nodes: map[uint8]uint64{0: 32614, 1: 7335, 2: 1982, 3: 2497}}, - Anon: cgroups.PageStats{Total: 183, Nodes: map[uint8]uint64{0: 17, 1: 166, 2: 0, 3: 0}}, - Unevictable: cgroups.PageStats{Total: 0, Nodes: map[uint8]uint64{0: 0, 1: 0, 2: 0, 3: 0}}, - }, - Hierarchical: cgroups.PageUsageByNUMAInner{}, - } - expectPageUsageByNUMAEquals(t, pageUsageByNUMA, actualStats) -} - -func TestBadNumaStat(t *testing.T) { - memoryNUMAStatBadContents := []struct { - desc, contents string - }{ - { - desc: "Nx where x is not a number", - contents: `total=44611 N0=44611, -file=44428 Nx=0 -`, - }, { - desc: "Nx where x > 255", - contents: `total=44611 N333=444`, - }, { - desc: "Nx argument missing", - contents: `total=44611 N0=123 N1=`, - }, { - desc: "Nx argument is not a number", - contents: `total=44611 N0=123 N1=a`, - }, { - desc: "Missing = after Nx", - contents: `total=44611 N0=123 N1`, - }, { - desc: "No Nx at non-first position", - contents: `total=44611 N0=32631 -file=44428 N0=32614 -anon=183 N0=12 badone -`, - }, - } - path := tempDir(t, "memory") - for _, c := range memoryNUMAStatBadContents { - writeFileContents(t, path, map[string]string{ - "memory.numa_stat": c.contents, - }) - - _, err := getPageUsageByNUMA(path) - if err == nil { - t.Errorf("case %q: expected error, got nil", c.desc) - } - } -} - -func TestWithoutNumaStat(t *testing.T) { - path := tempDir(t, "memory") - - actualStats, err := getPageUsageByNUMA(path) - if err != nil { - t.Fatal(err) - } - expectPageUsageByNUMAEquals(t, cgroups.PageUsageByNUMA{}, actualStats) -} diff --git a/libcontainer/cgroups/fs/net_cls_test.go b/libcontainer/cgroups/fs/net_cls_test.go deleted file mode 100644 index ea051d99a..000000000 --- a/libcontainer/cgroups/fs/net_cls_test.go +++ /dev/null @@ -1,41 +0,0 @@ -package fs - -import ( - "strconv" - "testing" - - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" -) - -const ( - classidBefore = 0x100002 - classidAfter = 0x100001 -) - -func TestNetClsSetClassid(t *testing.T) { - path := tempDir(t, "net_cls") - - writeFileContents(t, path, map[string]string{ - "net_cls.classid": strconv.FormatUint(classidBefore, 10), - }) - - r := &cgroups.Resources{ - NetClsClassid: classidAfter, - } - netcls := &NetClsGroup{} - if err := netcls.Set(path, r); err != nil { - t.Fatal(err) - } - - // As we are in mock environment, we can't get correct value of classid from - // net_cls.classid. - // So. we just judge if we successfully write classid into file - value, err := fscommon.GetCgroupParamUint(path, "net_cls.classid") - if err != nil { - t.Fatal(err) - } - if value != classidAfter { - t.Fatal("Got the wrong value, set net_cls.classid failed.") - } -} diff --git a/libcontainer/cgroups/fs/net_prio_test.go b/libcontainer/cgroups/fs/net_prio_test.go deleted file mode 100644 index 90115e99e..000000000 --- a/libcontainer/cgroups/fs/net_prio_test.go +++ /dev/null @@ -1,36 +0,0 @@ -package fs - -import ( - "strings" - "testing" - - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" -) - -var prioMap = []*cgroups.IfPrioMap{ - { - Interface: "test", - Priority: 5, - }, -} - -func TestNetPrioSetIfPrio(t *testing.T) { - path := tempDir(t, "net_prio") - - r := &cgroups.Resources{ - NetPrioIfpriomap: prioMap, - } - netPrio := &NetPrioGroup{} - if err := netPrio.Set(path, r); err != nil { - t.Fatal(err) - } - - value, err := fscommon.GetCgroupParamString(path, "net_prio.ifpriomap") - if err != nil { - t.Fatal(err) - } - if !strings.Contains(value, "test 5") { - t.Fatal("Got the wrong value, set net_prio.ifpriomap failed.") - } -} diff --git a/libcontainer/cgroups/fs/paths_test.go b/libcontainer/cgroups/fs/paths_test.go deleted file mode 100644 index 692ff5e56..000000000 --- a/libcontainer/cgroups/fs/paths_test.go +++ /dev/null @@ -1,104 +0,0 @@ -package fs - -import ( - "path/filepath" - "strings" - "testing" - - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/internal/path" -) - -func TestInvalidCgroupPath(t *testing.T) { - if cgroups.IsCgroup2UnifiedMode() { - t.Skip("cgroup v2 is not supported") - } - - root, err := rootPath() - if err != nil { - t.Fatalf("couldn't get cgroup root: %v", err) - } - - testCases := []struct { - test string - path, name, parent string - }{ - { - test: "invalid cgroup path", - path: "../../../../../../../../../../some/path", - }, - { - test: "invalid absolute cgroup path", - path: "/../../../../../../../../../../some/path", - }, - { - test: "invalid cgroup parent", - parent: "../../../../../../../../../../some/path", - name: "name", - }, - { - test: "invalid absolute cgroup parent", - parent: "/../../../../../../../../../../some/path", - name: "name", - }, - { - test: "invalid cgroup name", - parent: "parent", - name: "../../../../../../../../../../some/path", - }, - { - test: "invalid absolute cgroup name", - parent: "parent", - name: "/../../../../../../../../../../some/path", - }, - { - test: "invalid cgroup name and parent", - parent: "../../../../../../../../../../some/path", - name: "../../../../../../../../../../some/path", - }, - { - test: "invalid absolute cgroup name and parent", - parent: "/../../../../../../../../../../some/path", - name: "/../../../../../../../../../../some/path", - }, - } - - for _, tc := range testCases { - t.Run(tc.test, func(t *testing.T) { - config := &cgroups.Cgroup{Path: tc.path, Name: tc.name, Parent: tc.parent} - - inner, err := path.Inner(config) - if err != nil { - t.Fatalf("couldn't get cgroup data: %v", err) - } - - // Make sure the final inner path doesn't go outside the cgroup mountpoint. - if strings.HasPrefix(inner, "..") { - t.Errorf("SECURITY: cgroup innerPath is outside cgroup mountpoint!") - } - - // Double-check, using an actual cgroup. - deviceRoot := filepath.Join(root, "devices") - devicePath, err := subsysPath(root, inner, "devices") - if err != nil { - t.Fatalf("couldn't get cgroup path: %v", err) - } - if !strings.HasPrefix(devicePath, deviceRoot) { - t.Errorf("SECURITY: cgroup path() is outside cgroup mountpoint!") - } - }) - } -} - -func TestTryDefaultCgroupRoot(t *testing.T) { - res := tryDefaultCgroupRoot() - exp := defaultCgroupRoot - if cgroups.IsCgroup2UnifiedMode() { - // checking that tryDefaultCgroupRoot does return "" - // in case /sys/fs/cgroup is not cgroup v1 root dir. - exp = "" - } - if res != exp { - t.Errorf("tryDefaultCgroupRoot: want %q, got %q", exp, res) - } -} diff --git a/libcontainer/cgroups/fs/pids_test.go b/libcontainer/cgroups/fs/pids_test.go deleted file mode 100644 index eb05511ff..000000000 --- a/libcontainer/cgroups/fs/pids_test.go +++ /dev/null @@ -1,108 +0,0 @@ -package fs - -import ( - "strconv" - "testing" - - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" -) - -const ( - maxUnlimited = -1 - maxLimited = 1024 -) - -func TestPidsSetMax(t *testing.T) { - path := tempDir(t, "pids") - - writeFileContents(t, path, map[string]string{ - "pids.max": "max", - }) - - r := &cgroups.Resources{ - PidsLimit: maxLimited, - } - pids := &PidsGroup{} - if err := pids.Set(path, r); err != nil { - t.Fatal(err) - } - - value, err := fscommon.GetCgroupParamUint(path, "pids.max") - if err != nil { - t.Fatal(err) - } - if value != maxLimited { - t.Fatalf("Expected %d, got %d for setting pids.max - limited", maxLimited, value) - } -} - -func TestPidsSetUnlimited(t *testing.T) { - path := tempDir(t, "pids") - - writeFileContents(t, path, map[string]string{ - "pids.max": strconv.Itoa(maxLimited), - }) - - r := &cgroups.Resources{ - PidsLimit: maxUnlimited, - } - pids := &PidsGroup{} - if err := pids.Set(path, r); err != nil { - t.Fatal(err) - } - - value, err := fscommon.GetCgroupParamString(path, "pids.max") - if err != nil { - t.Fatal(err) - } - if value != "max" { - t.Fatalf("Expected %s, got %s for setting pids.max - unlimited", "max", value) - } -} - -func TestPidsStats(t *testing.T) { - path := tempDir(t, "pids") - - writeFileContents(t, path, map[string]string{ - "pids.current": strconv.Itoa(1337), - "pids.max": strconv.Itoa(maxLimited), - }) - - pids := &PidsGroup{} - stats := *cgroups.NewStats() - if err := pids.GetStats(path, &stats); err != nil { - t.Fatal(err) - } - - if stats.PidsStats.Current != 1337 { - t.Fatalf("Expected %d, got %d for pids.current", 1337, stats.PidsStats.Current) - } - - if stats.PidsStats.Limit != maxLimited { - t.Fatalf("Expected %d, got %d for pids.max", maxLimited, stats.PidsStats.Limit) - } -} - -func TestPidsStatsUnlimited(t *testing.T) { - path := tempDir(t, "pids") - - writeFileContents(t, path, map[string]string{ - "pids.current": strconv.Itoa(4096), - "pids.max": "max", - }) - - pids := &PidsGroup{} - stats := *cgroups.NewStats() - if err := pids.GetStats(path, &stats); err != nil { - t.Fatal(err) - } - - if stats.PidsStats.Current != 4096 { - t.Fatalf("Expected %d, got %d for pids.current", 4096, stats.PidsStats.Current) - } - - if stats.PidsStats.Limit != 0 { - t.Fatalf("Expected %d, got %d for pids.max", 0, stats.PidsStats.Limit) - } -} diff --git a/libcontainer/cgroups/fs/stats_util_test.go b/libcontainer/cgroups/fs/stats_util_test.go deleted file mode 100644 index 9b7d840a7..000000000 --- a/libcontainer/cgroups/fs/stats_util_test.go +++ /dev/null @@ -1,138 +0,0 @@ -package fs - -import ( - "errors" - "fmt" - "reflect" - "testing" - - "github.com/opencontainers/runc/libcontainer/cgroups" -) - -func blkioStatEntryEquals(expected, actual []cgroups.BlkioStatEntry) error { - if len(expected) != len(actual) { - return errors.New("blkioStatEntries length do not match") - } - for i, expValue := range expected { - actValue := actual[i] - if expValue != actValue { - return fmt.Errorf("expected: %v, actual: %v", expValue, actValue) - } - } - return nil -} - -func expectBlkioStatsEquals(t *testing.T, expected, actual cgroups.BlkioStats) { - t.Helper() - if err := blkioStatEntryEquals(expected.IoServiceBytesRecursive, actual.IoServiceBytesRecursive); err != nil { - t.Errorf("blkio IoServiceBytesRecursive do not match: %s", err) - } - - if err := blkioStatEntryEquals(expected.IoServicedRecursive, actual.IoServicedRecursive); err != nil { - t.Errorf("blkio IoServicedRecursive do not match: %s", err) - } - - if err := blkioStatEntryEquals(expected.IoQueuedRecursive, actual.IoQueuedRecursive); err != nil { - t.Errorf("blkio IoQueuedRecursive do not match: %s", err) - } - - if err := blkioStatEntryEquals(expected.SectorsRecursive, actual.SectorsRecursive); err != nil { - t.Errorf("blkio SectorsRecursive do not match: %s", err) - } - - if err := blkioStatEntryEquals(expected.IoServiceTimeRecursive, actual.IoServiceTimeRecursive); err != nil { - t.Errorf("blkio IoServiceTimeRecursive do not match: %s", err) - } - - if err := blkioStatEntryEquals(expected.IoWaitTimeRecursive, actual.IoWaitTimeRecursive); err != nil { - t.Errorf("blkio IoWaitTimeRecursive do not match: %s", err) - } - - if err := blkioStatEntryEquals(expected.IoMergedRecursive, actual.IoMergedRecursive); err != nil { - t.Errorf("blkio IoMergedRecursive do not match: expected: %v, actual: %v", expected.IoMergedRecursive, actual.IoMergedRecursive) - } - - if err := blkioStatEntryEquals(expected.IoTimeRecursive, actual.IoTimeRecursive); err != nil { - t.Errorf("blkio IoTimeRecursive do not match: %s", err) - } -} - -func expectThrottlingDataEquals(t *testing.T, expected, actual cgroups.ThrottlingData) { - t.Helper() - if expected != actual { - t.Errorf("Expected throttling data: %v, actual: %v", expected, actual) - } -} - -func expectHugetlbStatEquals(t *testing.T, expected, actual cgroups.HugetlbStats) { - t.Helper() - if expected != actual { - t.Errorf("Expected hugetlb stats: %v, actual: %v", expected, actual) - } -} - -func expectMemoryStatEquals(t *testing.T, expected, actual cgroups.MemoryStats) { - t.Helper() - expectMemoryDataEquals(t, expected.Usage, actual.Usage) - expectMemoryDataEquals(t, expected.SwapUsage, actual.SwapUsage) - expectMemoryDataEquals(t, expected.KernelUsage, actual.KernelUsage) - expectPageUsageByNUMAEquals(t, expected.PageUsageByNUMA, actual.PageUsageByNUMA) - - if expected.UseHierarchy != actual.UseHierarchy { - t.Errorf("Expected memory use hierarchy: %v, actual: %v", expected.UseHierarchy, actual.UseHierarchy) - } - - for key, expValue := range expected.Stats { - actValue, ok := actual.Stats[key] - if !ok { - t.Errorf("Expected memory stat key %s not found", key) - } - if expValue != actValue { - t.Errorf("Expected memory stat value: %d, actual: %d", expValue, actValue) - } - } -} - -func expectMemoryDataEquals(t *testing.T, expected, actual cgroups.MemoryData) { - t.Helper() - if expected.Usage != actual.Usage { - t.Errorf("Expected memory usage: %d, actual: %d", expected.Usage, actual.Usage) - } - if expected.MaxUsage != actual.MaxUsage { - t.Errorf("Expected memory max usage: %d, actual: %d", expected.MaxUsage, actual.MaxUsage) - } - if expected.Failcnt != actual.Failcnt { - t.Errorf("Expected memory failcnt %d, actual: %d", expected.Failcnt, actual.Failcnt) - } - if expected.Limit != actual.Limit { - t.Errorf("Expected memory limit: %d, actual: %d", expected.Limit, actual.Limit) - } -} - -func expectPageUsageByNUMAEquals(t *testing.T, expected, actual cgroups.PageUsageByNUMA) { - t.Helper() - if !reflect.DeepEqual(expected.Total, actual.Total) { - t.Errorf("Expected total page usage by NUMA: %#v, actual: %#v", expected.Total, actual.Total) - } - if !reflect.DeepEqual(expected.File, actual.File) { - t.Errorf("Expected file page usage by NUMA: %#v, actual: %#v", expected.File, actual.File) - } - if !reflect.DeepEqual(expected.Anon, actual.Anon) { - t.Errorf("Expected anon page usage by NUMA: %#v, actual: %#v", expected.Anon, actual.Anon) - } - if !reflect.DeepEqual(expected.Unevictable, actual.Unevictable) { - t.Errorf("Expected unevictable page usage by NUMA: %#v, actual: %#v", expected.Unevictable, actual.Unevictable) - } - if !reflect.DeepEqual(expected.Hierarchical.Total, actual.Hierarchical.Total) { - t.Errorf("Expected hierarchical total page usage by NUMA: %#v, actual: %#v", expected.Hierarchical.Total, actual.Hierarchical.Total) - } - if !reflect.DeepEqual(expected.Hierarchical.File, actual.Hierarchical.File) { - t.Errorf("Expected hierarchical file page usage by NUMA: %#v, actual: %#v", expected.Hierarchical.File, actual.Hierarchical.File) - } - if !reflect.DeepEqual(expected.Hierarchical.Anon, actual.Hierarchical.Anon) { - t.Errorf("Expected hierarchical anon page usage by NUMA: %#v, actual: %#v", expected.Hierarchical.Anon, actual.Hierarchical.Anon) - } - if !reflect.DeepEqual(expected.Hierarchical.Unevictable, actual.Hierarchical.Unevictable) { - t.Errorf("Expected hierarchical total page usage by NUMA: %#v, actual: %#v", expected.Hierarchical.Unevictable, actual.Hierarchical.Unevictable) - } -} diff --git a/libcontainer/cgroups/fs/util_test.go b/libcontainer/cgroups/fs/util_test.go deleted file mode 100644 index 87c70ed1d..000000000 --- a/libcontainer/cgroups/fs/util_test.go +++ /dev/null @@ -1,39 +0,0 @@ -/* -Utility for testing cgroup operations. - -Creates a mock of the cgroup filesystem for the duration of the test. -*/ -package fs - -import ( - "os" - "path/filepath" - "testing" - - "github.com/opencontainers/runc/libcontainer/cgroups" -) - -func init() { - cgroups.TestMode = true -} - -// tempDir creates a new test directory for the specified subsystem. -func tempDir(t testing.TB, subsystem string) string { - path := filepath.Join(t.TempDir(), subsystem) - // Ensure the full mock cgroup path exists. - if err := os.Mkdir(path, 0o755); err != nil { - t.Fatal(err) - } - return path -} - -// writeFileContents writes the specified contents on the mock of the specified -// cgroup files. -func writeFileContents(t testing.TB, path string, fileContents map[string]string) { - for file, contents := range fileContents { - err := cgroups.WriteFile(path, file, contents) - if err != nil { - t.Fatal(err) - } - } -} diff --git a/libcontainer/cgroups/fs2/defaultpath_test.go b/libcontainer/cgroups/fs2/defaultpath_test.go deleted file mode 100644 index 6fcc19792..000000000 --- a/libcontainer/cgroups/fs2/defaultpath_test.go +++ /dev/null @@ -1,93 +0,0 @@ -/* - Copyright The containerd Authors. - - 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 fs2 - -import ( - "path/filepath" - "strings" - "testing" - - "github.com/opencontainers/runc/libcontainer/cgroups" -) - -func TestParseCgroupFromReader(t *testing.T) { - cases := map[string]string{ - "0::/user.slice/user-1001.slice/session-1.scope\n": "/user.slice/user-1001.slice/session-1.scope", - "2:cpuset:/foo\n1:name=systemd:/\n": "", - "2:cpuset:/foo\n1:name=systemd:/\n0::/user.slice/user-1001.slice/session-1.scope\n": "/user.slice/user-1001.slice/session-1.scope", - } - for s, expected := range cases { - g, err := parseCgroupFromReader(strings.NewReader(s)) - if expected != "" { - if g != expected { - t.Errorf("expected %q, got %q", expected, g) - } - if err != nil { - t.Error(err) - } - } else { - if err == nil { - t.Error("error is expected") - } - } - } -} - -func TestDefaultDirPath(t *testing.T) { - if !cgroups.IsCgroup2UnifiedMode() { - t.Skip("need cgroupv2") - } - // same code as in defaultDirPath() - ownCgroup, err := parseCgroupFile("/proc/self/cgroup") - if err != nil { - // Not a test failure, but rather some weird - // environment so we can't run this test. - t.Skipf("can't get own cgroup: %v", err) - } - ownCgroup = filepath.Dir(ownCgroup) - - cases := []struct { - cgPath string - cgParent string - cgName string - expected string - }{ - { - cgPath: "/foo/bar", - expected: "/sys/fs/cgroup/foo/bar", - }, - { - cgPath: "foo/bar", - expected: filepath.Join(UnifiedMountpoint, ownCgroup, "foo/bar"), - }, - } - for _, c := range cases { - cg := &cgroups.Cgroup{ - Path: c.cgPath, - Parent: c.cgParent, - Name: c.cgName, - } - - got, err := defaultDirPath(cg) - if err != nil { - t.Fatal(err) - } - if got != c.expected { - t.Fatalf("expected %q, got %q", c.expected, got) - } - } -} diff --git a/libcontainer/cgroups/fs2/io_test.go b/libcontainer/cgroups/fs2/io_test.go deleted file mode 100644 index 15bb64a1d..000000000 --- a/libcontainer/cgroups/fs2/io_test.go +++ /dev/null @@ -1,81 +0,0 @@ -package fs2 - -import ( - "os" - "path/filepath" - "reflect" - "sort" - "testing" - - "github.com/opencontainers/runc/libcontainer/cgroups" -) - -const exampleIoStatData = `254:1 rbytes=6901432320 wbytes=14245535744 rios=263278 wios=248603 dbytes=0 dios=0 -254:0 rbytes=2702336 wbytes=0 rios=97 wios=0 dbytes=0 dios=0 -259:0 rbytes=6911345664 wbytes=14245536256 rios=264538 wios=244914 dbytes=530485248 dios=2` - -var exampleIoStatsParsed = cgroups.BlkioStats{ - IoServiceBytesRecursive: []cgroups.BlkioStatEntry{ - {Major: 254, Minor: 1, Value: 6901432320, Op: "Read"}, - {Major: 254, Minor: 1, Value: 14245535744, Op: "Write"}, - {Major: 254, Minor: 0, Value: 2702336, Op: "Read"}, - {Major: 254, Minor: 0, Value: 0, Op: "Write"}, - {Major: 259, Minor: 0, Value: 6911345664, Op: "Read"}, - {Major: 259, Minor: 0, Value: 14245536256, Op: "Write"}, - }, - IoServicedRecursive: []cgroups.BlkioStatEntry{ - {Major: 254, Minor: 1, Value: 263278, Op: "Read"}, - {Major: 254, Minor: 1, Value: 248603, Op: "Write"}, - {Major: 254, Minor: 0, Value: 97, Op: "Read"}, - {Major: 254, Minor: 0, Value: 0, Op: "Write"}, - {Major: 259, Minor: 0, Value: 264538, Op: "Read"}, - {Major: 259, Minor: 0, Value: 244914, Op: "Write"}, - }, -} - -func lessBlkioStatEntry(a, b cgroups.BlkioStatEntry) bool { - if a.Major != b.Major { - return a.Major < b.Major - } - if a.Minor != b.Minor { - return a.Minor < b.Minor - } - if a.Op != b.Op { - return a.Op < b.Op - } - return a.Value < b.Value -} - -func sortBlkioStats(stats *cgroups.BlkioStats) { - for _, table := range []*[]cgroups.BlkioStatEntry{ - &stats.IoServicedRecursive, - &stats.IoServiceBytesRecursive, - } { - sort.SliceStable(*table, func(i, j int) bool { return lessBlkioStatEntry((*table)[i], (*table)[j]) }) - } -} - -func TestStatIo(t *testing.T) { - // We're using a fake cgroupfs. - cgroups.TestMode = true - - fakeCgroupDir := t.TempDir() - statPath := filepath.Join(fakeCgroupDir, "io.stat") - - if err := os.WriteFile(statPath, []byte(exampleIoStatData), 0o644); err != nil { - t.Fatal(err) - } - - var gotStats cgroups.Stats - if err := statIo(fakeCgroupDir, &gotStats); err != nil { - t.Error(err) - } - - // Sort the output since statIo uses a map internally. - sortBlkioStats(&gotStats.BlkioStats) - sortBlkioStats(&exampleIoStatsParsed) - - if !reflect.DeepEqual(gotStats.BlkioStats, exampleIoStatsParsed) { - t.Errorf("parsed cgroupv2 io.stat doesn't match expected result: \ngot %#v\nexpected %#v\n", gotStats.BlkioStats, exampleIoStatsParsed) - } -} diff --git a/libcontainer/cgroups/fs2/memory_test.go b/libcontainer/cgroups/fs2/memory_test.go deleted file mode 100644 index 89c999d0c..000000000 --- a/libcontainer/cgroups/fs2/memory_test.go +++ /dev/null @@ -1,155 +0,0 @@ -package fs2 - -import ( - "os" - "path/filepath" - "strings" - "testing" - - "github.com/opencontainers/runc/libcontainer/cgroups" -) - -const exampleMemoryStatData = `anon 790425600 -file 6502666240 -kernel_stack 7012352 -pagetables 8867840 -percpu 2445520 -sock 40960 -shmem 6721536 -file_mapped 656187392 -file_dirty 1122304 -file_writeback 0 -swapcached 10 -anon_thp 438304768 -file_thp 0 -shmem_thp 0 -inactive_anon 892223488 -active_anon 2973696 -inactive_file 5307346944 -active_file 1179316224 -unevictable 31477760 -slab_reclaimable 348866240 -slab_unreclaimable 10099808 -slab 358966048 -workingset_refault_anon 0 -workingset_refault_file 0 -workingset_activate_anon 0 -workingset_activate_file 0 -workingset_restore_anon 0 -workingset_restore_file 0 -workingset_nodereclaim 0 -pgfault 103216687 -pgmajfault 6879 -pgrefill 0 -pgscan 0 -pgsteal 0 -pgactivate 1110217 -pgdeactivate 292 -pglazyfree 267 -pglazyfreed 0 -thp_fault_alloc 57411 -thp_collapse_alloc 443` - -func TestStatMemoryPodCgroupNotFound(t *testing.T) { - // We're using a fake cgroupfs. - cgroups.TestMode = true - fakeCgroupDir := t.TempDir() - - // only write memory.stat to ensure pod cgroup usage - // still reads memory.current. - statPath := filepath.Join(fakeCgroupDir, "memory.stat") - if err := os.WriteFile(statPath, []byte(exampleMemoryStatData), 0o644); err != nil { - t.Fatal(err) - } - - gotStats := cgroups.NewStats() - - // use a fake root path to mismatch the file we wrote. - // this triggers the non-root path which should fail to find memory.current. - err := statMemory(fakeCgroupDir, gotStats) - if err == nil { - t.Errorf("expected error when statting memory for cgroupv2 root, but was nil") - } - - if !strings.Contains(err.Error(), "memory.current: no such file or directory") { - t.Errorf("expected error to contain 'memory.current: no such file or directory', but was %s", err.Error()) - } -} - -func TestStatMemoryPodCgroup(t *testing.T) { - // We're using a fake cgroupfs. - cgroups.TestMode = true - fakeCgroupDir := t.TempDir() - - statPath := filepath.Join(fakeCgroupDir, "memory.stat") - if err := os.WriteFile(statPath, []byte(exampleMemoryStatData), 0o644); err != nil { - t.Fatal(err) - } - - if err := os.WriteFile(filepath.Join(fakeCgroupDir, "memory.current"), []byte("123456789"), 0o644); err != nil { - t.Fatal(err) - } - - if err := os.WriteFile(filepath.Join(fakeCgroupDir, "memory.max"), []byte("999999999"), 0o644); err != nil { - t.Fatal(err) - } - - if err := os.WriteFile(filepath.Join(fakeCgroupDir, "memory.peak"), []byte("987654321"), 0o644); err != nil { - t.Fatal(err) - } - - gotStats := cgroups.NewStats() - - // use a fake root path to trigger the pod cgroup lookup. - err := statMemory(fakeCgroupDir, gotStats) - if err != nil { - t.Errorf("expected no error when statting memory for cgroupv2 root, but got %#+v", err) - } - - // result should be "memory.current" - var expectedUsageBytes uint64 = 123456789 - if gotStats.MemoryStats.Usage.Usage != expectedUsageBytes { - t.Errorf("parsed cgroupv2 memory.stat doesn't match expected result: \ngot %#v\nexpected %#v\n", gotStats.MemoryStats.Usage.Usage, expectedUsageBytes) - } - - // result should be "memory.max" - var expectedLimitBytes uint64 = 999999999 - if gotStats.MemoryStats.Usage.Limit != expectedLimitBytes { - t.Errorf("parsed cgroupv2 memory.stat doesn't match expected result: \ngot %#v\nexpected %#v\n", gotStats.MemoryStats.Usage.Limit, expectedLimitBytes) - } - - // result should be "memory.peak" - var expectedMaxUsageBytes uint64 = 987654321 - if gotStats.MemoryStats.Usage.MaxUsage != expectedMaxUsageBytes { - t.Errorf("parsed cgroupv2 memory.stat doesn't match expected result: \ngot %#v\nexpected %#v\n", gotStats.MemoryStats.Usage.MaxUsage, expectedMaxUsageBytes) - } -} - -func TestRootStatsFromMeminfo(t *testing.T) { - stats := &cgroups.Stats{ - MemoryStats: cgroups.MemoryStats{ - Stats: map[string]uint64{ - "anon": 790425600, - "file": 6502666240, - }, - }, - } - - if err := rootStatsFromMeminfo(stats); err != nil { - t.Fatal(err) - } - - // result is anon + file - var expectedUsageBytes uint64 = 7293091840 - if stats.MemoryStats.Usage.Usage != expectedUsageBytes { - t.Errorf("parsed cgroupv2 memory.stat doesn't match expected result: \ngot %d\nexpected %d\n", stats.MemoryStats.Usage.Usage, expectedUsageBytes) - } - - // swap is adjusted to mem+swap - if stats.MemoryStats.SwapUsage.Usage < stats.MemoryStats.Usage.Usage { - t.Errorf("swap usage %d should be at least mem usage %d", stats.MemoryStats.SwapUsage.Usage, stats.MemoryStats.Usage.Usage) - } - if stats.MemoryStats.SwapUsage.Limit < stats.MemoryStats.Usage.Limit { - t.Errorf("swap limit %d should be at least mem limit %d", stats.MemoryStats.SwapUsage.Limit, stats.MemoryStats.Usage.Limit) - } -} diff --git a/libcontainer/cgroups/fs2/misc_test.go b/libcontainer/cgroups/fs2/misc_test.go deleted file mode 100644 index a3f823951..000000000 --- a/libcontainer/cgroups/fs2/misc_test.go +++ /dev/null @@ -1,103 +0,0 @@ -package fs2 - -import ( - "os" - "path/filepath" - "strings" - "testing" - - "github.com/opencontainers/runc/libcontainer/cgroups" -) - -const exampleMiscCurrentData = `res_a 123 -res_b 456 -res_c 42` - -const exampleMiscEventsData = `res_a.max 1 -res_b.max 2 -res_c.max 3` - -func TestStatMiscPodCgroupEmpty(t *testing.T) { - // We're using a fake cgroupfs. - cgroups.TestMode = true - fakeCgroupDir := t.TempDir() - - // create empty misc.current and misc.events files to test the common case - // where no misc resource keys are available - for _, file := range []string{"misc.current", "misc.events"} { - if _, err := os.Create(filepath.Join(fakeCgroupDir, file)); err != nil { - t.Fatal(err) - } - } - - gotStats := cgroups.NewStats() - - err := statMisc(fakeCgroupDir, gotStats) - if err != nil { - t.Errorf("expected no error when statting empty misc.current/misc.events for cgroupv2, but got %#v", err) - } - - if len(gotStats.MiscStats) != 0 { - t.Errorf("parsed cgroupv2 misc.* returns unexpected resources: got %#v but expected nothing", gotStats.MiscStats) - } -} - -func TestStatMiscPodCgroupNotFound(t *testing.T) { - // We're using a fake cgroupfs. - cgroups.TestMode = true - fakeCgroupDir := t.TempDir() - - // only write misc.current to ensure pod cgroup usage - // still reads misc.events. - statPath := filepath.Join(fakeCgroupDir, "misc.current") - if err := os.WriteFile(statPath, []byte(exampleMiscCurrentData), 0o644); err != nil { - t.Fatal(err) - } - - gotStats := cgroups.NewStats() - - // use a fake root path to mismatch the file we wrote. - // this triggers the non-root path which should fail to find misc.events. - err := statMisc(fakeCgroupDir, gotStats) - if err == nil { - t.Errorf("expected error when statting misc.current for cgroupv2 root, but was nil") - } - - if !strings.Contains(err.Error(), "misc.events: no such file or directory") { - t.Errorf("expected error to contain 'misc.events: no such file or directory', but was %s", err.Error()) - } -} - -func TestStatMiscPodCgroup(t *testing.T) { - // We're using a fake cgroupfs. - cgroups.TestMode = true - fakeCgroupDir := t.TempDir() - - currentPath := filepath.Join(fakeCgroupDir, "misc.current") - if err := os.WriteFile(currentPath, []byte(exampleMiscCurrentData), 0o644); err != nil { - t.Fatal(err) - } - - eventsPath := filepath.Join(fakeCgroupDir, "misc.events") - if err := os.WriteFile(eventsPath, []byte(exampleMiscEventsData), 0o644); err != nil { - t.Fatal(err) - } - - gotStats := cgroups.NewStats() - - // use a fake root path to trigger the pod cgroup lookup. - err := statMisc(fakeCgroupDir, gotStats) - if err != nil { - t.Errorf("expected no error when statting misc for cgroupv2 root, but got %#+v", err) - } - - // make sure all res_* from exampleMisc*Data are returned - if len(gotStats.MiscStats) != 3 { - t.Errorf("parsed cgroupv2 misc doesn't return all expected resources: \ngot %#v\nexpected %#v\n", len(gotStats.MiscStats), 3) - } - - var expectedUsageBytes uint64 = 42 - if gotStats.MiscStats["res_c"].Usage != expectedUsageBytes { - t.Errorf("parsed cgroupv2 misc.current for res_c doesn't match expected result: \ngot %#v\nexpected %#v\n", gotStats.MiscStats["res_c"].Usage, expectedUsageBytes) - } -} diff --git a/libcontainer/cgroups/fs2/psi_test.go b/libcontainer/cgroups/fs2/psi_test.go deleted file mode 100644 index f70c19f78..000000000 --- a/libcontainer/cgroups/fs2/psi_test.go +++ /dev/null @@ -1,47 +0,0 @@ -package fs2 - -import ( - "os" - "path/filepath" - "reflect" - "testing" - - "github.com/opencontainers/runc/libcontainer/cgroups" -) - -func TestStatCPUPSI(t *testing.T) { - const examplePSIData = `some avg10=1.71 avg60=2.36 avg300=2.57 total=230548833 -full avg10=1.00 avg60=1.01 avg300=1.00 total=157622356` - - // We're using a fake cgroupfs. - cgroups.TestMode = true - - fakeCgroupDir := t.TempDir() - statPath := filepath.Join(fakeCgroupDir, "cpu.pressure") - - if err := os.WriteFile(statPath, []byte(examplePSIData), 0o644); err != nil { - t.Fatal(err) - } - - st, err := statPSI(fakeCgroupDir, "cpu.pressure") - if err != nil { - t.Fatal(err) - } - - if !reflect.DeepEqual(*st, cgroups.PSIStats{ - Some: cgroups.PSIData{ - Avg10: 1.71, - Avg60: 2.36, - Avg300: 2.57, - Total: 230548833, - }, - Full: cgroups.PSIData{ - Avg10: 1.00, - Avg60: 1.01, - Avg300: 1.00, - Total: 157622356, - }, - }) { - t.Errorf("unexpected PSI result: %+v", st) - } -} diff --git a/libcontainer/cgroups/fscommon/rdma_test.go b/libcontainer/cgroups/fscommon/rdma_test.go deleted file mode 100644 index ad15d515d..000000000 --- a/libcontainer/cgroups/fscommon/rdma_test.go +++ /dev/null @@ -1,57 +0,0 @@ -package fscommon - -import ( - "os" - "path/filepath" - "testing" - - "github.com/opencontainers/runc/libcontainer/cgroups" -) - -/* Roadmap for future */ -// (Low-priority) TODO: Check if it is possible to virtually mimic an actual RDMA device. -// TODO: Think of more edge-cases to add. - -// TestRdmaSet performs an E2E test of RdmaSet(), parseRdmaKV() using dummy device and a dummy cgroup file-system. -// Note: Following test does not guarantees that your host supports RDMA since this mocks underlying infrastructure. -func TestRdmaSet(t *testing.T) { - testCgroupPath := filepath.Join(t.TempDir(), "rdma") - - // Ensure the full mock cgroup path exists. - err := os.Mkdir(testCgroupPath, 0o755) - if err != nil { - t.Fatal(err) - } - - rdmaDevice := "mlx5_1" - maxHandles := uint32(100) - maxObjects := uint32(300) - - rdmaStubResource := &cgroups.Resources{ - Rdma: map[string]cgroups.LinuxRdma{ - rdmaDevice: { - HcaHandles: &maxHandles, - HcaObjects: &maxObjects, - }, - }, - } - - if err := RdmaSet(testCgroupPath, rdmaStubResource); err != nil { - t.Fatal(err) - } - - // The default rdma.max must be written. - rdmaEntries, err := readRdmaEntries(testCgroupPath, "rdma.max") - if err != nil { - t.Fatal(err) - } - if len(rdmaEntries) != 1 { - t.Fatal("rdma_test: Got the wrong values while parsing entries from rdma.max") - } - if rdmaEntries[0].HcaHandles != maxHandles { - t.Fatalf("rdma_test: Got the wrong value for hca_handles") - } - if rdmaEntries[0].HcaObjects != maxObjects { - t.Fatalf("rdma_test: Got the wrong value for hca_Objects") - } -} diff --git a/libcontainer/cgroups/fscommon/utils_test.go b/libcontainer/cgroups/fscommon/utils_test.go deleted file mode 100644 index 0339e9989..000000000 --- a/libcontainer/cgroups/fscommon/utils_test.go +++ /dev/null @@ -1,95 +0,0 @@ -package fscommon - -import ( - "math" - "os" - "path/filepath" - "strconv" - "testing" - - "github.com/opencontainers/runc/libcontainer/cgroups" -) - -const ( - cgroupFile = "cgroup.file" - floatValue = 2048.0 - floatString = "2048" -) - -func init() { - cgroups.TestMode = true -} - -func TestGetCgroupParamsInt(t *testing.T) { - // Setup tempdir. - tempDir := t.TempDir() - tempFile := filepath.Join(tempDir, cgroupFile) - - // Success. - if err := os.WriteFile(tempFile, []byte(floatString), 0o755); err != nil { - t.Fatal(err) - } - value, err := GetCgroupParamUint(tempDir, cgroupFile) - if err != nil { - t.Fatal(err) - } else if value != floatValue { - t.Fatalf("Expected %d to equal %f", value, floatValue) - } - - // Success with new line. - err = os.WriteFile(tempFile, []byte(floatString+"\n"), 0o755) - if err != nil { - t.Fatal(err) - } - value, err = GetCgroupParamUint(tempDir, cgroupFile) - if err != nil { - t.Fatal(err) - } else if value != floatValue { - t.Fatalf("Expected %d to equal %f", value, floatValue) - } - - // Success with negative values - err = os.WriteFile(tempFile, []byte("-12345"), 0o755) - if err != nil { - t.Fatal(err) - } - value, err = GetCgroupParamUint(tempDir, cgroupFile) - if err != nil { - t.Fatal(err) - } else if value != 0 { - t.Fatalf("Expected %d to equal %d", value, 0) - } - - // Success with negative values lesser than min int64 - s := strconv.FormatFloat(math.MinInt64, 'f', -1, 64) - err = os.WriteFile(tempFile, []byte(s), 0o755) - if err != nil { - t.Fatal(err) - } - value, err = GetCgroupParamUint(tempDir, cgroupFile) - if err != nil { - t.Fatal(err) - } else if value != 0 { - t.Fatalf("Expected %d to equal %d", value, 0) - } - - // Not a float. - err = os.WriteFile(tempFile, []byte("not-a-float"), 0o755) - if err != nil { - t.Fatal(err) - } - _, err = GetCgroupParamUint(tempDir, cgroupFile) - if err == nil { - t.Fatal("Expecting error, got none") - } - - // Unknown file. - err = os.Remove(tempFile) - if err != nil { - t.Fatal(err) - } - _, err = GetCgroupParamUint(tempDir, cgroupFile) - if err == nil { - t.Fatal("Expecting error, got none") - } -} diff --git a/libcontainer/cgroups/getallpids_test.go b/libcontainer/cgroups/getallpids_test.go deleted file mode 100644 index e6b063237..000000000 --- a/libcontainer/cgroups/getallpids_test.go +++ /dev/null @@ -1,17 +0,0 @@ -package cgroups - -import ( - "testing" -) - -func BenchmarkGetAllPids(b *testing.B) { - total := 0 - for i := 0; i < b.N; i++ { - i, err := GetAllPids("/sys/fs/cgroup") - if err != nil { - b.Fatal(err) - } - total += len(i) - } - b.Logf("iter: %d, total: %d", b.N, total) -} diff --git a/libcontainer/cgroups/manager/manager_test.go b/libcontainer/cgroups/manager/manager_test.go deleted file mode 100644 index dc861bb42..000000000 --- a/libcontainer/cgroups/manager/manager_test.go +++ /dev/null @@ -1,55 +0,0 @@ -package manager - -import ( - "testing" - - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/systemd" -) - -// TestNilResources checks that a cgroup manager do not panic when -// config.Resources is nil. While it does not make sense to use a -// manager with no resources, it should not result in a panic. -// -// This tests either v1 or v2 fs cgroup manager, depending on which -// cgroup version is available. -func TestNilResources(t *testing.T) { - testNilResources(t, false) -} - -// TestNilResourcesSystemd is the same as TestNilResources, -// only checking the systemd cgroup manager. -func TestNilResourcesSystemd(t *testing.T) { - if !systemd.IsRunningSystemd() { - t.Skip("requires systemd") - } - testNilResources(t, true) -} - -func testNilResources(t *testing.T, systemd bool) { - cg := &cgroups.Cgroup{} // .Resources is nil - cg.Systemd = systemd - mgr, err := New(cg) - if err != nil { - // Some managers require non-nil Resources during - // instantiation -- provide and retry. In such case - // we're mostly testing Set(nil) below. - cg.Resources = &cgroups.Resources{} - mgr, err = New(cg) - if err != nil { - t.Fatal(err) - } - } - _ = mgr.Apply(-1) - _ = mgr.Set(nil) - _ = mgr.Freeze(cgroups.Thawed) - _ = mgr.Exists() - _, _ = mgr.GetAllPids() - _, _ = mgr.GetCgroups() - _, _ = mgr.GetFreezerState() - _ = mgr.Path("") - _ = mgr.GetPaths() - _, _ = mgr.GetStats() - _, _ = mgr.OOMKillCount() - _ = mgr.Destroy() -} diff --git a/libcontainer/cgroups/systemd/cpuset_test.go b/libcontainer/cgroups/systemd/cpuset_test.go deleted file mode 100644 index bda31a5be..000000000 --- a/libcontainer/cgroups/systemd/cpuset_test.go +++ /dev/null @@ -1,55 +0,0 @@ -package systemd - -import ( - "bytes" - "testing" -) - -func TestRangeToBits(t *testing.T) { - testCases := []struct { - in string - out []byte - isErr bool - }{ - {in: "", isErr: true}, - {in: "0", out: []byte{1}}, - {in: "1", out: []byte{2}}, - {in: "0-1", out: []byte{3}}, - {in: "0,1", out: []byte{3}}, - {in: ",0,1,", out: []byte{3}}, - {in: "0-3", out: []byte{0x0f}}, - {in: "0,1,2-3", out: []byte{0x0f}}, - {in: "4-7", out: []byte{0xf0}}, - {in: "0-7", out: []byte{0xff}}, - {in: "0-15", out: []byte{0xff, 0xff}}, - {in: "16", out: []byte{0, 0, 1}}, - {in: "0-3,32-33", out: []byte{0x0f, 0, 0, 0, 3}}, - // extra spaces and tabs are ok - {in: "1, 2, 1-2", out: []byte{6}}, - {in: " , 1 , 3 , 5-7, ", out: []byte{0xea}}, - // somewhat large values - {in: "128-130,1", out: []byte{2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7}}, - - {in: "-", isErr: true}, - {in: "1-", isErr: true}, - {in: "-3", isErr: true}, - // bad range (start > end) - {in: "54-53", isErr: true}, - // kernel does not allow extra spaces inside a range - {in: "1 - 2", isErr: true}, - } - - for _, tc := range testCases { - out, err := RangeToBits(tc.in) - if err != nil { - if !tc.isErr { - t.Errorf("case %q: unexpected error: %v", tc.in, err) - } - - continue - } - if !bytes.Equal(out, tc.out) { - t.Errorf("case %q: expected %v, got %v", tc.in, tc.out, out) - } - } -} diff --git a/libcontainer/cgroups/systemd/freeze_test.go b/libcontainer/cgroups/systemd/freeze_test.go deleted file mode 100644 index 8ecf5e6e6..000000000 --- a/libcontainer/cgroups/systemd/freeze_test.go +++ /dev/null @@ -1,354 +0,0 @@ -package systemd - -import ( - "bufio" - "bytes" - "os" - "os/exec" - "strings" - "testing" - - "github.com/opencontainers/runc/libcontainer/cgroups" - "golang.org/x/sys/unix" -) - -func TestFreezeBeforeSet(t *testing.T) { - requireV1(t) - - testCases := []struct { - desc string - // Test input. - cg *cgroups.Cgroup - preFreeze bool - // Expected values. - // Before unit creation (Apply). - freeze0, thaw0 bool - // After unit creation. - freeze1, thaw1 bool - }{ - { - // A slice with SkipDevices. - desc: "slice,skip-devices", - cg: &cgroups.Cgroup{ - Name: "system-runc_test_freeze_1.slice", - Parent: "system.slice", - Resources: &cgroups.Resources{ - SkipDevices: true, - }, - }, - // Expected. - freeze0: false, - thaw0: false, - freeze1: false, - thaw1: false, - }, - { - // A scope with SkipDevices. Not a realistic scenario with runc - // (as container can't have SkipDevices == true), but possible - // for a standalone cgroup manager. - desc: "scope,skip-devices", - cg: &cgroups.Cgroup{ - ScopePrefix: "test", - Name: "testFreeze2", - Parent: "system.slice", - Resources: &cgroups.Resources{ - SkipDevices: true, - }, - }, - // Expected. - freeze0: false, - thaw0: false, - freeze1: false, - thaw1: false, - }, - { - // A slice that is about to be frozen in Set. - desc: "slice,will-freeze", - cg: &cgroups.Cgroup{ - Name: "system-runc_test_freeze_3.slice", - Parent: "system.slice", - Resources: &cgroups.Resources{ - Freezer: cgroups.Frozen, - }, - }, - // Expected. - freeze0: true, - thaw0: false, - freeze1: true, - thaw1: false, - }, - { - // A pre-frozen slice that should stay frozen. - desc: "slice,pre-frozen,will-freeze", - cg: &cgroups.Cgroup{ - Name: "system-runc_test_freeze_4.slice", - Parent: "system.slice", - Resources: &cgroups.Resources{ - Freezer: cgroups.Frozen, - }, - }, - preFreeze: true, - // Expected. - freeze0: true, // not actually frozen yet. - thaw0: false, - freeze1: false, - thaw1: false, - }, - { - // A pre-frozen scope with skip devices set. - desc: "scope,pre-frozen,skip-devices", - cg: &cgroups.Cgroup{ - ScopePrefix: "test", - Name: "testFreeze5", - Parent: "system.slice", - Resources: &cgroups.Resources{ - SkipDevices: true, - }, - }, - preFreeze: true, - // Expected. - freeze0: false, - thaw0: false, - freeze1: false, - thaw1: false, - }, - { - // A pre-frozen scope which will be thawed. - desc: "scope,pre-frozen", - cg: &cgroups.Cgroup{ - ScopePrefix: "test", - Name: "testFreeze6", - Parent: "system.slice", - Resources: &cgroups.Resources{}, - }, - preFreeze: true, - // Expected. - freeze0: true, // not actually frozen yet. - thaw0: true, - freeze1: false, - thaw1: false, - }, - } - - for _, tc := range testCases { - tc := tc - t.Run(tc.desc, func(t *testing.T) { - m, err := NewLegacyManager(tc.cg, nil) - if err != nil { - t.Fatal(err) - } - defer m.Destroy() //nolint:errcheck - - // Checks for a non-existent unit. - freeze, thaw, err := m.freezeBeforeSet(getUnitName(tc.cg), tc.cg.Resources) - if err != nil { - t.Fatal(err) - } - if freeze != tc.freeze0 || thaw != tc.thaw0 { - t.Errorf("before Apply (non-existent unit): expected freeze: %v, thaw: %v, got freeze: %v, thaw: %v", - tc.freeze0, tc.thaw0, freeze, thaw) - } - - // Create systemd unit. - pid := -1 - if strings.HasSuffix(getUnitName(tc.cg), ".scope") { - // Scopes require a process inside. - cmd := exec.Command("bash", "-c", "sleep 1m") - if err := cmd.Start(); err != nil { - t.Fatal(err) - } - pid = cmd.Process.Pid - // Make sure to not leave a zombie. - defer func() { - // These may fail, we don't care. - _ = cmd.Process.Kill() - _ = cmd.Wait() - }() - } - if err := m.Apply(pid); err != nil { - t.Fatal(err) - } - if tc.preFreeze { - if err := m.Freeze(cgroups.Frozen); err != nil { - t.Error(err) - return // no more checks - } - } - freeze, thaw, err = m.freezeBeforeSet(getUnitName(tc.cg), tc.cg.Resources) - if err != nil { - t.Error(err) - return // no more checks - } - if freeze != tc.freeze1 || thaw != tc.thaw1 { - t.Errorf("expected freeze: %v, thaw: %v, got freeze: %v, thaw: %v", - tc.freeze1, tc.thaw1, freeze, thaw) - } - // Destroy() timeouts on a frozen container, so we need to thaw it. - if tc.preFreeze { - if err := m.Freeze(cgroups.Thawed); err != nil { - t.Error(err) - } - } - // Destroy() does not kill processes in cgroup, so we should. - if pid != -1 { - if err = unix.Kill(pid, unix.SIGKILL); err != nil { - t.Errorf("unable to kill pid %d: %s", pid, err) - } - } - // Not really needed, but may help catch some bugs. - if err := m.Destroy(); err != nil { - t.Errorf("destroy: %s", err) - } - }) - } -} - -// requireV1 skips the test unless a set of requirements (cgroup v1, -// systemd, root) is met. -func requireV1(t *testing.T) { - t.Helper() - if cgroups.IsCgroup2UnifiedMode() { - t.Skip("Test requires cgroup v1.") - } - if !IsRunningSystemd() { - t.Skip("Test requires systemd.") - } - if os.Geteuid() != 0 { - t.Skip("Test requires root.") - } -} - -func TestFreezePodCgroup(t *testing.T) { - if !IsRunningSystemd() { - t.Skip("Test requires systemd.") - } - if os.Geteuid() != 0 { - t.Skip("Test requires root.") - } - - podConfig := &cgroups.Cgroup{ - Parent: "system.slice", - Name: "system-runc_test_pod.slice", - Resources: &cgroups.Resources{ - SkipDevices: true, - Freezer: cgroups.Frozen, - }, - } - // Create a "pod" cgroup (a systemd slice to hold containers), - // which is frozen initially. - pm := newManager(t, podConfig) - if err := pm.Apply(-1); err != nil { - t.Fatal(err) - } - - if err := pm.Set(podConfig.Resources); err != nil { - t.Fatal(err) - } - - // Check the pod is frozen. - pf, err := pm.GetFreezerState() - if err != nil { - t.Fatal(err) - } - if pf != cgroups.Frozen { - t.Fatalf("expected pod to be frozen, got %v", pf) - } - - // Create a "container" within the "pod" cgroup. - // This is not a real container, just a process in the cgroup. - containerConfig := &cgroups.Cgroup{ - Parent: "system-runc_test_pod.slice", - ScopePrefix: "test", - Name: "inner-container", - Resources: &cgroups.Resources{}, - } - - cmd := exec.Command("bash", "-c", "while read; do echo $REPLY; done") - cmd.Env = append(os.Environ(), "LANG=C") - - // Setup stdin. - stdinR, stdinW, err := os.Pipe() - if err != nil { - t.Fatal(err) - } - cmd.Stdin = stdinR - - // Setup stdout. - stdoutR, stdoutW, err := os.Pipe() - if err != nil { - t.Fatal(err) - } - cmd.Stdout = stdoutW - rdr := bufio.NewReader(stdoutR) - - // Setup stderr. - var stderr bytes.Buffer - cmd.Stderr = &stderr - - err = cmd.Start() - stdinR.Close() - stdoutW.Close() - defer func() { - _ = stdinW.Close() - _ = stdoutR.Close() - }() - if err != nil { - t.Fatal(err) - } - // Make sure to not leave a zombie. - defer func() { - // These may fail, we don't care. - _ = cmd.Process.Kill() - _ = cmd.Wait() - }() - - // Put the process into a cgroup. - cm := newManager(t, containerConfig) - - if err := cm.Apply(cmd.Process.Pid); err != nil { - t.Fatal(err) - } - if err := cm.Set(containerConfig.Resources); err != nil { - t.Fatal(err) - } - // Check that we put the "container" into the "pod" cgroup. - if !strings.HasPrefix(cm.Path("freezer"), pm.Path("freezer")) { - t.Fatalf("expected container cgroup path %q to be under pod cgroup path %q", - cm.Path("freezer"), pm.Path("freezer")) - } - // Check the container is not reported as frozen despite the frozen parent. - cf, err := cm.GetFreezerState() - if err != nil { - t.Fatal(err) - } - if cf != cgroups.Thawed { - t.Fatalf("expected container to be thawed, got %v", cf) - } - - // Unfreeze the pod. - if err := pm.Freeze(cgroups.Thawed); err != nil { - t.Fatal(err) - } - - cf, err = cm.GetFreezerState() - if err != nil { - t.Fatal(err) - } - if cf != cgroups.Thawed { - t.Fatalf("expected container to be thawed, got %v", cf) - } - - // Check the "container" works. - marker := "one two\n" - _, err = stdinW.WriteString(marker) - if err != nil { - t.Fatal(err) - } - reply, err := rdr.ReadString('\n') - if err != nil { - t.Fatalf("reading from container: %v", err) - } - if reply != marker { - t.Fatalf("expected %q, got %q", marker, reply) - } -} diff --git a/libcontainer/cgroups/systemd/systemd_test.go b/libcontainer/cgroups/systemd/systemd_test.go deleted file mode 100644 index 9980e780d..000000000 --- a/libcontainer/cgroups/systemd/systemd_test.go +++ /dev/null @@ -1,180 +0,0 @@ -package systemd - -import ( - "os" - "reflect" - "testing" - - systemdDbus "github.com/coreos/go-systemd/v22/dbus" - "github.com/opencontainers/runc/libcontainer/cgroups" -) - -func newManager(t *testing.T, config *cgroups.Cgroup) (m cgroups.Manager) { - t.Helper() - var err error - - if cgroups.IsCgroup2UnifiedMode() { - m, err = NewUnifiedManager(config, "") - } else { - m, err = NewLegacyManager(config, nil) - } - if err != nil { - t.Fatal(err) - } - t.Cleanup(func() { _ = m.Destroy() }) - - return m -} - -func TestSystemdVersion(t *testing.T) { - systemdVersionTests := []struct { - verStr string - expectedVer int - expectErr bool - }{ - {`"219"`, 219, false}, - {`"v245.4-1.fc32"`, 245, false}, - {`"241-1"`, 241, false}, - {`"v241-1"`, 241, false}, - {`333.45"`, 333, false}, - {`v321-0`, 321, false}, - {"NaN", -1, true}, - {"", -1, true}, - {"v", -1, true}, - } - for _, sdTest := range systemdVersionTests { - ver, err := systemdVersionAtoi(sdTest.verStr) - if !sdTest.expectErr && err != nil { - t.Errorf("systemdVersionAtoi(%s); want nil; got %v", sdTest.verStr, err) - } - if sdTest.expectErr && err == nil { - t.Errorf("systemdVersionAtoi(%s); wanted failure; got nil", sdTest.verStr) - } - if ver != sdTest.expectedVer { - t.Errorf("systemdVersionAtoi(%s); want %d; got %d", sdTest.verStr, sdTest.expectedVer, ver) - } - } -} - -func TestValidUnitTypes(t *testing.T) { - testCases := []struct { - unitName string - expectedUnitType string - }{ - {"system.slice", "Slice"}, - {"kubepods.slice", "Slice"}, - {"testing-container:ab.scope", "Scope"}, - } - for _, sdTest := range testCases { - unitType := getUnitType(sdTest.unitName) - if unitType != sdTest.expectedUnitType { - t.Errorf("getUnitType(%s); want %q; got %q", sdTest.unitName, sdTest.expectedUnitType, unitType) - } - } -} - -func TestUnitExistsIgnored(t *testing.T) { - if !IsRunningSystemd() { - t.Skip("Test requires systemd.") - } - if os.Geteuid() != 0 { - t.Skip("Test requires root.") - } - - podConfig := &cgroups.Cgroup{ - Parent: "system.slice", - Name: "system-runc_test_exists.slice", - Resources: &cgroups.Resources{}, - } - // Create "pods" cgroup (a systemd slice to hold containers). - pm := newManager(t, podConfig) - - // create twice to make sure "UnitExists" error is ignored. - for i := 0; i < 2; i++ { - if err := pm.Apply(-1); err != nil { - t.Fatal(err) - } - } -} - -func TestUnifiedResToSystemdProps(t *testing.T) { - if !IsRunningSystemd() { - t.Skip("Test requires systemd.") - } - if !cgroups.IsCgroup2UnifiedMode() { - t.Skip("cgroup v2 is required") - } - - cm := newDbusConnManager(os.Geteuid() != 0) - - testCases := []struct { - name string - minVer int - res map[string]string - expError bool - expProps []systemdDbus.Property - }{ - { - name: "empty map", - res: map[string]string{}, - }, - { - name: "only cpu.idle=1", - minVer: cpuIdleSupportedVersion, - res: map[string]string{ - "cpu.idle": "1", - }, - expProps: []systemdDbus.Property{ - newProp("CPUWeight", uint64(0)), - }, - }, - { - name: "only cpu.idle=0", - minVer: cpuIdleSupportedVersion, - res: map[string]string{ - "cpu.idle": "0", - }, - }, - { - name: "cpu.idle=1 and cpu.weight=1000", - minVer: cpuIdleSupportedVersion, - res: map[string]string{ - "cpu.idle": "1", - "cpu.weight": "1000", - }, - expProps: []systemdDbus.Property{ - newProp("CPUWeight", uint64(0)), - }, - }, - { - name: "cpu.idle=0 and cpu.weight=1000", - minVer: cpuIdleSupportedVersion, - res: map[string]string{ - "cpu.idle": "0", - "cpu.weight": "1000", - }, - expProps: []systemdDbus.Property{ - newProp("CPUWeight", uint64(1000)), - }, - }, - } - - for _, tc := range testCases { - tc := tc - t.Run(tc.name, func(t *testing.T) { - if tc.minVer != 0 && systemdVersion(cm) < tc.minVer { - t.Skipf("requires systemd >= %d", tc.minVer) - } - props, err := unifiedResToSystemdProps(cm, tc.res) - if err != nil && !tc.expError { - t.Fatalf("expected no error, got: %v", err) - } - if err == nil && tc.expError { - t.Fatal("expected error, got nil") - } - if !reflect.DeepEqual(tc.expProps, props) { - t.Errorf("wrong properties (exp %+v, got %+v)", tc.expProps, props) - } - }) - } -} diff --git a/libcontainer/cgroups/utils_test.go b/libcontainer/cgroups/utils_test.go deleted file mode 100644 index 58ac85a58..000000000 --- a/libcontainer/cgroups/utils_test.go +++ /dev/null @@ -1,691 +0,0 @@ -package cgroups - -import ( - "bytes" - "errors" - "path/filepath" - "reflect" - "strings" - "testing" - - "github.com/moby/sys/mountinfo" - "golang.org/x/sys/unix" -) - -const fedoraMountinfo = `15 35 0:3 / /proc rw,nosuid,nodev,noexec,relatime shared:5 - proc proc rw -16 35 0:14 / /sys rw,nosuid,nodev,noexec,relatime shared:6 - sysfs sysfs rw,seclabel -17 35 0:5 / /dev rw,nosuid shared:2 - devtmpfs devtmpfs rw,seclabel,size=8056484k,nr_inodes=2014121,mode=755 -18 16 0:15 / /sys/kernel/security rw,nosuid,nodev,noexec,relatime shared:7 - securityfs securityfs rw -19 16 0:13 / /sys/fs/selinux rw,relatime shared:8 - selinuxfs selinuxfs rw -20 17 0:16 / /dev/shm rw,nosuid,nodev shared:3 - tmpfs tmpfs rw,seclabel -21 17 0:10 / /dev/pts rw,nosuid,noexec,relatime shared:4 - devpts devpts rw,seclabel,gid=5,mode=620,ptmxmode=000 -22 35 0:17 / /run rw,nosuid,nodev shared:21 - tmpfs tmpfs rw,seclabel,mode=755 -23 16 0:18 / /sys/fs/cgroup rw,nosuid,nodev,noexec shared:9 - tmpfs tmpfs rw,seclabel,mode=755 -24 23 0:19 / /sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime shared:10 - cgroup cgroup rw,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd -25 16 0:20 / /sys/fs/pstore rw,nosuid,nodev,noexec,relatime shared:20 - pstore pstore rw -26 23 0:21 / /sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime shared:11 - cgroup cgroup rw,cpuset,clone_children -27 23 0:22 / /sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime shared:12 - cgroup cgroup rw,cpuacct,cpu,clone_children -28 23 0:23 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:13 - cgroup cgroup rw,memory,clone_children -29 23 0:24 / /sys/fs/cgroup/devices rw,nosuid,nodev,noexec,relatime shared:14 - cgroup cgroup rw,devices,clone_children -30 23 0:25 / /sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime shared:15 - cgroup cgroup rw,freezer,clone_children -31 23 0:26 / /sys/fs/cgroup/net_cls rw,nosuid,nodev,noexec,relatime shared:16 - cgroup cgroup rw,net_cls,clone_children -32 23 0:27 / /sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime shared:17 - cgroup cgroup rw,blkio,clone_children -33 23 0:28 / /sys/fs/cgroup/perf_event rw,nosuid,nodev,noexec,relatime shared:18 - cgroup cgroup rw,perf_event,clone_children -34 23 0:29 / /sys/fs/cgroup/hugetlb rw,nosuid,nodev,noexec,relatime shared:19 - cgroup cgroup rw,hugetlb,clone_children -35 1 253:2 / / rw,relatime shared:1 - ext4 /dev/mapper/ssd-root--f20 rw,seclabel,data=ordered -36 15 0:30 / /proc/sys/fs/binfmt_misc rw,relatime shared:22 - autofs systemd-1 rw,fd=38,pgrp=1,timeout=300,minproto=5,maxproto=5,direct -37 17 0:12 / /dev/mqueue rw,relatime shared:23 - mqueue mqueue rw,seclabel -38 35 0:31 / /tmp rw shared:24 - tmpfs tmpfs rw,seclabel -39 17 0:32 / /dev/hugepages rw,relatime shared:25 - hugetlbfs hugetlbfs rw,seclabel -40 16 0:7 / /sys/kernel/debug rw,relatime shared:26 - debugfs debugfs rw -41 16 0:33 / /sys/kernel/config rw,relatime shared:27 - configfs configfs rw -42 35 0:34 / /var/lib/nfs/rpc_pipefs rw,relatime shared:28 - rpc_pipefs sunrpc rw -43 15 0:35 / /proc/fs/nfsd rw,relatime shared:29 - nfsd sunrpc rw -45 35 8:17 / /boot rw,relatime shared:30 - ext4 /dev/sdb1 rw,seclabel,data=ordered -46 35 253:4 / /home rw,relatime shared:31 - ext4 /dev/mapper/ssd-home rw,seclabel,data=ordered -47 35 253:5 / /var/lib/libvirt/images rw,noatime,nodiratime shared:32 - ext4 /dev/mapper/ssd-virt rw,seclabel,discard,data=ordered -48 35 253:12 / /mnt/old rw,relatime shared:33 - ext4 /dev/mapper/HelpDeskRHEL6-FedoraRoot rw,seclabel,data=ordered -121 22 0:36 / /run/user/1000/gvfs rw,nosuid,nodev,relatime shared:104 - fuse.gvfsd-fuse gvfsd-fuse rw,user_id=1000,group_id=1000 -124 16 0:37 / /sys/fs/fuse/connections rw,relatime shared:107 - fusectl fusectl rw -165 38 253:3 / /tmp/mnt rw,relatime shared:147 - ext4 /dev/mapper/ssd-root rw,seclabel,data=ordered -167 35 253:15 / /var/lib/docker/devicemapper/mnt/aae4076022f0e2b80a2afbf8fc6df450c52080191fcef7fb679a73e6f073e5c2 rw,relatime shared:149 - ext4 /dev/mapper/docker-253:2-425882-aae4076022f0e2b80a2afbf8fc6df450c52080191fcef7fb679a73e6f073e5c2 rw,seclabel,discard,stripe=16,data=ordered -171 35 253:16 / /var/lib/docker/devicemapper/mnt/c71be651f114db95180e472f7871b74fa597ee70a58ccc35cb87139ddea15373 rw,relatime shared:153 - ext4 /dev/mapper/docker-253:2-425882-c71be651f114db95180e472f7871b74fa597ee70a58ccc35cb87139ddea15373 rw,seclabel,discard,stripe=16,data=ordered -175 35 253:17 / /var/lib/docker/devicemapper/mnt/1bac6ab72862d2d5626560df6197cf12036b82e258c53d981fa29adce6f06c3c rw,relatime shared:157 - ext4 /dev/mapper/docker-253:2-425882-1bac6ab72862d2d5626560df6197cf12036b82e258c53d981fa29adce6f06c3c rw,seclabel,discard,stripe=16,data=ordered -179 35 253:18 / /var/lib/docker/devicemapper/mnt/d710a357d77158e80d5b2c55710ae07c94e76d34d21ee7bae65ce5418f739b09 rw,relatime shared:161 - ext4 /dev/mapper/docker-253:2-425882-d710a357d77158e80d5b2c55710ae07c94e76d34d21ee7bae65ce5418f739b09 rw,seclabel,discard,stripe=16,data=ordered -183 35 253:19 / /var/lib/docker/devicemapper/mnt/6479f52366114d5f518db6837254baab48fab39f2ac38d5099250e9a6ceae6c7 rw,relatime shared:165 - ext4 /dev/mapper/docker-253:2-425882-6479f52366114d5f518db6837254baab48fab39f2ac38d5099250e9a6ceae6c7 rw,seclabel,discard,stripe=16,data=ordered -187 35 253:20 / /var/lib/docker/devicemapper/mnt/8d9df91c4cca5aef49eeb2725292aab324646f723a7feab56be34c2ad08268e1 rw,relatime shared:169 - ext4 /dev/mapper/docker-253:2-425882-8d9df91c4cca5aef49eeb2725292aab324646f723a7feab56be34c2ad08268e1 rw,seclabel,discard,stripe=16,data=ordered -191 35 253:21 / /var/lib/docker/devicemapper/mnt/c8240b768603d32e920d365dc9d1dc2a6af46cd23e7ae819947f969e1b4ec661 rw,relatime shared:173 - ext4 /dev/mapper/docker-253:2-425882-c8240b768603d32e920d365dc9d1dc2a6af46cd23e7ae819947f969e1b4ec661 rw,seclabel,discard,stripe=16,data=ordered -195 35 253:22 / /var/lib/docker/devicemapper/mnt/2eb3a01278380bbf3ed12d86ac629eaa70a4351301ee307a5cabe7b5f3b1615f rw,relatime shared:177 - ext4 /dev/mapper/docker-253:2-425882-2eb3a01278380bbf3ed12d86ac629eaa70a4351301ee307a5cabe7b5f3b1615f rw,seclabel,discard,stripe=16,data=ordered -199 35 253:23 / /var/lib/docker/devicemapper/mnt/37a17fb7c9d9b80821235d5f2662879bd3483915f245f9b49cdaa0e38779b70b rw,relatime shared:181 - ext4 /dev/mapper/docker-253:2-425882-37a17fb7c9d9b80821235d5f2662879bd3483915f245f9b49cdaa0e38779b70b rw,seclabel,discard,stripe=16,data=ordered -203 35 253:24 / /var/lib/docker/devicemapper/mnt/aea459ae930bf1de913e2f29428fd80ee678a1e962d4080019d9f9774331ee2b rw,relatime shared:185 - ext4 /dev/mapper/docker-253:2-425882-aea459ae930bf1de913e2f29428fd80ee678a1e962d4080019d9f9774331ee2b rw,seclabel,discard,stripe=16,data=ordered -207 35 253:25 / /var/lib/docker/devicemapper/mnt/928ead0bc06c454bd9f269e8585aeae0a6bd697f46dc8754c2a91309bc810882 rw,relatime shared:189 - ext4 /dev/mapper/docker-253:2-425882-928ead0bc06c454bd9f269e8585aeae0a6bd697f46dc8754c2a91309bc810882 rw,seclabel,discard,stripe=16,data=ordered -211 35 253:26 / /var/lib/docker/devicemapper/mnt/0f284d18481d671644706e7a7244cbcf63d590d634cc882cb8721821929d0420 rw,relatime shared:193 - ext4 /dev/mapper/docker-253:2-425882-0f284d18481d671644706e7a7244cbcf63d590d634cc882cb8721821929d0420 rw,seclabel,discard,stripe=16,data=ordered -215 35 253:27 / /var/lib/docker/devicemapper/mnt/d9dd16722ab34c38db2733e23f69e8f4803ce59658250dd63e98adff95d04919 rw,relatime shared:197 - ext4 /dev/mapper/docker-253:2-425882-d9dd16722ab34c38db2733e23f69e8f4803ce59658250dd63e98adff95d04919 rw,seclabel,discard,stripe=16,data=ordered -219 35 253:28 / /var/lib/docker/devicemapper/mnt/bc4500479f18c2c08c21ad5282e5f826a016a386177d9874c2764751c031d634 rw,relatime shared:201 - ext4 /dev/mapper/docker-253:2-425882-bc4500479f18c2c08c21ad5282e5f826a016a386177d9874c2764751c031d634 rw,seclabel,discard,stripe=16,data=ordered -223 35 253:29 / /var/lib/docker/devicemapper/mnt/7770c8b24eb3d5cc159a065910076938910d307ab2f5d94e1dc3b24c06ee2c8a rw,relatime shared:205 - ext4 /dev/mapper/docker-253:2-425882-7770c8b24eb3d5cc159a065910076938910d307ab2f5d94e1dc3b24c06ee2c8a rw,seclabel,discard,stripe=16,data=ordered -227 35 253:30 / /var/lib/docker/devicemapper/mnt/c280cd3d0bf0aa36b478b292279671624cceafc1a67eaa920fa1082601297adf rw,relatime shared:209 - ext4 /dev/mapper/docker-253:2-425882-c280cd3d0bf0aa36b478b292279671624cceafc1a67eaa920fa1082601297adf rw,seclabel,discard,stripe=16,data=ordered -231 35 253:31 / /var/lib/docker/devicemapper/mnt/8b59a7d9340279f09fea67fd6ad89ddef711e9e7050eb647984f8b5ef006335f rw,relatime shared:213 - ext4 /dev/mapper/docker-253:2-425882-8b59a7d9340279f09fea67fd6ad89ddef711e9e7050eb647984f8b5ef006335f rw,seclabel,discard,stripe=16,data=ordered -235 35 253:32 / /var/lib/docker/devicemapper/mnt/1a28059f29eda821578b1bb27a60cc71f76f846a551abefabce6efd0146dce9f rw,relatime shared:217 - ext4 /dev/mapper/docker-253:2-425882-1a28059f29eda821578b1bb27a60cc71f76f846a551abefabce6efd0146dce9f rw,seclabel,discard,stripe=16,data=ordered -239 35 253:33 / /var/lib/docker/devicemapper/mnt/e9aa60c60128cad1 rw,relatime shared:221 - ext4 /dev/mapper/docker-253:2-425882-e9aa60c60128cad1 rw,seclabel,discard,stripe=16,data=ordered -243 35 253:34 / /var/lib/docker/devicemapper/mnt/5fec11304b6f4713fea7b6ccdcc1adc0a1966187f590fe25a8227428a8df275d-init rw,relatime shared:225 - ext4 /dev/mapper/docker-253:2-425882-5fec11304b6f4713fea7b6ccdcc1adc0a1966187f590fe25a8227428a8df275d-init rw,seclabel,discard,stripe=16,data=ordered -247 35 253:35 / /var/lib/docker/devicemapper/mnt/5fec11304b6f4713fea7b6ccdcc1adc0a1966187f590fe25a8227428a8df275d rw,relatime shared:229 - ext4 /dev/mapper/docker-253:2-425882-5fec11304b6f4713fea7b6ccdcc1adc0a1966187f590fe25a8227428a8df275d rw,seclabel,discard,stripe=16,data=ordered -31 21 0:23 / /DATA/foo_bla_bla rw,relatime - cifs //foo/BLA\040BLA\040BLA/ rw,sec=ntlm,cache=loose,unc=\\foo\BLA BLA BLA,username=my_login,domain=mydomain.com,uid=12345678,forceuid,gid=12345678,forcegid,addr=10.1.30.10,file_mode=0755,dir_mode=0755,nounix,rsize=61440,wsize=65536,actimeo=1` - -const systemdMountinfo = `115 83 0:32 / / rw,relatime - aufs none rw,si=c0bd3d3,dio,dirperm1 -116 115 0:35 / /proc rw,nosuid,nodev,noexec,relatime - proc proc rw -117 115 0:36 / /dev rw,nosuid - tmpfs tmpfs rw,mode=755 -118 117 0:37 / /dev/pts rw,nosuid,noexec,relatime - devpts devpts rw,gid=5,mode=620,ptmxmode=666 -119 115 0:38 / /sys rw,nosuid,nodev,noexec,relatime - sysfs sysfs rw -120 119 0:39 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - tmpfs tmpfs rw,mode=755 -121 120 0:19 /system.slice/docker-dc4eaa1a34ec4d593bc0125d31eea823a1d76ae483aeb1409cca80304e34da2e.scope /sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,xattr,release_agent=/lib/systemd/systemd-cgroups-agent,name=systemd -122 120 0:20 /system.slice/docker-dc4eaa1a34ec4d593bc0125d31eea823a1d76ae483aeb1409cca80304e34da2e.scope /sys/fs/cgroup/devices rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,devices -123 120 0:21 /system.slice/docker-dc4eaa1a34ec4d593bc0125d31eea823a1d76ae483aeb1409cca80304e34da2e.scope /sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,freezer -124 120 0:22 /system.slice/docker-dc4eaa1a34ec4d593bc0125d31eea823a1d76ae483aeb1409cca80304e34da2e.scope /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,memory -125 120 0:23 /system.slice/docker-dc4eaa1a34ec4d593bc0125d31eea823a1d76ae483aeb1409cca80304e34da2e.scope /sys/fs/cgroup/net_cls,net_prio rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,net_cls,net_prio -126 120 0:24 /system.slice/docker-dc4eaa1a34ec4d593bc0125d31eea823a1d76ae483aeb1409cca80304e34da2e.scope /sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,blkio -127 120 0:25 /system.slice/docker-dc4eaa1a34ec4d593bc0125d31eea823a1d76ae483aeb1409cca80304e34da2e.scope /sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,cpuset,clone_children -128 120 0:26 /system.slice/docker-dc4eaa1a34ec4d593bc0125d31eea823a1d76ae483aeb1409cca80304e34da2e.scope /sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,cpu,cpuacct -129 120 0:27 /system.slice/docker-dc4eaa1a34ec4d593bc0125d31eea823a1d76ae483aeb1409cca80304e34da2e.scope /sys/fs/cgroup/perf_event rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,perf_event,release_agent=/run/cgmanager/agents/cgm-release-agent.perf_event -130 115 43:0 /var/lib/docker/volumes/a44a712176377f57c094397330ee04387284c478364eb25f4c3d25f775f25c26/_data /var/lib/docker rw,relatime - ext4 /dev/nbd0 rw,data=ordered -131 115 43:0 /var/lib/docker/containers/dc4eaa1a34ec4d593bc0125d31eea823a1d76ae483aeb1409cca80304e34da2e/resolv.conf /etc/resolv.conf rw,relatime - ext4 /dev/nbd0 rw,data=ordered -132 115 43:0 /var/lib/docker/containers/dc4eaa1a34ec4d593bc0125d31eea823a1d76ae483aeb1409cca80304e34da2e/hostname /etc/hostname rw,relatime - ext4 /dev/nbd0 rw,data=ordered -133 115 43:0 /var/lib/docker/containers/dc4eaa1a34ec4d593bc0125d31eea823a1d76ae483aeb1409cca80304e34da2e/hosts /etc/hosts rw,relatime - ext4 /dev/nbd0 rw,data=ordered -134 117 0:33 / /dev/shm rw,nosuid,nodev,noexec,relatime - tmpfs shm rw,size=65536k -135 117 0:13 / /dev/mqueue rw,nosuid,nodev,noexec,relatime - mqueue mqueue rw -136 117 0:12 /1 /dev/console rw,nosuid,noexec,relatime - devpts none rw,gid=5,mode=620,ptmxmode=000 -84 115 0:40 / /tmp rw,relatime - tmpfs none rw` - -const bedrockMountinfo = `120 17 0:28 / /sys/fs/cgroup ro,nosuid,nodev,noexec shared:16 - tmpfs tmpfs ro,mode=755 -124 28 0:28 / /bedrock/strata/arch/sys/fs/cgroup rw,nosuid,nodev,noexec shared:16 - tmpfs tmpfs ro,mode=755 -123 53 0:28 / /bedrock/strata/fallback/sys/fs/cgroup rw,nosuid,nodev,noexec shared:16 - tmpfs tmpfs ro,mode=755 -122 71 0:28 / /bedrock/strata/gentoo/sys/fs/cgroup rw,nosuid,nodev,noexec shared:16 - tmpfs tmpfs ro,mode=755 -121 89 0:28 / /bedrock/strata/kde/sys/fs/cgroup rw,nosuid,nodev,noexec shared:16 - tmpfs tmpfs ro,mode=755 -125 120 0:29 / /sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime shared:17 - cgroup cgroup rw,xattr,release_agent=/lib/systemd/systemd-cgroups-agent,name=systemd -129 124 0:29 / /bedrock/strata/arch/sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime shared:17 - cgroup cgroup rw,xattr,release_agent=/lib/systemd/systemd-cgroups-agent,name=systemd -128 123 0:29 / /bedrock/strata/fallback/sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime shared:17 - cgroup cgroup rw,xattr,release_agent=/lib/systemd/systemd-cgroups-agent,name=systemd -127 122 0:29 / /bedrock/strata/gentoo/sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime shared:17 - cgroup cgroup rw,xattr,release_agent=/lib/systemd/systemd-cgroups-agent,name=systemd -126 121 0:29 / /bedrock/strata/kde/sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime shared:17 - cgroup cgroup rw,xattr,release_agent=/lib/systemd/systemd-cgroups-agent,name=systemd -140 120 0:32 / /sys/fs/cgroup/net_cls,net_prio rw,nosuid,nodev,noexec,relatime shared:48 - cgroup cgroup rw,net_cls,net_prio -144 124 0:32 / /bedrock/strata/arch/sys/fs/cgroup/net_cls,net_prio rw,nosuid,nodev,noexec,relatime shared:48 - cgroup cgroup rw,net_cls,net_prio -143 123 0:32 / /bedrock/strata/fallback/sys/fs/cgroup/net_cls,net_prio rw,nosuid,nodev,noexec,relatime shared:48 - cgroup cgroup rw,net_cls,net_prio -142 122 0:32 / /bedrock/strata/gentoo/sys/fs/cgroup/net_cls,net_prio rw,nosuid,nodev,noexec,relatime shared:48 - cgroup cgroup rw,net_cls,net_prio -141 121 0:32 / /bedrock/strata/kde/sys/fs/cgroup/net_cls,net_prio rw,nosuid,nodev,noexec,relatime shared:48 - cgroup cgroup rw,net_cls,net_prio -145 120 0:33 / /sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime shared:49 - cgroup cgroup rw,blkio -149 124 0:33 / /bedrock/strata/arch/sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime shared:49 - cgroup cgroup rw,blkio -148 123 0:33 / /bedrock/strata/fallback/sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime shared:49 - cgroup cgroup rw,blkio -147 122 0:33 / /bedrock/strata/gentoo/sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime shared:49 - cgroup cgroup rw,blkio -146 121 0:33 / /bedrock/strata/kde/sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime shared:49 - cgroup cgroup rw,blkio -150 120 0:34 / /sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime shared:50 - cgroup cgroup rw,cpu,cpuacct -154 124 0:34 / /bedrock/strata/arch/sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime shared:50 - cgroup cgroup rw,cpu,cpuacct -153 123 0:34 / /bedrock/strata/fallback/sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime shared:50 - cgroup cgroup rw,cpu,cpuacct -152 122 0:34 / /bedrock/strata/gentoo/sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime shared:50 - cgroup cgroup rw,cpu,cpuacct -151 121 0:34 / /bedrock/strata/kde/sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime shared:50 - cgroup cgroup rw,cpu,cpuacct -155 120 0:35 / /sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime shared:51 - cgroup cgroup rw,cpuset -159 124 0:35 / /bedrock/strata/arch/sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime shared:51 - cgroup cgroup rw,cpuset -158 123 0:35 / /bedrock/strata/fallback/sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime shared:51 - cgroup cgroup rw,cpuset -157 122 0:35 / /bedrock/strata/gentoo/sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime shared:51 - cgroup cgroup rw,cpuset -156 121 0:35 / /bedrock/strata/kde/sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime shared:51 - cgroup cgroup rw,cpuset -160 120 0:36 / /sys/fs/cgroup/devices rw,nosuid,nodev,noexec,relatime shared:52 - cgroup cgroup rw,devices -164 124 0:36 / /bedrock/strata/arch/sys/fs/cgroup/devices rw,nosuid,nodev,noexec,relatime shared:52 - cgroup cgroup rw,devices -163 123 0:36 / /bedrock/strata/fallback/sys/fs/cgroup/devices rw,nosuid,nodev,noexec,relatime shared:52 - cgroup cgroup rw,devices -162 122 0:36 / /bedrock/strata/gentoo/sys/fs/cgroup/devices rw,nosuid,nodev,noexec,relatime shared:52 - cgroup cgroup rw,devices -161 121 0:36 / /bedrock/strata/kde/sys/fs/cgroup/devices rw,nosuid,nodev,noexec,relatime shared:52 - cgroup cgroup rw,devices -165 120 0:37 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:53 - cgroup cgroup rw,memory -169 124 0:37 / /bedrock/strata/arch/sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:53 - cgroup cgroup rw,memory -168 123 0:37 / /bedrock/strata/fallback/sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:53 - cgroup cgroup rw,memory -167 122 0:37 / /bedrock/strata/gentoo/sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:53 - cgroup cgroup rw,memory -166 121 0:37 / /bedrock/strata/kde/sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:53 - cgroup cgroup rw,memory -170 120 0:38 / /sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime shared:54 - cgroup cgroup rw,freezer -174 124 0:38 / /bedrock/strata/arch/sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime shared:54 - cgroup cgroup rw,freezer -173 123 0:38 / /bedrock/strata/fallback/sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime shared:54 - cgroup cgroup rw,freezer -172 122 0:38 / /bedrock/strata/gentoo/sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime shared:54 - cgroup cgroup rw,freezer -171 121 0:38 / /bedrock/strata/kde/sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime shared:54 - cgroup cgroup rw,freezer -175 120 0:39 / /sys/fs/cgroup/pids rw,nosuid,nodev,noexec,relatime shared:55 - cgroup cgroup rw,pids -179 124 0:39 / /bedrock/strata/arch/sys/fs/cgroup/pids rw,nosuid,nodev,noexec,relatime shared:55 - cgroup cgroup rw,pids -178 123 0:39 / /bedrock/strata/fallback/sys/fs/cgroup/pids rw,nosuid,nodev,noexec,relatime shared:55 - cgroup cgroup rw,pids -177 122 0:39 / /bedrock/strata/gentoo/sys/fs/cgroup/pids rw,nosuid,nodev,noexec,relatime shared:55 - cgroup cgroup rw,pids -176 121 0:39 / /bedrock/strata/kde/sys/fs/cgroup/pids rw,nosuid,nodev,noexec,relatime shared:55 - cgroup cgroup rw,pids -180 120 0:40 / /sys/fs/cgroup/perf_event rw,nosuid,nodev,noexec,relatime shared:56 - cgroup cgroup rw,perf_event -184 124 0:40 / /bedrock/strata/arch/sys/fs/cgroup/perf_event rw,nosuid,nodev,noexec,relatime shared:56 - cgroup cgroup rw,perf_event -183 123 0:40 / /bedrock/strata/fallback/sys/fs/cgroup/perf_event rw,nosuid,nodev,noexec,relatime shared:56 - cgroup cgroup rw,perf_event -182 122 0:40 / /bedrock/strata/gentoo/sys/fs/cgroup/perf_event rw,nosuid,nodev,noexec,relatime shared:56 - cgroup cgroup rw,perf_event -181 121 0:40 / /bedrock/strata/kde/sys/fs/cgroup/perf_event rw,nosuid,nodev,noexec,relatime shared:56 - cgroup cgroup rw,perf_event` - -const cgroup2Mountinfo = `18 64 0:18 / /sys rw,nosuid,nodev,noexec,relatime shared:6 - sysfs sysfs rw,seclabel -19 64 0:4 / /proc rw,nosuid,nodev,noexec,relatime shared:5 - proc proc rw -20 64 0:6 / /dev rw,nosuid shared:2 - devtmpfs devtmpfs rw,seclabel,size=8171204k,nr_inodes=2042801,mode=755 -21 18 0:19 / /sys/kernel/security rw,nosuid,nodev,noexec,relatime shared:7 - securityfs securityfs rw -22 20 0:20 / /dev/shm rw,nosuid,nodev shared:3 - tmpfs tmpfs rw,seclabel -23 20 0:21 / /dev/pts rw,nosuid,noexec,relatime shared:4 - devpts devpts rw,seclabel,gid=5,mode=620,ptmxmode=000 -24 64 0:22 / /run rw,nosuid,nodev shared:24 - tmpfs tmpfs rw,seclabel,mode=755 -25 18 0:23 / /sys/fs/cgroup ro,nosuid,nodev,noexec shared:8 - tmpfs tmpfs ro,seclabel,mode=755 -26 25 0:24 / /sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime shared:9 - cgroup2 cgroup rw -27 18 0:25 / /sys/fs/pstore rw,nosuid,nodev,noexec,relatime shared:20 - pstore pstore rw,seclabel -28 18 0:26 / /sys/firmware/efi/efivars rw,nosuid,nodev,noexec,relatime shared:21 - efivarfs efivarfs rw -29 25 0:27 / /sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime shared:10 - cgroup cgroup rw,cpu,cpuacct -30 25 0:28 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:11 - cgroup cgroup rw,memory -31 25 0:29 / /sys/fs/cgroup/net_cls,net_prio rw,nosuid,nodev,noexec,relatime shared:12 - cgroup cgroup rw,net_cls,net_prio -32 25 0:30 / /sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime shared:13 - cgroup cgroup rw,blkio -33 25 0:31 / /sys/fs/cgroup/perf_event rw,nosuid,nodev,noexec,relatime shared:14 - cgroup cgroup rw,perf_event -34 25 0:32 / /sys/fs/cgroup/hugetlb rw,nosuid,nodev,noexec,relatime shared:15 - cgroup cgroup rw,hugetlb -35 25 0:33 / /sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime shared:16 - cgroup cgroup rw,freezer -36 25 0:34 / /sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime shared:17 - cgroup cgroup rw,cpuset -37 25 0:35 / /sys/fs/cgroup/devices rw,nosuid,nodev,noexec,relatime shared:18 - cgroup cgroup rw,devices -38 25 0:36 / /sys/fs/cgroup/pids rw,nosuid,nodev,noexec,relatime shared:19 - cgroup cgroup rw,pids -61 18 0:37 / /sys/kernel/config rw,relatime shared:22 - configfs configfs rw -64 0 253:0 / / rw,relatime shared:1 - ext4 /dev/mapper/fedora_dhcp--16--129-root rw,seclabel,data=ordered -39 18 0:17 / /sys/fs/selinux rw,relatime shared:23 - selinuxfs selinuxfs rw -40 20 0:16 / /dev/mqueue rw,relatime shared:25 - mqueue mqueue rw,seclabel -41 20 0:39 / /dev/hugepages rw,relatime shared:26 - hugetlbfs hugetlbfs rw,seclabel -` - -func TestGetCgroupMounts(t *testing.T) { - type testData struct { - mountInfo string - root string - // all is the total number of records expected with all=true, - // or 0 for no extra records expected (most cases). - all int - subsystems map[string]bool - } - testTable := []testData{ - { - mountInfo: fedoraMountinfo, - root: "/", - subsystems: map[string]bool{ - "name=systemd": false, - "cpuset": false, - "cpu": false, - "cpuacct": false, - "memory": false, - "devices": false, - "freezer": false, - "net_cls": false, - "blkio": false, - "perf_event": false, - "hugetlb": false, - }, - }, - { - mountInfo: systemdMountinfo, - root: "/system.slice/docker-dc4eaa1a34ec4d593bc0125d31eea823a1d76ae483aeb1409cca80304e34da2e.scope", - subsystems: map[string]bool{ - "name=systemd": false, - "cpuset": false, - "cpu": false, - "cpuacct": false, - "memory": false, - "devices": false, - "freezer": false, - "net_cls": false, - "net_prio": false, - "blkio": false, - "perf_event": false, - }, - }, - { - mountInfo: bedrockMountinfo, - root: "/", - all: 50, - subsystems: map[string]bool{ - "name=systemd": false, - "cpuset": false, - "cpu": false, - "cpuacct": false, - "memory": false, - "devices": false, - "freezer": false, - "net_cls": false, - "net_prio": false, - "blkio": false, - "perf_event": false, - "pids": false, - }, - }, - } - for _, td := range testTable { - mi, err := mountinfo.GetMountsFromReader( - bytes.NewBufferString(td.mountInfo), - mountinfo.FSTypeFilter("cgroup"), - ) - if err != nil { - t.Fatal(err) - } - cgMounts, err := getCgroupMountsHelper(td.subsystems, mi, false) - if err != nil { - t.Fatal(err) - } - cgMap := make(map[string]Mount) - for _, m := range cgMounts { - for _, ss := range m.Subsystems { - cgMap[ss] = m - } - } - for ss := range td.subsystems { - ss = strings.TrimPrefix(ss, CgroupNamePrefix) - m, ok := cgMap[ss] - if !ok { - t.Fatalf("%s not found", ss) - } - if m.Root != td.root { - t.Fatalf("unexpected root for %s: %s", ss, m.Root) - } - if !strings.HasPrefix(m.Mountpoint, "/sys/fs/cgroup/") && !strings.Contains(m.Mountpoint, ss) { - t.Fatalf("unexpected mountpoint for %s: %s", ss, m.Mountpoint) - } - var ssFound bool - for _, mss := range m.Subsystems { - if mss == ss { - ssFound = true - break - } - } - if !ssFound { - t.Fatalf("subsystem %s not found in Subsystems field %v", ss, m.Subsystems) - } - } - // Test the all=true case. - - // Reset the test input. - for k := range td.subsystems { - td.subsystems[k] = false - } - cgMountsAll, err := getCgroupMountsHelper(td.subsystems, mi, true) - if err != nil { - t.Fatal(err) - } - if td.all == 0 { - // Results with and without "all" should be the same. - if len(cgMounts) != len(cgMountsAll) || !reflect.DeepEqual(cgMounts, cgMountsAll) { - t.Errorf("expected same results, got (all=false) %v, (all=true) %v", cgMounts, cgMountsAll) - } - } else { - // Make sure we got all records. - if len(cgMountsAll) != td.all { - t.Errorf("expected %d records, got %d (%+v)", td.all, len(cgMountsAll), cgMountsAll) - } - } - - } -} - -func BenchmarkGetCgroupMounts(b *testing.B) { - subsystems := map[string]bool{ - "cpuset": false, - "cpu": false, - "cpuacct": false, - "memory": false, - "devices": false, - "freezer": false, - "net_cls": false, - "blkio": false, - "perf_event": false, - "hugetlb": false, - } - mi, err := mountinfo.GetMountsFromReader( - bytes.NewBufferString(fedoraMountinfo), - mountinfo.FSTypeFilter("cgroup"), - ) - if err != nil { - b.Fatal(err) - } - b.ResetTimer() - for i := 0; i < b.N; i++ { - if _, err := getCgroupMountsHelper(subsystems, mi, false); err != nil { - b.Fatal(err) - } - } -} - -func TestParseCgroupString(t *testing.T) { - testCases := []struct { - input string - expectedError error - expectedOutput map[string]string - }{ - { - // Taken from a CoreOS instance running systemd 225 with CPU/Mem - // accounting enabled in systemd - input: `9:blkio:/ -8:freezer:/ -7:perf_event:/ -6:devices:/system.slice/system-sshd.slice -5:cpuset:/ -4:cpu,cpuacct:/system.slice/system-sshd.slice/sshd@126-10.240.0.15:22-xxx.yyy.zzz.aaa:33678.service -3:net_cls,net_prio:/ -2:memory:/system.slice/system-sshd.slice/sshd@126-10.240.0.15:22-xxx.yyy.zzz.aaa:33678.service -1:name=systemd:/system.slice/system-sshd.slice/sshd@126-10.240.0.15:22-xxx.yyy.zzz.aaa:33678.service`, - expectedOutput: map[string]string{ - "name=systemd": "/system.slice/system-sshd.slice/sshd@126-10.240.0.15:22-xxx.yyy.zzz.aaa:33678.service", - "blkio": "/", - "freezer": "/", - "perf_event": "/", - "devices": "/system.slice/system-sshd.slice", - "cpuset": "/", - "cpu": "/system.slice/system-sshd.slice/sshd@126-10.240.0.15:22-xxx.yyy.zzz.aaa:33678.service", - "cpuacct": "/system.slice/system-sshd.slice/sshd@126-10.240.0.15:22-xxx.yyy.zzz.aaa:33678.service", - "net_cls": "/", - "net_prio": "/", - "memory": "/system.slice/system-sshd.slice/sshd@126-10.240.0.15:22-xxx.yyy.zzz.aaa:33678.service", - }, - }, - { - input: `malformed input`, - expectedError: errors.New(`invalid cgroup entry: must contain at least two colons: malformed input`), - }, - } - - for ndx, testCase := range testCases { - out, err := parseCgroupFromReader(strings.NewReader(testCase.input)) - if err != nil { - if testCase.expectedError == nil || testCase.expectedError.Error() != err.Error() { - t.Errorf("%v: expected error %v, got error %v", ndx, testCase.expectedError, err) - } - } else { - if !reflect.DeepEqual(testCase.expectedOutput, out) { - t.Errorf("%v: expected output %v, got error %v", ndx, testCase.expectedOutput, out) - } - } - } -} - -func TestIgnoreCgroup2Mount(t *testing.T) { - subsystems := map[string]bool{ - "cpuset": false, - "cpu": false, - "cpuacct": false, - "memory": false, - "devices": false, - "freezer": false, - "net_cls": false, - "blkio": false, - "perf_event": false, - "pids": false, - "name=systemd": false, - } - - mi, err := mountinfo.GetMountsFromReader( - bytes.NewBufferString(cgroup2Mountinfo), - mountinfo.FSTypeFilter("cgroup"), - ) - if err != nil { - t.Fatal(err) - } - cgMounts, err := getCgroupMountsHelper(subsystems, mi, false) - if err != nil { - t.Fatal(err) - } - for _, m := range cgMounts { - if m.Mountpoint == "/sys/fs/cgroup/systemd" { - t.Errorf("parsed a cgroup2 mount at /sys/fs/cgroup/systemd instead of ignoring it") - } - } -} - -func TestFindCgroupMountpointAndRoot(t *testing.T) { - fakeMountInfo := `35 27 0:29 / /foo rw,nosuid,nodev,noexec,relatime shared:18 - cgroup cgroup rw,devices -35 27 0:29 / /sys/fs/cgroup/devices rw,nosuid,nodev,noexec,relatime shared:18 - cgroup cgroup rw,devices` - testCases := []struct { - cgroupPath string - output string - }{ - {cgroupPath: "/sys/fs", output: "/sys/fs/cgroup/devices"}, - {cgroupPath: "", output: "/foo"}, - } - - mi, err := mountinfo.GetMountsFromReader( - bytes.NewBufferString(fakeMountInfo), - mountinfo.FSTypeFilter("cgroup"), - ) - if err != nil { - t.Fatal(err) - } - - for _, c := range testCases { - mountpoint, _, _ := findCgroupMountpointAndRootFromMI(mi, c.cgroupPath, "devices") - if mountpoint != c.output { - t.Errorf("expected %s, got %s", c.output, mountpoint) - } - } -} - -func BenchmarkGetHugePageSizeImpl(b *testing.B) { - var ( - input = []string{"hugepages-1048576kB", "hugepages-2048kB", "hugepages-32768kB", "hugepages-64kB"} - output []string - err error - ) - for i := 0; i < b.N; i++ { - output, err = getHugePageSizeFromFilenames(input) - } - if err != nil || len(output) != len(input) { - b.Fatal("unexpected results") - } -} - -func TestGetHugePageSizeImpl(t *testing.T) { - testCases := []struct { - doc string - input []string - output []string - isErr bool - }{ - { - doc: "normal input", - input: []string{"hugepages-1048576kB", "hugepages-2048kB", "hugepages-32768kB", "hugepages-64kB"}, - output: []string{"1GB", "2MB", "32MB", "64KB"}, - }, - { - doc: "empty input", - input: []string{}, - output: []string{}, - }, - { - doc: "not a number", - input: []string{"hugepages-akB"}, - isErr: true, - }, - { - doc: "no prefix (silently skipped)", - input: []string{"1024kB"}, - }, - { - doc: "invalid prefix (silently skipped)", - input: []string{"whatever-1024kB"}, - }, - { - doc: "invalid suffix", - input: []string{"hugepages-1024gB"}, - isErr: true, - }, - { - doc: "no suffix", - input: []string{"hugepages-1024"}, - isErr: true, - }, - { - doc: "mixed valid and invalid entries", - input: []string{"hugepages-4194304kB", "hugepages-2048kB", "hugepages-akB", "hugepages-64kB"}, - output: []string{"4GB", "2MB", "64KB"}, - isErr: true, - }, - { - doc: "more mixed valid and invalid entries", - input: []string{"hugepages-2048kB", "hugepages-kB", "hugepages-64kB"}, - output: []string{"2MB", "64KB"}, - isErr: true, - }, - } - - for _, c := range testCases { - c := c - t.Run(c.doc, func(t *testing.T) { - output, err := getHugePageSizeFromFilenames(c.input) - t.Log("input:", c.input, "; output:", output, "; err:", err) - if err != nil { - if !c.isErr { - t.Errorf("input %v, expected nil, got error: %v", c.input, err) - } - // no more checks - return - } - if c.isErr { - t.Errorf("input %v, expected error, got error: nil, output: %v", c.input, output) - } - // check output - if len(output) != len(c.output) || (len(output) > 0 && !reflect.DeepEqual(output, c.output)) { - t.Errorf("input %v, expected %v, got %v", c.input, c.output, output) - } - }) - } -} - -func TestConvertCPUSharesToCgroupV2Value(t *testing.T) { - cases := map[uint64]uint64{ - 0: 0, - 2: 1, - 262144: 10000, - } - for i, expected := range cases { - got := ConvertCPUSharesToCgroupV2Value(i) - if got != expected { - t.Errorf("expected ConvertCPUSharesToCgroupV2Value(%d) to be %d, got %d", i, expected, got) - } - } -} - -func TestConvertMemorySwapToCgroupV2Value(t *testing.T) { - cases := []struct { - descr string - memswap, memory int64 - expected int64 - expErr bool - }{ - { - descr: "all unset", - memswap: 0, - memory: 0, - expected: 0, - }, - { - descr: "unlimited memory+swap, unset memory", - memswap: -1, - memory: 0, - expected: -1, - }, - { - descr: "unlimited memory", - memswap: 300, - memory: -1, - expected: 300, - }, - { - descr: "all unlimited", - memswap: -1, - memory: -1, - expected: -1, - }, - { - descr: "negative memory+swap", - memswap: -2, - memory: 0, - expErr: true, - }, - { - descr: "unlimited memory+swap, set memory", - memswap: -1, - memory: 1000, - expected: -1, - }, - { - descr: "memory+swap == memory", - memswap: 1000, - memory: 1000, - expected: 0, - }, - { - descr: "memory+swap > memory", - memswap: 500, - memory: 200, - expected: 300, - }, - { - descr: "memory+swap < memory", - memswap: 300, - memory: 400, - expErr: true, - }, - { - descr: "unset memory", - memswap: 300, - memory: 0, - expErr: true, - }, - { - descr: "negative memory", - memswap: 300, - memory: -300, - expErr: true, - }, - } - - for _, c := range cases { - c := c - t.Run(c.descr, func(t *testing.T) { - swap, err := ConvertMemorySwapToCgroupV2Value(c.memswap, c.memory) - if c.expErr { - if err == nil { - t.Errorf("memswap: %d, memory %d, expected error, got %d, nil", c.memswap, c.memory, swap) - } - // No more checks. - return - } - if err != nil { - t.Errorf("memswap: %d, memory %d, expected success, got error %s", c.memswap, c.memory, err) - } - if swap != c.expected { - t.Errorf("memswap: %d, memory %d, expected %d, got %d", c.memswap, c.memory, c.expected, swap) - } - }) - } -} - -func TestConvertBlkIOToIOWeightValue(t *testing.T) { - cases := map[uint16]uint64{ - 0: 0, - 10: 1, - 1000: 10000, - } - for i, expected := range cases { - got := ConvertBlkIOToIOWeightValue(i) - if got != expected { - t.Errorf("expected ConvertBlkIOToIOWeightValue(%d) to be %d, got %d", i, expected, got) - } - } -} - -// TestRemovePathReadOnly is to test remove a non-existent dir in a ro mount point. -// The similar issue example: https://github.com/opencontainers/runc/issues/4518 -func TestRemovePathReadOnly(t *testing.T) { - dirTo := t.TempDir() - err := unix.Mount(t.TempDir(), dirTo, "", unix.MS_BIND, "") - if err != nil { - t.Skip("no permission of mount") - } - defer func() { - _ = unix.Unmount(dirTo, 0) - }() - err = unix.Mount("", dirTo, "", unix.MS_REMOUNT|unix.MS_BIND|unix.MS_RDONLY, "") - if err != nil { - t.Skip("no permission of mount") - } - nonExistentDir := filepath.Join(dirTo, "non-existent-dir") - err = rmdir(nonExistentDir, true) - if !errors.Is(err, unix.EROFS) { - t.Fatalf("expected the error of removing a non-existent dir %s in a ro mount point with rmdir to be unix.EROFS, but got: %v", nonExistentDir, err) - } - err = RemovePath(nonExistentDir) - if err != nil { - t.Fatalf("expected the error of removing a non-existent dir %s in a ro mount point with RemovePath to be nil, but got: %v", nonExistentDir, err) - } -} diff --git a/libcontainer/configs/cgroup_deprecated.go b/libcontainer/configs/cgroup_deprecated.go index 2277d326e..9a7a1a201 100644 --- a/libcontainer/configs/cgroup_deprecated.go +++ b/libcontainer/configs/cgroup_deprecated.go @@ -1,6 +1,6 @@ -package configs // Deprecated: use [github.com/opencontainers/runc/libcontainer/cgroups]. +package configs // Deprecated: use [github.com/opencontainers/cgroups]. -import "github.com/opencontainers/runc/libcontainer/cgroups" +import "github.com/opencontainers/cgroups" type ( Cgroup = cgroups.Cgroup diff --git a/libcontainer/configs/config.go b/libcontainer/configs/config.go index 746c7190e..3cca1eef6 100644 --- a/libcontainer/configs/config.go +++ b/libcontainer/configs/config.go @@ -10,7 +10,7 @@ import ( "github.com/sirupsen/logrus" "golang.org/x/sys/unix" - devices "github.com/opencontainers/runc/libcontainer/cgroups/devices/config" + devices "github.com/opencontainers/cgroups/devices/config" "github.com/opencontainers/runtime-spec/specs-go" ) diff --git a/libcontainer/configs/validate/validator.go b/libcontainer/configs/validate/validator.go index 7d17676ed..e0052900f 100644 --- a/libcontainer/configs/validate/validator.go +++ b/libcontainer/configs/validate/validator.go @@ -8,7 +8,7 @@ import ( "strings" "sync" - "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/cgroups" "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/intelrdt" "github.com/opencontainers/runtime-spec/specs-go" diff --git a/libcontainer/container_linux.go b/libcontainer/container_linux.go index ecb05a0d1..4bc117e51 100644 --- a/libcontainer/container_linux.go +++ b/libcontainer/container_linux.go @@ -20,7 +20,7 @@ import ( "github.com/vishvananda/netlink/nl" "golang.org/x/sys/unix" - "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/cgroups" "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/exeseal" "github.com/opencontainers/runc/libcontainer/intelrdt" diff --git a/libcontainer/container_linux_test.go b/libcontainer/container_linux_test.go index 8d9920925..e6bdd86ba 100644 --- a/libcontainer/container_linux_test.go +++ b/libcontainer/container_linux_test.go @@ -5,7 +5,7 @@ import ( "os" "testing" - "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/cgroups" "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/system" ) diff --git a/libcontainer/criu_linux.go b/libcontainer/criu_linux.go index 4d2fa0569..93f628715 100644 --- a/libcontainer/criu_linux.go +++ b/libcontainer/criu_linux.go @@ -23,7 +23,7 @@ import ( "golang.org/x/sys/unix" "google.golang.org/protobuf/proto" - "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/cgroups" "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/utils" ) diff --git a/libcontainer/devices/device_deprecated.go b/libcontainer/devices/device_deprecated.go index 6e960a424..9483f054d 100644 --- a/libcontainer/devices/device_deprecated.go +++ b/libcontainer/devices/device_deprecated.go @@ -1,8 +1,8 @@ package devices -import "github.com/opencontainers/runc/libcontainer/cgroups/devices/config" +import "github.com/opencontainers/cgroups/devices/config" -// Deprecated: use [github.com/opencontainers/runc/libcontainer/cgroups/devices/config]. +// Deprecated: use [github.com/opencontainers/cgroups/devices/config]. const ( Wildcard = config.Wildcard WildcardDevice = config.WildcardDevice @@ -11,7 +11,7 @@ const ( FifoDevice = config.FifoDevice ) -// Deprecated: use [github.com/opencontainers/runc/libcontainer/cgroups/devices/config]. +// Deprecated: use [github.com/opencontainers/cgroups/devices/config]. type ( Device = config.Device Permissions = config.Permissions diff --git a/libcontainer/factory_linux.go b/libcontainer/factory_linux.go index 114cbf20e..539726dfd 100644 --- a/libcontainer/factory_linux.go +++ b/libcontainer/factory_linux.go @@ -9,8 +9,8 @@ import ( securejoin "github.com/cyphar/filepath-securejoin" "golang.org/x/sys/unix" - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/manager" + "github.com/opencontainers/cgroups" + "github.com/opencontainers/cgroups/manager" "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/configs/validate" "github.com/opencontainers/runc/libcontainer/intelrdt" diff --git a/libcontainer/factory_linux_test.go b/libcontainer/factory_linux_test.go index 7e4fcecfd..bbbbd3465 100644 --- a/libcontainer/factory_linux_test.go +++ b/libcontainer/factory_linux_test.go @@ -7,7 +7,7 @@ import ( "reflect" "testing" - "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/cgroups" "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/utils" "github.com/opencontainers/runtime-spec/specs-go" diff --git a/libcontainer/init_linux.go b/libcontainer/init_linux.go index f78e56175..354f0c149 100644 --- a/libcontainer/init_linux.go +++ b/libcontainer/init_linux.go @@ -19,8 +19,8 @@ import ( "github.com/vishvananda/netlink" "golang.org/x/sys/unix" + "github.com/opencontainers/cgroups" "github.com/opencontainers/runc/libcontainer/capabilities" - "github.com/opencontainers/runc/libcontainer/cgroups" "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/system" "github.com/opencontainers/runc/libcontainer/utils" diff --git a/libcontainer/integration/exec_test.go b/libcontainer/integration/exec_test.go index c9a7cbc56..f18dd50f2 100644 --- a/libcontainer/integration/exec_test.go +++ b/libcontainer/integration/exec_test.go @@ -14,9 +14,9 @@ import ( "syscall" "testing" + "github.com/opencontainers/cgroups" + "github.com/opencontainers/cgroups/systemd" "github.com/opencontainers/runc/libcontainer" - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/systemd" "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/internal/userns" "github.com/opencontainers/runc/libcontainer/utils" diff --git a/libcontainer/integration/init_test.go b/libcontainer/integration/init_test.go index a79ffe5c3..74f4dbcbe 100644 --- a/libcontainer/integration/init_test.go +++ b/libcontainer/integration/init_test.go @@ -6,7 +6,7 @@ import ( "github.com/opencontainers/runc/libcontainer" //nolint:revive // Enable cgroup manager to manage devices - _ "github.com/opencontainers/runc/libcontainer/cgroups/devices" + _ "github.com/opencontainers/cgroups/devices" _ "github.com/opencontainers/runc/libcontainer/nsenter" ) diff --git a/libcontainer/integration/template_test.go b/libcontainer/integration/template_test.go index 4d31acb09..0c178f34e 100644 --- a/libcontainer/integration/template_test.go +++ b/libcontainer/integration/template_test.go @@ -6,8 +6,8 @@ import ( "testing" "time" - "github.com/opencontainers/runc/libcontainer/cgroups" - devices "github.com/opencontainers/runc/libcontainer/cgroups/devices/config" + "github.com/opencontainers/cgroups" + devices "github.com/opencontainers/cgroups/devices/config" "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/specconv" "golang.org/x/sys/unix" diff --git a/libcontainer/integration/update_test.go b/libcontainer/integration/update_test.go index 68e77b5d9..eb864f7fe 100644 --- a/libcontainer/integration/update_test.go +++ b/libcontainer/integration/update_test.go @@ -6,9 +6,9 @@ import ( "strings" "testing" + devices "github.com/opencontainers/cgroups/devices/config" + "github.com/opencontainers/cgroups/systemd" "github.com/opencontainers/runc/libcontainer" - devices "github.com/opencontainers/runc/libcontainer/cgroups/devices/config" - "github.com/opencontainers/runc/libcontainer/cgroups/systemd" ) func testUpdateDevices(t *testing.T, systemd bool) { diff --git a/libcontainer/intelrdt/intelrdt.go b/libcontainer/intelrdt/intelrdt.go index 0f5c457b0..97a9fe4d3 100644 --- a/libcontainer/intelrdt/intelrdt.go +++ b/libcontainer/intelrdt/intelrdt.go @@ -13,7 +13,7 @@ import ( "github.com/moby/sys/mountinfo" "golang.org/x/sys/unix" - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" + "github.com/opencontainers/cgroups/fscommon" "github.com/opencontainers/runc/libcontainer/configs" ) diff --git a/libcontainer/notify_v2_linux.go b/libcontainer/notify_v2_linux.go index 8d15833ab..751f4c91d 100644 --- a/libcontainer/notify_v2_linux.go +++ b/libcontainer/notify_v2_linux.go @@ -6,7 +6,7 @@ import ( "path/filepath" "unsafe" - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" + "github.com/opencontainers/cgroups/fscommon" "github.com/sirupsen/logrus" "golang.org/x/sys/unix" ) diff --git a/libcontainer/process_linux.go b/libcontainer/process_linux.go index 68a5fd7bc..320eff5fe 100644 --- a/libcontainer/process_linux.go +++ b/libcontainer/process_linux.go @@ -19,8 +19,8 @@ import ( "github.com/sirupsen/logrus" "golang.org/x/sys/unix" - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/fs2" + "github.com/opencontainers/cgroups" + "github.com/opencontainers/cgroups/fs2" "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/intelrdt" "github.com/opencontainers/runc/libcontainer/internal/userns" diff --git a/libcontainer/rootfs_linux.go b/libcontainer/rootfs_linux.go index 68e16b792..e46109a2f 100644 --- a/libcontainer/rootfs_linux.go +++ b/libcontainer/rootfs_linux.go @@ -21,9 +21,9 @@ import ( "github.com/sirupsen/logrus" "golang.org/x/sys/unix" - "github.com/opencontainers/runc/libcontainer/cgroups" - devices "github.com/opencontainers/runc/libcontainer/cgroups/devices/config" - "github.com/opencontainers/runc/libcontainer/cgroups/fs2" + "github.com/opencontainers/cgroups" + devices "github.com/opencontainers/cgroups/devices/config" + "github.com/opencontainers/cgroups/fs2" "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/utils" ) diff --git a/libcontainer/specconv/example.go b/libcontainer/specconv/example.go index 1e9cfa2db..9e639f197 100644 --- a/libcontainer/specconv/example.go +++ b/libcontainer/specconv/example.go @@ -5,7 +5,7 @@ import ( "path/filepath" "strings" - "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/cgroups" "github.com/opencontainers/runtime-spec/specs-go" ) diff --git a/libcontainer/specconv/spec_linux.go b/libcontainer/specconv/spec_linux.go index f4f5f0995..c12471de6 100644 --- a/libcontainer/specconv/spec_linux.go +++ b/libcontainer/specconv/spec_linux.go @@ -14,8 +14,8 @@ import ( systemdDbus "github.com/coreos/go-systemd/v22/dbus" dbus "github.com/godbus/dbus/v5" - "github.com/opencontainers/runc/libcontainer/cgroups" - devices "github.com/opencontainers/runc/libcontainer/cgroups/devices/config" + "github.com/opencontainers/cgroups" + devices "github.com/opencontainers/cgroups/devices/config" "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/internal/userns" "github.com/opencontainers/runc/libcontainer/seccomp" diff --git a/libcontainer/specconv/spec_linux_test.go b/libcontainer/specconv/spec_linux_test.go index c8d4ae464..66359f79e 100644 --- a/libcontainer/specconv/spec_linux_test.go +++ b/libcontainer/specconv/spec_linux_test.go @@ -6,7 +6,7 @@ import ( "testing" dbus "github.com/godbus/dbus/v5" - devices "github.com/opencontainers/runc/libcontainer/cgroups/devices/config" + devices "github.com/opencontainers/cgroups/devices/config" "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/configs/validate" "github.com/opencontainers/runtime-spec/specs-go" diff --git a/libcontainer/state_linux.go b/libcontainer/state_linux.go index 64f43e8fb..2b7b8b5bc 100644 --- a/libcontainer/state_linux.go +++ b/libcontainer/state_linux.go @@ -5,7 +5,7 @@ import ( "os" "path/filepath" - "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/cgroups" "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runtime-spec/specs-go" "golang.org/x/sys/unix" diff --git a/libcontainer/stats_linux.go b/libcontainer/stats_linux.go index fff9dd37a..e776aad43 100644 --- a/libcontainer/stats_linux.go +++ b/libcontainer/stats_linux.go @@ -1,7 +1,7 @@ package libcontainer import ( - "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/cgroups" "github.com/opencontainers/runc/libcontainer/intelrdt" "github.com/opencontainers/runc/types" ) diff --git a/main.go b/main.go index cac34ce03..2242f9301 100644 --- a/main.go +++ b/main.go @@ -11,7 +11,7 @@ import ( "strings" //nolint:revive // Enable cgroup manager to manage devices - _ "github.com/opencontainers/runc/libcontainer/cgroups/devices" + _ "github.com/opencontainers/cgroups/devices" "github.com/opencontainers/runc/libcontainer/seccomp" "github.com/opencontainers/runtime-spec/specs-go" diff --git a/rootless_linux.go b/rootless_linux.go index 6ba178b53..f9d9a42ba 100644 --- a/rootless_linux.go +++ b/rootless_linux.go @@ -7,7 +7,7 @@ import ( "github.com/sirupsen/logrus" "github.com/urfave/cli" - "github.com/opencontainers/runc/libcontainer/cgroups/systemd" + "github.com/opencontainers/cgroups/systemd" ) func shouldUseRootlessCgroupManager(context *cli.Context) (bool, error) { diff --git a/tests/cmd/sd-helper/helper.go b/tests/cmd/sd-helper/helper.go index be7de3e58..0820c2ef9 100644 --- a/tests/cmd/sd-helper/helper.go +++ b/tests/cmd/sd-helper/helper.go @@ -7,14 +7,14 @@ import ( "github.com/sirupsen/logrus" - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/systemd" + "github.com/opencontainers/cgroups" + "github.com/opencontainers/cgroups/systemd" ) func usage() { fmt.Print(`Open Container Initiative tests/cmd/sd-helper -sd-helper is a tool that uses runc/libcontainer/cgroups/systemd package +sd-helper is a tool that uses github.com/opencontainers/groups/systemd package functionality to communicate to systemd in order to perform various operations. Currently this is limited to starting and stopping systemd transient slice units. diff --git a/tests/integration/update.bats b/tests/integration/update.bats index 22a92e8bd..034e959fc 100644 --- a/tests/integration/update.bats +++ b/tests/integration/update.bats @@ -221,7 +221,7 @@ EOF if [ -v HAVE_SWAP ]; then # Test case for https://github.com/opencontainers/runc/pull/592, - # checking libcontainer/cgroups/fs/memory.go:setMemoryAndSwap. + # checking github.com/opencontainers/cgroups/fs/memory.go:setMemoryAndSwap. runc update test_update --memory 30M --memory-swap 50M [ "$status" -eq 0 ] diff --git a/types/events.go b/types/events.go index e28ac8c38..8af94236b 100644 --- a/types/events.go +++ b/types/events.go @@ -1,7 +1,7 @@ package types import ( - "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/cgroups" "github.com/opencontainers/runc/libcontainer/intelrdt" ) diff --git a/update.go b/update.go index 4fef85f71..7a6ae70fe 100644 --- a/update.go +++ b/update.go @@ -7,7 +7,7 @@ import ( "os" "strconv" - "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/cgroups" "github.com/sirupsen/logrus" "github.com/docker/go-units" diff --git a/vendor/github.com/opencontainers/cgroups/CODEOWNERS b/vendor/github.com/opencontainers/cgroups/CODEOWNERS new file mode 100644 index 000000000..7201e35ac --- /dev/null +++ b/vendor/github.com/opencontainers/cgroups/CODEOWNERS @@ -0,0 +1 @@ +* @maintainer1 @maintainer2 @maintainer3 diff --git a/vendor/github.com/opencontainers/cgroups/CONTRIBUTING.md b/vendor/github.com/opencontainers/cgroups/CONTRIBUTING.md new file mode 100644 index 000000000..135abcf02 --- /dev/null +++ b/vendor/github.com/opencontainers/cgroups/CONTRIBUTING.md @@ -0,0 +1,150 @@ +# Contribution Guidelines + +Development happens on GitHub. +Issues are used for bugs and actionable items and longer discussions can happen on the [mailing list](#mailing-list). + +The content of this repository is licensed under the [Apache License, Version 2.0](LICENSE). + +## Code of Conduct + +Participation in the Open Container community is governed by [Open Container Code of Conduct][code-of-conduct]. + +## Meetings + +The contributors and maintainers of all OCI projects have monthly meetings at 2:00 PM (USA Pacific) on the first Wednesday of every month. +There is an [iCalendar][rfc5545] format for the meetings [here][meeting.ics]. +Everyone is welcome to participate via [UberConference web][UberConference] or audio-only: +1 415 968 0849 (no PIN needed). +An initial agenda will be posted to the [mailing list](#mailing-list) in the week before each meeting, and everyone is welcome to propose additional topics or suggest other agenda alterations there. +Minutes from past meetings are archived [here][minutes]. + +## Mailing list + +You can subscribe and browse the mailing list on [Google Groups][mailing-list]. + +## IRC + +OCI discussion happens on #opencontainers on [Freenode][] ([logs][irc-logs]). + +## Git + +### Security issues + +If you are reporting a security issue, do not create an issue or file a pull +request on GitHub. Instead, disclose the issue responsibly by sending an email +to security@opencontainers.org (which is inhabited only by the maintainers of +the various OCI projects). + +### Pull requests are always welcome + +We are always thrilled to receive pull requests, and do our best to +process them as fast as possible. Not sure if that typo is worth a pull +request? Do it! We will appreciate it. + +If your pull request is not accepted on the first try, don't be +discouraged! If there's a problem with the implementation, hopefully you +received feedback on what to improve. + +We're trying very hard to keep the project lean and focused. We don't want it +to do everything for everybody. This means that we might decide against +incorporating a new feature. + +### Conventions + +Fork the repo and make changes on your fork in a feature branch. +For larger bugs and enhancements, consider filing a leader issue or mailing-list thread for discussion that is independent of the implementation. +Small changes or changes that have been discussed on the [project mailing list](#mailing-list) may be submitted without a leader issue. + +If the project has a test suite, submit unit tests for your changes. Take a +look at existing tests for inspiration. Run the full test suite on your branch +before submitting a pull request. + +Update the documentation when creating or modifying features. Test +your documentation changes for clarity, concision, and correctness, as +well as a clean documentation build. + +Pull requests descriptions should be as clear as possible and include a +reference to all the issues that they address. + +Commit messages must start with a capitalized and short summary +written in the imperative, followed by an optional, more detailed +explanatory text which is separated from the summary by an empty line. + +Code review comments may be added to your pull request. Discuss, then make the +suggested modifications and push additional commits to your feature branch. Be +sure to post a comment after pushing. The new commits will show up in the pull +request automatically, but the reviewers will not be notified unless you +comment. + +Before the pull request is merged, make sure that you squash your commits into +logical units of work using `git rebase -i` and `git push -f`. After every +commit the test suite (if any) should be passing. Include documentation changes +in the same commit so that a revert would remove all traces of the feature or +fix. + +Commits that fix or close an issue should include a reference like `Closes #XXX` +or `Fixes #XXX`, which will automatically close the issue when merged. + +### Sign your work + +The sign-off is a simple line at the end of the explanation for the +patch, which certifies that you wrote it or otherwise have the right to +pass it on as an open-source patch. The rules are pretty simple: if you +can certify the below (from [developercertificate.org][]): + +``` +Developer Certificate of Origin +Version 1.1 + +Copyright (C) 2004, 2006 The Linux Foundation and its contributors. +1 Letterman Drive +Suite D4700 +San Francisco, CA, 94129 + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + + +Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +(b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. +``` + +then you just add a line to every git commit message: + + Signed-off-by: Joe Smith + +using your real name (sorry, no pseudonyms or anonymous contributions.) + +You can add the sign off when creating the git commit via `git commit -s`. + +[code-of-conduct]: https://github.com/opencontainers/tob/blob/d2f9d68c1332870e40693fe077d311e0742bc73d/code-of-conduct.md +[developercertificate.org]: http://developercertificate.org/ +[Freenode]: https://freenode.net/ +[irc-logs]: http://ircbot.wl.linuxfoundation.org/eavesdrop/%23opencontainers/ +[mailing-list]: https://groups.google.com/a/opencontainers.org/forum/#!forum/dev +[meeting.ics]: https://github.com/opencontainers/runtime-spec/blob/master/meeting.ics +[minutes]: http://ircbot.wl.linuxfoundation.org/meetings/opencontainers/ +[rfc5545]: https://tools.ietf.org/html/rfc5545 +[UberConference]: https://www.uberconference.com/opencontainers diff --git a/vendor/github.com/opencontainers/cgroups/GOVERNANCE.md b/vendor/github.com/opencontainers/cgroups/GOVERNANCE.md new file mode 100644 index 000000000..3b7b32f78 --- /dev/null +++ b/vendor/github.com/opencontainers/cgroups/GOVERNANCE.md @@ -0,0 +1,63 @@ +# Project governance + +The [OCI charter][charter] §5.b.viii tasks an OCI Project's maintainers (listed in the repository's MAINTAINERS file and sometimes referred to as "the TDC", [§5.e][charter]) with: + +> Creating, maintaining and enforcing governance guidelines for the TDC, approved by the maintainers, and which shall be posted visibly for the TDC. + +This section describes generic rules and procedures for fulfilling that mandate. + +## Proposing a motion + +A maintainer SHOULD propose a motion on the dev@opencontainers.org mailing list (except [security issues](#security-issues)) with another maintainer as a co-sponsor. + +## Voting + +Voting on a proposed motion SHOULD happen on the dev@opencontainers.org mailing list (except [security issues](#security-issues)) with maintainers posting LGTM or REJECT. +Maintainers MAY also explicitly not vote by posting ABSTAIN (which is useful to revert a previous vote). +Maintainers MAY post multiple times (e.g. as they revise their position based on feedback), but only their final post counts in the tally. +A proposed motion is adopted if two-thirds of votes cast, a quorum having voted, are in favor of the release. + +Voting SHOULD remain open for a week to collect feedback from the wider community and allow the maintainers to digest the proposed motion. +Under exceptional conditions (e.g. non-major security fix releases) proposals which reach quorum with unanimous support MAY be adopted earlier. + +A maintainer MAY choose to reply with REJECT. +A maintainer posting a REJECT MUST include a list of concerns or links to written documentation for those concerns (e.g. GitHub issues or mailing-list threads). +The maintainers SHOULD try to resolve the concerns and wait for the rejecting maintainer to change their opinion to LGTM. +However, a motion MAY be adopted with REJECTs, as outlined in the previous paragraphs. + +## Quorum + +A quorum is established when at least two-thirds of maintainers have voted. + +For projects that are not specifications, a [motion to release](#release-approval) MAY be adopted if the tally is at least three LGTMs and no REJECTs, even if three votes does not meet the usual two-thirds quorum. + +## Amendments + +The [project governance](#project-governance) rules and procedures MAY be amended or replaced using the procedures themselves. +The MAINTAINERS of this project governance document is the total set of MAINTAINERS from all Open Containers projects (go-digest, image-spec, image-tools, runC, runtime-spec, runtime-tools, and selinux). + +## Subject templates + +Maintainers are busy and get lots of email. +To make project proposals recognizable, proposed motions SHOULD use the following subject templates. + +### Proposing a motion + +> [{project} VOTE]: {motion description} (closes {end of voting window}) + +For example: + +> [runtime-spec VOTE]: Tag 0647920 as 1.0.0-rc (closes 2016-06-03 20:00 UTC) + +### Tallying results + +After voting closes, a maintainer SHOULD post a tally to the motion thread with a subject template like: + +> [{project} {status}]: {motion description} (+{LGTMs} -{REJECTs} #{ABSTAINs}) + +Where `{status}` is either `adopted` or `rejected`. +For example: + +> [runtime-spec adopted]: Tag 0647920 as 1.0.0-rc (+6 -0 #3) + +[charter]: https://www.opencontainers.org/about/governance diff --git a/vendor/github.com/opencontainers/cgroups/LICENSE b/vendor/github.com/opencontainers/cgroups/LICENSE new file mode 100644 index 000000000..8dada3eda --- /dev/null +++ b/vendor/github.com/opencontainers/cgroups/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + 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. diff --git a/vendor/github.com/opencontainers/cgroups/MAINTAINERS b/vendor/github.com/opencontainers/cgroups/MAINTAINERS new file mode 100644 index 000000000..413edcb7d --- /dev/null +++ b/vendor/github.com/opencontainers/cgroups/MAINTAINERS @@ -0,0 +1,8 @@ +Akihiro Suda (@AkihiroSuda) +Aleksa Sarai (@cyphar) +Kir Kolyshkin (@kolyshkin) +Mrunal Patel (@mrunalp) +Sebastiaan van Stijn (@thaJeztah) +Odin Ugedal (@odinuge) +Peter Hunt (@haircommander) +Davanum Srinivas (@dims) diff --git a/vendor/github.com/opencontainers/cgroups/MAINTAINERS_GUIDE.md b/vendor/github.com/opencontainers/cgroups/MAINTAINERS_GUIDE.md new file mode 100644 index 000000000..8e9691747 --- /dev/null +++ b/vendor/github.com/opencontainers/cgroups/MAINTAINERS_GUIDE.md @@ -0,0 +1,92 @@ +## Introduction + +Dear maintainer. Thank you for investing the time and energy to help +make this project as useful as possible. Maintaining a project is difficult, +sometimes unrewarding work. Sure, you will get to contribute cool +features to the project. But most of your time will be spent reviewing, +cleaning up, documenting, answering questions, justifying design +decisions - while everyone has all the fun! But remember - the quality +of the maintainers work is what distinguishes the good projects from the +great. So please be proud of your work, even the unglamourous parts, +and encourage a culture of appreciation and respect for *every* aspect +of improving the project - not just the hot new features. + +This document is a manual for maintainers old and new. It explains what +is expected of maintainers, how they should work, and what tools are +available to them. + +This is a living document - if you see something out of date or missing, +speak up! + +## What are a maintainer's responsibilities? + +It is every maintainer's responsibility to: + +* Expose a clear roadmap for improving their component. +* Deliver prompt feedback and decisions on pull requests. +* Be available to anyone with questions, bug reports, criticism etc. on their component. + This includes IRC and GitHub issues and pull requests. +* Make sure their component respects the philosophy, design and roadmap of the project. + +## How are decisions made? + +This project is an open-source project with an open design philosophy. This +means that the repository is the source of truth for EVERY aspect of the +project, including its philosophy, design, roadmap and APIs. *If it's +part of the project, it's in the repo. It's in the repo, it's part of +the project.* + +As a result, all decisions can be expressed as changes to the +repository. An implementation change is a change to the source code. An +API change is a change to the API specification. A philosophy change is +a change to the philosophy manifesto. And so on. + +All decisions affecting this project, big and small, follow the same procedure: + +1. Discuss a proposal on the [mailing list](CONTRIBUTING.md#mailing-list). + Anyone can do this. +2. Open a pull request. + Anyone can do this. +3. Discuss the pull request. + Anyone can do this. +4. Endorse (`LGTM`) or oppose (`Rejected`) the pull request. + The relevant maintainers do this (see below [Who decides what?](#who-decides-what)). + Changes that affect project management (changing policy, cutting releases, etc.) are [proposed and voted on the mailing list](GOVERNANCE.md). +5. Merge or close the pull request. + The relevant maintainers do this. + +### I'm a maintainer, should I make pull requests too? + +Yes. Nobody should ever push to master directly. All changes should be +made through a pull request. + +## Who decides what? + +All decisions are pull requests, and the relevant maintainers make +decisions by accepting or refusing the pull request. Review and acceptance +by anyone is denoted by adding a comment in the pull request: `LGTM`. +However, only currently listed `MAINTAINERS` are counted towards the required +two LGTMs. In addition, if a maintainer has created a pull request, they cannot +count toward the two LGTM rule (to ensure equal amounts of review for every pull +request, no matter who wrote it). + +Overall the maintainer system works because of mutual respect. +The maintainers trust one another to act in the best interests of the project. +Sometimes maintainers can disagree and this is part of a healthy project to represent the points of view of various people. +In the case where maintainers cannot find agreement on a specific change, maintainers should use the [governance procedure](GOVERNANCE.md) to attempt to reach a consensus. + +### How are maintainers added? + +The best maintainers have a vested interest in the project. Maintainers +are first and foremost contributors that have shown they are committed to +the long term success of the project. Contributors wanting to become +maintainers are expected to be deeply involved in contributing code, +pull request review, and triage of issues in the project for more than two months. + +Just contributing does not make you a maintainer, it is about building trust with the current maintainers of the project and being a person that they can depend on to act in the best interest of the project. +The final vote to add a new maintainer should be approved by the [governance procedure](GOVERNANCE.md). + +### How are maintainers removed? + +When a maintainer is unable to perform the [required duties](#what-are-a-maintainers-responsibilities) they can be removed by the [governance procedure](GOVERNANCE.md). +Issues related to a maintainer's performance should be discussed with them among the other maintainers so that they are not surprised by a pull request removing them. diff --git a/vendor/github.com/opencontainers/cgroups/README.md b/vendor/github.com/opencontainers/cgroups/README.md new file mode 100644 index 000000000..a8187da1e --- /dev/null +++ b/vendor/github.com/opencontainers/cgroups/README.md @@ -0,0 +1,11 @@ +# OCI Project Template + +Useful boilerplate and organizational information for all OCI projects. + +* README (this file) +* [The Apache License, Version 2.0](LICENSE) +* [A list of maintainers](MAINTAINERS) +* [Maintainer guidelines](MAINTAINERS_GUIDE.md) +* [Contributor guidelines](CONTRIBUTING.md) +* [Project governance](GOVERNANCE.md) +* [Release procedures](RELEASES.md) diff --git a/vendor/github.com/opencontainers/cgroups/RELEASES.md b/vendor/github.com/opencontainers/cgroups/RELEASES.md new file mode 100644 index 000000000..028ec265d --- /dev/null +++ b/vendor/github.com/opencontainers/cgroups/RELEASES.md @@ -0,0 +1,51 @@ +# Releases + +The release process hopes to encourage early, consistent consensus-building during project development. +The mechanisms used are regular community communication on the mailing list about progress, scheduled meetings for issue resolution and release triage, and regularly paced and communicated releases. +Releases are proposed and adopted or rejected using the usual [project governance](GOVERNANCE.md) rules and procedures. + +An anti-pattern that we want to avoid is heavy development or discussions "late cycle" around major releases. +We want to build a community that is involved and communicates consistently through all releases instead of relying on "silent periods" as a judge of stability. + +## Parallel releases + +A single project MAY consider several motions to release in parallel. +However each motion to release after the initial 0.1.0 MUST be based on a previous release that has already landed. + +For example, runtime-spec maintainers may propose a v1.0.0-rc2 on the 1st of the month and a v0.9.1 bugfix on the 2nd of the month. +They may not propose a v1.0.0-rc3 until the v1.0.0-rc2 is accepted (on the 7th if the vote initiated on the 1st passes). + +## Specifications + +The OCI maintains three categories of projects: specifications, applications, and conformance-testing tools. +However, specification releases have special restrictions in the [OCI charter][charter]: + +* They are the target of backwards compatibility (§7.g), and +* They are subject to the OFWa patent grant (§8.d and e). + +To avoid unfortunate side effects (onerous backwards compatibity requirements or Member resignations), the following additional procedures apply to specification releases: + +### Planning a release + +Every OCI specification project SHOULD hold meetings that involve maintainers reviewing pull requests, debating outstanding issues, and planning releases. +This meeting MUST be advertised on the project README and MAY happen on a phone call, video conference, or on IRC. +Maintainers MUST send updates to the dev@opencontainers.org with results of these meetings. + +Before the specification reaches v1.0.0, the meetings SHOULD be weekly. +Once a specification has reached v1.0.0, the maintainers may alter the cadence, but a meeting MUST be held within four weeks of the previous meeting. + +The release plans, corresponding milestones and estimated due dates MUST be published on GitHub (e.g. https://github.com/opencontainers/runtime-spec/milestones). +GitHub milestones and issues are only used for community organization and all releases MUST follow the [project governance](GOVERNANCE.md) rules and procedures. + +### Timelines + +Specifications have a variety of different timelines in their lifecycle. + +* Pre-v1.0.0 specifications SHOULD release on a monthly cadence to garner feedback. +* Major specification releases MUST release at least three release candidates spaced a minimum of one week apart. + This means a major release like a v1.0.0 or v2.0.0 release will take 1 month at minimum: one week for rc1, one week for rc2, one week for rc3, and one week for the major release itself. + Maintainers SHOULD strive to make zero breaking changes during this cycle of release candidates and SHOULD restart the three-candidate count when a breaking change is introduced. + For example if a breaking change is introduced in v1.0.0-rc2 then the series would end with v1.0.0-rc4 and v1.0.0. +* Minor and patch releases SHOULD be made on an as-needed basis. + +[charter]: https://www.opencontainers.org/about/governance diff --git a/libcontainer/cgroups/cgroups.go b/vendor/github.com/opencontainers/cgroups/cgroups.go similarity index 97% rename from libcontainer/cgroups/cgroups.go rename to vendor/github.com/opencontainers/cgroups/cgroups.go index 719489c02..1f127550c 100644 --- a/libcontainer/cgroups/cgroups.go +++ b/vendor/github.com/opencontainers/cgroups/cgroups.go @@ -16,7 +16,7 @@ var ( // DevicesSetV1 and DevicesSetV2 are functions to set devices for // cgroup v1 and v2, respectively. Unless - // [github.com/opencontainers/runc/libcontainer/cgroups/devices] + // [github.com/opencontainers/cgroups/devices] // package is imported, it is set to nil, so cgroup managers can't // manage devices. DevicesSetV1 func(path string, r *Resources) error diff --git a/libcontainer/cgroups/config_blkio_device.go b/vendor/github.com/opencontainers/cgroups/config_blkio_device.go similarity index 100% rename from libcontainer/cgroups/config_blkio_device.go rename to vendor/github.com/opencontainers/cgroups/config_blkio_device.go diff --git a/libcontainer/cgroups/config_hugepages.go b/vendor/github.com/opencontainers/cgroups/config_hugepages.go similarity index 100% rename from libcontainer/cgroups/config_hugepages.go rename to vendor/github.com/opencontainers/cgroups/config_hugepages.go diff --git a/libcontainer/cgroups/config_ifprio_map.go b/vendor/github.com/opencontainers/cgroups/config_ifprio_map.go similarity index 100% rename from libcontainer/cgroups/config_ifprio_map.go rename to vendor/github.com/opencontainers/cgroups/config_ifprio_map.go diff --git a/libcontainer/cgroups/config_linux.go b/vendor/github.com/opencontainers/cgroups/config_linux.go similarity index 98% rename from libcontainer/cgroups/config_linux.go rename to vendor/github.com/opencontainers/cgroups/config_linux.go index 3052ef50d..ce98b3d78 100644 --- a/libcontainer/cgroups/config_linux.go +++ b/vendor/github.com/opencontainers/cgroups/config_linux.go @@ -2,7 +2,7 @@ package cgroups import ( systemdDbus "github.com/coreos/go-systemd/v22/dbus" - devices "github.com/opencontainers/runc/libcontainer/cgroups/devices/config" + devices "github.com/opencontainers/cgroups/devices/config" ) type FreezerState string diff --git a/libcontainer/cgroups/config_rdma.go b/vendor/github.com/opencontainers/cgroups/config_rdma.go similarity index 100% rename from libcontainer/cgroups/config_rdma.go rename to vendor/github.com/opencontainers/cgroups/config_rdma.go diff --git a/libcontainer/cgroups/config_unsupported.go b/vendor/github.com/opencontainers/cgroups/config_unsupported.go similarity index 100% rename from libcontainer/cgroups/config_unsupported.go rename to vendor/github.com/opencontainers/cgroups/config_unsupported.go diff --git a/libcontainer/cgroups/devices/config/device.go b/vendor/github.com/opencontainers/cgroups/devices/config/device.go similarity index 100% rename from libcontainer/cgroups/devices/config/device.go rename to vendor/github.com/opencontainers/cgroups/devices/config/device.go diff --git a/libcontainer/cgroups/devices/config/mknod_unix.go b/vendor/github.com/opencontainers/cgroups/devices/config/mknod_unix.go similarity index 100% rename from libcontainer/cgroups/devices/config/mknod_unix.go rename to vendor/github.com/opencontainers/cgroups/devices/config/mknod_unix.go diff --git a/libcontainer/cgroups/devices/devicefilter.go b/vendor/github.com/opencontainers/cgroups/devices/devicefilter.go similarity index 98% rename from libcontainer/cgroups/devices/devicefilter.go rename to vendor/github.com/opencontainers/cgroups/devices/devicefilter.go index 416c7f27a..aafa0d0b2 100644 --- a/libcontainer/cgroups/devices/devicefilter.go +++ b/vendor/github.com/opencontainers/cgroups/devices/devicefilter.go @@ -13,7 +13,7 @@ import ( "strconv" "github.com/cilium/ebpf/asm" - devices "github.com/opencontainers/runc/libcontainer/cgroups/devices/config" + devices "github.com/opencontainers/cgroups/devices/config" "golang.org/x/sys/unix" ) diff --git a/libcontainer/cgroups/devices/devices.go b/vendor/github.com/opencontainers/cgroups/devices/devices.go similarity index 75% rename from libcontainer/cgroups/devices/devices.go rename to vendor/github.com/opencontainers/cgroups/devices/devices.go index 844d0563b..2cfd7d0ff 100644 --- a/libcontainer/cgroups/devices/devices.go +++ b/vendor/github.com/opencontainers/cgroups/devices/devices.go @@ -5,8 +5,8 @@ package devices import ( - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/systemd" + "github.com/opencontainers/cgroups" + "github.com/opencontainers/cgroups/systemd" ) func init() { diff --git a/libcontainer/cgroups/devices/devices_emulator.go b/vendor/github.com/opencontainers/cgroups/devices/devices_emulator.go similarity index 99% rename from libcontainer/cgroups/devices/devices_emulator.go rename to vendor/github.com/opencontainers/cgroups/devices/devices_emulator.go index 81ff206a9..ab1826826 100644 --- a/libcontainer/cgroups/devices/devices_emulator.go +++ b/vendor/github.com/opencontainers/cgroups/devices/devices_emulator.go @@ -26,7 +26,7 @@ import ( "strconv" "strings" - devices "github.com/opencontainers/runc/libcontainer/cgroups/devices/config" + devices "github.com/opencontainers/cgroups/devices/config" ) // deviceMeta is a Rule without the Allow or Permissions fields, and no diff --git a/libcontainer/cgroups/devices/ebpf_linux.go b/vendor/github.com/opencontainers/cgroups/devices/ebpf_linux.go similarity index 100% rename from libcontainer/cgroups/devices/ebpf_linux.go rename to vendor/github.com/opencontainers/cgroups/devices/ebpf_linux.go diff --git a/libcontainer/cgroups/devices/systemd.go b/vendor/github.com/opencontainers/cgroups/devices/systemd.go similarity index 98% rename from libcontainer/cgroups/devices/systemd.go rename to vendor/github.com/opencontainers/cgroups/devices/systemd.go index 47ba7182b..010f7f22e 100644 --- a/libcontainer/cgroups/devices/systemd.go +++ b/vendor/github.com/opencontainers/cgroups/devices/systemd.go @@ -11,8 +11,8 @@ import ( "github.com/godbus/dbus/v5" "github.com/sirupsen/logrus" - "github.com/opencontainers/runc/libcontainer/cgroups" - devices "github.com/opencontainers/runc/libcontainer/cgroups/devices/config" + "github.com/opencontainers/cgroups" + devices "github.com/opencontainers/cgroups/devices/config" ) // systemdProperties takes the configured device rules and generates a diff --git a/libcontainer/cgroups/devices/v1.go b/vendor/github.com/opencontainers/cgroups/devices/v1.go similarity index 94% rename from libcontainer/cgroups/devices/v1.go rename to vendor/github.com/opencontainers/cgroups/devices/v1.go index 27a7ab294..8d0986dd3 100644 --- a/libcontainer/cgroups/devices/v1.go +++ b/vendor/github.com/opencontainers/cgroups/devices/v1.go @@ -6,8 +6,8 @@ import ( "reflect" "github.com/moby/sys/userns" - "github.com/opencontainers/runc/libcontainer/cgroups" - devices "github.com/opencontainers/runc/libcontainer/cgroups/devices/config" + "github.com/opencontainers/cgroups" + devices "github.com/opencontainers/cgroups/devices/config" ) var testingSkipFinalCheck bool diff --git a/libcontainer/cgroups/devices/v2.go b/vendor/github.com/opencontainers/cgroups/devices/v2.go similarity index 93% rename from libcontainer/cgroups/devices/v2.go rename to vendor/github.com/opencontainers/cgroups/devices/v2.go index 911d1ce2f..d54298f7e 100644 --- a/libcontainer/cgroups/devices/v2.go +++ b/vendor/github.com/opencontainers/cgroups/devices/v2.go @@ -6,8 +6,8 @@ import ( "github.com/moby/sys/userns" "golang.org/x/sys/unix" - "github.com/opencontainers/runc/libcontainer/cgroups" - devices "github.com/opencontainers/runc/libcontainer/cgroups/devices/config" + "github.com/opencontainers/cgroups" + devices "github.com/opencontainers/cgroups/devices/config" ) func isRWM(perms devices.Permissions) bool { diff --git a/libcontainer/cgroups/file.go b/vendor/github.com/opencontainers/cgroups/file.go similarity index 100% rename from libcontainer/cgroups/file.go rename to vendor/github.com/opencontainers/cgroups/file.go diff --git a/libcontainer/cgroups/fs/blkio.go b/vendor/github.com/opencontainers/cgroups/fs/blkio.go similarity index 99% rename from libcontainer/cgroups/fs/blkio.go rename to vendor/github.com/opencontainers/cgroups/fs/blkio.go index 58d8ded6a..f3c4c5cf8 100644 --- a/libcontainer/cgroups/fs/blkio.go +++ b/vendor/github.com/opencontainers/cgroups/fs/blkio.go @@ -7,7 +7,7 @@ import ( "strconv" "strings" - "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/cgroups" ) type BlkioGroup struct { diff --git a/libcontainer/cgroups/fs/cpu.go b/vendor/github.com/opencontainers/cgroups/fs/cpu.go similarity index 97% rename from libcontainer/cgroups/fs/cpu.go rename to vendor/github.com/opencontainers/cgroups/fs/cpu.go index e3dd1ebe3..3e05788a3 100644 --- a/libcontainer/cgroups/fs/cpu.go +++ b/vendor/github.com/opencontainers/cgroups/fs/cpu.go @@ -7,8 +7,8 @@ import ( "os" "strconv" - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" + "github.com/opencontainers/cgroups" + "github.com/opencontainers/cgroups/fscommon" "golang.org/x/sys/unix" ) diff --git a/libcontainer/cgroups/fs/cpuacct.go b/vendor/github.com/opencontainers/cgroups/fs/cpuacct.go similarity index 97% rename from libcontainer/cgroups/fs/cpuacct.go rename to vendor/github.com/opencontainers/cgroups/fs/cpuacct.go index 53ffbb8e6..391a023c7 100644 --- a/libcontainer/cgroups/fs/cpuacct.go +++ b/vendor/github.com/opencontainers/cgroups/fs/cpuacct.go @@ -6,8 +6,8 @@ import ( "strconv" "strings" - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" + "github.com/opencontainers/cgroups" + "github.com/opencontainers/cgroups/fscommon" ) const ( diff --git a/libcontainer/cgroups/fs/cpuset.go b/vendor/github.com/opencontainers/cgroups/fs/cpuset.go similarity index 98% rename from libcontainer/cgroups/fs/cpuset.go rename to vendor/github.com/opencontainers/cgroups/fs/cpuset.go index f517c6b57..ef6ff7da3 100644 --- a/libcontainer/cgroups/fs/cpuset.go +++ b/vendor/github.com/opencontainers/cgroups/fs/cpuset.go @@ -10,8 +10,8 @@ import ( "golang.org/x/sys/unix" - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" + "github.com/opencontainers/cgroups" + "github.com/opencontainers/cgroups/fscommon" ) var ( diff --git a/libcontainer/cgroups/fs/devices.go b/vendor/github.com/opencontainers/cgroups/fs/devices.go similarity index 93% rename from libcontainer/cgroups/fs/devices.go rename to vendor/github.com/opencontainers/cgroups/fs/devices.go index 305bb0dac..26483ecb7 100644 --- a/libcontainer/cgroups/fs/devices.go +++ b/vendor/github.com/opencontainers/cgroups/fs/devices.go @@ -1,7 +1,7 @@ package fs import ( - "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/cgroups" ) type DevicesGroup struct{} diff --git a/libcontainer/cgroups/fs/error.go b/vendor/github.com/opencontainers/cgroups/fs/error.go similarity index 84% rename from libcontainer/cgroups/fs/error.go rename to vendor/github.com/opencontainers/cgroups/fs/error.go index f2ab6f130..f13033e3d 100644 --- a/libcontainer/cgroups/fs/error.go +++ b/vendor/github.com/opencontainers/cgroups/fs/error.go @@ -3,7 +3,7 @@ package fs import ( "fmt" - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" + "github.com/opencontainers/cgroups/fscommon" ) type parseError = fscommon.ParseError diff --git a/libcontainer/cgroups/fs/freezer.go b/vendor/github.com/opencontainers/cgroups/fs/freezer.go similarity index 98% rename from libcontainer/cgroups/fs/freezer.go rename to vendor/github.com/opencontainers/cgroups/fs/freezer.go index c959afde3..dae4a6058 100644 --- a/libcontainer/cgroups/fs/freezer.go +++ b/vendor/github.com/opencontainers/cgroups/fs/freezer.go @@ -7,7 +7,7 @@ import ( "strings" "time" - "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/cgroups" "github.com/sirupsen/logrus" "golang.org/x/sys/unix" ) diff --git a/libcontainer/cgroups/fs/fs.go b/vendor/github.com/opencontainers/cgroups/fs/fs.go similarity index 98% rename from libcontainer/cgroups/fs/fs.go rename to vendor/github.com/opencontainers/cgroups/fs/fs.go index 490847246..23a8fb874 100644 --- a/libcontainer/cgroups/fs/fs.go +++ b/vendor/github.com/opencontainers/cgroups/fs/fs.go @@ -8,8 +8,8 @@ import ( "golang.org/x/sys/unix" - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" + "github.com/opencontainers/cgroups" + "github.com/opencontainers/cgroups/fscommon" ) var subsystems = []subsystem{ diff --git a/libcontainer/cgroups/fs/hugetlb.go b/vendor/github.com/opencontainers/cgroups/fs/hugetlb.go similarity index 93% rename from libcontainer/cgroups/fs/hugetlb.go rename to vendor/github.com/opencontainers/cgroups/fs/hugetlb.go index 9800f627a..698fd691e 100644 --- a/libcontainer/cgroups/fs/hugetlb.go +++ b/vendor/github.com/opencontainers/cgroups/fs/hugetlb.go @@ -5,8 +5,8 @@ import ( "os" "strconv" - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" + "github.com/opencontainers/cgroups" + "github.com/opencontainers/cgroups/fscommon" ) type HugetlbGroup struct{} diff --git a/libcontainer/cgroups/fs/memory.go b/vendor/github.com/opencontainers/cgroups/fs/memory.go similarity index 98% rename from libcontainer/cgroups/fs/memory.go rename to vendor/github.com/opencontainers/cgroups/fs/memory.go index ad9190db1..d92f2322b 100644 --- a/libcontainer/cgroups/fs/memory.go +++ b/vendor/github.com/opencontainers/cgroups/fs/memory.go @@ -12,8 +12,8 @@ import ( "golang.org/x/sys/unix" - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" + "github.com/opencontainers/cgroups" + "github.com/opencontainers/cgroups/fscommon" ) const ( diff --git a/libcontainer/cgroups/fs/name.go b/vendor/github.com/opencontainers/cgroups/fs/name.go similarity index 90% rename from libcontainer/cgroups/fs/name.go rename to vendor/github.com/opencontainers/cgroups/fs/name.go index bf51cd632..28643519b 100644 --- a/libcontainer/cgroups/fs/name.go +++ b/vendor/github.com/opencontainers/cgroups/fs/name.go @@ -1,7 +1,7 @@ package fs import ( - "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/cgroups" ) type NameGroup struct { diff --git a/libcontainer/cgroups/fs/net_cls.go b/vendor/github.com/opencontainers/cgroups/fs/net_cls.go similarity index 91% rename from libcontainer/cgroups/fs/net_cls.go rename to vendor/github.com/opencontainers/cgroups/fs/net_cls.go index ce3b3f3ae..2bd6c5ab2 100644 --- a/libcontainer/cgroups/fs/net_cls.go +++ b/vendor/github.com/opencontainers/cgroups/fs/net_cls.go @@ -3,7 +3,7 @@ package fs import ( "strconv" - "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/cgroups" ) type NetClsGroup struct{} diff --git a/libcontainer/cgroups/fs/net_prio.go b/vendor/github.com/opencontainers/cgroups/fs/net_prio.go similarity index 91% rename from libcontainer/cgroups/fs/net_prio.go rename to vendor/github.com/opencontainers/cgroups/fs/net_prio.go index 3fb5050ab..b51682b6d 100644 --- a/libcontainer/cgroups/fs/net_prio.go +++ b/vendor/github.com/opencontainers/cgroups/fs/net_prio.go @@ -1,7 +1,7 @@ package fs import ( - "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/cgroups" ) type NetPrioGroup struct{} diff --git a/libcontainer/cgroups/fs/paths.go b/vendor/github.com/opencontainers/cgroups/fs/paths.go similarity index 96% rename from libcontainer/cgroups/fs/paths.go rename to vendor/github.com/opencontainers/cgroups/fs/paths.go index 59cd13d5c..edbe041ea 100644 --- a/libcontainer/cgroups/fs/paths.go +++ b/vendor/github.com/opencontainers/cgroups/fs/paths.go @@ -8,8 +8,8 @@ import ( "golang.org/x/sys/unix" - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/internal/path" + "github.com/opencontainers/cgroups" + "github.com/opencontainers/cgroups/internal/path" ) // The absolute path to the root of the cgroup hierarchies. diff --git a/libcontainer/cgroups/fs/perf_event.go b/vendor/github.com/opencontainers/cgroups/fs/perf_event.go similarity index 88% rename from libcontainer/cgroups/fs/perf_event.go rename to vendor/github.com/opencontainers/cgroups/fs/perf_event.go index 3a04767a2..929c412a3 100644 --- a/libcontainer/cgroups/fs/perf_event.go +++ b/vendor/github.com/opencontainers/cgroups/fs/perf_event.go @@ -1,7 +1,7 @@ package fs import ( - "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/cgroups" ) type PerfEventGroup struct{} diff --git a/libcontainer/cgroups/fs/pids.go b/vendor/github.com/opencontainers/cgroups/fs/pids.go similarity index 90% rename from libcontainer/cgroups/fs/pids.go rename to vendor/github.com/opencontainers/cgroups/fs/pids.go index 6ab094bc0..9319761e6 100644 --- a/libcontainer/cgroups/fs/pids.go +++ b/vendor/github.com/opencontainers/cgroups/fs/pids.go @@ -4,8 +4,8 @@ import ( "math" "strconv" - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" + "github.com/opencontainers/cgroups" + "github.com/opencontainers/cgroups/fscommon" ) type PidsGroup struct{} diff --git a/libcontainer/cgroups/fs/rdma.go b/vendor/github.com/opencontainers/cgroups/fs/rdma.go similarity index 78% rename from libcontainer/cgroups/fs/rdma.go rename to vendor/github.com/opencontainers/cgroups/fs/rdma.go index bc40c2d5b..4b175365f 100644 --- a/libcontainer/cgroups/fs/rdma.go +++ b/vendor/github.com/opencontainers/cgroups/fs/rdma.go @@ -1,8 +1,8 @@ package fs import ( - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" + "github.com/opencontainers/cgroups" + "github.com/opencontainers/cgroups/fscommon" ) type RdmaGroup struct{} diff --git a/libcontainer/cgroups/fs2/cpu.go b/vendor/github.com/opencontainers/cgroups/fs2/cpu.go similarity index 95% rename from libcontainer/cgroups/fs2/cpu.go rename to vendor/github.com/opencontainers/cgroups/fs2/cpu.go index 9734f6c45..8eae67351 100644 --- a/libcontainer/cgroups/fs2/cpu.go +++ b/vendor/github.com/opencontainers/cgroups/fs2/cpu.go @@ -8,8 +8,8 @@ import ( "golang.org/x/sys/unix" - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" + "github.com/opencontainers/cgroups" + "github.com/opencontainers/cgroups/fscommon" ) func isCPUSet(r *cgroups.Resources) bool { diff --git a/libcontainer/cgroups/fs2/cpuset.go b/vendor/github.com/opencontainers/cgroups/fs2/cpuset.go similarity index 89% rename from libcontainer/cgroups/fs2/cpuset.go rename to vendor/github.com/opencontainers/cgroups/fs2/cpuset.go index 7c3326e37..9399919a0 100644 --- a/libcontainer/cgroups/fs2/cpuset.go +++ b/vendor/github.com/opencontainers/cgroups/fs2/cpuset.go @@ -1,7 +1,7 @@ package fs2 import ( - "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/cgroups" ) func isCpusetSet(r *cgroups.Resources) bool { diff --git a/libcontainer/cgroups/fs2/create.go b/vendor/github.com/opencontainers/cgroups/fs2/create.go similarity index 98% rename from libcontainer/cgroups/fs2/create.go rename to vendor/github.com/opencontainers/cgroups/fs2/create.go index 9427aae60..565ca8830 100644 --- a/libcontainer/cgroups/fs2/create.go +++ b/vendor/github.com/opencontainers/cgroups/fs2/create.go @@ -6,7 +6,7 @@ import ( "path/filepath" "strings" - "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/cgroups" ) func supportedControllers() (string, error) { diff --git a/libcontainer/cgroups/fs2/defaultpath.go b/vendor/github.com/opencontainers/cgroups/fs2/defaultpath.go similarity index 94% rename from libcontainer/cgroups/fs2/defaultpath.go rename to vendor/github.com/opencontainers/cgroups/fs2/defaultpath.go index 6a08cceaf..0bc479de3 100644 --- a/libcontainer/cgroups/fs2/defaultpath.go +++ b/vendor/github.com/opencontainers/cgroups/fs2/defaultpath.go @@ -24,8 +24,8 @@ import ( "path/filepath" "strings" - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/internal/path" + "github.com/opencontainers/cgroups" + "github.com/opencontainers/cgroups/internal/path" ) const UnifiedMountpoint = "/sys/fs/cgroup" diff --git a/libcontainer/cgroups/fs2/freezer.go b/vendor/github.com/opencontainers/cgroups/fs2/freezer.go similarity index 98% rename from libcontainer/cgroups/fs2/freezer.go rename to vendor/github.com/opencontainers/cgroups/fs2/freezer.go index 1f831500f..f0192f095 100644 --- a/libcontainer/cgroups/fs2/freezer.go +++ b/vendor/github.com/opencontainers/cgroups/fs2/freezer.go @@ -10,7 +10,7 @@ import ( "golang.org/x/sys/unix" - "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/cgroups" ) func setFreezer(dirPath string, state cgroups.FreezerState) error { diff --git a/libcontainer/cgroups/fs2/fs2.go b/vendor/github.com/opencontainers/cgroups/fs2/fs2.go similarity index 98% rename from libcontainer/cgroups/fs2/fs2.go rename to vendor/github.com/opencontainers/cgroups/fs2/fs2.go index 10e4a3ad8..c5d5a1f8e 100644 --- a/libcontainer/cgroups/fs2/fs2.go +++ b/vendor/github.com/opencontainers/cgroups/fs2/fs2.go @@ -6,8 +6,8 @@ import ( "os" "strings" - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" + "github.com/opencontainers/cgroups" + "github.com/opencontainers/cgroups/fscommon" ) type parseError = fscommon.ParseError diff --git a/libcontainer/cgroups/fs2/hugetlb.go b/vendor/github.com/opencontainers/cgroups/fs2/hugetlb.go similarity index 92% rename from libcontainer/cgroups/fs2/hugetlb.go rename to vendor/github.com/opencontainers/cgroups/fs2/hugetlb.go index 117b69f50..8e1ac874a 100644 --- a/libcontainer/cgroups/fs2/hugetlb.go +++ b/vendor/github.com/opencontainers/cgroups/fs2/hugetlb.go @@ -5,8 +5,8 @@ import ( "os" "strconv" - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" + "github.com/opencontainers/cgroups" + "github.com/opencontainers/cgroups/fscommon" ) func isHugeTlbSet(r *cgroups.Resources) bool { diff --git a/libcontainer/cgroups/fs2/io.go b/vendor/github.com/opencontainers/cgroups/fs2/io.go similarity index 98% rename from libcontainer/cgroups/fs2/io.go rename to vendor/github.com/opencontainers/cgroups/fs2/io.go index 2da1449eb..0f6ef7fea 100644 --- a/libcontainer/cgroups/fs2/io.go +++ b/vendor/github.com/opencontainers/cgroups/fs2/io.go @@ -10,7 +10,7 @@ import ( "github.com/sirupsen/logrus" - "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/cgroups" ) func isIoSet(r *cgroups.Resources) bool { diff --git a/libcontainer/cgroups/fs2/memory.go b/vendor/github.com/opencontainers/cgroups/fs2/memory.go similarity index 98% rename from libcontainer/cgroups/fs2/memory.go rename to vendor/github.com/opencontainers/cgroups/fs2/memory.go index f314755f4..d67fd8aba 100644 --- a/libcontainer/cgroups/fs2/memory.go +++ b/vendor/github.com/opencontainers/cgroups/fs2/memory.go @@ -10,8 +10,8 @@ import ( "golang.org/x/sys/unix" - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" + "github.com/opencontainers/cgroups" + "github.com/opencontainers/cgroups/fscommon" ) // numToStr converts an int64 value to a string for writing to a diff --git a/libcontainer/cgroups/fs2/misc.go b/vendor/github.com/opencontainers/cgroups/fs2/misc.go similarity index 87% rename from libcontainer/cgroups/fs2/misc.go rename to vendor/github.com/opencontainers/cgroups/fs2/misc.go index f0b292aa0..f20136b66 100644 --- a/libcontainer/cgroups/fs2/misc.go +++ b/vendor/github.com/opencontainers/cgroups/fs2/misc.go @@ -5,8 +5,8 @@ import ( "os" "strings" - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" + "github.com/opencontainers/cgroups" + "github.com/opencontainers/cgroups/fscommon" ) func statMisc(dirPath string, stats *cgroups.Stats) error { diff --git a/libcontainer/cgroups/fs2/pids.go b/vendor/github.com/opencontainers/cgroups/fs2/pids.go similarity index 92% rename from libcontainer/cgroups/fs2/pids.go rename to vendor/github.com/opencontainers/cgroups/fs2/pids.go index 86d2f5673..9b82b9011 100644 --- a/libcontainer/cgroups/fs2/pids.go +++ b/vendor/github.com/opencontainers/cgroups/fs2/pids.go @@ -8,8 +8,8 @@ import ( "golang.org/x/sys/unix" - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" + "github.com/opencontainers/cgroups" + "github.com/opencontainers/cgroups/fscommon" ) func isPidsSet(r *cgroups.Resources) bool { diff --git a/libcontainer/cgroups/fs2/psi.go b/vendor/github.com/opencontainers/cgroups/fs2/psi.go similarity index 97% rename from libcontainer/cgroups/fs2/psi.go rename to vendor/github.com/opencontainers/cgroups/fs2/psi.go index ac765affb..010fe0bff 100644 --- a/libcontainer/cgroups/fs2/psi.go +++ b/vendor/github.com/opencontainers/cgroups/fs2/psi.go @@ -10,7 +10,7 @@ import ( "golang.org/x/sys/unix" - "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/cgroups" ) func statPSI(dirPath string, file string) (*cgroups.PSIStats, error) { diff --git a/libcontainer/cgroups/fscommon/rdma.go b/vendor/github.com/opencontainers/cgroups/fscommon/rdma.go similarity index 97% rename from libcontainer/cgroups/fscommon/rdma.go rename to vendor/github.com/opencontainers/cgroups/fscommon/rdma.go index 70d92a000..86e38fdcb 100644 --- a/libcontainer/cgroups/fscommon/rdma.go +++ b/vendor/github.com/opencontainers/cgroups/fscommon/rdma.go @@ -10,7 +10,7 @@ import ( "golang.org/x/sys/unix" - "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/cgroups" ) // parseRdmaKV parses raw string to RdmaEntry. diff --git a/libcontainer/cgroups/fscommon/utils.go b/vendor/github.com/opencontainers/cgroups/fscommon/utils.go similarity index 98% rename from libcontainer/cgroups/fscommon/utils.go rename to vendor/github.com/opencontainers/cgroups/fscommon/utils.go index e11e038f2..d8f8dfc02 100644 --- a/libcontainer/cgroups/fscommon/utils.go +++ b/vendor/github.com/opencontainers/cgroups/fscommon/utils.go @@ -8,7 +8,7 @@ import ( "strconv" "strings" - "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/cgroups" ) var ( diff --git a/libcontainer/cgroups/getallpids.go b/vendor/github.com/opencontainers/cgroups/getallpids.go similarity index 100% rename from libcontainer/cgroups/getallpids.go rename to vendor/github.com/opencontainers/cgroups/getallpids.go diff --git a/libcontainer/cgroups/internal/path/path.go b/vendor/github.com/opencontainers/cgroups/internal/path/path.go similarity index 96% rename from libcontainer/cgroups/internal/path/path.go rename to vendor/github.com/opencontainers/cgroups/internal/path/path.go index 94e491791..a105a7cf4 100644 --- a/libcontainer/cgroups/internal/path/path.go +++ b/vendor/github.com/opencontainers/cgroups/internal/path/path.go @@ -5,7 +5,7 @@ import ( "os" "path/filepath" - "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/cgroups" ) // Inner returns a path to cgroup relative to a cgroup mount point, based diff --git a/libcontainer/cgroups/manager/new.go b/vendor/github.com/opencontainers/cgroups/manager/new.go similarity index 90% rename from libcontainer/cgroups/manager/new.go rename to vendor/github.com/opencontainers/cgroups/manager/new.go index f6313b16b..2df39e587 100644 --- a/libcontainer/cgroups/manager/new.go +++ b/vendor/github.com/opencontainers/cgroups/manager/new.go @@ -5,10 +5,10 @@ import ( "fmt" "path/filepath" - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/fs" - "github.com/opencontainers/runc/libcontainer/cgroups/fs2" - "github.com/opencontainers/runc/libcontainer/cgroups/systemd" + "github.com/opencontainers/cgroups" + "github.com/opencontainers/cgroups/fs" + "github.com/opencontainers/cgroups/fs2" + "github.com/opencontainers/cgroups/systemd" ) // New returns the instance of a cgroup manager, which is chosen diff --git a/libcontainer/cgroups/stats.go b/vendor/github.com/opencontainers/cgroups/stats.go similarity index 100% rename from libcontainer/cgroups/stats.go rename to vendor/github.com/opencontainers/cgroups/stats.go diff --git a/libcontainer/cgroups/systemd/common.go b/vendor/github.com/opencontainers/cgroups/systemd/common.go similarity index 98% rename from libcontainer/cgroups/systemd/common.go rename to vendor/github.com/opencontainers/cgroups/systemd/common.go index bcd1f99eb..b3077bd37 100644 --- a/libcontainer/cgroups/systemd/common.go +++ b/vendor/github.com/opencontainers/cgroups/systemd/common.go @@ -15,7 +15,7 @@ import ( dbus "github.com/godbus/dbus/v5" "github.com/sirupsen/logrus" - "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/cgroups" ) const ( @@ -34,7 +34,7 @@ var ( // GenerateDeviceProps is a function to generate systemd device // properties, used by Set methods. Unless - // [github.com/opencontainers/runc/libcontainer/cgroups/devices] + // [github.com/opencontainers/cgroups/devices] // package is imported, it is set to nil, so cgroup managers can't // configure devices. GenerateDeviceProps func(r *cgroups.Resources, sdVer int) ([]systemdDbus.Property, error) diff --git a/libcontainer/cgroups/systemd/cpuset.go b/vendor/github.com/opencontainers/cgroups/systemd/cpuset.go similarity index 100% rename from libcontainer/cgroups/systemd/cpuset.go rename to vendor/github.com/opencontainers/cgroups/systemd/cpuset.go diff --git a/libcontainer/cgroups/systemd/dbus.go b/vendor/github.com/opencontainers/cgroups/systemd/dbus.go similarity index 100% rename from libcontainer/cgroups/systemd/dbus.go rename to vendor/github.com/opencontainers/cgroups/systemd/dbus.go diff --git a/libcontainer/cgroups/systemd/devices.go b/vendor/github.com/opencontainers/cgroups/systemd/devices.go similarity index 97% rename from libcontainer/cgroups/systemd/devices.go rename to vendor/github.com/opencontainers/cgroups/systemd/devices.go index 424d1c6eb..51ca7fa11 100644 --- a/libcontainer/cgroups/systemd/devices.go +++ b/vendor/github.com/opencontainers/cgroups/systemd/devices.go @@ -5,7 +5,7 @@ import ( dbus "github.com/godbus/dbus/v5" - "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/cgroups" ) // freezeBeforeSet answers whether there is a need to freeze the cgroup before diff --git a/libcontainer/cgroups/systemd/user.go b/vendor/github.com/opencontainers/cgroups/systemd/user.go similarity index 100% rename from libcontainer/cgroups/systemd/user.go rename to vendor/github.com/opencontainers/cgroups/systemd/user.go diff --git a/libcontainer/cgroups/systemd/v1.go b/vendor/github.com/opencontainers/cgroups/systemd/v1.go similarity index 98% rename from libcontainer/cgroups/systemd/v1.go rename to vendor/github.com/opencontainers/cgroups/systemd/v1.go index cee76eb35..8453e9b49 100644 --- a/libcontainer/cgroups/systemd/v1.go +++ b/vendor/github.com/opencontainers/cgroups/systemd/v1.go @@ -10,8 +10,8 @@ import ( systemdDbus "github.com/coreos/go-systemd/v22/dbus" "github.com/sirupsen/logrus" - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/fs" + "github.com/opencontainers/cgroups" + "github.com/opencontainers/cgroups/fs" ) type LegacyManager struct { diff --git a/libcontainer/cgroups/systemd/v2.go b/vendor/github.com/opencontainers/cgroups/systemd/v2.go similarity index 99% rename from libcontainer/cgroups/systemd/v2.go rename to vendor/github.com/opencontainers/cgroups/systemd/v2.go index 7b16f528b..42a6e3551 100644 --- a/libcontainer/cgroups/systemd/v2.go +++ b/vendor/github.com/opencontainers/cgroups/systemd/v2.go @@ -15,8 +15,8 @@ import ( securejoin "github.com/cyphar/filepath-securejoin" "github.com/sirupsen/logrus" - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/fs2" + "github.com/opencontainers/cgroups" + "github.com/opencontainers/cgroups/fs2" ) const ( diff --git a/libcontainer/cgroups/utils.go b/vendor/github.com/opencontainers/cgroups/utils.go similarity index 100% rename from libcontainer/cgroups/utils.go rename to vendor/github.com/opencontainers/cgroups/utils.go diff --git a/libcontainer/cgroups/v1_utils.go b/vendor/github.com/opencontainers/cgroups/v1_utils.go similarity index 100% rename from libcontainer/cgroups/v1_utils.go rename to vendor/github.com/opencontainers/cgroups/v1_utils.go diff --git a/vendor/modules.txt b/vendor/modules.txt index 16797f3ad..0ead139c0 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -51,6 +51,17 @@ github.com/moby/sys/userns # github.com/mrunalp/fileutils v0.5.1 ## explicit; go 1.13 github.com/mrunalp/fileutils +# github.com/opencontainers/cgroups v0.0.1 +## explicit; go 1.23.0 +github.com/opencontainers/cgroups +github.com/opencontainers/cgroups/devices +github.com/opencontainers/cgroups/devices/config +github.com/opencontainers/cgroups/fs +github.com/opencontainers/cgroups/fs2 +github.com/opencontainers/cgroups/fscommon +github.com/opencontainers/cgroups/internal/path +github.com/opencontainers/cgroups/manager +github.com/opencontainers/cgroups/systemd # github.com/opencontainers/runtime-spec v1.2.1 ## explicit github.com/opencontainers/runtime-spec/specs-go