mirror of
https://github.com/NVIDIA/nvidia-container-toolkit
synced 2025-06-23 02:06:44 +00:00
Add discovery for ldconfig hook that updates the LDCache
This change adds a discovered hook for updating the ldcache as a container-create hook. The mounts from a discoverer are inspected to determine the folders that must be added to the cache using the nvidia-ctk hook update-ldcache command. This is added to the "csv" discovery mode for the experimental runtime. Signed-off-by: Evan Lezar <elezar@nvidia.com>
This commit is contained in:
parent
740bd3fb9d
commit
d970d0a627
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
}
|
@ -23,10 +23,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// NewLegacyDiscoverer creates a discoverer for the experimental runtime
|
// NewLegacyDiscoverer creates a discoverer for the experimental runtime
|
||||||
func NewLegacyDiscoverer(logger *logrus.Logger, root string) (Discover, error) {
|
func NewLegacyDiscoverer(logger *logrus.Logger, cfg *Config) (Discover, error) {
|
||||||
d := legacy{
|
d := legacy{
|
||||||
logger: logger,
|
logger: logger,
|
||||||
lookup: lookup.NewExecutableLocator(logger, root),
|
lookup: lookup.NewExecutableLocator(logger, cfg.Root),
|
||||||
}
|
}
|
||||||
|
|
||||||
return &d, nil
|
return &d, 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
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user