mirror of
				https://github.com/NVIDIA/nvidia-container-toolkit
				synced 2025-06-26 18:18:24 +00:00 
			
		
		
		
	Merge branch 'CNT-2875/create-specific-symlinks' into 'main'
Create specific symlinks for CSV mode See merge request nvidia/container-toolkit/container-toolkit!150
This commit is contained in:
		
						commit
						ae57a2fc93
					
				| @ -109,7 +109,7 @@ func NewExperimentalModifier(logger *logrus.Logger, cfg *config.Config, ociSpec | ||||
| 			return nil, fmt.Errorf("failed to create ldcach update hook discoverer: %v", err) | ||||
| 		} | ||||
| 
 | ||||
| 		createSymlinksHook, err := discover.NewCreateSymlinksHook(logger, csvFiles, config) | ||||
| 		createSymlinksHook, err := discover.NewCreateSymlinksHook(logger, csvFiles, csvDiscoverer, config) | ||||
| 		if err != nil { | ||||
| 			return nil, fmt.Errorf("failed to create symlink hook discoverer: %v", err) | ||||
| 		} | ||||
|  | ||||
| @ -20,6 +20,7 @@ import ( | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	"github.com/NVIDIA/nvidia-container-toolkit/internal/discover/csv" | ||||
| 	"github.com/NVIDIA/nvidia-container-toolkit/internal/lookup" | ||||
| @ -35,6 +36,7 @@ type command struct { | ||||
| type config struct { | ||||
| 	hostRoot      string | ||||
| 	filenames     cli.StringSlice | ||||
| 	links         cli.StringSlice | ||||
| 	containerSpec string | ||||
| } | ||||
| 
 | ||||
| @ -70,6 +72,11 @@ func (m command) build() *cli.Command { | ||||
| 			Usage:       "Specify a (CSV) filename to process", | ||||
| 			Destination: &cfg.filenames, | ||||
| 		}, | ||||
| 		&cli.StringSliceFlag{ | ||||
| 			Name:        "link", | ||||
| 			Usage:       "Specify a specific link to create. The link is specified as source:target", | ||||
| 			Destination: &cfg.links, | ||||
| 		}, | ||||
| 		&cli.StringFlag{ | ||||
| 			Name:        "container-spec", | ||||
| 			Usage:       "Specify the path to the OCI container spec. If empty or '-' the spec will be read from STDIN", | ||||
| @ -129,40 +136,59 @@ func (m command) run(c *cli.Context, cfg *config) error { | ||||
| 			m.logger.Debugf("%v is not a symlink", candidate) | ||||
| 			continue | ||||
| 		} | ||||
| 		target, err := changeRoot(cfg.hostRoot, "/", targets[0]) | ||||
| 
 | ||||
| 		err = m.createLink(created, cfg.hostRoot, containerRoot, targets[0], candidate) | ||||
| 		if err != nil { | ||||
| 			m.logger.Warnf("Failed to resolve path for target %v relative to %v: %v", target, cfg.hostRoot, err) | ||||
| 			m.logger.Warnf("Failed to create link %v: %v", []string{targets[0], candidate}, err) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	links := cfg.links.Value() | ||||
| 	for _, l := range links { | ||||
| 		parts := strings.Split(l, ":") | ||||
| 		if len(parts) != 2 { | ||||
| 			m.logger.Warnf("Invalid link specification %v", l) | ||||
| 			continue | ||||
| 		} | ||||
| 
 | ||||
| 		linkPath, err := changeRoot(cfg.hostRoot, containerRoot, candidate) | ||||
| 		err := m.createLink(created, cfg.hostRoot, containerRoot, parts[0], parts[1]) | ||||
| 		if err != nil { | ||||
| 			m.logger.Warnf("Failed to resolve path for link %v relative to %v: %v", candidate, cfg.hostRoot, err) | ||||
| 			continue | ||||
| 			m.logger.Warnf("Failed to create link %v: %v", parts, err) | ||||
| 		} | ||||
| 
 | ||||
| 		if created[linkPath] { | ||||
| 			m.logger.Debugf("Link %v already created", linkPath) | ||||
| 			continue | ||||
| 		} | ||||
| 		m.logger.Infof("Symlinking %v to %v", linkPath, target) | ||||
| 		err = os.MkdirAll(filepath.Dir(linkPath), 0755) | ||||
| 		if err != nil { | ||||
| 			m.logger.Warnf("Faild to create directory: %v", err) | ||||
| 			continue | ||||
| 		} | ||||
| 		err = os.Symlink(target, linkPath) | ||||
| 		if err != nil { | ||||
| 			m.logger.Warnf("Failed to create symlink: %v", err) | ||||
| 			continue | ||||
| 		} | ||||
| 		created[linkPath] = true | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| func (m command) createLink(created map[string]bool, hostRoot string, containerRoot string, target string, link string) error { | ||||
| 	linkPath, err := changeRoot(hostRoot, containerRoot, link) | ||||
| 	if err != nil { | ||||
| 		m.logger.Warnf("Failed to resolve path for link %v relative to %v: %v", link, containerRoot, err) | ||||
| 	} | ||||
| 	if created[linkPath] { | ||||
| 		m.logger.Debugf("Link %v already created", linkPath) | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	targetPath, err := changeRoot(hostRoot, "/", target) | ||||
| 	if err != nil { | ||||
| 		m.logger.Warnf("Failed to resolve path for target %v relative to %v: %v", target, "/", err) | ||||
| 	} | ||||
| 
 | ||||
| 	m.logger.Infof("Symlinking %v to %v", linkPath, targetPath) | ||||
| 	err = os.MkdirAll(filepath.Dir(linkPath), 0755) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("failed to create directory: %v", err) | ||||
| 	} | ||||
| 	err = os.Symlink(target, linkPath) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("failed to create symlink: %v", err) | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func changeRoot(current string, new string, path string) (string, error) { | ||||
| 	if !filepath.IsAbs(path) { | ||||
| 		return path, nil | ||||
|  | ||||
| @ -17,6 +17,10 @@ | ||||
| package discover | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"path/filepath" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	"github.com/NVIDIA/nvidia-container-toolkit/internal/lookup" | ||||
| 	"github.com/container-orchestrated-devices/container-device-interface/pkg/cdi" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| @ -28,15 +32,17 @@ type symlinks struct { | ||||
| 	lookup                  lookup.Locator | ||||
| 	nvidiaCTKExecutablePath string | ||||
| 	csvFiles                []string | ||||
| 	mountsFrom              Discover | ||||
| } | ||||
| 
 | ||||
| // NewCreateSymlinksHook creates a discoverer for a hook that creates required symlinks in the container
 | ||||
| func NewCreateSymlinksHook(logger *logrus.Logger, csvFiles []string, cfg *Config) (Discover, error) { | ||||
| func NewCreateSymlinksHook(logger *logrus.Logger, csvFiles []string, mounts Discover, cfg *Config) (Discover, error) { | ||||
| 	d := symlinks{ | ||||
| 		logger:                  logger, | ||||
| 		lookup:                  lookup.NewExecutableLocator(logger, cfg.Root), | ||||
| 		nvidiaCTKExecutablePath: cfg.NVIDIAContainerToolkitCLIExecutablePath, | ||||
| 		csvFiles:                csvFiles, | ||||
| 		mountsFrom:              mounts, | ||||
| 	} | ||||
| 
 | ||||
| 	return &d, nil | ||||
| @ -61,6 +67,12 @@ func (d symlinks) Hooks() ([]Hook, error) { | ||||
| 		args = append(args, "--csv-filename", f) | ||||
| 	} | ||||
| 
 | ||||
| 	links, err := d.getSpecificLinkArgs() | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("failed to determine specific links: %v", err) | ||||
| 	} | ||||
| 	args = append(args, links...) | ||||
| 
 | ||||
| 	h := Hook{ | ||||
| 		Lifecycle: cdi.CreateContainerHook, | ||||
| 		Path:      hookPath, | ||||
| @ -69,3 +81,45 @@ func (d symlinks) Hooks() ([]Hook, error) { | ||||
| 
 | ||||
| 	return []Hook{h}, nil | ||||
| } | ||||
| 
 | ||||
| // getSpecificLinkArgs returns the required specic links that need to be created
 | ||||
| func (d symlinks) getSpecificLinkArgs() ([]string, error) { | ||||
| 	mounts, err := d.mountsFrom.Mounts() | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("failed to discover mounts for ldcache update: %v", err) | ||||
| 	} | ||||
| 
 | ||||
| 	linkProcessed := make(map[string]bool) | ||||
| 	var links []string | ||||
| 	for _, m := range mounts { | ||||
| 		var target string | ||||
| 		var link string | ||||
| 
 | ||||
| 		lib := filepath.Base(m.Path) | ||||
| 
 | ||||
| 		if strings.HasPrefix(lib, "libcuda.so") { | ||||
| 			// XXX Many applications wrongly assume that libcuda.so exists (e.g. with dlopen).
 | ||||
| 			target = "libcuda.so.1" | ||||
| 			link = "libcuda.so" | ||||
| 		} else if strings.HasPrefix(lib, "libGLX_nvidia.so") { | ||||
| 			// XXX GLVND requires this symlink for indirect GLX support.
 | ||||
| 			target = lib | ||||
| 			link = "libGLX_indirect.so.0" | ||||
| 		} else if strings.HasPrefix(lib, "libnvidia-opticalflow.so") { | ||||
| 			// XXX Fix missing symlink for libnvidia-opticalflow.so.
 | ||||
| 			target = "libnvidia-opticalflow.so.1" | ||||
| 			link = "libnvidia-opticalflow.so" | ||||
| 		} else { | ||||
| 			continue | ||||
| 		} | ||||
| 		if linkProcessed[link] { | ||||
| 			continue | ||||
| 		} | ||||
| 
 | ||||
| 		linkPath := filepath.Join(filepath.Dir(m.Path), link) | ||||
| 		links = append(links, "--link", fmt.Sprintf("%v:%v", target, linkPath)) | ||||
| 		linkProcessed[link] = true | ||||
| 	} | ||||
| 
 | ||||
| 	return links, nil | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user