mirror of
				https://github.com/NVIDIA/nvidia-container-toolkit
				synced 2025-06-26 18:18:24 +00:00 
			
		
		
		
	Merge branch 'add-hooks-cli' into 'master'
Add nvidia-ctk CLI with hook command and update-ldcache subcommand to update LD cache See merge request nvidia/container-toolkit/container-toolkit!115
This commit is contained in:
		
						commit
						f7c74d35cc
					
				
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -5,4 +5,5 @@ dist | |||||||
| /test/output/ | /test/output/ | ||||||
| /nvidia-container-runtime | /nvidia-container-runtime | ||||||
| /nvidia-container-toolkit | /nvidia-container-toolkit | ||||||
|  | /nvidia-ctk | ||||||
| /shared-* | /shared-* | ||||||
|  | |||||||
| @ -59,13 +59,16 @@ func NewExperimentalModifier(logger *logrus.Logger, cfg *config.Config, ociSpec | |||||||
| 	} | 	} | ||||||
| 	logger.Infof("Constructing modifier from config: %+v", cfg) | 	logger.Infof("Constructing modifier from config: %+v", cfg) | ||||||
| 
 | 
 | ||||||
| 	root := cfg.NVIDIAContainerCLIConfig.Root | 	config := &discover.Config{ | ||||||
|  | 		Root:                                    cfg.NVIDIAContainerCLIConfig.Root, | ||||||
|  | 		NVIDIAContainerToolkitCLIExecutablePath: cfg.NVIDIACTKConfig.Path, | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	var d discover.Discover | 	var d discover.Discover | ||||||
| 
 | 
 | ||||||
| 	switch resolveAutoDiscoverMode(logger, cfg.NVIDIAContainerRuntimeConfig.DiscoverMode) { | 	switch resolveAutoDiscoverMode(logger, cfg.NVIDIAContainerRuntimeConfig.DiscoverMode) { | ||||||
| 	case "legacy": | 	case "legacy": | ||||||
| 		legacyDiscoverer, err := discover.NewLegacyDiscoverer(logger, root) | 		legacyDiscoverer, err := discover.NewLegacyDiscoverer(logger, config) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return nil, fmt.Errorf("failed to create legacy discoverer: %v", err) | 			return nil, fmt.Errorf("failed to create legacy discoverer: %v", err) | ||||||
| 		} | 		} | ||||||
| @ -81,11 +84,17 @@ func NewExperimentalModifier(logger *logrus.Logger, cfg *config.Config, ociSpec | |||||||
| 			csvFiles = csv.BaseFilesOnly(csvFiles) | 			csvFiles = csv.BaseFilesOnly(csvFiles) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		csvDiscoverer, err := discover.NewFromCSVFiles(logger, csvFiles, root) | 		csvDiscoverer, err := discover.NewFromCSVFiles(logger, csvFiles, config.Root) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return nil, fmt.Errorf("failed to create CSV discoverer: %v", err) | 			return nil, fmt.Errorf("failed to create CSV discoverer: %v", err) | ||||||
| 		} | 		} | ||||||
| 		d = csvDiscoverer | 
 | ||||||
|  | 		hooks, err := discover.NewLDCacheUpdateHook(logger, csvDiscoverer, config) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return nil, fmt.Errorf("failed to create hook discoverer: %v", err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		d = discover.NewList(csvDiscoverer, hooks) | ||||||
| 	default: | 	default: | ||||||
| 		return nil, fmt.Errorf("invalid discover mode: %v", cfg.NVIDIAContainerRuntimeConfig.DiscoverMode) | 		return nil, fmt.Errorf("invalid discover mode: %v", cfg.NVIDIAContainerRuntimeConfig.DiscoverMode) | ||||||
| 	} | 	} | ||||||
|  | |||||||
							
								
								
									
										3
									
								
								cmd/nvidia-ctk/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								cmd/nvidia-ctk/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | # NVIDIA Container Toolkit CLI | ||||||
|  | 
 | ||||||
|  | The NVIDIA Container Toolkit CLI `nvidia-ctk` provides a number of utilities that are useful for working with the NVIDIA Container Toolkit. | ||||||
							
								
								
									
										50
									
								
								cmd/nvidia-ctk/hook/hook.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								cmd/nvidia-ctk/hook/hook.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,50 @@ | |||||||
|  | /** | ||||||
|  | # Copyright (c) 2022, NVIDIA CORPORATION.  All rights reserved. | ||||||
|  | # | ||||||
|  | # 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 hook | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	ldcache "github.com/NVIDIA/nvidia-container-toolkit/cmd/nvidia-ctk/hook/update-ldcache" | ||||||
|  | 	"github.com/sirupsen/logrus" | ||||||
|  | 	"github.com/urfave/cli/v2" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type hookCommand struct { | ||||||
|  | 	logger *logrus.Logger | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // NewCommand constructs a hook command with the specified logger
 | ||||||
|  | func NewCommand(logger *logrus.Logger) *cli.Command { | ||||||
|  | 	c := hookCommand{ | ||||||
|  | 		logger: logger, | ||||||
|  | 	} | ||||||
|  | 	return c.build() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // build
 | ||||||
|  | func (m hookCommand) build() *cli.Command { | ||||||
|  | 	// Create the 'hook' command
 | ||||||
|  | 	hook := cli.Command{ | ||||||
|  | 		Name:  "hook", | ||||||
|  | 		Usage: "A collection of hooks that may be injected into an OCI spec", | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	hook.Subcommands = []*cli.Command{ | ||||||
|  | 		ldcache.NewCommand(m.logger), | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return &hook | ||||||
|  | } | ||||||
							
								
								
									
										155
									
								
								cmd/nvidia-ctk/hook/update-ldcache/update-ldcache.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										155
									
								
								cmd/nvidia-ctk/hook/update-ldcache/update-ldcache.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,155 @@ | |||||||
|  | /** | ||||||
|  | # Copyright (c) 2022, NVIDIA CORPORATION.  All rights reserved. | ||||||
|  | # | ||||||
|  | # 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 ldcache | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"encoding/json" | ||||||
|  | 	"fmt" | ||||||
|  | 	"os" | ||||||
|  | 	"path/filepath" | ||||||
|  | 	"syscall" | ||||||
|  | 
 | ||||||
|  | 	"github.com/NVIDIA/nvidia-container-toolkit/internal/oci" | ||||||
|  | 	"github.com/opencontainers/runtime-spec/specs-go" | ||||||
|  | 	"github.com/sirupsen/logrus" | ||||||
|  | 	"github.com/urfave/cli/v2" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type command struct { | ||||||
|  | 	logger *logrus.Logger | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type config struct { | ||||||
|  | 	folders       cli.StringSlice | ||||||
|  | 	containerSpec string | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // NewCommand constructs an update-ldcache command with the specified logger
 | ||||||
|  | func NewCommand(logger *logrus.Logger) *cli.Command { | ||||||
|  | 	c := command{ | ||||||
|  | 		logger: logger, | ||||||
|  | 	} | ||||||
|  | 	return c.build() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // build the update-ldcache command
 | ||||||
|  | func (m command) build() *cli.Command { | ||||||
|  | 	cfg := config{} | ||||||
|  | 
 | ||||||
|  | 	// Create the 'update-ldcache' command
 | ||||||
|  | 	c := cli.Command{ | ||||||
|  | 		Name:  "update-ldcache", | ||||||
|  | 		Usage: "Update ldcache in a container by running ldconfig", | ||||||
|  | 		Action: func(c *cli.Context) error { | ||||||
|  | 			return m.run(c, &cfg) | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	c.Flags = []cli.Flag{ | ||||||
|  | 		&cli.StringSliceFlag{ | ||||||
|  | 			Name:        "folders", | ||||||
|  | 			Usage:       "Specifiy the additional folders to add to /etc/ld.so.conf before updating the ld cache", | ||||||
|  | 			Destination: &cfg.folders, | ||||||
|  | 		}, | ||||||
|  | 		&cli.StringFlag{ | ||||||
|  | 			Name:        "container-spec", | ||||||
|  | 			Usage:       "Specify the path to the OCI container spec. If empty or '-' the spec will be read from STDIN", | ||||||
|  | 			Destination: &cfg.containerSpec, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return &c | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (m command) run(c *cli.Context, cfg *config) error { | ||||||
|  | 	var s specs.State | ||||||
|  | 
 | ||||||
|  | 	inputReader := os.Stdin | ||||||
|  | 	if cfg.containerSpec != "" && cfg.containerSpec != "-" { | ||||||
|  | 		inputFile, err := os.Open(cfg.containerSpec) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return fmt.Errorf("failed to open intput: %v", err) | ||||||
|  | 		} | ||||||
|  | 		defer inputFile.Close() | ||||||
|  | 		inputReader = inputFile | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	d := json.NewDecoder(inputReader) | ||||||
|  | 	if err := d.Decode(&s); err != nil { | ||||||
|  | 		return fmt.Errorf("failed to decode container state: %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	specFilePath := oci.GetSpecFilePath(s.Bundle) | ||||||
|  | 	specFile, err := os.Open(specFilePath) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return fmt.Errorf("failed to open OCI spec file: %v", err) | ||||||
|  | 	} | ||||||
|  | 	defer specFile.Close() | ||||||
|  | 
 | ||||||
|  | 	spec, err := oci.LoadFrom(specFile) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return fmt.Errorf("failed to load OCI spec: %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	var containerRoot string | ||||||
|  | 	if spec.Root != nil { | ||||||
|  | 		containerRoot = spec.Root.Path | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = m.createConfig(containerRoot, cfg.folders.Value()) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return fmt.Errorf("failed to update ld.so.conf: %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	args := []string{"/sbin/ldconfig"} | ||||||
|  | 	if containerRoot != "" { | ||||||
|  | 		args = append(args, "-r", containerRoot) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return syscall.Exec(args[0], args, nil) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // createConfig creates (or updates) /etc/ld.so.conf.d/nvcr-<RANDOM_STRING>.conf in the container
 | ||||||
|  | // to include the required paths.
 | ||||||
|  | func (m command) createConfig(root string, folders []string) error { | ||||||
|  | 	if len(folders) == 0 { | ||||||
|  | 		m.logger.Debugf("No folders to add to /etc/ld.so.conf") | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	configFile, err := os.CreateTemp(filepath.Join(root, "/etc/ld.so.conf.d"), "nvcr-*.conf") | ||||||
|  | 	if err != nil { | ||||||
|  | 		return fmt.Errorf("failed to create config file: %v", err) | ||||||
|  | 	} | ||||||
|  | 	defer configFile.Close() | ||||||
|  | 
 | ||||||
|  | 	m.logger.Debugf("Adding folders %v to %v", folders, configFile.Name()) | ||||||
|  | 
 | ||||||
|  | 	configured := make(map[string]bool) | ||||||
|  | 	for _, folder := range folders { | ||||||
|  | 		if configured[folder] { | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 		_, err = configFile.WriteString(fmt.Sprintf("%s\n", folder)) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return fmt.Errorf("failed to update ld.so.conf.d: %v", err) | ||||||
|  | 		} | ||||||
|  | 		configured[folder] = true | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
							
								
								
									
										82
									
								
								cmd/nvidia-ctk/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								cmd/nvidia-ctk/main.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,82 @@ | |||||||
|  | /** | ||||||
|  | # Copyright (c) 2021, NVIDIA CORPORATION.  All rights reserved. | ||||||
|  | # | ||||||
|  | # 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 main | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"os" | ||||||
|  | 
 | ||||||
|  | 	"github.com/NVIDIA/nvidia-container-toolkit/cmd/nvidia-ctk/hook" | ||||||
|  | 	log "github.com/sirupsen/logrus" | ||||||
|  | 	cli "github.com/urfave/cli/v2" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | var version string | ||||||
|  | 
 | ||||||
|  | var logger = log.New() | ||||||
|  | 
 | ||||||
|  | // config defines the options that can be set for the CLI through config files,
 | ||||||
|  | // environment variables, or command line flags
 | ||||||
|  | type config struct { | ||||||
|  | 	// Debug indicates whether the CLI is started in "debug" mode
 | ||||||
|  | 	Debug bool | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func main() { | ||||||
|  | 	// Create a config struct to hold the parsed environment variables or command line flags
 | ||||||
|  | 	config := config{} | ||||||
|  | 
 | ||||||
|  | 	// Create the top-level CLI
 | ||||||
|  | 	c := cli.NewApp() | ||||||
|  | 	c.UseShortOptionHandling = true | ||||||
|  | 	c.EnableBashCompletion = true | ||||||
|  | 	c.Usage = "Tools to configure the NVIDIA Container Toolkit" | ||||||
|  | 	c.Version = version | ||||||
|  | 
 | ||||||
|  | 	// Setup the flags for this command
 | ||||||
|  | 	c.Flags = []cli.Flag{ | ||||||
|  | 		&cli.BoolFlag{ | ||||||
|  | 			Name:        "debug", | ||||||
|  | 			Aliases:     []string{"d"}, | ||||||
|  | 			Usage:       "Enable debug-level logging", | ||||||
|  | 			Destination: &config.Debug, | ||||||
|  | 			EnvVars:     []string{"NVIDIA_CTK_DEBUG"}, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Set log-level for all subcommands
 | ||||||
|  | 	c.Before = func(c *cli.Context) error { | ||||||
|  | 		logLevel := log.InfoLevel | ||||||
|  | 		if config.Debug { | ||||||
|  | 			logLevel = log.DebugLevel | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		logger.SetLevel(logLevel) | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Define the subcommands
 | ||||||
|  | 	c.Commands = []*cli.Command{ | ||||||
|  | 		hook.NewCommand(logger), | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Run the CLI
 | ||||||
|  | 	err := c.Run(os.Args) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Errorf("%v", err) | ||||||
|  | 		log.Exit(1) | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @ -38,6 +38,7 @@ var ( | |||||||
| // Note: This is currently duplicated by the HookConfig in cmd/nvidia-container-toolkit/hook_config.go
 | // Note: This is currently duplicated by the HookConfig in cmd/nvidia-container-toolkit/hook_config.go
 | ||||||
| type Config struct { | type Config struct { | ||||||
| 	NVIDIAContainerCLIConfig     ContainerCLIConfig `toml:"nvidia-container-cli"` | 	NVIDIAContainerCLIConfig     ContainerCLIConfig `toml:"nvidia-container-cli"` | ||||||
|  | 	NVIDIACTKConfig              CTKConfig          `toml:"nvidia-ctk"` | ||||||
| 	NVIDIAContainerRuntimeConfig RuntimeConfig      `toml:"nvidia-container-runtime"` | 	NVIDIAContainerRuntimeConfig RuntimeConfig      `toml:"nvidia-container-runtime"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -83,6 +84,7 @@ func getConfigFrom(toml *toml.Tree) *Config { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	cfg.NVIDIAContainerCLIConfig = *getContainerCLIConfigFrom(toml) | 	cfg.NVIDIAContainerCLIConfig = *getContainerCLIConfigFrom(toml) | ||||||
|  | 	cfg.NVIDIACTKConfig = *getCTKConfigFrom(toml) | ||||||
| 	cfg.NVIDIAContainerRuntimeConfig = *getRuntimeConfigFrom(toml) | 	cfg.NVIDIAContainerRuntimeConfig = *getRuntimeConfigFrom(toml) | ||||||
| 
 | 
 | ||||||
| 	return cfg | 	return cfg | ||||||
| @ -92,6 +94,7 @@ func getConfigFrom(toml *toml.Tree) *Config { | |||||||
| func getDefaultConfig() *Config { | func getDefaultConfig() *Config { | ||||||
| 	c := Config{ | 	c := Config{ | ||||||
| 		NVIDIAContainerCLIConfig:     *getDefaultContainerCLIConfig(), | 		NVIDIAContainerCLIConfig:     *getDefaultContainerCLIConfig(), | ||||||
|  | 		NVIDIACTKConfig:              *getDefaultCTKConfig(), | ||||||
| 		NVIDIAContainerRuntimeConfig: *getDefaultRuntimeConfig(), | 		NVIDIAContainerRuntimeConfig: *getDefaultRuntimeConfig(), | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -65,43 +65,58 @@ func TestGetConfig(t *testing.T) { | |||||||
| 					Experimental:  false, | 					Experimental:  false, | ||||||
| 					DiscoverMode:  "auto", | 					DiscoverMode:  "auto", | ||||||
| 				}, | 				}, | ||||||
|  | 				NVIDIACTKConfig: CTKConfig{ | ||||||
|  | 					Path: "nvidia-ctk", | ||||||
|  | 				}, | ||||||
| 			}, | 			}, | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			description: "config options set inline", | 			description: "config options set inline", | ||||||
| 			contents: []string{ | 			contents: []string{ | ||||||
|  | 				"nvidia-container-cli.root = \"/bar/baz\"", | ||||||
| 				"nvidia-container-runtime.debug = \"/foo/bar\"", | 				"nvidia-container-runtime.debug = \"/foo/bar\"", | ||||||
| 				"nvidia-container-runtime.experimental = true", | 				"nvidia-container-runtime.experimental = true", | ||||||
| 				"nvidia-container-runtime.discover-mode = \"not-legacy\"", | 				"nvidia-container-runtime.discover-mode = \"not-legacy\"", | ||||||
|  | 				"nvidia-ctk.path = \"/foo/bar/nvidia-ctk\"", | ||||||
| 			}, | 			}, | ||||||
| 			expectedConfig: &Config{ | 			expectedConfig: &Config{ | ||||||
| 				NVIDIAContainerCLIConfig: ContainerCLIConfig{ | 				NVIDIAContainerCLIConfig: ContainerCLIConfig{ | ||||||
| 					Root: "", | 					Root: "/bar/baz", | ||||||
| 				}, | 				}, | ||||||
| 				NVIDIAContainerRuntimeConfig: RuntimeConfig{ | 				NVIDIAContainerRuntimeConfig: RuntimeConfig{ | ||||||
| 					DebugFilePath: "/foo/bar", | 					DebugFilePath: "/foo/bar", | ||||||
| 					Experimental:  true, | 					Experimental:  true, | ||||||
| 					DiscoverMode:  "not-legacy", | 					DiscoverMode:  "not-legacy", | ||||||
| 				}, | 				}, | ||||||
|  | 				NVIDIACTKConfig: CTKConfig{ | ||||||
|  | 					Path: "/foo/bar/nvidia-ctk", | ||||||
|  | 				}, | ||||||
| 			}, | 			}, | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			description: "config options set in section", | 			description: "config options set in section", | ||||||
| 			contents: []string{ | 			contents: []string{ | ||||||
|  | 				"[nvidia-container-cli]", | ||||||
|  | 				"root = \"/bar/baz\"", | ||||||
| 				"[nvidia-container-runtime]", | 				"[nvidia-container-runtime]", | ||||||
| 				"debug = \"/foo/bar\"", | 				"debug = \"/foo/bar\"", | ||||||
| 				"experimental = true", | 				"experimental = true", | ||||||
| 				"discover-mode = \"not-legacy\"", | 				"discover-mode = \"not-legacy\"", | ||||||
|  | 				"[nvidia-ctk]", | ||||||
|  | 				"path = \"/foo/bar/nvidia-ctk\"", | ||||||
| 			}, | 			}, | ||||||
| 			expectedConfig: &Config{ | 			expectedConfig: &Config{ | ||||||
| 				NVIDIAContainerCLIConfig: ContainerCLIConfig{ | 				NVIDIAContainerCLIConfig: ContainerCLIConfig{ | ||||||
| 					Root: "", | 					Root: "/bar/baz", | ||||||
| 				}, | 				}, | ||||||
| 				NVIDIAContainerRuntimeConfig: RuntimeConfig{ | 				NVIDIAContainerRuntimeConfig: RuntimeConfig{ | ||||||
| 					DebugFilePath: "/foo/bar", | 					DebugFilePath: "/foo/bar", | ||||||
| 					Experimental:  true, | 					Experimental:  true, | ||||||
| 					DiscoverMode:  "not-legacy", | 					DiscoverMode:  "not-legacy", | ||||||
| 				}, | 				}, | ||||||
|  | 				NVIDIACTKConfig: CTKConfig{ | ||||||
|  | 					Path: "/foo/bar/nvidia-ctk", | ||||||
|  | 				}, | ||||||
| 			}, | 			}, | ||||||
| 		}, | 		}, | ||||||
| 	} | 	} | ||||||
							
								
								
									
										46
									
								
								internal/config/toolkit-cli.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								internal/config/toolkit-cli.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,46 @@ | |||||||
|  | /** | ||||||
|  | # Copyright (c) 2022, NVIDIA CORPORATION.  All rights reserved. | ||||||
|  | # | ||||||
|  | # 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 | ||||||
|  | 
 | ||||||
|  | import "github.com/pelletier/go-toml" | ||||||
|  | 
 | ||||||
|  | // CTKConfig stores the config options for the NVIDIA Container Toolkit CLI (nvidia-ctk)
 | ||||||
|  | type CTKConfig struct { | ||||||
|  | 	Path string `toml:"path"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // getCTKConfigFrom reads the nvidia container runtime config from the specified toml Tree.
 | ||||||
|  | func getCTKConfigFrom(toml *toml.Tree) *CTKConfig { | ||||||
|  | 	cfg := getDefaultCTKConfig() | ||||||
|  | 
 | ||||||
|  | 	if toml == nil { | ||||||
|  | 		return cfg | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	cfg.Path = toml.GetDefault("nvidia-ctk.path", cfg.Path).(string) | ||||||
|  | 
 | ||||||
|  | 	return cfg | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // getDefaultCTKConfig defines the default values for the config
 | ||||||
|  | func getDefaultCTKConfig() *CTKConfig { | ||||||
|  | 	c := CTKConfig{ | ||||||
|  | 		Path: "nvidia-ctk", | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return &c | ||||||
|  | } | ||||||
| @ -119,7 +119,7 @@ func newFromMountSpecs(logger *logrus.Logger, locators map[csv.MountSpecType]loo | |||||||
| 
 | 
 | ||||||
| // Mounts returns the discovered mounts for the csvDiscoverer.
 | // Mounts returns the discovered mounts for the csvDiscoverer.
 | ||||||
| // Note that if the discoverer is for the device MountSpecType, the list of mounts is empty.
 | // Note that if the discoverer is for the device MountSpecType, the list of mounts is empty.
 | ||||||
| func (d csvDiscoverer) Mounts() ([]Mount, error) { | func (d *csvDiscoverer) Mounts() ([]Mount, error) { | ||||||
| 	if d.mountType == csv.MountSpecDev { | 	if d.mountType == csv.MountSpecDev { | ||||||
| 		return d.None.Mounts() | 		return d.None.Mounts() | ||||||
| 	} | 	} | ||||||
| @ -129,7 +129,7 @@ func (d csvDiscoverer) Mounts() ([]Mount, error) { | |||||||
| 
 | 
 | ||||||
| // Devices returns the discovered devices for the csvDiscoverer.
 | // Devices returns the discovered devices for the csvDiscoverer.
 | ||||||
| // Note that if the discoverer is not for the device MountSpecType, the list of devices is empty.
 | // Note that if the discoverer is not for the device MountSpecType, the list of devices is empty.
 | ||||||
| func (d csvDiscoverer) Devices() ([]Device, error) { | func (d *csvDiscoverer) Devices() ([]Device, error) { | ||||||
| 	if d.mountType != csv.MountSpecDev { | 	if d.mountType != csv.MountSpecDev { | ||||||
| 		return d.None.Devices() | 		return d.None.Devices() | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -31,7 +31,7 @@ func TestCSVDiscoverer(t *testing.T) { | |||||||
| 
 | 
 | ||||||
| 	testCases := []struct { | 	testCases := []struct { | ||||||
| 		description          string | 		description          string | ||||||
| 		input                csvDiscoverer | 		input                *csvDiscoverer | ||||||
| 		expectedMounts       []Mount | 		expectedMounts       []Mount | ||||||
| 		expectedMountsError  error | 		expectedMountsError  error | ||||||
| 		expectedDevicesError error | 		expectedDevicesError error | ||||||
| @ -39,7 +39,7 @@ func TestCSVDiscoverer(t *testing.T) { | |||||||
| 	}{ | 	}{ | ||||||
| 		{ | 		{ | ||||||
| 			description: "dev mounts are empty", | 			description: "dev mounts are empty", | ||||||
| 			input: csvDiscoverer{ | 			input: &csvDiscoverer{ | ||||||
| 				mounts: mounts{ | 				mounts: mounts{ | ||||||
| 					lookup: &lookup.LocatorMock{ | 					lookup: &lookup.LocatorMock{ | ||||||
| 						LocateFunc: func(string) ([]string, error) { | 						LocateFunc: func(string) ([]string, error) { | ||||||
| @ -54,14 +54,14 @@ func TestCSVDiscoverer(t *testing.T) { | |||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			description: "dev devices returns error for nil lookup", | 			description: "dev devices returns error for nil lookup", | ||||||
| 			input: csvDiscoverer{ | 			input: &csvDiscoverer{ | ||||||
| 				mountType: "dev", | 				mountType: "dev", | ||||||
| 			}, | 			}, | ||||||
| 			expectedDevicesError: fmt.Errorf("no lookup defined"), | 			expectedDevicesError: fmt.Errorf("no lookup defined"), | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			description: "lib devices are empty", | 			description: "lib devices are empty", | ||||||
| 			input: csvDiscoverer{ | 			input: &csvDiscoverer{ | ||||||
| 				mounts: mounts{ | 				mounts: mounts{ | ||||||
| 					lookup: &lookup.LocatorMock{ | 					lookup: &lookup.LocatorMock{ | ||||||
| 						LocateFunc: func(string) ([]string, error) { | 						LocateFunc: func(string) ([]string, error) { | ||||||
| @ -76,7 +76,7 @@ func TestCSVDiscoverer(t *testing.T) { | |||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			description: "lib mounts returns error for nil lookup", | 			description: "lib mounts returns error for nil lookup", | ||||||
| 			input: csvDiscoverer{ | 			input: &csvDiscoverer{ | ||||||
| 				mountType: "lib", | 				mountType: "lib", | ||||||
| 			}, | 			}, | ||||||
| 			expectedMountsError: fmt.Errorf("no lookup defined"), | 			expectedMountsError: fmt.Errorf("no lookup defined"), | ||||||
|  | |||||||
| @ -16,6 +16,12 @@ | |||||||
| 
 | 
 | ||||||
| package discover | package discover | ||||||
| 
 | 
 | ||||||
|  | // Config represents the configuration options for discovery
 | ||||||
|  | type Config struct { | ||||||
|  | 	Root                                    string | ||||||
|  | 	NVIDIAContainerToolkitCLIExecutablePath string | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // Device represents a discovered character device.
 | // Device represents a discovered character device.
 | ||||||
| type Device struct { | type Device struct { | ||||||
| 	Path string | 	Path string | ||||||
|  | |||||||
							
								
								
									
										126
									
								
								internal/discover/ldconfig.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								internal/discover/ldconfig.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,126 @@ | |||||||
|  | /** | ||||||
|  | # Copyright (c) 2022, NVIDIA CORPORATION.  All rights reserved. | ||||||
|  | # | ||||||
|  | # 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 discover | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"path/filepath" | ||||||
|  | 	"sort" | ||||||
|  | 	"strings" | ||||||
|  | 
 | ||||||
|  | 	"github.com/NVIDIA/nvidia-container-toolkit/internal/lookup" | ||||||
|  | 	"github.com/container-orchestrated-devices/container-device-interface/pkg/cdi" | ||||||
|  | 	"github.com/sirupsen/logrus" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // NewLDCacheUpdateHook creates a discoverer that updates the ldcache for the specified mounts. A logger can also be specified
 | ||||||
|  | func NewLDCacheUpdateHook(logger *logrus.Logger, mounts Discover, cfg *Config) (Discover, error) { | ||||||
|  | 	d := ldconfig{ | ||||||
|  | 		logger:                  logger, | ||||||
|  | 		mountsFrom:              mounts, | ||||||
|  | 		lookup:                  lookup.NewExecutableLocator(logger, cfg.Root), | ||||||
|  | 		nvidiaCTKExecutablePath: cfg.NVIDIAContainerToolkitCLIExecutablePath, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return &d, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const ( | ||||||
|  | 	nvidiaCTKDefaultFilePath = "/usr/bin/nvidia-ctk" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type ldconfig struct { | ||||||
|  | 	None | ||||||
|  | 	logger                  *logrus.Logger | ||||||
|  | 	mountsFrom              Discover | ||||||
|  | 	lookup                  lookup.Locator | ||||||
|  | 	nvidiaCTKExecutablePath string | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Hooks checks the required mounts for libraries and returns a hook to update the LDcache for the discovered paths.
 | ||||||
|  | func (d ldconfig) Hooks() ([]Hook, error) { | ||||||
|  | 	mounts, err := d.mountsFrom.Mounts() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, fmt.Errorf("failed to discover mounts for ldcache update: %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	libDirs := getLibDirs(mounts) | ||||||
|  | 
 | ||||||
|  | 	hookPath := nvidiaCTKDefaultFilePath | ||||||
|  | 	targets, err := d.lookup.Locate(d.nvidiaCTKExecutablePath) | ||||||
|  | 	if err != nil { | ||||||
|  | 		d.logger.Warnf("Failed to locate %v: %v", d.nvidiaCTKExecutablePath, err) | ||||||
|  | 	} else if len(targets) == 0 { | ||||||
|  | 		d.logger.Warnf("%v not found", d.nvidiaCTKExecutablePath) | ||||||
|  | 	} else { | ||||||
|  | 		d.logger.Debugf("Found %v candidates: %v", d.nvidiaCTKExecutablePath, targets) | ||||||
|  | 		hookPath = targets[0] | ||||||
|  | 	} | ||||||
|  | 	d.logger.Debugf("Using NVIDIA Container Toolkit CLI path %v", hookPath) | ||||||
|  | 
 | ||||||
|  | 	args := []string{hookPath, "hook", "update-ldcache"} | ||||||
|  | 	for _, f := range libDirs { | ||||||
|  | 		args = append(args, "--folders", f) | ||||||
|  | 	} | ||||||
|  | 	h := Hook{ | ||||||
|  | 		Lifecycle: cdi.CreateContainerHook, | ||||||
|  | 		Path:      hookPath, | ||||||
|  | 		Args:      args, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return []Hook{h}, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // getLibDirs extracts the library dirs from the specified mounts
 | ||||||
|  | func getLibDirs(mounts []Mount) []string { | ||||||
|  | 	var paths []string | ||||||
|  | 	checked := make(map[string]bool) | ||||||
|  | 
 | ||||||
|  | 	for _, m := range mounts { | ||||||
|  | 		dir := filepath.Dir(m.Path) | ||||||
|  | 		if dir == "" { | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		_, exists := checked[dir] | ||||||
|  | 		if exists { | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 		checked[dir] = isLibName(filepath.Base(m.Path)) | ||||||
|  | 
 | ||||||
|  | 		if checked[dir] { | ||||||
|  | 			paths = append(paths, dir) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	sort.Strings(paths) | ||||||
|  | 
 | ||||||
|  | 	return paths | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // isLibName checks if the specified filename is a library (i.e. ends in `.so*`)
 | ||||||
|  | func isLibName(filename string) bool { | ||||||
|  | 	parts := strings.Split(filename, ".") | ||||||
|  | 
 | ||||||
|  | 	for _, p := range parts { | ||||||
|  | 		if p == "so" { | ||||||
|  | 			return true | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return false | ||||||
|  | } | ||||||
| @ -22,36 +22,33 @@ import ( | |||||||
| 	"github.com/sirupsen/logrus" | 	"github.com/sirupsen/logrus" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | // NewLegacyDiscoverer creates a discoverer for the experimental runtime
 | ||||||
|  | func NewLegacyDiscoverer(logger *logrus.Logger, cfg *Config) (Discover, error) { | ||||||
|  | 	d := legacy{ | ||||||
|  | 		logger: logger, | ||||||
|  | 		lookup: lookup.NewExecutableLocator(logger, cfg.Root), | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return &d, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
| type legacy struct { | type legacy struct { | ||||||
| 	None | 	None | ||||||
| 	logger *logrus.Logger | 	logger *logrus.Logger | ||||||
| 	lookup lookup.Locator | 	lookup lookup.Locator | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const ( |  | ||||||
| 	nvidiaContainerRuntimeHookExecutable = "nvidia-container-runtime-hook" |  | ||||||
| 	hookDefaultFilePath                  = "/usr/bin/nvidia-container-runtime-hook" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| var _ Discover = (*legacy)(nil) | var _ Discover = (*legacy)(nil) | ||||||
| 
 | 
 | ||||||
| // NewLegacyDiscoverer creates a discoverer for the legacy runtime
 | const ( | ||||||
| func NewLegacyDiscoverer(logger *logrus.Logger, root string) (Discover, error) { | 	nvidiaContainerRuntimeHookExecutable      = "nvidia-container-runtime-hook" | ||||||
| 	d := legacy{ | 	nvidiaContainerRuntimeHookDefaultFilePath = "/usr/bin/nvidia-container-runtime-hook" | ||||||
| 		logger: logger, | ) | ||||||
| 		lookup: lookup.NewExecutableLocator(logger, root), |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	return &d, nil | // Hooks returns the "legacy" NVIDIA Container Runtime hook. This mirrors the behaviour of the stable
 | ||||||
| } | // modifier.
 | ||||||
| 
 |  | ||||||
| // Hooks returns the "legacy" NVIDIA Container Runtime hook. This hook calls out
 |  | ||||||
| // to the nvidia-container-cli to make modifications to the container as defined
 |  | ||||||
| // in libnvidia-container.
 |  | ||||||
| func (d legacy) Hooks() ([]Hook, error) { | func (d legacy) Hooks() ([]Hook, error) { | ||||||
| 	var hooks []Hook | 	hookPath := nvidiaContainerRuntimeHookDefaultFilePath | ||||||
| 
 |  | ||||||
| 	hookPath := hookDefaultFilePath |  | ||||||
| 	targets, err := d.lookup.Locate(nvidiaContainerRuntimeHookExecutable) | 	targets, err := d.lookup.Locate(nvidiaContainerRuntimeHookExecutable) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		d.logger.Warnf("Failed to locate %v: %v", nvidiaContainerRuntimeHookExecutable, err) | 		d.logger.Warnf("Failed to locate %v: %v", nvidiaContainerRuntimeHookExecutable, err) | ||||||
| @ -64,11 +61,11 @@ func (d legacy) Hooks() ([]Hook, error) { | |||||||
| 	d.logger.Debugf("Using NVIDIA Container Runtime Hook path %v", hookPath) | 	d.logger.Debugf("Using NVIDIA Container Runtime Hook path %v", hookPath) | ||||||
| 
 | 
 | ||||||
| 	args := []string{hookPath, "prestart"} | 	args := []string{hookPath, "prestart"} | ||||||
| 	legacyHook := Hook{ | 	h := Hook{ | ||||||
| 		Lifecycle: cdi.PrestartHook, | 		Lifecycle: cdi.PrestartHook, | ||||||
| 		Path:      hookPath, | 		Path:      hookPath, | ||||||
| 		Args:      args, | 		Args:      args, | ||||||
| 	} | 	} | ||||||
| 	hooks = append(hooks, legacyHook) | 
 | ||||||
| 	return hooks, nil | 	return []Hook{h}, nil | ||||||
| } | } | ||||||
|  | |||||||
| @ -27,6 +27,15 @@ type list struct { | |||||||
| 
 | 
 | ||||||
| var _ Discover = (*list)(nil) | var _ Discover = (*list)(nil) | ||||||
| 
 | 
 | ||||||
|  | // NewList creates a discoverer that is the composite of a list of discoveres.
 | ||||||
|  | func NewList(d ...Discover) Discover { | ||||||
|  | 	l := list{ | ||||||
|  | 		discoverers: d, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return &l | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // Devices returns all devices from the included discoverers
 | // Devices returns all devices from the included discoverers
 | ||||||
| func (d list) Devices() ([]Device, error) { | func (d list) Devices() ([]Device, error) { | ||||||
| 	var allDevices []Device | 	var allDevices []Device | ||||||
|  | |||||||
| @ -18,6 +18,7 @@ package discover | |||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"sync" | ||||||
| 
 | 
 | ||||||
| 	"github.com/NVIDIA/nvidia-container-toolkit/internal/lookup" | 	"github.com/NVIDIA/nvidia-container-toolkit/internal/lookup" | ||||||
| 	"github.com/sirupsen/logrus" | 	"github.com/sirupsen/logrus" | ||||||
| @ -31,15 +32,25 @@ type mounts struct { | |||||||
| 	logger   *logrus.Logger | 	logger   *logrus.Logger | ||||||
| 	lookup   lookup.Locator | 	lookup   lookup.Locator | ||||||
| 	required []string | 	required []string | ||||||
|  | 	sync.Mutex | ||||||
|  | 	cache []Mount | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| var _ Discover = (*mounts)(nil) | var _ Discover = (*mounts)(nil) | ||||||
| 
 | 
 | ||||||
| func (d mounts) Mounts() ([]Mount, error) { | func (d *mounts) Mounts() ([]Mount, error) { | ||||||
| 	if d.lookup == nil { | 	if d.lookup == nil { | ||||||
| 		return nil, fmt.Errorf("no lookup defined") | 		return nil, fmt.Errorf("no lookup defined") | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	if d.cache != nil { | ||||||
|  | 		d.logger.Debugf("returning cached mounts") | ||||||
|  | 		return d.cache, nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	d.Lock() | ||||||
|  | 	defer d.Unlock() | ||||||
|  | 
 | ||||||
| 	paths := make(map[string]bool) | 	paths := make(map[string]bool) | ||||||
| 
 | 
 | ||||||
| 	for _, candidate := range d.required { | 	for _, candidate := range d.required { | ||||||
| @ -68,5 +79,7 @@ func (d mounts) Mounts() ([]Mount, error) { | |||||||
| 		mounts = append(mounts, mount) | 		mounts = append(mounts, mount) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	d.cache = mounts | ||||||
|  | 
 | ||||||
| 	return mounts, nil | 	return mounts, nil | ||||||
| } | } | ||||||
|  | |||||||
| @ -41,16 +41,17 @@ func TestMounts(t *testing.T) { | |||||||
| 		description    string | 		description    string | ||||||
| 		expectedError  error | 		expectedError  error | ||||||
| 		expectedMounts []Mount | 		expectedMounts []Mount | ||||||
| 		input          mounts | 		input          *mounts | ||||||
| 	}{ | 	}{ | ||||||
| 		{ | 		{ | ||||||
| 			description:   "nill lookup returns error", | 			description:   "nill lookup returns error", | ||||||
| 			expectedError: fmt.Errorf("no lookup defined"), | 			expectedError: fmt.Errorf("no lookup defined"), | ||||||
|  | 			input:         &mounts{}, | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			description:   "empty required returns no mounts", | 			description:   "empty required returns no mounts", | ||||||
| 			expectedError: nil, | 			expectedError: nil, | ||||||
| 			input: mounts{ | 			input: &mounts{ | ||||||
| 				lookup: &lookup.LocatorMock{ | 				lookup: &lookup.LocatorMock{ | ||||||
| 					LocateFunc: func(string) ([]string, error) { | 					LocateFunc: func(string) ([]string, error) { | ||||||
| 						return []string{"located"}, nil | 						return []string{"located"}, nil | ||||||
| @ -61,7 +62,7 @@ func TestMounts(t *testing.T) { | |||||||
| 		{ | 		{ | ||||||
| 			description:   "required returns located", | 			description:   "required returns located", | ||||||
| 			expectedError: nil, | 			expectedError: nil, | ||||||
| 			input: mounts{ | 			input: &mounts{ | ||||||
| 				lookup: &lookup.LocatorMock{ | 				lookup: &lookup.LocatorMock{ | ||||||
| 					LocateFunc: func(string) ([]string, error) { | 					LocateFunc: func(string) ([]string, error) { | ||||||
| 						return []string{"located"}, nil | 						return []string{"located"}, nil | ||||||
| @ -74,7 +75,7 @@ func TestMounts(t *testing.T) { | |||||||
| 		{ | 		{ | ||||||
| 			description:   "mounts removes located duplicates", | 			description:   "mounts removes located duplicates", | ||||||
| 			expectedError: nil, | 			expectedError: nil, | ||||||
| 			input: mounts{ | 			input: &mounts{ | ||||||
| 				lookup: &lookup.LocatorMock{ | 				lookup: &lookup.LocatorMock{ | ||||||
| 					LocateFunc: func(string) ([]string, error) { | 					LocateFunc: func(string) ([]string, error) { | ||||||
| 						return []string{"located"}, nil | 						return []string{"located"}, nil | ||||||
| @ -86,7 +87,7 @@ func TestMounts(t *testing.T) { | |||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			description: "mounts skips located errors", | 			description: "mounts skips located errors", | ||||||
| 			input: mounts{ | 			input: &mounts{ | ||||||
| 				lookup: &lookup.LocatorMock{ | 				lookup: &lookup.LocatorMock{ | ||||||
| 					LocateFunc: func(s string) ([]string, error) { | 					LocateFunc: func(s string) ([]string, error) { | ||||||
| 						if s == "error" { | 						if s == "error" { | ||||||
| @ -101,7 +102,7 @@ func TestMounts(t *testing.T) { | |||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			description: "mounts skips unlocated", | 			description: "mounts skips unlocated", | ||||||
| 			input: mounts{ | 			input: &mounts{ | ||||||
| 				lookup: &lookup.LocatorMock{ | 				lookup: &lookup.LocatorMock{ | ||||||
| 					LocateFunc: func(s string) ([]string, error) { | 					LocateFunc: func(s string) ([]string, error) { | ||||||
| 						if s == "empty" { | 						if s == "empty" { | ||||||
| @ -116,7 +117,7 @@ func TestMounts(t *testing.T) { | |||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			description: "mounts skips unlocated", | 			description: "mounts skips unlocated", | ||||||
| 			input: mounts{ | 			input: &mounts{ | ||||||
| 				lookup: &lookup.LocatorMock{ | 				lookup: &lookup.LocatorMock{ | ||||||
| 					LocateFunc: func(s string) ([]string, error) { | 					LocateFunc: func(s string) ([]string, error) { | ||||||
| 						if s == "multiple" { | 						if s == "multiple" { | ||||||
|  | |||||||
| @ -32,7 +32,7 @@ func (e None) Mounts() ([]Mount, error) { | |||||||
| 	return []Mount{}, nil | 	return []Mount{}, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Hooks returns and empty list of hooks
 | // Hooks returns an empty list of hooks
 | ||||||
| func (e None) Hooks() ([]Hook, error) { | func (e None) Hooks() ([]Hook, error) { | ||||||
| 	return []Hook{}, nil | 	return []Hook{}, nil | ||||||
| } | } | ||||||
|  | |||||||
| @ -52,7 +52,7 @@ func (s *fileSpec) Load() error { | |||||||
| 	} | 	} | ||||||
| 	defer specFile.Close() | 	defer specFile.Close() | ||||||
| 
 | 
 | ||||||
| 	spec, err := loadFrom(specFile) | 	spec, err := LoadFrom(specFile) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return fmt.Errorf("error loading OCI specification from file: %v", err) | 		return fmt.Errorf("error loading OCI specification from file: %v", err) | ||||||
| 	} | 	} | ||||||
| @ -60,8 +60,8 @@ func (s *fileSpec) Load() error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // loadFrom reads the contents of the OCI spec from the specified io.Reader.
 | // LoadFrom reads the contents of the OCI spec from the specified io.Reader.
 | ||||||
| func loadFrom(reader io.Reader) (*specs.Spec, error) { | func LoadFrom(reader io.Reader) (*specs.Spec, error) { | ||||||
| 	decoder := json.NewDecoder(reader) | 	decoder := json.NewDecoder(reader) | ||||||
| 
 | 
 | ||||||
| 	var spec specs.Spec | 	var spec specs.Spec | ||||||
|  | |||||||
| @ -44,7 +44,7 @@ func TestLoadFrom(t *testing.T) { | |||||||
| 
 | 
 | ||||||
| 	for i, tc := range testCases { | 	for i, tc := range testCases { | ||||||
| 		var spec *specs.Spec | 		var spec *specs.Spec | ||||||
| 		spec, err := loadFrom(bytes.NewReader(tc.contents)) | 		spec, err := LoadFrom(bytes.NewReader(tc.contents)) | ||||||
| 
 | 
 | ||||||
| 		if tc.isError { | 		if tc.isError { | ||||||
| 			require.Error(t, err, "%d: %v", i, tc) | 			require.Error(t, err, "%d: %v", i, tc) | ||||||
|  | |||||||
| @ -1,5 +1,6 @@ | |||||||
| nvidia-container-toolkit (1.10.0~rc.1-1) experimental; urgency=medium | nvidia-container-toolkit (1.10.0~rc.1-1) experimental; urgency=medium | ||||||
| 
 | 
 | ||||||
|  |   * Include nvidia-ctk CLI in installed binaries | ||||||
|   * Add experimental option to NVIDIA Container Runtime |   * Add experimental option to NVIDIA Container Runtime | ||||||
| 
 | 
 | ||||||
|  -- NVIDIA CORPORATION <cudatools@nvidia.com>  Thu, 24 Mar 2022 13:22:24 +0200 |  -- NVIDIA CORPORATION <cudatools@nvidia.com>  Thu, 24 Mar 2022 13:22:24 +0200 | ||||||
|  | |||||||
| @ -1,3 +1,4 @@ | |||||||
| config.toml /etc/nvidia-container-runtime | config.toml /etc/nvidia-container-runtime | ||||||
| nvidia-container-toolkit /usr/bin | nvidia-container-toolkit /usr/bin | ||||||
| nvidia-container-runtime /usr/bin | nvidia-container-runtime /usr/bin | ||||||
|  | nvidia-ctk /usr/bin | ||||||
|  | |||||||
| @ -12,10 +12,11 @@ License: Apache-2.0 | |||||||
| 
 | 
 | ||||||
| Source0: nvidia-container-toolkit | Source0: nvidia-container-toolkit | ||||||
| Source1: nvidia-container-runtime | Source1: nvidia-container-runtime | ||||||
| Source2: config.toml | Source2: nvidia-ctk | ||||||
| Source3: oci-nvidia-hook | Source3: config.toml | ||||||
| Source4: oci-nvidia-hook.json | Source4: oci-nvidia-hook | ||||||
| Source5: LICENSE | Source5: oci-nvidia-hook.json | ||||||
|  | Source6: LICENSE | ||||||
| 
 | 
 | ||||||
| Obsoletes: nvidia-container-runtime <= 3.5.0-1, nvidia-container-runtime-hook | Obsoletes: nvidia-container-runtime <= 3.5.0-1, nvidia-container-runtime-hook | ||||||
| Provides: nvidia-container-runtime | Provides: nvidia-container-runtime | ||||||
| @ -33,12 +34,13 @@ Requires: libseccomp | |||||||
| Provides a OCI hook to enable GPU support in containers. | Provides a OCI hook to enable GPU support in containers. | ||||||
| 
 | 
 | ||||||
| %prep | %prep | ||||||
| cp %{SOURCE0} %{SOURCE1} %{SOURCE2} %{SOURCE3} %{SOURCE4} %{SOURCE5} . | cp %{SOURCE0} %{SOURCE1} %{SOURCE2} %{SOURCE3} %{SOURCE4} %{SOURCE5} %{SOURCE6} . | ||||||
| 
 | 
 | ||||||
| %install | %install | ||||||
| mkdir -p %{buildroot}%{_bindir} | mkdir -p %{buildroot}%{_bindir} | ||||||
| install -m 755 -t %{buildroot}%{_bindir} nvidia-container-toolkit | install -m 755 -t %{buildroot}%{_bindir} nvidia-container-toolkit | ||||||
| install -m 755 -t %{buildroot}%{_bindir} nvidia-container-runtime | install -m 755 -t %{buildroot}%{_bindir} nvidia-container-runtime | ||||||
|  | install -m 755 -t %{buildroot}%{_bindir} nvidia-ctk | ||||||
| 
 | 
 | ||||||
| mkdir -p %{buildroot}/etc/nvidia-container-runtime | mkdir -p %{buildroot}/etc/nvidia-container-runtime | ||||||
| install -m 644 -t %{buildroot}/etc/nvidia-container-runtime config.toml | install -m 644 -t %{buildroot}/etc/nvidia-container-runtime config.toml | ||||||
| @ -59,12 +61,14 @@ rm -f %{_bindir}/nvidia-container-runtime-hook | |||||||
| %license LICENSE | %license LICENSE | ||||||
| %{_bindir}/nvidia-container-toolkit | %{_bindir}/nvidia-container-toolkit | ||||||
| %{_bindir}/nvidia-container-runtime | %{_bindir}/nvidia-container-runtime | ||||||
|  | %{_bindir}/nvidia-ctk | ||||||
| %config /etc/nvidia-container-runtime/config.toml | %config /etc/nvidia-container-runtime/config.toml | ||||||
| /usr/libexec/oci/hooks.d/oci-nvidia-hook | /usr/libexec/oci/hooks.d/oci-nvidia-hook | ||||||
| /usr/share/containers/oci/hooks.d/oci-nvidia-hook.json | /usr/share/containers/oci/hooks.d/oci-nvidia-hook.json | ||||||
| 
 | 
 | ||||||
| %changelog | %changelog | ||||||
| * Thu Mar 24 2022 NVIDIA CORPORATION <cudatools@nvidia.com> 1.10.0-0.1.rc.1 | * Thu Mar 24 2022 NVIDIA CORPORATION <cudatools@nvidia.com> 1.10.0-0.1.rc.1 | ||||||
|  | - Include nvidia-ctk CLI in installed binaries | ||||||
| - Add experimental option to NVIDIA Container Runtime | - Add experimental option to NVIDIA Container Runtime | ||||||
| 
 | 
 | ||||||
| * Fri Mar 18 2022 NVIDIA CORPORATION <cudatools@nvidia.com> 1.9.0-1 | * Fri Mar 18 2022 NVIDIA CORPORATION <cudatools@nvidia.com> 1.9.0-1 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user