Skip to content

Commit

Permalink
Add support for devices
Browse files Browse the repository at this point in the history
Signed-off-by: Zik Aeroh <48577114+zikaeroh@users.noreply.github.com>
  • Loading branch information
zikaeroh authored and olljanat committed Nov 23, 2024
1 parent cd9ed94 commit 606f702
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 0 deletions.
49 changes: 49 additions & 0 deletions swarmd/cmd/swarmctl/service/flagparser/device.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package flagparser

import (
"strings"

"github.com/moby/swarmkit/v2/api"
"github.com/pkg/errors"
"github.com/spf13/pflag"
)

func parseDevice(flags *pflag.FlagSet, spec *api.ServiceSpec) error {
if flags.Changed("device") {
container := spec.Task.GetContainer()
if container == nil {
return nil
}

devices, err := flags.GetStringSlice("device")
if err != nil {
return err
}

container.Devices = make([]*api.ContainerSpec_DeviceMapping, len(devices))

for i, device := range devices {
parts := strings.Split(device, ":")
if len(parts) < 1 || len(parts) > 3 {
return errors.Wrap(err, "failed to parse device")
}

mapping := &api.ContainerSpec_DeviceMapping{
PathOnHost: parts[0],
PathInContainer: parts[0],
}

if len(parts) > 1 {
mapping.PathInContainer = parts[1]
}

if len(parts) == 3 {
mapping.CgroupPermissions = parts[2]
}

container.Devices[i] = mapping
}
}

return nil
}
5 changes: 5 additions & 0 deletions swarmd/cmd/swarmctl/service/flagparser/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ func AddServiceFlags(flags *pflag.FlagSet) {
flags.StringSlice("volume", nil, "define a volume mount")
flags.StringSlice("tmpfs", nil, "define a tmpfs mount")
flags.StringSlice("npipe", nil, "define a npipe mount")
flags.StringSlice("device", nil, "device options")

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

if err := parseDevice(flags, spec); err != nil {
return err
}

driver, err := common.ParseLogDriverFlags(flags)
if err != nil {
return err
Expand Down
9 changes: 9 additions & 0 deletions swarmd/dockerexec/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,15 @@ func (c *containerConfig) resources() enginecontainer.Resources {
}
}

resources.Devices = make([]enginecontainer.DeviceMapping, len(c.spec().Devices))
for i, device := range c.spec().Devices {
resources.Devices[i] = enginecontainer.DeviceMapping{
PathOnHost: device.PathOnHost,
PathInContainer: device.PathInContainer,
CgroupPermissions: device.CgroupPermissions,
}
}

// If no limits are specified let the engine use its defaults.
//
// TODO(aluzzardi): We might want to set some limits anyway otherwise
Expand Down
32 changes: 32 additions & 0 deletions swarmd/dockerexec/container_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -332,3 +332,35 @@ func TestUlimits(t *testing.T) {
t.Fatalf("expected %v, got %v", expected, actual)
}
}

func TestDevices(t *testing.T) {
c := containerConfig{
task: &api.Task{
Spec: api.TaskSpec{
Runtime: &api.TaskSpec_Container{
Container: &api.ContainerSpec{
Devices: []*api.ContainerSpec_DeviceMapping{
{
PathOnHost: "/dev/dri/card0",
PathInContainer: "/dev/card0",
CgroupPermissions: "ro",
},
},
},
},
},
},
}

expected := []enginecontainer.DeviceMapping{
{
PathOnHost: "/dev/dri/card0",
PathInContainer: "/dev/card0",
CgroupPermissions: "ro",
},
}
actual := c.resources().Devices
if !reflect.DeepEqual(actual, expected) {
t.Fatalf("expected %v, got %v", expected, actual)
}
}

0 comments on commit 606f702

Please sign in to comment.