def test_detach_volume_wait_error(self): server = dict(id='server001') attachments = [{'server_id': 'server001', 'device': 'device001'}] vol = { 'id': 'volume001', 'status': 'attached', 'name': '', 'attachments': attachments } volume = meta.obj_to_munch(fakes.FakeVolume(**vol)) vol['status'] = 'error' vol['attachments'] = [] errored_volume = meta.obj_to_munch(fakes.FakeVolume(**vol)) self.register_uris([ dict(method='DELETE', uri=self.get_mock_url('compute', 'public', append=[ 'servers', server['id'], 'os-volume_attachments', volume.id ])), dict(method='GET', uri=self.get_mock_url('volumev2', 'public', append=['volumes', 'detail']), json={'volumes': [errored_volume]}) ]) with testtools.ExpectedException( openstack.cloud.OpenStackCloudException, "Error in detaching volume %s" % errored_volume['id']): self.cloud.detach_volume(server, volume) self.assert_calls()
def test_list_volumes_with_pagination_next_link_fails_once(self): vol1 = meta.obj_to_munch(fakes.FakeVolume('01', 'available', 'vol1')) vol2 = meta.obj_to_munch(fakes.FakeVolume('02', 'available', 'vol2')) self.register_uris([ self.get_cinder_discovery_mock_dict(), dict(method='GET', uri=self.get_mock_url( 'volumev2', 'public', append=['volumes', 'detail']), json={ 'volumes': [vol1], 'volumes_links': [ {'href': self.get_mock_url( 'volumev2', 'public', append=['volumes', 'detail'], qs_elements=['marker=01']), 'rel': 'next'}]}), dict(method='GET', uri=self.get_mock_url( 'volumev2', 'public', append=['volumes', 'detail'], qs_elements=['marker=01']), status_code=404), dict(method='GET', uri=self.get_mock_url( 'volumev2', 'public', append=['volumes', 'detail']), json={ 'volumes': [vol1], 'volumes_links': [ {'href': self.get_mock_url( 'volumev2', 'public', append=['volumes', 'detail'], qs_elements=['marker=01']), 'rel': 'next'}]}), dict(method='GET', uri=self.get_mock_url( 'volumev2', 'public', append=['volumes', 'detail'], qs_elements=['marker=01']), json={ 'volumes': [vol2], 'volumes_links': [ {'href': self.get_mock_url( 'volumev2', 'public', append=['volumes', 'detail'], qs_elements=['marker=02']), 'rel': 'next'}]}), dict(method='GET', uri=self.get_mock_url( 'volumev2', 'public', append=['volumes', 'detail'], qs_elements=['marker=02']), json={'volumes': []})]) self.assertEqual( [self.cloud._normalize_volume(vol1), self.cloud._normalize_volume(vol2)], self.cloud.list_volumes()) self.assert_calls()
def test_list_volumes_creating_invalidates(self): fake_volume = fakes.FakeVolume('volume1', 'creating', 'Volume 1 Display Name') fake_volume_dict = meta.obj_to_munch(fake_volume) fake_volume2 = fakes.FakeVolume('volume2', 'available', 'Volume 2 Display Name') fake_volume2_dict = meta.obj_to_munch(fake_volume2) self.register_uris([ dict(method='GET', uri=self.get_mock_url('volumev2', 'public', append=['volumes', 'detail']), json={'volumes': [fake_volume_dict]}), dict(method='GET', uri=self.get_mock_url('volumev2', 'public', append=['volumes', 'detail']), json={'volumes': [fake_volume_dict, fake_volume2_dict]}) ]) self.assertEqual([self.cloud._normalize_volume(fake_volume_dict)], self.cloud.list_volumes()) self.assertEqual([ self.cloud._normalize_volume(fake_volume_dict), self.cloud._normalize_volume(fake_volume2_dict) ], self.cloud.list_volumes()) self.assert_calls()
def test_detach_volume_wait(self): server = dict(id='server001') attachments = [{'server_id': 'server001', 'device': 'device001'}] vol = { 'id': 'volume001', 'status': 'attached', 'name': '', 'attachments': attachments } volume = meta.obj_to_munch(fakes.FakeVolume(**vol)) vol['status'] = 'available' vol['attachments'] = [] avail_volume = meta.obj_to_munch(fakes.FakeVolume(**vol)) self.register_uris([ dict(method='DELETE', uri=self.get_mock_url('compute', 'public', append=[ 'servers', server['id'], 'os-volume_attachments', volume.id ])), dict(method='GET', uri=self.get_mock_url('volumev2', 'public', append=['volumes', 'detail']), json={'volumes': [avail_volume]}) ]) self.cloud.detach_volume(server, volume) self.assert_calls()
def test_attach_volume_wait(self): server = dict(id='server001') vol = {'id': 'volume001', 'status': 'available', 'name': '', 'attachments': []} volume = meta.obj_to_munch(fakes.FakeVolume(**vol)) vol['attachments'] = [{'server_id': server['id'], 'device': 'device001'}] vol['status'] = 'attached' attached_volume = meta.obj_to_munch(fakes.FakeVolume(**vol)) rattach = {'server_id': server['id'], 'device': 'device001', 'volumeId': volume['id'], 'id': 'attachmentId'} self.register_uris([ dict(method='POST', uri=self.get_mock_url( 'compute', 'public', append=['servers', server['id'], 'os-volume_attachments']), json={'volumeAttachment': rattach}, validate=dict(json={ 'volumeAttachment': { 'volumeId': vol['id']}})), self.get_cinder_discovery_mock_dict(), dict(method='GET', uri=self.get_mock_url( 'volumev2', 'public', append=['volumes', 'detail']), json={'volumes': [volume]}), dict(method='GET', uri=self.get_mock_url( 'volumev2', 'public', append=['volumes', 'detail']), json={'volumes': [attached_volume]})]) # defaults to wait=True ret = self.cloud.attach_volume(server, volume) self.assertEqual(rattach, ret) self.assert_calls()
def test_attach_volume_wait_error(self): server = dict(id='server001') vol = {'id': 'volume001', 'status': 'available', 'name': '', 'attachments': []} volume = meta.obj_to_munch(fakes.FakeVolume(**vol)) vol['status'] = 'error' errored_volume = meta.obj_to_munch(fakes.FakeVolume(**vol)) rattach = {'server_id': server['id'], 'device': 'device001', 'volumeId': volume['id'], 'id': 'attachmentId'} self.register_uris([ dict(method='POST', uri=self.get_mock_url( 'compute', 'public', append=['servers', server['id'], 'os-volume_attachments']), json={'volumeAttachment': rattach}, validate=dict(json={ 'volumeAttachment': { 'volumeId': vol['id']}})), self.get_cinder_discovery_mock_dict(), dict(method='GET', uri=self.get_mock_url( 'volumev2', 'public', append=['volumes', 'detail']), json={'volumes': [errored_volume]})]) with testtools.ExpectedException( openstack.cloud.OpenStackCloudException, "Error in attaching volume %s" % errored_volume['id'] ): self.cloud.attach_volume(server, volume) self.assert_calls()
def test_set_volume_bootable_false(self): vol = { 'id': 'volume001', 'status': 'attached', 'name': '', 'attachments': [] } volume = meta.obj_to_munch(fakes.FakeVolume(**vol)) self.register_uris([ dict(method='GET', uri=self.get_mock_url('volumev2', 'public', append=['volumes', 'detail']), json={'volumes': [volume]}), dict(method='POST', uri=self.get_mock_url('volumev2', 'public', append=['volumes', volume.id, 'action']), json={'os-set_bootable': { 'bootable': False }}), ]) self.cloud.set_volume_bootable(volume['id']) self.assert_calls()
def test_delete_volume_force(self): vol = { 'id': 'volume001', 'status': 'attached', 'name': '', 'attachments': [] } volume = meta.obj_to_munch(fakes.FakeVolume(**vol)) self.register_uris([ dict(method='GET', uri=self.get_mock_url('volumev2', 'public', append=['volumes', 'detail']), json={'volumes': [volume]}), dict(method='POST', uri=self.get_mock_url('volumev2', 'public', append=['volumes', volume.id, 'action']), validate=dict(json={'os-force_delete': None})), dict(method='GET', uri=self.get_mock_url('volumev2', 'public', append=['volumes', 'detail']), json={'volumes': []}) ]) self.assertTrue(self.cloud.delete_volume(volume['id'], force=True)) self.assert_calls()
def test_attach_volume(self): server = dict(id='server001') vol = { 'id': 'volume001', 'status': 'available', 'name': '', 'attachments': [] } volume = meta.obj_to_munch(fakes.FakeVolume(**vol)) rattach = { 'server_id': server['id'], 'device': 'device001', 'volumeId': volume['id'], 'id': 'attachmentId' } self.register_uris([ dict(method='POST', uri=self.get_mock_url( 'compute', 'public', append=['servers', server['id'], 'os-volume_attachments']), json={'volumeAttachment': rattach}, validate=dict( json={'volumeAttachment': { 'volumeId': vol['id'] }})) ]) ret = self.cloud.attach_volume(server, volume, wait=False) self.assertEqual(rattach, ret) self.assert_calls()
def test_list_volumes_with_pagination_next_link_fails_all_attempts(self): vol1 = meta.obj_to_munch(fakes.FakeVolume('01', 'available', 'vol1')) uris = [self.get_cinder_discovery_mock_dict()] attempts = 5 for i in range(attempts): uris.extend([ dict(method='GET', uri=self.get_mock_url( 'volumev2', 'public', append=['volumes', 'detail']), json={ 'volumes': [vol1], 'volumes_links': [ {'href': self.get_mock_url( 'volumev2', 'public', append=['volumes', 'detail'], qs_elements=['marker=01']), 'rel': 'next'}]}), dict(method='GET', uri=self.get_mock_url( 'volumev2', 'public', append=['volumes', 'detail'], qs_elements=['marker=01']), status_code=404)]) self.register_uris(uris) # Check that found volumes are returned even if pagination didn't # complete because call to get next link 404'ed for all the allowed # attempts self.assertEqual( [self.cloud._normalize_volume(vol1)], self.cloud.list_volumes()) self.assert_calls()
def test_attach_volume_exception(self): server = dict(id='server001') vol = { 'id': 'volume001', 'status': 'available', 'name': '', 'attachments': [] } volume = meta.obj_to_munch(fakes.FakeVolume(**vol)) self.register_uris([ dict(method='POST', uri=self.get_mock_url( 'compute', 'public', append=['servers', server['id'], 'os-volume_attachments']), status_code=404, validate=dict( json={'volumeAttachment': { 'volumeId': vol['id'] }})) ]) with testtools.ExpectedException( openstack.cloud.OpenStackCloudURINotFound, "Error attaching volume %s to server %s" % (volume['id'], server['id'])): self.cloud.attach_volume(server, volume, wait=False) self.assert_calls()
def test_delete_volume_deletes(self): vol = { 'id': 'volume001', 'status': 'attached', 'name': '', 'attachments': [] } volume = meta.obj_to_munch(fakes.FakeVolume(**vol)) self.register_uris([ dict(method='GET', uri=self.get_mock_url('volumev2', 'public', append=['volumes', 'detail']), json={'volumes': [volume]}), dict(method='DELETE', uri=self.get_mock_url('volumev2', 'public', append=['volumes', volume.id])), dict(method='GET', uri=self.get_mock_url('volumev2', 'public', append=['volumes', 'detail']), json={'volumes': []}) ]) self.assertTrue(self.cloud.delete_volume(volume['id'])) self.assert_calls()
def test_create_bootable_volume(self): vol1 = meta.obj_to_munch(fakes.FakeVolume('01', 'available', 'vol1')) self.register_uris([ dict(method='POST', uri=self.get_mock_url('volumev2', 'public', append=['volumes']), json={'volume': vol1}, validate=dict(json={'volume': { 'size': 50, 'name': 'vol1', }})), dict(method='GET', uri=self.get_mock_url('volumev2', 'public', append=['volumes', 'detail']), json={'volumes': [vol1]}), dict(method='POST', uri=self.get_mock_url('volumev2', 'public', append=['volumes', '01', 'action']), validate=dict(json={'os-set_bootable': { 'bootable': True }})), ]) self.cloud.create_volume(50, name='vol1', bootable=True) self.assert_calls()
def test_create_boot_attach_volume(self): build_server = fakes.make_fake_server('1234', '', 'BUILD') active_server = fakes.make_fake_server('1234', '', 'BUILD') vol = {'id': 'volume001', 'status': 'available', 'name': '', 'attachments': []} volume = meta.obj_to_munch(fakes.FakeVolume(**vol)) self.register_uris([ dict(method='GET', uri=self.get_mock_url( 'network', 'public', append=['v2.0', 'networks']), json={'networks': []}), dict(method='POST', uri=self.get_mock_url( 'compute', 'public', append=['os-volumes_boot']), json={'server': build_server}, validate=dict( json={'server': { u'flavorRef': 'flavor-id', u'imageRef': 'image-id', u'max_count': 1, u'min_count': 1, u'block_device_mapping_v2': [ { u'boot_index': 0, u'delete_on_termination': True, u'destination_type': u'local', u'source_type': u'image', u'uuid': u'image-id' }, { u'boot_index': u'-1', u'delete_on_termination': False, u'destination_type': u'volume', u'source_type': u'volume', u'uuid': u'volume001' } ], u'name': u'server-name'}})), dict(method='GET', uri=self.get_mock_url( 'compute', 'public', append=['servers', '1234']), json={'server': active_server}), ]) self.cloud.create_server( name='server-name', image=dict(id='image-id'), flavor=dict(id='flavor-id'), boot_from_volume=False, volumes=[volume], wait=False) self.assert_calls()
def test_get_volume_by_id(self): vol1 = meta.obj_to_munch(fakes.FakeVolume('01', 'available', 'vol1')) self.register_uris([ dict(method='GET', uri=self.get_mock_url('volumev2', 'public', append=['volumes', '01']), json={'volume': vol1}) ]) self.assertEqual(self.cloud._normalize_volume(vol1), self.cloud.get_volume_by_id('01')) self.assert_calls()
def test_has_volume(self): mock_cloud = mock.MagicMock() fake_volume = fakes.FakeVolume( id='volume1', status='available', name='Volume 1 Display Name', attachments=[{'device': '/dev/sda0'}]) fake_volume_dict = meta.obj_to_munch(fake_volume) mock_cloud.get_volumes.return_value = [fake_volume_dict] hostvars = meta.get_hostvars_from_server( mock_cloud, meta.obj_to_munch(standard_fake_server)) self.assertEqual('volume1', hostvars['volumes'][0]['id']) self.assertEqual('/dev/sda0', hostvars['volumes'][0]['device'])
def test_create_volume_invalidates(self): fake_volb4 = meta.obj_to_munch( fakes.FakeVolume('volume1', 'available', '')) _id = '12345' fake_vol_creating = meta.obj_to_munch( fakes.FakeVolume(_id, 'creating', '')) fake_vol_avail = meta.obj_to_munch( fakes.FakeVolume(_id, 'available', '')) def now_deleting(request, context): fake_vol_avail['status'] = 'deleting' self.register_uris([ dict(method='GET', uri=self.get_mock_url('volumev2', 'public', append=['volumes', 'detail']), json={'volumes': [fake_volb4]}), dict(method='POST', uri=self.get_mock_url('volumev2', 'public', append=['volumes']), json={'volume': fake_vol_creating}), dict(method='GET', uri=self.get_mock_url('volumev2', 'public', append=['volumes', 'detail']), json={'volumes': [fake_volb4, fake_vol_creating]}), dict(method='GET', uri=self.get_mock_url('volumev2', 'public', append=['volumes', 'detail']), json={'volumes': [fake_volb4, fake_vol_avail]}), dict(method='GET', uri=self.get_mock_url('volumev2', 'public', append=['volumes', 'detail']), json={'volumes': [fake_volb4, fake_vol_avail]}), dict(method='DELETE', uri=self.get_mock_url('volumev2', 'public', append=['volumes', _id]), json=now_deleting), dict(method='GET', uri=self.get_mock_url('volumev2', 'public', append=['volumes', 'detail']), json={'volumes': [fake_volb4]}) ]) self.assertEqual([self.cloud._normalize_volume(fake_volb4)], self.cloud.list_volumes()) volume = dict(display_name='junk_vol', size=1, display_description='test junk volume') self.cloud.create_volume(wait=True, timeout=None, **volume) # If cache was not invalidated, we would not see our own volume here # because the first volume was available and thus would already be # cached. self.assertEqual([ self.cloud._normalize_volume(fake_volb4), self.cloud._normalize_volume(fake_vol_avail) ], self.cloud.list_volumes()) self.cloud.delete_volume(_id) # And now delete and check same thing since list is cached as all # available self.assertEqual([self.cloud._normalize_volume(fake_volb4)], self.cloud.list_volumes()) self.assert_calls()