mirror of
				https://github.com/NVIDIA/nvidia-container-toolkit
				synced 2025-06-26 18:18:24 +00:00 
			
		
		
		
	Migrate cri-o config update to engine.Interface
Signed-off-by: Evan Lezar <elezar@nvidia.com>
This commit is contained in:
		
							parent
							
								
									9fff19da23
								
							
						
					
					
						commit
						3bac4fad09
					
				| @ -173,13 +173,14 @@ func (m command) configureCrio(c *cli.Context, config *config) error { | |||||||
| 		configFilePath = defaultCrioConfigFilePath | 		configFilePath = defaultCrioConfigFilePath | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	cfg, err := crio.LoadConfig(configFilePath) | 	cfg, err := crio.New( | ||||||
|  | 		crio.WithPath(configFilePath), | ||||||
|  | 	) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return fmt.Errorf("unable to load config: %v", err) | 		return fmt.Errorf("unable to load config: %v", err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err = crio.UpdateConfig( | 	err = cfg.AddRuntime( | ||||||
| 		cfg, |  | ||||||
| 		config.nvidiaOptions.RuntimeName, | 		config.nvidiaOptions.RuntimeName, | ||||||
| 		config.nvidiaOptions.RuntimePath, | 		config.nvidiaOptions.RuntimePath, | ||||||
| 		config.nvidiaOptions.SetAsDefault, | 		config.nvidiaOptions.SetAsDefault, | ||||||
| @ -196,12 +197,16 @@ func (m command) configureCrio(c *cli.Context, config *config) error { | |||||||
| 		os.Stdout.WriteString(fmt.Sprintf("%s\n", output)) | 		os.Stdout.WriteString(fmt.Sprintf("%s\n", output)) | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
| 	err = crio.FlushConfig(configFilePath, cfg) | 	n, err := cfg.Save(configFilePath) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return fmt.Errorf("unable to flush config: %v", err) | 		return fmt.Errorf("unable to flush config: %v", err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	m.logger.Infof("Wrote updated config to %v", configFilePath) | 	if n == 0 { | ||||||
|  | 		m.logger.Infof("Removed empty config from %v", configFilePath) | ||||||
|  | 	} else { | ||||||
|  | 		m.logger.Infof("Wrote updated config to %v", configFilePath) | ||||||
|  | 	} | ||||||
| 	m.logger.Infof("It is recommended that the cri-o daemon be restarted.") | 	m.logger.Infof("It is recommended that the cri-o daemon be restarted.") | ||||||
| 
 | 
 | ||||||
| 	return nil | 	return nil | ||||||
|  | |||||||
| @ -20,62 +20,71 @@ import ( | |||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"os" | 	"os" | ||||||
| 
 | 
 | ||||||
|  | 	"github.com/NVIDIA/nvidia-container-toolkit/internal/config/engine" | ||||||
| 	"github.com/pelletier/go-toml" | 	"github.com/pelletier/go-toml" | ||||||
| 	log "github.com/sirupsen/logrus" |  | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // LoadConfig loads the cri-o config from disk
 | // Config represents the cri-o config
 | ||||||
| func LoadConfig(config string) (*toml.Tree, error) { | type Config toml.Tree | ||||||
| 	log.Infof("Loading config: %v", config) |  | ||||||
| 
 | 
 | ||||||
| 	info, err := os.Stat(config) | // New creates a cri-o config with the specified options
 | ||||||
| 	if os.IsExist(err) && info.IsDir() { | func New(opts ...Option) (engine.Interface, error) { | ||||||
| 		return nil, fmt.Errorf("config file is a directory") | 	b := &builder{} | ||||||
|  | 	for _, opt := range opts { | ||||||
|  | 		opt(b) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	configFile := config | 	return b.build() | ||||||
| 	if os.IsNotExist(err) { |  | ||||||
| 		configFile = "/dev/null" |  | ||||||
| 		log.Infof("Config file does not exist, creating new one") |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	cfg, err := toml.LoadFile(configFile) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	log.Infof("Successfully loaded config") |  | ||||||
| 
 |  | ||||||
| 	return cfg, nil |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // UpdateConfig updates the cri-o config to include the NVIDIA Container Runtime
 | // AddRuntime adds a new runtime to the crio config
 | ||||||
| func UpdateConfig(config *toml.Tree, runtimeClass string, runtimePath string, setAsDefault bool) error { | func (c *Config) AddRuntime(name string, path string, setAsDefault bool) error { | ||||||
|  | 	if c == nil { | ||||||
|  | 		return fmt.Errorf("config is nil") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	config := (toml.Tree)(*c) | ||||||
|  | 
 | ||||||
| 	switch runc := config.Get("crio.runtime.runtimes.runc").(type) { | 	switch runc := config.Get("crio.runtime.runtimes.runc").(type) { | ||||||
| 	case *toml.Tree: | 	case *toml.Tree: | ||||||
| 		runc, _ = toml.Load(runc.String()) | 		runc, _ = toml.Load(runc.String()) | ||||||
| 		config.SetPath([]string{"crio", "runtime", "runtimes", runtimeClass}, runc) | 		config.SetPath([]string{"crio", "runtime", "runtimes", name}, runc) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	config.SetPath([]string{"crio", "runtime", "runtimes", runtimeClass, "runtime_path"}, runtimePath) | 	config.SetPath([]string{"crio", "runtime", "runtimes", name, "runtime_path"}, path) | ||||||
| 	config.SetPath([]string{"crio", "runtime", "runtimes", runtimeClass, "runtime_type"}, "oci") | 	config.SetPath([]string{"crio", "runtime", "runtimes", name, "runtime_type"}, "oci") | ||||||
| 
 | 
 | ||||||
| 	if setAsDefault { | 	if setAsDefault { | ||||||
| 		config.SetPath([]string{"crio", "runtime", "default_runtime"}, runtimeClass) | 		config.SetPath([]string{"crio", "runtime", "default_runtime"}, name) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	*c = (Config)(config) | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // RevertConfig reverts the cri-o config to remove the NVIDIA Container Runtime
 | // DefaultRuntime returns the default runtime for the cri-o config
 | ||||||
| func RevertConfig(config *toml.Tree, runtimeClass string) error { | func (c Config) DefaultRuntime() string { | ||||||
|  | 	config := (toml.Tree)(c) | ||||||
| 	if runtime, ok := config.GetPath([]string{"crio", "runtime", "default_runtime"}).(string); ok { | 	if runtime, ok := config.GetPath([]string{"crio", "runtime", "default_runtime"}).(string); ok { | ||||||
| 		if runtimeClass == runtime { | 		return runtime | ||||||
|  | 	} | ||||||
|  | 	return "" | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // RemoveRuntime removes a runtime from the cri-o config
 | ||||||
|  | func (c *Config) RemoveRuntime(name string) error { | ||||||
|  | 	if c == nil { | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	config := (toml.Tree)(*c) | ||||||
|  | 	if runtime, ok := config.GetPath([]string{"crio", "runtime", "default_runtime"}).(string); ok { | ||||||
|  | 		if runtime == name { | ||||||
| 			config.DeletePath([]string{"crio", "runtime", "default_runtime"}) | 			config.DeletePath([]string{"crio", "runtime", "default_runtime"}) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	runtimeClassPath := []string{"crio", "runtime", "runtimes", runtimeClass} | 	runtimeClassPath := []string{"crio", "runtime", "runtimes", name} | ||||||
| 	config.DeletePath(runtimeClassPath) | 	config.DeletePath(runtimeClassPath) | ||||||
| 	for i := 0; i < len(runtimeClassPath); i++ { | 	for i := 0; i < len(runtimeClassPath); i++ { | ||||||
| 		remainingPath := runtimeClassPath[:len(runtimeClassPath)-i] | 		remainingPath := runtimeClassPath[:len(runtimeClassPath)-i] | ||||||
| @ -87,39 +96,36 @@ func RevertConfig(config *toml.Tree, runtimeClass string) error { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	*c = (Config)(config) | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // FlushConfig flushes the updated/reverted config out to disk
 | // Save writes the config to the specified path
 | ||||||
| func FlushConfig(config string, cfg *toml.Tree) error { | func (c Config) Save(path string) (int64, error) { | ||||||
| 	log.Infof("Flushing config") | 	config := (toml.Tree)(c) | ||||||
| 
 | 	output, err := config.ToTomlString() | ||||||
| 	output, err := cfg.ToTomlString() |  | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return fmt.Errorf("unable to convert to TOML: %v", err) | 		return 0, fmt.Errorf("unable to convert to TOML: %v", err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	switch len(output) { | 	if len(output) == 0 { | ||||||
| 	case 0: | 		err := os.Remove(path) | ||||||
| 		err := os.Remove(config) |  | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return fmt.Errorf("unable to remove empty file: %v", err) | 			return 0, fmt.Errorf("unable to remove empty file: %v", err) | ||||||
| 		} |  | ||||||
| 		log.Infof("Config empty, removing file") |  | ||||||
| 	default: |  | ||||||
| 		f, err := os.Create(config) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return fmt.Errorf("unable to open '%v' for writing: %v", config, err) |  | ||||||
| 		} |  | ||||||
| 		defer f.Close() |  | ||||||
| 
 |  | ||||||
| 		_, err = f.WriteString(output) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return fmt.Errorf("unable to write output: %v", err) |  | ||||||
| 		} | 		} | ||||||
|  | 		return 0, nil | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	log.Infof("Successfully flushed config") | 	f, err := os.Create(path) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return 0, fmt.Errorf("unable to open '%v' for writing: %v", path, err) | ||||||
|  | 	} | ||||||
|  | 	defer f.Close() | ||||||
| 
 | 
 | ||||||
| 	return nil | 	n, err := f.WriteString(output) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return 0, fmt.Errorf("unable to write output: %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return int64(n), err | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										73
									
								
								internal/config/engine/crio/option.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								internal/config/engine/crio/option.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,73 @@ | |||||||
|  | /** | ||||||
|  | # Copyright (c) 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 crio | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"os" | ||||||
|  | 
 | ||||||
|  | 	"github.com/pelletier/go-toml" | ||||||
|  | 	log "github.com/sirupsen/logrus" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type builder struct { | ||||||
|  | 	path string | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Option defines a function that can be used to configure the config builder
 | ||||||
|  | type Option func(*builder) | ||||||
|  | 
 | ||||||
|  | // WithPath sets the path for the config builder
 | ||||||
|  | func WithPath(path string) Option { | ||||||
|  | 	return func(b *builder) { | ||||||
|  | 		b.path = path | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (b *builder) build() (*Config, error) { | ||||||
|  | 	if b.path == "" { | ||||||
|  | 		empty := toml.Tree{} | ||||||
|  | 		return (*Config)(&empty), nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return loadConfig(b.path) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // loadConfig loads the cri-o config from disk
 | ||||||
|  | func loadConfig(config string) (*Config, error) { | ||||||
|  | 	log.Infof("Loading config: %v", config) | ||||||
|  | 
 | ||||||
|  | 	info, err := os.Stat(config) | ||||||
|  | 	if os.IsExist(err) && info.IsDir() { | ||||||
|  | 		return nil, fmt.Errorf("config file is a directory") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	configFile := config | ||||||
|  | 	if os.IsNotExist(err) { | ||||||
|  | 		configFile = "/dev/null" | ||||||
|  | 		log.Infof("Config file does not exist, creating new one") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	cfg, err := toml.LoadFile(configFile) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	log.Infof("Successfully loaded config") | ||||||
|  | 
 | ||||||
|  | 	return (*Config)(cfg), nil | ||||||
|  | } | ||||||
| @ -24,8 +24,9 @@ import ( | |||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
| 
 | 
 | ||||||
| 	"github.com/NVIDIA/nvidia-container-toolkit/internal/config" | 	"github.com/NVIDIA/nvidia-container-toolkit/internal/config" | ||||||
|  | 	"github.com/NVIDIA/nvidia-container-toolkit/internal/config/engine" | ||||||
| 	"github.com/NVIDIA/nvidia-container-toolkit/internal/config/engine/crio" | 	"github.com/NVIDIA/nvidia-container-toolkit/internal/config/engine/crio" | ||||||
| 	"github.com/pelletier/go-toml" | 	"github.com/NVIDIA/nvidia-container-toolkit/tools/container/operator" | ||||||
| 	log "github.com/sirupsen/logrus" | 	log "github.com/sirupsen/logrus" | ||||||
| 	cli "github.com/urfave/cli/v2" | 	cli "github.com/urfave/cli/v2" | ||||||
| ) | ) | ||||||
| @ -213,7 +214,9 @@ func setupHook(o *options) error { | |||||||
| func setupConfig(o *options) error { | func setupConfig(o *options) error { | ||||||
| 	log.Infof("Updating config file") | 	log.Infof("Updating config file") | ||||||
| 
 | 
 | ||||||
| 	cfg, err := crio.LoadConfig(o.config) | 	cfg, err := crio.New( | ||||||
|  | 		crio.WithPath(o.config), | ||||||
|  | 	) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return fmt.Errorf("unable to load config: %v", err) | 		return fmt.Errorf("unable to load config: %v", err) | ||||||
| 	} | 	} | ||||||
| @ -223,10 +226,14 @@ func setupConfig(o *options) error { | |||||||
| 		return fmt.Errorf("unable to update config: %v", err) | 		return fmt.Errorf("unable to update config: %v", err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err = crio.FlushConfig(o.config, cfg) | 	log.Infof("Flushing cri-o config to %v", o.config) | ||||||
|  | 	n, err := cfg.Save(o.config) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return fmt.Errorf("unable to flush config: %v", err) | 		return fmt.Errorf("unable to flush config: %v", err) | ||||||
| 	} | 	} | ||||||
|  | 	if n == 0 { | ||||||
|  | 		log.Infof("Config file is empty, removed") | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	err = RestartCrio(o) | 	err = RestartCrio(o) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| @ -267,7 +274,9 @@ func cleanupHook(o *options) error { | |||||||
| func cleanupConfig(o *options) error { | func cleanupConfig(o *options) error { | ||||||
| 	log.Infof("Reverting config file modifications") | 	log.Infof("Reverting config file modifications") | ||||||
| 
 | 
 | ||||||
| 	cfg, err := crio.LoadConfig(o.config) | 	cfg, err := crio.New( | ||||||
|  | 		crio.WithPath(o.config), | ||||||
|  | 	) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return fmt.Errorf("unable to load config: %v", err) | 		return fmt.Errorf("unable to load config: %v", err) | ||||||
| 	} | 	} | ||||||
| @ -277,10 +286,14 @@ func cleanupConfig(o *options) error { | |||||||
| 		return fmt.Errorf("unable to update config: %v", err) | 		return fmt.Errorf("unable to update config: %v", err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err = crio.FlushConfig(o.config, cfg) | 	log.Infof("Flushing cri-o config to %v", o.config) | ||||||
|  | 	n, err := cfg.Save(o.config) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return fmt.Errorf("unable to flush config: %v", err) | 		return fmt.Errorf("unable to flush config: %v", err) | ||||||
| 	} | 	} | ||||||
|  | 	if n == 0 { | ||||||
|  | 		log.Infof("Config file is empty, removed") | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	err = RestartCrio(o) | 	err = RestartCrio(o) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| @ -345,14 +358,36 @@ func generateOciHook(toolkitDir string) podmanHook { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // UpdateConfig updates the cri-o config to include the NVIDIA Container Runtime
 | // UpdateConfig updates the cri-o config to include the NVIDIA Container Runtime
 | ||||||
| func UpdateConfig(config *toml.Tree, o *options) error { | func UpdateConfig(cfg engine.Interface, o *options) error { | ||||||
| 	runtimePath := filepath.Join(o.runtimeDir, "nvidia-container-runtime") | 	runtimes := operator.GetRuntimes( | ||||||
| 	return crio.UpdateConfig(config, o.runtimeClass, runtimePath, o.setAsDefault) | 		operator.WithNvidiaRuntimeName(o.runtimeClass), | ||||||
|  | 		operator.WithSetAsDefault(o.setAsDefault), | ||||||
|  | 		operator.WithRoot(o.runtimeDir), | ||||||
|  | 	) | ||||||
|  | 	for class, runtime := range runtimes { | ||||||
|  | 		err := cfg.AddRuntime(class, runtime.Path, runtime.SetAsDefault) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return fmt.Errorf("unable to update config for runtime class '%v': %v", class, err) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // RevertConfig reverts the cri-o config to remove the NVIDIA Container Runtime
 | // RevertConfig reverts the cri-o config to remove the NVIDIA Container Runtime
 | ||||||
| func RevertConfig(config *toml.Tree, o *options) error { | func RevertConfig(cfg engine.Interface, o *options) error { | ||||||
| 	return crio.RevertConfig(config, o.runtimeClass) | 	runtimes := operator.GetRuntimes( | ||||||
|  | 		operator.WithNvidiaRuntimeName(o.runtimeClass), | ||||||
|  | 		operator.WithSetAsDefault(o.setAsDefault), | ||||||
|  | 		operator.WithRoot(o.runtimeDir), | ||||||
|  | 	) | ||||||
|  | 	for class := range runtimes { | ||||||
|  | 		err := cfg.RemoveRuntime(class) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return fmt.Errorf("unable to revert config for runtime class '%v': %v", class, err) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // RestartCrio restarts crio depending on the value of restartModeFlag
 | // RestartCrio restarts crio depending on the value of restartModeFlag
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user