From 46fc96e33d8ea8612b898eba02373830d0f22c2d Mon Sep 17 00:00:00 2001 From: Johannes Ziemke Date: Thu, 6 Jun 2024 11:36:26 +0200 Subject: [PATCH] Add sound device when engine.sound is set --- pkg/container/docker.go | 29 +++++++++++++++++++++++++++++ pkg/container/getgid.go | 17 +++++++++++++++++ pkg/container/getgid_windows.go | 5 +++++ pkg/container/runner.go | 1 + pkg/diambra/credentials.go | 3 --- pkg/diambra/diambra.go | 2 ++ 6 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 pkg/container/getgid.go create mode 100644 pkg/container/getgid_windows.go diff --git a/pkg/container/docker.go b/pkg/container/docker.go index bd70939..a1ba0f8 100644 --- a/pkg/container/docker.go +++ b/pkg/container/docker.go @@ -20,6 +20,7 @@ import ( "fmt" "io" "os" + "runtime" "strconv" "strings" "time" @@ -112,6 +113,34 @@ func (r *DockerRunner) Start(c *Container) (*ContainerStatus, error) { Target: m.ContainerPath, } } + if c.Sound { + if runtime.GOOS == "windows" { + return nil, fmt.Errorf("sound is not supported on windows") + } + level.Debug(r.Logger).Log("msg", "enabling sound") + hostConfig.Devices = append(hostConfig.Devices, container.DeviceMapping{ + PathOnHost: "/dev/snd", + PathInContainer: "/dev/snd", + CgroupPermissions: "rwm", + }) + + agid, err := getGID("/dev/snd/seq") + if err != nil { + return nil, err + } + hostConfig.GroupAdd = []string{fmt.Sprintf("%d", agid)} + hostConfig.Mounts = append(hostConfig.Mounts, mount.Mount{ + Type: mount.TypeBind, + Source: "/etc/group", + Target: "/etc/group", + ReadOnly: true, + }, mount.Mount{ + Type: mount.TypeBind, + Source: "/usr/share/alsa", + Target: "/usr/share/alsa", + ReadOnly: true, + }) + } level.Debug(r.Logger).Log("msg", "creating container", "config", fmt.Sprintf("%#v", config), "hostConfig", fmt.Sprintf("%#v", hostConfig)) dc, err := r.Client.ContainerCreate(ctx, config, hostConfig, nil, nil, "") if err != nil { diff --git a/pkg/container/getgid.go b/pkg/container/getgid.go new file mode 100644 index 0000000..b1116fe --- /dev/null +++ b/pkg/container/getgid.go @@ -0,0 +1,17 @@ +//go:build !windows + +package container + +import ( + "fmt" + "os" + "syscall" +) + +func getGID(path string) (uint32, error) { + fi, err := os.Stat(path) + if err != nil { + return 0, fmt.Errorf("couldn't stat /dev/snd: %w", err) + } + return fi.Sys().(*syscall.Stat_t).Gid, nil +} diff --git a/pkg/container/getgid_windows.go b/pkg/container/getgid_windows.go new file mode 100644 index 0000000..d32773a --- /dev/null +++ b/pkg/container/getgid_windows.go @@ -0,0 +1,5 @@ +package container + +func getGID(path string) (uint32, error) { + panic("GetGid is not implemented on windows") +} diff --git a/pkg/container/runner.go b/pkg/container/runner.go index 1b7238c..e66cc10 100644 --- a/pkg/container/runner.go +++ b/pkg/container/runner.go @@ -97,6 +97,7 @@ type Container struct { Hostname string WorkingDir string IPCMode string + Sound bool // If true, the entrypoint of the image will be overridden. Only used for // `diambra agent test`. diff --git a/pkg/diambra/credentials.go b/pkg/diambra/credentials.go index 8357d64..659fd58 100644 --- a/pkg/diambra/credentials.go +++ b/pkg/diambra/credentials.go @@ -67,9 +67,6 @@ func EnsureCredentials(logger log.Logger, credPath string) error { if exists { var err error - if err != nil { - return fmt.Errorf("couldn't create client: %w", err) - } user, err := dc.User() if err == nil { level.Info(logger).Log("msg", "logged in", "user", user.Username) diff --git a/pkg/diambra/diambra.go b/pkg/diambra/diambra.go index 8ceb895..c9c18ec 100644 --- a/pkg/diambra/diambra.go +++ b/pkg/diambra/diambra.go @@ -265,6 +265,7 @@ func newEnvContainer(config *EnvConfig, envID, randomSeed int) (*container.Conta container.NewBindMount(config.CredPath, "/tmp/.diambra/credentials"), container.NewBindMount(config.RomsPath, "/opt/diambraArena/roms"), }, + Sound: args.Sound, } c.BindMounts = append(c.BindMounts, config.Mounts...) @@ -276,6 +277,7 @@ func newEnvContainer(config *EnvConfig, envID, randomSeed int) (*container.Conta if config.SeccompProfile != "" { c.SecurityOpt = []string{"seccomp=" + config.SeccompProfile} } + return c, nil }