Fix volume snapshot creation
The referenced template was wrong, and the quota usages information had not been switched to using limits. Thanks to Nuno Santos and Rohan Kanade for the initial versions of this patch. Change-Id: I97f578b84cd1cd4babab2580c60f0132026e3c93 Closes-Bug: #1194506
This commit is contained in:
parent
d1afd53a92
commit
2ed62bb2e5
|
@ -32,12 +32,15 @@ INDEX_URL = reverse('horizon:project:images_and_snapshots:index')
|
||||||
|
|
||||||
|
|
||||||
class VolumeSnapshotsViewTests(test.TestCase):
|
class VolumeSnapshotsViewTests(test.TestCase):
|
||||||
@test.create_stubs({quotas: ('tenant_quota_usages',)})
|
@test.create_stubs({quotas: ('tenant_limit_usages',)})
|
||||||
def test_create_snapshot_get(self):
|
def test_create_snapshot_get(self):
|
||||||
volume = self.volumes.first()
|
volume = self.volumes.first()
|
||||||
usage = {'gigabytes': {'available': 250},
|
usage_limit = {'maxTotalVolumeGigabytes': 250,
|
||||||
'snapshots': {'available': 6}}
|
'gigabytesUsed': 20,
|
||||||
quotas.tenant_quota_usages(IsA(http.HttpRequest)).AndReturn(usage)
|
'volumesUsed': len(self.volumes.list()),
|
||||||
|
'maxTotalVolumes': 6}
|
||||||
|
quotas.tenant_limit_usages(IsA(http.HttpRequest)).\
|
||||||
|
AndReturn(usage_limit)
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
url = reverse('horizon:project:volumes:create_snapshot',
|
url = reverse('horizon:project:volumes:create_snapshot',
|
||||||
|
|
|
@ -25,6 +25,7 @@ from openstack_dashboard.api import cinder
|
||||||
from openstack_dashboard.api import glance
|
from openstack_dashboard.api import glance
|
||||||
from openstack_dashboard.dashboards.project.images_and_snapshots import utils
|
from openstack_dashboard.dashboards.project.images_and_snapshots import utils
|
||||||
from openstack_dashboard.dashboards.project.instances import tables
|
from openstack_dashboard.dashboards.project.instances import tables
|
||||||
|
from openstack_dashboard.usage import quotas
|
||||||
|
|
||||||
|
|
||||||
class CreateForm(forms.SelfHandlingForm):
|
class CreateForm(forms.SelfHandlingForm):
|
||||||
|
@ -138,13 +139,8 @@ class CreateForm(forms.SelfHandlingForm):
|
||||||
|
|
||||||
def handle(self, request, data):
|
def handle(self, request, data):
|
||||||
try:
|
try:
|
||||||
usages = cinder.tenant_absolute_limits(self.request)
|
usages = quotas.tenant_limit_usages(self.request)
|
||||||
volumes = cinder.volume_list(self.request)
|
availableGB = usages['maxTotalVolumeGigabytes'] - \
|
||||||
total_size = sum([getattr(volume, 'size', 0) for volume
|
|
||||||
in volumes])
|
|
||||||
usages['gigabytesUsed'] = total_size
|
|
||||||
usages['volumesUsed'] = len(volumes)
|
|
||||||
availableGB = usages['maxTotalVolumeGigabytes'] -\
|
|
||||||
usages['gigabytesUsed']
|
usages['gigabytesUsed']
|
||||||
availableVol = usages['maxTotalVolumes'] - usages['volumesUsed']
|
availableVol = usages['maxTotalVolumes'] - usages['volumesUsed']
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
<div class="right quota-dynamic">
|
<div class="right quota-dynamic">
|
||||||
{% include "project/volumes/_quota.html" with usages=usages snapshot_quota=True %}
|
{% include "project/volumes/_limits.html" with usages=usages snapshot_quota=True %}
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|
|
@ -35,16 +35,16 @@ from openstack_dashboard.usage import quotas
|
||||||
class VolumeViewTests(test.TestCase):
|
class VolumeViewTests(test.TestCase):
|
||||||
@test.create_stubs({cinder: ('volume_create',
|
@test.create_stubs({cinder: ('volume_create',
|
||||||
'volume_snapshot_list',
|
'volume_snapshot_list',
|
||||||
'volume_type_list',
|
'volume_type_list',),
|
||||||
'tenant_absolute_limits',
|
api.glance: ('image_list_detailed',),
|
||||||
'volume_list',),
|
quotas: ('tenant_limit_usages',)})
|
||||||
api.glance: ('image_list_detailed',)})
|
|
||||||
def test_create_volume(self):
|
def test_create_volume(self):
|
||||||
volume = self.volumes.first()
|
volume = self.volumes.first()
|
||||||
volume_type = self.volume_types.first()
|
volume_type = self.volume_types.first()
|
||||||
usage_limit = {'maxTotalVolumeGigabytes': 250,
|
usage_limit = {'maxTotalVolumeGigabytes': 250,
|
||||||
'gigabytesUsed': 20,
|
'gigabytesUsed': 20,
|
||||||
'maxTotalVolumes': 6}
|
'volumesUsed': len(self.volumes.list()),
|
||||||
|
'maxTotalVolumes': 6}
|
||||||
formData = {'name': u'A Volume I Am Making',
|
formData = {'name': u'A Volume I Am Making',
|
||||||
'description': u'This is a volume I am making for a test.',
|
'description': u'This is a volume I am making for a test.',
|
||||||
'method': u'CreateForm',
|
'method': u'CreateForm',
|
||||||
|
@ -54,10 +54,8 @@ class VolumeViewTests(test.TestCase):
|
||||||
|
|
||||||
cinder.volume_type_list(IsA(http.HttpRequest)).\
|
cinder.volume_type_list(IsA(http.HttpRequest)).\
|
||||||
AndReturn(self.volume_types.list())
|
AndReturn(self.volume_types.list())
|
||||||
cinder.tenant_absolute_limits(IsA(http.HttpRequest)).\
|
quotas.tenant_limit_usages(IsA(http.HttpRequest)).\
|
||||||
AndReturn(usage_limit)
|
AndReturn(usage_limit)
|
||||||
cinder.volume_list(IsA(http.HttpRequest)).\
|
|
||||||
AndReturn(self.volumes.list())
|
|
||||||
cinder.volume_snapshot_list(IsA(http.HttpRequest)).\
|
cinder.volume_snapshot_list(IsA(http.HttpRequest)).\
|
||||||
AndReturn(self.volume_snapshots.list())
|
AndReturn(self.volume_snapshots.list())
|
||||||
api.glance.image_list_detailed(IsA(http.HttpRequest),
|
api.glance.image_list_detailed(IsA(http.HttpRequest),
|
||||||
|
@ -87,14 +85,15 @@ class VolumeViewTests(test.TestCase):
|
||||||
|
|
||||||
@test.create_stubs({cinder: ('volume_create',
|
@test.create_stubs({cinder: ('volume_create',
|
||||||
'volume_snapshot_list',
|
'volume_snapshot_list',
|
||||||
'volume_type_list',
|
'volume_type_list',),
|
||||||
'tenant_absolute_limits',
|
api.glance: ('image_list_detailed',),
|
||||||
'volume_list',),
|
quotas: ('tenant_limit_usages',)})
|
||||||
api.glance: ('image_list_detailed',)})
|
|
||||||
def test_create_volume_dropdown(self):
|
def test_create_volume_dropdown(self):
|
||||||
volume = self.volumes.first()
|
volume = self.volumes.first()
|
||||||
usage_limit = {'maxTotalVolumeGigabytes': 250,
|
usage_limit = {'maxTotalVolumeGigabytes': 250,
|
||||||
'maxTotalVolumes': 6}
|
'gigabytesUsed': 20,
|
||||||
|
'volumesUsed': len(self.volumes.list()),
|
||||||
|
'maxTotalVolumes': 6}
|
||||||
formData = {'name': u'A Volume I Am Making',
|
formData = {'name': u'A Volume I Am Making',
|
||||||
'description': u'This is a volume I am making for a test.',
|
'description': u'This is a volume I am making for a test.',
|
||||||
'method': u'CreateForm',
|
'method': u'CreateForm',
|
||||||
|
@ -116,10 +115,8 @@ class VolumeViewTests(test.TestCase):
|
||||||
filters={'property-owner_id': self.tenant.id,
|
filters={'property-owner_id': self.tenant.id,
|
||||||
'status': 'active'}) \
|
'status': 'active'}) \
|
||||||
.AndReturn([[], False])
|
.AndReturn([[], False])
|
||||||
cinder.tenant_absolute_limits(IsA(http.HttpRequest)).\
|
quotas.tenant_limit_usages(IsA(http.HttpRequest)).\
|
||||||
AndReturn(usage_limit)
|
AndReturn(usage_limit)
|
||||||
cinder.volume_list(IsA(http.HttpRequest)).\
|
|
||||||
AndReturn(self.volumes.list())
|
|
||||||
cinder.volume_create(IsA(http.HttpRequest),
|
cinder.volume_create(IsA(http.HttpRequest),
|
||||||
formData['size'],
|
formData['size'],
|
||||||
formData['name'],
|
formData['name'],
|
||||||
|
@ -141,13 +138,14 @@ class VolumeViewTests(test.TestCase):
|
||||||
@test.create_stubs({cinder: ('volume_create',
|
@test.create_stubs({cinder: ('volume_create',
|
||||||
'volume_snapshot_get',
|
'volume_snapshot_get',
|
||||||
'volume_get',
|
'volume_get',
|
||||||
'volume_type_list',
|
'volume_type_list',),
|
||||||
'tenant_absolute_limits',
|
quotas: ('tenant_limit_usages',)})
|
||||||
'volume_list',)})
|
|
||||||
def test_create_volume_from_snapshot(self):
|
def test_create_volume_from_snapshot(self):
|
||||||
volume = self.volumes.first()
|
volume = self.volumes.first()
|
||||||
usage_limit = {'maxTotalVolumeGigabytes': 250,
|
usage_limit = {'maxTotalVolumeGigabytes': 250,
|
||||||
'maxTotalVolumes': 6}
|
'gigabytesUsed': 20,
|
||||||
|
'volumesUsed': len(self.volumes.list()),
|
||||||
|
'maxTotalVolumes': 6}
|
||||||
snapshot = self.volume_snapshots.first()
|
snapshot = self.volume_snapshots.first()
|
||||||
formData = {'name': u'A Volume I Am Making',
|
formData = {'name': u'A Volume I Am Making',
|
||||||
'description': u'This is a volume I am making for a test.',
|
'description': u'This is a volume I am making for a test.',
|
||||||
|
@ -158,10 +156,8 @@ class VolumeViewTests(test.TestCase):
|
||||||
|
|
||||||
cinder.volume_type_list(IsA(http.HttpRequest)).\
|
cinder.volume_type_list(IsA(http.HttpRequest)).\
|
||||||
AndReturn(self.volume_types.list())
|
AndReturn(self.volume_types.list())
|
||||||
cinder.tenant_absolute_limits(IsA(http.HttpRequest)).\
|
quotas.tenant_limit_usages(IsA(http.HttpRequest)).\
|
||||||
AndReturn(usage_limit)
|
AndReturn(usage_limit)
|
||||||
cinder.volume_list(IsA(http.HttpRequest)).\
|
|
||||||
AndReturn(self.volumes.list())
|
|
||||||
cinder.volume_snapshot_get(IsA(http.HttpRequest),
|
cinder.volume_snapshot_get(IsA(http.HttpRequest),
|
||||||
str(snapshot.id)).AndReturn(snapshot)
|
str(snapshot.id)).AndReturn(snapshot)
|
||||||
cinder.volume_get(IsA(http.HttpRequest), snapshot.volume_id).\
|
cinder.volume_get(IsA(http.HttpRequest), snapshot.volume_id).\
|
||||||
|
@ -190,14 +186,15 @@ class VolumeViewTests(test.TestCase):
|
||||||
'volume_snapshot_list',
|
'volume_snapshot_list',
|
||||||
'volume_snapshot_get',
|
'volume_snapshot_get',
|
||||||
'volume_get',
|
'volume_get',
|
||||||
'volume_type_list',
|
'volume_type_list',),
|
||||||
'tenant_absolute_limits',
|
api.glance: ('image_list_detailed',),
|
||||||
'volume_list',),
|
quotas: ('tenant_limit_usages',)})
|
||||||
api.glance: ('image_list_detailed',)})
|
|
||||||
def test_create_volume_from_snapshot_dropdown(self):
|
def test_create_volume_from_snapshot_dropdown(self):
|
||||||
volume = self.volumes.first()
|
volume = self.volumes.first()
|
||||||
usage_limit = {'maxTotalVolumeGigabytes': 250,
|
usage_limit = {'maxTotalVolumeGigabytes': 250,
|
||||||
'maxTotalVolumes': 6}
|
'gigabytesUsed': 20,
|
||||||
|
'volumesUsed': len(self.volumes.list()),
|
||||||
|
'maxTotalVolumes': 6}
|
||||||
snapshot = self.volume_snapshots.first()
|
snapshot = self.volume_snapshots.first()
|
||||||
formData = {'name': u'A Volume I Am Making',
|
formData = {'name': u'A Volume I Am Making',
|
||||||
'description': u'This is a volume I am making for a test.',
|
'description': u'This is a volume I am making for a test.',
|
||||||
|
@ -219,10 +216,8 @@ class VolumeViewTests(test.TestCase):
|
||||||
filters={'property-owner_id': self.tenant.id,
|
filters={'property-owner_id': self.tenant.id,
|
||||||
'status': 'active'}) \
|
'status': 'active'}) \
|
||||||
.AndReturn([[], False])
|
.AndReturn([[], False])
|
||||||
cinder.tenant_absolute_limits(IsA(http.HttpRequest)).\
|
quotas.tenant_limit_usages(IsA(http.HttpRequest)).\
|
||||||
AndReturn(usage_limit)
|
AndReturn(usage_limit)
|
||||||
cinder.volume_list(IsA(http.HttpRequest)).\
|
|
||||||
AndReturn(self.volumes.list())
|
|
||||||
cinder.volume_snapshot_get(IsA(http.HttpRequest),
|
cinder.volume_snapshot_get(IsA(http.HttpRequest),
|
||||||
str(snapshot.id)).AndReturn(snapshot)
|
str(snapshot.id)).AndReturn(snapshot)
|
||||||
cinder.volume_create(IsA(http.HttpRequest),
|
cinder.volume_create(IsA(http.HttpRequest),
|
||||||
|
@ -246,13 +241,14 @@ class VolumeViewTests(test.TestCase):
|
||||||
|
|
||||||
@test.create_stubs({cinder: ('volume_snapshot_get',
|
@test.create_stubs({cinder: ('volume_snapshot_get',
|
||||||
'volume_type_list',
|
'volume_type_list',
|
||||||
'volume_get',
|
'volume_get',),
|
||||||
'tenant_absolute_limits',
|
api.glance: ('image_list_detailed',),
|
||||||
'volume_list',),
|
quotas: ('tenant_limit_usages',)})
|
||||||
api.glance: ('image_list_detailed',)})
|
|
||||||
def test_create_volume_from_snapshot_invalid_size(self):
|
def test_create_volume_from_snapshot_invalid_size(self):
|
||||||
usage_limit = {'maxTotalVolumeGigabytes': 100,
|
usage_limit = {'maxTotalVolumeGigabytes': 100,
|
||||||
'maxTotalVolumes': 6}
|
'gigabytesUsed': 20,
|
||||||
|
'volumesUsed': len(self.volumes.list()),
|
||||||
|
'maxTotalVolumes': 6}
|
||||||
snapshot = self.volume_snapshots.first()
|
snapshot = self.volume_snapshots.first()
|
||||||
formData = {'name': u'A Volume I Am Making',
|
formData = {'name': u'A Volume I Am Making',
|
||||||
'description': u'This is a volume I am making for a test.',
|
'description': u'This is a volume I am making for a test.',
|
||||||
|
@ -261,18 +257,14 @@ class VolumeViewTests(test.TestCase):
|
||||||
|
|
||||||
cinder.volume_type_list(IsA(http.HttpRequest)).\
|
cinder.volume_type_list(IsA(http.HttpRequest)).\
|
||||||
AndReturn(self.volume_types.list())
|
AndReturn(self.volume_types.list())
|
||||||
cinder.tenant_absolute_limits(IsA(http.HttpRequest)).\
|
quotas.tenant_limit_usages(IsA(http.HttpRequest)).\
|
||||||
AndReturn(usage_limit)
|
AndReturn(usage_limit)
|
||||||
cinder.volume_list(IsA(http.HttpRequest)).\
|
|
||||||
AndReturn(self.volumes.list())
|
|
||||||
cinder.volume_snapshot_get(IsA(http.HttpRequest),
|
cinder.volume_snapshot_get(IsA(http.HttpRequest),
|
||||||
str(snapshot.id)).AndReturn(snapshot)
|
str(snapshot.id)).AndReturn(snapshot)
|
||||||
cinder.volume_get(IsA(http.HttpRequest), snapshot.volume_id).\
|
cinder.volume_get(IsA(http.HttpRequest), snapshot.volume_id).\
|
||||||
AndReturn(self.volumes.first())
|
AndReturn(self.volumes.first())
|
||||||
cinder.tenant_absolute_limits(IsA(http.HttpRequest)).\
|
quotas.tenant_limit_usages(IsA(http.HttpRequest)).\
|
||||||
AndReturn(usage_limit)
|
AndReturn(usage_limit)
|
||||||
cinder.volume_list(IsA(http.HttpRequest)).\
|
|
||||||
AndReturn(self.volumes.list())
|
|
||||||
|
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
|
@ -286,14 +278,15 @@ class VolumeViewTests(test.TestCase):
|
||||||
"snapshot size (40GB)")
|
"snapshot size (40GB)")
|
||||||
|
|
||||||
@test.create_stubs({cinder: ('volume_create',
|
@test.create_stubs({cinder: ('volume_create',
|
||||||
'volume_type_list',
|
'volume_type_list',),
|
||||||
'tenant_absolute_limits',
|
api.glance: ('image_get',),
|
||||||
'volume_list',),
|
quotas: ('tenant_limit_usages',)})
|
||||||
api.glance: ('image_get',)})
|
|
||||||
def test_create_volume_from_image(self):
|
def test_create_volume_from_image(self):
|
||||||
volume = self.volumes.first()
|
volume = self.volumes.first()
|
||||||
usage_limit = {'maxTotalVolumeGigabytes': 200,
|
usage_limit = {'maxTotalVolumeGigabytes': 200,
|
||||||
'maxTotalVolumes': 6}
|
'gigabytesUsed': 20,
|
||||||
|
'volumesUsed': len(self.volumes.list()),
|
||||||
|
'maxTotalVolumes': 6}
|
||||||
image = self.images.first()
|
image = self.images.first()
|
||||||
formData = {'name': u'A Volume I Am Making',
|
formData = {'name': u'A Volume I Am Making',
|
||||||
'description': u'This is a volume I am making for a test.',
|
'description': u'This is a volume I am making for a test.',
|
||||||
|
@ -304,10 +297,8 @@ class VolumeViewTests(test.TestCase):
|
||||||
|
|
||||||
cinder.volume_type_list(IsA(http.HttpRequest)).\
|
cinder.volume_type_list(IsA(http.HttpRequest)).\
|
||||||
AndReturn(self.volume_types.list())
|
AndReturn(self.volume_types.list())
|
||||||
cinder.tenant_absolute_limits(IsA(http.HttpRequest)).\
|
quotas.tenant_limit_usages(IsA(http.HttpRequest)).\
|
||||||
AndReturn(usage_limit)
|
AndReturn(usage_limit)
|
||||||
cinder.volume_list(IsA(http.HttpRequest)).\
|
|
||||||
AndReturn(self.volumes.list())
|
|
||||||
api.glance.image_get(IsA(http.HttpRequest),
|
api.glance.image_get(IsA(http.HttpRequest),
|
||||||
str(image.id)).AndReturn(image)
|
str(image.id)).AndReturn(image)
|
||||||
cinder.volume_create(IsA(http.HttpRequest),
|
cinder.volume_create(IsA(http.HttpRequest),
|
||||||
|
@ -333,15 +324,16 @@ class VolumeViewTests(test.TestCase):
|
||||||
|
|
||||||
@test.create_stubs({cinder: ('volume_create',
|
@test.create_stubs({cinder: ('volume_create',
|
||||||
'volume_type_list',
|
'volume_type_list',
|
||||||
'volume_snapshot_list',
|
'volume_snapshot_list',),
|
||||||
'tenant_absolute_limits',
|
|
||||||
'volume_list',),
|
|
||||||
api.glance: ('image_get',
|
api.glance: ('image_get',
|
||||||
'image_list_detailed')})
|
'image_list_detailed'),
|
||||||
|
quotas: ('tenant_limit_usages',)})
|
||||||
def test_create_volume_from_image_dropdown(self):
|
def test_create_volume_from_image_dropdown(self):
|
||||||
volume = self.volumes.first()
|
volume = self.volumes.first()
|
||||||
usage_limit = {'maxTotalVolumeGigabytes': 200,
|
usage_limit = {'maxTotalVolumeGigabytes': 200,
|
||||||
'maxTotalVolumes': 6}
|
'gigabytesUsed': 20,
|
||||||
|
'volumesUsed': len(self.volumes.list()),
|
||||||
|
'maxTotalVolumes': 6}
|
||||||
image = self.images.first()
|
image = self.images.first()
|
||||||
formData = {'name': u'A Volume I Am Making',
|
formData = {'name': u'A Volume I Am Making',
|
||||||
'description': u'This is a volume I am making for a test.',
|
'description': u'This is a volume I am making for a test.',
|
||||||
|
@ -364,10 +356,8 @@ class VolumeViewTests(test.TestCase):
|
||||||
filters={'property-owner_id': self.tenant.id,
|
filters={'property-owner_id': self.tenant.id,
|
||||||
'status': 'active'}) \
|
'status': 'active'}) \
|
||||||
.AndReturn([[], False])
|
.AndReturn([[], False])
|
||||||
cinder.tenant_absolute_limits(IsA(http.HttpRequest)) \
|
quotas.tenant_limit_usages(IsA(http.HttpRequest)) \
|
||||||
.AndReturn(usage_limit)
|
.AndReturn(usage_limit)
|
||||||
cinder.volume_list(IsA(http.HttpRequest)) \
|
|
||||||
.AndReturn(self.volumes.list())
|
|
||||||
api.glance.image_get(IsA(http.HttpRequest),
|
api.glance.image_get(IsA(http.HttpRequest),
|
||||||
str(image.id)).AndReturn(image)
|
str(image.id)).AndReturn(image)
|
||||||
cinder.volume_create(IsA(http.HttpRequest),
|
cinder.volume_create(IsA(http.HttpRequest),
|
||||||
|
@ -389,13 +379,15 @@ class VolumeViewTests(test.TestCase):
|
||||||
redirect_url = reverse('horizon:project:volumes:index')
|
redirect_url = reverse('horizon:project:volumes:index')
|
||||||
self.assertRedirectsNoFollow(res, redirect_url)
|
self.assertRedirectsNoFollow(res, redirect_url)
|
||||||
|
|
||||||
@test.create_stubs({cinder: ('volume_type_list', 'tenant_absolute_limits',
|
@test.create_stubs({cinder: ('volume_type_list',),
|
||||||
'volume_list',),
|
|
||||||
api.glance: ('image_get',
|
api.glance: ('image_get',
|
||||||
'image_list_detailed')})
|
'image_list_detailed'),
|
||||||
|
quotas: ('tenant_limit_usages',)})
|
||||||
def test_create_volume_from_image_invalid_size(self):
|
def test_create_volume_from_image_invalid_size(self):
|
||||||
usage_limit = {'maxTotalVolumeGigabytes': 100,
|
usage_limit = {'maxTotalVolumeGigabytes': 100,
|
||||||
'maxTotalVolumes': 6}
|
'gigabytesUsed': 20,
|
||||||
|
'volumesUsed': len(self.volumes.list()),
|
||||||
|
'maxTotalVolumes': 6}
|
||||||
image = self.images.first()
|
image = self.images.first()
|
||||||
formData = {'name': u'A Volume I Am Making',
|
formData = {'name': u'A Volume I Am Making',
|
||||||
'description': u'This is a volume I am making for a test.',
|
'description': u'This is a volume I am making for a test.',
|
||||||
|
@ -404,16 +396,12 @@ class VolumeViewTests(test.TestCase):
|
||||||
|
|
||||||
cinder.volume_type_list(IsA(http.HttpRequest)).\
|
cinder.volume_type_list(IsA(http.HttpRequest)).\
|
||||||
AndReturn(self.volume_types.list())
|
AndReturn(self.volume_types.list())
|
||||||
cinder.tenant_absolute_limits(IsA(http.HttpRequest)).\
|
quotas.tenant_limit_usages(IsA(http.HttpRequest)).\
|
||||||
AndReturn(usage_limit)
|
AndReturn(usage_limit)
|
||||||
cinder.volume_list(IsA(http.HttpRequest)).\
|
|
||||||
AndReturn(self.volumes.list())
|
|
||||||
api.glance.image_get(IsA(http.HttpRequest),
|
api.glance.image_get(IsA(http.HttpRequest),
|
||||||
str(image.id)).AndReturn(image)
|
str(image.id)).AndReturn(image)
|
||||||
cinder.tenant_absolute_limits(IsA(http.HttpRequest)).\
|
quotas.tenant_limit_usages(IsA(http.HttpRequest)).\
|
||||||
AndReturn(usage_limit)
|
AndReturn(usage_limit)
|
||||||
cinder.volume_list(IsA(http.HttpRequest)).\
|
|
||||||
AndReturn(self.volumes.list())
|
|
||||||
|
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
|
@ -426,12 +414,14 @@ class VolumeViewTests(test.TestCase):
|
||||||
"The volume size cannot be less than the "
|
"The volume size cannot be less than the "
|
||||||
"image size (20.0 GB)")
|
"image size (20.0 GB)")
|
||||||
|
|
||||||
@test.create_stubs({cinder: ('volume_snapshot_list', 'volume_type_list',
|
@test.create_stubs({cinder: ('volume_snapshot_list', 'volume_type_list',),
|
||||||
'tenant_absolute_limits', 'volume_list',),
|
api.glance: ('image_list_detailed',),
|
||||||
api.glance: ('image_list_detailed',)})
|
quotas: ('tenant_limit_usages',)})
|
||||||
def test_create_volume_gb_used_over_alloted_quota(self):
|
def test_create_volume_gb_used_over_alloted_quota(self):
|
||||||
usage_limit = {'maxTotalVolumeGigabytes': 100,
|
usage_limit = {'maxTotalVolumeGigabytes': 100,
|
||||||
'maxTotalVolumes': 6}
|
'gigabytesUsed': 80,
|
||||||
|
'volumesUsed': len(self.volumes.list()),
|
||||||
|
'maxTotalVolumes': 6}
|
||||||
formData = {'name': u'This Volume Is Huge!',
|
formData = {'name': u'This Volume Is Huge!',
|
||||||
'description': u'This is a volume that is just too big!',
|
'description': u'This is a volume that is just too big!',
|
||||||
'method': u'CreateForm',
|
'method': u'CreateForm',
|
||||||
|
@ -439,10 +429,8 @@ class VolumeViewTests(test.TestCase):
|
||||||
|
|
||||||
cinder.volume_type_list(IsA(http.HttpRequest)).\
|
cinder.volume_type_list(IsA(http.HttpRequest)).\
|
||||||
AndReturn(self.volume_types.list())
|
AndReturn(self.volume_types.list())
|
||||||
cinder.tenant_absolute_limits(IsA(http.HttpRequest)).\
|
quotas.tenant_limit_usages(IsA(http.HttpRequest)).\
|
||||||
AndReturn(usage_limit)
|
AndReturn(usage_limit)
|
||||||
cinder.volume_list(IsA(http.HttpRequest)).\
|
|
||||||
AndReturn(self.volumes.list())
|
|
||||||
cinder.volume_snapshot_list(IsA(http.HttpRequest)).\
|
cinder.volume_snapshot_list(IsA(http.HttpRequest)).\
|
||||||
AndReturn(self.volume_snapshots.list())
|
AndReturn(self.volume_snapshots.list())
|
||||||
api.glance.image_list_detailed(IsA(http.HttpRequest),
|
api.glance.image_list_detailed(IsA(http.HttpRequest),
|
||||||
|
@ -453,10 +441,8 @@ class VolumeViewTests(test.TestCase):
|
||||||
filters={'property-owner_id': self.tenant.id,
|
filters={'property-owner_id': self.tenant.id,
|
||||||
'status': 'active'}) \
|
'status': 'active'}) \
|
||||||
.AndReturn([[], False])
|
.AndReturn([[], False])
|
||||||
cinder.tenant_absolute_limits(IsA(http.HttpRequest)).\
|
quotas.tenant_limit_usages(IsA(http.HttpRequest)).\
|
||||||
AndReturn(usage_limit)
|
AndReturn(usage_limit)
|
||||||
cinder.volume_list(IsA(http.HttpRequest)).\
|
|
||||||
AndReturn(self.volumes.list())
|
|
||||||
|
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
|
@ -467,12 +453,14 @@ class VolumeViewTests(test.TestCase):
|
||||||
' have 20GB of your quota available.']
|
' have 20GB of your quota available.']
|
||||||
self.assertEqual(res.context['form'].errors['__all__'], expected_error)
|
self.assertEqual(res.context['form'].errors['__all__'], expected_error)
|
||||||
|
|
||||||
@test.create_stubs({cinder: ('volume_snapshot_list', 'volume_type_list',
|
@test.create_stubs({cinder: ('volume_snapshot_list', 'volume_type_list',),
|
||||||
'tenant_absolute_limits', 'volume_list',),
|
api.glance: ('image_list_detailed',),
|
||||||
api.glance: ('image_list_detailed',)})
|
quotas: ('tenant_limit_usages',)})
|
||||||
def test_create_volume_number_over_alloted_quota(self):
|
def test_create_volume_number_over_alloted_quota(self):
|
||||||
usage_limit = {'maxTotalVolumeGigabytes': 100,
|
usage_limit = {'maxTotalVolumeGigabytes': 100,
|
||||||
'maxTotalVolumes': len(self.volumes.list())}
|
'gigabytesUsed': 20,
|
||||||
|
'volumesUsed': len(self.volumes.list()),
|
||||||
|
'maxTotalVolumes': len(self.volumes.list())}
|
||||||
formData = {'name': u'Too Many...',
|
formData = {'name': u'Too Many...',
|
||||||
'description': u'We have no volumes left!',
|
'description': u'We have no volumes left!',
|
||||||
'method': u'CreateForm',
|
'method': u'CreateForm',
|
||||||
|
@ -480,10 +468,8 @@ class VolumeViewTests(test.TestCase):
|
||||||
|
|
||||||
cinder.volume_type_list(IsA(http.HttpRequest)).\
|
cinder.volume_type_list(IsA(http.HttpRequest)).\
|
||||||
AndReturn(self.volume_types.list())
|
AndReturn(self.volume_types.list())
|
||||||
cinder.tenant_absolute_limits(IsA(http.HttpRequest)).\
|
quotas.tenant_limit_usages(IsA(http.HttpRequest)).\
|
||||||
AndReturn(usage_limit)
|
AndReturn(usage_limit)
|
||||||
cinder.volume_list(IsA(http.HttpRequest)).\
|
|
||||||
AndReturn(self.volumes.list())
|
|
||||||
cinder.volume_snapshot_list(IsA(http.HttpRequest)).\
|
cinder.volume_snapshot_list(IsA(http.HttpRequest)).\
|
||||||
AndReturn(self.volume_snapshots.list())
|
AndReturn(self.volume_snapshots.list())
|
||||||
api.glance.image_list_detailed(IsA(http.HttpRequest),
|
api.glance.image_list_detailed(IsA(http.HttpRequest),
|
||||||
|
@ -494,10 +480,8 @@ class VolumeViewTests(test.TestCase):
|
||||||
filters={'property-owner_id': self.tenant.id,
|
filters={'property-owner_id': self.tenant.id,
|
||||||
'status': 'active'}) \
|
'status': 'active'}) \
|
||||||
.AndReturn([[], False])
|
.AndReturn([[], False])
|
||||||
cinder.tenant_absolute_limits(IsA(http.HttpRequest)).\
|
quotas.tenant_limit_usages(IsA(http.HttpRequest)).\
|
||||||
AndReturn(usage_limit)
|
AndReturn(usage_limit)
|
||||||
cinder.volume_list(IsA(http.HttpRequest)).\
|
|
||||||
AndReturn(self.volumes.list())
|
|
||||||
|
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
|
|
|
@ -105,13 +105,7 @@ class CreateView(forms.ModalFormView):
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super(CreateView, self).get_context_data(**kwargs)
|
context = super(CreateView, self).get_context_data(**kwargs)
|
||||||
try:
|
try:
|
||||||
context['usages'] = cinder.tenant_absolute_limits(self.request)
|
context['usages'] = quotas.tenant_limit_usages(self.request)
|
||||||
volumes = cinder.volume_list(self.request)
|
|
||||||
total_size = sum([getattr(volume, 'size', 0) for volume
|
|
||||||
in volumes])
|
|
||||||
context['usages']['gigabytesUsed'] = total_size
|
|
||||||
context['usages']['volumesUsed'] = len(volumes)
|
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
exceptions.handle(self.request)
|
exceptions.handle(self.request)
|
||||||
return context
|
return context
|
||||||
|
@ -126,7 +120,7 @@ class CreateSnapshotView(forms.ModalFormView):
|
||||||
context = super(CreateSnapshotView, self).get_context_data(**kwargs)
|
context = super(CreateSnapshotView, self).get_context_data(**kwargs)
|
||||||
context['volume_id'] = self.kwargs['volume_id']
|
context['volume_id'] = self.kwargs['volume_id']
|
||||||
try:
|
try:
|
||||||
context['usages'] = quotas.tenant_quota_usages(self.request)
|
context['usages'] = quotas.tenant_limit_usages(self.request)
|
||||||
except Exception:
|
except Exception:
|
||||||
exceptions.handle(self.request)
|
exceptions.handle(self.request)
|
||||||
return context
|
return context
|
||||||
|
|
|
@ -2,6 +2,8 @@ from collections import defaultdict # noqa
|
||||||
import itertools
|
import itertools
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
from django.utils.translation import ugettext_lazy as _ # noqa
|
||||||
|
|
||||||
from horizon import exceptions
|
from horizon import exceptions
|
||||||
from horizon.utils.memoized import memoized # noqa
|
from horizon.utils.memoized import memoized # noqa
|
||||||
|
|
||||||
|
@ -205,3 +207,27 @@ def tenant_quota_usages(request):
|
||||||
usages.tally('ram', 0)
|
usages.tally('ram', 0)
|
||||||
|
|
||||||
return usages
|
return usages
|
||||||
|
|
||||||
|
|
||||||
|
def tenant_limit_usages(request):
|
||||||
|
limits = {}
|
||||||
|
|
||||||
|
try:
|
||||||
|
limits.update(nova.tenant_absolute_limits(request))
|
||||||
|
except Exception:
|
||||||
|
msg = _("Unable to retrieve compute limit information.")
|
||||||
|
exceptions.handle(request, msg)
|
||||||
|
|
||||||
|
if base.is_service_enabled(request, 'volume'):
|
||||||
|
try:
|
||||||
|
limits.update(cinder.tenant_absolute_limits(request))
|
||||||
|
volumes = cinder.volume_list(request)
|
||||||
|
total_size = sum([getattr(volume, 'size', 0) for volume
|
||||||
|
in volumes])
|
||||||
|
limits['gigabytesUsed'] = total_size
|
||||||
|
limits['volumesUsed'] = len(volumes)
|
||||||
|
except Exception:
|
||||||
|
msg = _("Unable to retrieve volume limit information.")
|
||||||
|
exceptions.handle(request, msg)
|
||||||
|
|
||||||
|
return limits
|
||||||
|
|
Loading…
Reference in New Issue