View and update Neutron project quotas
Also ensure that the correct quota is displayed in the Floating IPs allocation page (Security & Access panel). Closes-Bug: #1109140 Change-Id: I30d207fbf149bfbcfefeaddf91af49082b7b1f53
This commit is contained in:
parent
065786c745
commit
3852d1ce19
|
@ -176,6 +176,19 @@ class QuotaSet(Sequence):
|
|||
def __getitem__(self, index):
|
||||
return self.items[index]
|
||||
|
||||
def __add__(self, other):
|
||||
'''Merge another QuotaSet into this one. Existing quotas are
|
||||
not overriden.'''
|
||||
if not isinstance(other, QuotaSet):
|
||||
msg = "Can only add QuotaSet to QuotaSet, " \
|
||||
"but received %s instead" % type(other)
|
||||
raise ValueError(msg)
|
||||
|
||||
for item in other:
|
||||
if self.get(item.name).limit is None:
|
||||
self.items.append(item)
|
||||
return self
|
||||
|
||||
def __len__(self):
|
||||
return len(self.items)
|
||||
|
||||
|
@ -186,6 +199,9 @@ class QuotaSet(Sequence):
|
|||
match = [quota for quota in self.items if quota.name == key]
|
||||
return match.pop() if len(match) else Quota(key, default)
|
||||
|
||||
def add(self, other):
|
||||
return self.__add__(other)
|
||||
|
||||
|
||||
def get_service_from_catalog(catalog, service_type):
|
||||
if catalog:
|
||||
|
|
|
@ -608,6 +608,11 @@ def tenant_quota_get(request, tenant_id):
|
|||
return base.QuotaSet(neutronclient(request).show_quota(tenant_id)['quota'])
|
||||
|
||||
|
||||
def tenant_quota_update(request, tenant_id, **kwargs):
|
||||
quotas = {'quota': kwargs}
|
||||
return neutronclient(request).update_quota(tenant_id, quotas)
|
||||
|
||||
|
||||
def list_extensions(request):
|
||||
extensions_list = neutronclient(request).list_extensions()
|
||||
if 'extensions' in extensions_list:
|
||||
|
@ -624,3 +629,12 @@ def is_extension_supported(request, extension_alias):
|
|||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def is_quotas_extension_supported(request):
|
||||
network_config = getattr(settings, 'OPENSTACK_NEUTRON_NETWORK', {})
|
||||
if network_config.get('enable_quotas', False) and \
|
||||
is_extension_supported(request, 'quotas'):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
|
|
@ -96,7 +96,7 @@ class SystemInfoViewTests(test.BaseAdminViewTests):
|
|||
api.base.is_service_enabled(IsA(http.HttpRequest), 'volume') \
|
||||
.AndReturn(True)
|
||||
api.base.is_service_enabled(IsA(http.HttpRequest), 'network') \
|
||||
.AndReturn(False)
|
||||
.MultipleTimes().AndReturn(False)
|
||||
|
||||
api.nova.default_quota_get(IsA(http.HttpRequest),
|
||||
self.tenant.id).AndReturn(self.quotas.nova)
|
||||
|
|
|
@ -18,6 +18,7 @@ import logging
|
|||
|
||||
from django.core.urlresolvers import reverse # noqa
|
||||
from django import http
|
||||
from django.test.utils import override_settings # noqa
|
||||
|
||||
from mox import IsA # noqa
|
||||
|
||||
|
@ -84,11 +85,14 @@ class CreateProjectWorkflowTests(test.BaseAdminViewTests):
|
|||
|
||||
def _get_quota_info(self, quota):
|
||||
cinder_quota = self.cinder_quotas.first()
|
||||
neutron_quota = self.neutron_quotas.first()
|
||||
quota_data = {}
|
||||
for field in quotas.NOVA_QUOTA_FIELDS:
|
||||
quota_data[field] = int(quota.get(field).limit)
|
||||
for field in quotas.CINDER_QUOTA_FIELDS:
|
||||
quota_data[field] = int(cinder_quota.get(field).limit)
|
||||
for field in quotas.NEUTRON_QUOTA_FIELDS:
|
||||
quota_data[field] = int(neutron_quota.get(field).limit)
|
||||
return quota_data
|
||||
|
||||
def _get_workflow_data(self, project, quota):
|
||||
|
@ -147,6 +151,8 @@ class CreateProjectWorkflowTests(test.BaseAdminViewTests):
|
|||
res = self.client.get(url)
|
||||
|
||||
self.assertTemplateUsed(res, views.WorkflowView.template_name)
|
||||
self.assertContains(res, '<input type="hidden" name="subnet" '
|
||||
'id="id_subnet" />', html=True)
|
||||
|
||||
workflow = res.context['workflow']
|
||||
self.assertEqual(res.context['workflow'].name,
|
||||
|
@ -168,6 +174,52 @@ class CreateProjectWorkflowTests(test.BaseAdminViewTests):
|
|||
domain_context_name=domain.name)
|
||||
self.test_add_project_get()
|
||||
|
||||
@test.create_stubs({api.keystone: ('get_default_role',
|
||||
'user_list',
|
||||
'group_list',
|
||||
'role_list'),
|
||||
api.neutron: ('is_extension_supported',
|
||||
'tenant_quota_get'),
|
||||
quotas: ('get_default_quota_data',)})
|
||||
@override_settings(OPENSTACK_NEUTRON_NETWORK={'enable_quotas': True})
|
||||
def test_add_project_get_with_neutron(self):
|
||||
quota = self.quotas.first()
|
||||
neutron_quotas = self.neutron_quotas.first()
|
||||
|
||||
quotas.get_default_quota_data(IsA(http.HttpRequest)) \
|
||||
.AndReturn(quota)
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest), 'quotas') \
|
||||
.MultipleTimes().AndReturn(True)
|
||||
api.neutron.tenant_quota_get(IsA(http.HttpRequest),
|
||||
tenant_id=self.tenant.id) \
|
||||
.AndReturn(neutron_quotas)
|
||||
api.keystone.get_default_role(IsA(http.HttpRequest)) \
|
||||
.MultipleTimes().AndReturn(self.roles.first())
|
||||
api.keystone.user_list(IsA(http.HttpRequest), domain=None) \
|
||||
.AndReturn(self.users.list())
|
||||
api.keystone.role_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.roles.list())
|
||||
api.keystone.group_list(IsA(http.HttpRequest), domain=None) \
|
||||
.AndReturn(self.groups.list())
|
||||
api.keystone.role_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.roles.list())
|
||||
self.mox.ReplayAll()
|
||||
|
||||
res = self.client.get(reverse('horizon:admin:projects:create'))
|
||||
|
||||
self.assertTemplateUsed(res, views.WorkflowView.template_name)
|
||||
self.assertContains(res, '<input name="subnet" id="id_subnet" '
|
||||
'value="10" type="text" />', html=True)
|
||||
|
||||
workflow = res.context['workflow']
|
||||
self.assertEqual(res.context['workflow'].name,
|
||||
workflows.CreateProject.name)
|
||||
|
||||
step = workflow.get_step("createprojectinfoaction")
|
||||
self.assertEqual(step.action.initial['ram'], quota.get('ram').limit)
|
||||
self.assertEqual(step.action.initial['subnet'],
|
||||
neutron_quotas.get('subnet').limit)
|
||||
|
||||
@test.create_stubs({api.keystone: ('get_default_role',
|
||||
'add_tenant_user_role',
|
||||
'tenant_create',
|
||||
|
@ -250,6 +302,21 @@ class CreateProjectWorkflowTests(test.BaseAdminViewTests):
|
|||
domain_context_name=domain.name)
|
||||
self.test_add_project_post()
|
||||
|
||||
@test.create_stubs({api.neutron: ('is_extension_supported',
|
||||
'tenant_quota_update')})
|
||||
@override_settings(OPENSTACK_NEUTRON_NETWORK={'enable_quotas': True})
|
||||
def test_add_project_post_with_neutron(self):
|
||||
quota_data = self.neutron_quotas.first()
|
||||
neutron_updated_quota = dict([(key, quota_data.get(key).limit)
|
||||
for key in quotas.NEUTRON_QUOTA_FIELDS])
|
||||
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest), 'quotas') \
|
||||
.MultipleTimes().AndReturn(True)
|
||||
api.neutron.tenant_quota_update(IsA(http.HttpRequest),
|
||||
self.tenant.id,
|
||||
**neutron_updated_quota)
|
||||
self.test_add_project_post()
|
||||
|
||||
@test.create_stubs({api.keystone: ('user_list',
|
||||
'role_list',
|
||||
'group_list',
|
||||
|
@ -539,11 +606,14 @@ class CreateProjectWorkflowTests(test.BaseAdminViewTests):
|
|||
class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
|
||||
def _get_quota_info(self, quota):
|
||||
cinder_quota = self.cinder_quotas.first()
|
||||
neutron_quota = self.neutron_quotas.first()
|
||||
quota_data = {}
|
||||
for field in quotas.NOVA_QUOTA_FIELDS:
|
||||
quota_data[field] = int(quota.get(field).limit)
|
||||
for field in quotas.CINDER_QUOTA_FIELDS:
|
||||
quota_data[field] = int(cinder_quota.get(field).limit)
|
||||
for field in quotas.NEUTRON_QUOTA_FIELDS:
|
||||
quota_data[field] = int(neutron_quota.get(field).limit)
|
||||
return quota_data
|
||||
|
||||
def _get_domain_id(self):
|
||||
|
@ -845,6 +915,25 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
|
|||
domain_context_name=domain.name)
|
||||
self.test_update_project_save()
|
||||
|
||||
@test.create_stubs({api.neutron: ('is_extension_supported',
|
||||
'tenant_quota_get',
|
||||
'tenant_quota_update')})
|
||||
@override_settings(OPENSTACK_NEUTRON_NETWORK={'enable_quotas': True})
|
||||
def test_update_project_save_with_neutron(self):
|
||||
quota_data = self.neutron_quotas.first()
|
||||
neutron_updated_quota = dict([(key, quota_data.get(key).limit)
|
||||
for key in quotas.NEUTRON_QUOTA_FIELDS])
|
||||
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest), 'quotas') \
|
||||
.MultipleTimes().AndReturn(True)
|
||||
api.neutron.tenant_quota_get(IsA(http.HttpRequest),
|
||||
tenant_id=self.tenant.id) \
|
||||
.AndReturn(quota_data)
|
||||
api.neutron.tenant_quota_update(IsA(http.HttpRequest),
|
||||
self.tenant.id,
|
||||
**neutron_updated_quota)
|
||||
self.test_update_project_save()
|
||||
|
||||
@test.create_stubs({api.keystone: ('tenant_get',)})
|
||||
def test_update_project_get_error(self):
|
||||
|
||||
|
|
|
@ -109,6 +109,22 @@ class CreateProjectView(workflows.WorkflowView):
|
|||
# get initial quota defaults
|
||||
try:
|
||||
quota_defaults = quotas.get_default_quota_data(self.request)
|
||||
|
||||
try:
|
||||
if api.base.is_service_enabled(self.request, 'network') and \
|
||||
api.neutron.is_quotas_extension_supported(self.request):
|
||||
# TODO(jpichon): There is no API to access the Neutron
|
||||
# default quotas (LP#1204956). For now, use the values
|
||||
# from the current project.
|
||||
project_id = self.request.user.project_id
|
||||
quota_defaults += api.neutron.tenant_quota_get(
|
||||
self.request,
|
||||
tenant_id=project_id)
|
||||
except Exception:
|
||||
error_msg = _('Unable to retrieve default Neutron quota '
|
||||
'values.')
|
||||
self.add_error_to_step(error_msg, 'update_quotas')
|
||||
|
||||
for field in quotas.QUOTA_FIELDS:
|
||||
initial[field] = quota_defaults.get(field).limit
|
||||
|
||||
|
@ -138,6 +154,10 @@ class UpdateProjectView(workflows.WorkflowView):
|
|||
# get initial project quota
|
||||
quota_data = quotas.get_tenant_quota_data(self.request,
|
||||
tenant_id=project_id)
|
||||
if api.base.is_service_enabled(self.request, 'network') and \
|
||||
api.neutron.is_quotas_extension_supported(self.request):
|
||||
quota_data += api.neutron.tenant_quota_get(self.request,
|
||||
tenant_id=project_id)
|
||||
for field in quotas.QUOTA_FIELDS:
|
||||
initial[field] = quota_data.get(field).limit
|
||||
except Exception:
|
||||
|
|
|
@ -63,6 +63,13 @@ class UpdateProjectQuotaAction(workflows.Action):
|
|||
security_group_rules = forms.IntegerField(min_value=-1,
|
||||
label=_("Security Group Rules"))
|
||||
|
||||
# Neutron
|
||||
floatingip = forms.IntegerField(min_value=-1, label=_("Floating IPs"))
|
||||
network = forms.IntegerField(min_value=-1, label=_("Networks"))
|
||||
port = forms.IntegerField(min_value=-1, label=_("Ports"))
|
||||
router = forms.IntegerField(min_value=-1, label=_("Routers"))
|
||||
subnet = forms.IntegerField(min_value=-1, label=_("Subnets"))
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
super(UpdateProjectQuotaAction, self).__init__(request,
|
||||
*args,
|
||||
|
@ -418,6 +425,14 @@ class CreateProject(workflows.Workflow):
|
|||
cinder.tenant_quota_update(request,
|
||||
project_id,
|
||||
**cinder_data)
|
||||
|
||||
if api.base.is_service_enabled(request, 'network') and \
|
||||
api.neutron.is_quotas_extension_supported(request):
|
||||
neutron_data = dict([(key, data[key]) for key in
|
||||
quotas.NEUTRON_QUOTA_FIELDS])
|
||||
api.neutron.tenant_quota_update(request,
|
||||
project_id,
|
||||
**neutron_data)
|
||||
except Exception:
|
||||
exceptions.handle(request, _('Unable to set project quotas.'))
|
||||
return True
|
||||
|
@ -667,6 +682,14 @@ class UpdateProject(workflows.Workflow):
|
|||
cinder.tenant_quota_update(request,
|
||||
project_id,
|
||||
**cinder_data)
|
||||
|
||||
if api.base.is_service_enabled(request, 'network') and \
|
||||
api.neutron.is_quotas_extension_supported(request):
|
||||
neutron_data = dict([(key, data[key]) for key in
|
||||
quotas.NEUTRON_QUOTA_FIELDS])
|
||||
api.neutron.tenant_quota_update(request,
|
||||
project_id,
|
||||
**neutron_data)
|
||||
return True
|
||||
except Exception:
|
||||
exceptions.handle(request, _('Modified project information and '
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
from django.core.urlresolvers import reverse # noqa
|
||||
from django import http
|
||||
from django.test.utils import override_settings # noqa
|
||||
|
||||
from mox import IsA # noqa
|
||||
|
||||
|
@ -175,3 +176,43 @@ class FloatingIpNeutronViewTests(FloatingIpViewTests):
|
|||
def tearDown(self):
|
||||
self.floating_ips = self._floating_ips_orig
|
||||
super(FloatingIpViewTests, self).tearDown()
|
||||
|
||||
@test.create_stubs({api.nova: ('tenant_quota_get', 'flavor_list',
|
||||
'server_list'),
|
||||
api.cinder: ('tenant_quota_get', 'volume_list',
|
||||
'volume_snapshot_list',),
|
||||
api.network: ('floating_ip_pools_list',
|
||||
'tenant_floating_ip_list'),
|
||||
api.neutron: ('is_extension_supported',
|
||||
'tenant_quota_get')})
|
||||
@override_settings(OPENSTACK_NEUTRON_NETWORK={'enable_quotas': True})
|
||||
def test_correct_quotas_displayed(self):
|
||||
servers = [s for s in self.servers.list()
|
||||
if s.tenant_id == self.request.user.tenant_id]
|
||||
|
||||
api.nova.tenant_quota_get(IsA(http.HttpRequest), '1') \
|
||||
.AndReturn(self.quotas.first())
|
||||
api.nova.flavor_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.flavors.list())
|
||||
api.nova.server_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn([servers, False])
|
||||
api.cinder.volume_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.volumes.list())
|
||||
api.cinder.volume_snapshot_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.snapshots.list())
|
||||
api.cinder.tenant_quota_get(IsA(http.HttpRequest), '1') \
|
||||
.AndReturn(self.cinder_quotas.first())
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest), 'quotas') \
|
||||
.AndReturn(True)
|
||||
api.neutron.tenant_quota_get(IsA(http.HttpRequest), self.tenant.id) \
|
||||
.AndReturn(self.neutron_quotas.first())
|
||||
api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
.MultipleTimes().AndReturn(self.floating_ips.list())
|
||||
api.network.floating_ip_pools_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.pools.list())
|
||||
self.mox.ReplayAll()
|
||||
|
||||
url = reverse('%s:allocate' % NAMESPACE)
|
||||
res = self.client.get(url)
|
||||
self.assertEqual(res.context['usages']['floating_ips']['quota'],
|
||||
self.neutron_quotas.first().get('floatingip').limit)
|
||||
|
|
|
@ -169,3 +169,47 @@ class ApiHelperTests(test.TestCase):
|
|||
self.request.user.services_region = "bogus_value"
|
||||
with self.assertRaises(exceptions.ServiceCatalogException):
|
||||
url = api_base.url_for(self.request, 'image')
|
||||
|
||||
|
||||
class QuotaSetTests(test.TestCase):
|
||||
|
||||
def test_quotaset_add_with_plus(self):
|
||||
quota_dict = {'foo': 1, 'bar': 10}
|
||||
other_quota_dict = {'my_test': 12}
|
||||
quota_set = api_base.QuotaSet(quota_dict)
|
||||
other_quota_set = api_base.QuotaSet(other_quota_dict)
|
||||
|
||||
quota_set += other_quota_set
|
||||
self.assertEqual(len(quota_set), 3)
|
||||
|
||||
quota_dict.update(other_quota_dict)
|
||||
for q in quota_set:
|
||||
self.assertEqual(q.limit, quota_dict[q.name])
|
||||
|
||||
def test_quotaset_add_doesnt_override_existing_quota(self):
|
||||
quota_dict = {'foo': 1, 'bar': 10}
|
||||
quota_set = api_base.QuotaSet(quota_dict)
|
||||
other_quota_set = api_base.QuotaSet({'foo': 12})
|
||||
|
||||
quota_set += other_quota_set
|
||||
self.assertEqual(len(quota_set), 2)
|
||||
|
||||
for q in quota_set:
|
||||
self.assertEqual(q.limit, quota_dict[q.name])
|
||||
|
||||
def test_quotaset_add_method(self):
|
||||
quota_dict = {'foo': 1, 'bar': 10}
|
||||
other_quota_dict = {'my_test': 12}
|
||||
quota_set = api_base.QuotaSet(quota_dict)
|
||||
other_quota_set = api_base.QuotaSet(other_quota_dict)
|
||||
|
||||
quota_set.add(other_quota_set)
|
||||
self.assertEqual(len(quota_set), 3)
|
||||
|
||||
quota_dict.update(other_quota_dict)
|
||||
for q in quota_set:
|
||||
self.assertEqual(q.limit, quota_dict[q.name])
|
||||
|
||||
def test_quotaset_add_with_wrong_type(self):
|
||||
quota_set = api_base.QuotaSet({'foo': 1, 'bar': 10})
|
||||
self.assertRaises(ValueError, quota_set.add, {'test': 7})
|
||||
|
|
|
@ -64,6 +64,8 @@ class QuotaTests(test.APITestCase):
|
|||
|
||||
api.base.is_service_enabled(IsA(http.HttpRequest),
|
||||
'volume').AndReturn(True)
|
||||
api.base.is_service_enabled(IsA(http.HttpRequest),
|
||||
'network').AndReturn(False)
|
||||
api.nova.flavor_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.flavors.list())
|
||||
api.nova.tenant_quota_get(IsA(http.HttpRequest), '1') \
|
||||
|
@ -98,6 +100,8 @@ class QuotaTests(test.APITestCase):
|
|||
|
||||
api.base.is_service_enabled(IsA(http.HttpRequest),
|
||||
'volume').AndReturn(False)
|
||||
api.base.is_service_enabled(IsA(http.HttpRequest),
|
||||
'network').AndReturn(False)
|
||||
api.nova.flavor_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.flavors.list())
|
||||
api.nova.tenant_quota_get(IsA(http.HttpRequest), '1') \
|
||||
|
@ -123,6 +127,8 @@ class QuotaTests(test.APITestCase):
|
|||
def test_tenant_quota_usages_no_instances_running(self):
|
||||
api.base.is_service_enabled(IsA(http.HttpRequest),
|
||||
'volume').AndReturn(False)
|
||||
api.base.is_service_enabled(IsA(http.HttpRequest),
|
||||
'network').AndReturn(False)
|
||||
api.nova.flavor_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.flavors.list())
|
||||
api.nova.tenant_quota_get(IsA(http.HttpRequest), '1') \
|
||||
|
@ -160,6 +166,8 @@ class QuotaTests(test.APITestCase):
|
|||
|
||||
api.base.is_service_enabled(IsA(http.HttpRequest),
|
||||
'volume').AndReturn(True)
|
||||
api.base.is_service_enabled(IsA(http.HttpRequest),
|
||||
'network').AndReturn(False)
|
||||
api.nova.flavor_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.flavors.list())
|
||||
api.nova.tenant_quota_get(IsA(http.HttpRequest), '1') \
|
||||
|
|
|
@ -120,9 +120,7 @@ class BaseUsage(object):
|
|||
|
||||
# Quotas are an optional extension in Neutron. If it isn't
|
||||
# enabled, assume the floating IP limit is infinite.
|
||||
network_config = getattr(settings, 'OPENSTACK_NEUTRON_NETWORK', {})
|
||||
if not network_config.get('enable_quotas', False) or \
|
||||
not api.neutron.is_extension_supported(self.request, 'quotas'):
|
||||
if not api.neutron.is_quotas_extension_supported(self.request):
|
||||
self.limits['maxTotalFloatingIps'] = float("inf")
|
||||
return
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from collections import defaultdict # noqa
|
||||
import itertools
|
||||
import logging
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon.utils.memoized import memoized # noqa
|
||||
|
@ -7,8 +8,13 @@ from horizon.utils.memoized import memoized # noqa
|
|||
from openstack_dashboard.api import base
|
||||
from openstack_dashboard.api import cinder
|
||||
from openstack_dashboard.api import network
|
||||
from openstack_dashboard.api import neutron
|
||||
from openstack_dashboard.api import nova
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
NOVA_QUOTA_FIELDS = ("metadata_items",
|
||||
"cores",
|
||||
"instances",
|
||||
|
@ -24,7 +30,13 @@ CINDER_QUOTA_FIELDS = ("volumes",
|
|||
"snapshots",
|
||||
"gigabytes",)
|
||||
|
||||
QUOTA_FIELDS = NOVA_QUOTA_FIELDS + CINDER_QUOTA_FIELDS
|
||||
NEUTRON_QUOTA_FIELDS = ("network",
|
||||
"subnet",
|
||||
"port",
|
||||
"router",
|
||||
"floatingip",)
|
||||
|
||||
QUOTA_FIELDS = NOVA_QUOTA_FIELDS + CINDER_QUOTA_FIELDS + NEUTRON_QUOTA_FIELDS
|
||||
|
||||
|
||||
class QuotaUsage(dict):
|
||||
|
@ -96,16 +108,51 @@ def get_default_quota_data(request, disabled_quotas=None, tenant_id=None):
|
|||
|
||||
|
||||
def get_tenant_quota_data(request, disabled_quotas=None, tenant_id=None):
|
||||
return _get_quota_data(request,
|
||||
"tenant_quota_get",
|
||||
disabled_quotas=disabled_quotas,
|
||||
tenant_id=tenant_id)
|
||||
qs = _get_quota_data(request,
|
||||
"tenant_quota_get",
|
||||
disabled_quotas=disabled_quotas,
|
||||
tenant_id=tenant_id)
|
||||
|
||||
# TODO(jpichon): There is no API to get the default system quotas
|
||||
# in Neutron (cf. LP#1204956), so for now handle tenant quotas here.
|
||||
# This should be handled in _get_quota_data() eventually.
|
||||
if disabled_quotas and 'floating_ips' in disabled_quotas:
|
||||
# Neutron with quota extension disabled
|
||||
if 'floatingip' in disabled_quotas:
|
||||
qs.add(base.QuotaSet({'floating_ips': -1}))
|
||||
# Neutron with quota extension enabled
|
||||
else:
|
||||
tenant_id = tenant_id or request.user.tenant_id
|
||||
neutron_quotas = neutron.tenant_quota_get(request, tenant_id)
|
||||
# Rename floatingip to floating_ips since that's how it's
|
||||
# expected in some places (e.g. Security & Access' Floating IPs)
|
||||
fips_quota = neutron_quotas.get('floatingip').limit
|
||||
qs.add(base.QuotaSet({'floating_ips': fips_quota}))
|
||||
|
||||
return qs
|
||||
|
||||
|
||||
def get_disabled_quotas(request):
|
||||
disabled_quotas = []
|
||||
|
||||
# Cinder
|
||||
if not base.is_service_enabled(request, 'volume'):
|
||||
disabled_quotas.extend(CINDER_QUOTA_FIELDS)
|
||||
|
||||
# Neutron
|
||||
if not base.is_service_enabled(request, 'network'):
|
||||
disabled_quotas.extend(NEUTRON_QUOTA_FIELDS)
|
||||
else:
|
||||
# Remove the nova network quotas
|
||||
disabled_quotas.extend(['floating_ips', 'fixed_ips'])
|
||||
|
||||
try:
|
||||
if not neutron.is_quotas_extension_supported(request):
|
||||
disabled_quotas.extend(NEUTRON_QUOTA_FIELDS)
|
||||
except Exception:
|
||||
LOG.exception("There was an error checking if the Neutron "
|
||||
"quotas extension is enabled.")
|
||||
|
||||
return disabled_quotas
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue