Skip to content

Commit 70eed01

Browse files
committed
fix(linstor): surface ambiguous template fallbacks and legacy template orphans
Two small visibility improvements that make existing template behaviour easier to audit, especially after upgrading from versions that predated the ref-count convention. LinstorUtil.findResourceDefinition When no resource has the exact "_cs-template-for-<rscGrpName>" Aux property, the method silently returned the first resource whose name starts with the requested prefix. With multiple resource groups on a single controller, this can route a clone to the wrong template. Now logs a WARN naming the requested rscGrpName, the fallback resource, and the actual aux properties present. Behaviour unchanged: still returns the first match. Operators can act on the warning by setting the property explicitly or removing the unrelated definition. LinstorStorageAdaptor.deRefOrDeleteResource When deleting a resource that has zero `_cs-template-for-` aux properties AND whose name starts with the template-name prefix the caller is acting on, log an INFO line. These are legacy templates cached before the ref-count convention was introduced — they get picked up by the existing "if expectedProps == 0" branch and deleted. Surfacing them lets operators see how many orphans existed at upgrade time and confirm the cleanup happened.
1 parent 6f4445c commit 70eed01

2 files changed

Lines changed: 33 additions & 3 deletions

File tree

plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -508,9 +508,20 @@ private boolean deRefOrDeleteResource(DevelopersApi api, String rscName, String
508508
// if there is only one template-for property left for templates, the template isn't needed anymore
509509
// or if it isn't a template anyway, it will not have this Aux property
510510
// _cs-template-for- properties work like a ref-count.
511-
if (rd.getProps().keySet().stream()
511+
long remainingTemplateRefs = rd.getProps().keySet().stream()
512512
.filter(key -> key.startsWith("Aux/" + LinstorUtil.CS_TEMPLATE_FOR_PREFIX))
513-
.count() == expectedProps) {
513+
.count();
514+
if (remainingTemplateRefs == expectedProps) {
515+
// Surface the case where a resource that LOOKS like a template (resource name
516+
// starts with the requested prefix) has zero `_cs-template-for-` aux properties
517+
// even though we never decremented one — that's a legacy template predating the
518+
// ref-count convention. Logging it before deletion lets operators audit how
519+
// many such orphans existed at upgrade time.
520+
if (expectedProps == 0 && rd.getName().toLowerCase().startsWith(rscName.toLowerCase())) {
521+
logger.info("Linstor: deleting resource {} which has no _cs-template-for- aux properties " +
522+
"(legacy template predating the ref-count convention, or a stale orphan). " +
523+
"Resource group context: {}", rd.getName(), rscGrpName);
524+
}
514525
ApiCallRcList answers = api.resourceDefinitionDelete(rd.getName());
515526
checkLinstorAnswersThrow(answers);
516527
deleted = true;

plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/util/LinstorUtil.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,26 @@ public static ResourceDefinition findResourceDefinition(DevelopersApi api, Strin
491491
.filter(rscDfn -> rscDfn.getProps().containsKey(LinstorUtil.getTemplateForAuxPropKey(rscGrpName)))
492492
.findFirst();
493493

494-
return rd.orElseGet(() -> rdsStartingWith.get(0));
494+
if (rd.isPresent()) {
495+
return rd.get();
496+
}
497+
// Fallback: no resource has the exact "_cs-template-for-<rscGrpName>" property.
498+
// This happens when (a) the matched resource is a legacy template created before that
499+
// convention was introduced, or (b) the template was cached by a different resource
500+
// group and the operator hopes to share it. Log so the ambiguity is visible — silent
501+
// first-match selection has previously routed clones to the wrong template when
502+
// multiple resource groups coexisted on the same controller.
503+
ResourceDefinition fallback = rdsStartingWith.get(0);
504+
LOGGER.warn("LINSTOR findResourceDefinition: no resource for '{}' has the expected " +
505+
"Aux property '{}' for resource group '{}'; falling back to first match '{}' " +
506+
"(present aux properties: {}). If this is wrong, set the property explicitly " +
507+
"or remove the unrelated resource definition.",
508+
rscName, getTemplateForAuxPropKey(rscGrpName), rscGrpName,
509+
fallback.getName(),
510+
fallback.getProps().keySet().stream()
511+
.filter(k -> k.startsWith("Aux/" + CS_TEMPLATE_FOR_PREFIX))
512+
.collect(Collectors.toList()));
513+
return fallback;
495514
}
496515

497516
public static boolean isRscDiskless(ResourceWithVolumes rsc) {

0 commit comments

Comments
 (0)