def test_transfer_volume_create_delete(self, mock_notify): tx_api = transfer_api.API() volume = utils.create_volume(self.ctxt, updated_at=self.updated_at) response = tx_api.create(self.ctxt, volume.id, 'Description') volume = objects.Volume.get_by_id(self.ctxt, volume.id) self.assertEqual('awaiting-transfer', volume['status'], 'Unexpected state') calls = [ mock.call(self.ctxt, mock.ANY, "transfer.create.start"), mock.call(self.ctxt, mock.ANY, "transfer.create.end") ] mock_notify.assert_has_calls(calls) self.assertEqual(2, mock_notify.call_count) tx_api.delete(self.ctxt, response['id']) volume = objects.Volume.get_by_id(self.ctxt, volume.id) self.assertEqual('available', volume['status'], 'Unexpected state') calls = [ mock.call(self.ctxt, mock.ANY, "transfer.delete.start"), mock.call(self.ctxt, mock.ANY, "transfer.delete.end") ] mock_notify.assert_has_calls(calls) self.assertEqual(4, mock_notify.call_count)
def test_get_all_transfers_non_admin(self, search_opts, get_all_by_project, get_all, auth_mock): ctxt = context.RequestContext(user_id=None, is_admin=False, project_id=mock.sentinel.project_id, read_deleted='no', overwrite=False) tx_api = transfer_api.API() res = tx_api.get_all(ctxt, mock.sentinel.marker, mock.sentinel.limit, mock.sentinel.sort_keys, mock.sentinel.sort_dirs, search_opts, mock.sentinel.offset) auth_mock.assert_called_once_with(transfer_api.policy.GET_ALL_POLICY) get_all.assert_not_called() get_all_by_project.assert_called_once_with( ctxt, mock.sentinel.project_id, filters={'name': 'transfer1'}, limit=mock.sentinel.limit, marker=mock.sentinel.marker, offset=mock.sentinel.offset, sort_dirs=mock.sentinel.sort_dirs, sort_keys=mock.sentinel.sort_keys) self.assertEqual(get_all_by_project.return_value, res)
def test_transfer_accept_with_detail_records(self, mock_notify): svc = self.start_service('volume', host='test_host') self.addCleanup(svc.stop) tx_api = transfer_api.API() volume = utils.create_volume(self.ctxt, updated_at=self.updated_at) transfer = tx_api.create(self.ctxt, volume.id, 'Description') self.assertEqual(volume.project_id, transfer['source_project_id']) self.assertIsNone(transfer['destination_project_id']) self.assertFalse(transfer['accepted']) # Get volume and snapshot quota before accept self.ctxt.user_id = fake.USER2_ID self.ctxt.project_id = fake.PROJECT2_ID tx_api.accept(self.ctxt, transfer['id'], transfer['auth_key']) xfer = db_api.model_query( self.ctxt, models.Transfer, read_deleted='yes').filter_by(id=transfer['id']).first() self.assertEqual(volume.project_id, xfer['source_project_id']) self.assertTrue(xfer['accepted']) self.assertEqual(fake.PROJECT2_ID, xfer['destination_project_id'])
def test_transfer_accept_over_quota_check_limit(self, mock_notify, mock_quota_limit): svc = self.start_service('volume', host='test_host') self.addCleanup(svc.stop) tx_api = transfer_api.API() volume = utils.create_volume(self.ctxt, volume_type_id=fake.VOLUME_TYPE_ID, updated_at=self.updated_at) transfer = tx_api.create(self.ctxt, volume.id, 'Description') fake_overs = ['per_volume_gigabytes'] fake_quotas = {'per_volume_gigabytes': 1} fake_usages = {} mock_quota_limit.side_effect = exception.OverQuota(overs=fake_overs, quotas=fake_quotas, usages=fake_usages) self.ctxt.user_id = fake.USER2_ID self.ctxt.project_id = fake.PROJECT2_ID self.assertRaises(exception.VolumeSizeExceedsLimit, tx_api.accept, self.ctxt, transfer['id'], transfer['auth_key']) # notification of transfer.accept is sent only after quota check # passes self.assertEqual(2, mock_notify.call_count)
def test_transfer_accept(self): svc = self.start_service('volume', host='test_host') tx_api = transfer_api.API() utils.create_volume(self.ctxt, id='1', updated_at=self.updated_at) transfer = tx_api.create(self.ctxt, '1', 'Description') volume = db.volume_get(self.ctxt, '1') self.assertEqual('awaiting-transfer', volume['status'], 'Unexpected state') self.assertRaises(exception.TransferNotFound, tx_api.accept, self.ctxt, '2', transfer['auth_key']) self.assertRaises(exception.InvalidAuthKey, tx_api.accept, self.ctxt, transfer['id'], 'wrong') db.volume_update(self.ctxt, '1', {'status': 'wrong'}) self.assertRaises(exception.InvalidVolume, tx_api.accept, self.ctxt, transfer['id'], transfer['auth_key']) db.volume_update(self.ctxt, '1', {'status': 'awaiting-transfer'}) self.ctxt.user_id = 'new_user_id' self.ctxt.project_id = 'new_project_id' response = tx_api.accept(self.ctxt, transfer['id'], transfer['auth_key']) volume = db.volume_get(self.ctxt, '1') self.assertEqual(volume['project_id'], 'new_project_id', 'Unexpected project id') self.assertEqual(volume['user_id'], 'new_user_id', 'Unexpected user id') self.assertEqual(volume['id'], response['volume_id'], 'Unexpected volume id in response.') self.assertEqual(transfer['id'], response['id'], 'Unexpected transfer id in response.') svc.stop()
def test_transfer_accept_invalid_volume(self): svc = self.start_service('volume', host='test_host') self.addCleanup(svc.stop) tx_api = transfer_api.API() volume = utils.create_volume(self.ctxt, updated_at=self.updated_at, volume_type_id=self.vt['id']) with mock.patch('cinder.volume.volume_utils.notify_about_volume_usage' ) as mock_notify: transfer = tx_api.create(self.ctxt, volume.id, 'Description') calls = [ mock.call(self.ctxt, mock.ANY, "transfer.create.start"), mock.call(self.ctxt, mock.ANY, "transfer.create.end") ] mock_notify.assert_has_calls(calls) self.assertEqual(2, mock_notify.call_count) volume = objects.Volume.get_by_id(self.ctxt, volume.id) self.assertEqual('awaiting-transfer', volume['status'], 'Unexpected state') volume.status = 'wrong' volume.save() with mock.patch('cinder.volume.volume_utils.notify_about_volume_usage' ) as mock_notify: self.assertRaises(exception.InvalidVolume, tx_api.accept, self.ctxt, transfer['id'], transfer['auth_key']) # Because the InvalidVolume exception is raised in tx_api, so # there is only transfer.accept.start called and missing # transfer.accept.end. calls = [mock.call(self.ctxt, mock.ANY, "transfer.accept.start")] mock_notify.assert_has_calls(calls) self.assertEqual(1, mock_notify.call_count) volume.status = 'awaiting-transfer' volume.save()
def test_transfer_accept(self, mock_quota_voltype, mock_quota_reserve, mock_quota_limit): svc = self.start_service('volume', host='test_host') self.addCleanup(svc.stop) tx_api = transfer_api.API() volume = utils.create_volume(self.ctxt, volume_type_id=fake.VOLUME_TYPE_ID, updated_at=self.updated_at) with mock.patch('cinder.volume.volume_utils.notify_about_volume_usage' ) as mock_notify: transfer = tx_api.create(self.ctxt, volume.id, 'Description') calls = [ mock.call(self.ctxt, mock.ANY, "transfer.create.start"), mock.call(self.ctxt, mock.ANY, "transfer.create.end") ] mock_notify.assert_has_calls(calls) self.assertEqual(2, mock_notify.call_count) self.ctxt.user_id = fake.USER2_ID self.ctxt.project_id = fake.PROJECT2_ID with mock.patch('cinder.volume.volume_utils.notify_about_volume_usage' ) as mock_notify: response = tx_api.accept(self.ctxt, transfer['id'], transfer['auth_key']) calls = [ mock.call(self.ctxt, mock.ANY, "transfer.accept.start"), mock.call(self.ctxt, mock.ANY, "transfer.accept.end") ] mock_notify.assert_has_calls(calls) self.assertEqual(2, mock_notify.call_count) volume = objects.Volume.get_by_id(self.ctxt, volume.id) self.assertEqual(fake.PROJECT2_ID, volume.project_id) self.assertEqual(fake.USER2_ID, volume.user_id) self.assertEqual(response['volume_id'], volume.id, 'Unexpected volume id in response.') self.assertEqual(response['id'], transfer['id'], 'Unexpected transfer id in response.') # Check QUOTAS reservation calls # QUOTAS.add_volume_type_opts reserve_opt = {'volumes': 1, 'gigabytes': 1} release_opt = {'volumes': -1, 'gigabytes': -1} calls = [ mock.call(self.ctxt, reserve_opt, fake.VOLUME_TYPE_ID), mock.call(self.ctxt, release_opt, fake.VOLUME_TYPE_ID) ] mock_quota_voltype.assert_has_calls(calls) # QUOTAS.reserve calls = [ mock.call(mock.ANY, **reserve_opt), mock.call(mock.ANY, project_id=fake.PROJECT_ID, **release_opt) ] mock_quota_reserve.assert_has_calls(calls) # QUOTAS.limit_check values = {'per_volume_gigabytes': 1} mock_quota_limit.assert_called_once_with(self.ctxt, project_id=fake.PROJECT2_ID, **values)
from cinder import objects objects.register_all() from cinder.db.sqlalchemy import api as cinder_db from cinder import rpc from cinder.transfer import api as transfer_api from oslo_config import cfg from oschown import base from oschown import exception # Not sure why but this has to happen at import time where our config # is set properly cfg.CONF([], project='cinder') CONF = cfg.CONF rpc.init(CONF) TRANSFER_API = transfer_api.API() LOG = logging.getLogger(__name__) class CinderResource(base.ChownableResource): def __init__(self, volume): self._volume = volume self._admin_ctx = cinder_context.get_admin_context() self._deps = [] self._collect_instances() def _collect_instances(self): if self._volume.volume_attachment: for attachment in self._volume.volume_attachment: LOG.info('Cinder volume %s requires attached instance %s' %