Skip to content

Commit

Permalink
[release-4.14] OCPBUGS-26003: E2E: PPC Test cases (#905)
Browse files Browse the repository at this point in the history
* Add variables for mustgather and NTO image

Adds to new environment variables
NTO_IMAGE_REGISTRY and MUSGATHER_DIR for providing
NTO image and mustgather directory respectively

Signed-off-by: Niranjan M.R <mrniranjan@redhat.com>

* gexec vendor updates

Signed-off-by: Niranjan M.R <mrniranjan@redhat.com>

* E2E: PPC test cases

PPC Test cases executed through podman

Signed-off-by: Niranjan M.R <mrniranjan@redhat.com>

* Include E2E ppc to be executed as part of functional tests

Signed-off-by: Niranjan M.R <mrniranjan@redhat.com>

* Removed unused variables and minor review fixes

Signed-off-by: Niranjan M.R <mrniranjan@redhat.com>

* minor gofmt fixes

Signed-off-by: Niranjan M.R <mrniranjan@redhat.com>

* Remove hardcoded values of reserved and isolated

Signed-off-by: Niranjan M.R <mrniranjan@redhat.com>

* Remove unused struct and rename NtoImageRegistry as NtoImage

Signed-off-by: Niranjan M.R <mrniranjan@redhat.com>

* use cpuset to get length of cpus

Signed-off-by: Niranjan M.R <mrniranjan@redhat.com>

* update the NTOImage variable

Signed-off-by: Niranjan M.R <mrniranjan@redhat.com>

---------

Signed-off-by: Niranjan M.R <mrniranjan@redhat.com>
Co-authored-by: Niranjan M.R <mrniranjan@redhat.com>
  • Loading branch information
openshift-cherrypick-robot and Niranjan M.R committed Jan 9, 2024
1 parent c2dffde commit 6d4553b
Show file tree
Hide file tree
Showing 12 changed files with 1,381 additions and 1 deletion.
2 changes: 1 addition & 1 deletion Makefile
Expand Up @@ -201,7 +201,7 @@ pao-functests: cluster-label-worker-cnf pao-functests-only
pao-functests-only:
@echo "Cluster Version"
hack/show-cluster-version.sh
hack/run-test.sh -t "test/e2e/performanceprofile/functests/0_config test/e2e/performanceprofile/functests/1_performance test/e2e/performanceprofile/functests/6_mustgather_testing" -p "-v -r --fail-fast --flake-attempts=2 --junit-report=report.xml" -m "Running Functional Tests"
hack/run-test.sh -t "test/e2e/performanceprofile/functests/0_config test/e2e/performanceprofile/functests/1_performance test/e2e/performanceprofile/functests/6_mustgather_testing test/e2e/performanceprofile/functests/10_performance_ppc" -p "-v -r --fail-fast --flake-attempts=2 --junit-report=report.xml" -m "Running Functional Tests"

.PHONY: pao-functests-updating-profile
pao-functests-updating-profile: cluster-label-worker-cnf pao-functests-update-only
Expand Down
@@ -0,0 +1,39 @@
package __performance_ppc

import (
"fmt"
"os/exec"
"testing"

. "github.com/onsi/ginkgo/v2"

. "github.com/onsi/gomega"
testutils "github.com/openshift/cluster-node-tuning-operator/test/e2e/performanceprofile/functests/utils"
testlog "github.com/openshift/cluster-node-tuning-operator/test/e2e/performanceprofile/functests/utils/log"
)

const (
DefaultPodmanBinaryPath = "/usr/bin/podman"
)

var _ = BeforeSuite(func() {
var err error
By("Check podman binary exists")
path, err := exec.LookPath(DefaultPodmanBinaryPath)
if err != nil {
Skip(fmt.Sprintf("%s doesn't exists", DefaultPodmanBinaryPath))
}
testlog.Infof("Podman binary executed from path %s", path)
By("Checking Environment Variables")
testlog.Infof("NTO Image used: %s", testutils.NTOImage)
if testutils.MustGatherDir == "" {
Skip("set env variable MUSTGATHER_DIR to ocp mustgather directory")
}
testlog.Infof("Mustgather Directory used: %s", testutils.MustGatherDir)

})

func TestPPC(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "PPC Suite")
}
198 changes: 198 additions & 0 deletions test/e2e/performanceprofile/functests/10_performance_ppc/ppc.go
@@ -0,0 +1,198 @@
package __performance_ppc

import (
"fmt"
"os/exec"
"regexp"
"strings"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/gexec"
performancev2 "github.com/openshift/cluster-node-tuning-operator/pkg/apis/performanceprofile/v2"
testutils "github.com/openshift/cluster-node-tuning-operator/test/e2e/performanceprofile/functests/utils"
testlog "github.com/openshift/cluster-node-tuning-operator/test/e2e/performanceprofile/functests/utils/log"
"k8s.io/kubernetes/pkg/kubelet/cm/cpuset"
"sigs.k8s.io/yaml"
)

type PPCTest struct {
PodmanMakeOptions func(args []string) []string
PodmanBinary string
}

type PPCSession struct {
*gexec.Session
}

func (p *PPCTest) MakeOptions(args []string) []string {
return p.PodmanMakeOptions(args)
}

func (p *PPCTest) PodmanAsUserBase(args []string, noEvents, noCache bool) (*PPCSession, error) {
var command *exec.Cmd
podmanOptions := p.MakeOptions(args)
podmanBinary := p.PodmanBinary
fmt.Printf("Running: %s %s\n", podmanBinary, strings.Join(podmanOptions, " "))
command = exec.Command(podmanBinary, podmanOptions...)
session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
if err != nil {
return nil, err
}

return &PPCSession{session}, nil
}

type PPCTestIntegration struct {
PPCTest
}

func (p *PPCTestIntegration) MakeOptions(args []string) []string {
return args
}
func PPCTestCreateUtil() *PPCTestIntegration {
p := &PPCTestIntegration{
PPCTest: PPCTest{
PodmanBinary: DefaultPodmanBinaryPath,
},
}
p.PodmanMakeOptions = p.MakeOptions
return p
}

var _ = Describe("[rfe_id: 38968] PerformanceProfile setup helper and platform awareness", func() {
mustgatherDir := testutils.MustGatherDir
ntoImage := testutils.NTOImage
Context("PPC Sanity Tests", func() {
ppcIntgTest := PPCTestCreateUtil()
It("[test_id:40940] Performance Profile regression tests", func() {
pp := &performancev2.PerformanceProfile{}
var reservedCpuCount = 2
defaultArgs := []string{
"run",
"--entrypoint",
"performance-profile-creator",
"-v",
}

cmdArgs := []string{
fmt.Sprintf("%s:%s:z", mustgatherDir, mustgatherDir),
ntoImage,
"--mcp-name=worker",
fmt.Sprintf("--reserved-cpu-count=%d", reservedCpuCount),
fmt.Sprintf("--rt-kernel=%t", true),
fmt.Sprintf("--power-consumption-mode=%s", "low-latency"),
fmt.Sprintf("--split-reserved-cpus-across-numa=%t", false),
fmt.Sprintf("--must-gather-dir-path=%s", mustgatherDir),
}
podmanArgs := []string{}
podmanArgs = append(defaultArgs, cmdArgs...)
session, err := ppcIntgTest.PodmanAsUserBase(podmanArgs, false, false)
Expect(err).ToNot(HaveOccurred(), "Podman command failed")
output := session.Wait(20).Out.Contents()
err = yaml.Unmarshal(output, pp)
Expect(err).ToNot(HaveOccurred(), "Unable to marshal the ppc output")
reservedCpus, err := cpuset.Parse(string(*pp.Spec.CPU.Reserved))
Expect(err).ToNot(HaveOccurred(), "Unable to parse cpus")
totalReservedCpus := reservedCpus.Size()
Expect(totalReservedCpus).To(Equal(reservedCpuCount))
Expect(*pp.Spec.RealTimeKernel.Enabled).To(BeTrue())
Expect(*pp.Spec.WorkloadHints.RealTime).To(BeTrue())
Expect(*pp.Spec.NUMA.TopologyPolicy).To(Equal("restricted"))
Eventually(session).Should(gexec.Exit(0))
})
It("[test_id:41405] Verify PPC script fails when the splitting of reserved cpus and single numa-node policy is specified", func() {
defaultArgs := []string{
"run",
"--entrypoint",
"performance-profile-creator",
"-v",
}
cmdArgs := []string{
fmt.Sprintf("%s:%s:z", mustgatherDir, mustgatherDir),
ntoImage,
"--mcp-name=worker",
fmt.Sprintf("--reserved-cpu-count=%d", 2),
fmt.Sprintf("--rt-kernel=%t", true),
fmt.Sprintf("--power-consumption-mode=%s", "low-latency"),
fmt.Sprintf("--split-reserved-cpus-across-numa=%t", true),
fmt.Sprintf("--topology-manager-policy=%s", "single-numa-node"),
fmt.Sprintf("--must-gather-dir-path=%s", mustgatherDir),
}
podmanArgs := []string{}
podmanArgs = append(defaultArgs, cmdArgs...)
session, err := ppcIntgTest.PodmanAsUserBase(podmanArgs, false, false)
Expect(err).ToNot(HaveOccurred(), "Podman command failed")
output := session.Wait(20).Err.Contents()
errString := "Error: failed to obtain data from flags not appropriate to split reserved CPUs in case of topology-manager-policy: single-numa-node"
ok, err := regexp.MatchString(errString, string(output))
if ok {
testlog.Info(errString)
}
Eventually(session).Should(gexec.Exit(1))
})

It("[test_id:41419] Verify PPC script fails when reserved cpu count is 2 and requires to split across numa nodes", func() {
defaultArgs := []string{
"run",
"--entrypoint",
"performance-profile-creator",
"-v",
}
cmdArgs := []string{
fmt.Sprintf("%s:%s:z", mustgatherDir, mustgatherDir),
ntoImage,
"--mcp-name=worker",
fmt.Sprintf("--reserved-cpu-count=%d", 2),
fmt.Sprintf("--rt-kernel=%t", true),
fmt.Sprintf("--power-consumption-mode=%s", "low-latency"),
fmt.Sprintf("--split-reserved-cpus-across-numa=%t", true),
fmt.Sprintf("--must-gather-dir-path=%s", mustgatherDir),
}
podmanArgs := []string{}
podmanArgs = append(defaultArgs, cmdArgs...)
session, err := ppcIntgTest.PodmanAsUserBase(podmanArgs, false, false)
Expect(err).ToNot(HaveOccurred(), "Podman command failed")
output := session.Wait(20).Err.Contents()
errString := "Error: failed to compute the reserved and isolated CPUs: can't allocate odd number of CPUs from a NUMA Node"
ok, err := regexp.MatchString(errString, string(output))
Expect(err).ToNot(HaveOccurred(), "did not fail with Expected:%s failure", errString)
if ok {
testlog.Info(errString)
}
Eventually(session).Should(gexec.Exit(1))
})

It("[test_id:41420] Verify PPC script fails when reserved cpu count is more than available cpus", func() {
defaultArgs := []string{
"run",
"--entrypoint",
"performance-profile-creator",
"-v",
}
cmdArgs := []string{
fmt.Sprintf("%s:%s:z", mustgatherDir, mustgatherDir),
ntoImage,
"--mcp-name=worker",
fmt.Sprintf("--reserved-cpu-count=%d", 100),
fmt.Sprintf("--rt-kernel=%t", true),
fmt.Sprintf("--power-consumption-mode=%s", "low-latency"),
fmt.Sprintf("--split-reserved-cpus-across-numa=%t", true),
fmt.Sprintf("--must-gather-dir-path=%s", mustgatherDir),
}
podmanArgs := []string{}
podmanArgs = append(defaultArgs, cmdArgs...)
session, err := ppcIntgTest.PodmanAsUserBase(podmanArgs, false, false)
Expect(err).ToNot(HaveOccurred(), "Podman command failed")
output := session.Wait(20).Err.Contents()
errString := "Error: failed to compute the reserved and isolated CPUs: please specify the reserved CPU count in the range [1,3]"
ok, err := regexp.MatchString(errString, string(output))
Expect(err).ToNot(HaveOccurred(), "did not fail with Expected:%s failure", errString)
if ok {
testlog.Info(errString)
}
Eventually(session).Should(gexec.Exit(1))
})

})
})
14 changes: 14 additions & 0 deletions test/e2e/performanceprofile/functests/utils/consts.go
Expand Up @@ -24,6 +24,12 @@ var NodesSelector string
// ProfileNotFound is true when discovery mode is enabled and no valid profile was found
var ProfileNotFound bool

// NtoImage represents NTO Image location which is either quay.io or any other internal registry
var NTOImage string

// MustGatherDir represents Mustgather directory created using oc adm mustgather
var MustGatherDir string

func init() {
RoleWorkerCNF = os.Getenv("ROLE_WORKER_CNF")
if RoleWorkerCNF == "" {
Expand All @@ -41,6 +47,14 @@ func init() {
fmt.Sprintf("%s/%s", LabelRole, RoleWorkerCNF): "",
}

NTOImage = os.Getenv("NTO_IMAGE")

if NTOImage == "" {
NTOImage = "quay.io/openshift/origin-cluster-node-tuning-operator:latest"
}

MustGatherDir = os.Getenv("MUSTGATHER_DIR")

if discovery.Enabled() {
profile, err := discovery.GetDiscoveryPerformanceProfile(NodesSelector)
if err == discovery.ErrProfileNotFound {
Expand Down

0 comments on commit 6d4553b

Please sign in to comment.