Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -508,9 +508,20 @@ private boolean deRefOrDeleteResource(DevelopersApi api, String rscName, String
// 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 case where a resource that LOOKS like a template (resource name
// starts with the requested prefix) has zero `_cs-template-for-` aux properties
// even though we never decremented one — that's a legacy template predating the
// ref-count convention. Logging it before deletion lets operators audit how
// many such orphans existed at upgrade time.
if (expectedProps == 0 && rd.getName().toLowerCase().startsWith(rscName.toLowerCase())) {
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);
}
Comment on lines +515 to +524
Copy link

Copilot AI Apr 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new INFO log for “legacy template predating the ref-count convention” will currently fire for all non-template resource deletions too. existingRDs is already built via getRDListStartingWith(api, rscName), so rd.getName().toLowerCase().startsWith(rscName.toLowerCase()) is always true; whenever expectedProps == 0 (normal volume/resource with no _cs-template-for- props), this will emit the legacy-template message and add significant log noise/misleading attribution. Tighten the condition so it only matches the intended legacy-template-orphan case (e.g., by using a reliable template discriminator, passing an isTemplate flag from the caller, or checking for a template-specific naming/property convention), and avoid logging for ordinary resource deletions.

Suggested change
// Surface the case where a resource that LOOKS like a template (resource name
// starts with the requested prefix) has zero `_cs-template-for-` aux properties
// even though we never decremented one — that's a legacy template predating the
// ref-count convention. Logging it before deletion lets operators audit how
// many such orphans existed at upgrade time.
if (expectedProps == 0 && rd.getName().toLowerCase().startsWith(rscName.toLowerCase())) {
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);
}

Copilot uses AI. Check for mistakes.
ApiCallRcList answers = api.resourceDefinitionDelete(rd.getName());
checkLinstorAnswersThrow(answers);
deleted = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,26 @@ public static ResourceDefinition findResourceDefinition(DevelopersApi api, Strin
.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 selection 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) {
Expand Down
Loading