Skip to content

Commit f534d4a

Browse files
committed
fix(LinstorSR): ensure we can detach when deflate call is not possible
Signed-off-by: Ronan Abhamon <[email protected]>
1 parent 9c27161 commit f534d4a

File tree

1 file changed

+30
-15
lines changed

1 file changed

+30
-15
lines changed

drivers/LinstorSR.py

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ def attach_thin(session, journaler, linstor, sr_uuid, vdi_uuid):
175175
lock.release()
176176

177177

178-
def detach_thin(session, linstor, sr_uuid, vdi_uuid):
178+
def detach_thin_impl(session, linstor, sr_uuid, vdi_uuid):
179179
volume_metadata = linstor.get_volume_metadata(vdi_uuid)
180180
image_type = volume_metadata.get(VDI_TYPE_TAG)
181181
if image_type == vhdutil.VDI_TYPE_RAW:
@@ -185,21 +185,26 @@ def detach_thin(session, linstor, sr_uuid, vdi_uuid):
185185
try:
186186
lock.acquire()
187187

188-
vdi_ref = session.xenapi.VDI.get_by_uuid(vdi_uuid)
189-
vbds = session.xenapi.VBD.get_all_records_where(
190-
'field "VDI" = "{}"'.format(vdi_ref)
191-
)
188+
def check_vbd_count():
189+
vdi_ref = session.xenapi.VDI.get_by_uuid(vdi_uuid)
190+
vbds = session.xenapi.VBD.get_all_records_where(
191+
'field "VDI" = "{}"'.format(vdi_ref)
192+
)
192193

193-
num_plugged = 0
194-
for vbd_rec in vbds.values():
195-
if vbd_rec['currently_attached']:
196-
num_plugged += 1
197-
if num_plugged > 1:
198-
raise xs_errors.XenError(
199-
'VDIUnavailable',
200-
opterr='Cannot deflate VDI {}, already used by '
201-
'at least 2 VBDs'.format(vdi_uuid)
202-
)
194+
num_plugged = 0
195+
for vbd_rec in vbds.values():
196+
if vbd_rec['currently_attached']:
197+
num_plugged += 1
198+
if num_plugged > 1:
199+
raise xs_errors.XenError(
200+
'VDIUnavailable',
201+
opterr='Cannot deflate VDI {}, already used by '
202+
'at least 2 VBDs'.format(vdi_uuid)
203+
)
204+
205+
# We can have multiple VBDs attached to a VDI during a VM-template clone.
206+
# So we use a timeout to ensure that we can detach the volume properly.
207+
util.retry(check_vbd_count, maxretry=10, period=1)
203208

204209
device_path = linstor.get_device_path(vdi_uuid)
205210
new_volume_size = LinstorVolumeManager.round_up_volume_size(
@@ -217,6 +222,16 @@ def detach_thin(session, linstor, sr_uuid, vdi_uuid):
217222
lock.release()
218223

219224

225+
def detach_thin(session, linstor, sr_uuid, vdi_uuid):
226+
# This function must always return without errors.
227+
# Otherwise it could cause errors in the XAPI regarding the state of the VDI.
228+
# It's why we use this `try` block.
229+
try:
230+
detach_thin_impl(session, linstor, sr_uuid, vdi_uuid)
231+
except Exception as e:
232+
util.SMlog('Failed to detach properly VDI {}: {}'.format(vdi_uuid, e))
233+
234+
220235
def inflate(journaler, linstor, vdi_uuid, vdi_path, new_size, old_size):
221236
# Only inflate if the LINSTOR volume capacity is not enough.
222237
new_size = LinstorVolumeManager.round_up_volume_size(new_size)

0 commit comments

Comments
 (0)