mirror of
https://github.com/NVIDIA/nvidia-container-toolkit
synced 2025-02-23 20:53:27 +00:00
119 lines
2.9 KiB
Go
119 lines
2.9 KiB
Go
/*
|
|
* Copyright (c) 2025, 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 e2e
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"text/template"
|
|
)
|
|
|
|
// dockerInstallTemplate is a template for installing the NVIDIA Container Toolkit
|
|
// on a host using Docker.
|
|
var dockerInstallTemplate = `
|
|
#! /usr/bin/env bash
|
|
set -xe
|
|
|
|
: ${IMAGE:={{.Image}}}
|
|
|
|
# Create a temporary directory
|
|
TEMP_DIR="/tmp/ctk_e2e.$(date +%s)_$RANDOM"
|
|
mkdir -p "$TEMP_DIR"
|
|
|
|
# Given that docker has an init function that checks for the existence of the
|
|
# nvidia-container-toolkit, we need to create a symlink to the nvidia-container-runtime-hook
|
|
# in the /usr/bin directory.
|
|
# See https://github.com/moby/moby/blob/20a05dabf44934447d1a66cdd616cc803b81d4e2/daemon/nvidia_linux.go#L32-L46
|
|
sudo rm -f /usr/bin/nvidia-container-runtime-hook
|
|
sudo ln -s "$TEMP_DIR/toolkit/nvidia-container-runtime-hook" /usr/bin/nvidia-container-runtime-hook
|
|
|
|
docker run --pid=host --rm -i --privileged \
|
|
-v /:/host \
|
|
-v /var/run/docker.sock:/var/run/docker.sock \
|
|
-v "$TEMP_DIR:$TEMP_DIR" \
|
|
-v /etc/docker:/config-root \
|
|
${IMAGE} \
|
|
--root "$TEMP_DIR" \
|
|
--runtime=docker \
|
|
--config=/config-root/daemon.json \
|
|
--driver-root=/ \
|
|
--no-daemon \
|
|
--restart-mode=systemd
|
|
`
|
|
|
|
type ToolkitInstaller struct {
|
|
runner Runner
|
|
template string
|
|
|
|
Image string
|
|
}
|
|
|
|
type installerOption func(*ToolkitInstaller)
|
|
|
|
func WithRunner(r Runner) installerOption {
|
|
return func(i *ToolkitInstaller) {
|
|
i.runner = r
|
|
}
|
|
}
|
|
|
|
func WithImage(image string) installerOption {
|
|
return func(i *ToolkitInstaller) {
|
|
i.Image = image
|
|
}
|
|
}
|
|
|
|
func WithTemplate(template string) installerOption {
|
|
return func(i *ToolkitInstaller) {
|
|
i.template = template
|
|
}
|
|
}
|
|
|
|
func NewToolkitInstaller(opts ...installerOption) (*ToolkitInstaller, error) {
|
|
i := &ToolkitInstaller{
|
|
runner: localRunner{},
|
|
template: dockerInstallTemplate,
|
|
}
|
|
|
|
for _, opt := range opts {
|
|
opt(i)
|
|
}
|
|
|
|
if i.Image == "" {
|
|
return nil, fmt.Errorf("image is required")
|
|
}
|
|
|
|
return i, nil
|
|
}
|
|
|
|
func (i *ToolkitInstaller) Install() error {
|
|
// Parse the combined template
|
|
tmpl, err := template.New("installScript").Parse(i.template)
|
|
if err != nil {
|
|
return fmt.Errorf("error parsing template: %w", err)
|
|
}
|
|
|
|
// Execute the template
|
|
var renderedScript bytes.Buffer
|
|
err = tmpl.Execute(&renderedScript, i)
|
|
if err != nil {
|
|
return fmt.Errorf("error executing template: %w", err)
|
|
}
|
|
|
|
_, _, err = i.runner.Run(renderedScript.String())
|
|
return err
|
|
}
|