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 }