mirror of
https://github.com/NVIDIA/nvidia-container-toolkit
synced 2025-02-18 10:18:40 +00:00
170 lines
3.9 KiB
Go
170 lines
3.9 KiB
Go
/**
|
|
# Copyright 2024 NVIDIA CORPORATION
|
|
#
|
|
# 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 installer
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"html/template"
|
|
"io"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
"github.com/NVIDIA/nvidia-container-toolkit/tools/container/operator"
|
|
)
|
|
|
|
type executable struct {
|
|
path string
|
|
symlink string
|
|
args []string
|
|
env map[string]string
|
|
}
|
|
|
|
func (t *toolkitInstaller) collectExecutables(destDir string) ([]Installer, error) {
|
|
configHome := filepath.Join(destDir, ".config")
|
|
configDir := filepath.Join(configHome, "nvidia-container-runtime")
|
|
configPath := filepath.Join(configDir, "config.toml")
|
|
|
|
executables := []executable{
|
|
{
|
|
path: "nvidia-ctk",
|
|
},
|
|
{
|
|
path: "nvidia-cdi-hook",
|
|
},
|
|
}
|
|
for _, runtime := range operator.GetRuntimes() {
|
|
e := executable{
|
|
path: runtime.Path,
|
|
env: map[string]string{
|
|
"XDG_CONFIG_HOME": configHome,
|
|
},
|
|
}
|
|
executables = append(executables, e)
|
|
}
|
|
executables = append(executables,
|
|
executable{
|
|
path: "nvidia-container-cli",
|
|
env: map[string]string{"LD_LIBRARY_PATH": destDir + ":$LD_LIBRARY_PATH"},
|
|
},
|
|
)
|
|
|
|
executables = append(executables,
|
|
executable{
|
|
path: "nvidia-container-runtime-hook",
|
|
symlink: "nvidia-container-toolkit",
|
|
args: []string{fmt.Sprintf("-config %s", configPath)},
|
|
},
|
|
)
|
|
|
|
var installers []Installer
|
|
for _, executable := range executables {
|
|
executablePath, err := t.artifactRoot.findExecutable(executable.path)
|
|
if err != nil {
|
|
if t.ignoreErrors {
|
|
log.Errorf("Ignoring error: %v", err)
|
|
continue
|
|
}
|
|
return nil, err
|
|
}
|
|
|
|
wrappedExecutableFilename := filepath.Base(executablePath)
|
|
dotRealFilename := wrappedExecutableFilename + ".real"
|
|
|
|
w := &wrapper{
|
|
Source: executablePath,
|
|
WrappedExecutable: dotRealFilename,
|
|
Args: executable.args,
|
|
Envvars: map[string]string{
|
|
"PATH": strings.Join([]string{destDir, "$PATH"}, ":"),
|
|
},
|
|
}
|
|
for k, v := range executable.env {
|
|
w.Envvars[k] = v
|
|
}
|
|
|
|
installers = append(installers, w)
|
|
|
|
if executable.symlink == "" {
|
|
continue
|
|
}
|
|
link := symlink{
|
|
linkname: executable.symlink,
|
|
target: filepath.Base(executablePath),
|
|
}
|
|
installers = append(installers, link)
|
|
}
|
|
|
|
return installers, nil
|
|
|
|
}
|
|
|
|
type wrapper struct {
|
|
Source string
|
|
Envvars map[string]string
|
|
WrappedExecutable string
|
|
Args []string
|
|
}
|
|
|
|
func (w *wrapper) Install(destDir string) error {
|
|
// Copy the executable with a .real extension.
|
|
mode, err := installFile(w.Source, filepath.Join(destDir, w.WrappedExecutable))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Create a wrapper file.
|
|
content, err := w.render()
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
wrapperFile := filepath.Join(destDir, filepath.Base(w.Source))
|
|
return installContent(content, wrapperFile, mode|0111)
|
|
}
|
|
|
|
func (w *wrapper) render() (io.Reader, error) {
|
|
wrapperTemplate := `#! /bin/sh
|
|
|
|
cat /proc/modules | grep -e \"^nvidia \" >/dev/null 2>&1
|
|
if [ "${?}" != "0" ]; then
|
|
echo "nvidia driver modules are not yet loaded, invoking runc directly"
|
|
exec runc "$@"
|
|
fi
|
|
{{- range $key, $value := .Envvars }}
|
|
{{$key}}={{$value}} \
|
|
{{- end }}
|
|
{{ .WrappedExecutable }} \
|
|
{{- range $arg := .Args }}
|
|
{{$arg}} \
|
|
{{- end }}
|
|
"$@"
|
|
`
|
|
|
|
var content bytes.Buffer
|
|
tmpl, err := template.New("wrapper").Parse(wrapperTemplate)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err := tmpl.Execute(&content, w); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &content, nil
|
|
}
|