Skip to content

Commit 06623b2

Browse files
committed
Update Validator for /usr/bin symlink
Signed-off-by: Arjun <agadiyar@nvidia.com>
1 parent 9aff6f5 commit 06623b2

12 files changed

Lines changed: 906 additions & 14 deletions

File tree

cmd/nvidia-validator/main.go

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
"github.com/NVIDIA/go-nvlib/pkg/nvmdev"
3232
"github.com/NVIDIA/go-nvlib/pkg/nvpci"
3333
devchar "github.com/NVIDIA/nvidia-container-toolkit/cmd/nvidia-ctk/system/create-dev-char-symlinks"
34+
"github.com/moby/sys/symlink"
3435
log "github.com/sirupsen/logrus"
3536
"github.com/stretchr/testify/assert/yaml"
3637
cli "github.com/urfave/cli/v3"
@@ -135,6 +136,7 @@ var (
135136
hostRootFlag string
136137
driverInstallDirFlag string
137138
driverInstallDirCtrPathFlag string
139+
hostRootCtrPath = "/host"
138140
)
139141

140142
// defaultGPUWorkloadConfig is "vm-passthrough" unless
@@ -742,22 +744,43 @@ func isDriverManagedByOperator(ctx context.Context) (bool, error) {
742744
return false, nil
743745
}
744746

747+
func resolveHostNvidiaSMIPath() (string, error) {
748+
nvidiaSMIPath, err := symlink.FollowSymlinkInScope(filepath.Join(hostRootCtrPath, "usr/bin/nvidia-smi"), hostRootCtrPath)
749+
if err != nil {
750+
return "", fmt.Errorf("failed to resolve 'nvidia-smi' path on the host: %w", err)
751+
}
752+
753+
fileInfo, err := os.Lstat(nvidiaSMIPath)
754+
if err != nil {
755+
return "", fmt.Errorf("no 'nvidia-smi' file present on the host: %w", err)
756+
}
757+
if fileInfo.Size() == 0 {
758+
return "", fmt.Errorf("empty 'nvidia-smi' file found on the host")
759+
}
760+
761+
return nvidiaSMIPath, nil
762+
}
763+
764+
func hostDriverValidationCommand() (string, []string, error) {
765+
if _, err := resolveHostNvidiaSMIPath(); err != nil {
766+
return "", nil, err
767+
}
768+
769+
return "chroot", []string{hostRootCtrPath, "nvidia-smi"}, nil
770+
}
771+
745772
func validateHostDriver(silent bool) error {
746773
log.Info("Attempting to validate a pre-installed driver on the host")
747-
if fileInfo, err := os.Lstat(filepath.Join("/host", wslNvidiaSMIPath)); err == nil && fileInfo.Size() != 0 {
774+
if fileInfo, err := os.Lstat(filepath.Join(hostRootCtrPath, wslNvidiaSMIPath)); err == nil && fileInfo.Size() != 0 {
748775
log.Infof("WSL2 system detected, assuming driver is pre-installed")
749776
disableDevCharSymlinkCreation = true
750777
return nil
751778
}
752-
fileInfo, err := os.Lstat("/host/usr/bin/nvidia-smi")
779+
780+
command, args, err := hostDriverValidationCommand()
753781
if err != nil {
754-
return fmt.Errorf("no 'nvidia-smi' file present on the host: %w", err)
755-
}
756-
if fileInfo.Size() == 0 {
757-
return fmt.Errorf("empty 'nvidia-smi' file found on the host")
782+
return err
758783
}
759-
command := "chroot"
760-
args := []string{"/host", "nvidia-smi"}
761784

762785
return runCommand(command, args, silent)
763786
}
@@ -1747,17 +1770,21 @@ func (v *VGPUManager) validate() error {
17471770
return nil
17481771
}
17491772

1750-
func (v *VGPUManager) runValidation(silent bool) (hostDriver bool, err error) {
1751-
// invoke validation command
1773+
func vGPUManagerValidationCommand() (bool, string, []string) {
17521774
command := "chroot"
17531775
args := []string{"/run/nvidia/driver", "nvidia-smi"}
17541776

1755-
// check if driver is pre-installed on the host and use host path for validation
1756-
if _, err := os.Lstat("/host/usr/bin/nvidia-smi"); err == nil {
1757-
args = []string{"/host", "nvidia-smi"}
1758-
hostDriver = true
1777+
if _, err := resolveHostNvidiaSMIPath(); err == nil {
1778+
return true, command, []string{hostRootCtrPath, "nvidia-smi"}
17591779
}
17601780

1781+
return false, command, args
1782+
}
1783+
1784+
func (v *VGPUManager) runValidation(silent bool) (hostDriver bool, err error) {
1785+
// invoke validation command
1786+
hostDriver, command, args := vGPUManagerValidationCommand()
1787+
17611788
if withWaitFlag {
17621789
return hostDriver, runCommandWithWait(command, args, sleepIntervalSecondsFlag, silent)
17631790
}

cmd/nvidia-validator/main_test.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,58 @@ package main
1919
import (
2020
"context"
2121
"os"
22+
"path/filepath"
23+
"reflect"
2224
"testing"
2325
)
2426

27+
func Test_validateHostDriverWithAbsoluteUsrBinSymlink(t *testing.T) {
28+
hostRoot := t.TempDir()
29+
30+
targetDir := filepath.Join(hostRoot, "run/current-system/sw/bin")
31+
if err := os.MkdirAll(targetDir, 0755); err != nil {
32+
t.Fatalf("failed to create target directory: %v", err)
33+
}
34+
if err := os.WriteFile(filepath.Join(targetDir, "nvidia-smi"), []byte("fake nvidia-smi"), 0755); err != nil {
35+
t.Fatalf("failed to create nvidia-smi: %v", err)
36+
}
37+
38+
usrDir := filepath.Join(hostRoot, "usr")
39+
if err := os.MkdirAll(usrDir, 0755); err != nil {
40+
t.Fatalf("failed to create usr directory: %v", err)
41+
}
42+
if err := os.Symlink("/run/current-system/sw/bin", filepath.Join(usrDir, "bin")); err != nil {
43+
t.Fatalf("failed to create usr/bin symlink: %v", err)
44+
}
45+
46+
originalHostRootCtrPath := hostRootCtrPath
47+
hostRootCtrPath = hostRoot
48+
defer func() { hostRootCtrPath = originalHostRootCtrPath }()
49+
50+
command, args, err := hostDriverValidationCommand()
51+
if err != nil {
52+
t.Fatalf("hostDriverValidationCommand() unexpected error: %v", err)
53+
}
54+
if command != "chroot" {
55+
t.Fatalf("command = %q, want %q", command, "chroot")
56+
}
57+
wantArgs := []string{hostRoot, "nvidia-smi"}
58+
if !reflect.DeepEqual(args, wantArgs) {
59+
t.Fatalf("args = %v, want %v", args, wantArgs)
60+
}
61+
62+
hostDriver, command, args := vGPUManagerValidationCommand()
63+
if !hostDriver {
64+
t.Fatal("vGPUManagerValidationCommand() did not detect host driver")
65+
}
66+
if command != "chroot" {
67+
t.Fatalf("command = %q, want %q", command, "chroot")
68+
}
69+
if !reflect.DeepEqual(args, wantArgs) {
70+
t.Fatalf("args = %v, want %v", args, wantArgs)
71+
}
72+
}
73+
2574
func Test_isValidComponent(t *testing.T) {
2675
tests := []struct {
2776
name string

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ require (
1111
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc
1212
github.com/go-logr/logr v1.4.3
1313
github.com/go-logr/zapr v1.3.0
14+
github.com/moby/sys/symlink v0.3.0
1415
github.com/onsi/ginkgo/v2 v2.28.3
1516
github.com/onsi/gomega v1.40.0
1617
github.com/openshift/api v0.0.0-20260213204242-d34f11c515b3

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,8 @@ github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zx
148148
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
149149
github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ=
150150
github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc=
151+
github.com/moby/sys/symlink v0.3.0 h1:GZX89mEZ9u53f97npBy4Rc3vJKj7JBDj/PN2I22GrNU=
152+
github.com/moby/sys/symlink v0.3.0/go.mod h1:3eNdhduHmYPcgsJtZXW1W4XUJdZGBIkttZ8xKqPUJq0=
151153
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
152154
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
153155
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=

vendor/github.com/moby/sys/symlink/LICENSE

Lines changed: 202 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)