mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-06-22 21:49:41 +00:00
virtcontainers: implement function to get the backing file
Implement function the get the backing file from a loop device. The backing file can be used as backend file for a NVDIMM device in the guest Signed-off-by: Julio Montes <julio.montes@intel.com>
This commit is contained in:
parent
0a4e2edcf4
commit
9ff44dba87
@ -12,6 +12,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/go-ini/ini"
|
"github.com/go-ini/ini"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
@ -91,6 +92,8 @@ var SysBusPciDevicesPath = "/sys/bus/pci/devices"
|
|||||||
// SysBusPciSlotsPath is static string of /sys/bus/pci/slots
|
// SysBusPciSlotsPath is static string of /sys/bus/pci/slots
|
||||||
var SysBusPciSlotsPath = "/sys/bus/pci/slots"
|
var SysBusPciSlotsPath = "/sys/bus/pci/slots"
|
||||||
|
|
||||||
|
var getSysDevPath = getSysDevPathImpl
|
||||||
|
|
||||||
// DeviceInfo is an embedded type that contains device data common to all types of devices.
|
// DeviceInfo is an embedded type that contains device data common to all types of devices.
|
||||||
type DeviceInfo struct {
|
type DeviceInfo struct {
|
||||||
// Hostpath is device path on host
|
// Hostpath is device path on host
|
||||||
@ -257,29 +260,14 @@ func GetHostPath(devInfo DeviceInfo, vhostUserStoreEnabled bool, vhostUserStoreP
|
|||||||
return "", fmt.Errorf("Empty path provided for device")
|
return "", fmt.Errorf("Empty path provided for device")
|
||||||
}
|
}
|
||||||
|
|
||||||
var pathComp string
|
|
||||||
|
|
||||||
switch devInfo.DevType {
|
|
||||||
case "c", "u":
|
|
||||||
pathComp = "char"
|
|
||||||
case "b":
|
|
||||||
pathComp = "block"
|
|
||||||
default:
|
|
||||||
// Unsupported device types. Return nil error to ignore devices
|
|
||||||
// that cannot be handled currently.
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter out vhost-user storage devices by device Major numbers.
|
// Filter out vhost-user storage devices by device Major numbers.
|
||||||
if vhostUserStoreEnabled && devInfo.DevType == "b" &&
|
if vhostUserStoreEnabled && devInfo.DevType == "b" &&
|
||||||
(devInfo.Major == VhostUserSCSIMajor || devInfo.Major == VhostUserBlkMajor) {
|
(devInfo.Major == VhostUserSCSIMajor || devInfo.Major == VhostUserBlkMajor) {
|
||||||
return getVhostUserHostPath(devInfo, vhostUserStorePath)
|
return getVhostUserHostPath(devInfo, vhostUserStorePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
format := strconv.FormatInt(devInfo.Major, 10) + ":" + strconv.FormatInt(devInfo.Minor, 10)
|
ueventPath := filepath.Join(getSysDevPath(devInfo), "uevent")
|
||||||
sysDevPath := filepath.Join(SysDevPrefix, pathComp, format, "uevent")
|
if _, err := os.Stat(ueventPath); err != nil {
|
||||||
|
|
||||||
if _, err := os.Stat(sysDevPath); err != nil {
|
|
||||||
// Some devices(eg. /dev/fuse, /dev/cuse) do not always implement sysfs interface under /sys/dev
|
// Some devices(eg. /dev/fuse, /dev/cuse) do not always implement sysfs interface under /sys/dev
|
||||||
// These devices are passed by default by docker.
|
// These devices are passed by default by docker.
|
||||||
//
|
//
|
||||||
@ -293,7 +281,7 @@ func GetHostPath(devInfo DeviceInfo, vhostUserStoreEnabled bool, vhostUserStoreP
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
content, err := ini.Load(sysDevPath)
|
content, err := ini.Load(ueventPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@ -306,6 +294,35 @@ func GetHostPath(devInfo DeviceInfo, vhostUserStoreEnabled bool, vhostUserStoreP
|
|||||||
return filepath.Join("/dev", devName.String()), nil
|
return filepath.Join("/dev", devName.String()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getBackingFile is used to fetch the backing file for the device.
|
||||||
|
func getBackingFile(devInfo DeviceInfo) (string, error) {
|
||||||
|
backingFilePath := filepath.Join(getSysDevPath(devInfo), "loop", "backing_file")
|
||||||
|
data, err := ioutil.ReadFile(backingFilePath)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.TrimSpace(string(data)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getSysDevPathImpl(devInfo DeviceInfo) string {
|
||||||
|
var pathComp string
|
||||||
|
|
||||||
|
switch devInfo.DevType {
|
||||||
|
case "c", "u":
|
||||||
|
pathComp = "char"
|
||||||
|
case "b":
|
||||||
|
pathComp = "block"
|
||||||
|
default:
|
||||||
|
// Unsupported device types. Return nil error to ignore devices
|
||||||
|
// that cannot be handled currently.
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
format := strconv.FormatInt(devInfo.Major, 10) + ":" + strconv.FormatInt(devInfo.Minor, 10)
|
||||||
|
return filepath.Join(SysDevPrefix, pathComp, format)
|
||||||
|
}
|
||||||
|
|
||||||
// getVhostUserHostPath is used to fetch host path for the vhost-user device.
|
// getVhostUserHostPath is used to fetch host path for the vhost-user device.
|
||||||
// For vhost-user block device like vhost-user-blk or vhost-user-scsi, its
|
// For vhost-user block device like vhost-user-blk or vhost-user-scsi, its
|
||||||
// socket should be under directory "<vhostUserStorePath>/block/sockets/";
|
// socket should be under directory "<vhostUserStorePath>/block/sockets/";
|
||||||
|
73
virtcontainers/device/config/config_test.go
Normal file
73
virtcontainers/device/config/config_test.go
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
// Copyright (c) 2020 Intel Corporation
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetBackingFile(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
|
dir, err := ioutil.TempDir("", "backing")
|
||||||
|
assert.NoError(err)
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
|
orgGetSysDevPath := getSysDevPath
|
||||||
|
getSysDevPath = func(info DeviceInfo) string {
|
||||||
|
return dir
|
||||||
|
}
|
||||||
|
defer func() { getSysDevPath = orgGetSysDevPath }()
|
||||||
|
|
||||||
|
info := DeviceInfo{}
|
||||||
|
path, err := getBackingFile(info)
|
||||||
|
assert.Error(err)
|
||||||
|
assert.Empty(path)
|
||||||
|
|
||||||
|
loopDir := filepath.Join(dir, "loop")
|
||||||
|
err = os.Mkdir(loopDir, os.FileMode(0755))
|
||||||
|
assert.NoError(err)
|
||||||
|
|
||||||
|
backingFile := "/fake-img"
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(filepath.Join(loopDir, "backing_file"), []byte(backingFile), os.FileMode(0755))
|
||||||
|
assert.NoError(err)
|
||||||
|
|
||||||
|
path, err = getBackingFile(info)
|
||||||
|
assert.NoError(err)
|
||||||
|
assert.Equal(backingFile, path)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetSysDevPathImpl(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
|
info := DeviceInfo{
|
||||||
|
DevType: "",
|
||||||
|
Major: 127,
|
||||||
|
Minor: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
path := getSysDevPathImpl(info)
|
||||||
|
assert.Empty(path)
|
||||||
|
|
||||||
|
expectedFormat := fmt.Sprintf("%d:%d", info.Major, info.Minor)
|
||||||
|
|
||||||
|
info.DevType = "c"
|
||||||
|
path = getSysDevPathImpl(info)
|
||||||
|
assert.Contains(path, expectedFormat)
|
||||||
|
assert.Contains(path, "char")
|
||||||
|
|
||||||
|
info.DevType = "b"
|
||||||
|
path = getSysDevPathImpl(info)
|
||||||
|
assert.Contains(path, expectedFormat)
|
||||||
|
assert.Contains(path, "block")
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user