Skip to content

Commit 16309cc

Browse files
qat,e2e: add heartbeat and auto-reset validations
Signed-off-by: Hyeongju Johannes Lee <[email protected]>
1 parent 7c365e8 commit 16309cc

File tree

2 files changed

+105
-0
lines changed

2 files changed

+105
-0
lines changed

test/e2e/qat/qatplugin_dpdk.go

+89
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,19 @@ import (
2929
"k8s.io/apimachinery/pkg/labels"
3030
"k8s.io/kubernetes/test/e2e/framework"
3131
e2edebug "k8s.io/kubernetes/test/e2e/framework/debug"
32+
e2ejob "k8s.io/kubernetes/test/e2e/framework/job"
3233
e2ekubectl "k8s.io/kubernetes/test/e2e/framework/kubectl"
3334
e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
35+
imageutils "k8s.io/kubernetes/test/utils/image"
3436
admissionapi "k8s.io/pod-security-admission/api"
3537
)
3638

3739
const (
3840
qatPluginKustomizationYaml = "deployments/qat_plugin/overlays/e2e/kustomization.yaml"
3941
cryptoTestYaml = "deployments/qat_dpdk_app/crypto-perf/crypto-perf-dpdk-pod-requesting-qat-cy.yaml"
4042
compressTestYaml = "deployments/qat_dpdk_app/compress-perf/compress-perf-dpdk-pod-requesting-qat-dc.yaml"
43+
cy = "qat.intel.com/cy"
44+
dc = "qat.intel.com/dc"
4145
)
4246

4347
const (
@@ -77,6 +81,7 @@ func describeQatDpdkPlugin() {
7781
var dpPodName string
7882

7983
var resourceName v1.ResourceName
84+
var nodeName string
8085

8186
ginkgo.JustBeforeEach(func(ctx context.Context) {
8287
ginkgo.By("deploying QAT plugin in DPDK mode")
@@ -97,6 +102,18 @@ func describeQatDpdkPlugin() {
97102
framework.Failf("container filesystem info checks failed: %v", err)
98103
}
99104

105+
// when running [Functionality] e2e tests
106+
if resourceName == "" {
107+
if err := utils.WaitForNodesWithResource(ctx, f.ClientSet, cy, 100*time.Second, utils.WaitForPositiveResource); err != nil {
108+
resourceName = dc
109+
nodeName, _ = utils.FindNodeAndResourceCapacity(f, ctx, dc)
110+
return
111+
}
112+
resourceName = cy
113+
nodeName, _ = utils.FindNodeAndResourceCapacity(f, ctx, cy)
114+
return
115+
}
116+
100117
ginkgo.By("checking if the resource is allocatable")
101118
if err := utils.WaitForNodesWithResource(ctx, f.ClientSet, resourceName, 30*time.Second, utils.WaitForPositiveResource); err != nil {
102119
framework.Failf("unable to wait for nodes to have positive allocatable resource: %v", err)
@@ -165,6 +182,45 @@ func describeQatDpdkPlugin() {
165182
ginkgo.It("does nothing", func() {})
166183
})
167184
})
185+
186+
ginkgo.Context("When QAT's autoreset is off [Functionality:heartbeat]", func() {
187+
ginkgo.BeforeEach(func() {
188+
ginkgo.By("creating a configMap before plugin gets deployed")
189+
e2ekubectl.RunKubectlOrDie(f.Namespace.Name, "create", "configmap", "--from-literal", "qat.conf=AutoresetEnabled=off", "qat-config")
190+
})
191+
192+
ginkgo.It("checks if the heartbeat is read correctly", func(ctx context.Context) {
193+
injectError(ctx, f, nodeName)
194+
195+
ginkgo.By("seeing if there is zero resource")
196+
if err := utils.WaitForNodesWithResource(ctx, f.ClientSet, resourceName, 100*time.Second, utils.WaitForZeroResource); err != nil {
197+
framework.Failf("unable to wait for nodes to have no resource: %v", err)
198+
}
199+
})
200+
})
201+
202+
ginkgo.Context("When QAT's autoreset is on [Functionality:auto-reset]", func() {
203+
ginkgo.BeforeEach(func() {
204+
ginkgo.By("creating a configMap before plugin gets deployed")
205+
e2ekubectl.RunKubectlOrDie(f.Namespace.Name, "create", "configmap", "--from-literal", "qat.conf=AutoresetEnabled=on", "qat-config")
206+
})
207+
208+
ginkgo.It("checks if an injected error gets solved", func(ctx context.Context) {
209+
injectError(ctx, f, nodeName)
210+
211+
ginkgo.By("seeing if there is zero resource")
212+
if err := utils.WaitForNodesWithResource(ctx, f.ClientSet, resourceName, 100*time.Second, utils.WaitForZeroResource); err != nil {
213+
// It should not fail since there can be a case auto-reset function worked before plugin notices.
214+
// It is still useful to wait for some time to ensure that injected error affects other specs.
215+
framework.Logf("unable to wait for nodes to have no resource: %v", err)
216+
}
217+
218+
ginkgo.By("seeing if there is positive allocatable resource")
219+
if err := utils.WaitForNodesWithResource(ctx, f.ClientSet, resourceName, 300*time.Second, utils.WaitForPositiveResource); err != nil {
220+
framework.Failf("unable to wait for nodes to have positive allocatable resource: %v", err)
221+
}
222+
})
223+
})
168224
}
169225

170226
func runCpaSampleCode(ctx context.Context, f *framework.Framework, runTests int, resourceName v1.ResourceName) {
@@ -199,3 +255,36 @@ func runCpaSampleCode(ctx context.Context, f *framework.Framework, runTests int,
199255
err = e2epod.WaitForPodSuccessInNamespaceTimeout(ctx, f.ClientSet, pod.ObjectMeta.Name, f.Namespace.Name, 300*time.Second)
200256
gomega.Expect(err).To(gomega.BeNil(), utils.GetPodLogs(ctx, f, pod.ObjectMeta.Name, pod.Spec.Containers[0].Name))
201257
}
258+
259+
func injectError(ctx context.Context, f *framework.Framework, nodeName string) {
260+
job := e2ejob.NewTestJobOnNode("success", "qat-inject-error", v1.RestartPolicyNever, 1, 1, nil, 0, nodeName)
261+
262+
job.Spec.Template.Spec.Containers[0].Image = imageutils.GetE2EImage(imageutils.BusyBox)
263+
job.Spec.Template.Spec.Containers[0].Command = []string{
264+
"/bin/sh",
265+
"-c",
266+
"find /sys/kernel/debug/qat_*/heartbeat/ -name inject_error -exec sh -c 'echo 1 > {}' \\;",
267+
}
268+
job.Spec.Template.Spec.Containers[0].VolumeMounts = []v1.VolumeMount{{
269+
Name: "debugfs",
270+
MountPath: "/sys/kernel/debug/",
271+
}}
272+
job.Spec.Template.Spec.Volumes = []v1.Volume{{
273+
Name: "debugfs",
274+
VolumeSource: v1.VolumeSource{
275+
HostPath: &v1.HostPathVolumeSource{
276+
Path: "/sys/kernel/debug/",
277+
},
278+
},
279+
}}
280+
yes := true
281+
job.Spec.Template.Spec.Containers[0].SecurityContext = &v1.SecurityContext{
282+
Privileged: &yes,
283+
}
284+
285+
job, err := e2ejob.CreateJob(ctx, f.ClientSet, f.Namespace.Name, job)
286+
framework.ExpectNoError(err, "failed to create job in namespace: %s", f.Namespace.Name)
287+
288+
err = e2ejob.WaitForJobComplete(ctx, f.ClientSet, f.Namespace.Name, job.Name, nil, 1)
289+
framework.ExpectNoError(err, "failed to ensure job completion in namespace: %s", f.Namespace.Name)
290+
}

test/e2e/utils/utils.go

+16
Original file line numberDiff line numberDiff line change
@@ -365,3 +365,19 @@ func Kubectl(ns string, cmd string, opt string, file string) {
365365
msg := e2ekubectl.RunKubectlOrDie(ns, cmd, opt, path)
366366
framework.Logf("%s", msg)
367367
}
368+
369+
func FindNodeAndResourceCapacity(f *framework.Framework, ctx context.Context, resourceName string) (string, int64) {
370+
nodelist, err := f.ClientSet.CoreV1().Nodes().List(ctx, metav1.ListOptions{})
371+
if err != nil {
372+
framework.Failf("failed to list Nodes: %v", err)
373+
}
374+
375+
// we have at least one node with resource capacity
376+
for _, item := range nodelist.Items {
377+
if q, ok := item.Status.Allocatable[v1.ResourceName(resourceName)]; ok && q.Value() > 0 {
378+
return item.Name, q.Value()
379+
}
380+
}
381+
382+
return "", 0
383+
}

0 commit comments

Comments
 (0)