diff --git a/src/cmd/initContainer.go b/src/cmd/initContainer.go index b3a7bd983..0a4fa1f47 100644 --- a/src/cmd/initContainer.go +++ b/src/cmd/initContainer.go @@ -28,6 +28,8 @@ import ( "syscall" "time" + "github.com/containers/toolbox/pkg/config" + "github.com/containers/toolbox/pkg/nvidia" "github.com/containers/toolbox/pkg/shell" "github.com/containers/toolbox/pkg/utils" "github.com/fsnotify/fsnotify" @@ -283,6 +285,15 @@ func initContainer(cmd *cobra.Command, args []string) error { return fmt.Errorf("failed to look up user ID %s: %w", uidString, err) } + cfg, err := config.GetRunningContainerConfig( + filepath.Join(initContainerFlags.home, ".config"), + initContainerFlags.uid, + initContainerFlags.gid, + ) + if err != nil { + logrus.Debugf("Failed to load container configuration: %s", err) + } + cdiFileForNvidia, err := getCDIFileForNvidia(targetUser) if err != nil { return err @@ -302,6 +313,10 @@ func initContainer(cmd *cobra.Command, args []string) error { } if cdiSpecForNvidia != nil { + if err := nvidia.PatchConfigForMultilib(cfg); err != nil { + return err + } + if err := applyCDISpecForNvidia(cdiSpecForNvidia); err != nil { return err } @@ -437,9 +452,8 @@ func applyCDISpecForNvidia(spec *specs.Spec) error { continue } - flags := strings.Join(mount.Options, ",") hostPath := filepath.Join(string(filepath.Separator), "run", "host", mount.HostPath) - if err := mountBind(mount.ContainerPath, hostPath, flags); err != nil { + if err := mountExt(mount.ContainerPath, hostPath, "", mount.Options...); err != nil { logrus.Debugf("Applying Container Device Interface for NVIDIA: %s", err) return errors.New("failed to apply mount from Container Device Interface for NVIDIA") } @@ -1001,7 +1015,7 @@ func loadCDISpecFrom(path string) (*specs.Spec, error) { return spec, nil } -func mountBind(containerPath, source, flags string) error { +func mountExt(containerPath, source string, flag string, opts ...string) error { fi, err := os.Stat(source) if err != nil { if os.IsNotExist(err) { @@ -1036,12 +1050,14 @@ func mountBind(containerPath, source, flags string) error { logrus.Debugf("Binding %s to %s", containerPath, source) - args := []string{ - "--rbind", + args := make([]string, 0, 2) + + if flag != "" { + args = append(args, flag) } - if flags != "" { - args = append(args, []string{"-o", flags}...) + if len(opts) > 0 { + args = append(args, []string{"-o", strings.Join(opts, ",")}...) } args = append(args, []string{source, containerPath}...) @@ -1053,6 +1069,10 @@ func mountBind(containerPath, source, flags string) error { return nil } +func mountBind(containerPath, source, flags string) error { + return mountExt(containerPath, source, "--rbind", strings.Split(flags, ",")...) +} + // redirectPath serves for creating symbolic links for crucial system // configuration files to their counterparts on the host's file system. // diff --git a/src/cmd/rm.go b/src/cmd/rm.go index d4d0aac68..2fdb7d3fa 100644 --- a/src/cmd/rm.go +++ b/src/cmd/rm.go @@ -22,6 +22,7 @@ import ( "os" "strings" + "github.com/containers/toolbox/pkg/config" "github.com/containers/toolbox/pkg/podman" "github.com/containers/toolbox/pkg/utils" "github.com/sirupsen/logrus" @@ -83,6 +84,10 @@ func rm(cmd *cobra.Command, args []string) error { fmt.Fprintf(os.Stderr, "Error: %s\n", err) continue } + + if cfg, _ := config.GetContainerConfig(container.Name()); cfg != nil { + cfg.Delete() + } } } else { if len(args) == 0 { @@ -110,6 +115,10 @@ func rm(cmd *cobra.Command, args []string) error { fmt.Fprintf(os.Stderr, "Error: %s\n", err) continue } + + if cfg, _ := config.GetContainerConfig(containerObj.Name()); cfg != nil { + cfg.Delete() + } } } diff --git a/src/cmd/run.go b/src/cmd/run.go index ed421aa68..c43353dbc 100644 --- a/src/cmd/run.go +++ b/src/cmd/run.go @@ -30,6 +30,7 @@ import ( "syscall" "time" + "github.com/containers/toolbox/pkg/config" "github.com/containers/toolbox/pkg/nvidia" "github.com/containers/toolbox/pkg/podman" "github.com/containers/toolbox/pkg/shell" @@ -345,8 +346,13 @@ func runCommand(container string, } logrus.Debugf("Container %s is initialized", container) - environ := append(cdiEnviron, p11KitServerEnviron...) + + cfg, err := config.GetContainerConfig(container) + if cfg != nil { + environ = append(environ, cfg.ListEnv()...) + } + if err := runCommandWithFallbacks(container, preserveFDs, command, diff --git a/src/go.mod b/src/go.mod index 047b6aafd..e05b2e163 100644 --- a/src/go.mod +++ b/src/go.mod @@ -1,26 +1,27 @@ module github.com/containers/toolbox -go 1.22.0 +go 1.25.6 require ( github.com/HarryMichal/go-version v1.0.1 - github.com/NVIDIA/go-nvlib v0.7.2 - github.com/NVIDIA/go-nvml v0.12.4-1 - github.com/NVIDIA/nvidia-container-toolkit v1.17.8 + github.com/NVIDIA/go-nvlib v0.9.1-0.20251202135446-d0f42ba016dd + github.com/NVIDIA/go-nvml v0.13.0-1.0.20260212130905-92cf8c963449 + github.com/NVIDIA/nvidia-container-toolkit v1.19.1 github.com/acobaugh/osrelease v0.1.0 github.com/briandowns/spinner v1.23.2 github.com/docker/go-units v0.5.0 - github.com/fsnotify/fsnotify v1.8.0 + github.com/fsnotify/fsnotify v1.10.1 github.com/go-logfmt/logfmt v0.5.0 - github.com/godbus/dbus/v5 v5.0.6 + github.com/godbus/dbus/v5 v5.2.2 github.com/google/renameio/v2 v2.0.0 - github.com/sirupsen/logrus v1.9.3 - github.com/spf13/cobra v1.6.1 + github.com/sirupsen/logrus v1.9.4 + github.com/spf13/cobra v1.10.2 github.com/spf13/viper v1.20.1 - github.com/stretchr/testify v1.10.0 - golang.org/x/sys v0.29.0 - tags.cncf.io/container-device-interface v0.8.1 - tags.cncf.io/container-device-interface/specs-go v0.8.0 + github.com/stretchr/testify v1.11.1 + go.podman.io/podman/v6 v6.0.2 + golang.org/x/sys v0.46.0 + tags.cncf.io/container-device-interface v1.1.0 + tags.cncf.io/container-device-interface/specs-go v1.1.0 ) require ( @@ -28,11 +29,14 @@ require ( github.com/fatih/color v1.14.1 // indirect github.com/go-viper/mapstructure/v2 v2.4.0 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/inconshreveable/mousetrap v1.0.1 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.17 // indirect - github.com/opencontainers/runtime-spec v1.2.1 // indirect - github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626 // indirect + github.com/moby/sys/capability v0.4.0 // indirect + github.com/opencontainers/cgroups v0.0.6 // indirect + github.com/opencontainers/runc v1.4.2 // indirect + github.com/opencontainers/runtime-spec v1.3.0 // indirect + github.com/opencontainers/runtime-tools v0.9.1-0.20260316125833-8a4db579f5c8 // indirect github.com/pelletier/go-toml/v2 v2.2.3 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect @@ -40,15 +44,14 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.12.0 // indirect github.com/spf13/cast v1.7.1 // indirect - github.com/spf13/pflag v1.0.6 // indirect + github.com/spf13/pflag v1.0.10 // indirect github.com/subosito/gotenv v1.6.0 // indirect - github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect - golang.org/x/mod v0.20.0 // indirect - golang.org/x/term v0.1.0 // indirect - golang.org/x/text v0.21.0 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect + go.yaml.in/yaml/v2 v2.4.3 // indirect + golang.org/x/mod v0.36.0 // indirect + golang.org/x/term v0.44.0 // indirect + golang.org/x/text v0.38.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - sigs.k8s.io/yaml v1.3.0 // indirect + sigs.k8s.io/yaml v1.6.0 // indirect ) diff --git a/src/go.sum b/src/go.sum index 09780bd92..d01068547 100644 --- a/src/go.sum +++ b/src/go.sum @@ -1,18 +1,22 @@ +cyphar.com/go-pathrs v0.2.4 h1:iD/mge36swa1UFKdINkr1Frkpp6wZsy3YYEildj9cLY= +cyphar.com/go-pathrs v0.2.4/go.mod h1:y8f1EMG7r+hCuFf/rXsKqMJrJAUoADZGNh5/vZPKcGc= github.com/HarryMichal/go-version v1.0.1 h1:Vgk1dPyHckkoUu0AED900+yO43+uwDuiNPsdpYe63KE= github.com/HarryMichal/go-version v1.0.1/go.mod h1:UNoJ+GvCcmwu0F9Mu1u5y56lP5rWksgkiwLlGx3r+Pk= -github.com/NVIDIA/go-nvlib v0.7.2 h1:7sy/NVUa4sM9FLKwH6CjBfHSWrJUmv8emVyxLTzjfOA= -github.com/NVIDIA/go-nvlib v0.7.2/go.mod h1:2Kh2kYSP5IJ8EKf0/SYDzHiQKb9EJkwOf2LQzu6pXzY= -github.com/NVIDIA/go-nvml v0.12.4-1 h1:WKUvqshhWSNTfm47ETRhv0A0zJyr1ncCuHiXwoTrBEc= -github.com/NVIDIA/go-nvml v0.12.4-1/go.mod h1:8Llmj+1Rr+9VGGwZuRer5N/aCjxGuR5nPb/9ebBiIEQ= -github.com/NVIDIA/nvidia-container-toolkit v1.17.8 h1:ndE23TKvQBicsZT88mzZudygn6JNOe6+UsIgqk6gGvw= -github.com/NVIDIA/nvidia-container-toolkit v1.17.8/go.mod h1:khOgMW80+g8eX/1zPlO4demLShHht9I0YEm8ngcPgwk= +github.com/NVIDIA/go-nvlib v0.9.1-0.20251202135446-d0f42ba016dd h1:MC1w/VYuo9Zt0se4SSx9BVid4a46ai+voN3knRvVWjE= +github.com/NVIDIA/go-nvlib v0.9.1-0.20251202135446-d0f42ba016dd/go.mod h1:7mzx9FSdO9fXWP9NKuZmWkCwhkEcSWQFe2tmFwtLb9c= +github.com/NVIDIA/go-nvml v0.13.0-1.0.20260212130905-92cf8c963449 h1:UrArFAaPhj9av2yzEN35CvzWw68BeQjp2MaQFUIoJSU= +github.com/NVIDIA/go-nvml v0.13.0-1.0.20260212130905-92cf8c963449/go.mod h1:ahi2psRYoa+wYUBIrZPRO+wJs9lcvMhxSSkjjvsJJNQ= +github.com/NVIDIA/nvidia-container-toolkit v1.19.1 h1:1sV4ddFrBccqL9Lbzcdu50w2j5FhyNJpN5hXTfCsjps= +github.com/NVIDIA/nvidia-container-toolkit v1.19.1/go.mod h1:yGsZ4s2lMjfE4r8/DMUPVpaFhRGkWvo2H++/Dy84nVc= github.com/acobaugh/osrelease v0.1.0 h1:Yb59HQDGGNhCj4suHaFQQfBps5wyoKLSSX/J/+UifRE= github.com/acobaugh/osrelease v0.1.0/go.mod h1:4bFEs0MtgHNHBrmHCt67gNisnabCRAlzdVasCEGHTWY= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/briandowns/spinner v1.23.2 h1:Zc6ecUnI+YzLmJniCfDNaMbW0Wid1d5+qcTq4L2FW8w= github.com/briandowns/spinner v1.23.2/go.mod h1:LaZeM4wm2Ywy6vO571mvhQNRcWfRUnXOs0RcKV0wYKM= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE= +github.com/cyphar/filepath-securejoin v0.6.1/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -23,28 +27,26 @@ github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= -github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= -github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/fsnotify/fsnotify v1.10.1 h1:b0/UzAf9yR5rhf3RPm9gf3ehBPpf0oZKIjtpKrx59Ho= +github.com/fsnotify/fsnotify v1.10.1/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo= github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= -github.com/godbus/dbus/v5 v5.0.6 h1:mkgN1ofwASrYnJ5W6U/BxG15eXXXjirgZc7CLqkcaro= -github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ= +github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg= github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= -github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -54,15 +56,18 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mndrix/tap-go v0.0.0-20171203230836-629fa407e90b/go.mod h1:pzzDgJWZ34fGzaAZGFW22KVZDfyrYW+QABMrWnJBnSs= -github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= -github.com/opencontainers/runtime-spec v1.0.3-0.20220825212826-86290f6a00fb/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.2.1 h1:S4k4ryNgEpxW1dzyqffOmhI1BHYcjzU8lpJfSlR0xww= -github.com/opencontainers/runtime-spec v1.2.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626 h1:DmNGcqH3WDbV5k8OJ+esPWbqUOX5rMLR2PMvziDMJi0= -github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626/go.mod h1:BRHJJd0E+cx42OybVYSgUvZmU0B8P9gZuRXlZUP7TKI= -github.com/opencontainers/selinux v1.9.1 h1:b4VPEF3O5JLZgdTDBmGepaaIbAo0GqoF6EBRq5f/g3Y= -github.com/opencontainers/selinux v1.9.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= +github.com/moby/sys/capability v0.4.0 h1:4D4mI6KlNtWMCM1Z/K0i7RV1FkX+DBDHKVJpCndZoHk= +github.com/moby/sys/capability v0.4.0/go.mod h1:4g9IK291rVkms3LKCDOoYlnV8xKwoDTpIrNEE35Wq0I= +github.com/opencontainers/cgroups v0.0.6 h1:tfZFWTIIGaUUFImTyuTg+Mr5x8XRiSdZESgEBW7UxuI= +github.com/opencontainers/cgroups v0.0.6/go.mod h1:oWVzJsKK0gG9SCRBfTpnn16WcGEqDI8PAcpMGbqWxcs= +github.com/opencontainers/runc v1.4.2 h1:/AEjjXuVH9lTRl9ZyUFQj7oWBM7Xv00qFV6Vx9q5N3o= +github.com/opencontainers/runc v1.4.2/go.mod h1:ufk5PTTsy5pnGBAvTh50e+eqGk01pYH2YcVxh557Qlk= +github.com/opencontainers/runtime-spec v1.3.0 h1:YZupQUdctfhpZy3TM39nN9Ika5CBWT5diQ8ibYCRkxg= +github.com/opencontainers/runtime-spec v1.3.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-tools v0.9.1-0.20260316125833-8a4db579f5c8 h1:2NAWFjN0PmdIe3XojVL9wf3lJ1//VqAgc7MOSYHQslE= +github.com/opencontainers/runtime-tools v0.9.1-0.20260316125833-8a4db579f5c8/go.mod h1:DKDEfzxvRkoQ6n9TGhxQgg2IM1lY4aM0eaQP4e3oElw= +github.com/opencontainers/selinux v1.15.1 h1:ERxeh5caJvCzNAKdI8WQbJmB1LDTn4BuaAg8wihLBpA= +github.com/opencontainers/selinux v1.15.1/go.mod h1:LenyElirjUHszfxrjuFqC85HIeXZKumHcKMQtnaDlQQ= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -73,67 +78,60 @@ github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo= github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= +github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4= github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= -github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= -github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= -github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= +github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= +github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= +github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= -github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI= -github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/urfave/cli v1.19.1/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +go.podman.io/podman/v6 v6.0.2 h1:T7p1IJytTb1JbWCMrNnt17O4+d2qMk8Wyw7Pezihr44= +go.podman.io/podman/v6 v6.0.2/go.mod h1:+WXAeC8vD6yCu7loCL20vDY4A3gWb6FN8vINPEQSo2Y= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= -golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= -golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0= +go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +golang.org/x/mod v0.36.0 h1:JJjpVx6myfUsUdAzZuOSTTmRE0PfZeNWzzvKrP7amb4= +golang.org/x/mod v0.36.0/go.mod h1:moc6ELqsWcOw5Ef3xVprK5ul/MvtVvkIXLziUOICjUQ= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= -golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw= -golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw= +golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/term v0.44.0 h1:0rLvDRCtNj0gZkyIXhCyOb2OAzEhLVqc4B+hrsBhrmc= +golang.org/x/term v0.44.0/go.mod h1:7ze4MdzUzLXpSAoFP1H0bOI9aXDqveSvatT5vKcFh2Y= +golang.org/x/text v0.38.0 h1:sXmwo9DwP3OK9EZ7PqAdaooSGozfl/3a6/xJcbzPRhE= +golang.org/x/text v0.38.0/go.mod h1:YXZt3QhHUKYT53r2lLKFIVi6Ao1jdzrTR/KQ09qyxF4= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= -tags.cncf.io/container-device-interface v0.8.1 h1:c0jN4Mt6781jD67NdPajmZlD1qrqQyov/Xfoab37lj0= -tags.cncf.io/container-device-interface v0.8.1/go.mod h1:Apb7N4VdILW0EVdEMRYXIDVRZfNJZ+kmEUss2kRRQ6Y= -tags.cncf.io/container-device-interface/specs-go v0.8.0 h1:QYGFzGxvYK/ZLMrjhvY0RjpUavIn4KcmRmVP/JjdBTA= -tags.cncf.io/container-device-interface/specs-go v0.8.0/go.mod h1:BhJIkjjPh4qpys+qm4DAYtUyryaTDg9zris+AczXyws= +sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= +sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= +tags.cncf.io/container-device-interface v1.1.0 h1:RnxNhxF1JOu6CJUVpetTYvrXHdxw9j9jFYgZpI+anSY= +tags.cncf.io/container-device-interface v1.1.0/go.mod h1:76Oj0Yqp9FwTx/pySDc8Bxjpg+VqXfDb50cKAXVJ34Q= +tags.cncf.io/container-device-interface/specs-go v1.1.0 h1:QRZVeAceQM+zTZe12eyfuJuuzp524EKYwhmvLd+h+yQ= +tags.cncf.io/container-device-interface/specs-go v1.1.0/go.mod h1:u86hoFWqnh3hWz3esofRFKbI261bUlvUfLKGrDhJkgQ= diff --git a/src/meson.build b/src/meson.build index 6706fe28c..4b0b6baa8 100644 --- a/src/meson.build +++ b/src/meson.build @@ -20,6 +20,7 @@ sources = files( 'cmd/root_test.go', 'cmd/run.go', 'cmd/utils.go', + 'pkg/config/config.go', 'pkg/nvidia/nvidia.go', 'pkg/podman/container.go', 'pkg/podman/errors.go', diff --git a/src/pkg/config/config.go b/src/pkg/config/config.go new file mode 100644 index 000000000..13e0a0ea5 --- /dev/null +++ b/src/pkg/config/config.go @@ -0,0 +1,163 @@ +/* + * Copyright © 2019 – 2026 Red Hat Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Package config implements helper functions to manage toolbx containers persistent config +// parameters, such as injected environment variables +package config + +import ( + "encoding/json" + "fmt" + "os" + "path/filepath" + "slices" + "strings" + + "github.com/sirupsen/logrus" + podenv "go.podman.io/podman/v6/pkg/env" +) + +type Container interface { + Env() map[string]string // Get container environment map + ListEnv() []string // Get serialized container environment + Save() error // Save updated container config + Delete() error // Delete config file +} + +type containerConfig struct { + Environment map[string]string `json:"env,omitempty"` // Environment var map + + fpath string // config location + gid int + uid int +} + +func (cfg *containerConfig) Env() map[string]string { + return cfg.Environment +} + +func (cfg *containerConfig) ListEnv() []string { + var str strings.Builder + return slices.Collect(func(yield func(string) bool) { + for k, v := range cfg.Environment { + str.Grow(len(v) + 1) // key=val + + str.WriteString(k) + str.WriteRune('=') + str.WriteString(v) + + if !yield(str.String()) { + return + } + str.Reset() + } + }) +} + +func (cfg *containerConfig) Save() error { + f, err := os.OpenFile(cfg.fpath, os.O_CREATE|os.O_RDWR, 0644) + if err != nil { + logrus.Debugf("Save container config: error opening config file %s: %s", cfg.fpath, err) + return fmt.Errorf("error opening file config file %s: %w", cfg.fpath, err) + } + defer f.Close() + if cfg.uid != -1 && cfg.gid != -1 { + f.Chown(cfg.uid, cfg.gid) + } + + enc := json.NewEncoder(f) + // 4-space pretty indentation + enc.SetIndent("", " ") + + return enc.Encode(cfg) +} + +func (cfg *containerConfig) Delete() (err error) { + err = os.Remove(cfg.fpath) + if err != nil { + logrus.Debugf("Delete container config: error deleting config %s: %s", cfg.fpath, err) + } + + return +} + +func GetContainerConfig(name string) (Container, error) { + return loadContainerConfig(name, "", -1, -1) +} + +func GetRunningContainerConfig(configDir string, uid, gid int) (Container, error) { + env, err := parseContainerEnv() + if err != nil { + logrus.Debugf("Load container config: failed to load running container env: %s", err) + return nil, fmt.Errorf("failed to parse running container env: %w", err) + } + return loadContainerConfig(env.Name, configDir, uid, gid) +} + +func loadContainerConfig(name, configDir string, uid, gid int) (Container, error) { + if configDir == "" { + dir, err := os.UserConfigDir() + if err != nil { + logrus.Debugf("Load container config: failed to get the user config directory: %s", err) + return nil, fmt.Errorf("failed to get the user config directory: %w", err) + } + configDir = dir + } + + fpath := filepath.Join(configDir, "toolbox", name+"-config.json") + cfg := containerConfig{fpath: fpath, uid: uid, gid: uid, Environment: make(map[string]string)} + + f, err := os.OpenFile(fpath, os.O_RDWR, 0644) + if os.IsNotExist(err) { + // Empty config in case file not exist (older container without config) + logrus.Debugf("Load container config: container config file %s not found", fpath) + return &cfg, nil + } else if err != nil { + logrus.Debugf("Load container config: failed to get the user config directory: %s", err) + return nil, fmt.Errorf("error opening config %s: %w", cfg.fpath, err) + } + defer f.Close() + + err = json.NewDecoder(f).Decode(&cfg) + if err != nil { + logrus.Debugf("Load container config: failed decoding container config %s: %s", fpath, err) + return nil, fmt.Errorf("error decoding config %s: %w", fpath, err) + } + + return &cfg, nil +} + +type podmanEnv struct { + ImageID string + Image string + Name string + ID string +} + +// parseContainerEnv parses podman's .containerenv file information +func parseContainerEnv() (*podmanEnv, error) { + data, err := podenv.ParseFile("/run/.containerenv") + if err != nil { + return nil, err + } + + return &podmanEnv{ + ImageID: strings.Trim(data["imageid"], "\""), + Image: strings.Trim(data["image"], "\""), + Name: strings.Trim(data["name"], "\""), + ID: strings.Trim(data["id"], "\""), + }, nil +} diff --git a/src/pkg/nvidia/nvidia.go b/src/pkg/nvidia/nvidia.go index 4fb9f0a82..2e7685514 100644 --- a/src/pkg/nvidia/nvidia.go +++ b/src/pkg/nvidia/nvidia.go @@ -19,11 +19,16 @@ package nvidia import ( "errors" "io" + "math/bits" + "path/filepath" + "strings" "github.com/NVIDIA/go-nvlib/pkg/nvlib/info" "github.com/NVIDIA/go-nvml/pkg/nvml" "github.com/NVIDIA/nvidia-container-toolkit/pkg/nvcdi" nvspec "github.com/NVIDIA/nvidia-container-toolkit/pkg/nvcdi/spec" + "github.com/containers/toolbox/pkg/config" + "github.com/containers/toolbox/pkg/utils" "github.com/sirupsen/logrus" "tags.cncf.io/container-device-interface/specs-go" ) @@ -89,7 +94,7 @@ func GenerateCDISpec() (*specs.Spec, error) { reason) } - isTegra, reason := info.IsTegraSystem() + isTegra, reason := info.HasTegraFiles() if !isTegra { logrus.Debugf("Generating Container Device Interface for NVIDIA: not a Tegra system: %s", reason) } @@ -99,7 +104,7 @@ func GenerateCDISpec() (*specs.Spec, error) { return nil, ErrPlatformUnsupported } - cdi, err := nvcdi.New(nvcdi.WithDisabledHook(nvcdi.HookEnableCudaCompat), + cdi, err := nvcdi.New(nvcdi.WithDisabledHooks(nvcdi.HookEnableCudaCompat), nvcdi.WithInfoLib(info), nvcdi.WithLogger(logger), nvcdi.WithNvmlLib(nvmLib)) @@ -126,6 +131,58 @@ func GenerateCDISpec() (*specs.Spec, error) { return specRaw, nil } +func PatchConfigForMultilib(config config.Container) error { + if config == nil { + return nil + } + + libpath, err := utils.GetMultilibDir() + if err != nil { + logrus.Debugf("Patching nvidia config multilib: error determining multilib container: %s", err) + return err + } + + if libpath == "" { + logrus.Debug("Patching nvidia config multilib: container is not a multilib env") + return nil + } + + env := config.Env() + // CDI will deposit gbm backends in /usr/lib64/gbm. Multilib builds expect the backends + // in /usr/lib/x86_64-linux-gnu/gbm or /usr/lib/aarch64-linux-gnu/gbm. + // Patching both locations with the environment variable GBM_BACKENDS_PATH + env["GBM_BACKENDS_PATH"] = getGBMBackendPaths(libpath) + + // Commit changes + return config.Save() +} + +func getGBMBackendPaths(libpath string) string { + var ( + strVar strings.Builder + hostLibpath string + ) + switch bits.UintSize { + case 64: + hostLibpath = "/usr/lib64" + default: + hostLibpath = "/usr/lib" + } + + // strVar.WriteString("GBM_BACKENDS_PATH=") + strVar.WriteString( + strings.Join( + []string{ + filepath.Join(hostLibpath, "gbm"), + filepath.Join(libpath, "gbm"), + }, + string(filepath.ListSeparator), + ), + ) + + return strVar.String() +} + func SetLogLevel(level logrus.Level) { logLevel = level } diff --git a/src/pkg/utils/utils.go b/src/pkg/utils/utils.go index 790f08423..88ba13cf2 100644 --- a/src/pkg/utils/utils.go +++ b/src/pkg/utils/utils.go @@ -20,10 +20,12 @@ import ( "errors" "fmt" "os" + "os/exec" "os/user" "path" "path/filepath" "regexp" + "slices" "strconv" "strings" "syscall" @@ -892,3 +894,47 @@ func ResolveContainerAndImageNames(container, distroCLI, imageCLI, releaseCLI st return container, image, release, nil } + +func GetMultilibDir() (string, error) { + var ( + libPaths []string = []string{"/lib", "/lib64", "/usr/lib", "/usr/lib64"} + path string + ld string + ) + logrus.Debug("Retrieving platform multilib dir") + + cmd := exec.Command("ldd", "/bin/sh") + stdout, err := cmd.CombinedOutput() + if err != nil { + return "", fmt.Errorf("Error determining elf interpreter: %w", err) + } + for line := range strings.Lines(string(stdout)) { + clean := strings.TrimSpace(line) + if strings.Contains(clean, "ld-linux") { + ld = strings.Split(clean, " ")[0] + break + } + } + logrus.Debugf("Determined %s as the elf interpreter", ld) + + cmd = exec.Command(ld, "--help") + stdout, _ = cmd.CombinedOutput() + + for line := range strings.Lines(string(stdout)) { + clean := strings.TrimSpace(line) + if strings.Contains(clean, "(system search path)") { + match := strings.Split(clean, " ")[0] + if len(match) > len(path) { + path = match + } + } + } + logrus.Debugf("Found longest system search path: %s", path) + + if slices.Contains(libPaths, path) { + logrus.Debugf("System is not a multilib config") + return "", nil + } + + return path, nil +}