mirror of
https://github.com/aljazceru/kata-containers.git
synced 2026-01-04 23:14:19 +01:00
Add functions to convert a host device to a cgroup device or linux device, the first one is used to update the device cgroup and the second one to update the resources in the OCI spec. Signed-off-by: Julio Montes <julio.montes@intel.com> Signed-off-by: Peng Tao <bergwolf@hyper.sh>
121 lines
3.2 KiB
Go
121 lines
3.2 KiB
Go
// Copyright (c) 2020 Intel Corporation
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
|
|
package cgroups
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"regexp"
|
|
|
|
"github.com/opencontainers/runc/libcontainer/configs"
|
|
"github.com/opencontainers/runtime-spec/specs-go"
|
|
"golang.org/x/sys/unix"
|
|
)
|
|
|
|
// prepend a kata specific string to oci cgroup path to
|
|
// form a different cgroup path, thus cAdvisor couldn't
|
|
// find kata containers cgroup path on host to prevent it
|
|
// from grabbing the stats data.
|
|
const CgroupKataPrefix = "kata"
|
|
|
|
// DefaultCgroupPath runtime-determined location in the cgroups hierarchy.
|
|
const DefaultCgroupPath = "/vc"
|
|
|
|
func RenameCgroupPath(path string) (string, error) {
|
|
if path == "" {
|
|
return "", fmt.Errorf("Cgroup path is empty")
|
|
}
|
|
|
|
cgroupPathDir := filepath.Dir(path)
|
|
cgroupPathName := fmt.Sprintf("%s_%s", CgroupKataPrefix, filepath.Base(path))
|
|
return filepath.Join(cgroupPathDir, cgroupPathName), nil
|
|
|
|
}
|
|
|
|
// validCgroupPath returns a valid cgroup path.
|
|
// see https://github.com/opencontainers/runtime-spec/blob/master/config-linux.md#cgroups-path
|
|
func ValidCgroupPath(path string, systemdCgroup bool) (string, error) {
|
|
if IsSystemdCgroup(path) {
|
|
return path, nil
|
|
}
|
|
|
|
if systemdCgroup {
|
|
return "", fmt.Errorf("malformed systemd path '%v': expected to be of form 'slice:prefix:name'", path)
|
|
}
|
|
|
|
// In the case of an absolute path (starting with /), the runtime MUST
|
|
// take the path to be relative to the cgroups mount point.
|
|
if filepath.IsAbs(path) {
|
|
return RenameCgroupPath(filepath.Clean(path))
|
|
}
|
|
|
|
// In the case of a relative path (not starting with /), the runtime MAY
|
|
// interpret the path relative to a runtime-determined location in the cgroups hierarchy.
|
|
// clean up path and return a new path relative to DefaultCgroupPath
|
|
return RenameCgroupPath(filepath.Join(DefaultCgroupPath, filepath.Clean("/"+path)))
|
|
}
|
|
|
|
func IsSystemdCgroup(cgroupPath string) bool {
|
|
// systemd cgroup path: slice:prefix:name
|
|
re := regexp.MustCompile(`([[:alnum:]]|\.)+:([[:alnum:]]|\.)+:([[:alnum:]]|\.)+`)
|
|
found := re.FindStringIndex(cgroupPath)
|
|
|
|
// if found string is equal to cgroupPath then
|
|
// it's a correct systemd cgroup path.
|
|
return found != nil && cgroupPath[found[0]:found[1]] == cgroupPath
|
|
}
|
|
|
|
func DeviceToCgroupDevice(device string) (*configs.Device, error) {
|
|
var st unix.Stat_t
|
|
linuxDevice := configs.Device{
|
|
Allow: true,
|
|
Permissions: "rwm",
|
|
Path: device,
|
|
}
|
|
|
|
if err := unix.Stat(device, &st); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
devType := st.Mode & unix.S_IFMT
|
|
|
|
switch devType {
|
|
case unix.S_IFCHR:
|
|
linuxDevice.Type = 'c'
|
|
case unix.S_IFBLK:
|
|
linuxDevice.Type = 'b'
|
|
default:
|
|
return nil, fmt.Errorf("unsupported device type: %v", devType)
|
|
}
|
|
|
|
major := int64(unix.Major(st.Rdev))
|
|
minor := int64(unix.Minor(st.Rdev))
|
|
linuxDevice.Major = major
|
|
linuxDevice.Minor = minor
|
|
|
|
linuxDevice.Gid = st.Gid
|
|
linuxDevice.Uid = st.Uid
|
|
linuxDevice.FileMode = os.FileMode(st.Mode)
|
|
|
|
return &linuxDevice, nil
|
|
}
|
|
|
|
func DeviceToLinuxDevice(device string) (specs.LinuxDeviceCgroup, error) {
|
|
dev, err := DeviceToCgroupDevice(device)
|
|
if err != nil {
|
|
return specs.LinuxDeviceCgroup{}, err
|
|
}
|
|
|
|
return specs.LinuxDeviceCgroup{
|
|
Allow: dev.Allow,
|
|
Type: string(dev.Type),
|
|
Major: &dev.Major,
|
|
Minor: &dev.Minor,
|
|
Access: dev.Permissions,
|
|
}, nil
|
|
}
|