mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #10745 from jfrazelle/device-dir
Mounting a dir of devices like /dev/snd should mount all child devices
This commit is contained in:
commit
b9be50b578
2 changed files with 72 additions and 6 deletions
|
@ -215,6 +215,45 @@ func (container *Container) getRootResourcePath(path string) (string, error) {
|
||||||
return symlink.FollowSymlinkInScope(filepath.Join(container.root, cleanPath), container.root)
|
return symlink.FollowSymlinkInScope(filepath.Join(container.root, cleanPath), container.root)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getDevicesFromPath(deviceMapping runconfig.DeviceMapping) (devs []*configs.Device, err error) {
|
||||||
|
device, err := devices.DeviceFromPath(deviceMapping.PathOnHost, deviceMapping.CgroupPermissions)
|
||||||
|
// if there was no error, return the device
|
||||||
|
if err == nil {
|
||||||
|
device.Path = deviceMapping.PathInContainer
|
||||||
|
return append(devs, device), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the device is not a device node
|
||||||
|
// try to see if it's a directory holding many devices
|
||||||
|
if err == devices.ErrNotADevice {
|
||||||
|
|
||||||
|
// check if it is a directory
|
||||||
|
if src, e := os.Stat(deviceMapping.PathOnHost); e == nil && src.IsDir() {
|
||||||
|
|
||||||
|
// mount the internal devices recursively
|
||||||
|
filepath.Walk(deviceMapping.PathOnHost, func(dpath string, f os.FileInfo, e error) error {
|
||||||
|
childDevice, e := devices.DeviceFromPath(dpath, deviceMapping.CgroupPermissions)
|
||||||
|
if e != nil {
|
||||||
|
// ignore the device
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the device to userSpecified devices
|
||||||
|
childDevice.Path = strings.Replace(dpath, deviceMapping.PathOnHost, deviceMapping.PathInContainer, 1)
|
||||||
|
devs = append(devs, childDevice)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(devs) > 0 {
|
||||||
|
return devs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return devs, fmt.Errorf("error gathering device information while adding custom device %q: %s", deviceMapping.PathOnHost, err)
|
||||||
|
}
|
||||||
|
|
||||||
func populateCommand(c *Container, env []string) error {
|
func populateCommand(c *Container, env []string) error {
|
||||||
en := &execdriver.Network{
|
en := &execdriver.Network{
|
||||||
Mtu: c.daemon.config.Mtu,
|
Mtu: c.daemon.config.Mtu,
|
||||||
|
@ -267,14 +306,14 @@ func populateCommand(c *Container, env []string) error {
|
||||||
pid.HostPid = c.hostConfig.PidMode.IsHost()
|
pid.HostPid = c.hostConfig.PidMode.IsHost()
|
||||||
|
|
||||||
// Build lists of devices allowed and created within the container.
|
// Build lists of devices allowed and created within the container.
|
||||||
userSpecifiedDevices := make([]*configs.Device, len(c.hostConfig.Devices))
|
var userSpecifiedDevices []*configs.Device
|
||||||
for i, deviceMapping := range c.hostConfig.Devices {
|
for _, deviceMapping := range c.hostConfig.Devices {
|
||||||
device, err := devices.DeviceFromPath(deviceMapping.PathOnHost, deviceMapping.CgroupPermissions)
|
devs, err := getDevicesFromPath(deviceMapping)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error gathering device information while adding custom device %q: %s", deviceMapping.PathOnHost, err)
|
return err
|
||||||
}
|
}
|
||||||
device.Path = deviceMapping.PathInContainer
|
|
||||||
userSpecifiedDevices[i] = device
|
userSpecifiedDevices = append(userSpecifiedDevices, devs...)
|
||||||
}
|
}
|
||||||
allowedDevices := append(configs.DefaultAllowedDevices, userSpecifiedDevices...)
|
allowedDevices := append(configs.DefaultAllowedDevices, userSpecifiedDevices...)
|
||||||
|
|
||||||
|
|
|
@ -173,3 +173,30 @@ func TestRunContainerWithCgroupParentAbsPath(t *testing.T) {
|
||||||
|
|
||||||
logDone("run - cgroup parent with absolute cgroup path")
|
logDone("run - cgroup parent with absolute cgroup path")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRunDeviceDirectory(t *testing.T) {
|
||||||
|
defer deleteAllContainers()
|
||||||
|
cmd := exec.Command(dockerBinary, "run", "--device", "/dev/snd:/dev/snd", "busybox", "sh", "-c", "ls /dev/snd/")
|
||||||
|
|
||||||
|
out, _, err := runCommandWithOutput(cmd)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
if actual := strings.Trim(out, "\r\n"); !strings.Contains(out, "timer") {
|
||||||
|
t.Fatalf("expected output /dev/snd/timer, received %s", actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd = exec.Command(dockerBinary, "run", "--device", "/dev/snd:/dev/othersnd", "busybox", "sh", "-c", "ls /dev/othersnd/")
|
||||||
|
|
||||||
|
out, _, err = runCommandWithOutput(cmd)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
if actual := strings.Trim(out, "\r\n"); !strings.Contains(out, "seq") {
|
||||||
|
t.Fatalf("expected output /dev/othersnd/timer, received %s", actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
logDone("run - test --device directory mounts all internal devices")
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue