Skip to content

Commit c17149f

Browse files
authored
Merge pull request #1399 from tkatila/prepare-0.26.1
Prepare 0.26.1
2 parents d7a14ab + 4e3ef52 commit c17149f

File tree

60 files changed

+514
-87
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+514
-87
lines changed

Jenkinsfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ pipeline {
142142
stage('make test-with-kind') {
143143
steps {
144144
dir(path: "$REPO_DIR") {
145-
sh "make test-with-kind REG=intel/ TAG=0.26.0"
145+
sh "make test-with-kind REG=intel/ TAG=0.26.1"
146146
}
147147
}
148148
}

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ clean:
136136

137137
ORG?=intel
138138
REG?=$(ORG)/
139-
TAG?=0.26.0
139+
TAG?=0.26.1
140140
export TAG
141141

142142
e2e-fpga:

cmd/gpu_plugin/gpu_plugin.go

+74-5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"fmt"
2020
"os"
2121
"path"
22+
"path/filepath"
2223
"regexp"
2324
"sort"
2425
"strings"
@@ -39,6 +40,7 @@ const (
3940
devfsDriDirectory = "/dev/dri"
4041
gpuDeviceRE = `^card[0-9]+$`
4142
controlDeviceRE = `^controlD[0-9]+$`
43+
pciAddressRE = "^[0-9a-f]{4}:[0-9a-f]{2}:[0-9a-f]{2}\\.[0-9a-f]{1}$"
4244
vendorString = "0x8086"
4345

4446
// Device plugin settings.
@@ -145,32 +147,86 @@ func packedPolicy(req *pluginapi.ContainerPreferredAllocationRequest) []string {
145147
return deviceIds
146148
}
147149

150+
// Returns a slice of by-path Mounts for a cardPath&Name.
151+
// by-path files are searched from the given bypathDir.
152+
// In the by-path dir, any files that start with "pci-<pci addr>" will be added to mounts.
153+
func (dp *devicePlugin) bypathMountsForPci(cardPath, cardName, bypathDir string) []pluginapi.Mount {
154+
linkPath, err := os.Readlink(cardPath)
155+
if err != nil {
156+
return nil
157+
}
158+
159+
// Fetches the pci address for a drm card by reading the
160+
// symbolic link that the /sys/class/drm/cardX points to.
161+
// ../../devices/pci0000:00/0000:00:02.0/drm/card
162+
// -------------------------^^^^^^^^^^^^---------.
163+
pciAddress := filepath.Base(strings.TrimSuffix(linkPath, filepath.Join("drm", cardName)))
164+
165+
if !dp.pciAddressReg.MatchString(pciAddress) {
166+
klog.Warningf("Invalid pci address for %s: %s", cardPath, pciAddress)
167+
168+
return nil
169+
}
170+
171+
files, err := os.ReadDir(bypathDir)
172+
if err != nil {
173+
klog.Warningf("Failed to read by-path directory: %+v", err)
174+
175+
return nil
176+
}
177+
178+
linkPrefix := "pci-" + pciAddress
179+
180+
var mounts []pluginapi.Mount
181+
182+
for _, f := range files {
183+
if strings.HasPrefix(f.Name(), linkPrefix) {
184+
absPath := path.Join(bypathDir, f.Name())
185+
186+
mounts = append(mounts, pluginapi.Mount{
187+
ContainerPath: absPath,
188+
HostPath: absPath,
189+
ReadOnly: true,
190+
})
191+
}
192+
}
193+
194+
return mounts
195+
}
196+
148197
type devicePlugin struct {
149198
gpuDeviceReg *regexp.Regexp
150199
controlDeviceReg *regexp.Regexp
200+
pciAddressReg *regexp.Regexp
151201

152202
scanTicker *time.Ticker
153203
scanDone chan bool
154204

155205
resMan rm.ResourceManager
156206

157-
sysfsDir string
158-
devfsDir string
207+
sysfsDir string
208+
devfsDir string
209+
bypathDir string
159210

160211
// Note: If restarting the plugin with a new policy, the allocations for existing pods remain with old policy.
161212
policy preferredAllocationPolicyFunc
162213
options cliOptions
214+
215+
bypathFound bool
163216
}
164217

165218
func newDevicePlugin(sysfsDir, devfsDir string, options cliOptions) *devicePlugin {
166219
dp := &devicePlugin{
167220
sysfsDir: sysfsDir,
168221
devfsDir: devfsDir,
222+
bypathDir: path.Join(devfsDir, "/by-path"),
169223
options: options,
170224
gpuDeviceReg: regexp.MustCompile(gpuDeviceRE),
171225
controlDeviceReg: regexp.MustCompile(controlDeviceRE),
226+
pciAddressReg: regexp.MustCompile(pciAddressRE),
172227
scanTicker: time.NewTicker(scanPeriod),
173228
scanDone: make(chan bool, 1), // buffered as we may send to it before Scan starts receiving from it
229+
bypathFound: true,
174230
}
175231

176232
if options.resourceManagement {
@@ -192,6 +248,12 @@ func newDevicePlugin(sysfsDir, devfsDir string, options cliOptions) *devicePlugi
192248
dp.policy = nonePolicy
193249
}
194250

251+
if _, err := os.ReadDir(dp.bypathDir); err != nil {
252+
klog.Warningf("failed to read by-path dir: $+v", err)
253+
254+
dp.bypathFound = false
255+
}
256+
195257
return dp
196258
}
197259

@@ -299,7 +361,9 @@ func (dp *devicePlugin) scan() (dpapi.DeviceTree, error) {
299361
continue
300362
}
301363

302-
drmFiles, err := os.ReadDir(path.Join(dp.sysfsDir, f.Name(), "device/drm"))
364+
cardPath := path.Join(dp.sysfsDir, f.Name())
365+
366+
drmFiles, err := os.ReadDir(path.Join(cardPath, "device/drm"))
303367
if err != nil {
304368
return nil, errors.Wrap(err, "Can't read device folder")
305369
}
@@ -338,15 +402,20 @@ func (dp *devicePlugin) scan() (dpapi.DeviceTree, error) {
338402
}
339403

340404
if len(nodes) > 0 {
341-
deviceInfo := dpapi.NewDeviceInfo(pluginapi.Healthy, nodes, nil, nil, nil)
405+
mounts := []pluginapi.Mount{}
406+
if dp.bypathFound {
407+
mounts = dp.bypathMountsForPci(cardPath, f.Name(), dp.bypathDir)
408+
}
409+
410+
deviceInfo := dpapi.NewDeviceInfo(pluginapi.Healthy, nodes, mounts, nil, nil)
342411

343412
for i := 0; i < dp.options.sharedDevNum; i++ {
344413
devID := fmt.Sprintf("%s-%d", f.Name(), i)
345414
// Currently only one device type (i915) is supported.
346415
// TODO: check model ID to differentiate device models.
347416
devTree.AddDevice(deviceType, devID, deviceInfo)
348417

349-
rmDevInfos[devID] = rm.NewDeviceInfo(nodes, nil, nil)
418+
rmDevInfos[devID] = rm.NewDeviceInfo(nodes, mounts, nil)
350419
}
351420
}
352421
}

cmd/gpu_plugin/gpu_plugin_test.go

+131-1
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@ import (
1818
"flag"
1919
"os"
2020
"path"
21+
"path/filepath"
2122
"reflect"
2223
"testing"
2324

2425
"github.com/pkg/errors"
2526
"k8s.io/kubelet/pkg/apis/deviceplugin/v1beta1"
27+
"k8s.io/utils/strings/slices"
2628

2729
"github.com/intel/intel-device-plugins-for-kubernetes/cmd/gpu_plugin/rm"
2830
dpapi "github.com/intel/intel-device-plugins-for-kubernetes/pkg/deviceplugin"
@@ -43,6 +45,7 @@ type mockNotifier struct {
4345
func (n *mockNotifier) Notify(newDeviceTree dpapi.DeviceTree) {
4446
n.monitorCount = len(newDeviceTree[monitorType])
4547
n.devCount = len(newDeviceTree[deviceType])
48+
4649
n.scanDone <- true
4750
}
4851

@@ -190,7 +193,11 @@ func TestScan(t *testing.T) {
190193
sysfsfiles: map[string][]byte{
191194
"card0/device/vendor": []byte("0x8086"),
192195
},
193-
devfsdirs: []string{"card0"},
196+
devfsdirs: []string{
197+
"card0",
198+
"by-path/pci-0000:00:00.0-card",
199+
"by-path/pci-0000:00:00.0-render",
200+
},
194201
expectedDevs: 1,
195202
},
196203
{
@@ -314,3 +321,126 @@ func TestScan(t *testing.T) {
314321
})
315322
}
316323
}
324+
325+
// Would be nice to combine these with the overall Scan unit tests.
326+
func createBypathTestFiles(t *testing.T, card, root, linkFile string, bypathFiles []string) (string, string) {
327+
drmPath := path.Join(root, "sys/class/drm/", card)
328+
devPath := path.Join(root, "sys", linkFile)
329+
byPath := path.Join(root, "by-path")
330+
331+
if linkFile != "" {
332+
if err := os.MkdirAll(filepath.Dir(devPath), os.ModePerm); err != nil {
333+
t.Fatal("Couldn't create test dev dir", err)
334+
}
335+
336+
if err := os.MkdirAll(filepath.Dir(drmPath), os.ModePerm); err != nil {
337+
t.Fatal("Couldn't create test drm dir", err)
338+
}
339+
340+
if err := os.WriteFile(devPath, []byte{0}, os.ModePerm); err != nil {
341+
t.Fatal("Couldn't create card file", err)
342+
}
343+
344+
if err := os.Symlink(devPath, drmPath); err != nil {
345+
t.Fatal("Couldn't create symlink between pci path and sysfs drm path")
346+
}
347+
}
348+
349+
if len(bypathFiles) > 0 {
350+
if err := os.MkdirAll(byPath, os.ModePerm); err != nil {
351+
t.Fatal("Mkdir failed:", byPath)
352+
}
353+
354+
for _, f := range bypathFiles {
355+
if err := os.WriteFile(path.Join(byPath, f), []byte{1}, os.ModePerm); err != nil {
356+
t.Fatal("WriteFile failed:", path.Join(byPath, f))
357+
}
358+
}
359+
}
360+
361+
return drmPath, byPath
362+
}
363+
364+
func TestBypath(t *testing.T) {
365+
type testData struct {
366+
desc string
367+
linkpath string
368+
bypathFiles []string
369+
mountCount int
370+
}
371+
372+
const cardName string = "card0"
373+
374+
tds := []testData{
375+
{
376+
"card with two by-path files",
377+
"00.10.2/00.334.302/0.0.1.00/0000:0f:05.0/drm/" + cardName,
378+
[]string{"pci-0000:0f:05.0-card", "pci-0000:0f:05.0-render"},
379+
2,
380+
},
381+
{
382+
"different by-path files",
383+
"00.10.2/00.334.302/0.0.1.00/0000:ff:05.0/drm/" + cardName,
384+
[]string{"pci-0000:0f:05.0-card", "pci-0000:0f:05.0-render"},
385+
0,
386+
},
387+
{
388+
"invalid pci address",
389+
"00.10.2/00.334.302/0.0.1.00/000:ff:05.1/drm/" + cardName,
390+
[]string{"pci-0000:0f:05.0-card", "pci-0000:0f:05.0-render"},
391+
0,
392+
},
393+
{
394+
"symlink without card",
395+
"00.10.2/00.334.302/0.0.1.00/0000:0f:05.0/drm",
396+
[]string{"pci-0000:0f:05.0-card", "pci-0000:0f:05.0-render"},
397+
0,
398+
},
399+
{
400+
"no symlink",
401+
"",
402+
[]string{"pci-0000:0f:05.0-card", "pci-0000:0f:05.0-render"},
403+
0,
404+
},
405+
{
406+
"no by-path files",
407+
"00.10.2/00.334.302/0.0.1.00/0000:0f:05.0/drm/" + cardName,
408+
[]string{},
409+
0,
410+
},
411+
}
412+
413+
for _, td := range tds {
414+
root, err := os.MkdirTemp("", "test_bypath_mounting")
415+
if err != nil {
416+
t.Fatalf("can't create temporary directory: %+v", err)
417+
}
418+
// dirs/files need to be removed for the next test
419+
defer os.RemoveAll(root)
420+
421+
plugin := newDevicePlugin("/", "/", cliOptions{})
422+
423+
drmPath, byPath := createBypathTestFiles(t, cardName, root, td.linkpath, td.bypathFiles)
424+
425+
mounts := plugin.bypathMountsForPci(drmPath, cardName, byPath)
426+
427+
if len(mounts) != td.mountCount {
428+
t.Errorf("%s: Wrong number of mounts %d vs. %d", td.desc, len(mounts), td.mountCount)
429+
}
430+
431+
absPaths := []string{}
432+
for _, link := range td.bypathFiles {
433+
absPaths = append(absPaths, path.Join(byPath, link))
434+
}
435+
436+
for _, mount := range mounts {
437+
if !slices.Contains(absPaths, mount.ContainerPath) {
438+
t.Errorf("%s: containerpath is incorrect: %s", td.desc, mount.ContainerPath)
439+
}
440+
441+
if !slices.Contains(absPaths, mount.HostPath) {
442+
t.Errorf("%s: hostpath is incorrect: %s", td.desc, mount.HostPath)
443+
}
444+
}
445+
}
446+
}

0 commit comments

Comments
 (0)