Skip to content

Commit 606f702

Browse files
zikaeroholljanat
authored andcommitted
Add support for devices
Signed-off-by: Zik Aeroh <[email protected]>
1 parent cd9ed94 commit 606f702

File tree

4 files changed

+95
-0
lines changed

4 files changed

+95
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package flagparser
2+
3+
import (
4+
"strings"
5+
6+
"github.com/moby/swarmkit/v2/api"
7+
"github.com/pkg/errors"
8+
"github.com/spf13/pflag"
9+
)
10+
11+
func parseDevice(flags *pflag.FlagSet, spec *api.ServiceSpec) error {
12+
if flags.Changed("device") {
13+
container := spec.Task.GetContainer()
14+
if container == nil {
15+
return nil
16+
}
17+
18+
devices, err := flags.GetStringSlice("device")
19+
if err != nil {
20+
return err
21+
}
22+
23+
container.Devices = make([]*api.ContainerSpec_DeviceMapping, len(devices))
24+
25+
for i, device := range devices {
26+
parts := strings.Split(device, ":")
27+
if len(parts) < 1 || len(parts) > 3 {
28+
return errors.Wrap(err, "failed to parse device")
29+
}
30+
31+
mapping := &api.ContainerSpec_DeviceMapping{
32+
PathOnHost: parts[0],
33+
PathInContainer: parts[0],
34+
}
35+
36+
if len(parts) > 1 {
37+
mapping.PathInContainer = parts[1]
38+
}
39+
40+
if len(parts) == 3 {
41+
mapping.CgroupPermissions = parts[2]
42+
}
43+
44+
container.Devices[i] = mapping
45+
}
46+
}
47+
48+
return nil
49+
}

swarmd/cmd/swarmctl/service/flagparser/flags.go

+5
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ func AddServiceFlags(flags *pflag.FlagSet) {
5959
flags.StringSlice("volume", nil, "define a volume mount")
6060
flags.StringSlice("tmpfs", nil, "define a tmpfs mount")
6161
flags.StringSlice("npipe", nil, "define a npipe mount")
62+
flags.StringSlice("device", nil, "device options")
6263

6364
flags.String("log-driver", "", "specify a log driver")
6465
flags.StringSlice("log-opt", nil, "log driver options, as key value pairs")
@@ -151,6 +152,10 @@ func Merge(cmd *cobra.Command, spec *api.ServiceSpec, c api.ControlClient) error
151152
return err
152153
}
153154

155+
if err := parseDevice(flags, spec); err != nil {
156+
return err
157+
}
158+
154159
driver, err := common.ParseLogDriverFlags(flags)
155160
if err != nil {
156161
return err

swarmd/dockerexec/container.go

+9
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,15 @@ func (c *containerConfig) resources() enginecontainer.Resources {
467467
}
468468
}
469469

470+
resources.Devices = make([]enginecontainer.DeviceMapping, len(c.spec().Devices))
471+
for i, device := range c.spec().Devices {
472+
resources.Devices[i] = enginecontainer.DeviceMapping{
473+
PathOnHost: device.PathOnHost,
474+
PathInContainer: device.PathInContainer,
475+
CgroupPermissions: device.CgroupPermissions,
476+
}
477+
}
478+
470479
// If no limits are specified let the engine use its defaults.
471480
//
472481
// TODO(aluzzardi): We might want to set some limits anyway otherwise

swarmd/dockerexec/container_test.go

+32
Original file line numberDiff line numberDiff line change
@@ -332,3 +332,35 @@ func TestUlimits(t *testing.T) {
332332
t.Fatalf("expected %v, got %v", expected, actual)
333333
}
334334
}
335+
336+
func TestDevices(t *testing.T) {
337+
c := containerConfig{
338+
task: &api.Task{
339+
Spec: api.TaskSpec{
340+
Runtime: &api.TaskSpec_Container{
341+
Container: &api.ContainerSpec{
342+
Devices: []*api.ContainerSpec_DeviceMapping{
343+
{
344+
PathOnHost: "/dev/dri/card0",
345+
PathInContainer: "/dev/card0",
346+
CgroupPermissions: "ro",
347+
},
348+
},
349+
},
350+
},
351+
},
352+
},
353+
}
354+
355+
expected := []enginecontainer.DeviceMapping{
356+
{
357+
PathOnHost: "/dev/dri/card0",
358+
PathInContainer: "/dev/card0",
359+
CgroupPermissions: "ro",
360+
},
361+
}
362+
actual := c.resources().Devices
363+
if !reflect.DeepEqual(actual, expected) {
364+
t.Fatalf("expected %v, got %v", expected, actual)
365+
}
366+
}

0 commit comments

Comments
 (0)