Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit dbea6f2

Browse files
Merge pull request #77 from crosbymichael/non-active
Check for non-active/supported cgroups
2 parents 39b18af + 4a9f0f7 commit dbea6f2

File tree

4 files changed

+129
-4
lines changed

4 files changed

+129
-4
lines changed

cgroup.go

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,24 +30,49 @@ import (
3030
)
3131

3232
// New returns a new control via the cgroup cgroups interface
33-
func New(hierarchy Hierarchy, path Path, resources *specs.LinuxResources) (Cgroup, error) {
33+
func New(hierarchy Hierarchy, path Path, resources *specs.LinuxResources, opts ...InitOpts) (Cgroup, error) {
34+
config := newInitConfig()
35+
for _, o := range opts {
36+
if err := o(config); err != nil {
37+
return nil, err
38+
}
39+
}
3440
subsystems, err := hierarchy()
3541
if err != nil {
3642
return nil, err
3743
}
44+
var active []Subsystem
3845
for _, s := range subsystems {
46+
// check if subsystem exists
3947
if err := initializeSubsystem(s, path, resources); err != nil {
48+
if err == ErrControllerNotActive {
49+
if config.InitCheck != nil {
50+
if skerr := config.InitCheck(s, path, err); skerr != nil {
51+
if skerr != ErrIgnoreSubsystem {
52+
return nil, skerr
53+
}
54+
}
55+
}
56+
continue
57+
}
4058
return nil, err
4159
}
60+
active = append(active, s)
4261
}
4362
return &cgroup{
4463
path: path,
45-
subsystems: subsystems,
64+
subsystems: active,
4665
}, nil
4766
}
4867

4968
// Load will load an existing cgroup and allow it to be controlled
50-
func Load(hierarchy Hierarchy, path Path) (Cgroup, error) {
69+
func Load(hierarchy Hierarchy, path Path, opts ...InitOpts) (Cgroup, error) {
70+
config := newInitConfig()
71+
for _, o := range opts {
72+
if err := o(config); err != nil {
73+
return nil, err
74+
}
75+
}
5176
var activeSubsystems []Subsystem
5277
subsystems, err := hierarchy()
5378
if err != nil {
@@ -60,6 +85,16 @@ func Load(hierarchy Hierarchy, path Path) (Cgroup, error) {
6085
if os.IsNotExist(errors.Cause(err)) {
6186
return nil, ErrCgroupDeleted
6287
}
88+
if err == ErrControllerNotActive {
89+
if config.InitCheck != nil {
90+
if skerr := config.InitCheck(s, path, err); skerr != nil {
91+
if skerr != ErrIgnoreSubsystem {
92+
return nil, skerr
93+
}
94+
}
95+
}
96+
continue
97+
}
6398
return nil, err
6499
}
65100
if _, err := os.Lstat(s.Path(p)); err != nil {

opts.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
Copyright The containerd Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package cgroups
18+
19+
import (
20+
"github.com/pkg/errors"
21+
)
22+
23+
var (
24+
// ErrIgnoreSubsystem allows the specific subsystem to be skipped
25+
ErrIgnoreSubsystem = errors.New("skip subsystem")
26+
// ErrDevicesRequired is returned when the devices subsystem is required but
27+
// does not exist or is not active
28+
ErrDevicesRequired = errors.New("devices subsystem is required")
29+
)
30+
31+
// InitOpts allows configuration for the creation or loading of a cgroup
32+
type InitOpts func(*InitConfig) error
33+
34+
// InitConfig provides configuration options for the creation
35+
// or loading of a cgroup and its subsystems
36+
type InitConfig struct {
37+
// InitCheck can be used to check initialization errors from the subsystem
38+
InitCheck InitCheck
39+
}
40+
41+
func newInitConfig() *InitConfig {
42+
return &InitConfig{
43+
InitCheck: RequireDevices,
44+
}
45+
}
46+
47+
// InitCheck allows subsystems errors to be checked when initialized or loaded
48+
type InitCheck func(Subsystem, Path, error) error
49+
50+
// AllowAny allows any subsystem errors to be skipped
51+
func AllowAny(s Subsystem, p Path, err error) error {
52+
return ErrIgnoreSubsystem
53+
}
54+
55+
// RequireDevices requires the device subsystem but no others
56+
func RequireDevices(s Subsystem, p Path, err error) error {
57+
if s.Name() == Devices {
58+
return ErrDevicesRequired
59+
}
60+
return ErrIgnoreSubsystem
61+
}

paths.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ func PidPath(pid int) Path {
5757
return existingPath(paths, "")
5858
}
5959

60+
// ErrControllerNotActive is returned when a controller is not supported or enabled
61+
var ErrControllerNotActive = errors.New("controller is not supported")
62+
6063
func existingPath(paths map[string]string, suffix string) Path {
6164
// localize the paths based on the root mount dest for nested cgroups
6265
for n, p := range paths {
@@ -77,7 +80,7 @@ func existingPath(paths map[string]string, suffix string) Path {
7780
root, ok := paths[string(name)]
7881
if !ok {
7982
if root, ok = paths[fmt.Sprintf("name=%s", name)]; !ok {
80-
return "", fmt.Errorf("unable to find %q in controller set", name)
83+
return "", ErrControllerNotActive
8184
}
8285
}
8386
if suffix != "" {

paths_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,3 +112,29 @@ func TestEmptySubsystem(t *testing.T) {
112112
}
113113
}
114114
}
115+
116+
func TestSystemd240(t *testing.T) {
117+
const data = `8:net_cls:/
118+
7:memory:/system.slice/docker.service
119+
6:freezer:/
120+
5:blkio:/system.slice/docker.service
121+
4:devices:/system.slice/docker.service
122+
3:cpuset:/
123+
2:cpu,cpuacct:/system.slice/docker.service
124+
1:name=systemd:/system.slice/docker.service
125+
0::/system.slice/docker.service`
126+
r := strings.NewReader(data)
127+
paths, err := parseCgroupFromReader(r)
128+
if err != nil {
129+
t.Fatal(err)
130+
}
131+
132+
path := existingPath(paths, "")
133+
_, err = path("net_prio")
134+
if err == nil {
135+
t.Fatal("error for net_prio shoulld not be nil")
136+
}
137+
if err != ErrControllerNotActive {
138+
t.Fatalf("expected error %q but received %q", ErrControllerNotActive, err)
139+
}
140+
}

0 commit comments

Comments
 (0)