Add config keys for controlling public/private template secondary storage replica counts#12877
Add config keys for controlling public/private template secondary storage replica counts#12877Damans227 wants to merge 3 commits intoapache:mainfrom
Conversation
…rage replica counts
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #12877 +/- ##
=========================================
Coverage 18.02% 18.02%
- Complexity 16450 16452 +2
=========================================
Files 5968 5968
Lines 537086 537093 +7
Branches 65961 65964 +3
=========================================
+ Hits 96819 96824 +5
- Misses 429347 429348 +1
- Partials 10920 10921 +1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
@blueorangutan package |
|
@Damans227 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. |
|
Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ el10 ✔️ debian ✔️ suse15. SL-JID 17224 |
There was a problem hiding this comment.
Pull request overview
This PR introduces new template-related configuration keys intended to control how many secondary storage replicas are created for public vs private templates, decoupling replication behavior from template visibility.
Changes:
- Adds two new Zone-scoped
ConfigKey<Integer>settings:public.template.secstorage.copyandprivate.template.secstorage.copy. - Reworks secondary storage allocation logic to enforce a per-zone replica limit using a zone→count map.
- Updates unit tests to match the new method signatures/replica-limit behavior.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
engine/components-api/src/main/java/com/cloud/template/TemplateManager.java |
Adds new Zone-scoped config keys for public/private template replica limits. |
server/src/main/java/com/cloud/template/TemplateManagerImpl.java |
Registers the new config keys via getConfigKeys(). |
server/src/main/java/com/cloud/template/TemplateAdapterBase.java |
Replaces zone-set visibility logic with zone copy counting + replica limit enforcement. |
server/src/main/java/com/cloud/template/HypervisorTemplateAdapter.java |
Threads replica-limit and zone copy count through template creation/allocation paths. |
server/src/test/java/com/cloud/template/HypervisorTemplateAdapterTest.java |
Updates tests for the new signatures and adds coverage for replica-limit behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| int replicaLimit = isPrivateTemplate(template) | ||
| ? TemplateManager.PrivateTemplateSecStorageCopy.value() | ||
| : TemplateManager.PublicTemplateSecStorageCopy.value(); | ||
| Map<Long, Integer> zoneCopyCount = new HashMap<>(); |
There was a problem hiding this comment.
PublicTemplateSecStorageCopy/PrivateTemplateSecStorageCopy are declared with ConfigKey.Scope.Zone, but here value() is used, which always reads the global value (see ConfigKey#value()), ignoring per-zone configuration. Compute the limit per image store/zone using valueIn(zoneId) (or valueInScope(Scope.Zone, zoneId)), and avoid reading it once before iterating image stores across multiple zones.
| /** | ||
| * If the template/ISO is marked as private, then it is allocated to a random secondary storage; otherwise, allocates to every storage pool in every zone given by the | ||
| * {@link TemplateProfile#getZoneIdList()}. | ||
| */ | ||
| protected void postUploadAllocation(List<DataStore> imageStores, VMTemplateVO template, List<TemplateOrVolumePostUploadCommand> payloads) { |
There was a problem hiding this comment.
This method JavaDoc no longer matches the behavior: allocation is now governed by replica-limit config keys (public/private can both be limited), not strictly by template visibility (private=random vs public=all). Please update the comment to reflect the new replica-limit semantics (and that the limits are zone-scoped).
| ? TemplateManager.PrivateTemplateSecStorageCopy.value() | ||
| : TemplateManager.PublicTemplateSecStorageCopy.value(); |
There was a problem hiding this comment.
PublicTemplateSecStorageCopy/PrivateTemplateSecStorageCopy are Scope.Zone config keys, but value() always reads the global value, so zone-level overrides will never apply. In this loop the zone ID is already available (zoneId), so use valueIn(zoneId) when deriving replicaLimit.
| ? TemplateManager.PrivateTemplateSecStorageCopy.value() | |
| : TemplateManager.PublicTemplateSecStorageCopy.value(); | |
| ? TemplateManager.PrivateTemplateSecStorageCopy.valueIn(zoneId) | |
| : TemplateManager.PublicTemplateSecStorageCopy.valueIn(zoneId); |
| protected void standardImageStoreAllocation(List<DataStore> imageStores, VMTemplateVO template) { | ||
| Set<Long> zoneSet = new HashSet<Long>(); | ||
| int replicaLimit = isPrivateTemplate(template) | ||
| ? TemplateManager.PrivateTemplateSecStorageCopy.value() | ||
| : TemplateManager.PublicTemplateSecStorageCopy.value(); | ||
| Collections.shuffle(imageStores); | ||
| validateSecondaryStorageAndCreateTemplate(imageStores, template, zoneSet); | ||
| validateSecondaryStorageAndCreateTemplate(imageStores, template, new HashMap<>(), replicaLimit); |
There was a problem hiding this comment.
standardImageStoreAllocation derives replicaLimit using ConfigKey#value(), which only reads the global value; these keys are Scope.Zone, so per-zone settings won’t take effect. Since imageStores is zone-specific (from getImageStoresByZoneIds(zoneId)), derive the zone ID from the list (e.g., first store) and use valueIn(zoneId) (or compute the limit per-store inside the loop).
| ConfigKey<Integer> PublicTemplateSecStorageCopy = new ConfigKey<Integer>("Advanced", Integer.class, | ||
| PublicTemplateSecStorageCopyCK, "0", | ||
| "Maximum number of secondary storage pools to which a public template is copied. " + | ||
| "0 means copy to all secondary storage pools (default behavior).", | ||
| true, ConfigKey.Scope.Zone); | ||
|
|
||
| ConfigKey<Integer> PrivateTemplateSecStorageCopy = new ConfigKey<Integer>("Advanced", Integer.class, | ||
| PrivateTemplateSecStorageCopyCK, "1", | ||
| "Maximum number of secondary storage pools to which a private template is copied. " + | ||
| "Default is 1 to preserve existing behavior.", | ||
| true, ConfigKey.Scope.Zone); |
There was a problem hiding this comment.
The config key descriptions don’t mention that the limits are evaluated per-zone (and the keys themselves are zone-scoped). Consider clarifying the wording (e.g., “per zone”) so operators understand how replica limits are applied across multiple zones/image stores.
Description
Adds two new operator-level configuration keys to control the number of secondary storage copies made for public and private templates, decoupling replica count from template visibility.
public.template.secstorage.copy(default: 0 = all stores, preserving existing behavior)private.template.secstorage.copy(default: 1, preserving existing behavior)Types of changes
Feature/Enhancement Scale or Bug Severity
Feature/Enhancement Scale
How Has This Been Tested?