Merge "quota: Merge tenant_limit_usages into tenant_quota_usages"

This commit is contained in:
Zuul 2018-05-16 16:52:55 +00:00 committed by Gerrit Code Review
commit 63ac162658
16 changed files with 275 additions and 345 deletions

View File

@ -130,14 +130,14 @@ class CreateCGroupView(forms.ModalFormView):
volumes = api.cinder.volume_list(self.request,
search_opts=search_opts)
num_volumes = len(volumes)
usages = quotas.tenant_limit_usages(self.request)
if usages['totalVolumesUsed'] + num_volumes > \
usages['maxTotalVolumes']:
usages = quotas.tenant_quota_usages(
self.request, targets=('volumes', 'gigabytes'))
if (usages['volumes']['used'] + num_volumes >
usages['volumes']['quota']):
raise ValueError(_('Unable to create consistency group due to '
'exceeding volume quota limit.'))
else:
usages['numRequestedItems'] = num_volumes
context['numRequestedItems'] = num_volumes
context['usages'] = usages
except ValueError as e:

View File

@ -10,11 +10,11 @@
{% endblock %}
{% block gigabytes_used %}
{{ usages.totalGigabytesUsed|intcomma }}
{{ usages.gigabytes.used|intcomma }}
{% endblock %}
{% block gigabytes_used_progress %}
"{{ usages.totalGigabytesUsed }}"
"{{ usages.gigabytes.used }}"
{% endblock %}
{% block type_title %}
@ -22,11 +22,11 @@
{% endblock %}
{% block used %}
{{ usages.totalSnapshotsUsed|intcomma }}
{{ usages.snapshots.used|intcomma }}
{% endblock %}
{% block total %}
{{ usages.maxTotalSnapshots|intcomma|quota }}
{{ usages.snapshots.quota|intcomma|quota }}
{% endblock %}
{% block type_id %}
@ -34,9 +34,9 @@
{% endblock %}
{% block total_progress %}
"{{ usages.maxTotalSnapshots }}"
"{{ usages.snapshots.quota }}"
{% endblock %}
{% block used_progress %}
"{{ usages.totalSnapshotsUsed }}"
"{{ usages.snapshots.used }}"
{% endblock %}

View File

@ -203,14 +203,14 @@ class CreateSnapshotView(forms.ModalFormView):
volumes = api.cinder.volume_list(self.request,
search_opts=search_opts)
num_volumes = len(volumes)
usages = quotas.tenant_limit_usages(self.request)
if usages['totalSnapshotsUsed'] + num_volumes > \
usages['maxTotalSnapshots']:
usages = quotas.tenant_quota_usages(
self.request, targets=('snapshots', 'gigabytes'))
if (usages['snapshots']['used'] + num_volumes >
usages['snapshots']['quota']):
raise ValueError(_('Unable to create snapshots due to '
'exceeding snapshot quota limit.'))
else:
usages['numRequestedItems'] = num_volumes
context['numRequestedItems'] = num_volumes
context['usages'] = usages
except ValueError as e:
@ -247,14 +247,14 @@ class CloneCGroupView(forms.ModalFormView):
volumes = api.cinder.volume_list(self.request,
search_opts=search_opts)
num_volumes = len(volumes)
usages = quotas.tenant_limit_usages(self.request)
if usages['totalVolumesUsed'] + num_volumes > \
usages['maxTotalVolumes']:
usages = quotas.tenant_quota_usages(
self.request, targets=('volumes', 'gigabytes'))
if (usages['volumes']['used'] + num_volumes >
usages['volumes']['quota']):
raise ValueError(_('Unable to create consistency group due to '
'exceeding volume quota limit.'))
else:
usages['numRequestedItems'] = num_volumes
context['numRequestedItems'] = num_volumes
context['usages'] = usages
except ValueError as e:

View File

@ -20,7 +20,7 @@
<div class="quota_title">
<strong class="pull-left">{% trans "Number of Instances" %}</strong>
<span class="pull-right">
{% blocktrans trimmed with used=usages.totalInstancesUsed|intcomma quota=usages.maxTotalInstances|intcomma|quotainf %}
{% blocktrans trimmed with used=usages.instances.used|intcomma quota=usages.instances.quota|intcomma|quotainf %}
{{ used }} of {{ quota }} Used
{% endblocktrans %}
</span>
@ -30,9 +30,9 @@
<div id="{{ resize_instance|yesno:"quota_resize_instance,quota_instances" }}"
class="quota_bar"
data-progress-indicator-flavor
data-quota-limit="{{ usages.maxTotalInstances }}"
data-quota-used="{{ usages.totalInstancesUsed }}">
{% widthratio usages.totalInstancesUsed usages.maxTotalInstances 100 as instance_percent %}
data-quota-limit="{{ usages.instances.quota }}"
data-quota-used="{{ usages.instances.used }}">
{% widthratio usages.instances.used usages.instances.quota 100 as instance_percent %}
{% bs_progress_bar instance_percent 0 %}
</div>
{{ endminifyspace }}
@ -40,7 +40,7 @@
<div class="quota_title">
<strong class="pull-left">{% trans "Number of VCPUs" %}</strong>
<span class="pull-right">
{% blocktrans trimmed with used=usages.totalCoresUsed|intcomma quota=usages.maxTotalCores|intcomma|quotainf %}
{% blocktrans trimmed with used=usages.cores.used|intcomma quota=usages.cores.quota|intcomma|quotainf %}
{{ used }} of {{ quota }} Used
{% endblocktrans %}
</span>
@ -50,9 +50,9 @@
<div id="quota_vcpus"
class="quota_bar"
data-progress-indicator-flavor
data-quota-limit="{{ usages.maxTotalCores }}"
data-quota-used="{{ usages.totalCoresUsed }}">
{% widthratio usages.totalCoresUsed usages.maxTotalCores 100 as vcpu_percent %}
data-quota-limit="{{ usages.cores.quota }}"
data-quota-used="{{ usages.cores.used }}">
{% widthratio usages.cores.used usages.cores.quota 100 as vcpu_percent %}
{% bs_progress_bar vcpu_percent 0 %}
</div>
{{ endminifyspace }}
@ -60,7 +60,7 @@
<div class="quota_title">
<strong class="pull-left">{% trans "Total RAM" %}</strong>
<span class="pull-right">
{% blocktrans trimmed with used=usages.totalRAMUsed|intcomma quota=usages.maxTotalRAMSize|intcomma|quotainf %}
{% blocktrans trimmed with used=usages.ram.used|intcomma quota=usages.ram.quota|intcomma|quotainf %}
{{ used }} of {{ quota }} MB Used
{% endblocktrans %}
</span>
@ -70,9 +70,9 @@
<div id="quota_ram"
class="quota_bar"
data-progress-indicator-flavor
data-quota-limit="{{ usages.maxTotalRAMSize }}"
data-quota-used="{{ usages.totalRAMUsed }}">
{% widthratio usages.totalRAMUsed usages.maxTotalRAMSize 100 as vcpu_percent %}
data-quota-limit="{{ usages.ram.quota }}"
data-quota-used="{{ usages.ram.used }}">
{% widthratio usages.ram.used usages.ram.quota 100 as vcpu_percent %}
{% bs_progress_bar vcpu_percent 0 %}
</div>
{{ endminifyspace }}
@ -81,7 +81,7 @@
<div class="quota_title">
<strong class="pull-left">{% trans "Number of Volumes" %}</strong>
<span class="pull-right">
{% blocktrans with used=usages.totalVolumesUsed|intcomma quota=usages.maxTotalVolumes|intcomma|quotainf %}
{% blocktrans with used=usages.volumes.used|intcomma quota=usages.volumes.quota|intcomma|quotainf %}
{{ used }} of {{ quota }} Used
{% endblocktrans %}
</span>
@ -89,16 +89,16 @@
<div id="quota_volume"
class="quota_bar"
data-progress-indicator-flavor
data-quota-limit="{{ usages.maxTotalVolumes }}"
data-quota-used="{{ usages.totalVolumesUsed }}">
{% widthratio usages.totalVolumesUsed usages.maxTotalVolumes 100 as volume_percent %}
data-quota-limit="{{ usages.volumes.quota }}"
data-quota-used="{{ usages.volumes.used }}">
{% widthratio usages.volumes.used usages.volumes.quota 100 as volume_percent %}
{% bs_progress_bar volume_percent 0 %}
</div>
<div class="quota_title">
<strong class="pull-left">{% trans "Total Volume Storage" %}</strong>
<span class="pull-right">
{% blocktrans with used=usages.totalGigabytesUsed|intcomma quota=usages.maxTotalVolumeGigabytes|intcomma|quotainf %}
{% blocktrans with used=usages.gigabytes.used|intcomma quota=usages.gigabytes.quota|intcomma|quotainf %}
{{ used }} of {{ quota }} GiB Used
{% endblocktrans %}
</span>
@ -106,9 +106,9 @@
<div id="quota_volume_storage"
class="quota_bar"
data-progress-indicator-flavor
data-quota-limit="{{ usages.maxTotalVolumeGigabytes }}"
data-quota-used="{{ usages.totalGigabytesUsed }}">
{% widthratio usages.totalGigabytesUsed usages.maxTotalVolumeGigabytes 100 as volume_storage_percent %}
data-quota-limit="{{ usages.gigabytes.quota }}"
data-quota-used="{{ usages.gigabytes.used }}">
{% widthratio usages.gigabytes.used usages.gigabytes.quota 100 as volume_storage_percent %}
{% bs_progress_bar volume_storage_percent 0 %}
</div>
{% endif %}

View File

@ -2025,7 +2025,7 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
'port_list_with_trunk_types',
'security_group_list',),
api.glance: ('image_list_detailed',),
quotas: ('tenant_limit_usages',)})
quotas: ('tenant_quota_usages',)})
def test_launch_instance_get(self,
expect_password_fields=True,
block_device_mapping_v2=True,
@ -2053,7 +2053,7 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
]
self.mock_port_list_with_trunk_types.return_value = self.ports.list()
self.mock_server_group_list.return_value = self.server_groups.list()
self.mock_tenant_limit_usages.return_value = self.limits['absolute']
self.mock_tenant_quota_usages.return_value = self.quota_usages.first()
self._mock_nova_lists()
url = reverse('horizon:project:instances:launch')
@ -2188,8 +2188,9 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
self.mock_port_list_with_trunk_types.call_count)
self.mock_server_group_list.assert_called_once_with(
helpers.IsHttpRequest())
self.mock_tenant_limit_usages.assert_called_once_with(
helpers.IsHttpRequest())
self.mock_tenant_quota_usages.assert_called_once_with(
helpers.IsHttpRequest(),
targets=('instances', 'cores', 'ram', 'volumes', 'gigabytes'))
self._check_nova_lists(flavor_count=2)
@override_settings(OPENSTACK_API_VERSIONS={'image': 1})
@ -2274,7 +2275,7 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
'port_list_with_trunk_types',
'security_group_list',),
api.glance: ('image_list_detailed',),
quotas: ('tenant_limit_usages',)})
quotas: ('tenant_quota_usages',)})
def test_launch_instance_get_bootable_volumes(self,
block_device_mapping_v2=True,
only_one_network=False,
@ -2299,7 +2300,7 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
]
self.mock_port_list_with_trunk_types.return_value = self.ports.list()
self.mock_server_group_list.return_value = self.server_groups.list()
self.mock_tenant_limit_usages.return_value = self.limits['absolute']
self.mock_tenant_quota_usages.return_value = self.quota_usages.first()
self._mock_nova_lists()
url = reverse('horizon:project:instances:launch')
@ -2353,8 +2354,9 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
for net in self.networks.list()])
self.mock_server_group_list.assert_called_once_with(
helpers.IsHttpRequest())
self.mock_tenant_limit_usages.assert_called_once_with(
helpers.IsHttpRequest())
self.mock_tenant_quota_usages.assert_called_once_with(
helpers.IsHttpRequest(),
targets=('instances', 'cores', 'ram', 'volumes', 'gigabytes'))
self._check_nova_lists(flavor_count=2)
@override_settings(OPENSTACK_API_VERSIONS={'image': 1})
@ -2753,8 +2755,7 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
'availability_zone_list'),
cinder: ('volume_list',
'volume_snapshot_list',),
quotas: ('tenant_quota_usages',
'tenant_limit_usages')})
quotas: ('tenant_quota_usages',)})
def test_launch_instance_post_no_images_available(self):
flavor = self.flavors.first()
keypair = self.keypairs.first()
@ -2770,7 +2771,7 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
'ConfigDrive': True,
'ServerGroups': False,
})
self.mock_tenant_limit_usages.return_value = self.limits['absolute']
self.mock_tenant_quota_usages.return_value = self.quota_usages.first()
self._mock_glance_image_list_detailed([])
self._mock_neutron_network_and_port_list()
self._mock_nova_lists()
@ -2803,8 +2804,15 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
'ConfigDrive': 1,
'ServerGroups': 1,
})
self.mock_tenant_limit_usages.assert_called_once_with(
helpers.IsHttpRequest())
self.mock_tenant_quota_usages.assert_has_calls([
mock.call(
helpers.IsHttpRequest(),
targets=('instances', 'cores', 'ram', 'volumes', )),
mock.call(
helpers.IsHttpRequest(),
targets=('instances', 'cores', 'ram', 'volumes', 'gigabytes')),
])
self.assertEqual(2, self.mock_tenant_quota_usages.call_count)
self._check_glance_image_list_detailed(count=5)
self._check_neutron_network_and_port_list()
self._check_nova_lists(flavor_count=3)
@ -2817,9 +2825,15 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
self.mock_volume_snapshot_list.assert_called_once_with(
helpers.IsHttpRequest(),
search_opts=SNAPSHOT_SEARCH_OPTS)
self.mock_tenant_quota_usages.assert_called_once_with(
helpers.IsHttpRequest(),
targets=('instances', 'cores', 'ram', 'volumes', ))
self.mock_tenant_quota_usages.assert_has_calls([
mock.call(
helpers.IsHttpRequest(),
targets=('instances', 'cores', 'ram', 'volumes', )),
mock.call(
helpers.IsHttpRequest(),
targets=('instances', 'cores', 'ram', 'volumes', 'gigabytes')),
])
self.assertEqual(2, self.mock_tenant_quota_usages.call_count)
@helpers.create_mocks({
api.glance: ('image_list_detailed',),
@ -2973,11 +2987,9 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
'flavor_list',
'keypair_list',
'availability_zone_list',
'server_create',
('tenant_absolute_limits', 'nova_tenant_absolute_limits')),
'server_create'),
cinder: ('volume_list',
'volume_snapshot_list',
('tenant_absolute_limits', 'cinder_tenant_absolute_limits')),
'volume_snapshot_list'),
quotas: ('tenant_quota_usages',)})
def test_launch_instance_post_boot_from_snapshot_error(self):
flavor = self.flavors.first()
@ -2995,10 +3007,6 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
'ConfigDrive': True,
'ServerGroups': False,
})
self.mock_nova_tenant_absolute_limits.return_value = \
self.limits['absolute']
self.mock_cinder_tenant_absolute_limits.return_value = \
self.cinder_limits['absolute']
bad_snapshot_id = 'a-bogus-id'
@ -3034,9 +3042,15 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
filters={'status': 'active', 'visibility': 'shared'}),
])
self.mock_tenant_quota_usages.assert_called_once_with(
helpers.IsHttpRequest(),
targets=('instances', 'cores', 'ram', 'volumes', ))
self.mock_tenant_quota_usages.assert_has_calls([
mock.call(
helpers.IsHttpRequest(),
targets=('instances', 'cores', 'ram', 'volumes', )),
mock.call(
helpers.IsHttpRequest(),
targets=('instances', 'cores', 'ram', 'volumes', 'gigabytes')),
])
self.assertEqual(2, self.mock_tenant_quota_usages.call_count)
self._check_neutron_network_and_port_list()
@ -3047,11 +3061,6 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
'ServerGroups': 1,
})
self.mock_nova_tenant_absolute_limits.assert_called_once_with(
helpers.IsHttpRequest(), reserved=True)
self.mock_cinder_tenant_absolute_limits.assert_called_once_with(
helpers.IsHttpRequest())
@helpers.create_mocks({api.glance: ('image_list_detailed',),
api.neutron: ('network_list',
'port_list_with_trunk_types',
@ -3063,7 +3072,7 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
'flavor_list',
'keypair_list',
'availability_zone_list',),
quotas: ('tenant_limit_usages',)})
quotas: ('tenant_quota_usages',)})
def test_launch_flavorlist_error(self):
self._mock_extension_supported({
'BlockDeviceMappingV2Boot': True,
@ -3075,7 +3084,7 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
self.mock_volume_snapshot_list.return_value = []
self._mock_glance_image_list_detailed(self.versioned_images.list())
self._mock_neutron_network_and_port_list()
self.mock_tenant_limit_usages.return_value = self.limits['absolute']
self.mock_tenant_quota_usages.return_value = self.quota_usages.first()
self.mock_flavor_list.side_effect = self.exceptions.nova
self.mock_keypair_list.return_value = self.keypairs.list()
self.mock_security_group_list.return_value = \
@ -3107,8 +3116,9 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
self._check_glance_image_list_detailed(count=5)
self._check_neutron_network_and_port_list()
self.mock_tenant_limit_usages.assert_called_once_with(
helpers.IsHttpRequest())
self.mock_tenant_quota_usages.assert_called_once_with(
helpers.IsHttpRequest(),
targets=('instances', 'cores', 'ram', 'volumes', 'gigabytes'))
self.assert_mock_multiple_calls_with_same_arguments(
self.mock_flavor_list, 2,
mock.call(helpers.IsHttpRequest()))
@ -3261,8 +3271,7 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
'availability_zone_list',),
cinder: ('volume_list',
'volume_snapshot_list',),
quotas: ('tenant_limit_usages',
'tenant_quota_usages')})
quotas: ('tenant_quota_usages',)})
def test_launch_form_instance_count_error(self):
flavor = self.flavors.first()
image = self.versioned_images.first()
@ -3289,7 +3298,6 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
self.mock_volume_list.return_value = volumes
self.mock_volume_snapshot_list.return_value = []
self.mock_flavor_list.return_value = self.flavors.list()
self.mock_tenant_limit_usages.return_value = self.limits['absolute']
self.mock_tenant_quota_usages.return_value = quota_usages
form_data = {'flavor': flavor.id,
@ -3333,11 +3341,15 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
self.assert_mock_multiple_calls_with_same_arguments(
self.mock_flavor_list, 3,
mock.call(helpers.IsHttpRequest()))
self.mock_tenant_limit_usages.assert_called_once_with(
helpers.IsHttpRequest())
self.mock_tenant_quota_usages.assert_called_once_with(
helpers.IsHttpRequest(),
targets=('instances', 'cores', 'ram', 'volumes', ))
self.mock_tenant_quota_usages.assert_has_calls([
mock.call(
helpers.IsHttpRequest(),
targets=('instances', 'cores', 'ram', 'volumes', )),
mock.call(
helpers.IsHttpRequest(),
targets=('instances', 'cores', 'ram', 'volumes', 'gigabytes')),
])
self.assertEqual(2, self.mock_tenant_quota_usages.call_count)
@override_settings(OPENSTACK_API_VERSIONS={'image': 1})
def test_launch_form_instance_count_error_glance_v1(self):
@ -3355,8 +3367,7 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
'availability_zone_list',),
cinder: ('volume_list',
'volume_snapshot_list',),
quotas: ('tenant_quota_usages',
'tenant_limit_usages')})
quotas: ('tenant_quota_usages',)})
def _test_launch_form_count_error(self, resource, avail):
flavor = self.flavors.first()
image = self.versioned_images.first()
@ -3388,7 +3399,6 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
self.mock_volume_list.return_value = volumes
self.mock_volume_snapshot_list.return_value = []
self.mock_flavor_list.return_value = self.flavors.list()
self.mock_tenant_limit_usages.return_value = self.limits['absolute']
self.mock_tenant_quota_usages.return_value = quota_usages
form_data = {'flavor': flavor.id,
@ -3444,11 +3454,15 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
self.assert_mock_multiple_calls_with_same_arguments(
self.mock_flavor_list, 3,
mock.call(helpers.IsHttpRequest()))
self.mock_tenant_limit_usages.assert_called_once_with(
helpers.IsHttpRequest())
self.mock_tenant_quota_usages.assert_called_once_with(
helpers.IsHttpRequest(),
targets=('instances', 'cores', 'ram', 'volumes', ))
self.mock_tenant_quota_usages.assert_has_calls([
mock.call(
helpers.IsHttpRequest(),
targets=('instances', 'cores', 'ram', 'volumes', )),
mock.call(
helpers.IsHttpRequest(),
targets=('instances', 'cores', 'ram', 'volumes', 'gigabytes')),
])
self.assertEqual(2, self.mock_tenant_quota_usages.call_count)
def test_launch_form_cores_count_error_glance_v2(self):
self._test_launch_form_count_error('cores', 1)
@ -3474,8 +3488,7 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
'availability_zone_list',),
cinder: ('volume_list',
'volume_snapshot_list',),
quotas: ('tenant_quota_usages',
'tenant_limit_usages')})
quotas: ('tenant_quota_usages',)})
def _launch_form_instance(self, image, flavor, keypair=None):
server = self.servers.first()
volume = self.volumes.first()
@ -3498,7 +3511,6 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
self.mock_volume_list.return_value = volumes
self.mock_volume_snapshot_list.return_value = []
self.mock_flavor_list.return_value = self.flavors.list()
self.mock_tenant_limit_usages.return_value = self.limits['absolute']
self.mock_tenant_quota_usages.return_value = quota_usages
form_data = {'flavor': flavor.id,
@ -3541,11 +3553,15 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
self.assert_mock_multiple_calls_with_same_arguments(
self.mock_flavor_list, 3,
mock.call(helpers.IsHttpRequest()))
self.mock_tenant_limit_usages.assert_called_once_with(
helpers.IsHttpRequest())
self.mock_tenant_quota_usages.assert_called_once_with(
helpers.IsHttpRequest(),
targets=('instances', 'cores', 'ram', 'volumes', ))
self.mock_tenant_quota_usages.assert_has_calls([
mock.call(
helpers.IsHttpRequest(),
targets=('instances', 'cores', 'ram', 'volumes', )),
mock.call(
helpers.IsHttpRequest(),
targets=('instances', 'cores', 'ram', 'volumes', 'gigabytes')),
])
self.assertEqual(2, self.mock_tenant_quota_usages.call_count)
return res
@ -3594,8 +3610,7 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
'availability_zone_list',),
cinder: ('volume_list',
'volume_snapshot_list',),
quotas: ('tenant_quota_usages',
'tenant_limit_usages')})
quotas: ('tenant_quota_usages',)})
def _test_launch_form_instance_show_device_name(self, device_name,
widget_class,
widget_attrs):
@ -3638,7 +3653,6 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
self.mock_volume_list.return_value = volumes
self.mock_volume_snapshot_list.return_value = []
self.mock_flavor_list.return_value = self.flavors.list()
self.mock_tenant_limit_usages.return_value = self.limits['absolute']
self.mock_tenant_quota_usages.return_value = quota_usages
form_data = {'flavor': flavor.id,
@ -3733,11 +3747,15 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
self.assert_mock_multiple_calls_with_same_arguments(
self.mock_flavor_list, 3,
mock.call(helpers.IsHttpRequest()))
self.mock_tenant_limit_usages.assert_called_once_with(
helpers.IsHttpRequest())
self.mock_tenant_quota_usages.assert_called_once_with(
helpers.IsHttpRequest(),
targets=('instances', 'cores', 'ram', 'volumes', ))
self.mock_tenant_quota_usages.assert_has_calls([
mock.call(
helpers.IsHttpRequest(),
targets=('instances', 'cores', 'ram', 'volumes', )),
mock.call(
helpers.IsHttpRequest(),
targets=('instances', 'cores', 'ram', 'volumes', 'gigabytes')),
])
self.assertEqual(2, self.mock_tenant_quota_usages.call_count)
@override_settings(
OPENSTACK_HYPERVISOR_FEATURES={'can_set_mount_point': True},)
@ -3780,8 +3798,7 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
'availability_zone_list',),
cinder: ('volume_list',
'volume_snapshot_list',),
quotas: ('tenant_quota_usages',
'tenant_limit_usages')})
quotas: ('tenant_quota_usages',)})
def _test_launch_form_instance_volume_size(self, image, volume_size, msg,
avail_volumes=None):
flavor = self.flavors.get(name='m1.massive')
@ -3815,7 +3832,6 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
if (v.status == AVAILABLE and v.bootable == 'true')]
self.mock_volume_list.return_value = volumes
self.mock_volume_snapshot_list.return_value = []
self.mock_tenant_limit_usages.return_value = self.limits['absolute']
self.mock_tenant_quota_usages.return_value = quota_usages
form_data = {
@ -3874,11 +3890,15 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
self.assert_mock_multiple_calls_with_same_arguments(
self.mock_flavor_list, flavor_list_count,
mock.call(helpers.IsHttpRequest()))
self.mock_tenant_limit_usages.assert_called_once_with(
helpers.IsHttpRequest())
self.mock_tenant_quota_usages.assert_called_once_with(
helpers.IsHttpRequest(),
targets=('instances', 'cores', 'ram', 'volumes', ))
self.mock_tenant_quota_usages.assert_has_calls([
mock.call(
helpers.IsHttpRequest(),
targets=('instances', 'cores', 'ram', 'volumes', )),
mock.call(
helpers.IsHttpRequest(),
targets=('instances', 'cores', 'ram', 'volumes', 'gigabytes')),
])
self.assertEqual(2, self.mock_tenant_quota_usages.call_count)
def test_launch_form_instance_volume_size_error(self):
image = self.versioned_images.get(name='protected_images')
@ -3913,7 +3933,6 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
def test_launch_button_attributes(self):
servers = self.servers.list()
limits = self.limits['absolute']
limits['totalInstancesUsed'] = 0
self._mock_extension_supported({'AdminActions': True,
'Shelve': True})
@ -4209,7 +4228,7 @@ class InstanceTests2(InstanceTestBase, InstanceTableTestMixin):
'port_list_with_trunk_types',
'security_group_list',),
api.glance: ('image_list_detailed',),
quotas: ('tenant_limit_usages',)})
quotas: ('tenant_quota_usages',)})
def test_select_default_keypair_if_only_one(self):
keypair = self.keypairs.first()
@ -4217,7 +4236,7 @@ class InstanceTests2(InstanceTestBase, InstanceTableTestMixin):
self.mock_volume_snapshot_list.return_value = []
self._mock_glance_image_list_detailed(self.versioned_images.list())
self._mock_neutron_network_and_port_list()
self.mock_tenant_limit_usages.return_value = self.limits['absolute']
self.mock_tenant_quota_usages.return_value = self.quota_usages.first()
self._mock_extension_supported({'BlockDeviceMappingV2Boot': True,
'DiskConfig': True,
'ConfigDrive': True,
@ -4242,8 +4261,9 @@ class InstanceTests2(InstanceTestBase, InstanceTableTestMixin):
helpers.IsHttpRequest(), search_opts=SNAPSHOT_SEARCH_OPTS)
self._check_glance_image_list_detailed(count=5)
self._check_neutron_network_and_port_list()
self.mock_tenant_limit_usages.assert_called_once_with(
helpers.IsHttpRequest())
self.mock_tenant_quota_usages.assert_called_once_with(
helpers.IsHttpRequest(),
targets=('instances', 'cores', 'ram', 'volumes', 'gigabytes'))
self._check_extension_supported({'BlockDeviceMappingV2Boot': 1,
'DiskConfig': 1,
'ConfigDrive': 1,

View File

@ -392,7 +392,9 @@ class SetInstanceDetailsAction(workflows.Action):
def get_help_text(self, extra_context=None):
extra = {} if extra_context is None else dict(extra_context)
try:
extra['usages'] = quotas.tenant_limit_usages(self.request)
extra['usages'] = quotas.tenant_quota_usages(
self.request,
targets=('instances', 'cores', 'ram', 'volumes', 'gigabytes'))
extra['usages_json'] = json.dumps(extra['usages'])
extra['cinder_enabled'] = \
base.is_service_enabled(self.request, 'volume')

View File

@ -122,16 +122,12 @@ class VolumeSnapshotsViewTests(test.TestCase):
self.assertItemsEqual(snapshots, expected_snapshots)
@test.create_mocks({api.cinder: ('volume_get',),
quotas: ('tenant_limit_usages',)})
quotas: ('tenant_quota_usages',)})
def test_create_snapshot_get(self):
volume = self.cinder_volumes.first()
self.mock_volume_get.return_value = volume
snapshot_used = len(self.cinder_volume_snapshots.list())
usage_limit = {'maxTotalVolumeGigabytes': 250,
'totalGigabytesUsed': 20,
'totalSnapshotsUsed': snapshot_used,
'maxTotalSnapshots': 6}
self.mock_tenant_limit_usages.return_value = usage_limit
self.mock_tenant_quota_usages.return_value = \
self.cinder_quota_usages.first()
url = reverse('horizon:project:volumes:create_snapshot',
args=[volume.id])
@ -140,8 +136,9 @@ class VolumeSnapshotsViewTests(test.TestCase):
self.assertTemplateUsed(res, 'project/volumes/create_snapshot.html')
self.mock_volume_get.assert_called_once_with(test.IsHttpRequest(),
volume.id)
self.mock_tenant_limit_usages.assert_called_once_with(
test.IsHttpRequest())
self.mock_tenant_quota_usages.assert_called_once_with(
test.IsHttpRequest(),
targets=('snapshots', 'gigabytes'))
@test.create_mocks({api.cinder: ('volume_get',
'volume_snapshot_create')})

View File

@ -317,11 +317,10 @@ class CreateForm(forms.SelfHandlingForm):
def handle(self, request, data):
try:
usages = quotas.tenant_limit_usages(self.request)
availableGB = usages['maxTotalVolumeGigabytes'] - \
usages['totalGigabytesUsed']
availableVol = usages['maxTotalVolumes'] - \
usages['totalVolumesUsed']
usages = quotas.tenant_quota_usages(
self.request, targets=('volumes', 'gigabytes'))
availableGB = usages['gigabytes']['available']
availableVol = usages['volumes']['available']
snapshot_id = None
image_id = None
@ -738,9 +737,10 @@ class ExtendForm(forms.SelfHandlingForm):
self._errors['new_size'] = self.error_class([error_msg])
return cleaned_data
usages = quotas.tenant_limit_usages(self.request)
availableGB = usages['maxTotalVolumeGigabytes'] - \
usages['totalGigabytesUsed']
usages = quotas.tenant_quota_usages(
self.request, targets=('gigabytes',))
availableGB = usages['gigabytes']['available']
if availableGB < (new_size - orig_size):
message = _('Volume cannot be extended to %(req)iGiB as '
'the maximum size it can be extended to is '

View File

@ -11,16 +11,16 @@
<strong>{% trans "Total Gibibytes" %}</strong>
</div>
<span class="pull-right">
{% blocktrans with used=usages.totalGigabytesUsed|intcomma quota=usages.maxTotalVolumeGigabytes|intcomma|quotainf %}{{ used }} of {{ quota }} GiB Used{% endblocktrans %}
{% blocktrans with used=usages.gigabytes.used|intcomma quota=usages.gigabytes.quota|intcomma|quotainf %}{{ used }} of {{ quota }} GiB Used{% endblocktrans %}
</span>
</div>
<div id="quota_size"
data-progress-indicator-for="id_new_size"
data-quota-limit="{{ usages.maxTotalVolumeGigabytes }}"
data-quota-used="{{ usages.totalGigabytesUsed }}"
data-quota-limit="{{ usages.gigabytes.quota }}"
data-quota-used="{{ usages.gigabytes.used }}"
class="quota_bar">
{% widthratio usages.totalGigabytesUsed usages.maxTotalVolumeGigabytes 100 as gigabytes_percent %}
{% widthratio usages.gigabytes.used usages.gigabytes.quota 100 as gigabytes_percent %}
{% bs_progress_bar gigabytes_percent 0 %}
</div>

View File

@ -19,17 +19,17 @@
<strong>{% trans "Total Gibibytes" %}</strong>
</div>
<span class="pull-right">
{% blocktrans with used=usages.totalGigabytesUsed|intcomma quota=usages.maxTotalVolumeGigabytes|intcomma|quotainf %}{{ used }} of {{ quota }} GiB Used{% endblocktrans %}
{% blocktrans with used=usages.gigabytes.used|intcomma quota=usages.gigabytes.quota|intcomma|quotainf %}{{ used }} of {{ quota }} GiB Used{% endblocktrans %}
</span>
</div>
{{ minifyspace }}
<div id="quota_size"
data-progress-indicator-for="id_size"
data-quota-limit="{{ usages.maxTotalVolumeGigabytes }}"
data-quota-used={% block gigabytes_used_progress %}"{{ usages.totalGigabytesUsed }}"{% endblock %}
data-quota-limit="{{ usages.gigabytes.quota }}"
data-quota-used={% block gigabytes_used_progress %}"{{ usages.gigabytes.used }}"{% endblock %}
class="quota_bar">
{% widthratio usages.totalGigabytesUsed usages.maxTotalVolumeGigabytes 100 as gigabytes_percent %}
{% widthratio usages.gigabytes.used usages.gigabytes.quota 100 as gigabytes_percent %}
{% bs_progress_bar gigabytes_percent 0 %}
</div>
{{ endminifyspace }}
@ -40,22 +40,22 @@
</div>
<span class="pull-right">
{% block used_of_quota %}
{% blocktrans with used=usages.totalVolumesUsed|intcomma quota=usages.maxTotalVolumes|intcomma|quotainf %}{{ used }} of {{ quota }} Used{% endblocktrans %}
{% blocktrans with used=usages.volumes.used|intcomma quota=usages.volumes.quota|intcomma|quotainf %}{{ used }} of {{ quota }} Used{% endblocktrans %}
{% endblock %}
</span>
</div>
{{ minifyspace }}
<div id={% block type_id %}"quota_volumes"{% endblock %}
data-quota-limit={% block total_progress %}"{{ usages.maxTotalVolumes }}"{% endblock %}
data-quota-used={% block used_progress %}"{{ usages.totalVolumesUsed }}"{% endblock %}
data-quota-limit={% block total_progress %}"{{ usages.volumes.quota }}"{% endblock %}
data-quota-used={% block used_progress %}"{{ usages.volumes.used }}"{% endblock %}
class="quota_bar">
{% block show_progress_bar %}
{% widthratio usages.totalVolumesUsed usages.maxTotalVolumes 100 as volumes_percent %}
{% if usages.numRequestedItems %}
{% widthratio 100 usages.maxTotalVolumes usages.numRequestedItems as single_step %}
{% widthratio usages.volumes.used usages.volumes.quota 100 as volumes_percent %}
{% if numRequestedItems %}
{% widthratio 100 usages.volumes.quota numRequestedItems as single_step %}
{% else %}
{% widthratio 100 usages.maxTotalVolumes 1 as single_step %}
{% widthratio 100 usages.volumes.quota 1 as single_step %}
{% endif %}
{% bs_progress_bar volumes_percent single_step %}
{% endblock %}

View File

@ -10,11 +10,11 @@
{% endblock %}
{% block gigabytes_used %}
{{ usages.totalGigabytesUsed|intcomma }}
{{ usages.gigabytes.used|intcomma }}
{% endblock %}
{% block gigabytes_used_progress %}
"{{ usages.totalGigabytesUsed }}"
"{{ usages.gigabytes.used }}"
{% endblock %}
{% block type_title %}
@ -22,7 +22,7 @@
{% endblock %}
{% block used_of_quota %}
{% blocktrans with used=usages.totalSnapshotsUsed|intcomma quota=usages.maxTotalSnapshots|intcomma|quotainf %}{{ used }} of {{ quota }} Used{% endblocktrans %}
{% blocktrans with used=usages.snapshots.used|intcomma quota=usages.snapshots.quota|intcomma|quotainf %}{{ used }} of {{ quota }} Used{% endblocktrans %}
{% endblock %}
{% block type_id %}
@ -30,19 +30,19 @@
{% endblock %}
{% block total_progress %}
"{{ usages.maxTotalSnapshots }}"
"{{ usages.snapshots.quota }}"
{% endblock %}
{% block used_progress %}
"{{ usages.totalSnapshotsUsed }}"
"{{ usages.snapshots.used }}"
{% endblock %}
{% block show_progress_bar %}
{% widthratio usages.totalSnapshotsUsed usages.maxTotalSnapshots 100 as volumes_percent %}
{% if usages.numRequestedItems %}
{% widthratio usages.numRequestedItems usages.maxTotalSnapshots 100 as single_step %}
{% widthratio usages.snapshots.used usages.snapshots.quota 100 as volumes_percent %}
{% if numRequestedItems %}
{% widthratio numRequestedItems usages.snapshots.quota 100 as single_step %}
{% else %}
{% widthratio 1 usages.maxTotalSnapshots 100 as single_step %}
{% widthratio 1 usages.snapshots.quota 100 as single_step %}
{% endif %}
{% bs_progress_bar volumes_percent single_step %}
{% endblock %}

View File

@ -5,18 +5,18 @@
<div class="quota_title">
<div class="pull-left">
<strong>{% trans "Total Gibibytes" %}</strong>
<span>({% block gigabytes_used %}{{ usages.totalGigabytesUsed|intcomma }}{% endblock %} {% trans "GiB" %})</span>
<span>({% block gigabytes_used %}{{ usages.gigabytes.used|intcomma }}{% endblock %} {% trans "GiB" %})</span>
</div>
<span class="pull-right">{{ usages.maxTotalVolumeGigabytes|intcomma|quota:_("GiB") }}</span>
<span class="pull-right">{{ usages.gigabytes.quota|intcomma|quota:_("GiB") }}</span>
</div>
{{ minifyspace }}
<div id="quota_size"
data-progress-indicator-for="id_size"
data-quota-limit="{{ usages.maxTotalVolumeGigabytes }}"
data-quota-used={% block gigabytes_used_progress %}"{{ usages.totalGigabytesUsed }}"{% endblock %}
data-quota-limit="{{ usages.gigabytes.quota }}"
data-quota-used={% block gigabytes_used_progress %}"{{ usages.gigabytes.used }}"{% endblock %}
class="quota_bar">
{% widthratio usages.totalGigabytesUsed usages.maxTotalVolumeGigabytes 100 as gigabytes_percent %}
{% widthratio usages.gigabytes.used usages.gigabytes.quota 100 as gigabytes_percent %}
{% bs_progress_bar gigabytes_percent 0 %}
</div>
{{ endminifyspace }}
@ -24,21 +24,21 @@
<div class="quota_title">
<div class="pull-left">
<strong>{% block type_title %}{% trans "Number of Volumes" %}{% endblock %}</strong>
<span>({% block used %}{{ usages.totalVolumesUsed|intcomma }}{% endblock %})</span>
<span>({% block used %}{{ usages.volumes.used|intcomma }}{% endblock %})</span>
</div>
<span class="pull-right">{% block total %}{{ usages.maxTotalVolumes|intcomma|quota }}{% endblock %}</span>
<span class="pull-right">{% block total %}{{ usages.volumes.quota|intcomma|quota }}{% endblock %}</span>
</div>
{{ minifyspace }}
<div id={% block type_id %}"quota_volumes"{% endblock %}
data-quota-limit={% block total_progress %}"{{ usages.maxTotalVolumes }}"{% endblock %}
data-quota-used={% block used_progress %}"{{ usages.totalVolumesUsed }}"{% endblock %}
data-quota-limit={% block total_progress %}"{{ usages.volumes.quota }}"{% endblock %}
data-quota-used={% block used_progress %}"{{ usages.volumes.used }}"{% endblock %}
class="quota_bar">
{% widthratio usages.totalVolumesUsed usages.maxTotalVolumes 100 as volumes_percent %}
{% if usages.numRequestedItems %}
{% widthratio 100 usages.maxTotalVolumes usages.numRequestedItems as single_step %}
{% widthratio usages.volumes.used usages.volumes.quota 100 as volumes_percent %}
{% if numRequestedItems %}
{% widthratio 100 usages.volumes.quota numRequestedItems as single_step %}
{% else %}
{% widthratio 100 usages.maxTotalVolumes 1 as single_step %}
{% widthratio 100 usages.volumes.quota 1 as single_step %}
{% endif %}
{% bs_progress_bar volumes_percent single_step %}
</div>

View File

@ -210,17 +210,13 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
'volume_type_list', 'volume_type_default',
'volume_list', 'availability_zone_list',
'extension_supported'],
quotas: ['tenant_limit_usages'],
quotas: ['tenant_quota_usages'],
api.glance: ['image_list_detailed'],
})
def test_create_volume(self):
volume = self.cinder_volumes.first()
volume_type = self.cinder_volume_types.first()
az = self.cinder_availability_zones.first().zoneName
usage_limit = {'maxTotalVolumeGigabytes': 250,
'totalGigabytesUsed': 20,
'totalVolumesUsed': len(self.cinder_volumes.list()),
'maxTotalVolumes': 6}
formData = {'name': u'A Volume I Am Making',
'description': u'This is a volume I am making for a test.',
'method': u'CreateForm',
@ -233,7 +229,8 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
self.cinder_volume_types.first()
self.mock_volume_type_list.return_value = \
self.cinder_volume_types.list()
self.mock_tenant_limit_usages.return_value = usage_limit
self.mock_tenant_quota_usages.return_value = \
self.cinder_quota_usages.first()
self.mock_volume_snapshot_list.return_value = \
self.cinder_volume_snapshots.list()
self.mock_image_list_detailed.return_value = [[], False, False]
@ -267,10 +264,12 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
self.mock_image_list_detailed.assert_called_with(
test.IsHttpRequest(),
filters={'visibility': 'shared', 'status': 'active'})
self.mock_tenant_limit_usages.assert_called_once()
self.mock_tenant_quota_usages.assert_called_once_with(
test.IsHttpRequest(),
targets=('volumes', 'gigabytes'))
@test.create_mocks({
quotas: ['tenant_limit_usages'],
quotas: ['tenant_quota_usages'],
api.glance: ['image_list_detailed'],
cinder: ['extension_supported',
'availability_zone_list',
@ -284,10 +283,6 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
volume = self.cinder_volumes.first()
volume_type = self.cinder_volume_types.first()
az = self.cinder_availability_zones.first().zoneName
usage_limit = {'maxTotalVolumeGigabytes': 250,
'totalGigabytesUsed': 20,
'totalVolumesUsed': len(self.cinder_volumes.list()),
'maxTotalVolumes': 6}
formData = {'name': '',
'description': u'This is a volume I am making for a test.',
'method': u'CreateForm',
@ -298,7 +293,8 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
self.mock_volume_type_list.return_value = \
self.cinder_volume_types.list()
self.mock_tenant_limit_usages.return_value = usage_limit
self.mock_tenant_quota_usages.return_value = \
self.cinder_quota_usages.first()
self.mock_volume_snapshot_list.return_value = \
self.cinder_volume_snapshots.list()
self.mock_image_list_detailed.return_value = [self.images.list(),
@ -319,7 +315,7 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
self.assertRedirectsNoFollow(res, redirect_url)
self.mock_volume_type_list.assert_called_once()
self.mock_tenant_limit_usages.assert_called_once()
self.mock_tenant_quota_usages.assert_called_once()
self.mock_volume_snapshot_list.assert_called_once_with(
test.IsHttpRequest(), search_opts=SEARCH_OPTS)
self.mock_image_list_detailed.assert_called_with(
@ -337,7 +333,7 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
availability_zone=formData['availability_zone'], source_volid=None)
@test.create_mocks({
quotas: ['tenant_limit_usages'],
quotas: ['tenant_quota_usages'],
api.glance: ['image_list_detailed'],
cinder: ['extension_supported',
'availability_zone_list',
@ -349,10 +345,6 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
})
def test_create_volume_dropdown(self):
volume = self.cinder_volumes.first()
usage_limit = {'maxTotalVolumeGigabytes': 250,
'totalGigabytesUsed': 20,
'totalVolumesUsed': len(self.cinder_volumes.list()),
'maxTotalVolumes': 6}
formData = {'name': u'A Volume I Am Making',
'description': u'This is a volume I am making for a test.',
'method': u'CreateForm',
@ -371,7 +363,8 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
self.mock_image_list_detailed.return_value = \
[self.images.list(), False, False]
self.mock_volume_list.return_value = self.cinder_volumes.list()
self.mock_tenant_limit_usages.return_value = usage_limit
self.mock_tenant_quota_usages.return_value = \
self.cinder_quota_usages.first()
self.mock_extension_supported.return_value = True
self.mock_availability_zone_list.return_value = \
@ -394,7 +387,7 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
filters={'visibility': 'shared', 'status': 'active'})
self.mock_volume_list.assert_called_once_with(test.IsHttpRequest(),
search_opts=SEARCH_OPTS)
self.mock_tenant_limit_usages.assert_called_once()
self.mock_tenant_quota_usages.assert_called_once()
self.mock_extension_supported.assert_called_once_with(
test.IsHttpRequest(), 'AvailabilityZones')
self.mock_availability_zone_list.assert_called_once()
@ -404,7 +397,7 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
image_id=None, availability_zone=None, source_volid=None)
@test.create_mocks({
quotas: ['tenant_limit_usages'],
quotas: ['tenant_quota_usages'],
cinder: ['volume_type_list',
'volume_type_default',
'volume_get',
@ -413,10 +406,6 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
})
def test_create_volume_from_snapshot(self):
volume = self.cinder_volumes.first()
usage_limit = {'maxTotalVolumeGigabytes': 250,
'totalGigabytesUsed': 20,
'totalVolumesUsed': len(self.cinder_volumes.list()),
'maxTotalVolumes': 6}
snapshot = self.cinder_volume_snapshots.first()
formData = {'name': u'A Volume I Am Making',
'description': u'This is a volume I am making for a test.',
@ -429,7 +418,8 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
self.cinder_volume_types.first()
self.mock_volume_type_list.return_value = \
self.cinder_volume_types.list()
self.mock_tenant_limit_usages.return_value = usage_limit
self.mock_tenant_quota_usages.return_value = \
self.cinder_quota_usages.first()
self.mock_volume_snapshot_get.return_value = snapshot
self.mock_volume_get.return_value = self.cinder_volumes.first()
self.mock_volume_create.return_value = volume
@ -445,7 +435,7 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
self.assertRedirectsNoFollow(res, redirect_url)
self.mock_volume_type_default.assert_called_once()
self.mock_volume_type_list.assert_called_once()
self.mock_tenant_limit_usages.assert_called_once()
self.mock_tenant_quota_usages.assert_called_once()
self.mock_volume_snapshot_get.assert_called_once_with(
test.IsHttpRequest(), str(snapshot.id))
self.mock_volume_get.assert_called_once_with(test.IsHttpRequest(),
@ -456,7 +446,7 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
image_id=None, availability_zone=None, source_volid=None)
@test.create_mocks({
quotas: ['tenant_limit_usages'],
quotas: ['tenant_quota_usages'],
api.glance: ['image_list_detailed'],
cinder: ['extension_supported',
'volume_snapshot_list',
@ -470,10 +460,6 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
})
def test_create_volume_from_volume(self):
volume = self.cinder_volumes.first()
usage_limit = {'maxTotalVolumeGigabytes': 250,
'totalGigabytesUsed': 20,
'totalVolumesUsed': len(self.cinder_volumes.list()),
'maxTotalVolumes': 6}
formData = {'name': u'A copy of a volume',
'description': u'This is a volume I am making for a test.',
@ -490,7 +476,8 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
self.cinder_volume_types.list()
self.mock_volume_snapshot_list.return_value = \
self.cinder_volume_snapshots.list()
self.mock_tenant_limit_usages.return_value = usage_limit
self.mock_tenant_quota_usages.return_value = \
self.cinder_quota_usages.first()
self.mock_volume_get.return_value = self.cinder_volumes.first()
self.mock_extension_supported.return_value = True
@ -513,7 +500,7 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
self.mock_volume_type_list.assert_called_once()
self.mock_volume_snapshot_list.assert_called_once_with(
test.IsHttpRequest(), search_opts=SEARCH_OPTS)
self.mock_tenant_limit_usages.assert_called_once()
self.mock_tenant_quota_usages.assert_called_once()
self.mock_volume_get.assert_called_once_with(test.IsHttpRequest(),
volume.id)
self.mock_extension_supported.assert_called_once_with(
@ -528,7 +515,7 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
image_id=None, availability_zone=None, source_volid=volume.id)
@test.create_mocks({
quotas: ['tenant_limit_usages'],
quotas: ['tenant_quota_usages'],
api.glance: ['image_list_detailed'],
cinder: ['extension_supported',
'availability_zone_list',
@ -542,10 +529,6 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
})
def test_create_volume_from_snapshot_dropdown(self):
volume = self.cinder_volumes.first()
usage_limit = {'maxTotalVolumeGigabytes': 250,
'totalGigabytesUsed': 20,
'totalVolumesUsed': len(self.cinder_volumes.list()),
'maxTotalVolumes': 6}
snapshot = self.cinder_volume_snapshots.first()
formData = {'name': u'A Volume I Am Making',
'description': u'This is a volume I am making for a test.',
@ -564,7 +547,8 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
self.mock_volume_type_default.return_value = \
self.cinder_volume_types.first()
self.mock_volume_list.return_value = self.cinder_volumes.list()
self.mock_tenant_limit_usages.return_value = usage_limit
self.mock_tenant_quota_usages.return_value = \
self.cinder_quota_usages.first()
self.mock_volume_snapshot_get.return_value = snapshot
self.mock_extension_supported.return_value = True
self.mock_availability_zone_list.return_value = \
@ -587,7 +571,7 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
self.mock_volume_type_default.assert_called_once()
self.mock_volume_list.assert_called_once_with(test.IsHttpRequest(),
search_opts=SEARCH_OPTS)
self.mock_tenant_limit_usages.assert_called_once()
self.mock_tenant_quota_usages.assert_called_once()
self.mock_volume_snapshot_get.assert_called_once_with(
test.IsHttpRequest(), str(snapshot.id))
self.mock_extension_supported.assert_called_once_with(
@ -599,7 +583,7 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
image_id=None, availability_zone=None, source_volid=None)
@test.create_mocks({
quotas: ['tenant_limit_usages'],
quotas: ['tenant_quota_usages'],
api.glance: ['image_list_detailed'],
cinder: ['volume_snapshot_get',
'volume_type_list',
@ -607,10 +591,6 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
'volume_get'],
})
def test_create_volume_from_snapshot_invalid_size(self):
usage_limit = {'maxTotalVolumeGigabytes': 100,
'totalGigabytesUsed': 20,
'totalVolumesUsed': len(self.cinder_volumes.list()),
'maxTotalVolumes': 6}
snapshot = self.cinder_volume_snapshots.first()
formData = {'name': u'A Volume I Am Making',
'description': u'This is a volume I am making for a test.',
@ -621,7 +601,8 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
self.cinder_volume_types.list()
self.mock_volume_type_default.return_value = \
self.cinder_volume_types.first()
self.mock_tenant_limit_usages.return_value = usage_limit
self.mock_tenant_quota_usages.return_value = \
self.cinder_quota_usages.first()
self.mock_volume_snapshot_get.return_value = snapshot
self.mock_volume_get.return_value = self.cinder_volumes.first()
@ -642,7 +623,7 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
snapshot.volume_id)
@test.create_mocks({
quotas: ['tenant_limit_usages'],
quotas: ['tenant_quota_usages'],
api.glance: ['image_get'],
cinder: ['extension_supported',
'availability_zone_list',
@ -652,10 +633,6 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
})
def test_create_volume_from_image(self):
volume = self.cinder_volumes.first()
usage_limit = {'maxTotalVolumeGigabytes': 200,
'totalGigabytesUsed': 20,
'totalVolumesUsed': len(self.cinder_volumes.list()),
'maxTotalVolumes': 6}
image = self.images.first()
formData = {'name': u'A Volume I Am Making',
'description': u'This is a volume I am making for a test.',
@ -667,7 +644,8 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
self.mock_volume_type_default.return_value = \
self.cinder_volume_types.first()
self.mock_volume_type_list.ret = self.cinder_volume_types.list()
self.mock_tenant_limit_usages.return_value = usage_limit
self.mock_tenant_quota_usages.return_value = \
self.cinder_quota_usages.first()
self.mock_image_get.return_value = image
self.mock_extension_supported.return_value = True
self.mock_availability_zone_list.return_value = \
@ -686,7 +664,7 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
self.mock_volume_type_default.assert_called_once()
self.mock_volume_type_list.assert_called_once()
self.mock_tenant_limit_usages.assert_called_once()
self.mock_tenant_quota_usages.assert_called_once()
self.mock_image_get.assert_called_once_with(test.IsHttpRequest(),
str(image.id))
self.mock_extension_supported.assert_called_once_with(
@ -698,7 +676,7 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
image_id=image.id, availability_zone=None, source_volid=None)
@test.create_mocks({
quotas: ['tenant_limit_usages'],
quotas: ['tenant_quota_usages'],
api.glance: ['image_list_detailed',
'image_get'],
cinder: ['extension_supported',
@ -711,10 +689,6 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
})
def test_create_volume_from_image_dropdown(self):
volume = self.cinder_volumes.first()
usage_limit = {'maxTotalVolumeGigabytes': 200,
'totalGigabytesUsed': 20,
'totalVolumesUsed': len(self.cinder_volumes.list()),
'maxTotalVolumes': 6}
image = self.images.first()
formData = {'name': u'A Volume I Am Making',
'description': u'This is a volume I am making for a test.',
@ -734,7 +708,8 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
self.mock_volume_type_default.return_value = \
self.cinder_volume_types.first()
self.mock_volume_list.return_value = self.cinder_volumes.list()
self.mock_tenant_limit_usages.return_value = usage_limit
self.mock_tenant_quota_usages.return_value = \
self.cinder_quota_usages.first()
self.mock_image_get.return_value = image
self.mock_extension_supported.return_value = True
self.mock_availability_zone_list.return_value = \
@ -758,7 +733,7 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
self.mock_volume_type_default.assert_called_once()
self.mock_volume_list.assert_called_once_with(test.IsHttpRequest(),
search_opts=SEARCH_OPTS)
self.mock_tenant_limit_usages.assert_called_once()
self.mock_tenant_quota_usages.assert_called_once()
self.mock_image_get.assert_called_with(test.IsHttpRequest(),
str(image.id))
self.mock_extension_supported.assert_called_once_with(
@ -770,7 +745,7 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
image_id=image.id, availability_zone=None, source_volid=None)
@test.create_mocks({
quotas: ['tenant_limit_usages'],
quotas: ['tenant_quota_usages'],
api.glance: ['image_get'],
cinder: ['extension_supported',
'availability_zone_list',
@ -778,10 +753,6 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
'volume_type_default'],
})
def test_create_volume_from_image_under_image_size(self):
usage_limit = {'maxTotalVolumeGigabytes': 100,
'totalGigabytesUsed': 20,
'totalVolumesUsed': len(self.cinder_volumes.list()),
'maxTotalVolumes': 6}
image = self.images.first()
formData = {'name': u'A Volume I Am Making',
'description': u'This is a volume I am making for a test.',
@ -792,7 +763,8 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
self.cinder_volume_types.list()
self.mock_volume_type_default.return_value = \
self.cinder_volume_types.first()
self.mock_tenant_limit_usages.return_value = usage_limit
self.mock_tenant_quota_usages.return_value = \
self.cinder_quota_usages.first()
self.mock_image_get.return_value = image
self.mock_extension_supported.return_value = True
@ -810,14 +782,14 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
self.assertEqual(3, self.mock_volume_type_list.call_count)
self.assertEqual(2, self.mock_volume_type_default.call_count)
self.assertEqual(2, self.mock_tenant_limit_usages.call_count)
self.assertEqual(2, self.mock_tenant_quota_usages.call_count)
self.mock_image_get.assert_called_with(test.IsHttpRequest(),
str(image.id))
self.mock_extension_supported.assert_called_with(test.IsHttpRequest(),
'AvailabilityZones')
@test.create_mocks({
quotas: ['tenant_limit_usages'],
quotas: ['tenant_quota_usages'],
api.glance: ['image_get'],
cinder: ['extension_supported',
'availability_zone_list',
@ -825,10 +797,6 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
'volume_type_default'],
})
def _test_create_volume_from_image_under_image_min_disk_size(self, image):
usage_limit = {'maxTotalVolumeGigabytes': 100,
'totalGigabytesUsed': 20,
'totalVolumesUsed': len(self.cinder_volumes.list()),
'maxTotalVolumes': 6}
formData = {'name': u'A Volume I Am Making',
'description': u'This is a volume I am making for a test.',
'method': u'CreateForm',
@ -838,7 +806,8 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
self.cinder_volume_types.list()
self.mock_volume_type_default.return_value = \
self.cinder_volume_types.first()
self.mock_tenant_limit_usages.return_value = usage_limit
self.mock_tenant_quota_usages.return_value = \
self.cinder_quota_usages.first()
self.mock_image_get.return_value = image
self.mock_extension_supported.return_value = True
self.mock_availability_zone_list.return_value = \
@ -878,7 +847,7 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
self._test_create_volume_from_image_under_image_min_disk_size(image)
@test.create_mocks({
quotas: ['tenant_limit_usages'],
quotas: ['tenant_quota_usages'],
api.glance: ['image_list_detailed'],
cinder: ['extension_supported',
'availability_zone_list',
@ -888,20 +857,22 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
'volume_snapshot_list'],
})
def test_create_volume_gb_used_over_alloted_quota(self):
usage_limit = {'maxTotalVolumeGigabytes': 100,
'totalGigabytesUsed': 80,
'totalVolumesUsed': len(self.cinder_volumes.list()),
'maxTotalVolumes': 6}
formData = {'name': u'This Volume Is Huge!',
'description': u'This is a volume that is just too big!',
'method': u'CreateForm',
'size': 5000}
usage_limit = self.cinder_quota_usages.first()
usage_limit.add_quota(api.base.Quota('volumes', 6))
usage_limit.tally('volumes', len(self.cinder_volumes.list()))
usage_limit.add_quota(api.base.Quota('gigabytes', 100))
usage_limit.tally('gigabytes', 80)
self.mock_volume_type_list.return_value = \
self.cinder_volume_types.list()
self.mock_volume_type_default.return_value = \
self.cinder_volume_types.first()
self.mock_tenant_limit_usages.return_value = usage_limit
self.mock_tenant_quota_usages.return_value = usage_limit
self.mock_volume_snapshot_list.return_value = \
self.cinder_volume_snapshots.list()
self.mock_image_list_detailed.return_value = [self.images.list(),
@ -923,7 +894,7 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
self.assertEqual(2, self.mock_volume_list.call_count)
self.assertEqual(2, self.mock_availability_zone_list.call_count)
self.assertEqual(2, self.mock_tenant_limit_usages.call_count)
self.assertEqual(2, self.mock_tenant_quota_usages.call_count)
self.mock_volume_snapshot_list.assert_called_with(
test.IsHttpRequest(), search_opts=SEARCH_OPTS)
self.mock_image_list_detailed.assert_called_with(
@ -933,7 +904,7 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
'AvailabilityZones')
@test.create_mocks({
quotas: ['tenant_limit_usages'],
quotas: ['tenant_quota_usages'],
api.glance: ['image_list_detailed'],
cinder: ['extension_supported',
'availability_zone_list',
@ -943,20 +914,23 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
'volume_snapshot_list'],
})
def test_create_volume_number_over_alloted_quota(self):
usage_limit = {'maxTotalVolumeGigabytes': 100,
'totalGigabytesUsed': 20,
'totalVolumesUsed': len(self.cinder_volumes.list()),
'maxTotalVolumes': len(self.cinder_volumes.list())}
formData = {'name': u'Too Many...',
'description': u'We have no volumes left!',
'method': u'CreateForm',
'size': 10}
usage_limit = self.cinder_quota_usages.first()
usage_limit.add_quota(api.base.Quota('volumes',
len(self.cinder_volumes.list())))
usage_limit.tally('volumes', len(self.cinder_volumes.list()))
usage_limit.add_quota(api.base.Quota('gigabytes', 100))
usage_limit.tally('gigabytes', 20)
self.mock_volume_type_list.return_value = \
self.cinder_volume_types.list()
self.mock_volume_type_default.return_value = \
self.cinder_volume_types.first()
self.mock_tenant_limit_usages.return_value = usage_limit
self.mock_tenant_quota_usages.return_value = usage_limit
self.mock_volume_snapshot_list.return_value = \
self.cinder_volume_snapshots.list()
self.mock_image_list_detailed.return_value = [self.images.list(),
@ -1587,21 +1561,17 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
form_data['container_format'],
form_data['disk_format'])
@mock.patch.object(quotas, 'tenant_limit_usages')
@mock.patch.object(quotas, 'tenant_quota_usages')
@mock.patch.object(cinder, 'volume_extend')
@mock.patch.object(cinder, 'volume_get')
def test_extend_volume(self, mock_get, mock_extend, mock_quotas):
volume = self.cinder_volumes.first()
usage_limit = {'maxTotalVolumeGigabytes': 100,
'totalGigabytesUsed': 20,
'totalVolumesUsed': len(self.volumes.list()),
'maxTotalVolumes': 6}
formData = {'name': u'A Volume I Am Making',
'orig_size': volume.size,
'new_size': 120}
mock_get.return_value = volume
mock_quotas.return_value = usage_limit
mock_quotas.return_value = self.cinder_quota_usages.first()
mock_extend.return_value = volume
url = reverse('horizon:project:volumes:extend',
@ -1616,20 +1586,16 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
mock_extend.assert_called_once_with(test.IsHttpRequest(), volume.id,
formData['new_size'])
@mock.patch.object(quotas, 'tenant_limit_usages')
@mock.patch.object(quotas, 'tenant_quota_usages')
@mock.patch.object(cinder, 'volume_get')
def test_extend_volume_with_wrong_size(self, mock_get, mock_quotas):
volume = self.cinder_volumes.first()
usage_limit = {'maxTotalVolumeGigabytes': 100,
'totalGigabytesUsed': 20,
'totalVolumesUsed': len(self.volumes.list()),
'maxTotalVolumes': 6}
formData = {'name': u'A Volume I Am Making',
'orig_size': volume.size,
'new_size': 10}
mock_get.return_value = volume
mock_quotas.return_value = usage_limit
mock_quotas.return_value = self.cinder_quota_usages.first()
url = reverse('horizon:project:volumes:extend',
args=[volume.id])
@ -1743,14 +1709,15 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
test.IsHttpRequest(), search_opts=None)
self.assertEqual(10, self.mock_tenant_absolute_limits.call_count)
@mock.patch.object(quotas, 'tenant_limit_usages')
@mock.patch.object(quotas, 'tenant_quota_usages')
@mock.patch.object(cinder, 'volume_get')
def test_extend_volume_with_size_out_of_quota(self, mock_get, mock_quotas):
volume = self.volumes.first()
usage_limit = {'maxTotalVolumeGigabytes': 100,
'totalGigabytesUsed': 20,
'totalVolumesUsed': len(self.volumes.list()),
'maxTotalVolumes': 6}
usage_limit = self.cinder_quota_usages.first()
usage_limit.add_quota(api.base.Quota('gigabytes', 100))
usage_limit.tally('gigabytes', 20)
usage_limit.tally('volumes', len(self.volumes.list()))
formData = {'name': u'A Volume I Am Making',
'orig_size': volume.size,
'new_size': 1000}

View File

@ -221,7 +221,8 @@ class CreateView(forms.ModalFormView):
def get_context_data(self, **kwargs):
context = super(CreateView, self).get_context_data(**kwargs)
try:
context['usages'] = quotas.tenant_limit_usages(self.request)
context['usages'] = quotas.tenant_quota_usages(
self.request, targets=('volumes', 'gigabytes'))
context['volume_types'] = self._get_volume_types()
except Exception:
exceptions.handle(self.request)
@ -279,9 +280,9 @@ class ExtendView(forms.ModalFormView):
args = (self.kwargs['volume_id'],)
context['submit_url'] = reverse(self.submit_url, args=args)
try:
usages = quotas.tenant_limit_usages(self.request)
usages['totalGigabytesUsed'] = (usages['totalGigabytesUsed'] -
context['volume'].size)
usages = quotas.tenant_quota_usages(self.request,
targets=('gigabytes',))
usages.tally('gigabytes', - context['volume'].size)
context['usages'] = usages
except Exception:
exceptions.handle(self.request)
@ -316,7 +317,8 @@ class CreateSnapshotView(forms.ModalFormView):
"snapshot from an attached "
"volume can result in a "
"corrupted snapshot."))
context['usages'] = quotas.tenant_limit_usages(self.request)
context['usages'] = quotas.tenant_quota_usages(
self.request, targets=('snapshots', 'gigabytes'))
except Exception:
exceptions.handle(self.request,
_('Unable to retrieve volume information.'))

View File

@ -341,32 +341,6 @@ class QuotaTests(test.APITestCase):
test.IsHttpRequest(),
_("Unable to retrieve volume limit information."))
@test.create_mocks({api.base: ('is_service_enabled',),
cinder: ('tenant_absolute_limits',
'is_volume_service_enabled'),
exceptions: ('handle',)})
def test_tenant_limit_usages_cinder_exception(self):
self.mock_is_service_enabled.retrieve = False
self.mock_is_volume_service_enabled.return_value = True
self.mock_tenant_absolute_limits.side_effect = \
cinder.cinder_exception.ClientException('test')
quotas.tenant_limit_usages(self.request)
self.mock_is_service_enabled.assert_called_once_with(
test.IsHttpRequest(), 'compute')
self.mock_is_volume_service_enabled.assert_called_once_with(
test.IsHttpRequest())
self.mock_tenant_absolute_limits.assert_called_once_with(
test.IsHttpRequest())
self.mock_handle.assert_has_calls([
mock.call(test.IsHttpRequest(),
_("Unable to retrieve compute limit information.")),
mock.call(test.IsHttpRequest(),
_("Unable to retrieve volume limit information.")),
])
self.assertEqual(2, self.mock_handle.call_count)
@test.create_mocks({api.neutron: ('is_router_enabled',
'is_extension_supported',
'is_quotas_extension_supported',),

View File

@ -391,9 +391,6 @@ def _get_tenant_volume_usages(request, usages, disabled_quotas, tenant_id):
disabled_quotas)
# TODO(amotoki): Merge tenant_quota_usages and tenant_limit_usages.
# These two functions are similar. There seems no reason to have both.
@profiler.trace
@memoized
def tenant_quota_usages(request, tenant_id=None, targets=None):
@ -429,35 +426,6 @@ def tenant_quota_usages(request, tenant_id=None, targets=None):
return usages
@profiler.trace
def tenant_limit_usages(request):
# TODO(licostan): This method shall be removed from Quota module.
# ProjectUsage/BaseUsage maybe used instead on volume/image dashboards.
limits = {}
try:
if base.is_service_enabled(request, 'compute'):
limits.update(nova.tenant_absolute_limits(request, reserved=True))
except Exception:
msg = _("Unable to retrieve compute limit information.")
exceptions.handle(request, msg)
if cinder.is_volume_service_enabled(request):
try:
limits.update(cinder.tenant_absolute_limits(request))
except cinder.cinder_exception.ClientException:
msg = _("Unable to retrieve volume limit information.")
exceptions.handle(request, msg)
# TODO(amotoki): Support neutron quota details extensions
# which returns limit/usage/reserved per resource.
# Note that the data format is different from nova/cinder limit API.
# https://developer.openstack.org/
# api-ref/network/v2/#quotas-details-extension-quota-details
return limits
def enabled_quotas(request):
"""Returns the list of quotas available minus those that are disabled"""
return QUOTA_FIELDS - get_disabled_quotas(request)