...

Source file src/github.com/opencontainers/runc/libcontainer/cgroups/manager/new.go

Documentation: github.com/opencontainers/runc/libcontainer/cgroups/manager

     1  package manager
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"path/filepath"
     7  
     8  	"github.com/opencontainers/runc/libcontainer/cgroups"
     9  	"github.com/opencontainers/runc/libcontainer/cgroups/fs"
    10  	"github.com/opencontainers/runc/libcontainer/cgroups/fs2"
    11  	"github.com/opencontainers/runc/libcontainer/cgroups/systemd"
    12  	"github.com/opencontainers/runc/libcontainer/configs"
    13  )
    14  
    15  // New returns the instance of a cgroup manager, which is chosen
    16  // based on the local environment (whether cgroup v1 or v2 is used)
    17  // and the config (whether config.Systemd is set or not).
    18  func New(config *configs.Cgroup) (cgroups.Manager, error) {
    19  	return NewWithPaths(config, nil)
    20  }
    21  
    22  // NewWithPaths is similar to New, and can be used in case cgroup paths
    23  // are already well known, which can save some resources.
    24  //
    25  // For cgroup v1, the keys are controller/subsystem name, and the values
    26  // are absolute filesystem paths to the appropriate cgroups.
    27  //
    28  // For cgroup v2, the only key allowed is "" (empty string), and the value
    29  // is the unified cgroup path.
    30  func NewWithPaths(config *configs.Cgroup, paths map[string]string) (cgroups.Manager, error) {
    31  	if config == nil {
    32  		return nil, errors.New("cgroups/manager.New: config must not be nil")
    33  	}
    34  	if config.Systemd && !systemd.IsRunningSystemd() {
    35  		return nil, errors.New("systemd not running on this host, cannot use systemd cgroups manager")
    36  	}
    37  
    38  	// Cgroup v2 aka unified hierarchy.
    39  	if cgroups.IsCgroup2UnifiedMode() {
    40  		path, err := getUnifiedPath(paths)
    41  		if err != nil {
    42  			return nil, fmt.Errorf("manager.NewWithPaths: inconsistent paths: %w", err)
    43  		}
    44  		if config.Systemd {
    45  			return systemd.NewUnifiedManager(config, path)
    46  		}
    47  		return fs2.NewManager(config, path)
    48  	}
    49  
    50  	// Cgroup v1.
    51  	if config.Systemd {
    52  		return systemd.NewLegacyManager(config, paths)
    53  	}
    54  
    55  	return fs.NewManager(config, paths)
    56  }
    57  
    58  // getUnifiedPath is an implementation detail of libcontainer factory.
    59  // Historically, it saves cgroup paths as per-subsystem path map (as returned
    60  // by cm.GetPaths(""), but with v2 we only have one single unified path
    61  // (with "" as a key).
    62  //
    63  // This function converts from that map to string (using "" as a key),
    64  // and also checks that the map itself is sane.
    65  func getUnifiedPath(paths map[string]string) (string, error) {
    66  	if len(paths) > 1 {
    67  		return "", fmt.Errorf("expected a single path, got %+v", paths)
    68  	}
    69  	path := paths[""]
    70  	// can be empty
    71  	if path != "" {
    72  		if filepath.Clean(path) != path || !filepath.IsAbs(path) {
    73  			return "", fmt.Errorf("invalid path: %q", path)
    74  		}
    75  	}
    76  
    77  	return path, nil
    78  }
    79  

View as plain text