Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
eda3d51
adding a delay on final step for testing case
EbiRider Aug 18, 2026
9be113f
disabling source cleanup
EbiRider Aug 18, 2026
171947f
remove the delay
EbiRider Aug 18, 2026
a160849
adding delays for each step after final batch migration
EbiRider Aug 18, 2026
85b0a09
disabling ana state switch
EbiRider Aug 18, 2026
e2807c8
disabling namespace swap
EbiRider Aug 18, 2026
968b7bf
disbaling the delete of intermediate snapshots
EbiRider Aug 18, 2026
431e446
adding logs to trace the tree not reconstructing issue
EbiRider Aug 18, 2026
4818986
fix: batch migration skip building the tree on the target
EbiRider Aug 18, 2026
fabb186
fix: redundent add listener rpc call, explicit ns id passing to the t…
EbiRider Aug 19, 2026
d10bed3
testing with source paths going off for 5 second before opening targe…
EbiRider Aug 19, 2026
8ab4f58
disabling rpc calls past final step in batch migration
EbiRider Aug 19, 2026
a89d393
making all paths inaccessible 10 second before fianl step
EbiRider Aug 19, 2026
7201d5b
reduced delay
EbiRider Aug 19, 2026
671a89b
reenable the disabled features for the testing
EbiRider Aug 19, 2026
60c18e4
removing debug logs, and redudent calls
EbiRider Aug 19, 2026
c6e31d2
fix: batch migration cleanup target fail to detect overlap nodes
EbiRider Aug 20, 2026
df8f808
removing any hub lvol detach call from the retry path of batch lvol m…
EbiRider Aug 20, 2026
8e0075c
batch migration now may take extra intermediate snapshots if the delt…
EbiRider Aug 20, 2026
90bece1
on retry batch migration will take extra intermediate snapshots if ne…
EbiRider Aug 21, 2026
797e1a2
temp: manually blockiong the port during lvol migration for testing
EbiRider Aug 21, 2026
5a440b6
removing temp port block
EbiRider Aug 21, 2026
6e4e172
adding a delay on final step for testing case
EbiRider Aug 18, 2026
9dfe3a7
disabling source cleanup
EbiRider Aug 18, 2026
9cbb3fb
remove the delay
EbiRider Aug 18, 2026
c1ba8c2
adding delays for each step after final batch migration
EbiRider Aug 18, 2026
53b401b
disabling ana state switch
EbiRider Aug 18, 2026
38d624d
disabling namespace swap
EbiRider Aug 18, 2026
c7c85b4
disbaling the delete of intermediate snapshots
EbiRider Aug 18, 2026
bba654f
adding logs to trace the tree not reconstructing issue
EbiRider Aug 18, 2026
738af6d
fix: batch migration skip building the tree on the target
EbiRider Aug 18, 2026
d24af18
fix: redundent add listener rpc call, explicit ns id passing to the t…
EbiRider Aug 19, 2026
a5a793f
testing with source paths going off for 5 second before opening targe…
EbiRider Aug 19, 2026
da4a86c
disabling rpc calls past final step in batch migration
EbiRider Aug 19, 2026
d24dc65
making all paths inaccessible 10 second before fianl step
EbiRider Aug 19, 2026
a3f7bc9
reduced delay
EbiRider Aug 19, 2026
713c5d0
reenable the disabled features for the testing
EbiRider Aug 19, 2026
25b0172
removing debug logs, and redudent calls
EbiRider Aug 19, 2026
2cfc8f4
fix: batch migration cleanup target fail to detect overlap nodes
EbiRider Aug 20, 2026
04a130a
removing any hub lvol detach call from the retry path of batch lvol m…
EbiRider Aug 20, 2026
21ed098
batch migration now may take extra intermediate snapshots if the delt…
EbiRider Aug 20, 2026
24608e9
on retry batch migration will take extra intermediate snapshots if ne…
EbiRider Aug 21, 2026
bb73f3c
temp: manually blockiong the port during lvol migration for testing
EbiRider Aug 21, 2026
6c845ea
removing temp port block
EbiRider Aug 21, 2026
9dba2b6
Merge branch 'batch-lvol-test' of https://github.com/simplyblock/sbcl…
EbiRider Aug 22, 2026
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
40 changes: 35 additions & 5 deletions simplyblock_core/controllers/migration_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -1174,7 +1174,8 @@ def create_migration(lvol_id, target_node_id,
f"create_migration: listener on overlap {_node_id[:8]} "
f"(non-fatal): {_e}")
else:
if not _rpc.subsystem_get(nqn):
_existing_subsys = _rpc.subsystem_get(nqn)
if not _existing_subsys:
if _min_cntlid in subsys_min_cntlid_used:
_min_cntlid = _min_cntlid + 10000
_rpc.subsystem_create(
Expand All @@ -1190,22 +1191,51 @@ def create_migration(lvol_id, target_node_id,
f"create_migration: allowed_hosts reapply on "
f"{_node_id[:8]} (non-fatal): {_e}")

# For a shared-namespace batch group, create_migration() runs once
# per member against the SAME nqn/listener -- guard against
# re-adding a listener that a prior member's precreate already
# established (listeners_create had no existence check and its
# result was never inspected, so a real failure on a later
# member's redundant add would previously have been silent).
_existing_listeners = {
(_l.get('trtype', '').lower(), _l.get('traddr'), str(_l.get('trsvcid')))
for _l in ((_existing_subsys or {}).get('listen_addresses') or [])
}
for nic in _node.data_nics:
if not nic.ip4_address or nic.trtype.lower() != lvol.fabric:
continue
_listener_key = (nic.trtype.lower(), nic.ip4_address, str(_port))
if _listener_key in _existing_listeners:
continue
try:
_rpc.listeners_create(nqn, nic.trtype.lower(), nic.ip4_address,
_port, ana_state="inaccessible")
_ret_listener = _rpc.listeners_create(
nqn, nic.trtype.lower(), nic.ip4_address,
_port, ana_state="inaccessible")
if not _ret_listener:
logger.warning(
f"create_migration: listener add for {_node_id[:8]} "
f"{nic.ip4_address}:{_port} returned falsy")
except Exception as _e:
logger.warning(
f"create_migration: listener on {_node_id[:8]} "
f"(non-fatal): {_e}")

_ns = _rpc.nvmf_subsystem_add_ns(nqn, _ns_bdev, lvol.uuid, lvol.guid)
# Pin the target namespace to the SAME nsid the source already
# uses, rather than letting SPDK auto-assign on the target
# subsystem. Auto-assignment just happens to reproduce the
# source's numbering when adds land in the same order on an
# empty subsystem -- it isn't enforced, and any stale/leftover
# namespace occupying a low nsid on the target (or add_ns calls
# racing/reordering across nodes) would silently diverge the
# source and target nsid maps for this lvol.
_ns = _rpc.nvmf_subsystem_add_ns(
nqn, _ns_bdev, lvol.uuid, lvol.guid,
nsid=lvol.ns_id if lvol.ns_id else None)
if _ns:
logger.info(
f"create_migration: namespace {_ns_bdev} added on "
f"{_tgt_label} {_node_id[:8]} nsid={_ns}")
f"{_tgt_label} {_node_id[:8]} nsid={_ns} "
f"(source nsid={lvol.ns_id})")
else:
logger.warning(
f"create_migration: nvmf_subsystem_add_ns failed on "
Expand Down
26 changes: 22 additions & 4 deletions simplyblock_core/models/lvol_migration_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,14 @@
N worker tasks copy their owned snapshot chains in parallel.
snap_copy_done tracks which workers have finished.
INTERMEDIATE
All workers take exactly one intermediate ('shrink') snapshot each.
intermediates_done tracks which workers have finished.
All workers take one intermediate ('shrink') snapshot each, in lockstep
rounds. intermediates_done tracks which workers have finished the
current round (intermediate_round). If any worker's dirty delta is
still above the threshold after a round, it flags itself in
intermediate_more_needed; once every worker has finished the round, the
orchestrator starts another synchronized round (all members retake a
snapshot together, even ones whose own delta was already low) if
intermediate_more_needed is non-empty and the round cap hasn't been hit.
BATCH_MIGRATE
Main calls bdev_lvol_batch_final_step with all lvols ordered by ns_id.
batch_result is set to True on success, False on failure.
Expand Down Expand Up @@ -80,10 +86,22 @@ class LVolMigrationGroup(BaseModel):
# waiting for the INTERMEDIATE phase signal from the main orchestrator.
snap_copy_done: List[str] = []

# migration_ids that have taken and transferred their single intermediate
# snapshot and are waiting for batch_result.
# migration_ids that have taken and transferred their intermediate
# snapshot for the CURRENT intermediate_round and are waiting for either
# another round or batch_result. Cleared when a new round starts.
intermediates_done: List[str] = []

# Which intermediate round is currently in flight (0-indexed; round 0 is
# always taken unconditionally). Incremented when the orchestrator starts
# another synchronized round.
intermediate_round: int = 0

# migration_ids that reported their dirty delta still exceeded the
# threshold after finishing intermediate_round. Cleared when a new round
# starts. Non-empty at the end of a round (and under the round cap)
# triggers another synchronized round for every member.
intermediate_more_needed: List[str] = []

# migration_ids that have completed CLEANUP_SOURCE.
cleanup_source_done: List[str] = []

Expand Down
2 changes: 1 addition & 1 deletion simplyblock_core/services/hub_controller_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ class HubControllerManager:
# Seconds since the last acquire() before the GC triggers a detach.
# Refreshed on every acquire() so concurrent migrations naturally keep
# the controller alive without any reference counting.
IDLE_TIMEOUT = 300 # 5 minutes
IDLE_TIMEOUT = 1200 # 20 minutes

# GC sweep period.
GC_INTERVAL = 30
Expand Down
Loading
Loading