Merge "Moved logic from monolithic attach/detach behaviors into component methods"
This commit is contained in:
commit
ab0bbfcd34
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user