Merge branch 'cdi-executable' into 'main'

Add nvidia-container-runtime.{{MODE}} executable that overrides runtime mode

See merge request nvidia/container-toolkit/container-toolkit!288
This commit is contained in:
Evan Lezar 2023-02-14 08:01:41 +00:00
commit dc4887cd44
17 changed files with 330 additions and 122 deletions

2
.gitignore vendored
View File

@ -1,9 +1,11 @@
dist dist
artifacts
*.swp *.swp
*.swo *.swo
/coverage.out* /coverage.out*
/test/output/ /test/output/
/nvidia-container-runtime /nvidia-container-runtime
/nvidia-container-runtime.*
/nvidia-container-runtime-hook /nvidia-container-runtime-hook
/nvidia-container-toolkit /nvidia-container-toolkit
/nvidia-ctk /nvidia-ctk

View File

@ -0,0 +1,34 @@
/**
# 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 main
import (
"os"
"github.com/NVIDIA/nvidia-container-toolkit/internal/runtime"
)
func main() {
rt := runtime.New(
runtime.WithModeOverride("cdi"),
)
err := rt.Run(os.Args)
if err != nil {
os.Exit(1)
}
}

View File

@ -0,0 +1,34 @@
/**
# 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 main
import (
"os"
"github.com/NVIDIA/nvidia-container-toolkit/internal/runtime"
)
func main() {
rt := runtime.New(
runtime.WithModeOverride("legacy"),
)
err := rt.Run(os.Args)
if err != nil {
os.Exit(1)
}
}

View File

@ -1,89 +1,15 @@
package main package main
import ( import (
"fmt"
"os" "os"
"strings"
"github.com/NVIDIA/nvidia-container-toolkit/internal/config" "github.com/NVIDIA/nvidia-container-toolkit/internal/runtime"
"github.com/NVIDIA/nvidia-container-toolkit/internal/info"
"github.com/opencontainers/runtime-spec/specs-go"
) )
// version must be set by go build's -X main.version= option in the Makefile.
var version = "unknown"
// gitCommit will be the hash that the binary was built from
// and will be populated by the Makefile
var gitCommit = ""
var logger = NewLogger()
func main() { func main() {
err := run(os.Args) r := runtime.New()
err := r.Run(os.Args)
if err != nil { if err != nil {
logger.Errorf("%v", err)
os.Exit(1) os.Exit(1)
} }
} }
// run is an entry point that allows for idiomatic handling of errors
// when calling from the main function.
func run(argv []string) (rerr error) {
printVersion := hasVersionFlag(argv)
if printVersion {
fmt.Printf("%v version %v\n", "NVIDIA Container Runtime", info.GetVersionString(fmt.Sprintf("spec: %v", specs.Version)))
}
cfg, err := config.GetConfig()
if err != nil {
return fmt.Errorf("error loading config: %v", err)
}
logger, err = UpdateLogger(
cfg.NVIDIAContainerRuntimeConfig.DebugFilePath,
cfg.NVIDIAContainerRuntimeConfig.LogLevel,
argv,
)
if err != nil {
return fmt.Errorf("failed to set up logger: %v", err)
}
defer func() {
if rerr != nil {
logger.Errorf("%v", rerr)
}
logger.Reset()
}()
logger.Debugf("Command line arguments: %v", argv)
runtime, err := newNVIDIAContainerRuntime(logger.Logger, cfg, argv)
if err != nil {
return fmt.Errorf("failed to create NVIDIA Container Runtime: %v", err)
}
if printVersion {
fmt.Print("\n")
}
return runtime.Exec(argv)
}
// TODO: This should be refactored / combined with parseArgs in logger.
func hasVersionFlag(args []string) bool {
for i := 0; i < len(args); i++ {
param := args[i]
parts := strings.SplitN(param, "=", 2)
trimmed := strings.TrimLeft(parts[0], "-")
// If this is not a flag we continue
if parts[0] == trimmed {
continue
}
// Check the version flag
if trimmed == "version" {
return true
}
}
return false
}

View File

@ -13,6 +13,7 @@ import (
"github.com/NVIDIA/nvidia-container-toolkit/internal/modifier" "github.com/NVIDIA/nvidia-container-toolkit/internal/modifier"
"github.com/NVIDIA/nvidia-container-toolkit/internal/test" "github.com/NVIDIA/nvidia-container-toolkit/internal/test"
"github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-spec/specs-go"
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -41,7 +42,7 @@ func TestMain(m *testing.M) {
var err error var err error
moduleRoot, err := test.GetModuleRoot() moduleRoot, err := test.GetModuleRoot()
if err != nil { if err != nil {
logger.Fatalf("error in test setup: could not get module root: %v", err) logrus.Fatalf("error in test setup: could not get module root: %v", err)
} }
testBinPath := filepath.Join(moduleRoot, "test", "bin") testBinPath := filepath.Join(moduleRoot, "test", "bin")
testInputPath := filepath.Join(moduleRoot, "test", "input") testInputPath := filepath.Join(moduleRoot, "test", "input")
@ -53,11 +54,11 @@ func TestMain(m *testing.M) {
// Confirm that the environment is configured correctly // Confirm that the environment is configured correctly
runcPath, err := exec.LookPath(runcExecutableName) runcPath, err := exec.LookPath(runcExecutableName)
if err != nil || filepath.Join(testBinPath, runcExecutableName) != runcPath { if err != nil || filepath.Join(testBinPath, runcExecutableName) != runcPath {
logger.Fatalf("error in test setup: mock runc path set incorrectly in TestMain(): %v", err) logrus.Fatalf("error in test setup: mock runc path set incorrectly in TestMain(): %v", err)
} }
hookPath, err := exec.LookPath(nvidiaHook) hookPath, err := exec.LookPath(nvidiaHook)
if err != nil || filepath.Join(testBinPath, nvidiaHook) != hookPath { if err != nil || filepath.Join(testBinPath, nvidiaHook) != hookPath {
logger.Fatalf("error in test setup: mock hook path set incorrectly in TestMain(): %v", err) logrus.Fatalf("error in test setup: mock hook path set incorrectly in TestMain(): %v", err)
} }
// Store the root and binary paths in the test Config // Store the root and binary paths in the test Config
@ -92,6 +93,7 @@ func TestBadInput(t *testing.T) {
// case 1) nvidia-container-runtime run --bundle <bundle-name> <ctr-name> // case 1) nvidia-container-runtime run --bundle <bundle-name> <ctr-name>
// - Confirm the runtime runs with no errors // - Confirm the runtime runs with no errors
//
// case 2) nvidia-container-runtime create --bundle <bundle-name> <ctr-name> // case 2) nvidia-container-runtime create --bundle <bundle-name> <ctr-name>
// - Confirm the runtime inserts the NVIDIA prestart hook correctly // - Confirm the runtime inserts the NVIDIA prestart hook correctly
func TestGoodInput(t *testing.T) { func TestGoodInput(t *testing.T) {
@ -170,7 +172,7 @@ func TestDuplicateHook(t *testing.T) {
// addNVIDIAHook is a basic wrapper for an addHookModifier that is used for // addNVIDIAHook is a basic wrapper for an addHookModifier that is used for
// testing. // testing.
func addNVIDIAHook(spec *specs.Spec) error { func addNVIDIAHook(spec *specs.Spec) error {
m := modifier.NewStableRuntimeModifier(logger.Logger) m := modifier.NewStableRuntimeModifier(logrus.StandardLogger())
return m.Modify(spec) return m.Modify(spec)
} }

View File

@ -14,27 +14,26 @@
# limitations under the License. # limitations under the License.
*/ */
package runtime package oci
import ( import (
"fmt" "fmt"
"github.com/NVIDIA/nvidia-container-toolkit/internal/oci"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
type modifyingRuntimeWrapper struct { type modifyingRuntimeWrapper struct {
logger *log.Logger logger *log.Logger
runtime oci.Runtime runtime Runtime
ociSpec oci.Spec ociSpec Spec
modifier oci.SpecModifier modifier SpecModifier
} }
var _ oci.Runtime = (*modifyingRuntimeWrapper)(nil) var _ Runtime = (*modifyingRuntimeWrapper)(nil)
// NewModifyingRuntimeWrapper creates a runtime wrapper that applies the specified modifier to the OCI specification // NewModifyingRuntimeWrapper creates a runtime wrapper that applies the specified modifier to the OCI specification
// before invoking the wrapped runtime. If the modifier is nil, the input runtime is returned. // before invoking the wrapped runtime. If the modifier is nil, the input runtime is returned.
func NewModifyingRuntimeWrapper(logger *log.Logger, runtime oci.Runtime, spec oci.Spec, modifier oci.SpecModifier) oci.Runtime { func NewModifyingRuntimeWrapper(logger *log.Logger, runtime Runtime, spec Spec, modifier SpecModifier) Runtime {
if modifier == nil { if modifier == nil {
logger.Infof("Using low-level runtime with no modification") logger.Infof("Using low-level runtime with no modification")
return runtime return runtime
@ -52,7 +51,7 @@ func NewModifyingRuntimeWrapper(logger *log.Logger, runtime oci.Runtime, spec oc
// Exec checks whether a modification of the OCI specification is required and modifies it accordingly before exec-ing // Exec checks whether a modification of the OCI specification is required and modifies it accordingly before exec-ing
// into the wrapped runtime. // into the wrapped runtime.
func (r *modifyingRuntimeWrapper) Exec(args []string) error { func (r *modifyingRuntimeWrapper) Exec(args []string) error {
if oci.HasCreateSubcommand(args) { if HasCreateSubcommand(args) {
err := r.modify() err := r.modify()
if err != nil { if err != nil {
return fmt.Errorf("could not apply required modification to OCI specification: %v", err) return fmt.Errorf("could not apply required modification to OCI specification: %v", err)

View File

@ -14,13 +14,12 @@
# limitations under the License. # limitations under the License.
*/ */
package runtime package oci
import ( import (
"fmt" "fmt"
"testing" "testing"
"github.com/NVIDIA/nvidia-container-toolkit/internal/oci"
"github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-spec/specs-go"
testlog "github.com/sirupsen/logrus/hooks/test" testlog "github.com/sirupsen/logrus/hooks/test"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -38,7 +37,7 @@ func TestExec(t *testing.T) {
args []string args []string
modifyError error modifyError error
writeError error writeError error
modifer oci.SpecModifier modifer SpecModifier
}{ }{
{ {
description: "no args forwards", description: "no args forwards",
@ -92,9 +91,9 @@ func TestExec(t *testing.T) {
hook.Reset() hook.Reset()
t.Run(tc.description, func(t *testing.T) { t.Run(tc.description, func(t *testing.T) {
runtimeMock := &oci.RuntimeMock{} runtimeMock := &RuntimeMock{}
specMock := &oci.SpecMock{ specMock := &SpecMock{
ModifyFunc: func(specModifier oci.SpecModifier) error { ModifyFunc: func(specModifier SpecModifier) error {
return tc.modifyError return tc.modifyError
}, },
FlushFunc: func() error { FlushFunc: func() error {
@ -144,8 +143,8 @@ func TestExec(t *testing.T) {
func TestNilModiferReturnsRuntime(t *testing.T) { func TestNilModiferReturnsRuntime(t *testing.T) {
logger, _ := testlog.NewNullLogger() logger, _ := testlog.NewNullLogger()
runtimeMock := &oci.RuntimeMock{} runtimeMock := &RuntimeMock{}
specMock := &oci.SpecMock{} specMock := &SpecMock{}
shim := NewModifyingRuntimeWrapper( shim := NewModifyingRuntimeWrapper(
logger, logger,

33
internal/runtime/api.go Normal file
View File

@ -0,0 +1,33 @@
package runtime
type rt struct {
logger *Logger
modeOverride string
}
// Interface is the interface for the runtime library.
type Interface interface {
Run([]string) error
}
// Option is a function that configures the runtime.
type Option func(*rt)
// New creates a runtime with the specified options.
func New(opts ...Option) Interface {
r := rt{}
for _, opt := range opts {
opt(&r)
}
if r.logger == nil {
r.logger = NewLogger()
}
return &r
}
// WithModeOverride allows for overriding the mode specified in the config.
func WithModeOverride(mode string) Option {
return func(r *rt) {
r.modeOverride = mode
}
}

View File

@ -14,7 +14,7 @@
# limitations under the License. # limitations under the License.
*/ */
package main package runtime
import ( import (
"fmt" "fmt"
@ -42,8 +42,8 @@ func NewLogger() *Logger {
} }
} }
// UpdateLogger constructs a Logger with a preddefined formatter // Update constructs a Logger with a preddefined formatter
func UpdateLogger(filename string, logLevel string, argv []string) (*Logger, error) { func (l *Logger) Update(filename string, logLevel string, argv []string) error {
configFromArgs := parseArgs(argv) configFromArgs := parseArgs(argv)
level, logLevelError := configFromArgs.getLevel(logLevel) level, logLevelError := configFromArgs.getLevel(logLevel)
@ -55,7 +55,7 @@ func UpdateLogger(filename string, logLevel string, argv []string) (*Logger, err
if !configFromArgs.version { if !configFromArgs.version {
configLogFile, err := createLogFile(filename) configLogFile, err := createLogFile(filename)
if err != nil { if err != nil {
return logger, fmt.Errorf("error opening debug log file: %v", err) return fmt.Errorf("error opening debug log file: %v", err)
} }
if configLogFile != nil { if configLogFile != nil {
logFiles = append(logFiles, configLogFile) logFiles = append(logFiles, configLogFile)
@ -68,9 +68,10 @@ func UpdateLogger(filename string, logLevel string, argv []string) (*Logger, err
argLogFileError = err argLogFileError = err
} }
l := &Logger{ previous := l.Logger
l = &Logger{
Logger: logrus.New(), Logger: logrus.New(),
previousLogger: logger.Logger, previousLogger: previous,
logFiles: logFiles, logFiles: logFiles,
} }
@ -115,7 +116,7 @@ func UpdateLogger(filename string, logLevel string, argv []string) (*Logger, err
l.Warnf("Failed to open log file: %v", argLogFileError) l.Warnf("Failed to open log file: %v", argLogFileError)
} }
return l, nil return nil
} }
// Reset closes the log file (if any) and resets the logger output to what it // Reset closes the log file (if any) and resets the logger output to what it
@ -126,7 +127,7 @@ func (l *Logger) Reset() error {
if previous == nil { if previous == nil {
previous = logrus.New() previous = logrus.New()
} }
logger = &Logger{Logger: previous} l = &Logger{Logger: previous}
}() }()
var errs []error var errs []error

109
internal/runtime/runtime.go Normal file
View File

@ -0,0 +1,109 @@
/**
# 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 runtime
import (
"encoding/json"
"fmt"
"strings"
"github.com/NVIDIA/nvidia-container-toolkit/internal/config"
"github.com/NVIDIA/nvidia-container-toolkit/internal/info"
"github.com/opencontainers/runtime-spec/specs-go"
)
// Run is an entry point that allows for idiomatic handling of errors
// when calling from the main function.
func (r rt) Run(argv []string) (rerr error) {
defer func() {
if rerr != nil {
r.logger.Errorf("%v", rerr)
}
}()
printVersion := hasVersionFlag(argv)
if printVersion {
fmt.Printf("%v version %v\n", "NVIDIA Container Runtime", info.GetVersionString(fmt.Sprintf("spec: %v", specs.Version)))
}
cfg, err := config.GetConfig()
if err != nil {
return fmt.Errorf("error loading config: %v", err)
}
if r.modeOverride != "" {
cfg.NVIDIAContainerRuntimeConfig.Mode = r.modeOverride
}
err = r.logger.Update(
cfg.NVIDIAContainerRuntimeConfig.DebugFilePath,
cfg.NVIDIAContainerRuntimeConfig.LogLevel,
argv,
)
if err != nil {
return fmt.Errorf("failed to set up logger: %v", err)
}
defer func() {
if rerr != nil {
r.logger.Errorf("%v", rerr)
}
r.logger.Reset()
}()
// Print the config to the output.
configJSON, err := json.MarshalIndent(cfg, "", " ")
if err == nil {
r.logger.Infof("Running with config:\n%v", string(configJSON))
} else {
r.logger.Infof("Running with config:\n%+v", cfg)
}
r.logger.Debugf("Command line arguments: %v", argv)
runtime, err := newNVIDIAContainerRuntime(r.logger.Logger, cfg, argv)
if err != nil {
return fmt.Errorf("failed to create NVIDIA Container Runtime: %v", err)
}
if printVersion {
fmt.Print("\n")
}
return runtime.Exec(argv)
}
func (r rt) Errorf(format string, args ...interface{}) {
r.logger.Errorf(format, args...)
}
// TODO: This should be refactored / combined with parseArgs in logger.
func hasVersionFlag(args []string) bool {
for i := 0; i < len(args); i++ {
param := args[i]
parts := strings.SplitN(param, "=", 2)
trimmed := strings.TrimLeft(parts[0], "-")
// If this is not a flag we continue
if parts[0] == trimmed {
continue
}
// Check the version flag
if trimmed == "version" {
return true
}
}
return false
}

View File

@ -14,7 +14,7 @@
# limitations under the License. # limitations under the License.
*/ */
package main package runtime
import ( import (
"fmt" "fmt"
@ -23,7 +23,6 @@ import (
"github.com/NVIDIA/nvidia-container-toolkit/internal/info" "github.com/NVIDIA/nvidia-container-toolkit/internal/info"
"github.com/NVIDIA/nvidia-container-toolkit/internal/modifier" "github.com/NVIDIA/nvidia-container-toolkit/internal/modifier"
"github.com/NVIDIA/nvidia-container-toolkit/internal/oci" "github.com/NVIDIA/nvidia-container-toolkit/internal/oci"
"github.com/NVIDIA/nvidia-container-toolkit/internal/runtime"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
@ -50,7 +49,7 @@ func newNVIDIAContainerRuntime(logger *logrus.Logger, cfg *config.Config, argv [
} }
// Create the wrapping runtime with the specified modifier // Create the wrapping runtime with the specified modifier
r := runtime.NewModifyingRuntimeWrapper( r := oci.NewModifyingRuntimeWrapper(
logger, logger,
lowLevelRuntime, lowLevelRuntime,
ociSpec, ociSpec,

View File

@ -14,20 +14,52 @@
# limitations under the License. # limitations under the License.
*/ */
package main package runtime
import ( import (
"encoding/json" "encoding/json"
"os" "os"
"os/exec"
"path/filepath" "path/filepath"
"testing" "testing"
"github.com/NVIDIA/nvidia-container-toolkit/internal/config" "github.com/NVIDIA/nvidia-container-toolkit/internal/config"
"github.com/NVIDIA/nvidia-container-toolkit/internal/test"
"github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-spec/specs-go"
"github.com/sirupsen/logrus"
testlog "github.com/sirupsen/logrus/hooks/test" testlog "github.com/sirupsen/logrus/hooks/test"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
const (
runcExecutableName = "runc"
)
func TestMain(m *testing.M) {
// TEST SETUP
// Determine the module root and the test binary path
var err error
moduleRoot, err := test.GetModuleRoot()
if err != nil {
logrus.Fatalf("error in test setup: could not get module root: %v", err)
}
testBinPath := filepath.Join(moduleRoot, "test", "bin")
// Set the environment variables for the test
os.Setenv("PATH", test.PrependToPath(testBinPath, moduleRoot))
// Confirm that the environment is configured correctly
runcPath, err := exec.LookPath(runcExecutableName)
if err != nil || filepath.Join(testBinPath, runcExecutableName) != runcPath {
logrus.Fatalf("error in test setup: mock runc path set incorrectly in TestMain(): %v", err)
}
// RUN TESTS
exitCode := m.Run()
os.Exit(exitCode)
}
func TestFactoryMethod(t *testing.T) { func TestFactoryMethod(t *testing.T) {
logger, _ := testlog.NewNullLogger() logger, _ := testlog.NewNullLogger()

View File

@ -23,3 +23,9 @@ Breaks: nvidia-container-runtime (<= 3.5.0-1), nvidia-container-runtime-hook, nv
Replaces: nvidia-container-runtime (<= 3.5.0-1), nvidia-container-runtime-hook Replaces: nvidia-container-runtime (<= 3.5.0-1), nvidia-container-runtime-hook
Description: NVIDIA Container Toolkit Base Description: NVIDIA Container Toolkit Base
Provides tools such as the NVIDIA Container Runtime and NVIDIA Container Toolkit CLI to enable GPU support in containers. Provides tools such as the NVIDIA Container Runtime and NVIDIA Container Toolkit CLI to enable GPU support in containers.
Package: nvidia-container-toolkit-operator-extensions
Architecture: any
Depends: ${misc:Depends}, nvidia-container-toolkit-base (= @VERSION@)
Description: NVIDIA Container Toolkit Operator Extensions
Provides tools for using the NVIDIA Container Toolkit with the GPU Operator

View File

@ -0,0 +1,2 @@
nvidia-container-runtime.cdi /usr/bin
nvidia-container-runtime.legacy /usr/bin

View File

@ -11,12 +11,14 @@ URL: https://github.com/NVIDIA/nvidia-container-toolkit
License: Apache-2.0 License: Apache-2.0
Source0: nvidia-container-runtime-hook Source0: nvidia-container-runtime-hook
Source1: nvidia-container-runtime Source1: nvidia-ctk
Source2: nvidia-ctk Source2: config.toml
Source3: config.toml Source3: oci-nvidia-hook
Source4: oci-nvidia-hook Source4: oci-nvidia-hook.json
Source5: oci-nvidia-hook.json Source5: LICENSE
Source6: LICENSE Source6: nvidia-container-runtime
Source7: nvidia-container-runtime.cdi
Source8: nvidia-container-runtime.legacy
Obsoletes: nvidia-container-runtime <= 3.5.0-1, nvidia-container-runtime-hook <= 1.4.0-2 Obsoletes: nvidia-container-runtime <= 3.5.0-1, nvidia-container-runtime-hook <= 1.4.0-2
Provides: nvidia-container-runtime Provides: nvidia-container-runtime
@ -35,12 +37,14 @@ Requires: libseccomp
Provides tools and utilities to enable GPU support in containers. Provides tools and utilities to enable GPU support in containers.
%prep %prep
cp %{SOURCE0} %{SOURCE1} %{SOURCE2} %{SOURCE3} %{SOURCE4} %{SOURCE5} %{SOURCE6} . cp %{SOURCE0} %{SOURCE1} %{SOURCE2} %{SOURCE3} %{SOURCE4} %{SOURCE5} %{SOURCE6} %{SOURCE7} %{SOURCE8} .
%install %install
mkdir -p %{buildroot}%{_bindir} mkdir -p %{buildroot}%{_bindir}
install -m 755 -t %{buildroot}%{_bindir} nvidia-container-runtime-hook install -m 755 -t %{buildroot}%{_bindir} nvidia-container-runtime-hook
install -m 755 -t %{buildroot}%{_bindir} nvidia-container-runtime install -m 755 -t %{buildroot}%{_bindir} nvidia-container-runtime
install -m 755 -t %{buildroot}%{_bindir} nvidia-container-runtime.cdi
install -m 755 -t %{buildroot}%{_bindir} nvidia-container-runtime.legacy
install -m 755 -t %{buildroot}%{_bindir} nvidia-ctk install -m 755 -t %{buildroot}%{_bindir} nvidia-ctk
mkdir -p %{buildroot}/etc/nvidia-container-runtime mkdir -p %{buildroot}/etc/nvidia-container-runtime
@ -97,3 +101,17 @@ Provides tools such as the NVIDIA Container Runtime and NVIDIA Container Toolkit
%config /etc/nvidia-container-runtime/config.toml %config /etc/nvidia-container-runtime/config.toml
%{_bindir}/nvidia-container-runtime %{_bindir}/nvidia-container-runtime
%{_bindir}/nvidia-ctk %{_bindir}/nvidia-ctk
# The OPERATOR EXTENSIONS package consists of components that are required to enable GPU support in Kubernetes.
# This package is not distributed as part of the NVIDIA Container Toolkit RPMs.
%package operator-extensions
Summary: NVIDIA Container Toolkit Operator Extensions
Requires: nvidia-container-toolkit-base == %{version}-%{release}
%description operator-extensions
Provides tools for using the NVIDIA Container Toolkit with the GPU Operator
%files operator-extensions
%license LICENSE
%{_bindir}/nvidia-container-runtime.cdi
%{_bindir}/nvidia-container-runtime.legacy

View File

@ -40,6 +40,12 @@ PACKAGE_IMAGE=$1
# For example, we don't release release candidates of nvidia-container-runtime and nvidia-docker2 # For example, we don't release release candidates of nvidia-container-runtime and nvidia-docker2
# since these only bump the nvidia-container-toolkit dependency. # since these only bump the nvidia-container-toolkit dependency.
function skip-for-release-candidate() { function skip-for-release-candidate() {
# We always skip nvidia-container-toolkit-operator-extensions packages
if [[ "${package_name/"nvidia-container-toolkit-operator-extensions"/}" != "${package_name}" ]]; then
return 0
fi
# We allow all other packages for non-rc versions.
if [[ "${VERSION/rc./}" == "${VERSION}" ]]; then if [[ "${VERSION/rc./}" == "${VERSION}" ]]; then
return 1 return 1
fi fi

View File

@ -120,6 +120,12 @@ function sync() {
mkdir -p ${dst} mkdir -p ${dst}
for f in $(ls ${src}/libnvidia-container*.${pkg_type} ${src}/nvidia-container-toolkit*.${pkg_type}); do for f in $(ls ${src}/libnvidia-container*.${pkg_type} ${src}/nvidia-container-toolkit*.${pkg_type}); do
# We never release nvidia-container-toolkit-operator-extensions packages
if [[ "${f/"nvidia-container-toolkit-operator-extensions"/}" != "${f}" ]]; then
echo "Skipping ${f}"
continue
fi
df=${dst}/$(basename ${f}) df=${dst}/$(basename ${f})
df_stable=${df//"/experimental/"/"/stable/"} df_stable=${df//"/experimental/"/"/stable/"}
if [[ -f "${df}" ]]; then if [[ -f "${df}" ]]; then