Skip to content

evetest: purge with the designated node down - #6478

Open
eriknordmark wants to merge 2 commits into
lf-edge:masterfrom
eriknordmark:purge-during-failover
Open

evetest: purge with the designated node down#6478
eriknordmark wants to merge 2 commits into
lf-edge:masterfrom
eriknordmark:purge-during-failover

Conversation

@eriknordmark

Copy link
Copy Markdown
Contributor

Description

A purge must not gate its teardown on the app's designated node, nor on wherever
a replica happens to be scheduled: neither signal is both durable and
liveness-aware, so either one deadlocks a purge issued while the designated node
is down. Nothing covered that case.

TestVMAppPurgeDuringFailover does: a three-node replicated-storage cluster, an
app deployed with a preferred designated node, that node powered off so KubeVirt
reschedules the replica elsewhere, and the purge issued while it is still down.
The surviving workload must be exactly one VMIRS, named for the new generation.
It makes no volume or guest-level assertion — replicated-storage VolumeStatus
semantics across a node failover are not established for this suite.

The second commit is a REMOVE ME workaround for an infra bug, not for
anything the suite tests. A first-ever PVC creation can stall forever in
Longhorn's CSI provisioner, whose ProvisioningFailed events alternate "volume
not found" and "volume already exists"; restarting the provisioner pod clears it
on the next retry. The mitigation wraps only this test's app-running wait, fires
only after the signature has held continuously for two minutes, and restarts the
pod once. Delete that file and its single call site once Longhorn no longer
needs the restart.

Both commits were drafted as part of #6318, which also carried a gcPVCs PVC
reclaim and re-enabled the Kubevirt assertNoOrphanedPVCs check. Both of those
now live in #6406 — the pillar files are byte-identical there and its unit tests
are a superset — so #6318 is closed and this PR is the test-only remainder.

The test sits in evetest/tests/apps rather than evetest/tests/cluster, where
the other multi-node tests live, because every helper it uses is defined in the
apps package: vmShimApplication, assertExactlyOneVMIRSAtGeneration,
listAppVMIRS, kubectlListItems, singleVIFWithSSH and the purge timeout
constants. Relocating it would mean duplicating those into a second package;
promoting them to the framework first, then moving the test, is the better
sequence and is left as follow-up.

PR dependencies

None. The end-state assertion is on VMIRS objects, so this test does not need
the gcPVCs reclaim in #6406.

If #6406 lands first, the workaround commit needs a small rebase: it calls the
package-local kubectlListItems, which #6406 promotes to
EdgeDevice.KubectlListItems alongside a new RunKubectl.

How to test and validate this PR

Kubevirt only, and it needs three devices; it is registered last in
TestAppsSuite for that reason. To run it alone:

EVETEST_HYPERVISOR=kubevirt make evetest NAME=TestVMAppPurgeDuringFailover

It skips on any other HYPERVISOR. EVETEST_TPM and EVETEST_FILESYSTEM
(ext4|zfs, default ext4) are the other parameters. The
checkpoints to watch are app-is-deployed (the app must land on its preferred
designated node while that node is healthy), failed-over (the replica
rescheduled onto another node with the powered-off one excluded from the
lookup), and purge-complete — a purge that gates on the dead node hangs here
rather than failing an assertion.

To confirm the test can fail: the decisive check is "exactly one VMIRS, named
for the new generation", which a resurrected or stranded generation breaks.

Changelog notes

None — test-only.

PR Backports

  • 17.0-stable: No, new test coverage only.
  • 16.0-stable: No, new test coverage only.
  • 14.5-stable: No, new test coverage only.
  • 13.4-stable: No, new test coverage only.

Checklist

  • I've provided a proper description
  • I've added the proper documentation — not applicable, test-only
  • I've tested my PR on amd64 device
  • I've tested my PR on arm64 device — the suite is amd64/Kubevirt
  • I've written the test verification instructions
  • I've set the proper labels to this PR

@codecov

codecov Bot commented Sep 7, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 26.25%. Comparing base (4a2d056) to head (8bc3c48).

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #6478      +/-   ##
==========================================
+ Coverage   25.95%   26.25%   +0.30%     
==========================================
  Files         513      523      +10     
  Lines       94167    95883    +1716     
==========================================
+ Hits        24437    25174     +737     
- Misses      67846    68640     +794     
- Partials     1884     2069     +185     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

andrewd-zededa and others added 2 commits September 9, 2026 16:26
A purge must not gate its teardown on the app's designated node, nor on
wherever a replica happens to be scheduled: neither signal is both durable
and liveness-aware, so either one deadlocks a purge issued while the
designated node is down.

Add a three-node cluster test for that case. The app is deployed with a
preferred designated node, that node is powered off so KubeVirt reschedules
the replica elsewhere, and the purge is issued while it is still down; the
surviving workload must be exactly one VMIRS, named for the new generation.

Signed-off-by: eriknordmark <erik@zededa.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A PVC can stay Pending forever. Its ProvisioningFailed events alternate
"volume not found" and "volume already exists" - the provisioner created the
Longhorn backend volume once, lost track of that success in its own cache,
and keeps retrying a name it no longer recognizes. This hits
TestVMAppPurgeDuringFailover at first-ever PVC creation, timing it out
before it reaches the failover step it tests. Confirmed live with no EVE or
pillar change involved: deleting the csi-provisioner pod forces a fresh
leader election and cache, and the next retry succeeds.

waitForAppRunningMitigatingPVCStall wraps the app-running wait with a
background watcher that restarts csi-provisioner once, and only after a PVC
has shown the failure signature continuously for two minutes. A PVC that
clears on its own before then passes through untouched, and the wait's own
timeout and failure behavior are unchanged. It is wired into the failover
test alone, the one test observed to fail this way, because restarting a
cluster-wide Longhorn pod is not something to do from every test that
creates a volume.

Marked REMOVE ME: it works around infra, not anything this suite tests.

Signed-off-by: eriknordmark <erik@zededa.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@eriknordmark
eriknordmark marked this pull request as ready for review September 9, 2026 14:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants