Merge "Update volume-status waiter for new cinder attach"

This commit is contained in:
Jenkins 2017-07-06 06:42:28 +00:00 committed by Gerrit Code Review
commit 8390829df2
3 changed files with 23 additions and 12 deletions

View File

@ -424,7 +424,7 @@ class BaseV2ComputeTest(api_version_utils.BaseMicroversionTest,
LOG.exception('Waiting for deletion of volume %s failed', LOG.exception('Waiting for deletion of volume %s failed',
volume['id']) volume['id'])
def attach_volume(self, server, volume, device=None): def attach_volume(self, server, volume, device=None, check_reserved=False):
"""Attaches volume to server and waits for 'in-use' volume status. """Attaches volume to server and waits for 'in-use' volume status.
The volume will be detached when the test tears down. The volume will be detached when the test tears down.
@ -433,10 +433,15 @@ class BaseV2ComputeTest(api_version_utils.BaseMicroversionTest,
:param volume: The volume to attach. :param volume: The volume to attach.
:param device: Optional mountpoint for the attached volume. Note that :param device: Optional mountpoint for the attached volume. Note that
this is not guaranteed for all hypervisors and is not recommended. this is not guaranteed for all hypervisors and is not recommended.
:param check_reserved: Consider a status of reserved as valid for
completion. This is to handle new Cinder attach where we more
accurately use 'reserved' for things like attaching to a shelved
server.
""" """
attach_kwargs = dict(volumeId=volume['id']) attach_kwargs = dict(volumeId=volume['id'])
if device: if device:
attach_kwargs['device'] = device attach_kwargs['device'] = device
attachment = self.servers_client.attach_volume( attachment = self.servers_client.attach_volume(
server['id'], **attach_kwargs)['volumeAttachment'] server['id'], **attach_kwargs)['volumeAttachment']
# On teardown detach the volume and wait for it to be available. This # On teardown detach the volume and wait for it to be available. This
@ -449,8 +454,11 @@ class BaseV2ComputeTest(api_version_utils.BaseMicroversionTest,
self.addCleanup(test_utils.call_and_ignore_notfound_exc, self.addCleanup(test_utils.call_and_ignore_notfound_exc,
self.servers_client.detach_volume, self.servers_client.detach_volume,
server['id'], volume['id']) server['id'], volume['id'])
statuses = ['in-use']
if check_reserved:
statuses.append('reserved')
waiters.wait_for_volume_resource_status(self.volumes_client, waiters.wait_for_volume_resource_status(self.volumes_client,
volume['id'], 'in-use') volume['id'], statuses)
return attachment return attachment

View File

@ -212,7 +212,8 @@ class AttachVolumeShelveTestJSON(AttachVolumeTestJSON):
num_vol = self._count_volumes(server) num_vol = self._count_volumes(server)
self._shelve_server(server) self._shelve_server(server)
attachment = self.attach_volume(server, volume, attachment = self.attach_volume(server, volume,
device=('/dev/%s' % self.device)) device=('/dev/%s' % self.device),
check_reserved=True)
# Unshelve the instance and check that attached volume exists # Unshelve the instance and check that attached volume exists
self._unshelve_server_and_check_volumes(server, num_vol + 1) self._unshelve_server_and_check_volumes(server, num_vol + 1)
@ -239,7 +240,8 @@ class AttachVolumeShelveTestJSON(AttachVolumeTestJSON):
self._shelve_server(server) self._shelve_server(server)
# Attach and then detach the volume # Attach and then detach the volume
self.attach_volume(server, volume, device=('/dev/%s' % self.device)) self.attach_volume(server, volume, device=('/dev/%s' % self.device),
check_reserved=True)
self.servers_client.detach_volume(server['id'], volume['id']) self.servers_client.detach_volume(server['id'], volume['id'])
waiters.wait_for_volume_resource_status(self.volumes_client, waiters.wait_for_volume_resource_status(self.volumes_client,
volume['id'], 'available') volume['id'], 'available')

View File

@ -179,25 +179,26 @@ def wait_for_image_status(client, image_id, status):
raise lib_exc.TimeoutException(message) raise lib_exc.TimeoutException(message)
def wait_for_volume_resource_status(client, resource_id, status): def wait_for_volume_resource_status(client, resource_id, statuses):
"""Waits for a volume resource to reach a given status. """Waits for a volume resource to reach any of the specified statuses.
This function is a common function for volume, snapshot and backup This function is a common function for volume, snapshot and backup
resources. The function extracts the name of the desired resource from resources. The function extracts the name of the desired resource from
the client class name of the resource. the client class name of the resource.
""" """
resource_name = re.findall( if not isinstance(statuses, list):
r'(Volume|Snapshot|Backup|Group)', statuses = [statuses]
client.__class__.__name__)[0].lower() resource_name = re.findall(r'(Volume|Snapshot|Backup|Group)',
client.__class__.__name__)[0].lower()
show_resource = getattr(client, 'show_' + resource_name) show_resource = getattr(client, 'show_' + resource_name)
resource_status = show_resource(resource_id)[resource_name]['status'] resource_status = show_resource(resource_id)[resource_name]['status']
start = int(time.time()) start = int(time.time())
while resource_status != status: while resource_status not in statuses:
time.sleep(client.build_interval) time.sleep(client.build_interval)
resource_status = show_resource(resource_id)[ resource_status = show_resource(resource_id)[
'{}'.format(resource_name)]['status'] '{}'.format(resource_name)]['status']
if resource_status == 'error' and resource_status != status: if resource_status == 'error' and resource_status not in statuses:
raise exceptions.VolumeResourceBuildErrorException( raise exceptions.VolumeResourceBuildErrorException(
resource_name=resource_name, resource_id=resource_id) resource_name=resource_name, resource_id=resource_id)
if resource_name == 'volume' and resource_status == 'error_restoring': if resource_name == 'volume' and resource_status == 'error_restoring':
@ -206,7 +207,7 @@ def wait_for_volume_resource_status(client, resource_id, status):
if int(time.time()) - start >= client.build_timeout: if int(time.time()) - start >= client.build_timeout:
message = ('%s %s failed to reach %s status (current %s) ' message = ('%s %s failed to reach %s status (current %s) '
'within the required time (%s s).' % 'within the required time (%s s).' %
(resource_name, resource_id, status, resource_status, (resource_name, resource_id, statuses, resource_status,
client.build_timeout)) client.build_timeout))
raise lib_exc.TimeoutException(message) raise lib_exc.TimeoutException(message)