Skip to content

Commit e768e3a

Browse files
authored
Add support for running binaries from NVIDIA driver directory (#1353)
This PR adds support for running binaries from NVIDIA driver directory mounted by NVIDIA GPU operator to "/run/nvidia/driver/usr/bin". This is in support of the new TuneD functionality requested by RHEL-88914 and supports both one-shot and daemon mode TuneD invocations. Co-authored-by: Jiri Mencak <jmencak@users.noreply.github.com>
1 parent 1e46c6b commit e768e3a

File tree

4 files changed

+112
-0
lines changed

4 files changed

+112
-0
lines changed

pkg/tuned/controller.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ const (
8484
ocpTunedPersist = ocpTunedRunDir + "/persist"
8585
ocpTunedProvider = ocpTunedHome + "/provider"
8686
tunedPersistHome = "/var/lib/tuned"
87+
nvidiaDriverBinDir = "/run/nvidia/driver/usr/bin"
8788
// With the less aggressive rate limiter, retries will happen at 100ms*2^(retry_n-1):
8889
// 100ms, 200ms, 400ms, 800ms, 1.6s, 3.2s, 6.4s, 12.8s, 25.6s, 51.2s, 102.4s, 3.4m, 6.8m, 13.7m, 27.3m
8990
maxRetries = 15

pkg/tuned/run.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import (
2323
"time"
2424

2525
"k8s.io/klog/v2"
26+
27+
"github.com/openshift/cluster-node-tuning-operator/pkg/util"
2628
)
2729

2830
func TunedCreateCmdline(debug bool) (string, []string) {
@@ -99,6 +101,10 @@ func TunedRunNoDaemon(timeout time.Duration) error {
99101
ctx, cancel := context.WithTimeout(context.Background(), timeout)
100102
defer cancel()
101103

104+
if err := util.AddToPath(nvidiaDriverBinDir); err != nil {
105+
return err
106+
}
107+
102108
command, args := TunedCreateCmdline(false)
103109
if timeout > 0 {
104110
// CommandContext sets Cancel to call the Kill (SIGKILL) method on the command's Process.
@@ -120,6 +126,10 @@ func TunedRunNoDaemon(timeout time.Duration) error {
120126
func TunedRun(cmd *exec.Cmd, daemon *Daemon, onDaemonReload func()) error {
121127
klog.Infof("running cmd...")
122128

129+
if err := util.AddToPath(nvidiaDriverBinDir); err != nil {
130+
return err
131+
}
132+
123133
cmdReader, err := cmd.StderrPipe()
124134
if err != nil {
125135
return fmt.Errorf("error creating StderrPipe for tuned: %w", err)

pkg/util/os.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
package util
22

33
import (
4+
"fmt"
45
"os"
6+
"strings"
7+
)
8+
9+
const (
10+
pathSeparator = string(os.PathListSeparator)
511
)
612

713
// Delete a file if it exists. Returns nil if 'file' does not exist.
@@ -25,3 +31,21 @@ func Symlink(target, linkName string) error {
2531

2632
return nil
2733
}
34+
35+
// AddToPath adds 'path' to PATH environment variable unless it exists.
36+
// Returns nil unless os.Setenv() call fails.
37+
func AddToPath(path string) error {
38+
currentPath := os.Getenv("PATH")
39+
40+
paths := strings.Split(currentPath, pathSeparator)
41+
for _, p := range paths {
42+
if p == path {
43+
// 'path' already exists in PATH
44+
return nil
45+
}
46+
}
47+
48+
newPath := fmt.Sprintf("%s%s%s", currentPath, pathSeparator, path)
49+
50+
return os.Setenv("PATH", newPath)
51+
}

pkg/util/os_test.go

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package util
2+
3+
import (
4+
"os"
5+
"testing"
6+
)
7+
8+
// TestAddToPath tests basic functionality of AddToPath.
9+
func TestAddToPath(t *testing.T) {
10+
tests := []struct {
11+
name string
12+
initialPath string
13+
pathToAdd string
14+
expected string
15+
}{
16+
{
17+
name: "Add new path to existing PATH",
18+
initialPath: "/usr/bin" + pathSeparator + "/usr/local/bin",
19+
pathToAdd: "/opt/bin",
20+
expected: "/usr/bin" + pathSeparator + "/usr/local/bin" + pathSeparator + "/opt/bin",
21+
},
22+
{
23+
name: "Path already exists in PATH",
24+
initialPath: "/usr/bin" + pathSeparator + "/usr/local/bin" + pathSeparator + "/opt/bin",
25+
pathToAdd: "/usr/bin",
26+
expected: "/usr/bin" + pathSeparator + "/usr/local/bin" + pathSeparator + "/opt/bin",
27+
},
28+
{
29+
name: "Path exists as substring but not as the exact match",
30+
initialPath: "/usr/bin" + pathSeparator + "/usr/local/bin",
31+
pathToAdd: "/usr",
32+
expected: "/usr/bin" + pathSeparator + "/usr/local/bin" + pathSeparator + "/usr",
33+
},
34+
// A zero-length (null) directory name in the value of PATH indicates the current directory.
35+
// Examples: PATH="", PATH=/usr/bin:, PATH=/usr/bin::/usr/local/bin
36+
{
37+
name: "Add path to empty PATH",
38+
initialPath: "",
39+
pathToAdd: "/usr/bin",
40+
expected: pathSeparator + "/usr/bin",
41+
},
42+
{
43+
name: "Add empty path",
44+
initialPath: "/usr/bin",
45+
pathToAdd: "",
46+
expected: "/usr/bin" + pathSeparator,
47+
},
48+
{
49+
name: "Single empty path exists in the middle of non-empty PATH",
50+
initialPath: "/usr/bin" + pathSeparator + pathSeparator + "/usr/local/bin",
51+
pathToAdd: "",
52+
expected: "/usr/bin" + pathSeparator + pathSeparator + "/usr/local/bin",
53+
},
54+
{
55+
name: "Single empty path exists at the end of in non-empty PATH",
56+
initialPath: "/usr/bin" + pathSeparator,
57+
pathToAdd: "",
58+
expected: "/usr/bin" + pathSeparator,
59+
},
60+
}
61+
62+
for _, tt := range tests {
63+
t.Run(tt.name, func(t *testing.T) {
64+
// Use t.Setenv instead of os.Setenv() to restore the original PATH automatically.
65+
t.Setenv("PATH", tt.initialPath)
66+
err := AddToPath(tt.pathToAdd)
67+
if err != nil {
68+
t.Errorf("Expected no error from AddToPath() but got: %v", err)
69+
}
70+
71+
newPath := os.Getenv("PATH")
72+
if newPath != tt.expected {
73+
t.Errorf("Expected PATH to be %q, but got %q", tt.expected, newPath)
74+
}
75+
})
76+
}
77+
}

0 commit comments

Comments
 (0)