Use project id from volume when retyping volumes

Use the project_id from the volume being retyped to reserve quota in
get_volume_type_reservation(). Previously the project_id from the
context was used, which could cause reservations to be made and never
cleared.

Change-Id: I25f7c00961e259102cdaea6ea9394d04ded96b92
Closes-Bug: #1505307
This commit is contained in:
Ollie Leahy 2015-10-15 15:20:28 +00:00
parent 71932e9c4f
commit ceb65b6f86
3 changed files with 46 additions and 2 deletions

View File

@ -31,7 +31,14 @@ def get_volume_type_reservation(ctxt, volume, type_id):
QUOTAS.add_volume_type_opts(ctxt,
reserve_opts,
type_id)
reservations = QUOTAS.reserve(ctxt, **reserve_opts)
# Note that usually the project_id on the volume will be the same as
# the project_id in the context. But, if they are different then the
# reservations must be recorded against the project_id that owns the
# volume.
project_id = volume['project_id']
reservations = QUOTAS.reserve(ctxt,
project_id=project_id,
**reserve_opts)
except exception.OverQuota as e:
overs = e.kwargs['overs']
usages = e.kwargs['usages']

View File

@ -53,7 +53,8 @@ class VolumeActionsTest(test.TestCase):
self.api_patchers[_meth].return_value = True
vol = {'id': 'fake', 'host': 'fake', 'status': 'available', 'size': 1,
'migration_status': None, 'volume_type_id': 'fake'}
'migration_status': None, 'volume_type_id': 'fake',
'project_id': 'project_id'}
self.get_patcher = mock.patch('cinder.volume.API.get')
self.mock_volume_get = self.get_patcher.start()
self.addCleanup(self.get_patcher.stop)

View File

@ -31,6 +31,7 @@ from cinder.db.sqlalchemy import models as sqa_models
from cinder import exception
from cinder import objects
from cinder import quota
from cinder import quota_utils
from cinder import test
import cinder.tests.unit.image.fake
from cinder import volume
@ -1821,3 +1822,38 @@ class QuotaReserveSqlAlchemyTestCase(test.TestCase):
usage_id=self.usages['gigabytes'],
project_id='test_project',
delta=-2 * 1024), ])
class QuotaVolumeTypeReservationTestCase(test.TestCase):
def setUp(self):
super(QuotaVolumeTypeReservationTestCase, self).setUp()
self.volume_type_name = CONF.default_volume_type
self.volume_type = db.volume_type_create(
context.get_admin_context(),
dict(name=self.volume_type_name))
@mock.patch.object(quota.QUOTAS, 'reserve')
@mock.patch.object(quota.QUOTAS, 'add_volume_type_opts')
def test_volume_type_reservation(self,
mock_add_volume_type_opts,
mock_reserve):
my_context = FakeContext('MyProject', None)
volume = {'name': 'my_vol_name',
'id': 'my_vol_id',
'size': '1',
'project_id': 'vol_project_id',
}
reserve_opts = {'volumes': 1, 'gigabytes': volume['size']}
quota_utils.get_volume_type_reservation(my_context,
volume,
self.volume_type['id'])
mock_add_volume_type_opts.assert_called_once_with(
my_context,
reserve_opts,
self.volume_type['id'])
mock_reserve.assert_called_once_with(my_context,
project_id='vol_project_id',
gigabytes='1',
volumes=1)