Skip to content

Commit 4ab2f40

Browse files
committed
fix(linstor): handle volume creation failure in clone rollback
A clone rollback may be initiated because the new volume could not be physically created. This can be detected by checking the `not-exists` property of this volume. If this property tells us that the new volume doesn't actually exist, then we mark it for later deletion by the GC so that rolling back the UUID of the base VDI doesn't fail later on. Signed-off-by: Alexandre Sollier <alexandre.sollier@vates.tech>
1 parent 8817813 commit 4ab2f40

2 files changed

Lines changed: 26 additions & 0 deletions

File tree

drivers/LinstorSR.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1481,6 +1481,18 @@ def _undo_clone(self, volume_names, vdi_uuid, base_uuid, snap_uuid):
14811481
# properly the base VDI below this line, so we must change the
14821482
# UUID of this bad VDI before.
14831483
self._linstor.mark_volume_for_deletion(vdi_uuid, force=True)
1484+
else:
1485+
not_exists_state = self._linstor.get_volume_not_exists_state(vdi_uuid)
1486+
1487+
if not_exists_state and not_exists_state != LinstorVolumeManager.STATE_EXISTS:
1488+
# At this point, some of the new volume properties were created,
1489+
# but volume creation was interrupted before the volume itself
1490+
# could be physically created.
1491+
# We mark this new volume for deletion so that the base VDI UUID
1492+
# can be restored back to its original value.
1493+
util.SMlog(f"VDI {vdi_uuid} was partially created, marking it for deletion")
1494+
1495+
self._linstor.mark_volume_for_deletion(vdi_uuid, force=True)
14841496

14851497
# Rename!
14861498
self._linstor.update_volume_uuid(base_uuid, vdi_uuid)

drivers/linstorvolumemanager.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1344,6 +1344,20 @@ def update_volume_metadata(self, volume_uuid, metadata):
13441344
current_metadata[key] = value
13451345
volume_properties[self.PROP_METADATA] = json.dumps(current_metadata)
13461346

1347+
def get_volume_not_exists_state(self, volume_uuid):
1348+
"""
1349+
Get the "not-exists" state of a volume.
1350+
:param str volume_uuid: The target volume.
1351+
:return: The "not-exists" state.
1352+
:rtype: Optional[str]
1353+
"""
1354+
1355+
# We do not ensure that the volume exists since it might not
1356+
# physically exist (for example, the volume creation failed), but it
1357+
# might still have had its "not-exists" property set.
1358+
volume_properties = self._get_volume_properties(volume_uuid)
1359+
return volume_properties.get(self.PROP_NOT_EXISTS)
1360+
13471361
def shallow_clone_volume(self, volume_uuid, clone_uuid, persistent=True):
13481362
"""
13491363
Clone a volume. Do not copy the data, this method creates a new volume

0 commit comments

Comments
 (0)