Added timeout configuration for different volume create scenarios.
* Updated blockstorage create_active_volume behavior method to use new create-method-specific timeout calculators and config iptions. * Fixed docstring discrepencies in behaviors and configs. * some pep8 fixes. Change-Id: Ibcdd2e07cdbc86cc9c98136c72adc9912fde5551
This commit is contained in:
@@ -18,7 +18,7 @@ class VolumesAPI_CommonBehaviors(BaseBehavior):
|
||||
self._log.error(msg)
|
||||
raise VolumesAPIBehaviorException(msg)
|
||||
|
||||
#Verify volume response entity deserialized correctly
|
||||
# Verify volume response entity deserialized correctly
|
||||
if resp.entity is None:
|
||||
msg = "Response body did not deserialize as expected"
|
||||
self._log.error(msg)
|
||||
@@ -71,6 +71,31 @@ class VolumesAPI_CommonBehaviors(BaseBehavior):
|
||||
|
||||
return timeout
|
||||
|
||||
def calculate_copy_image_to_volume_timeout(self, image_size):
|
||||
timeout = self._calculate_timeout(
|
||||
size=image_size,
|
||||
max_timeout=self.config.copy_image_to_volume_max_timeout,
|
||||
min_timeout=self.config.copy_image_to_volume_min_timeout,
|
||||
wait_per_gb=self.config.copy_image_to_volume_wait_per_gigabyte)
|
||||
if not timeout:
|
||||
timeout = self.config.copy_image_to_volume_base_timeout
|
||||
else:
|
||||
timeout += self.config.copy_image_to_volume_base_timeout
|
||||
|
||||
return timeout
|
||||
|
||||
def calculate_restore_snapshot_timeout(self, image_size):
|
||||
timeout = self._calculate_timeout(
|
||||
size=image_size,
|
||||
max_timeout=self.config.restore_snapshot_max_timeout,
|
||||
min_timeout=self.config.restore_snapshot_min_timeout,
|
||||
wait_per_gb=self.config.restore_snapshot_wait_per_gigabyte)
|
||||
if not timeout:
|
||||
timeout = self.config.snapshot_restore_base_timeout
|
||||
else:
|
||||
timeout += self.config.snapshot_restore_base_timeout
|
||||
return timeout
|
||||
|
||||
def calculate_snapshot_create_timeout(self, volume_size):
|
||||
timeout = self._calculate_timeout(
|
||||
size=volume_size,
|
||||
@@ -181,8 +206,9 @@ class VolumesAPI_CommonBehaviors(BaseBehavior):
|
||||
self._verify_entity(resp)
|
||||
|
||||
if resp.entity.status == expected_status:
|
||||
self._log.info('Expected Snapshot status "{0}" observed'
|
||||
.format(expected_status))
|
||||
self._log.info(
|
||||
'Expected Snapshot status "{0}" observed'.format(
|
||||
expected_status))
|
||||
break
|
||||
sleep(poll_rate)
|
||||
|
||||
@@ -198,16 +224,45 @@ class VolumesAPI_CommonBehaviors(BaseBehavior):
|
||||
self, size, volume_type, name=None, description=None,
|
||||
availability_zone=None, metadata=None, bootable=None,
|
||||
image_ref=None, snapshot_id=None, source_volid=None, timeout=None):
|
||||
"""Create a volume and wait for it to reach the 'available' status"""
|
||||
|
||||
metadata = metadata or {}
|
||||
timeout = timeout or self.calculate_volume_create_timeout(size)
|
||||
|
||||
try:
|
||||
if image_ref:
|
||||
timeout = self.calculate_copy_image_to_volume_timeout(size)
|
||||
self._log.info(
|
||||
"Copy image to volume timeout calculated at {0} "
|
||||
"seconds".format(timeout))
|
||||
|
||||
elif snapshot_id:
|
||||
timeout = self.calculate_snapshot_restore_timeout(size)
|
||||
self._log.info(
|
||||
"Create volume from snapshot timeout calculated at {0} "
|
||||
"seconds".format(timeout))
|
||||
|
||||
elif source_volid:
|
||||
timeout = self.calculate_volume_clone_timeout(size)
|
||||
self._log.info(
|
||||
"Clone a volume timeout calculated at {0} "
|
||||
"seconds".format(timeout))
|
||||
except:
|
||||
# Worst case if no config values are set.
|
||||
# Use the default volume create timeout.
|
||||
self._log.info(
|
||||
"Unable to use create-method-specific timeout, "
|
||||
"defaulting to normal volume create timeout of {0} "
|
||||
"seconds".format(timeout))
|
||||
|
||||
self._log.info("create_available_volume() is creating a volume")
|
||||
start_time = time()
|
||||
resp = self.create_volume(
|
||||
size, volume_type, name=name, description=description,
|
||||
availability_zone=availability_zone, metadata=metadata,
|
||||
bootable=bootable, image_ref=image_ref, snapshot_id=snapshot_id,
|
||||
source_volid=source_volid)
|
||||
timeout = timeout - (time() - start_time)
|
||||
|
||||
volume = self._verify_entity(resp)
|
||||
|
||||
@@ -215,20 +270,19 @@ class VolumesAPI_CommonBehaviors(BaseBehavior):
|
||||
verifier = StatusProgressionVerifier(
|
||||
'volume', volume.id_, self.get_volume_status, volume.id_)
|
||||
|
||||
verifier.set_global_timeout(timeout)
|
||||
verifier.add_state(
|
||||
expected_statuses=[self.statuses.Volume.CREATING],
|
||||
acceptable_statuses=[self.statuses.Volume.AVAILABLE],
|
||||
error_statuses=[self.statuses.Volume.ERROR],
|
||||
timeout=timeout,
|
||||
poll_rate=1)
|
||||
poll_rate=self.config.volume_status_poll_frequency)
|
||||
|
||||
verifier.add_state(
|
||||
expected_statuses=[self.statuses.Volume.AVAILABLE],
|
||||
error_statuses=[self.statuses.Volume.ERROR],
|
||||
timeout=timeout, poll_rate=1)
|
||||
poll_rate=self.config.volume_status_poll_frequency)
|
||||
|
||||
verifier.start()
|
||||
|
||||
# Return volume model
|
||||
resp = self.client.get_volume_info(volume.id_)
|
||||
volume = self._verify_entity(resp)
|
||||
@@ -325,9 +379,9 @@ class VolumesAPI_CommonBehaviors(BaseBehavior):
|
||||
self._log.error(timeout_msg)
|
||||
return False
|
||||
|
||||
#Contine where last timeout loop left off
|
||||
# Contine where last timeout loop left off
|
||||
while time() < end:
|
||||
#Poll volume status to make sure it deleted properly
|
||||
# Poll volume status to make sure it deleted properly
|
||||
status_resp = self.client.get_volume_info(volume_id)
|
||||
if status_resp.status_code == 404:
|
||||
self._log.info(
|
||||
@@ -398,7 +452,7 @@ class VolumesAPI_CommonBehaviors(BaseBehavior):
|
||||
def delete_volume_with_snapshots_confirmed(self, volume_id):
|
||||
"""Returns True if volume deleted, False otherwise"""
|
||||
|
||||
#Attempt to delete all snapshots associated with provided volume_id
|
||||
# Attempt to delete all snapshots associated with provided volume_id
|
||||
snapshots = self.list_volume_snapshots(volume_id)
|
||||
if snapshots:
|
||||
for snap in snapshots:
|
||||
|
||||
@@ -23,12 +23,14 @@ class VolumesAPIConfig(ConfigSectionInterface):
|
||||
|
||||
@property
|
||||
def serialize_format(self):
|
||||
"""Sets all reqeusts made to this api in either json or xml"""
|
||||
"""Sets all reqeusts made to the volumes api in either json or xml"""
|
||||
return self.get("serialize_format", default="json")
|
||||
|
||||
@property
|
||||
def deserialize_format(self):
|
||||
"""Requests all responses from this api to be in either json or xml"""
|
||||
"""Requests all responses from the volumes api to be in either json or
|
||||
xml
|
||||
"""
|
||||
return self.get("deserialize_format", default="json")
|
||||
|
||||
@property
|
||||
@@ -36,7 +38,7 @@ class VolumesAPIConfig(ConfigSectionInterface):
|
||||
"""Version of the cinder api under test, either '1' or '2' """
|
||||
return self.get("version_under_test", default="1")
|
||||
|
||||
# Volumes behavior config
|
||||
# Volume and Snapshot behavior config
|
||||
@property
|
||||
def default_volume_type(self):
|
||||
"""Sets the default volume type for some behaviors and tests"""
|
||||
@@ -54,11 +56,19 @@ class VolumesAPIConfig(ConfigSectionInterface):
|
||||
|
||||
@property
|
||||
def volume_status_poll_frequency(self):
|
||||
"""Controlls the rate at which some behaviors will poll the cinder
|
||||
api for information.
|
||||
"""Controls the rate at which some behaviors will poll the cinder
|
||||
api for volume information.
|
||||
"""
|
||||
return int(self.get("volume_status_poll_frequency", default=5))
|
||||
|
||||
@property
|
||||
def snapshot_status_poll_frequency(self):
|
||||
"""Controls the rate at which some behaviors will poll the cinder
|
||||
api for snapshot information.
|
||||
"""
|
||||
return int(self.get("snapshot_status_poll_frequency", default=10))
|
||||
|
||||
# Volume create timeouts
|
||||
@property
|
||||
def volume_create_min_timeout(self):
|
||||
"""Minimum time to allow any behavior to wait for a volume to finish
|
||||
@@ -84,42 +94,12 @@ class VolumesAPIConfig(ConfigSectionInterface):
|
||||
def volume_create_base_timeout(self):
|
||||
"""Amount of time added by default to the final calculated volume
|
||||
create timeouts for some behaviors. Useful for adding a constant
|
||||
amount of time to create timeouts globaly for dialing in good test
|
||||
amount of time to create timeouts globally for dialing in good test
|
||||
timeouts
|
||||
"""
|
||||
return int(self.get("volume_create_base_timeout", default=0))
|
||||
|
||||
@property
|
||||
def volume_clone_min_timeout(self):
|
||||
"""Minimum time to allow any behavior to wait for a volume to finish
|
||||
creating when using another volume as its source.
|
||||
"""
|
||||
return int(self.get("volume_clone_min_timeout", default=2))
|
||||
|
||||
@property
|
||||
def volume_clone_max_timeout(self):
|
||||
"""Maximum time to allow any behavior to wait for a volume to finish
|
||||
creating when using another volume as its source.
|
||||
"""
|
||||
return int(self.get("volume_clone_max_timeout", default=1200))
|
||||
|
||||
@property
|
||||
def volume_clone_wait_per_gigabyte(self):
|
||||
"""Used by some behaviors to attempt to calculate the time it will
|
||||
take for a volume to be created based on it's size when using another
|
||||
volume as its source
|
||||
"""
|
||||
return int(self.get("volume_clone_wait_per_gigabyte", default=2))
|
||||
|
||||
@property
|
||||
def volume_clone_base_timeout(self):
|
||||
"""Amount of time added by default to the final calculated volume
|
||||
clone timeouts for some behaviors. Useful for adding a constant
|
||||
amount of time to clone timeouts globaly for dialing in good test
|
||||
timeouts.
|
||||
"""
|
||||
return int(self.get("volume_create_base_timeout", default=0))
|
||||
return int(self.get("volume_create_base_timeout", default=1))
|
||||
|
||||
# Volume delete timeouts
|
||||
@property
|
||||
def volume_delete_min_timeout(self):
|
||||
"""Maximum time some behaviors wait for a volume to be confirmed
|
||||
@@ -139,14 +119,75 @@ class VolumesAPIConfig(ConfigSectionInterface):
|
||||
"""
|
||||
return int(self.get("volume_delete_wait_per_gigabyte", default=1))
|
||||
|
||||
# Snapshot behaviors config
|
||||
# Clone volume timeouts
|
||||
@property
|
||||
def snapshot_status_poll_frequency(self):
|
||||
"""Controlls the rate at which some behaviors will poll the cinder
|
||||
api for information.
|
||||
def volume_clone_min_timeout(self):
|
||||
"""Minimum time to allow any behavior to wait for a volume to finish
|
||||
creating when using another volume as its source.
|
||||
"""
|
||||
return int(self.get("snapshot_status_poll_frequency", default=10))
|
||||
return int(self.get("volume_clone_min_timeout"))
|
||||
|
||||
@property
|
||||
def volume_clone_max_timeout(self):
|
||||
"""Maximum time to allow any behavior to wait for a volume to finish
|
||||
creating when using another volume as its source.
|
||||
"""
|
||||
return int(self.get("volume_clone_max_timeout"))
|
||||
|
||||
@property
|
||||
def volume_clone_wait_per_gigabyte(self):
|
||||
"""Used by some behaviors to attempt to calculate the time it will
|
||||
take for a volume to be created based on it's size when using another
|
||||
volume as its source
|
||||
"""
|
||||
return int(self.get("volume_clone_wait_per_gigabyte"))
|
||||
|
||||
@property
|
||||
def volume_clone_base_timeout(self):
|
||||
"""Amount of time added by default to the final calculated volume
|
||||
clone timeouts for some behaviors. Useful for adding a constant
|
||||
amount of time to clone timeouts globally for dialing in good test
|
||||
timeouts.
|
||||
"""
|
||||
return int(self.get("volume_clone_base_timeout"))
|
||||
|
||||
# Copy image to volume timeouts
|
||||
@property
|
||||
def min_volume_from_image_size(self):
|
||||
"""Minimum size a volume can be if building from an image.
|
||||
Used by some behaviors and tests. Depending on how the environment
|
||||
under test is deployed, this value may be superceded by the
|
||||
minimum allowed volume size
|
||||
"""
|
||||
return int(self.get("min_volume_from_image_size"))
|
||||
|
||||
@property
|
||||
def copy_image_to_volume_base_timeout(self):
|
||||
"""Base time to add to any calculated copy-image-to-volume timeouts"""
|
||||
return int(self.get("copy_image_to_volume_base_timeout"))
|
||||
|
||||
@property
|
||||
def copy_image_to_volume_max_timeout(self):
|
||||
"""Maximum amount in time to wait for a create-volume-from-image
|
||||
request to timeout before raising an error
|
||||
"""
|
||||
return int(self.get("copy_image_to_volume_max_timeout"))
|
||||
|
||||
@property
|
||||
def copy_image_to_volume_min_timeout(self):
|
||||
"""Minimum amount in time to wait for a create-volume-from-image
|
||||
request to timeout before raising an error
|
||||
"""
|
||||
return int(self.get("copy_image_to_volume_min_timeout"))
|
||||
|
||||
@property
|
||||
def copy_image_to_volume_wait_per_gigabyte(self):
|
||||
"""Amount of time in seconds to wait per gigabyte of size of the image
|
||||
being copied to the volume
|
||||
"""
|
||||
return int(self.get("copy_image_to_volume_wait_per_gigabyte"))
|
||||
|
||||
# Snapshot create timeouts
|
||||
@property
|
||||
def snapshot_create_max_timeout(self):
|
||||
"""Maximum time to allow any behavior to wait for a snapshot to finish
|
||||
@@ -164,9 +205,9 @@ class VolumesAPIConfig(ConfigSectionInterface):
|
||||
@property
|
||||
def snapshot_create_base_timeout(self):
|
||||
"""Amount of time added by default to the final calculated volume
|
||||
snapshot timeouts for some behaviors. Useful for adding a constant
|
||||
amount of time to volume snapshot timeouts globaly for dialing in good
|
||||
test timeouts.
|
||||
snapshot create timeouts for some behaviors. Useful for adding a
|
||||
constant amount of time to volume snapshot timeouts globally for
|
||||
dialing in good test timeouts.
|
||||
"""
|
||||
return int(self.get("snapshot_create_base_timeout", default=0))
|
||||
|
||||
@@ -178,6 +219,7 @@ class VolumesAPIConfig(ConfigSectionInterface):
|
||||
"""
|
||||
return int(self.get("snapshot_create_wait_per_gigabyte", default=600))
|
||||
|
||||
# Snapshot delete timeouts
|
||||
@property
|
||||
def snapshot_delete_max_timeout(self):
|
||||
"""Maximum time some behaviors wait for a volume snapshot to be
|
||||
@@ -204,20 +246,44 @@ class VolumesAPIConfig(ConfigSectionInterface):
|
||||
def snapshot_delete_base_timeout(self):
|
||||
"""Amount of time added by default to the final calculated volume
|
||||
snapshot timeouts for some behaviors. Useful for adding a constant
|
||||
amount of time to volume snapshot timeouts globaly for dialing in good
|
||||
amount of time to volume snapshot timeouts globally for dialing in good
|
||||
test timeouts.
|
||||
"""
|
||||
return int(self.get("snapshot_delete_base_timeout", default=60))
|
||||
|
||||
# Misc
|
||||
# Restore snapshot to volume timeouts
|
||||
@property
|
||||
def min_volume_from_image_size(self):
|
||||
"""Minimum size a volume can be if building from an image.
|
||||
Used by some behaviors and tests. Depending on how the environment
|
||||
under test is deployed, this value may be superceded by the
|
||||
minimum allowed volume size"""
|
||||
return int(self.get("min_volume_from_image_size", default=1))
|
||||
def snapshot_restore_base_timeout(self):
|
||||
"""Amount of time added by default to the final calculated volume
|
||||
snapshot restore timeouts for some behaviors. Useful for adding a
|
||||
constant amount of time to volume snapshot restore timeouts globally
|
||||
for dialing in good test timeouts.
|
||||
"""
|
||||
return int(self.get("snapshot_restore_base_timeout"))
|
||||
|
||||
@property
|
||||
def snapshot_restore_min_timeout(self):
|
||||
"""Minimum time to allow any behavior to wait for a snapshot to finish
|
||||
restoring to a new volume.
|
||||
"""
|
||||
return int(self.get("snapshot_restore_min_timeout"))
|
||||
|
||||
@property
|
||||
def snapshot_restore_max_timeout(self):
|
||||
"""Maximum time to allow any behavior to wait for a snapshot to finish
|
||||
restoring to a new volume.
|
||||
"""
|
||||
return int(self.get("snapshot_restore_max_timeout"))
|
||||
|
||||
@property
|
||||
def snapshot_restore_wait_per_gigabyte(self):
|
||||
"""Used by some behaviors to attempt to calculate the time it will
|
||||
take for a snapshot to be restored based on the size of the original
|
||||
volume.
|
||||
"""
|
||||
return int(self.get("snapshot_restore_wait_per_gigabyte"))
|
||||
|
||||
# Misc
|
||||
@property
|
||||
def image_filter(self):
|
||||
"""Expects Json. Returns an empty dictionary by default (no filter).
|
||||
|
||||
Reference in New Issue
Block a user