Skip to content

🐛 e2e: Serialize default KMS provider across concurrent jobs - #1797

Open
aakashchan wants to merge 7 commits into
vmware-tanzu:mainfrom
aakashchan:topic/aakashc/encryption-kms-native-lock
Open

🐛 e2e: Serialize default KMS provider across concurrent jobs#1797
aakashchan wants to merge 7 commits into
vmware-tanzu:mainfrom
aakashchan:topic/aakashc/encryption-kms-native-lock

Conversation

@aakashchan

@aakashchan aakashchan commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

What does this PR do, and why is it needed?

vCenter's default KMS provider (CryptoManagerKmip.SetDefaultKmsCluster
/ GetDefaultKmsCluster called with entity=nil) is a single, VC-wide
setting — it is not scoped per-namespace, per-session, or per-test. The
vm_encryption.go E2E specs save and restore this value in
BeforeEach/AfterEach as if each test owned it exclusively. When two
E2E jobs run encryption specs concurrently against the same vCenter
appliance, one job's cleanup can clear or overwrite the default the
other job just set and is relying on, producing a spurious
VirtualMachineEncryptionSynced=NoDefaultKeyProvider failure and
timeout partway through VM creation.

This was root-caused from two UTS builds (1132205 and 1132208) that
ran encryption specs concurrently against the same shared vCenter: the
first build's AfterEach cleared the global default KMS provider 3
seconds before the second build's vTPM spec tried to create its VM,
which then failed because vm-operator correctly saw no default
provider configured.

This PR adds a distributed lock backed by a Kubernetes Lease in the
target supervisor cluster's vmware-system-vmop namespace, held for
the full read-mutate-restore window (from BeforeEach's read of the
current default through AfterEach's restore, via DeferCleanup), so
only one job at a time can mutate the default KMS provider for a given
vCenter appliance.

Changes:

  • Add AcquireDefaultKMSProviderLock in
    test/e2e/vmservice/utils/kmslock.go: an optimistic-concurrency
    create-or-take-over Lease lock with a bounded TTL so a crashed
    holder cannot permanently block other jobs.
  • Wire the lock into vm_encryption.go's BeforeEach, released after
    AfterEach restores the original default provider.
  • Register coordination/v1 in the shared e2e scheme
    (vmservice/common/scheme.go) so controller-runtime clients can
    read/write Lease objects — this was previously missing and caused
    the lock to fail with no kind is registered for the type v1.Lease.

Which issue(s) is/are addressed by this PR? (optional, in fixes #<issue number>(, fixes #<issue_number>, ...) format, will close the issue(s) when PR gets merged):

Fixes #

Are there any special notes for your reviewer:
UTS precheckin succeeded for all environment. Ran the encryption tests.

This is a test-infrastructure-only change (test/e2e/**); no product
(pkg/, api/) code is touched. Verified with go build ./...,
go vet, and gofmt on the e2e module; also validated live against a
real WCP testbed running the vm_encryption.go specs (surfaced and
fixed the missing coordination/v1 scheme registration in the
process).

Please add a release note if necessary:

NONE

The four Get-or-Create*StoragePolicy helpers in
test/e2e/infrastructure/vsphere/vcenter/storage.go each check
pbmClient.ProfileIDByName before calling CreateProfile, but had no
fallback if CreateProfile lost a create race. Two e2e shards
(e.g. Core and Experimental) sharing one testbed can both reach
SynchronizedBeforeSuite around the same time and race to create the
same fixed-name PBM storage profile (e.g. "worker-storagepolicy");
the loser got a PbmDuplicateName SOAP fault and failed its entire
suite with 0 specs run. Confirmed via UTS runs 1115673, 1108771, and
1108764, where two sibling shards created their content libraries
60ms apart against the same vCenter.
isPbmDuplicateNameFault manually unwrapped the SOAP fault via
soap.IsSoapFault/soap.ToSoapFault(...).VimFault(), which duplicates
logic govmomi already provides. Use fault.As against
types.PbmDuplicateName and types.PbmDuplicateNameFault instead,
matching the existing pattern in
pkg/providers/vsphere/vcenter/getvm.go.

Addresses review comment on PR vmware-tanzu#1788.
vCenter's default KMS provider (CryptoManagerKmip.SetDefaultKmsCluster
/ GetDefaultKmsCluster called with entity=nil) is a single, VC-wide
setting, not scoped per-namespace or per-test. The vm_encryption.go
specs save and restore it in BeforeEach/AfterEach as if each test
owned it exclusively. When two E2E jobs run encryption specs
concurrently against the same vCenter appliance, one job's cleanup
can clear or overwrite the default the other job just set and is
relying on, producing a spurious
VirtualMachineEncryptionSynced=NoDefaultKeyProvider failure.

Add a distributed lock backed by a Lease in the target supervisor
cluster's vmware-system-vmop namespace and hold it for the full
read-mutate-restore window (BeforeEach's read through AfterEach's
restore, via DeferCleanup) so only one job at a time can mutate the
default KMS provider for a given vCenter.

Changes:
- Add AcquireDefaultKMSProviderLock in
  test/e2e/vmservice/utils/kmslock.go, an optimistic-concurrency
  create-or-take-over Lease lock with a bounded TTL so a crashed
  holder cannot permanently block other jobs.
- Wire the lock into vm_encryption.go's BeforeEach, released after
  AfterEach restores the original default provider.
- Register coordination/v1 in the shared e2e scheme
  (vmservice/common/scheme.go) so controller-runtime clients can
  read/write Lease objects; this was previously missing and caused
  the lock to fail with "no kind is registered for the type v1.Lease".
@github-actions github-actions Bot added the size/L Denotes a PR that changes 100-499 lines. label Aug 5, 2026
@aakashchan
aakashchan marked this pull request as ready for review August 5, 2026 11:48
@aakashchan
aakashchan requested review from a team and faisalabujabal as code owners August 5, 2026 11:48
@aakashchan aakashchan changed the title Topic/aakashc/encryption kms native lock 🐛 e2e: Serialize default KMS provider across concurrent jobs Aug 5, 2026
test/e2e/infrastructure/vsphere/vcenter/storage.go's PBM
duplicate-profile-name handling is unrelated to the default-KMS-provider
lock work in this PR; drop it back to main so the PR only contains the
KMS-lock fix.
Keep only the non-obvious rationale (VC-wide setting, why the lock
lives in the supervisor cluster instead of vCenter) and drop
restatements of what the code already says, plus the ticket reference
so the comment stands on its own.
@faisalabujabal faisalabujabal added the pro-ai-review-requested Mark the PR as ready for the AI Review bot using a Pro model label Aug 5, 2026

@faisalabujabal faisalabujabal left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

post a message on the channel as we discussed that we are going with this solution. lets give the team a chance to object if anyone wants to

Comment thread test/e2e/vmservice/utils/kmslock.go Outdated
@svc-vmop-bot

Copy link
Copy Markdown

📝 CL Summary:

This PR introduces a distributed lock backed by a Kubernetes Lease to serialize access to vCenter's default KMS provider during end-to-end (E2E) tests. Because the KMS provider is a global vCenter setting, concurrent E2E jobs were previously overwriting each other's configurations, leading to spurious test failures. The changes implement the locking mechanism, integrate it into the VM encryption test setup and cleanup phases, and register the necessary coordination/v1 API scheme to support Lease objects.

@svc-vmop-bot svc-vmop-bot added the ai-reviewed This PR has been reviewed by the AI review bot label Aug 5, 2026
@faisalabujabal faisalabujabal removed the pro-ai-review-requested Mark the PR as ready for the AI Review bot using a Pro model label Aug 5, 2026
Comment thread test/e2e/vmservice/utils/kmslock.go Outdated
aakashchan and others added 2 commits August 12, 2026 18:52
Derives the Lease's lease-duration from the Ginkgo suite's own
--timeout (the same value hack/e2e/run-e2e.sh sets via GINKGO_TIMEOUT)
minus a buffer, instead of a separately maintained 15m constant, per
faisalabujabal's review comment to source it from the suite timeout.

Also preconditions releaseKMSLease's Delete on the Lease's UID and
resourceVersion captured at Get time, so a take-over landing between
the Get and Delete fails the delete with a conflict instead of
deleting a Lease this process no longer holds, per bryanv's review
comment.
The Lease's LeaseDurationSeconds was derived from the Ginkgo suite's
--timeout minus a buffer, so a holder could legitimately keep it for
up to that whole window (e.g. ~115m with --ginkgo.timeout=2h) while
waiters in AcquireDefaultKMSProviderLock only ever waited a fixed
10*time.Minute. Any time a holder's real BeforeEach+It+AfterEach work
ran long - observed swinging 4.6m to 7.5m per spec on live testbeds,
and up to ~12m just for namespace realization under load - a waiter
could exhaust its 10m budget and fail with "timed out waiting to
acquire the default KMS provider lock", even though the holder was
still alive and correctly serialized (UTS builds 1179655/1179879).

Shrinking the fixed lease duration instead of deriving it from the
suite timeout doesn't fix this: a static TTL either has to bound
worst-case runtime (which the observed variance shows is unsafe - a
holder judged "expired" while still alive causes two jobs to mutate
vCenter's global default KMS provider concurrently, the exact bug
this lock exists to prevent) or stays large enough that waiters keep
timing out under real contention.

Replace the fixed/derived TTL with a renewal loop: the lease duration
is now a short, fixed window (90s) that only bounds how fast a dead
holder (crash, panic) is reclaimed, and a background goroutine renews
RenewTime every 30s for as long as the holder is alive via
DeferCleanup, decoupling "how long the work takes" from "how long the
lock may be held". Waiters' timeout is bumped from 10m to 25m and
re-scoped to mean "how long to wait for queued jobs ahead of us",
sized off the several-minute-per-spec hold times actually observed,
since it's no longer coupled to lease TTL semantics at all.

Changes:
- kmslock.go: replace defaultKMSProviderLockLeaseDuration() (derived
  from GinkgoConfiguration().Timeout) with a fixed 90s constant, add
  renewKMSLeaseUntilStopped/renewKMSLease, and start/stop the renewal
  goroutine around the existing acquire/release in
  AcquireDefaultKMSProviderLock.
- vm_encryption.go: bump the lock-acquire wait timeout from 10m to
  25m and update the comment to reflect the new, decoupled meaning.

Test changes:
- No new test file; test/e2e/vmservice/utils has no unit-test
  convention today - this lock is exercised live by the
  vm_encryption.go specs it serializes, same as before this change.
@github-actions

Copy link
Copy Markdown

Code Coverage

Package Line Rate Health
github.com/vmware-tanzu/vm-operator/controllers/configtarget 74%
github.com/vmware-tanzu/vm-operator/controllers/contentlibrary/clustercontentlibraryitem 67%
github.com/vmware-tanzu/vm-operator/controllers/contentlibrary/contentlibraryitem 67%
github.com/vmware-tanzu/vm-operator/controllers/contentlibrary/utils 85%
github.com/vmware-tanzu/vm-operator/controllers/infra/capability/configmap 92%
github.com/vmware-tanzu/vm-operator/controllers/infra/capability/crd 100%
github.com/vmware-tanzu/vm-operator/controllers/infra/configmap 75%
github.com/vmware-tanzu/vm-operator/controllers/infra/node 77%
github.com/vmware-tanzu/vm-operator/controllers/infra/secret 76%
github.com/vmware-tanzu/vm-operator/controllers/infra/validatingwebhookconfiguration 87%
github.com/vmware-tanzu/vm-operator/controllers/infra/workloadnetworkconfig 86%
github.com/vmware-tanzu/vm-operator/controllers/infra/zone 80%
github.com/vmware-tanzu/vm-operator/controllers/storage/storageclass 93%
github.com/vmware-tanzu/vm-operator/controllers/storage/storagepolicy 96%
github.com/vmware-tanzu/vm-operator/controllers/storage/storagepolicyquota 91%
github.com/vmware-tanzu/vm-operator/controllers/storage/volumeattributesclass 93%
github.com/vmware-tanzu/vm-operator/controllers/util/encoding 73%
github.com/vmware-tanzu/vm-operator/controllers/virtualmachine/storagepolicyusage 96%
github.com/vmware-tanzu/vm-operator/controllers/virtualmachine/virtualmachine 65%
github.com/vmware-tanzu/vm-operator/controllers/virtualmachine/volume 86%
github.com/vmware-tanzu/vm-operator/controllers/virtualmachine/volumebatch 89%
github.com/vmware-tanzu/vm-operator/controllers/virtualmachineclass 73%
github.com/vmware-tanzu/vm-operator/controllers/virtualmachineconfigoptions 87%
github.com/vmware-tanzu/vm-operator/controllers/virtualmachinegroup 90%
github.com/vmware-tanzu/vm-operator/controllers/virtualmachinegrouppublishrequest 88%
github.com/vmware-tanzu/vm-operator/controllers/virtualmachineimagecache 89%
github.com/vmware-tanzu/vm-operator/controllers/virtualmachinepublishrequest 84%
github.com/vmware-tanzu/vm-operator/controllers/virtualmachinereplicaset 67%
github.com/vmware-tanzu/vm-operator/controllers/virtualmachineservice 90%
github.com/vmware-tanzu/vm-operator/controllers/virtualmachineservice/providers 93%
github.com/vmware-tanzu/vm-operator/controllers/virtualmachinesetresourcepolicy 81%
github.com/vmware-tanzu/vm-operator/controllers/virtualmachinesnapshot 91%
github.com/vmware-tanzu/vm-operator/controllers/virtualmachinewebconsolerequest 72%
github.com/vmware-tanzu/vm-operator/controllers/virtualmachinewebconsolerequest/v1alpha1 72%
github.com/vmware-tanzu/vm-operator/controllers/virtualmachinewebconsolerequest/v1alpha1/conditions 88%
github.com/vmware-tanzu/vm-operator/controllers/virtualmachinewebconsolerequest/v1alpha1/patch 78%
github.com/vmware-tanzu/vm-operator/controllers/vspherepolicy/policyevaluation 85%
github.com/vmware-tanzu/vm-operator/pkg/bitmask 100%
github.com/vmware-tanzu/vm-operator/pkg/builder 89%
github.com/vmware-tanzu/vm-operator/pkg/conditions 90%
github.com/vmware-tanzu/vm-operator/pkg/config 100%
github.com/vmware-tanzu/vm-operator/pkg/config/capabilities 97%
github.com/vmware-tanzu/vm-operator/pkg/config/env 100%
github.com/vmware-tanzu/vm-operator/pkg/context 37%
github.com/vmware-tanzu/vm-operator/pkg/context/generic 100%
github.com/vmware-tanzu/vm-operator/pkg/context/operation 100%
github.com/vmware-tanzu/vm-operator/pkg/crd 77%
github.com/vmware-tanzu/vm-operator/pkg/errors 74%
github.com/vmware-tanzu/vm-operator/pkg/exit 100%
github.com/vmware-tanzu/vm-operator/pkg/log 100%
github.com/vmware-tanzu/vm-operator/pkg/mem 100%
github.com/vmware-tanzu/vm-operator/pkg/patch 78%
github.com/vmware-tanzu/vm-operator/pkg/prober 89%
github.com/vmware-tanzu/vm-operator/pkg/prober/probe 90%
github.com/vmware-tanzu/vm-operator/pkg/prober/worker 77%
github.com/vmware-tanzu/vm-operator/pkg/providers/vsphere 74%
github.com/vmware-tanzu/vm-operator/pkg/providers/vsphere/clustermodules 73%
github.com/vmware-tanzu/vm-operator/pkg/providers/vsphere/config 88%
github.com/vmware-tanzu/vm-operator/pkg/providers/vsphere/contentlibrary 76%
github.com/vmware-tanzu/vm-operator/pkg/providers/vsphere/credentials 100%
github.com/vmware-tanzu/vm-operator/pkg/providers/vsphere/network 83%
github.com/vmware-tanzu/vm-operator/pkg/providers/vsphere/placement 70%
github.com/vmware-tanzu/vm-operator/pkg/providers/vsphere/session 60%
github.com/vmware-tanzu/vm-operator/pkg/providers/vsphere/storage 44%
github.com/vmware-tanzu/vm-operator/pkg/providers/vsphere/upgrade/virtualmachine 96%
github.com/vmware-tanzu/vm-operator/pkg/providers/vsphere/upgrade/virtualmachine/backfill 96%
github.com/vmware-tanzu/vm-operator/pkg/providers/vsphere/vcenter 86%
github.com/vmware-tanzu/vm-operator/pkg/providers/vsphere/virtualmachine 85%
github.com/vmware-tanzu/vm-operator/pkg/providers/vsphere/virtualmachine/extraconfig 91%
github.com/vmware-tanzu/vm-operator/pkg/providers/vsphere/virtualmachine/networkextraconfig 75%
github.com/vmware-tanzu/vm-operator/pkg/providers/vsphere/vmlifecycle 79%
github.com/vmware-tanzu/vm-operator/pkg/record 84%
github.com/vmware-tanzu/vm-operator/pkg/topology 91%
github.com/vmware-tanzu/vm-operator/pkg/util 79%
github.com/vmware-tanzu/vm-operator/pkg/util/cloudinit 89%
github.com/vmware-tanzu/vm-operator/pkg/util/cloudinit/validate 91%
github.com/vmware-tanzu/vm-operator/pkg/util/image 100%
github.com/vmware-tanzu/vm-operator/pkg/util/kube 91%
github.com/vmware-tanzu/vm-operator/pkg/util/kube/cource 100%
github.com/vmware-tanzu/vm-operator/pkg/util/kube/internal 100%
github.com/vmware-tanzu/vm-operator/pkg/util/kube/networksettings 100%
github.com/vmware-tanzu/vm-operator/pkg/util/kube/proxyaddr 73%
github.com/vmware-tanzu/vm-operator/pkg/util/kube/spq 99%
github.com/vmware-tanzu/vm-operator/pkg/util/linuxprep 97%
github.com/vmware-tanzu/vm-operator/pkg/util/netplan 100%
github.com/vmware-tanzu/vm-operator/pkg/util/nil 100%
github.com/vmware-tanzu/vm-operator/pkg/util/ovfcache 75%
github.com/vmware-tanzu/vm-operator/pkg/util/ovfcache/internal 100%
github.com/vmware-tanzu/vm-operator/pkg/util/paused 100%
github.com/vmware-tanzu/vm-operator/pkg/util/ptr 100%
github.com/vmware-tanzu/vm-operator/pkg/util/resize 98%
github.com/vmware-tanzu/vm-operator/pkg/util/sysprep 98%
github.com/vmware-tanzu/vm-operator/pkg/util/vmopv1 88%
github.com/vmware-tanzu/vm-operator/pkg/util/volumes 100%
github.com/vmware-tanzu/vm-operator/pkg/util/vsphere/client 66%
github.com/vmware-tanzu/vm-operator/pkg/util/vsphere/datastore 100%
github.com/vmware-tanzu/vm-operator/pkg/util/vsphere/fault 100%
github.com/vmware-tanzu/vm-operator/pkg/util/vsphere/library 95%
github.com/vmware-tanzu/vm-operator/pkg/util/vsphere/storage 82%
github.com/vmware-tanzu/vm-operator/pkg/util/vsphere/task 100%
github.com/vmware-tanzu/vm-operator/pkg/util/vsphere/vm 78%
github.com/vmware-tanzu/vm-operator/pkg/util/vsphere/watcher 85%
github.com/vmware-tanzu/vm-operator/pkg/vmconfig 95%
github.com/vmware-tanzu/vm-operator/pkg/vmconfig/anno2extraconfig 100%
github.com/vmware-tanzu/vm-operator/pkg/vmconfig/bootoptions 88%
github.com/vmware-tanzu/vm-operator/pkg/vmconfig/cdrom 88%
github.com/vmware-tanzu/vm-operator/pkg/vmconfig/crypto 92%
github.com/vmware-tanzu/vm-operator/pkg/vmconfig/diskpromo 100%
github.com/vmware-tanzu/vm-operator/pkg/vmconfig/extraconfig 100%
github.com/vmware-tanzu/vm-operator/pkg/vmconfig/networkextraconfig 79%
github.com/vmware-tanzu/vm-operator/pkg/vmconfig/policy 97%
github.com/vmware-tanzu/vm-operator/pkg/vmconfig/virtualcontroller 93%
github.com/vmware-tanzu/vm-operator/pkg/vmconfig/volumes/unmanaged/backfill 98%
github.com/vmware-tanzu/vm-operator/pkg/vmconfig/volumes/unmanaged/register 92%
github.com/vmware-tanzu/vm-operator/pkg/webconsolevalidation 100%
github.com/vmware-tanzu/vm-operator/services/vm-watcher 85%
github.com/vmware-tanzu/vm-operator/webhooks/common 98%
github.com/vmware-tanzu/vm-operator/webhooks/configtarget/validation 87%
github.com/vmware-tanzu/vm-operator/webhooks/persistentvolumeclaim/validation 95%
github.com/vmware-tanzu/vm-operator/webhooks/unifiedstoragequota/validation 89%
github.com/vmware-tanzu/vm-operator/webhooks/virtualmachine/mutation 86%
github.com/vmware-tanzu/vm-operator/webhooks/virtualmachine/validation 96%
github.com/vmware-tanzu/vm-operator/webhooks/virtualmachineclass/mutation 62%
github.com/vmware-tanzu/vm-operator/webhooks/virtualmachineclass/validation 89%
github.com/vmware-tanzu/vm-operator/webhooks/virtualmachineconfigoptions/validation 88%
github.com/vmware-tanzu/vm-operator/webhooks/virtualmachinegroup/mutation 87%
github.com/vmware-tanzu/vm-operator/webhooks/virtualmachinegroup/validation 93%
github.com/vmware-tanzu/vm-operator/webhooks/virtualmachinegrouppublishrequest/mutation 86%
github.com/vmware-tanzu/vm-operator/webhooks/virtualmachinegrouppublishrequest/validation 88%
github.com/vmware-tanzu/vm-operator/webhooks/virtualmachineguestoptions/validation 88%
github.com/vmware-tanzu/vm-operator/webhooks/virtualmachinepublishrequest/validation 90%
github.com/vmware-tanzu/vm-operator/webhooks/virtualmachinereplicaset/validation 90%
github.com/vmware-tanzu/vm-operator/webhooks/virtualmachineservice/mutation 67%
github.com/vmware-tanzu/vm-operator/webhooks/virtualmachineservice/validation 92%
github.com/vmware-tanzu/vm-operator/webhooks/virtualmachinesetresourcepolicy/validation 89%
github.com/vmware-tanzu/vm-operator/webhooks/virtualmachinesnapshot/mutation 86%
github.com/vmware-tanzu/vm-operator/webhooks/virtualmachinesnapshot/validation 91%
github.com/vmware-tanzu/vm-operator/webhooks/virtualmachinewebconsolerequest/v1alpha1/validation 92%
github.com/vmware-tanzu/vm-operator/webhooks/virtualmachinewebconsolerequest/validation 92%
Summary 84% (21714 / 25706)

Minimum allowed line rate is 79%

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

Labels

ai-reviewed This PR has been reviewed by the AI review bot size/L Denotes a PR that changes 100-499 lines.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants