Repository navigation
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #13788 +/- ##
=========================================
Coverage 19.91% 19.91%
- Complexity 20198 20203 +5
=========================================
Files 6373 6373
Lines 577230 577236 +6
Branches 70696 70696
=========================================
+ Hits 114936 114967 +31
+ Misses 449736 449703 -33
- Partials 12558 12566 +8
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
This pull request has merge conflicts. Dear author, please fix the conflicts and sync your branch with the base branch. |
…steners and ensuring downstream listeners are invoked. Add tests to verify behavior with null hostId and exception handling.
90ce7bd to
57a5ff8
Compare
|
@nvazquez can you review this one? its rebased on main and the conflicts are fixed |
There was a problem hiding this comment.
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Copilot review overview
3 open issues
CatchingExceptionwill also swallowInterruptedException, which can clear or ignore interrupt… · New This comment is ambiguous about whichhostIdis null (the method parameter vsvm.getHostId()vs… · New These stubbings useMockito.any()for theCommand[]argument, which is less specific than… · New
What changed in this PR
Improves resilience in AgentManagerImpl.handleCommands so a single misbehaving listener can’t prevent subsequent listeners (e.g., ping) from running, and fixes a DAO partial-select projection that omitted hostId, leading to incorrect VM host reporting.
Changes:
- Wrap each
Listener.processCommandsinvocation inhandleCommandswith try/catch and log-and-continue on failures. - Fix trace logging to report the listener type rather than the
Pairwrapper. - Include
hostIdinVMInstanceDaoImpl.IdsPowerStateSelectSearchand add tests covering the null-hostId projection case.
| File | Description |
|---|---|
| engine/orchestration/src/main/java/com/cloud/agent/manager/AgentManagerImpl.java | Adds exception isolation per listener and corrects trace logging to avoid starving downstream listeners. |
| engine/orchestration/src/test/java/com/cloud/agent/manager/AgentManagerImplTest.java | Adds tests ensuring throwing listeners don’t abort the listener loop and downstream listeners still run. |
| engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java | Fixes partial-select projection by adding hostId to selected fields. |
| engine/schema/src/test/java/com/cloud/vm/dao/VMInstanceDaoImplTest.java | Adds regression tests for update-power-state behavior when hostId is null due to partial-select projection. |
Review effort: Lite
| try { | ||
| final boolean processed = listener.second().processCommands(attache.getId(), sequence, cmds); | ||
| logger.trace("SeqA {}-{}: {} by {}", attache.getId(), sequence, (processed ? "processed" : "not processed"), listener.second().getClass()); | ||
| } catch (final Exception e) { | ||
| logger.warn("Listener {} threw an exception processing commands for agent {} seq {}; continuing to next listener", | ||
| listener.second().getClass().getName(), attache.getId(), sequence, e); | ||
| } |
| * hostId (the default from setUp), which is what happens when the row was loaded through | ||
| * a partial-select projection that doesn't include hostId. isPowerStateInSyncWithInstanceState | ||
| * must not NPE on the null hostId, and must still detect the state is out-of-sync. |
| Mockito.when(throwingListener.processCommands(Mockito.anyLong(), Mockito.anyLong(), Mockito.any())) | ||
| .thenThrow(new RuntimeException("simulated NPE from power-state sync")); | ||
|
|
||
| Listener goodListener = Mockito.mock(Listener.class); | ||
| Mockito.when(goodListener.processCommands(Mockito.anyLong(), Mockito.anyLong(), Mockito.any())) |



Description
If one listener in
handleCommandsthrows, the whole loop stops and every listener after it never runs. This can starvepingBy()and cause fake ping timeouts.This wraps each listener call in a try/catch, so one bad listener just logs a warning and the rest still run. Also fixed a trace log nearby that was logging the wrong class (the
Pairwrapper instead of the listener).Also added the missing
hostIdfield toIdsPowerStateSelectSearch. Without it, VMs loaded through that path always showed a null host, even when they had one. Not a crash, just a wrong log message.Types of changes
Feature/Enhancement Scale or Bug Severity
Bug Severity
How Has This Been Tested?
Added tests: a throwing listener doesn't block the next one, and existing behavior with only successful listeners is unchanged. Also added tests for the null-hostId case, which had no coverage before.