Skip to content

Commit 7332a6b

Browse files
committed
add default runtime binary path to runtimes field of toolkit config toml
Signed-off-by: Tariq Ibrahim <[email protected]>
1 parent ead4bdf commit 7332a6b

File tree

5 files changed

+154
-12
lines changed

5 files changed

+154
-12
lines changed

internal/config/toml.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,11 +170,26 @@ func (t *Toml) Get(key string) interface{} {
170170
return (*toml.Tree)(t).Get(key)
171171
}
172172

173+
// GetDefault returns the value for the specified key and falls back to the default value if the Get call fails
174+
func (t *Toml) GetDefault(key string, def interface{}) interface{} {
175+
val := (*toml.Tree)(t).Get(key)
176+
if val == nil {
177+
return def
178+
}
179+
return val
180+
}
181+
173182
// Set sets the specified key to the specified value in the TOML config.
174183
func (t *Toml) Set(key string, value interface{}) {
175184
(*toml.Tree)(t).Set(key, value)
176185
}
177186

187+
// WriteTo encode the Tree as Toml and writes it to the writer w.
188+
// Returns the number of bytes written in case of success, or an error if anything happened.
189+
func (t *Toml) WriteTo(w io.Writer) (int64, error) {
190+
return (*toml.Tree)(t).WriteTo(w)
191+
}
192+
178193
// commentDefaults applies the required comments for default values to the Toml.
179194
func (t *Toml) commentDefaults() *Toml {
180195
asToml := (*toml.Tree)(t)

pkg/config/engine/api.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,5 @@ type Interface interface {
2323
Set(string, interface{})
2424
RemoveRuntime(string) error
2525
Save(string) (int64, error)
26+
GetRuntime(name string) (interface{}, error)
2627
}

pkg/config/engine/containerd/config_v1.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,18 @@ func (c *ConfigV1) RemoveRuntime(name string) error {
146146
return nil
147147
}
148148

149+
func (c *ConfigV1) GetRuntime(name string) (interface{}, error) {
150+
if c == nil || c.Tree == nil {
151+
return nil, fmt.Errorf("config is nil")
152+
}
153+
config := *c.Tree
154+
runtimeData, ok := config.GetPath([]string{"plugins", "cri", "containerd", "runtimes", name}).(*toml.Tree)
155+
if !ok {
156+
return nil, fmt.Errorf("invalid toml object")
157+
}
158+
return runtimeData, nil
159+
}
160+
149161
// SetOption sets the specified containerd option.
150162
func (c *ConfigV1) Set(key string, value interface{}) {
151163
config := *c.Tree

pkg/config/engine/docker/docker.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,3 +132,25 @@ func (c Config) Save(path string) (int64, error) {
132132
n, err := config.Raw(path).Write(output)
133133
return int64(n), err
134134
}
135+
136+
// GetRuntime returns the TOML object of the runtime passed as input
137+
func (c *Config) GetRuntime(name string) (interface{}, error) {
138+
if c == nil {
139+
return nil, fmt.Errorf("config is nil")
140+
}
141+
142+
config := *c
143+
144+
var runtimes map[string]interface{}
145+
if _, exists := config["runtimes"]; exists {
146+
runtimes = config["runtimes"].(map[string]interface{})
147+
} else {
148+
return nil, fmt.Errorf("config is nil")
149+
}
150+
151+
if r, ok := runtimes[name]; ok {
152+
return r, nil
153+
} else {
154+
return nil, fmt.Errorf("runtime %s not found", name)
155+
}
156+
}

tools/container/toolkit/toolkit.go

Lines changed: 104 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ import (
3232

3333
"github.com/NVIDIA/nvidia-container-toolkit/internal/config"
3434
"github.com/NVIDIA/nvidia-container-toolkit/internal/system/nvdevices"
35+
pkgconfig "github.com/NVIDIA/nvidia-container-toolkit/pkg/config"
36+
"github.com/NVIDIA/nvidia-container-toolkit/pkg/config/engine/containerd"
37+
"github.com/NVIDIA/nvidia-container-toolkit/pkg/config/engine/crio"
3538
"github.com/NVIDIA/nvidia-container-toolkit/pkg/nvcdi"
3639
transformroot "github.com/NVIDIA/nvidia-container-toolkit/pkg/nvcdi/transform/root"
3740
)
@@ -40,6 +43,8 @@ const (
4043
// DefaultNvidiaDriverRoot specifies the default NVIDIA driver run directory
4144
DefaultNvidiaDriverRoot = "/run/nvidia/driver"
4245

46+
DefaultHostRootMount = "/host"
47+
4348
nvidiaContainerCliSource = "/usr/bin/nvidia-container-cli"
4449
nvidiaContainerRuntimeHookSource = "/usr/bin/nvidia-container-runtime-hook"
4550

@@ -54,6 +59,7 @@ type Options struct {
5459
DevRoot string
5560
DriverRootCtrPath string
5661
DevRootCtrPath string
62+
HostRootMount string
5763

5864
ContainerRuntimeMode string
5965
ContainerRuntimeDebug string
@@ -109,6 +115,13 @@ func Flags(opts *Options) []cli.Flag {
109115
Destination: &opts.DevRootCtrPath,
110116
EnvVars: []string{"DEV_ROOT_CTR_PATH"},
111117
},
118+
&cli.StringFlag{
119+
Name: "host-root",
120+
Usage: "Specify the path to the host root to be used when executing shell commands.",
121+
Value: DefaultHostRootMount,
122+
Destination: &opts.HostRootMount,
123+
EnvVars: []string{"HOST_ROOT_MOUNT"},
124+
},
112125
&cli.StringFlag{
113126
Name: "nvidia-container-runtime.debug",
114127
Aliases: []string{"nvidia-container-runtime-debug"},
@@ -342,7 +355,14 @@ func Install(cli *cli.Context, opts *Options, toolkitRoot string) error {
342355
log.Errorf("Ignoring error: %v", fmt.Errorf("error installing NVIDIA Container CDI Hook CLI: %v", err))
343356
}
344357

345-
err = installToolkitConfig(cli, toolkitConfigPath, nvidiaContainerCliExecutable, nvidiaCTKPath, nvidiaContainerRuntimeHookPath, opts)
358+
var runtimeBinPaths []string
359+
runtimeBinPaths, err = getRuntimeBinaryPaths(opts.HostRootMount)
360+
if err != nil {
361+
log.Warningf("Error retrieving runtime binary paths: %v", err)
362+
}
363+
364+
err = installToolkitConfig(cli, toolkitConfigPath, nvidiaContainerCliExecutable, nvidiaCTKPath,
365+
nvidiaContainerRuntimeHookPath, runtimeBinPaths, opts)
346366
if err != nil && !opts.ignoreErrors {
347367
return fmt.Errorf("error installing NVIDIA container toolkit config: %v", err)
348368
} else if err != nil {
@@ -419,11 +439,15 @@ func installLibrary(libName string, toolkitRoot string) error {
419439
func installToolkitConfig(c *cli.Context, toolkitConfigPath string, nvidiaContainerCliExecutablePath string, nvidiaCTKPath string, nvidaContainerRuntimeHookPath string, opts *Options) error {
420440
log.Infof("Installing NVIDIA container toolkit config '%v'", toolkitConfigPath)
421441

422-
cfg, err := loadConfig(nvidiaContainerToolkitConfigSource)
442+
cfg, err := config.New(
443+
config.WithConfigFile(opts.toolkitConfigSource),
444+
)
423445
if err != nil {
424446
return fmt.Errorf("could not open source config file: %v", err)
425447
}
426448

449+
log.Infof("Printing Default toolkit toml config: %v", cfg)
450+
427451
targetConfig, err := os.Create(toolkitConfigPath)
428452
if err != nil {
429453
return fmt.Errorf("could not create target config file: %v", err)
@@ -436,6 +460,18 @@ func installToolkitConfig(c *cli.Context, toolkitConfigPath string, nvidiaContai
436460
// Use the driver run root as the root:
437461
driverLdconfigPath := config.NormalizeLDConfigPath("@" + filepath.Join(opts.DriverRoot, strings.TrimPrefix(ldconfigPath, "@/")))
438462

463+
var ctkRuntimes []string
464+
defaultCfg, err := cfg.Config()
465+
if err == nil {
466+
defaultCfgRuntimes := defaultCfg.NVIDIAContainerRuntimeConfig.Runtimes
467+
if len(runtimeBinaryPaths) > 0 {
468+
ctkRuntimes = append(ctkRuntimes, runtimeBinaryPaths...)
469+
}
470+
ctkRuntimes = append(ctkRuntimes, defaultCfgRuntimes...)
471+
} else {
472+
log.Warningf("could not get default toolkit config: %v", err)
473+
}
474+
439475
configValues := map[string]interface{}{
440476
// Set the options in the root toml table
441477
"accept-nvidia-visible-devices-envvar-when-unprivileged": opts.acceptNVIDIAVisibleDevicesWhenUnprivileged,
@@ -450,6 +486,11 @@ func installToolkitConfig(c *cli.Context, toolkitConfigPath string, nvidiaContai
450486
"nvidia-container-runtime-hook.path": nvidaContainerRuntimeHookPath,
451487
"nvidia-container-runtime-hook.skip-mode-detection": opts.ContainerRuntimeHookSkipModeDetection,
452488
}
489+
490+
if len(ctkRuntimes) > 0 {
491+
configValues["nvidia-container-runtime.runtimes"] = ctkRuntimes
492+
}
493+
453494
for key, value := range configValues {
454495
cfg.Set(key, value)
455496
}
@@ -503,16 +544,6 @@ func installToolkitConfig(c *cli.Context, toolkitConfigPath string, nvidiaContai
503544
return nil
504545
}
505546

506-
func loadConfig(path string) (*toml.Tree, error) {
507-
_, err := os.Stat(path)
508-
if err == nil {
509-
return toml.LoadFile(path)
510-
} else if os.IsNotExist(err) {
511-
return toml.TreeFromMap(nil)
512-
}
513-
return nil, err
514-
}
515-
516547
// installContainerToolkitCLI installs the nvidia-ctk CLI executable and wrapper.
517548
func installContainerToolkitCLI(toolkitDir string) (string, error) {
518549
e := executable{
@@ -793,3 +824,64 @@ func generateCDISpec(opts *Options, nvidiaCDIHookPath string) error {
793824

794825
return nil
795826
}
827+
828+
// getRuntimeBinaryPaths extracts the full paths of the low-level runtime binaries specified in the container runtime config
829+
func getRuntimeBinaryPaths(hostRoot string) ([]string, error) {
830+
var runtimeBinaryPaths []string
831+
832+
if r, ok := os.LookupEnv("RUNTIME"); ok {
833+
834+
switch r {
835+
case "containerd":
836+
var cliArgs []string
837+
if hostRoot != "" {
838+
cliArgs = append(cliArgs, "chroot", hostRoot)
839+
}
840+
cliArgs = append(cliArgs, "containerd", "config", "dump")
841+
842+
cfg, err := containerd.New(
843+
containerd.WithReference(pkgconfig.FromCLI(cliArgs)),
844+
)
845+
if err != nil {
846+
return nil, fmt.Errorf("unable to load containerd config: %w", err)
847+
}
848+
849+
containerdDefaultRuntime := cfg.DefaultRuntime()
850+
if containerdDefaultRuntime != "" {
851+
runtimeData, err := cfg.GetRuntime(containerdDefaultRuntime)
852+
if err == nil {
853+
runtimeTOML := runtimeData.(*toml.Tree)
854+
if binaryPath, ok := runtimeTOML.GetPath([]string{"options", "BinaryName"}).(string); ok && binaryPath != "" {
855+
runtimeBinaryPaths = append(runtimeBinaryPaths, binaryPath)
856+
}
857+
}
858+
}
859+
860+
case "crio":
861+
var cliArgs []string
862+
if hostRoot != "" {
863+
cliArgs = append(cliArgs, "chroot", hostRoot)
864+
}
865+
cliArgs = append(cliArgs, "crio", "status", "config")
866+
867+
cfg, err := crio.New(
868+
crio.WithReference(pkgconfig.FromCLI(cliArgs)),
869+
)
870+
if err != nil {
871+
return nil, fmt.Errorf("unable to load crio config: %w", err)
872+
}
873+
874+
crioDefaultRuntime := cfg.DefaultRuntime()
875+
if crioDefaultRuntime != "" {
876+
runtimeData, err := cfg.GetRuntime(crioDefaultRuntime)
877+
if err == nil {
878+
runtimeTOML := runtimeData.(*toml.Tree)
879+
if binaryPath, ok := runtimeTOML.GetPath([]string{"runtime_path"}).(string); ok && binaryPath != "" {
880+
runtimeBinaryPaths = append(runtimeBinaryPaths, binaryPath)
881+
}
882+
}
883+
}
884+
}
885+
}
886+
return runtimeBinaryPaths, nil
887+
}

0 commit comments

Comments
 (0)