Skip to content

Batch VM and host lookups in StorageManagerImpl to eliminate N+1 queries during cleanup and pool connect#13353

Open
vishesh92 wants to merge 2 commits into
apache:4.22from
shapeblue:batch-vm-host-lookups
Open

Batch VM and host lookups in StorageManagerImpl to eliminate N+1 queries during cleanup and pool connect#13353
vishesh92 wants to merge 2 commits into
apache:4.22from
shapeblue:batch-vm-host-lookups

Conversation

@vishesh92

Copy link
Copy Markdown
Member

Description

cleanupStorage: replaced per-volume _vmInstanceDao.findById(vol.getInstanceId()) with a single batch SELECT ... WHERE id IN (...) before the loop, using a HashMap for O(1) lookups. Added null guard for volumes with null instanceId.

connectHostsToPool: replaced per-thread _hostDao.findById(hostId) with a batch load before thread pool submission. Each thread now reads from a pre-built HashMap instead of hitting the DB. Added null guard with warning log for hosts removed between list assembly and batch read.

Added VMInstanceDao.listByIds(List) with empty-list guard and IN-clause SearchBuilder, matching the established pattern in HostDao.

Types of changes

  • Breaking change (fix or feature that would cause existing functionality to change)
  • New feature (non-breaking change which adds functionality)
  • Bug fix (non-breaking change which fixes an issue)
  • Enhancement (improves an existing feature and functionality)
  • Cleanup (Code refactoring and cleanup, that may add test cases)
  • Build/CI
  • Test (unit or integration test code)

Feature/Enhancement Scale or Bug Severity

Feature/Enhancement Scale

  • Major
  • Minor

Bug Severity

  • BLOCKER
  • Critical
  • Major
  • Minor
  • Trivial

Screenshots (if appropriate):

How Has This Been Tested?

How did you try to break this feature and the system with this change?

@vishesh92

Copy link
Copy Markdown
Member Author

@blueorangutan package

@blueorangutan

Copy link
Copy Markdown

@vishesh92 a [SL] Jenkins job has been kicked to build packages. It will be bundled with no SystemVM templates. I'll keep you posted as I make progress.

@codecov

codecov Bot commented Jun 5, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 28.57143% with 20 lines in your changes missing coverage. Please review.
✅ Project coverage is 17.67%. Comparing base (a951ac6) to head (bc01b67).

Files with missing lines Patch % Lines
.../main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java 0.00% 10 Missing ⚠️
...ain/java/com/cloud/storage/StorageManagerImpl.java 44.44% 10 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff            @@
##               4.22   #13353   +/-   ##
=========================================
  Coverage     17.67%   17.67%           
  Complexity    15797    15797           
=========================================
  Files          5923     5923           
  Lines        533349   533375   +26     
  Branches      65248    65252    +4     
=========================================
+ Hits          94253    94262    +9     
- Misses       428437   428453   +16     
- Partials      10659    10660    +1     
Flag Coverage Δ
uitests 3.69% <ø> (ø)
unittests 18.74% <28.57%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ 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.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@vishesh92

Copy link
Copy Markdown
Member Author

@blueorangutan package

@apache apache deleted a comment from blueorangutan Jun 8, 2026
@apache apache deleted a comment from blueorangutan Jun 8, 2026
@apache apache deleted a comment from blueorangutan Jun 8, 2026
@apache apache deleted a comment from github-actions Bot Jun 8, 2026
@blueorangutan

Copy link
Copy Markdown

@vishesh92 a [SL] Jenkins job has been kicked to build packages. It will be bundled with no SystemVM templates. I'll keep you posted as I make progress.

@blueorangutan

Copy link
Copy Markdown

Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ el10 ✔️ debian ✔️ suse15. SL-JID 18188

@vishesh92

Copy link
Copy Markdown
Member Author

@blueorangutan test

@blueorangutan

Copy link
Copy Markdown

@vishesh92 a [SL] Trillian-Jenkins test job (ol8 mgmt + kvm-ol8) has been kicked to run smoke tests

@blueorangutan

Copy link
Copy Markdown

[SF] Trillian test result (tid-16262)
Environment: kvm-ol8 (x2), zone: Advanced Networking with Mgmt server ol8
Total time taken: 64134 seconds
Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr13353-t16262-kvm-ol8.zip
Smoke tests completed. 145 look OK, 6 have errors, 0 did not run
Only failed and skipped tests results shown below:

Test Result Time (s) Test File
ContextSuite context=TestVPCConserveModeRules>:setup Error 0.00 test_vpc_conserve_mode.py
ContextSuite context=TestIpv6Vpc>:setup Error 0.00 test_vpc_ipv6.py
ContextSuite context=TestVPCRedundancy>:setup Error 0.00 test_vpc_redundant.py
ContextSuite context=TestVPCNics>:setup Error 0.00 test_vpc_router_nics.py
ContextSuite context=TestRVPCSite2SiteVpn>:setup Error 0.00 test_vpc_vpn.py
ContextSuite context=TestVPCSite2SiteVPNMultipleOptions>:setup Error 0.00 test_vpc_vpn.py
ContextSuite context=TestVpcRemoteAccessVpn>:setup Error 0.00 test_vpc_vpn.py
ContextSuite context=TestVpcSite2SiteVpn>:setup Error 0.00 test_vpc_vpn.py
test_disable_oobm_ha_state_ineligible Error 1517.95 test_hostha_kvm.py

@weizhouapache weizhouapache added this to the 4.22.2 milestone Jun 29, 2026
@weizhouapache

weizhouapache commented Jun 29, 2026

Copy link
Copy Markdown
Member

@vishesh92
can you rebase it with 4.22 ?

Copilot AI 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.

Pull request overview

This PR reduces database N+1 lookup patterns in StorageManagerImpl by batching VM and host loads during storage cleanup and host-to-pool connection flows, and adds a VMInstanceDao.listByIds(...) helper to support that.

Changes:

  • Batch-load HostVO records before submitting pool-connection worker tasks, avoiding per-host DAO lookups.
  • Batch-load VMInstanceVO records for ROOT volumes during cleanupStorage, avoiding per-volume DAO lookups and adding null guards.
  • Add VMInstanceDao.listByIds(List<Long>) implementation and adjust related unit tests to match the new DAO access pattern.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
server/src/main/java/com/cloud/storage/StorageManagerImpl.java Replaces per-item DAO lookups with batch loads + map lookups in cleanup and pool connect paths.
engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java Adds listByIds query helper to enable batch VM fetches.
engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDao.java Exposes listByIds on the DAO interface.
plugins/storage/volume/scaleio/src/test/java/org/apache/cloudstack/storage/datastore/lifecycle/ScaleIOPrimaryDataStoreLifeCycleTest.java Updates tests impacted by the new batching behavior in connectHostsToPool.
plugins/storage/volume/default/src/test/java/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImplTest.java Adds test stubbing for HostDao.listByIds used by the new batching logic.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +130 to 133
public void testAttachZone() {
final DataStore dataStore = mock(DataStore.class);
when(dataStore.getId()).thenReturn(1L);

MockedStatic<ScaleIOGatewayClientConnectionPool> scaleIOGatewayClientConnectionPoolMocked = mockStatic(ScaleIOGatewayClientConnectionPool.class);
Comment on lines 146 to 150
Mockito.when(host1.getId()).thenReturn(1L);
Mockito.when(host2.getId()).thenReturn(2L);

when(resourceManager.getEligibleUpAndEnabledHostsInZoneForStorageConnection(dataStore, scope.getScopeId(), Hypervisor.HypervisorType.KVM))
.thenReturn(Arrays.asList(host1, host2));
Comment on lines +1357 to +1360
public List<VMInstanceVO> listByIds(List<Long> ids) {
if (ids == null || ids.isEmpty()) {
return new ArrayList<>();
}
@sureshanaparti sureshanaparti marked this pull request as ready for review July 7, 2026 10:44
@sureshanaparti sureshanaparti requested a review from nvazquez July 7, 2026 10:46

@nvazquez nvazquez 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.

Thanks @vishesh92 - can you please rebase to branch 4.22? Can you also check if the Copilot comments are applicable?

sliceofapplepie and others added 2 commits July 7, 2026 17:22
…ies during cleanup and pool connect

cleanupStorage: replaced per-volume _vmInstanceDao.findById(vol.getInstanceId())
with a single batch SELECT ... WHERE id IN (...) before the loop, using a
HashMap for O(1) lookups. Added null guard for volumes with null instanceId.

connectHostsToPool: replaced per-thread _hostDao.findById(hostId) with a
batch load before thread pool submission. Each thread now reads from a
pre-built HashMap instead of hitting the DB. Added null guard with warning
log for hosts removed between list assembly and batch read.

Added VMInstanceDao.listByIds(List<Long>) with empty-list guard and IN-clause
SearchBuilder, matching the established pattern in HostDao.
@vishesh92 vishesh92 force-pushed the batch-vm-host-lookups branch from d867216 to bc01b67 Compare July 7, 2026 11:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment