Skip to content

Commit 729bf14

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Robustify attachment tracking in CinderFixtureNewAttachFlow"
2 parents 6339e8c + 1d3ca5a commit 729bf14

File tree

1 file changed

+37
-20
lines changed

1 file changed

+37
-20
lines changed

nova/tests/fixtures.py

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1847,16 +1847,21 @@ def __init__(self, test):
18471847
self.swap_volume_instance_uuid = None
18481848
self.swap_volume_instance_error_uuid = None
18491849
self.attachment_error_id = None
1850-
# A map of volumes to a list of (attachment_id, instance_uuid).
1850+
# A dict, keyed by volume id, to a dict, keyed by attachment id,
1851+
# with keys:
1852+
# - id: the attachment id
1853+
# - instance_uuid: uuid of the instance attached to the volume
1854+
# - connector: host connector dict; None if not connected
18511855
# Note that a volume can have multiple attachments even without
18521856
# multi-attach, as some flows create a blank 'reservation' attachment
1853-
# before deleting another attachment.
1854-
self.volume_to_attachment = collections.defaultdict(list)
1857+
# before deleting another attachment. However, a non-multiattach volume
1858+
# can only have at most one attachment with a host connector at a time.
1859+
self.volume_to_attachment = collections.defaultdict(dict)
18551860

18561861
def volume_ids_for_instance(self, instance_uuid):
18571862
for volume_id, attachments in self.volume_to_attachment.items():
1858-
for _, _instance_uuid in attachments:
1859-
if _instance_uuid == instance_uuid:
1863+
for attachment in attachments.values():
1864+
if attachment['instance_uuid'] == instance_uuid:
18601865
# we might have multiple volumes attached to this instance
18611866
# so yield rather than return
18621867
yield volume_id
@@ -1888,14 +1893,14 @@ def fake_get(self_api, context, volume_id, microversion=None):
18881893
else self.swap_volume_instance_error_uuid)
18891894

18901895
if attachments:
1891-
attachment_id, instance_uuid = attachments[0]
1896+
attachment = list(attachments.values())[0]
18921897

18931898
volume.update({
18941899
'status': 'in-use',
18951900
'attachments': {
18961901
instance_uuid: {
18971902
'mountpoint': '/dev/vdb',
1898-
'attachment_id': attachment_id
1903+
'attachment_id': attachment['id']
18991904
}
19001905
},
19011906
'attach_status': 'attached'
@@ -1905,7 +1910,7 @@ def fake_get(self_api, context, volume_id, microversion=None):
19051910
# Check to see if the volume is attached.
19061911
if attachments:
19071912
# The volume is attached.
1908-
attachment_id, instance_uuid = attachments[0]
1913+
attachment = list(attachments.values())[0]
19091914
volume = {
19101915
'status': 'in-use',
19111916
'display_name': volume_id,
@@ -1914,8 +1919,8 @@ def fake_get(self_api, context, volume_id, microversion=None):
19141919
'multiattach': volume_id == self.MULTIATTACH_VOL,
19151920
'size': 1,
19161921
'attachments': {
1917-
instance_uuid: {
1918-
'attachment_id': attachment_id,
1922+
attachment['instance_uuid']: {
1923+
'attachment_id': attachment['id'],
19191924
'mountpoint': '/dev/vdb'
19201925
}
19211926
}
@@ -1959,14 +1964,13 @@ def _find_attachment(attachment_id):
19591964
"""Find attachment corresponding to ``attachment_id``.
19601965
19611966
Returns:
1962-
A tuple of the volume ID, an attachment-instance mapping tuple
1963-
for the given attachment ID, and a list of attachment-instance
1964-
mapping tuples for the volume.
1967+
A tuple of the volume ID, an attachment dict
1968+
for the given attachment ID, and a dict (keyed by attachment
1969+
id) of attachment dicts for the volume.
19651970
"""
19661971
for volume_id, attachments in self.volume_to_attachment.items():
1967-
for attachment in attachments:
1968-
_attachment_id, instance_uuid = attachment
1969-
if attachment_id == _attachment_id:
1972+
for attachment in attachments.values():
1973+
if attachment_id == attachment['id']:
19701974
return volume_id, attachment, attachments
19711975
raise exception.VolumeAttachmentNotFound(
19721976
attachment_id=attachment_id)
@@ -1977,8 +1981,10 @@ def fake_attachment_create(_self, context, volume_id, instance_uuid,
19771981
if self.attachment_error_id is not None:
19781982
attachment_id = self.attachment_error_id
19791983
attachment = {'id': attachment_id, 'connection_info': {'data': {}}}
1980-
self.volume_to_attachment[volume_id].append(
1981-
(attachment_id, instance_uuid))
1984+
self.volume_to_attachment[volume_id][attachment_id] = {
1985+
'id': attachment_id,
1986+
'instance_uuid': instance_uuid,
1987+
'connector': connector}
19821988
LOG.info('Created attachment %s for volume %s. Total '
19831989
'attachments for volume: %d', attachment_id, volume_id,
19841990
len(self.volume_to_attachment[volume_id]))
@@ -1989,15 +1995,26 @@ def fake_attachment_delete(_self, context, attachment_id):
19891995
# 'attachment' is a tuple defining a attachment-instance mapping
19901996
volume_id, attachment, attachments = (
19911997
_find_attachment(attachment_id))
1992-
attachments.remove(attachment)
1998+
del attachments[attachment_id]
19931999
LOG.info('Deleted attachment %s for volume %s. Total attachments '
19942000
'for volume: %d', attachment_id, volume_id,
19952001
len(attachments))
19962002

19972003
def fake_attachment_update(_self, context, attachment_id, connector,
19982004
mountpoint=None):
19992005
# Ensure the attachment exists
2000-
_find_attachment(attachment_id)
2006+
volume_id, attachment, attachments = (
2007+
_find_attachment(attachment_id))
2008+
# Cinder will only allow one "connected" attachment per
2009+
# non-multiattach volume at a time.
2010+
if volume_id != self.MULTIATTACH_VOL:
2011+
for _attachment in attachments.values():
2012+
if _attachment['connector'] is not None:
2013+
raise exception.InvalidInput(
2014+
'Volume %s is already connected with attachment '
2015+
'%s on host %s' % (volume_id, _attachment['id'],
2016+
_attachment['connector'].get('host')))
2017+
attachment['connector'] = connector
20012018
LOG.info('Updating volume attachment: %s', attachment_id)
20022019
attachment_ref = {'driver_volume_type': 'fake_type',
20032020
'id': attachment_id,

0 commit comments

Comments
 (0)