gitee.com/leisunstar/runtime@v0.0.0-20200521203717-5cef3e7b53f9/virtcontainers/pkg/cgroups/utils.go (about)

     1  // Copyright (c) 2020 Intel Corporation
     2  //
     3  // SPDX-License-Identifier: Apache-2.0
     4  //
     5  
     6  package cgroups
     7  
     8  import (
     9  	"fmt"
    10  	"os"
    11  	"path/filepath"
    12  	"regexp"
    13  
    14  	"github.com/opencontainers/runc/libcontainer/configs"
    15  	"github.com/opencontainers/runtime-spec/specs-go"
    16  	"golang.org/x/sys/unix"
    17  )
    18  
    19  // prepend a kata specific string to oci cgroup path to
    20  // form a different cgroup path, thus cAdvisor couldn't
    21  // find kata containers cgroup path on host to prevent it
    22  // from grabbing the stats data.
    23  const CgroupKataPrefix = "kata"
    24  
    25  // DefaultCgroupPath runtime-determined location in the cgroups hierarchy.
    26  const DefaultCgroupPath = "/vc"
    27  
    28  func RenameCgroupPath(path string) (string, error) {
    29  	if path == "" {
    30  		return "", fmt.Errorf("Cgroup path is empty")
    31  	}
    32  
    33  	cgroupPathDir := filepath.Dir(path)
    34  	cgroupPathName := fmt.Sprintf("%s_%s", CgroupKataPrefix, filepath.Base(path))
    35  	return filepath.Join(cgroupPathDir, cgroupPathName), nil
    36  
    37  }
    38  
    39  // validCgroupPath returns a valid cgroup path.
    40  // see https://github.com/opencontainers/runtime-spec/blob/master/config-linux.md#cgroups-path
    41  func ValidCgroupPath(path string, systemdCgroup bool) (string, error) {
    42  	if IsSystemdCgroup(path) {
    43  		return path, nil
    44  	}
    45  
    46  	if systemdCgroup {
    47  		return "", fmt.Errorf("malformed systemd path '%v': expected to be of form 'slice:prefix:name'", path)
    48  	}
    49  
    50  	// In the case of an absolute path (starting with /), the runtime MUST
    51  	// take the path to be relative to the cgroups mount point.
    52  	if filepath.IsAbs(path) {
    53  		return RenameCgroupPath(filepath.Clean(path))
    54  	}
    55  
    56  	// In the case of a relative path (not starting with /), the runtime MAY
    57  	// interpret the path relative to a runtime-determined location in the cgroups hierarchy.
    58  	// clean up path and return a new path relative to DefaultCgroupPath
    59  	return RenameCgroupPath(filepath.Join(DefaultCgroupPath, filepath.Clean("/"+path)))
    60  }
    61  
    62  func IsSystemdCgroup(cgroupPath string) bool {
    63  	// systemd cgroup path: slice:prefix:name
    64  	re := regexp.MustCompile(`([[:alnum:]]|\.)+:([[:alnum:]]|\.)+:([[:alnum:]]|\.)+`)
    65  	found := re.FindStringIndex(cgroupPath)
    66  
    67  	// if found string is equal to cgroupPath then
    68  	// it's a correct systemd cgroup path.
    69  	return found != nil && cgroupPath[found[0]:found[1]] == cgroupPath
    70  }
    71  
    72  func DeviceToCgroupDevice(device string) (*configs.Device, error) {
    73  	var st unix.Stat_t
    74  	linuxDevice := configs.Device{
    75  		Allow:       true,
    76  		Permissions: "rwm",
    77  		Path:        device,
    78  	}
    79  
    80  	if err := unix.Stat(device, &st); err != nil {
    81  		return nil, err
    82  	}
    83  
    84  	devType := st.Mode & unix.S_IFMT
    85  
    86  	switch devType {
    87  	case unix.S_IFCHR:
    88  		linuxDevice.Type = 'c'
    89  	case unix.S_IFBLK:
    90  		linuxDevice.Type = 'b'
    91  	default:
    92  		return nil, fmt.Errorf("unsupported device type: %v", devType)
    93  	}
    94  
    95  	major := int64(unix.Major(st.Rdev))
    96  	minor := int64(unix.Minor(st.Rdev))
    97  	linuxDevice.Major = major
    98  	linuxDevice.Minor = minor
    99  
   100  	linuxDevice.Gid = st.Gid
   101  	linuxDevice.Uid = st.Uid
   102  	linuxDevice.FileMode = os.FileMode(st.Mode)
   103  
   104  	return &linuxDevice, nil
   105  }
   106  
   107  func DeviceToLinuxDevice(device string) (specs.LinuxDeviceCgroup, error) {
   108  	dev, err := DeviceToCgroupDevice(device)
   109  	if err != nil {
   110  		return specs.LinuxDeviceCgroup{}, err
   111  	}
   112  
   113  	return specs.LinuxDeviceCgroup{
   114  		Allow:  dev.Allow,
   115  		Type:   string(dev.Type),
   116  		Major:  &dev.Major,
   117  		Minor:  &dev.Minor,
   118  		Access: dev.Permissions,
   119  	}, nil
   120  }