def test_wait_for_snapshot_status_good_response_code_config_wait_period( self): client = Mock(spec=VolumesClient) config = Mock(spec=VolumesAPIConfig) config.snapshot_status_poll_frequency = 1 snapshot_model = Mock(spec=VolumeSnapshotResponse) snapshot_model.status = self.defaults.expected_status response = Mock(spec=Response) response.ok = True response.entity = snapshot_model client.get_snapshot_info = MagicMock( return_value=response) behavior = VolumesAPI_Behaviors(client, config) resp = behavior.wait_for_snapshot_status( self.defaults.snapshot_name, self.defaults.expected_status, self.defaults.timeout) self.assertIsNone(resp)
def test_wait_for_volume_status_good_response_code_bad_status(self): volume_name = 'mock_volume' expected_status = 'available' timeout = 10 poll_rate = 2 client = Mock(spec=VolumesClient) config = Mock(spec=VolumesAPIConfig) config.volume_status_poll_frequency = 1 volume_model = Mock(spec=VolumeResponse) volume_model.status = expected_status response = Mock(spec=Response) response.ok = True response.entity = volume_model client.get_volume_info = MagicMock( return_value=response) behavior = VolumesAPI_Behaviors(client, config) resp = behavior.wait_for_volume_status( volume_name, expected_status, timeout, poll_rate=poll_rate) self.assertIsNone(resp)
def test_get_volume_status(self): client, config, volume_model, response = self.get_mocks() behavior = VolumesAPI_Behaviors(client, config) status = behavior.get_volume_status(self.defaults.volume_id) self.assertEqual(status, self.defaults.expected_status)
def test_wait_for_volume_status_good_response_code_configured_poll_rate( self): client = Mock(spec=VolumesClient) config = Mock(spec=VolumesAPIConfig) config.volume_status_poll_frequency = 1 volume_model = Mock(spec=VolumeResponse) volume_model.status = self.defaults.expected_status response = Mock(spec=Response) response.ok = True response.entity = volume_model client.get_volume_info = MagicMock( return_value=response) behavior = VolumesAPI_Behaviors(client, config) resp = behavior.wait_for_volume_status( self.defaults.volume_name, self.defaults.expected_status, self.defaults.timeout) self.assertIsNone(resp)
def test_wait_for_snapshot_status_good_response_and_entity_bad_status( self): recieved_status = 'error' client = Mock(spec=VolumesClient) config = Mock(spec=VolumesAPIConfig) config.snapshot_status_poll_frequency = 1 snapshot_model = Mock(spec=VolumeSnapshotResponse) snapshot_model.status = recieved_status response = Mock(spec=Response) response.ok = True response.entity = snapshot_model client.get_snapshot_info = MagicMock( return_value=response) behavior = VolumesAPI_Behaviors(client, config) with self.assertRaises(VolumesAPIBehaviorException): behavior.wait_for_snapshot_status( self.defaults.snapshot_name, self.defaults.expected_status, self.defaults.timeout, poll_rate=self.defaults.poll_rate)
def test_good_response_code_configured_poll_period(self): client, config, volume_model, response = self.get_mocks() behavior = VolumesAPI_Behaviors(client, config) resp = behavior.wait_for_volume_status( self.defaults.volume_name, self.defaults.expected_status, self.defaults.timeout) self.assertIsNone(resp)
def test_good_response_code_bad_status(self): client, config, snapshot_model, response = self.get_mocks() behavior = VolumesAPI_Behaviors(client, config) resp = behavior.wait_for_snapshot_status( self.defaults.snapshot_name, self.defaults.expected_status, self.defaults.timeout, poll_rate=self.defaults.poll_rate) self.assertIsNone(resp)
def test_happy_path(self): client, config, volume_model, volume_create_response = self.get_mocks() behavior = VolumesAPI_Behaviors(client, config) behavior.get_volume_status = MagicMock(return_value='available') volume_entity = behavior.create_available_volume( self.defaults.display_name, self.defaults.size, self.defaults.volume_type) self.assertIsInstance(volume_entity, VolumeResponse)
def test_good_response_code_empty_entity(self): client, config, volume_model, response = self.get_mocks() response.entity = None response.status_code = '200' client.get_volume_info = MagicMock(return_value=response) behavior = VolumesAPI_Behaviors(client, config) with self.assertRaises(StatusProgressionError): behavior.wait_for_volume_status( self.defaults.volume_name, self.defaults.expected_status, self.defaults.timeout, poll_rate=self.defaults.poll_rate)
def test_good_response_code_empty_entity(self): client, config, snapshot_model, response = self.get_mocks() response.entity = None response.status_code = '200' client.get_snapshot_info = MagicMock(return_value=response) behavior = VolumesAPI_Behaviors(client, config) with self.assertRaises(VolumesAPIBehaviorException): behavior.wait_for_snapshot_status( self.defaults.snapshot_name, self.defaults.expected_status, self.defaults.timeout, poll_rate=self.defaults.poll_rate)
def test_good_response_code_empty_entity(self): client, config, volume_model, response = self.get_mocks() response.entity = None response.status_code = '200' client.get_volume_info = MagicMock(return_value=response) behavior = VolumesAPI_Behaviors(client, config) with self.assertRaises(StatusProgressionError): behavior.wait_for_volume_status(self.defaults.volume_name, self.defaults.expected_status, self.defaults.timeout, poll_rate=self.defaults.poll_rate)
def test_bad_response_code(self): client, config, volume_model, response = self.get_mocks() response.ok = False response.entity = volume_model response.status_code = '401' client.get_volume_info = MagicMock(return_value=response) behavior = VolumesAPI_Behaviors(client, config) with self.assertRaises(VolumesAPIBehaviorException): behavior.wait_for_volume_status( self.defaults.volume_name, self.defaults.expected_status, self.defaults.timeout, poll_rate=self.defaults.poll_rate)
def test_bad_response_code(self): client, config, snapshot_model, response = self.get_mocks() response.ok = False response.entity = snapshot_model response.status_code = '401' client.get_snapshot_info = MagicMock(return_value=response) behavior = VolumesAPI_Behaviors(client, config) with self.assertRaises(StatusProgressionError): behavior.wait_for_snapshot_status( self.defaults.snapshot_name, self.defaults.expected_status, self.defaults.timeout, poll_rate=self.defaults.poll_rate)
def test_good_response_good_entity_bad_status(self): client, config, snapshot_model, response = self.get_mocks() recieved_status = 'error' poll_rate = 1 snapshot_model.status = recieved_status response.entity = snapshot_model client.get_snapshot_info = MagicMock(return_value=response) behavior = VolumesAPI_Behaviors(client, config) with self.assertRaises(VolumesAPIBehaviorException): behavior.wait_for_snapshot_status( self.defaults.snapshot_name, self.defaults.expected_status, self.defaults.timeout, poll_rate=poll_rate)
def test_bad_response_code(self): client, config, snapshot_model, response = self.get_mocks() response.ok = False response.entity = snapshot_model response.status_code = '401' client.get_snapshot_info = MagicMock(return_value=response) behavior = VolumesAPI_Behaviors(client, config) with self.assertRaises(StatusProgressionError): behavior.wait_for_snapshot_status( self.defaults.snapshot_name, self.defaults.expected_status, self.defaults.timeout, poll_rate=self.defaults.poll_rate)
def test_timeout_failure(self): client, config, volume_model, volume_create_response = self.get_mocks() volume_create_response.entity = None volume_create_response.status_code = 200 client.create_volume = MagicMock(return_value=volume_create_response) behavior = VolumesAPI_Behaviors(client, config) behavior.wait_for_volume_status = MagicMock( side_effect=VolumesAPIBehaviorException) with self.assertRaises(VolumesAPIBehaviorException): behavior.create_available_volume( self.defaults.display_name, self.defaults.size, self.defaults.volume_type)
def test_good_response_and_entity_bad_status(self): client, config, volume_model, response = self.get_mocks() recieved_status = 'error' timeout = 2 poll_rate = 1 volume_model.status = recieved_status response.entity = volume_model client.get_volume_info = MagicMock(return_value=response) behavior = VolumesAPI_Behaviors(client, config) with self.assertRaises(StatusProgressionError): behavior.wait_for_volume_status( self.defaults.volume_name, self.defaults.expected_status, timeout, poll_rate=poll_rate)
def test_good_response_and_entity_bad_status(self): client, config, volume_model, response = self.get_mocks() recieved_status = 'error' timeout = 2 poll_rate = 1 volume_model.status = recieved_status response.entity = volume_model client.get_volume_info = MagicMock(return_value=response) behavior = VolumesAPI_Behaviors(client, config) with self.assertRaises(StatusProgressionError): behavior.wait_for_volume_status(self.defaults.volume_name, self.defaults.expected_status, timeout, poll_rate=poll_rate)
def __init__( self, volume_attachments_client=None, volumes_client=None, volume_attachments_config=None, volumes_config=None): self.client = volume_attachments_client self.config = volume_attachments_config or VolumeAttachmentsAPIConfig() self.volumes_client = volumes_client self.volumes_behaviors = VolumesAPI_Behaviors(volumes_client) self.volumes_config = volumes_config or VolumesAPIConfig()
def test_create_availabe_volume_happy_path(self): volume_model = Mock(spec=VolumeResponse) volume_model.id_ = "mock" volume_create_response = Mock(spec=Response) volume_create_response.entity = volume_model volume_create_response.ok = True client = Mock(spec=VolumesClient) client.create_volume = MagicMock(return_value=volume_create_response) config = Mock(spec=VolumesAPIConfig) config.volume_create_timeout = 5 behavior = VolumesAPI_Behaviors(client, config) behavior.wait_for_volume_status = MagicMock(return_value=None) volume_entity = behavior.create_available_volume( self.defaults.display_name, self.defaults.size, self.defaults.volume_type) self.assertIsInstance(volume_entity, VolumeResponse)
def test_create_available_volume_failure_response_with_model(self): volume_model = Mock(spec=VolumeResponse) volume_model.id_ = "mock" volume_create_response = Mock(spec=Response) volume_create_response.entity = None volume_create_response.ok = True volume_create_response.status_code = 200 client = Mock(spec=VolumesClient) client.create_volume = MagicMock(return_value=volume_create_response) config = Mock(spec=VolumesAPIConfig) config.volume_create_timeout = 5 behavior = VolumesAPI_Behaviors(client, config) behavior.wait_for_volume_status = MagicMock(return_value=None) with self.assertRaises(VolumesAPIBehaviorException): behavior.create_available_volume( self.defaults.display_name, self.defaults.size, self.defaults.volume_type)
def test_wait_for_volume_status_good_response_code_empty_entity(self): client = Mock(spec=VolumesClient) config = Mock(spec=VolumesAPIConfig) config.volume_status_poll_frequency = 1 volume_model = Mock(spec=VolumeResponse) volume_model.status = self.defaults.expected_status response = Mock(spec=Response) response.ok = True response.entity = None response.status_code = '200' client.get_volume_info = MagicMock( return_value=response) behavior = VolumesAPI_Behaviors(client, config) with self.assertRaises(VolumesAPIBehaviorException): behavior.wait_for_volume_status( self.defaults.volume_name, self.defaults.expected_status, self.defaults.timeout, poll_rate=self.defaults.poll_rate)
class VolumeAttachmentsAPI_Behaviors(BaseBehavior): def __init__( self, volume_attachments_client=None, volumes_client=None, volume_attachments_config=None, volumes_config=None): self.client = volume_attachments_client self.config = volume_attachments_config or VolumeAttachmentsAPIConfig() self.volumes_client = volumes_client self.volumes_behaviors = VolumesAPI_Behaviors(volumes_client) self.volumes_config = volumes_config or VolumesAPIConfig() @behavior(VolumeAttachmentsAPIClient) 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 @behavior(VolumesClient) def verify_volume_status_progression_during_attachment( self, volume_id, state_list=None): # (status, transient, timeout, poll_rate) state_list = [ ('available', True, 5, 0), ('attaching', False, 30, 1), ('in-use', False, 60, 5)] self.volumes_behaviors.verify_volume_status_progression( volume_id, state_list) @behavior(VolumeAttachmentsAPIClient, VolumesClient) def attach_volume_to_server( self, server_id, volume_id, device=None, attachment_propagation_timeout=60): """Returns a VolumeAttachment object""" 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 auto_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)) attachment = resp.entity #Confirm volume attachment propagation propagated = self.wait_for_attachment_to_propagate( attachment.id_, server_id, timeout=attachment_propagation_timeout) if not propagated: raise VolumeAttachmentBehaviorError( "Volume attachment {0} belonging to server {1} failed to" "propagate to the relevant cell within {2} seconds".format( attachment.id_, server_id, attachment_propagation_timeout)) # Confirm volume status progression self.verify_volume_status_progression_during_attachment(volume_id) return attachment