Merge "Moved logic from monolithic attach/detach behaviors into component methods"

This commit is contained in:
Jenkins 2016-03-03 16:56:35 +00:00 committed by Gerrit Code Review
commit ab0bbfcd34
1 changed files with 87 additions and 62 deletions

View File

@ -21,20 +21,38 @@ class VolumeAttachmentsAPI_Behaviors(BaseComputeBehavior):
self.config = volume_attachments_config or VolumeAttachmentsAPIConfig()
self.volumes_client = volumes_client
def wait_for_attachment_to_propagate(
self, attachment_id, server_id, timeout=None, poll_rate=5):
def _validated_volume_attach(self, server_id, volume_id, device=None):
"""Performs a volume attach with response validation"""
timeout = timeout or self.config.attachment_propagation_timeout
poll_rate = poll_rate or self.config.api_poll_rate
endtime = time() + int(timeout)
while time() < endtime:
resp = self.client.get_volume_attachment_details(
attachment_id, server_id)
if resp.ok:
return True
sleep(poll_rate)
else:
return False
resp = self.client.attach_volume(server_id, volume_id, device=device)
if not resp.ok:
raise VolumeAttachmentBehaviorError(
"Volume attachment failed in attach_volume_to_server "
"with a '{0}'. Could not attach volume {1} to server {2}"
.format(resp.status_code, volume_id, server_id))
if resp.entity is None:
raise VolumeAttachmentBehaviorError(
"Volume attachment failed in auto_attach_volume_to_server. "
"Could not deserialize volume attachment response body. "
"Could not attach volume '{1}' to server '{2}'".format(
volume_id, server_id))
return resp
def _validated_volume_detach(self, attachment_id, server_id):
resp = self.client.delete_volume_attachment(
attachment_id, server_id)
if not resp.ok:
raise VolumeAttachmentBehaviorError(
"Volume attachment DELETE failed in delete_volume_attachment "
"with a {0}. Could not delete attachment '{1}' on server "
"'{2}'".format(resp.status_code, attachment_id, server_id))
return resp
def _get_volume_status(self, volume_id):
resp = self.volumes_client.get_volume_info(volume_id=volume_id)
@ -54,6 +72,41 @@ class VolumeAttachmentsAPI_Behaviors(BaseComputeBehavior):
return resp.entity.status
def wait_for_attachment_to_propagate(
self, attachment_id, server_id, timeout=None, poll_rate=5):
timeout = timeout or self.config.attachment_propagation_timeout
poll_rate = poll_rate or self.config.api_poll_rate
endtime = time() + int(timeout)
while time() < endtime:
resp = self.client.get_volume_attachment_details(
attachment_id, server_id)
if resp.ok:
return True
sleep(poll_rate)
else:
return False
def wait_for_attachment_to_delete(
self, attachment_id, server_id, timeout=None, poll_rate=None):
timeout = timeout or self.config.attachment_propagation_timeout
poll_rate = poll_rate or self.config.api_poll_rate
endtime = time() + int(timeout)
while time() < endtime:
resp = self.client.get_volume_attachment_details(
attachment_id, server_id)
if resp.status_code == 404:
return None
sleep(poll_rate)
else:
raise VolumeAttachmentBehaviorError(
"Volume Attachment {0} still exists on server '{1}', {2} "
"seconds after a successful DELETE. Could not verify that "
"attachment was deleted.".format(
attachment_id, server_id, timeout))
def verify_volume_status_progression_during_attachment(
self, volume_id, state_list=None):
@ -115,7 +168,8 @@ class VolumeAttachmentsAPI_Behaviors(BaseComputeBehavior):
verifier.add_state(
expected_statuses=['available'],
error_statuses=['error', 'attaching', 'creating', 'deleting'],
error_statuses=[
'error', 'attaching', 'creating', 'deleting', 'in-use'],
poll_rate=self.config.api_poll_rate,
poll_failure_retry_limit=3)
@ -125,62 +179,23 @@ class VolumeAttachmentsAPI_Behaviors(BaseComputeBehavior):
if raise_on_error:
raise exception
def delete_volume_attachment(
self, attachment_id, server_id, timeout=None, poll_rate=None):
"""Waits timeout seconds for volume attachment to 404 after issuing
a delete to it
"""
timeout = timeout or self.config.attachment_propagation_timeout
poll_rate = poll_rate or self.config.api_poll_rate
endtime = time() + int(timeout)
resp = self.client.delete_volume_attachment(
attachment_id, server_id)
if not resp.ok:
raise VolumeAttachmentBehaviorError(
"Volume attachment DELETE failed in delete_volume_attachment "
"with a {0}. Could not delete attachment '{1}' on server "
"'{2}'".format(resp.status_code, attachment_id, server_id))
while time() < endtime:
resp = self.client.get_volume_attachment_details(
attachment_id, server_id)
if resp.status_code == 404:
return None
sleep(poll_rate)
else:
raise VolumeAttachmentBehaviorError(
"Volume Attachment {0} still exists on server '{1}', {2} "
"seconds after a successful DELETE. Could not verify that "
"attachment was deleted.".format(
attachment_id, server_id, timeout))
def attach_volume_to_server(
self, server_id, volume_id, device=None,
attachment_propagation_timeout=60):
"""Returns a VolumeAttachment object"""
"""
Performs response validation on attach call, confirms volume attachment
propogation, and verifies volume status progression during the attach
process.
:rtype: VolumeAttachment model
"""
attachment_propagation_timeout = (
attachment_propagation_timeout
or self.config.attachment_propagation_timeout)
resp = self.client.attach_volume(server_id, volume_id, device=device)
if not resp.ok:
raise VolumeAttachmentBehaviorError(
"Volume attachment failed in attach_volume_to_server "
"with a '{0}'. Could not attach volume {1} to server {2}"
.format(resp.status_code, volume_id, server_id))
if resp.entity is None:
raise VolumeAttachmentBehaviorError(
"Volume attachment failed in auto_attach_volume_to_server. "
"Could not deserialize volume attachment response body. "
"Could not attach volume '{1}' to server '{2}'".format(
volume_id, server_id))
# Attach volume to server (validate response)
resp = self._validated_volume_attach(server_id, volume_id, device)
attachment = resp.entity
# Confirm volume attachment propagation
@ -197,3 +212,13 @@ class VolumeAttachmentsAPI_Behaviors(BaseComputeBehavior):
self.verify_volume_status_progression_during_attachment(volume_id)
return attachment
def delete_volume_attachment(
self, attachment_id, server_id, timeout=None, poll_rate=None):
"""Waits timeout seconds for volume attachment to 404 after issuing
a delete to it.
Raises exception on error.
"""
self._validated_volume_detach(attachment_id, server_id)
self.wait_for_attachment_to_delete(
attachment_id, server_id, timeout, poll_rate)