Skip to content

Commit dee62ca

Browse files
committed
Move toolkit config file update to separate file
This change moves the generating of a toolkit config to a separate file. Signed-off-by: Evan Lezar <[email protected]>
1 parent c409670 commit dee62ca

File tree

2 files changed

+148
-121
lines changed

2 files changed

+148
-121
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
/**
2+
# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3+
# SPDX-License-Identifier: Apache-2.0
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
**/
17+
18+
package toolkit
19+
20+
import (
21+
"fmt"
22+
"os"
23+
"path/filepath"
24+
"strings"
25+
26+
"github.com/urfave/cli/v2"
27+
28+
"github.com/NVIDIA/nvidia-container-toolkit/internal/config"
29+
)
30+
31+
const (
32+
configFilename = "config.toml"
33+
)
34+
35+
// installToolkitConfig installs the config file for the NVIDIA container toolkit ensuring
36+
// that the settings are updated to match the desired install and nvidia driver directories.
37+
func (t *Installer) installToolkitConfig(c *cli.Context, opts *Options) error {
38+
toolkitConfigDir := filepath.Join(t.toolkitRoot, ".config", "nvidia-container-runtime")
39+
toolkitConfigPath := filepath.Join(toolkitConfigDir, configFilename)
40+
41+
t.logger.Infof("Installing NVIDIA container toolkit config '%v'", toolkitConfigPath)
42+
43+
err := t.createDirectories(toolkitConfigDir)
44+
if err != nil && !opts.ignoreErrors {
45+
return fmt.Errorf("could not create required directories: %v", err)
46+
} else if err != nil {
47+
t.logger.Errorf("Ignoring error: %v", fmt.Errorf("could not create required directories: %v", err))
48+
}
49+
nvidiaContainerCliExecutablePath := filepath.Join(t.toolkitRoot, "nvidia-container-cli")
50+
nvidiaCTKPath := filepath.Join(t.toolkitRoot, "nvidia-ctk")
51+
nvidiaContainerRuntimeHookPath := filepath.Join(t.toolkitRoot, "nvidia-container-runtime-hook")
52+
53+
cfg, err := config.New()
54+
if err != nil {
55+
return fmt.Errorf("could not open source config file: %v", err)
56+
}
57+
58+
targetConfig, err := os.Create(toolkitConfigPath)
59+
if err != nil {
60+
return fmt.Errorf("could not create target config file: %v", err)
61+
}
62+
defer targetConfig.Close()
63+
64+
// Read the ldconfig path from the config as this may differ per platform
65+
// On ubuntu-based systems this ends in `.real`
66+
ldconfigPath := fmt.Sprintf("%s", cfg.GetDefault("nvidia-container-cli.ldconfig", "/sbin/ldconfig"))
67+
// Use the driver run root as the root:
68+
driverLdconfigPath := config.NormalizeLDConfigPath("@" + filepath.Join(opts.DriverRoot, strings.TrimPrefix(ldconfigPath, "@/")))
69+
70+
configValues := map[string]interface{}{
71+
// Set the options in the root toml table
72+
"accept-nvidia-visible-devices-envvar-when-unprivileged": opts.acceptNVIDIAVisibleDevicesWhenUnprivileged,
73+
"accept-nvidia-visible-devices-as-volume-mounts": opts.acceptNVIDIAVisibleDevicesAsVolumeMounts,
74+
// Set the nvidia-container-cli options
75+
"nvidia-container-cli.root": opts.DriverRoot,
76+
"nvidia-container-cli.path": nvidiaContainerCliExecutablePath,
77+
"nvidia-container-cli.ldconfig": driverLdconfigPath,
78+
// Set nvidia-ctk options
79+
"nvidia-ctk.path": nvidiaCTKPath,
80+
// Set the nvidia-container-runtime-hook options
81+
"nvidia-container-runtime-hook.path": nvidiaContainerRuntimeHookPath,
82+
"nvidia-container-runtime-hook.skip-mode-detection": opts.ContainerRuntimeHookSkipModeDetection,
83+
}
84+
85+
toolkitRuntimeList := opts.ContainerRuntimeRuntimes.Value()
86+
if len(toolkitRuntimeList) > 0 {
87+
configValues["nvidia-container-runtime.runtimes"] = toolkitRuntimeList
88+
}
89+
90+
for _, optInFeature := range opts.optInFeatures.Value() {
91+
configValues["features."+optInFeature] = true
92+
}
93+
94+
for key, value := range configValues {
95+
cfg.Set(key, value)
96+
}
97+
98+
// Set the optional config options
99+
optionalConfigValues := map[string]interface{}{
100+
"nvidia-container-runtime.debug": opts.ContainerRuntimeDebug,
101+
"nvidia-container-runtime.log-level": opts.ContainerRuntimeLogLevel,
102+
"nvidia-container-runtime.mode": opts.ContainerRuntimeMode,
103+
"nvidia-container-runtime.modes.cdi.annotation-prefixes": opts.ContainerRuntimeModesCDIAnnotationPrefixes,
104+
"nvidia-container-runtime.modes.cdi.default-kind": opts.ContainerRuntimeModesCdiDefaultKind,
105+
"nvidia-container-runtime.runtimes": opts.ContainerRuntimeRuntimes,
106+
"nvidia-container-cli.debug": opts.ContainerCLIDebug,
107+
}
108+
109+
for key, value := range optionalConfigValues {
110+
if !c.IsSet(key) {
111+
t.logger.Infof("Skipping unset option: %v", key)
112+
continue
113+
}
114+
if value == nil {
115+
t.logger.Infof("Skipping option with nil value: %v", key)
116+
continue
117+
}
118+
119+
switch v := value.(type) {
120+
case string:
121+
if v == "" {
122+
continue
123+
}
124+
case cli.StringSlice:
125+
if len(v.Value()) == 0 {
126+
continue
127+
}
128+
value = v.Value()
129+
default:
130+
t.logger.Warningf("Unexpected type for option %v=%v: %T", key, value, v)
131+
}
132+
133+
cfg.Set(key, value)
134+
}
135+
136+
if _, err := cfg.WriteTo(targetConfig); err != nil {
137+
return fmt.Errorf("error writing config: %v", err)
138+
}
139+
140+
os.Stdout.WriteString("Using config:\n")
141+
if _, err = cfg.WriteTo(os.Stdout); err != nil {
142+
t.logger.Warningf("Failed to output config to STDOUT: %v", err)
143+
}
144+
145+
return nil
146+
}

cmd/nvidia-ctk-installer/toolkit/toolkit.go

+2-121
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,12 @@ import (
2020
"fmt"
2121
"os"
2222
"path/filepath"
23-
"strings"
2423

2524
"github.com/urfave/cli/v2"
2625
"tags.cncf.io/container-device-interface/pkg/cdi"
2726
"tags.cncf.io/container-device-interface/pkg/parser"
2827

2928
"github.com/NVIDIA/nvidia-container-toolkit/cmd/nvidia-ctk-installer/toolkit/installer"
30-
"github.com/NVIDIA/nvidia-container-toolkit/internal/config"
3129
"github.com/NVIDIA/nvidia-container-toolkit/internal/logger"
3230
"github.com/NVIDIA/nvidia-container-toolkit/internal/system/nvdevices"
3331
"github.com/NVIDIA/nvidia-container-toolkit/pkg/nvcdi"
@@ -37,11 +35,6 @@ import (
3735
const (
3836
// DefaultNvidiaDriverRoot specifies the default NVIDIA driver run directory
3937
DefaultNvidiaDriverRoot = "/run/nvidia/driver"
40-
41-
nvidiaContainerCliSource = "/usr/bin/nvidia-container-cli"
42-
nvidiaContainerRuntimeHookSource = "/usr/bin/nvidia-container-runtime-hook"
43-
44-
configFilename = "config.toml"
4538
)
4639

4740
type cdiOptions struct {
@@ -318,20 +311,7 @@ func (t *Installer) Install(cli *cli.Context, opts *Options) error {
318311
t.logger.Errorf("Ignoring error: %v", fmt.Errorf("could not install toolkit components: %w", err))
319312
}
320313

321-
toolkitConfigDir := filepath.Join(t.toolkitRoot, ".config", "nvidia-container-runtime")
322-
toolkitConfigPath := filepath.Join(toolkitConfigDir, configFilename)
323-
324-
err = t.createDirectories(toolkitConfigDir)
325-
if err != nil && !opts.ignoreErrors {
326-
return fmt.Errorf("could not create required directories: %v", err)
327-
} else if err != nil {
328-
t.logger.Errorf("Ignoring error: %v", fmt.Errorf("could not create required directories: %v", err))
329-
}
330-
nvidiaContainerCliExecutable := filepath.Join(t.toolkitRoot, "nvidia-container-cli")
331-
nvidiaCTKPath := filepath.Join(t.toolkitRoot, "nvidia-ctk")
332-
nvidiaCDIHookPath := filepath.Join(t.toolkitRoot, "nvidia-cdi-hook")
333-
nvidiaContainerRuntimeHookPath := filepath.Join(t.toolkitRoot, "nvidia-container-runtime-hook")
334-
err = t.installToolkitConfig(cli, toolkitConfigPath, nvidiaContainerCliExecutable, nvidiaCTKPath, nvidiaContainerRuntimeHookPath, opts)
314+
err = t.installToolkitConfig(cli, opts)
335315
if err != nil && !opts.ignoreErrors {
336316
return fmt.Errorf("error installing NVIDIA container toolkit config: %v", err)
337317
} else if err != nil {
@@ -345,6 +325,7 @@ func (t *Installer) Install(cli *cli.Context, opts *Options) error {
345325
t.logger.Errorf("Ignoring error: %v", fmt.Errorf("error creating device nodes: %v", err))
346326
}
347327

328+
nvidiaCDIHookPath := filepath.Join(t.toolkitRoot, "nvidia-cdi-hook")
348329
err = t.generateCDISpec(opts, nvidiaCDIHookPath)
349330
if err != nil && !opts.ignoreErrors {
350331
return fmt.Errorf("error generating CDI specification: %v", err)
@@ -355,106 +336,6 @@ func (t *Installer) Install(cli *cli.Context, opts *Options) error {
355336
return nil
356337
}
357338

358-
// installToolkitConfig installs the config file for the NVIDIA container toolkit ensuring
359-
// that the settings are updated to match the desired install and nvidia driver directories.
360-
func (t *Installer) installToolkitConfig(c *cli.Context, toolkitConfigPath string, nvidiaContainerCliExecutablePath string, nvidiaCTKPath string, nvidaContainerRuntimeHookPath string, opts *Options) error {
361-
t.logger.Infof("Installing NVIDIA container toolkit config '%v'", toolkitConfigPath)
362-
363-
cfg, err := config.New()
364-
if err != nil {
365-
return fmt.Errorf("could not open source config file: %v", err)
366-
}
367-
368-
targetConfig, err := os.Create(toolkitConfigPath)
369-
if err != nil {
370-
return fmt.Errorf("could not create target config file: %v", err)
371-
}
372-
defer targetConfig.Close()
373-
374-
// Read the ldconfig path from the config as this may differ per platform
375-
// On ubuntu-based systems this ends in `.real`
376-
ldconfigPath := fmt.Sprintf("%s", cfg.GetDefault("nvidia-container-cli.ldconfig", "/sbin/ldconfig"))
377-
// Use the driver run root as the root:
378-
driverLdconfigPath := config.NormalizeLDConfigPath("@" + filepath.Join(opts.DriverRoot, strings.TrimPrefix(ldconfigPath, "@/")))
379-
380-
configValues := map[string]interface{}{
381-
// Set the options in the root toml table
382-
"accept-nvidia-visible-devices-envvar-when-unprivileged": opts.acceptNVIDIAVisibleDevicesWhenUnprivileged,
383-
"accept-nvidia-visible-devices-as-volume-mounts": opts.acceptNVIDIAVisibleDevicesAsVolumeMounts,
384-
// Set the nvidia-container-cli options
385-
"nvidia-container-cli.root": opts.DriverRoot,
386-
"nvidia-container-cli.path": nvidiaContainerCliExecutablePath,
387-
"nvidia-container-cli.ldconfig": driverLdconfigPath,
388-
// Set nvidia-ctk options
389-
"nvidia-ctk.path": nvidiaCTKPath,
390-
// Set the nvidia-container-runtime-hook options
391-
"nvidia-container-runtime-hook.path": nvidaContainerRuntimeHookPath,
392-
"nvidia-container-runtime-hook.skip-mode-detection": opts.ContainerRuntimeHookSkipModeDetection,
393-
}
394-
395-
toolkitRuntimeList := opts.ContainerRuntimeRuntimes.Value()
396-
if len(toolkitRuntimeList) > 0 {
397-
configValues["nvidia-container-runtime.runtimes"] = toolkitRuntimeList
398-
}
399-
400-
for _, optInFeature := range opts.optInFeatures.Value() {
401-
configValues["features."+optInFeature] = true
402-
}
403-
404-
for key, value := range configValues {
405-
cfg.Set(key, value)
406-
}
407-
408-
// Set the optional config options
409-
optionalConfigValues := map[string]interface{}{
410-
"nvidia-container-runtime.debug": opts.ContainerRuntimeDebug,
411-
"nvidia-container-runtime.log-level": opts.ContainerRuntimeLogLevel,
412-
"nvidia-container-runtime.mode": opts.ContainerRuntimeMode,
413-
"nvidia-container-runtime.modes.cdi.annotation-prefixes": opts.ContainerRuntimeModesCDIAnnotationPrefixes,
414-
"nvidia-container-runtime.modes.cdi.default-kind": opts.ContainerRuntimeModesCdiDefaultKind,
415-
"nvidia-container-runtime.runtimes": opts.ContainerRuntimeRuntimes,
416-
"nvidia-container-cli.debug": opts.ContainerCLIDebug,
417-
}
418-
419-
for key, value := range optionalConfigValues {
420-
if !c.IsSet(key) {
421-
t.logger.Infof("Skipping unset option: %v", key)
422-
continue
423-
}
424-
if value == nil {
425-
t.logger.Infof("Skipping option with nil value: %v", key)
426-
continue
427-
}
428-
429-
switch v := value.(type) {
430-
case string:
431-
if v == "" {
432-
continue
433-
}
434-
case cli.StringSlice:
435-
if len(v.Value()) == 0 {
436-
continue
437-
}
438-
value = v.Value()
439-
default:
440-
t.logger.Warningf("Unexpected type for option %v=%v: %T", key, value, v)
441-
}
442-
443-
cfg.Set(key, value)
444-
}
445-
446-
if _, err := cfg.WriteTo(targetConfig); err != nil {
447-
return fmt.Errorf("error writing config: %v", err)
448-
}
449-
450-
os.Stdout.WriteString("Using config:\n")
451-
if _, err = cfg.WriteTo(os.Stdout); err != nil {
452-
t.logger.Warningf("Failed to output config to STDOUT: %v", err)
453-
}
454-
455-
return nil
456-
}
457-
458339
func (t *Installer) createDirectories(dir ...string) error {
459340
for _, d := range dir {
460341
t.logger.Infof("Creating directory '%v'", d)

0 commit comments

Comments
 (0)