Skip to content

Commit 3ae1b0c

Browse files
authored
Merge pull request kubernetes#88234 from fromanirh/topomgr-e2e-tests-multicnt
e2e topology manager: single-numa-node multi container tests
2 parents 8fb66ae + 64904d0 commit 3ae1b0c

File tree

2 files changed

+366
-104
lines changed

2 files changed

+366
-104
lines changed

test/e2e_node/numa_alignment.go

Lines changed: 85 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ package e2enode
1919
import (
2020
"fmt"
2121
"io/ioutil"
22+
"os"
23+
"path/filepath"
2224
"sort"
2325
"strconv"
2426
"strings"
@@ -44,8 +46,7 @@ func (R *numaPodResources) CheckAlignment() bool {
4446
}
4547
}
4648
for _, devNode := range R.PCIDevsToNUMANode {
47-
// TODO: explain -1
48-
if devNode != -1 && nodeNum != devNode {
49+
if nodeNum != devNode {
4950
return false
5051
}
5152
}
@@ -88,7 +89,7 @@ func getCPUsPerNUMANode(nodeNum int) ([]int, error) {
8889
return cpus.ToSlice(), nil
8990
}
9091

91-
func getCPUToNUMANodeMapFromEnv(f *framework.Framework, pod *v1.Pod, environ map[string]string, numaNodes int) (map[int]int, error) {
92+
func getCPUToNUMANodeMapFromEnv(f *framework.Framework, pod *v1.Pod, cnt *v1.Container, environ map[string]string, numaNodes int) (map[int]int, error) {
9293
var cpuIDs []int
9394
cpuListAllowedEnvVar := "CPULIST_ALLOWED"
9495

@@ -102,12 +103,12 @@ func getCPUToNUMANodeMapFromEnv(f *framework.Framework, pod *v1.Pod, environ map
102103
}
103104
}
104105
if len(cpuIDs) == 0 {
105-
return nil, fmt.Errorf("variable %q found in environ", cpuListAllowedEnvVar)
106+
return nil, fmt.Errorf("variable %q not found in environ", cpuListAllowedEnvVar)
106107
}
107108

108109
cpusPerNUMA := make(map[int][]int)
109110
for numaNode := 0; numaNode < numaNodes; numaNode++ {
110-
nodeCPUList := f.ExecCommandInContainer(pod.Name, pod.Spec.Containers[0].Name,
111+
nodeCPUList := f.ExecCommandInContainer(pod.Name, cnt.Name,
111112
"/bin/cat", fmt.Sprintf("/sys/devices/system/node/node%d/cpulist", numaNode))
112113

113114
cpus, err := cpuset.Parse(nodeCPUList)
@@ -137,7 +138,7 @@ func getCPUToNUMANodeMapFromEnv(f *framework.Framework, pod *v1.Pod, environ map
137138
return CPUMap, nil
138139
}
139140

140-
func getPCIDeviceToNumaNodeMapFromEnv(f *framework.Framework, pod *v1.Pod, environ map[string]string) (map[string]int, error) {
141+
func getPCIDeviceToNumaNodeMapFromEnv(f *framework.Framework, pod *v1.Pod, cnt *v1.Container, environ map[string]string) (map[string]int, error) {
141142
pciDevPrefix := "PCIDEVICE_"
142143
// at this point we don't care which plugin selected the device,
143144
// we only need to know which devices were assigned to the POD.
@@ -152,19 +153,11 @@ func getPCIDeviceToNumaNodeMapFromEnv(f *framework.Framework, pod *v1.Pod, envir
152153
// a single plugin can allocate more than a single device
153154
pciDevs := strings.Split(value, ",")
154155
for _, pciDev := range pciDevs {
155-
pciDevNUMANode := f.ExecCommandInContainer(pod.Name, pod.Spec.Containers[0].Name,
156+
pciDevNUMANode := f.ExecCommandInContainer(pod.Name, cnt.Name,
156157
"/bin/cat", fmt.Sprintf("/sys/bus/pci/devices/%s/numa_node", pciDev))
157-
158-
nodeNum, err := strconv.Atoi(pciDevNUMANode)
159-
if err != nil {
160-
return nil, err
161-
}
162-
NUMAPerDev[pciDev] = nodeNum
158+
NUMAPerDev[pciDev] = numaNodeFromSysFsEntry(pciDevNUMANode)
163159
}
164160
}
165-
if len(NUMAPerDev) == 0 {
166-
return nil, fmt.Errorf("no PCI devices found in environ")
167-
}
168161
return NUMAPerDev, nil
169162
}
170163

@@ -184,29 +177,97 @@ func makeEnvMap(logs string) (map[string]string, error) {
184177
return envMap, nil
185178
}
186179

187-
func checkNUMAAlignment(f *framework.Framework, pod *v1.Pod, logs string, numaNodes int) (numaPodResources, error) {
180+
type testEnvInfo struct {
181+
numaNodes int
182+
sriovResourceName string
183+
policy string
184+
}
185+
186+
func containerWantsDevices(cnt *v1.Container, envInfo *testEnvInfo) bool {
187+
_, found := cnt.Resources.Requests[v1.ResourceName(envInfo.sriovResourceName)]
188+
return found
189+
}
190+
191+
func checkNUMAAlignment(f *framework.Framework, pod *v1.Pod, cnt *v1.Container, logs string, envInfo *testEnvInfo) (*numaPodResources, error) {
192+
var err error
188193
podEnv, err := makeEnvMap(logs)
189194
if err != nil {
190-
return numaPodResources{}, err
195+
return nil, err
191196
}
192197

193-
CPUToNUMANode, err := getCPUToNUMANodeMapFromEnv(f, pod, podEnv, numaNodes)
198+
CPUToNUMANode, err := getCPUToNUMANodeMapFromEnv(f, pod, cnt, podEnv, envInfo.numaNodes)
194199
if err != nil {
195-
return numaPodResources{}, err
200+
return nil, err
196201
}
197202

198-
PCIDevsToNUMANode, err := getPCIDeviceToNumaNodeMapFromEnv(f, pod, podEnv)
203+
PCIDevsToNUMANode, err := getPCIDeviceToNumaNodeMapFromEnv(f, pod, cnt, podEnv)
199204
if err != nil {
200-
return numaPodResources{}, err
205+
return nil, err
201206
}
202207

208+
if containerWantsDevices(cnt, envInfo) && len(PCIDevsToNUMANode) == 0 {
209+
return nil, fmt.Errorf("no PCI devices found in environ")
210+
}
203211
numaRes := numaPodResources{
204212
CPUToNUMANode: CPUToNUMANode,
205213
PCIDevsToNUMANode: PCIDevsToNUMANode,
206214
}
207215
aligned := numaRes.CheckAlignment()
208216
if !aligned {
209-
return numaRes, fmt.Errorf("NUMA resources not aligned")
217+
err = fmt.Errorf("NUMA resources not aligned")
210218
}
211-
return numaRes, nil
219+
return &numaRes, err
220+
}
221+
222+
type pciDeviceInfo struct {
223+
Address string
224+
NUMANode int
225+
IsPhysFn bool
226+
IsVFn bool
227+
}
228+
229+
func getPCIDeviceInfo(sysPCIDir string) ([]pciDeviceInfo, error) {
230+
var pciDevs []pciDeviceInfo
231+
232+
entries, err := ioutil.ReadDir(sysPCIDir)
233+
if err != nil {
234+
return nil, err
235+
}
236+
237+
for _, entry := range entries {
238+
isPhysFn := false
239+
isVFn := false
240+
if _, err := os.Stat(filepath.Join(sysPCIDir, entry.Name(), "sriov_numvfs")); err == nil {
241+
isPhysFn = true
242+
} else if !os.IsNotExist(err) {
243+
// unexpected error. Bail out
244+
return nil, err
245+
}
246+
if _, err := os.Stat(filepath.Join(sysPCIDir, entry.Name(), "physfn")); err == nil {
247+
isVFn = true
248+
} else if !os.IsNotExist(err) {
249+
// unexpected error. Bail out
250+
return nil, err
251+
}
252+
253+
content, err := ioutil.ReadFile(filepath.Join(sysPCIDir, entry.Name(), "numa_node"))
254+
if err != nil {
255+
return nil, err
256+
}
257+
258+
pciDevs = append(pciDevs, pciDeviceInfo{
259+
Address: entry.Name(),
260+
NUMANode: numaNodeFromSysFsEntry(string(content)),
261+
IsPhysFn: isPhysFn,
262+
IsVFn: isVFn,
263+
})
264+
}
265+
266+
return pciDevs, nil
267+
}
268+
269+
func numaNodeFromSysFsEntry(content string) int {
270+
nodeNum, err := strconv.Atoi(strings.TrimSpace(content))
271+
framework.ExpectNoError(err, "error detecting the device numa_node from sysfs: %v", err)
272+
return nodeNum
212273
}

0 commit comments

Comments
 (0)