engine: key removeNic work job lookup on nic uuid to fix concurrent removal race#13700
Open
Andr0human wants to merge 1 commit into
Open
engine: key removeNic work job lookup on nic uuid to fix concurrent removal race#13700Andr0human wants to merge 1 commit into
Andr0human wants to merge 1 commit into
Conversation
|
Congratulations on your first Pull Request and welcome to the Apache CloudStack community! If you have any issues or are unsure about any anything please check our Contribution Guide (https://github.com/apache/cloudstack/blob/main/CONTRIBUTING.md)
|
…emoval race removeNicFromVmThroughJobQueue looked up pending work jobs by (vmType, vmId, commandName) only, so the nic was not part of the dedup key. A second removeNicFromVirtualMachine request for a different nic on the same vm matched the first still-pending VmWorkRemoveNicFromVm job and joined it instead of submitting its own. That job removes only the nic it was created for, yet both callers wait on the same job id and both receive its success, leaving the second nic silently attached while its API call reports success. Make the nic uuid part of the lookup key, mirroring addVmToNetworkThroughJobQueue which was fixed the same way in apache#5658: - look up pending jobs with the 4-arg listPendingWorkJobs(Instance, vmId, cmd, nic.getUuid()) - fail fast with CloudRuntimeException if more than one job matches - stamp new jobs with setSecondaryObjectIdentifier(nic.getUuid()) before submitting Genuine duplicates, two requests for the same nic, still dedup as before. Adds three regression tests to VirtualMachineManagerImplTest covering the cross-nic race, same-nic dedup, and the multiple-pending-jobs guard. Fixes: apache#13699 Generated-by: Claude Code (Anthropic) Signed-off-by: Ayush Sinha <ayushsinha3199@gmail.com>
Andr0human
force-pushed
the
fix-concurrent-removenic-workjob-dedup-4.22
branch
from
July 25, 2026 12:08
a8054a6 to
09bed9d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
This PR makes the NIC uuid part of the pending work-job lookup key in
VirtualMachineManagerImpl.removeNicFromVmThroughJobQueue, so that two concurrentremoveNicFromVirtualMachinerequests for different NICs on the same VM no longer collapse into a single work job.Before this change the lookup was NIC-agnostic —
retrievePendingWorkJob(vmId, commandName), i.e. the 3-argVmWorkJobDao.listPendingWorkJobs(type, vmId, cmd). If a second remove-NIC request arrived while the firstVmWorkRemoveNicFromVmjob was still pending, it matched that job and joined it instead of submitting its own. The job removes only the NIC it was created for, but both callers wait on the same job id and both receive its success — so the second NIC stays attached while its API call reports success.Functional change in behaviour:
This is the mirror of an already-merged fix on the add path.
addVmToNetworkThroughJobQueuewas fixed in #5658 (issue #5541, 4.16.1.0) by keying on the object uuid; the symmetric remove path never got the same treatment. The change here follows that established pattern line for line:listPendingWorkJobs(Instance, vmId, VmWorkRemoveNicFromVm.class.getName(), nic.getUuid());CloudRuntimeException(same guard as the add path);workJob.setSecondaryObjectIdentifier(nic.getUuid())before submitting.Nic extends Identity, sogetUuid()is available — no interface or schema change is required.Scope is deliberately tight: only
removeNicFromVmThroughJobQueueis touched. The siblingremoveVmFromNetworkThroughJobQueuestill uses the network-agnosticretrievePendingWorkJob(vmId, commandName)lookup and appears to have the same class of race; that is left out of this PR and noted in the issue as a follow-up.Fixes: #13699
Types of changes
Feature/Enhancement Scale or Bug Severity
Feature/Enhancement Scale
Bug Severity
Screenshots (if appropriate):
N/A — management-server logic change, no UI surface.
How Has This Been Tested?
1. Unit tests — three regression tests added to
VirtualMachineManagerImplTestremoveNicFromVmThroughJobQueueDoesNotJoinAnotherNicsPendingJobremoveNicFromVmThroughJobQueueJoinsExistingJobForSameNicremoveNicFromVmThroughJobQueueThrowsWhenMultiplePendingJobsForSameNicsize() > 1guard throwsRed→green was confirmed by reverting the production change and re-running against this branch:
Tests run: 96, Failures: 1, Errors: 2— all three new tests and only those, with the regression test failing at thesetCmdInfoAndSubmitAsyncJobverification, i.e. precisely because the second request joined the first NIC's job instead of submitting its own.checkstyle:checkon the module reports 0 violations.2. End-to-end on the CloudStack simulator
Advanced-zone simulator (
mvn -Pdeveloper -Dsimulator,tools/docker), VM with three NICs, two of them removed concurrently.UnPlugNicCommandwas stalled withconfigureSimulator name=UnPlugNicCommand value=wait:20000so the first work job is guaranteed to still be pending when the second request arrives — that is the window the bug lives in. Both halves were built through the same two-module pipeline (-pl engine/orchestrationthen-pl client), so the only difference between the runs is the fix itself. (This end-to-end run was done on a simulator build ofmain; the diff proposed here is identical on both branches, and the unit tests above were run on this 4.22 branch.)vm_work_jobrows forVmWorkRemoveNicFromVmsecondary_object(the per-NIC key)NULLThe unfixed run reports the contradiction directly — the caller is told the removal succeeded while
listVirtualMachinesstill shows the NIC attached:and the same query after the fix shows the two per-NIC jobs the dedup key now produces:
How did you try to break this feature and the system with this change?
removeNicFromVmThroughJobQueueJoinsExistingJobForSameNic.removeNicFromVmThroughJobQueueThrowsWhenMultiplePendingJobsForSameNic.secondary_objectis an existingvm_work_jobcolumn already written by the add path since remove VmWorkJob after adding a nic to a vm #5658 — no schema change, and it is confirmed populated in the simulator run above.setSecondaryObjectIdentifieris only ever set here for jobs whosecmdisVmWorkRemoveNicFromVm, and the 4-arglistPendingWorkJobsoverload already exists and is already used byaddVmToNetworkThroughJobQueue. No other work-job path changes behaviour; the fullVirtualMachineManagerImplTestsuite (96 tests) passes.