Fix iSCSI target cascade: drop unmappable groups instead of failing target

When a portal fails to create (e.g. IP not on system), its ID is absent
from portal_id_map. Previously this caused every target referencing that
portal to be skipped entirely, which then cascaded to target-extent
failures.

Now each target's groups are filtered individually: groups with unmapped
portal or initiator references are dropped with a warning, and the target
is still created with the remaining valid groups. This keeps the target
and all its extent associations intact while clearly indicating which
groups need manual attention.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-05 16:50:07 -05:00
parent ecbc636035
commit c0619dfb9b

View File

@@ -386,21 +386,24 @@ async def _migrate_iscsi_targets(
summary.iscsi_targets_skipped += 1 summary.iscsi_targets_skipped += 1
continue continue
# Verify all referenced portals and initiators were successfully mapped # Filter out groups whose portal or initiator could not be mapped (e.g. portal
missing = [] # creation failed). Warn per dropped group but still create the target — a
# target without every portal group is valid and preferable to no target at all.
valid_groups = []
for g in target.get("groups", []): for g in target.get("groups", []):
unmapped = []
if g.get("portal") not in portal_id_map: if g.get("portal") not in portal_id_map:
missing.append(f"portal id={g['portal']}") unmapped.append(f"portal id={g['portal']}")
if g.get("initiator") not in initiator_id_map: if g.get("initiator") not in initiator_id_map:
missing.append(f"initiator id={g['initiator']}") unmapped.append(f"initiator id={g['initiator']}")
if missing: if unmapped:
msg = f"iSCSI target {name!r}: cannot remap {', '.join(missing)}" log.warning(" %s dropping group with unmapped %s",
log.error(" %s: %s", _bold_red("SKIP"), msg) _yellow("WARN"), ", ".join(unmapped))
summary.iscsi_targets_failed += 1 else:
summary.errors.append(msg) valid_groups.append(g)
continue
payload = _iscsi_target_payload(target, portal_id_map, initiator_id_map) payload = _iscsi_target_payload({**target, "groups": valid_groups},
portal_id_map, initiator_id_map)
log.debug(" payload: %s", json.dumps(payload)) log.debug(" payload: %s", json.dumps(payload))
if dry_run: if dry_run: