!7 syscontainer: internal change
Merge pull request !7 from zhangsong234/master
This commit is contained in:
commit
0f47151fa6
@ -96,6 +96,7 @@ func AddDevices(state *configs.HookState, hookConfig *hconfig.ContainerHookConfi
|
|||||||
// re-calc the dest path of device.
|
// re-calc the dest path of device.
|
||||||
resolvDev := calcPathForDevice(state.Root, dev)
|
resolvDev := calcPathForDevice(state.Root, dev)
|
||||||
device, err := libdevice.ParseDevice(resolvDev)
|
device, err := libdevice.ParseDevice(resolvDev)
|
||||||
|
device.Root = state.Root
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorf("[device-hook] Add device (%s), parse device failed: %v", resolvDev, err)
|
logrus.Errorf("[device-hook] Add device (%s), parse device failed: %v", resolvDev, err)
|
||||||
return err
|
return err
|
||||||
|
|||||||
@ -237,6 +237,12 @@ func doAddDevice(pipe *os.File) error {
|
|||||||
if err := MknodDevice(device.Path, device); err != nil {
|
if err := MknodDevice(device.Path, device); err != nil {
|
||||||
return fmt.Errorf("Current OS kernel do not support mknod in container user namespace for root, err: %s", err)
|
return fmt.Errorf("Current OS kernel do not support mknod in container user namespace for root, err: %s", err)
|
||||||
}
|
}
|
||||||
|
if device.Type == "b" {
|
||||||
|
// fdisk: add device soft link to /sys/block
|
||||||
|
if err := AddDeviceToSysBlock(device); err != nil {
|
||||||
|
return fmt.Errorf("Add device to /sys/block failed: %s", device, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,7 +261,12 @@ func doRemoveDevice(pipe *os.File) error {
|
|||||||
if _, err := DeviceFromPath(device.Path, ""); err != nil {
|
if _, err := DeviceFromPath(device.Path, ""); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if device.Type == "b" {
|
||||||
|
// fdisk: remove device symlink in /sys/block
|
||||||
|
if err := RemoveDeviceFromSysBlock(device.Path); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
// need strict check here?
|
// need strict check here?
|
||||||
return os.Remove(device.Path)
|
return os.Remove(device.Path)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,20 +18,26 @@ package libdevice
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/mrunalp/fileutils"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
"isula.org/syscontainer-tools/types"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"isula.org/syscontainer-tools/types"
|
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// ErrNotADevice not a device error
|
// ErrNotADevice not a device error
|
||||||
ErrNotADevice = errors.New("not a device")
|
ErrNotADevice = errors.New("not a device")
|
||||||
|
// MountSourcePath mount source path
|
||||||
|
MountSourcePath = "/mnt/sys/block"
|
||||||
|
// DevBlockPath device block path
|
||||||
|
DevBlockPath = "/sys/dev/block"
|
||||||
|
// MountDestPath mount dest path
|
||||||
|
MountDestPath = "/sys/block"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Testing dependencies
|
// Testing dependencies
|
||||||
@ -243,6 +249,92 @@ func MknodDevice(dest string, node *types.Device) error {
|
|||||||
return syscall.Chown(dest, int(node.UID), int(node.GID))
|
return syscall.Chown(dest, int(node.UID), int(node.GID))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// prepareSysBlockMount bind mount /mnt/sys/block to /sys/block
|
||||||
|
func prepareSysBlockMount(root string) error {
|
||||||
|
if unix.Access(filepath.Join(root, MountDestPath), unix.W_OK) == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err := os.RemoveAll(filepath.Join(root, MountSourcePath)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := fileutils.CopyDirectory(
|
||||||
|
filepath.Join(root, MountDestPath),
|
||||||
|
filepath.Join(root, MountSourcePath)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := syscall.Mount(
|
||||||
|
filepath.Join(root, MountSourcePath),
|
||||||
|
filepath.Join(root, MountDestPath),
|
||||||
|
"",
|
||||||
|
syscall.MS_BIND|syscall.MS_REC, ""); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddDeviceToSysBlock add device to /sys/block in container
|
||||||
|
func AddDeviceToSysBlock(node *types.Device) error {
|
||||||
|
if err := prepareSysBlockMount(node.Root); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
devStr := fmt.Sprintf("%d:%d", node.Major, node.Minor)
|
||||||
|
linkPath := filepath.Join(DevBlockPath, devStr)
|
||||||
|
if _, err := os.Lstat(linkPath); os.IsNotExist(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
realPath, err := os.Readlink(linkPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
hostDeviceName := filepath.Base(realPath)
|
||||||
|
containerDeviceName := filepath.Base(node.Path)
|
||||||
|
if err := os.Chdir(filepath.Join(node.Root, MountSourcePath)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := os.Lstat(containerDeviceName); err == nil {
|
||||||
|
if err := os.Remove(containerDeviceName); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
destPath := strings.Replace(realPath, "../", "", 1)
|
||||||
|
if destPath == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err := os.Symlink(destPath, containerDeviceName); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := os.Chdir(filepath.Join(node.Root, "/dev")); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if hostDeviceName != containerDeviceName {
|
||||||
|
if _, err := os.Stat(hostDeviceName); os.IsNotExist(err) {
|
||||||
|
return os.Symlink(containerDeviceName, hostDeviceName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveDeviceFromSysBlock remove device from /sys/block in container
|
||||||
|
func RemoveDeviceFromSysBlock(path string) error {
|
||||||
|
containerDeviceName := filepath.Base(path)
|
||||||
|
linkPath := filepath.Join(MountDestPath, containerDeviceName)
|
||||||
|
realPath, err := os.Readlink(linkPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
hostDeviceName := filepath.Base(realPath)
|
||||||
|
devPath := filepath.Join("/dev", hostDeviceName)
|
||||||
|
if _, err := os.Lstat(linkPath); err == nil {
|
||||||
|
if err := os.Remove(linkPath); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if hostDeviceName != containerDeviceName {
|
||||||
|
return os.Remove(devPath)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// SetDefaultPath set default path for device
|
// SetDefaultPath set default path for device
|
||||||
func SetDefaultPath(dev *types.Device) {
|
func SetDefaultPath(dev *types.Device) {
|
||||||
if dev.Path == "" {
|
if dev.Path == "" {
|
||||||
|
|||||||
@ -72,6 +72,7 @@ type Device struct {
|
|||||||
GID uint32 // Group ID
|
GID uint32 // Group ID
|
||||||
Allow bool // Used to differ add or remove
|
Allow bool // Used to differ add or remove
|
||||||
Parent string // Parent device name(pathonhost)
|
Parent string // Parent device name(pathonhost)
|
||||||
|
Root string // Rootfs path, prestart hook needed.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Qos is the device Qos structure
|
// Qos is the device Qos structure
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user