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:
Andrea Luzzardi 2015-04-01 16:53:01 -07:00
commit b9be50b578
2 changed files with 72 additions and 6 deletions

View File

@ -215,6 +215,45 @@ func (container *Container) getRootResourcePath(path string) (string, error) {
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 {
en := &execdriver.Network{
Mtu: c.daemon.config.Mtu,
@ -267,14 +306,14 @@ func populateCommand(c *Container, env []string) error {
pid.HostPid = c.hostConfig.PidMode.IsHost()
// Build lists of devices allowed and created within the container.
userSpecifiedDevices := make([]*configs.Device, len(c.hostConfig.Devices))
for i, deviceMapping := range c.hostConfig.Devices {
device, err := devices.DeviceFromPath(deviceMapping.PathOnHost, deviceMapping.CgroupPermissions)
var userSpecifiedDevices []*configs.Device
for _, deviceMapping := range c.hostConfig.Devices {
devs, err := getDevicesFromPath(deviceMapping)
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...)

View File

@ -173,3 +173,30 @@ func TestRunContainerWithCgroupParentAbsPath(t *testing.T) {
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")
}