diff --git a/cmd/nvidia-container-runtime/main_test.go b/cmd/nvidia-container-runtime/main_test.go index ff507f3b..69cab81f 100644 --- a/cmd/nvidia-container-runtime/main_test.go +++ b/cmd/nvidia-container-runtime/main_test.go @@ -24,6 +24,10 @@ const ( unmodifiedSpecFileSuffix = "test/input/test_spec.json" ) +const ( + runcExecutableName = "runc" +) + type testConfig struct { root string binPath string diff --git a/cmd/nvidia-container-runtime/runtime_factory.go b/cmd/nvidia-container-runtime/runtime_factory.go index a9d7a7ab..9c0a78c3 100644 --- a/cmd/nvidia-container-runtime/runtime_factory.go +++ b/cmd/nvidia-container-runtime/runtime_factory.go @@ -26,15 +26,9 @@ import ( "github.com/sirupsen/logrus" ) -const ( - dockerRuncExecutableName = "docker-runc" - runcExecutableName = "runc" -) - // newNVIDIAContainerRuntime is a factory method that constructs a runtime based on the selected configuration and specified logger func newNVIDIAContainerRuntime(logger *logrus.Logger, cfg *config.Config, argv []string) (oci.Runtime, error) { - lowLevelRuntimeCandidates := []string{dockerRuncExecutableName, runcExecutableName} - lowLevelRuntime, err := oci.NewLowLevelRuntime(logger, lowLevelRuntimeCandidates) + lowLevelRuntime, err := oci.NewLowLevelRuntime(logger, cfg.NVIDIAContainerRuntimeConfig.Runtimes) if err != nil { return nil, fmt.Errorf("error constructing low-level runtime: %v", err) } diff --git a/cmd/nvidia-container-runtime/runtime_factory_test.go b/cmd/nvidia-container-runtime/runtime_factory_test.go index a1bbef26..4133fecb 100644 --- a/cmd/nvidia-container-runtime/runtime_factory_test.go +++ b/cmd/nvidia-container-runtime/runtime_factory_test.go @@ -38,10 +38,19 @@ func TestFactoryMethod(t *testing.T) { expectedError bool }{ { - description: "empty config no error", + description: "empty config raises error", cfg: &config.Config{ NVIDIAContainerRuntimeConfig: config.RuntimeConfig{}, }, + expectedError: true, + }, + { + description: "config with runtime raises no error", + cfg: &config.Config{ + NVIDIAContainerRuntimeConfig: config.RuntimeConfig{ + Runtimes: []string{"runc"}, + }, + }, }, { description: "experimental flag supported", @@ -49,6 +58,7 @@ func TestFactoryMethod(t *testing.T) { NVIDIAContainerRuntimeConfig: config.RuntimeConfig{ Experimental: true, DiscoverMode: "legacy", + Runtimes: []string{"runc"}, }, }, spec: &specs.Spec{ diff --git a/config/config.toml.ubuntu b/config/config.toml.ubuntu index d2a4bc24..6c295ff7 100644 --- a/config/config.toml.ubuntu +++ b/config/config.toml.ubuntu @@ -17,3 +17,10 @@ ldconfig = "@/sbin/ldconfig.real" [nvidia-container-runtime] #debug = "/var/log/nvidia-container-runtime.log" #experimental = false + +# Specify the runtimes to consider. This list is processed in order and the PATH +# searched for matching executables unless the entry is an absolute path. +runtimes = [ + "docker-runc", + "runc", +] diff --git a/internal/config/config_test.go b/internal/config/config_test.go index cc18c04f..a78611ce 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -65,6 +65,7 @@ func TestGetConfig(t *testing.T) { Experimental: false, DiscoverMode: "auto", LogLevel: "info", + Runtimes: []string{"docker-runc", "runc"}, }, NVIDIACTKConfig: CTKConfig{ Path: "nvidia-ctk", @@ -79,6 +80,7 @@ func TestGetConfig(t *testing.T) { "nvidia-container-runtime.experimental = true", "nvidia-container-runtime.discover-mode = \"not-legacy\"", "nvidia-container-runtime.log-level = \"debug\"", + "nvidia-container-runtime.runtimes = [\"/some/runtime\",]", "nvidia-ctk.path = \"/foo/bar/nvidia-ctk\"", }, expectedConfig: &Config{ @@ -90,6 +92,7 @@ func TestGetConfig(t *testing.T) { Experimental: true, DiscoverMode: "not-legacy", LogLevel: "debug", + Runtimes: []string{"/some/runtime"}, }, NVIDIACTKConfig: CTKConfig{ Path: "/foo/bar/nvidia-ctk", @@ -106,6 +109,7 @@ func TestGetConfig(t *testing.T) { "experimental = true", "discover-mode = \"not-legacy\"", "log-level = \"debug\"", + "runtimes = [\"/some/runtime\",]", "[nvidia-ctk]", "path = \"/foo/bar/nvidia-ctk\"", }, @@ -118,6 +122,7 @@ func TestGetConfig(t *testing.T) { Experimental: true, DiscoverMode: "not-legacy", LogLevel: "debug", + Runtimes: []string{"/some/runtime"}, }, NVIDIACTKConfig: CTKConfig{ Path: "/foo/bar/nvidia-ctk", diff --git a/internal/config/runtime.go b/internal/config/runtime.go index 5961378b..b6ecd20a 100644 --- a/internal/config/runtime.go +++ b/internal/config/runtime.go @@ -21,6 +21,11 @@ import ( "github.com/sirupsen/logrus" ) +const ( + dockerRuncExecutableName = "docker-runc" + runcExecutableName = "runc" +) + // RuntimeConfig stores the config options for the NVIDIA Container Runtime type RuntimeConfig struct { DebugFilePath string @@ -28,6 +33,8 @@ type RuntimeConfig struct { DiscoverMode string // LogLevel defines the logging level for the application LogLevel string + // Runtimes defines the candidates for the low-level runtime + Runtimes []string } // getRuntimeConfigFrom reads the nvidia container runtime config from the specified toml Tree. @@ -43,6 +50,15 @@ func getRuntimeConfigFrom(toml *toml.Tree) *RuntimeConfig { cfg.DiscoverMode = toml.GetDefault("nvidia-container-runtime.discover-mode", cfg.DiscoverMode).(string) cfg.LogLevel = toml.GetDefault("nvidia-container-runtime.log-level", cfg.LogLevel).(string) + configRuntimes := toml.Get("nvidia-container-runtime.runtimes") + if configRuntimes != nil { + var runtimes []string + for _, r := range configRuntimes.([]interface{}) { + runtimes = append(runtimes, r.(string)) + } + cfg.Runtimes = runtimes + } + return cfg } @@ -53,6 +69,10 @@ func GetDefaultRuntimeConfig() *RuntimeConfig { Experimental: false, DiscoverMode: "auto", LogLevel: logrus.InfoLevel.String(), + Runtimes: []string{ + dockerRuncExecutableName, + runcExecutableName, + }, } return &c