Skip to content
This repository has been archived by the owner on May 12, 2021. It is now read-only.

Commit

Permalink
pkg/cgroups: implement functions to get information from a host device
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
Julio Montes committed Apr 28, 2020
1 parent 0d3b697 commit b345855
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 0 deletions.
55 changes: 55 additions & 0 deletions virtcontainers/pkg/cgroups/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,13 @@ 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
Expand Down Expand Up @@ -63,3 +68,53 @@ func IsSystemdCgroup(cgroupPath string) bool {
// 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
}
59 changes: 59 additions & 0 deletions virtcontainers/pkg/cgroups/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
package cgroups

import (
"io/ioutil"
"os"
"path/filepath"
"strings"
"testing"
Expand Down Expand Up @@ -102,3 +104,60 @@ func TestValidCgroupPath(t *testing.T) {
}

}

func TestDeviceToCgroupDevice(t *testing.T) {
assert := assert.New(t)

f, err := ioutil.TempFile("", "device")
assert.NoError(err)
f.Close()

// fail: regular file to device
dev, err := DeviceToCgroupDevice(f.Name())
assert.Error(err)
assert.Nil(dev)

// fail: no such file
os.Remove(f.Name())
dev, err = DeviceToCgroupDevice(f.Name())
assert.Error(err)
assert.Nil(dev)

devPath := "/dev/null"
if _, err := os.Stat(devPath); os.IsNotExist(err) {
t.Skipf("no such device: %v", devPath)
return
}
dev, err = DeviceToCgroupDevice(devPath)
assert.NoError(err)
assert.NotNil(dev)
assert.Equal(dev.Type, 'c')
assert.Equal(dev.Path, devPath)
assert.NotZero(dev.Major)
assert.NotZero(dev.Minor)
assert.NotEmpty(dev.Permissions)
assert.NotZero(dev.FileMode)
assert.Zero(dev.Uid)
assert.Zero(dev.Gid)
assert.True(dev.Allow)
}

func TestDeviceToLinuxDevice(t *testing.T) {
assert := assert.New(t)

devPath := "/dev/null"
if _, err := os.Stat(devPath); os.IsNotExist(err) {
t.Skipf("no such device: %v", devPath)
return
}
dev, err := DeviceToLinuxDevice(devPath)
assert.NoError(err)
assert.NotNil(dev)
assert.Equal(dev.Type, "c")
assert.NotNil(dev.Major)
assert.NotZero(*dev.Major)
assert.NotNil(dev.Minor)
assert.NotZero(*dev.Minor)
assert.NotEmpty(dev.Access)
assert.True(dev.Allow)
}

0 comments on commit b345855

Please sign in to comment.