Skip to content

OCPNODE-4470: Add DRA consumable capacity e2e tests - #31448

Draft
sairameshv wants to merge 1 commit into
openshift:mainfrom
sairameshv:dra_consumable_capacity
Draft

OCPNODE-4470: Add DRA consumable capacity e2e tests#31448
sairameshv wants to merge 1 commit into
openshift:mainfrom
sairameshv:dra_consumable_capacity

Conversation

@sairameshv

@sairameshv sairameshv commented Jul 29, 2026

Copy link
Copy Markdown
Member

Introduce tests for DRA consumable capacity (bandwidth sharing on NIC devices): resource slice validation, multi-allocation on the same device, capacity exhaustion scheduling, and capacity release after pod deletion.

Signed-ff-by: Sai Ramesh Vanka svanka@redhat.com

Summary by CodeRabbit

  • New Features
    • Added extended end-to-end coverage for consumable device capacity.
    • Validates capacity publication, multiple allocations, capacity consumption, exhaustion, and capacity release.
    • Added support for creating resource claims with requested capacity values.
    • Added validation helpers for device capacity, allocation behavior, schedulable nodes, and device counts.
  • Tests
    • Registered the consumable capacity test suite in the extended test package.

Introduce tests for DRA consumable capacity (bandwidth sharing on NIC
devices): resource slice validation, multi-allocation on the same device,
capacity exhaustion scheduling, and capacity release after pod deletion.

Signed-ff-by: Sai Ramesh Vanka <svanka@redhat.com>
@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Pipeline controller notification
This repo is configured to use the pipeline controller. Second-stage tests will be triggered either automatically or after lgtm label is added, depending on the repository configuration. The pipeline controller will automatically detect which contexts are required and will utilize /test Prow commands to trigger the second stage.

For optional jobs, comment /test ? to see a list of all defined jobs. To trigger manually all jobs from second stage use /pipeline required command.

This repository is configured in: automatic mode

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Jul 29, 2026
@openshift-ci-robot

openshift-ci-robot commented Jul 29, 2026

Copy link
Copy Markdown

@sairameshv: This pull request references OCPNODE-4470 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "5.0.0" version, but no target version was set.

Details

In response to this:

Introduce tests for DRA consumable capacity (bandwidth sharing on NIC devices): resource slice validation, multi-allocation on the same device, capacity exhaustion scheduling, and capacity release after pod deletion.

Signed-ff-by: Sai Ramesh Vanka svanka@redhat.com

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci openshift-ci Bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jul 29, 2026
@openshift-ci

openshift-ci Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Walkthrough

Changes

Consumable DRA capacity

Layer / File(s) Summary
Capacity validation and claim construction
test/extended/node/dra/common/capacity_validator.go, test/extended/node/dra/common/resource_builder.go
Adds helpers for validating published and consumed capacities, selecting device nodes, counting devices, and building capacity-aware claims.
Consumable capacity suite setup
test/extended/include.go, test/extended/node/dra/consumable/consumable_dra.go
Registers the suite, installs and configures the example network driver, waits for capacity devices, and restores the driver profile.
Allocation, exhaustion, and release scenarios
test/extended/node/dra/consumable/consumable_dra.go
Tests basic allocation, multiple allocations, exhausted capacity scheduling failures, and capacity reuse after resource deletion.

Estimated code review effort: 4 (Complex) | ~45 minutes

Suggested reviewers: sabujmaity

Sequence Diagram(s)

sequenceDiagram
  participant TestSuite
  participant ExampleDRA
  participant ResourceClaim
  participant Scheduler
  participant Pod
  participant CapacityValidator

  TestSuite->>ExampleDRA: configure net profile
  ExampleDRA-->>CapacityValidator: publish capacity devices
  TestSuite->>ResourceClaim: create capacity request
  TestSuite->>Pod: create consuming pod
  Pod->>Scheduler: request placement
  Scheduler-->>ResourceClaim: allocate device capacity
  CapacityValidator-->>TestSuite: validate ConsumedCapacity
  TestSuite->>ResourceClaim: delete claim and release capacity
Loading

Caution

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

  • Ignore

❌ Failed checks (1 error, 2 warnings)

Check name Status Explanation Resolution
No-Sensitive-Data-In-Logs ❌ Error The new DRA tests log raw node names via framework.Logf("Using node %s..."), which can expose internal hostnames. Avoid logging raw node/hostname values; redact or omit them from log messages, and review any condition-message logs for node details.
Test Structure And Quality ⚠️ Warning The release test creates consumeClaim/consumePod without deferred cleanup, and several cluster ops use bare ExpectNoError without context. Add deferred cleanup/AfterEach for consumeClaim and consumePod, and give bare expectations/waits descriptive failure messages.
Ipv6 And Disconnected Network Test Compatibility ⚠️ Warning The suite is tagged [Skipped:Disconnected], but its installer git-clones GitHub upstream repo, a public internet dependency, so it isn't disconnected-safe. Vendor or mirror the dra-example-driver source/chart inside the test environment and avoid public GitHub access, or keep the suite skipped on disconnected jobs.
✅ Passed checks (12 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: adding DRA consumable capacity end-to-end tests.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Stable And Deterministic Test Names ✅ Passed All Ginkgo Describe/Context/It titles in the new suite are static literals; no generated names, timestamps, UUIDs, or node/namespace values appear in titles.
Microshift Test Compatibility ✅ Passed The new DRA e2e suite calls nodeutils.SkipOnMicroShift(oc) before setup, so it won’t run on MicroShift, and it uses only core/Kubernetes resource APIs.
Single Node Openshift (Sno) Test Compatibility ✅ Passed No multi-node/HA assumptions found: tests use one node/device, not distinct nodes; helper even falls back to tainted nodes. No SNO skip needed.
Topology-Aware Scheduling Compatibility ✅ Passed PASS: the new DRA tests pin pods to a discovered hostname and add no anti-affinity, spread, worker/master selectors, replica logic, or PDBs.
Ote Binary Stdout Contract ✅ Passed No stdout writes were added in process-level code; new logging uses framework.Logf, which writes to GinkgoWriter, not stdout.
No-Weak-Crypto ✅ Passed Changed files contain no MD5/SHA1/DES/RC4/3DES/Blowfish/ECB, no crypto imports, and no secret-comparison code.
Container-Privileges ✅ Passed The new pod specs set AllowPrivilegeEscalation=false and drop ALL caps; no hostPID/hostNetwork/hostIPC/privileged/SYS_ADMIN fields appear in the touched code.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@openshift-ci

openshift-ci Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: sairameshv
Once this PR has been reviewed and has the lgtm label, please assign bertinatto for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
test/extended/node/dra/consumable/consumable_dra.go (2)

379-400: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Unschedulable assertion depends on free-text scheduler condition message.

The check requires cond.Message to contain "claim", "insufficient", or "unresolvable". This couples the test to the exact wording the DRA scheduler emits, which is not a documented/stable contract and could change across Kubernetes releases, causing this assertion to silently stop matching (test would then time out as "no DRA-related Unschedulable condition yet" rather than fail with a clear diagnosis).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/extended/node/dra/consumable/consumable_dra.go` around lines 379 - 400,
Update the unschedulable verification in the overflow pod polling block to rely
on stable pod scheduling status/reason fields rather than matching free-text
cond.Message substrings. Preserve validation that the pod remains Pending and
has a PodScheduled condition with False status, and provide a clear failure when
that condition is absent.

93-98: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Brittle error-message substring matching for skip-vs-fail decision.

strings.Contains(prerequisitesError.Error(), "not found or failed") couples control flow to free-text error wording from prereqInstaller.InstallAll. If that message ever changes, a genuine "tooling missing" case would incorrectly g.Fail (or vice versa). Prefer a typed/sentinel error (or errors.Is) from PrerequisitesInstaller to distinguish "tooling unavailable" from other failures.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/extended/node/dra/consumable/consumable_dra.go` around lines 93 - 98,
Replace the string-based check in the prerequisites handling block with a typed
or sentinel error classification exposed by PrerequisitesInstaller, using
errors.Is or the established equivalent to identify unavailable tooling. Keep
g.Skip for that specific condition and route all other prerequisite installation
errors to g.Fail.
test/extended/node/dra/common/capacity_validator.go (1)

37-51: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

HasCapacityDevices masks real API errors as "no capacity".

On a List failure it logs and returns false, identical to the legitimate "no devices publish capacity yet" case. This function is polled for up to 2 minutes in consumable_dra.go's BeforeAll (line 117-122); a persistent RBAC/API error would silently manifest as a suite-wide g.Skip("... no devices with Capacity published after upgrade") instead of a clear failure, hiding real infrastructure problems from CI.

Consider returning (bool, error) so the poller can fail fast on a genuine error and only continue polling on "not yet published".

♻️ Proposed fix
-func (cv *CapacityValidator) HasCapacityDevices(ctx context.Context) bool {
+func (cv *CapacityValidator) HasCapacityDevices(ctx context.Context) (bool, error) {
 	sliceList, err := cv.client.ResourceV1().ResourceSlices().List(ctx, cv.listOptions())
 	if err != nil {
-		framework.Logf("Failed to check for capacity devices: %v", err)
-		return false
+		return false, fmt.Errorf("failed to list ResourceSlices: %w", err)
 	}
 	for _, slice := range sliceList.Items {
 		for _, device := range slice.Spec.Devices {
 			if len(device.Capacity) > 0 {
-				return true
+				return true, nil
 			}
 		}
 	}
-	return false
+	return false, nil
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/extended/node/dra/common/capacity_validator.go` around lines 37 - 51,
Update CapacityValidator.HasCapacityDevices to return both the capacity result
and any ResourceSlices List error instead of converting API failures to false.
Propagate the error through consumable_dra.go's BeforeAll polling path so
genuine API or RBAC failures fail fast, while only a successful false result
continues polling for capacity publication.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/extended/node/dra/consumable/consumable_dra.go`:
- Around line 237-282: Update the cleanup deferred functions for pod1, pod2,
claim1, and claim2 in the consumable DRA test to wait until each resource is
actually deleted after issuing Delete. Reuse the existing Kubernetes wait
helpers or ResourceClaim polling utilities, and ensure all four resources are
absent before the next Ordered spec begins.

---

Nitpick comments:
In `@test/extended/node/dra/common/capacity_validator.go`:
- Around line 37-51: Update CapacityValidator.HasCapacityDevices to return both
the capacity result and any ResourceSlices List error instead of converting API
failures to false. Propagate the error through consumable_dra.go's BeforeAll
polling path so genuine API or RBAC failures fail fast, while only a successful
false result continues polling for capacity publication.

In `@test/extended/node/dra/consumable/consumable_dra.go`:
- Around line 379-400: Update the unschedulable verification in the overflow pod
polling block to rely on stable pod scheduling status/reason fields rather than
matching free-text cond.Message substrings. Preserve validation that the pod
remains Pending and has a PodScheduled condition with False status, and provide
a clear failure when that condition is absent.
- Around line 93-98: Replace the string-based check in the prerequisites
handling block with a typed or sentinel error classification exposed by
PrerequisitesInstaller, using errors.Is or the established equivalent to
identify unavailable tooling. Keep g.Skip for that specific condition and route
all other prerequisite installation errors to g.Fail.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 380f6d89-e760-490b-82b8-1deacdd9d2c5

📥 Commits

Reviewing files that changed from the base of the PR and between 15f2cf2 and 0b54d78.

📒 Files selected for processing (4)
  • test/extended/include.go
  • test/extended/node/dra/common/capacity_validator.go
  • test/extended/node/dra/common/resource_builder.go
  • test/extended/node/dra/consumable/consumable_dra.go

Comment on lines +237 to +282
defer func() {
if delErr := dracommon.DeleteResourceClaim(ctx, oc.KubeFramework().ClientSet, oc.Namespace(), claim1Name); delErr != nil {
framework.Logf("Warning: failed to delete ResourceClaim %s/%s: %v", oc.Namespace(), claim1Name, delErr)
}
}()

g.By("Creating first pod pinned to target node")
pod1 := builder.BuildLongRunningPodWithClaim(pod1Name, claim1Name, "")
pod1.Spec.NodeSelector = map[string]string{"kubernetes.io/hostname": nodeName}
pod1, err = oc.KubeFramework().ClientSet.CoreV1().Pods(oc.Namespace()).Create(ctx, pod1, metav1.CreateOptions{})
framework.ExpectNoError(err)
defer func() {
gracePeriod := int64(10)
if delErr := oc.KubeFramework().ClientSet.CoreV1().Pods(oc.Namespace()).Delete(ctx, pod1Name, metav1.DeleteOptions{GracePeriodSeconds: &gracePeriod}); delErr != nil && !errors.IsNotFound(delErr) {
framework.Logf("Warning: failed to delete pod %s/%s: %v", oc.Namespace(), pod1Name, delErr)
}
}()

g.By("Waiting for first pod to be running")
err = e2epod.WaitForPodRunningInNamespace(ctx, oc.KubeFramework().ClientSet, pod1)
framework.ExpectNoError(err, "First pod failed to start")

g.By("Creating second ResourceClaim requesting 10G ingress / 10G egress")
claim2 := builder.BuildResourceClaimWithCapacity(claim2Name, deviceClassName, 1, map[string]string{
"ingressBandwidth": "10G",
"egressBandwidth": "10G",
})
err = dracommon.CreateResourceClaim(ctx, oc.KubeFramework().ClientSet, oc.Namespace(), claim2)
framework.ExpectNoError(err)
defer func() {
if delErr := dracommon.DeleteResourceClaim(ctx, oc.KubeFramework().ClientSet, oc.Namespace(), claim2Name); delErr != nil {
framework.Logf("Warning: failed to delete ResourceClaim %s/%s: %v", oc.Namespace(), claim2Name, delErr)
}
}()

g.By("Creating second pod pinned to same node")
pod2 := builder.BuildLongRunningPodWithClaim(pod2Name, claim2Name, "")
pod2.Spec.NodeSelector = map[string]string{"kubernetes.io/hostname": nodeName}
pod2, err = oc.KubeFramework().ClientSet.CoreV1().Pods(oc.Namespace()).Create(ctx, pod2, metav1.CreateOptions{})
framework.ExpectNoError(err)
defer func() {
gracePeriod := int64(10)
if delErr := oc.KubeFramework().ClientSet.CoreV1().Pods(oc.Namespace()).Delete(ctx, pod2Name, metav1.DeleteOptions{GracePeriodSeconds: &gracePeriod}); delErr != nil && !errors.IsNotFound(delErr) {
framework.Logf("Warning: failed to delete pod %s/%s: %v", oc.Namespace(), pod2Name, delErr)
}
}()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Inspect DeleteResourceClaim/DeleteDeviceClass/CreateResourceClaim to see if they block until removal.
rg -n -B2 -A25 'func DeleteResourceClaim|func DeleteDeviceClass|func CreateResourceClaim' test/extended/node/dra/common

# Check whether exutil's per-spec project teardown waits for full namespace deletion.
rg -n -B2 -A20 'func NewCLIWithPodSecurityLevel|func \(c \*CLI\) TeardownProject|func.*[Tt]eardown' test/extended/util

Repository: openshift/origin

Length of output: 6260


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the relevant test sections and surrounding Ordered structure.
sed -n '200,520p' test/extended/node/dra/consumable/consumable_dra.go

# Find the Ordered container and any shared cleanup between these specs.
rg -n 'Ordered|AfterEach|BeforeEach|DeferCleanup|TeardownProject|DeleteResourceClaim|WaitForPodNotFoundInNamespace' test/extended/node/dra/consumable/consumable_dra.go test/extended/util/client.go test/extended/node/dra/common/crud_helpers.go

Repository: openshift/origin

Length of output: 19155


Wait for pod and ResourceClaim deletion before the next Ordered spec Delete() only sends the request here, so the following full-capacity allocation can race stale bandwidth. Add a wait for both resources to disappear before starting the next spec.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/extended/node/dra/consumable/consumable_dra.go` around lines 237 - 282,
Update the cleanup deferred functions for pod1, pod2, claim1, and claim2 in the
consumable DRA test to wait until each resource is actually deleted after
issuing Delete. Reuse the existing Kubernetes wait helpers or ResourceClaim
polling utilities, and ensure all four resources are absent before the next
Ordered spec begins.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants