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:
Jose Idar
2014-08-14 16:48:52 -05:00
parent 2ad2a4413c
commit c50a730354
3 changed files with 230 additions and 69 deletions

View File

@@ -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:

View File

@@ -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).