This is an automated email from the ASF dual-hosted git repository.
DaanHoogland pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/main by this push:
new 6786d45951a fix(linstor): surface ambiguous template fallbacks and
legacy orphan cleanup (#13078)
6786d45951a is described below
commit 6786d45951a5faf26ce3caa7fffecb880bbfd5e0
Author: James Peru Mmbono <[email protected]>
AuthorDate: Wed May 27 15:09:32 2026 +0300
fix(linstor): surface ambiguous template fallbacks and legacy orphan
cleanup (#13078)
Co-authored-by: jmsperu <[email protected]>
---
.../kvm/storage/LinstorStorageAdaptor.java | 14 ++++++++++++--
.../storage/datastore/util/LinstorUtil.java | 21 ++++++++++++++++++++-
2 files changed, 32 insertions(+), 3 deletions(-)
diff --git
a/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java
b/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java
index 31a41cd9407..32858108d6a 100644
---
a/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java
+++
b/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java
@@ -508,9 +508,19 @@ public class LinstorStorageAdaptor implements
StorageAdaptor {
// if there is only one template-for property left for templates,
the template isn't needed anymore
// or if it isn't a template anyway, it will not have this Aux
property
// _cs-template-for- properties work like a ref-count.
- if (rd.getProps().keySet().stream()
+ long remainingTemplateRefs = rd.getProps().keySet().stream()
.filter(key -> key.startsWith("Aux/" +
LinstorUtil.CS_TEMPLATE_FOR_PREFIX))
- .count() == expectedProps) {
+ .count();
+ if (remainingTemplateRefs == expectedProps) {
+ // Surface the legacy case where a resource has zero
`_cs-template-for-` aux
+ // properties even though we never decremented one — that's a
template predating
+ // the ref-count convention, or a stale orphan. Logging before
deletion lets
+ // operators audit how many such orphans existed at upgrade
time.
+ if (expectedProps == 0) {
+ logger.info("Linstor: deleting resource {} which has no
_cs-template-for- aux properties " +
+ "(legacy template predating the ref-count
convention, or a stale orphan). " +
+ "Resource group context: {}",
rd.getName(), rscGrpName);
+ }
ApiCallRcList answers =
api.resourceDefinitionDelete(rd.getName());
checkLinstorAnswersThrow(answers);
deleted = true;
diff --git
a/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/util/LinstorUtil.java
b/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/util/LinstorUtil.java
index 239331077e1..502bf6d0ca2 100644
---
a/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/util/LinstorUtil.java
+++
b/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/util/LinstorUtil.java
@@ -543,7 +543,26 @@ public class LinstorUtil {
.filter(rscDfn ->
rscDfn.getProps().containsKey(LinstorUtil.getTemplateForAuxPropKey(rscGrpName)))
.findFirst();
- return rd.orElseGet(() -> rdsStartingWith.get(0));
+ if (rd.isPresent()) {
+ return rd.get();
+ }
+ // Fallback: no resource has the exact "_cs-template-for-<rscGrpName>"
property.
+ // This happens when (a) the matched resource is a legacy template
created before that
+ // convention was introduced, or (b) the template was cached by a
different resource
+ // group and the operator hopes to share it. Log so the ambiguity is
visible — silent
+ // first-match fallback has previously routed clones to the wrong
template when
+ // multiple resource groups coexisted on the same controller.
+ ResourceDefinition fallback = rdsStartingWith.get(0);
+ LOGGER.warn("LINSTOR findResourceDefinition: no resource for '{}' has
the expected " +
+ "Aux property '{}' for resource group '{}'; falling
back to first match '{}' " +
+ "(present aux properties: {}). If this is wrong, set
the property explicitly " +
+ "or remove the unrelated resource definition.",
+ rscName, getTemplateForAuxPropKey(rscGrpName), rscGrpName,
+ fallback.getName(),
+ fallback.getProps().keySet().stream()
+ .filter(k -> k.startsWith("Aux/" +
CS_TEMPLATE_FOR_PREFIX))
+ .collect(Collectors.toList()));
+ return fallback;
}
public static boolean isRscDiskless(ResourceWithVolumes rsc) {