quota: Merge tenant_limit_usages into tenant_quota_usages
The response of tenant_quota_usages is now baesd on the limit API, so tenant_limit_usages and tenant_quota_usages provide same information. This commit changes all consumers of tenant_limit_usages to use tenant_quota_usages and updates the corresponding templates. blueprint make-quotas-great-again Change-Id: I620e2946f2aca31bac134c247ceaf971498f9eeb
This commit is contained in:
parent
2e0a3610bd
commit
df780f21d7
@ -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:
|
||||
|
@ -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 %}
|
||||
|
@ -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:
|
||||
|
@ -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 %}
|
||||
|
@ -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,
|
||||
|
@ -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')
|
||||
|
@ -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')})
|
||||
|
@ -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 '
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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 %}
|
||||
|
@ -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 %}
|
||||
|
@ -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>
|
||||
|
@ -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}
|
||||
|
@ -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.'))
|
||||
|
@ -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',),
|
||||
|
@ -389,9 +389,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):
|
||||
@ -427,35 +424,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)
|
||||
|
Loading…
Reference in New Issue
Block a user