Add the ability to get absolute limits from Cinder

This will be used in a later patch to check quota usage
for volume snapshots before attempting to create new
volume snapshots, so we can avoid an OverLimit error.

Change-Id: Ica7c087708e86494d285fc3905a5740fd1356e5f
Related-Bug: #1731986
This commit is contained in:
Matt Riedemann 2017-11-15 11:00:12 -05:00
parent bca425a33f
commit ad389244ba
2 changed files with 48 additions and 0 deletions

View File

@ -15,6 +15,7 @@
from cinderclient import api_versions as cinder_api_versions
from cinderclient import exceptions as cinder_exception
from cinderclient.v2 import limits as cinder_limits
from keystoneauth1 import loading as ks_loading
from keystoneclient import exceptions as keystone_exception
import mock
@ -752,6 +753,36 @@ class CinderApiTestCase(test.NoDBTestCase):
self.assertRaises(NotImplementedError,
self.api.update, self.ctx, '', '')
@mock.patch('nova.volume.cinder.cinderclient')
def test_get_absolute_limits_forbidden(self, cinderclient):
"""Tests to make sure we gracefully handle a Forbidden error raised
from python-cinderclient when getting limits.
"""
cinderclient.return_value.limits.get.side_effect = (
cinder_exception.Forbidden(403))
self.assertRaises(
exception.Forbidden, self.api.get_absolute_limits, self.ctx)
@mock.patch('nova.volume.cinder.cinderclient')
def test_get_absolute_limits(self, cinderclient):
"""Tests the happy path of getting the absolute limits."""
expected_limits = {
"totalSnapshotsUsed": 0,
"maxTotalBackups": 10,
"maxTotalVolumeGigabytes": 1000,
"maxTotalSnapshots": 10,
"maxTotalBackupGigabytes": 1000,
"totalBackupGigabytesUsed": 0,
"maxTotalVolumes": 10,
"totalVolumesUsed": 0,
"totalBackupsUsed": 0,
"totalGigabytesUsed": 0
}
limits_obj = cinder_limits.Limits(None, {'absolute': expected_limits})
cinderclient.return_value.limits.get.return_value = limits_obj
actual_limits = self.api.get_absolute_limits(self.ctx)
self.assertDictEqual(expected_limits, actual_limits)
@mock.patch('nova.volume.cinder.cinderclient')
def test_get_snapshot(self, mock_cinderclient):
snapshot_id = 'snapshot_id'

View File

@ -543,6 +543,23 @@ class API(object):
def update(self, context, volume_id, fields):
raise NotImplementedError()
@translate_cinder_exception
def get_absolute_limits(self, context):
"""Returns quota limit and usage information for the given tenant
See the <volumev3>/v3/{project_id}/limits API reference for details.
:param context: The nova RequestContext for the user request. Note
that the limit information returned from Cinder is specific to
the project_id within this context.
:returns: dict of absolute limits
"""
# cinderclient returns a generator of AbsoluteLimit objects, so iterate
# over the generator and return a dictionary which is easier for the
# nova client-side code to handle.
limits = cinderclient(context).limits.get().absolute
return {limit.name: limit.value for limit in limits}
@translate_snapshot_exception
def get_snapshot(self, context, snapshot_id):
item = cinderclient(context).volume_snapshots.get(snapshot_id)