Fix quotas issue during volume transfer
When admin transfers a volume with volume type from one tenant to another, it correctly updates the quota for the default values, but does not update for the volume type values. This patch fixes the problem to update quotas for the volume type values. Change-Id: If444639cea8e74a415220df43fccfb155ca89216 Closes-Bug: #1501855
This commit is contained in:
parent
1369c3c67a
commit
173fd8604c
@ -19,11 +19,15 @@ import mock
|
||||
from cinder import context
|
||||
from cinder import exception
|
||||
from cinder import objects
|
||||
from cinder import quota
|
||||
from cinder import test
|
||||
from cinder.tests.unit import utils
|
||||
from cinder.transfer import api as transfer_api
|
||||
|
||||
|
||||
QUOTAS = quota.QUOTAS
|
||||
|
||||
|
||||
class VolumeTransferTestCase(test.TestCase):
|
||||
"""Test cases for volume transfer code."""
|
||||
def setUp(self):
|
||||
@ -64,8 +68,9 @@ class VolumeTransferTestCase(test.TestCase):
|
||||
self.assertEqual('in-use', volume['status'], 'Unexpected state')
|
||||
|
||||
@mock.patch('cinder.volume.utils.notify_about_volume_usage')
|
||||
def test_transfer_accept(self, mock_notify):
|
||||
def test_transfer_accept_invalid_authkey(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')
|
||||
@ -81,6 +86,17 @@ class VolumeTransferTestCase(test.TestCase):
|
||||
tx_api.accept,
|
||||
self.ctxt, transfer['id'], 'wrong')
|
||||
|
||||
@mock.patch('cinder.volume.utils.notify_about_volume_usage')
|
||||
def test_transfer_accept_invalid_volume(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')
|
||||
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)
|
||||
@ -100,6 +116,18 @@ class VolumeTransferTestCase(test.TestCase):
|
||||
mock_notify.assert_has_calls(calls)
|
||||
self.assertEqual(3, mock_notify.call_count)
|
||||
|
||||
@mock.patch.object(QUOTAS, "reserve")
|
||||
@mock.patch.object(QUOTAS, "add_volume_type_opts")
|
||||
@mock.patch('cinder.volume.utils.notify_about_volume_usage')
|
||||
def test_transfer_accept(self, mock_notify, mock_quota_voltype,
|
||||
mock_quota_reserve):
|
||||
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='12345',
|
||||
updated_at=self.updated_at)
|
||||
transfer = tx_api.create(self.ctxt, volume.id, 'Description')
|
||||
|
||||
self.ctxt.user_id = 'new_user_id'
|
||||
self.ctxt.project_id = 'new_project_id'
|
||||
response = tx_api.accept(self.ctxt,
|
||||
@ -117,9 +145,22 @@ class VolumeTransferTestCase(test.TestCase):
|
||||
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(5, mock_notify.call_count)
|
||||
# The notify_about_volume_usage is called twice at create(),
|
||||
# and twice at accept().
|
||||
self.assertEqual(4, mock_notify.call_count)
|
||||
|
||||
svc.stop()
|
||||
# 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, '12345'),
|
||||
mock.call(self.ctxt, release_opt, '12345')]
|
||||
mock_quota_voltype.assert_has_calls(calls)
|
||||
|
||||
# QUOTAS.reserve
|
||||
calls = [mock.call(mock.ANY, **reserve_opt),
|
||||
mock.call(mock.ANY, project_id='project_id', **release_opt)]
|
||||
mock_quota_reserve.assert_has_calls(calls)
|
||||
|
||||
def test_transfer_get(self):
|
||||
tx_api = transfer_api.API()
|
||||
|
@ -165,8 +165,11 @@ class API(base.Base):
|
||||
"transfer.accept.start")
|
||||
|
||||
try:
|
||||
reservations = QUOTAS.reserve(context, volumes=1,
|
||||
gigabytes=vol_ref['size'])
|
||||
reserve_opts = {'volumes': 1, 'gigabytes': vol_ref.size}
|
||||
QUOTAS.add_volume_type_opts(context,
|
||||
reserve_opts,
|
||||
vol_ref.volume_type_id)
|
||||
reservations = QUOTAS.reserve(context, **reserve_opts)
|
||||
except exception.OverQuota as e:
|
||||
overs = e.kwargs['overs']
|
||||
usages = e.kwargs['usages']
|
||||
@ -196,10 +199,13 @@ class API(base.Base):
|
||||
raise exception.VolumeLimitExceeded(allowed=quotas['volumes'])
|
||||
try:
|
||||
donor_id = vol_ref['project_id']
|
||||
reserve_opts = {'volumes': -1, 'gigabytes': -vol_ref.size}
|
||||
QUOTAS.add_volume_type_opts(context,
|
||||
reserve_opts,
|
||||
vol_ref.volume_type_id)
|
||||
donor_reservations = QUOTAS.reserve(context.elevated(),
|
||||
project_id=donor_id,
|
||||
volumes=-1,
|
||||
gigabytes=-vol_ref['size'])
|
||||
**reserve_opts)
|
||||
except Exception:
|
||||
donor_reservations = None
|
||||
LOG.exception(_LE("Failed to update quota donating volume"
|
||||
|
Loading…
Reference in New Issue
Block a user