Add Octavia (LBaaS) into quota management
* Turned off by default but can be configured Change-Id: Ifa5a6e5b7a2c44cea5f799dc291c436eaa13d756 Implements: blueprint octavia-quota-service
This commit is contained in:
parent
7f33678642
commit
6508cc3804
|
@ -25,7 +25,7 @@ from adjutant.common.tests.utils import modify_dict_settings
|
|||
from adjutant.common.tests.fake_clients import (
|
||||
FakeManager, setup_identity_cache, get_fake_neutron, get_fake_novaclient,
|
||||
get_fake_cinderclient, setup_neutron_cache, neutron_cache, cinder_cache,
|
||||
nova_cache, setup_mock_caches)
|
||||
nova_cache, setup_mock_caches, get_fake_octaviaclient, octavia_cache)
|
||||
|
||||
|
||||
@mock.patch('adjutant.common.user_store.IdentityManager',
|
||||
|
@ -35,13 +35,13 @@ from adjutant.common.tests.fake_clients import (
|
|||
'openstack_clients.get_neutronclient',
|
||||
get_fake_neutron)
|
||||
@mock.patch(
|
||||
'adjutant.common.quota.get_neutronclient',
|
||||
'adjutant.common.openstack_clients.get_neutronclient',
|
||||
get_fake_neutron)
|
||||
@mock.patch(
|
||||
'adjutant.common.quota.get_novaclient',
|
||||
'adjutant.common.openstack_clients.get_novaclient',
|
||||
get_fake_novaclient)
|
||||
@mock.patch(
|
||||
'adjutant.common.quota.get_cinderclient',
|
||||
'adjutant.common.openstack_clients.get_cinderclient',
|
||||
get_fake_cinderclient)
|
||||
class ProjectSetupActionTests(TestCase):
|
||||
|
||||
|
@ -468,14 +468,17 @@ class ProjectSetupActionTests(TestCase):
|
|||
'adjutant.common.user_store.IdentityManager',
|
||||
FakeManager)
|
||||
@mock.patch(
|
||||
'adjutant.common.quota.get_neutronclient',
|
||||
'adjutant.common.openstack_clients.get_neutronclient',
|
||||
get_fake_neutron)
|
||||
@mock.patch(
|
||||
'adjutant.common.quota.get_novaclient',
|
||||
'adjutant.common.openstack_clients.get_novaclient',
|
||||
get_fake_novaclient)
|
||||
@mock.patch(
|
||||
'adjutant.common.quota.get_cinderclient',
|
||||
'adjutant.common.openstack_clients.get_cinderclient',
|
||||
get_fake_cinderclient)
|
||||
@mock.patch(
|
||||
'adjutant.common.openstack_clients.get_octaviaclient',
|
||||
get_fake_octaviaclient)
|
||||
class QuotaActionTests(TestCase):
|
||||
|
||||
def test_update_quota(self):
|
||||
|
@ -639,3 +642,107 @@ class QuotaActionTests(TestCase):
|
|||
self.assertEqual(novaquota['ram'], 655360)
|
||||
neutronquota = neutron_cache['RegionTwo']['test_project_id']['quota']
|
||||
self.assertEqual(neutronquota['network'], 10)
|
||||
|
||||
@modify_dict_settings(QUOTA_SERVICES={
|
||||
'operation': 'append',
|
||||
'key_list': ['*'],
|
||||
'value': 'octavia'
|
||||
})
|
||||
def test_update_quota_octavia(self):
|
||||
"""Tests the quota update of the octavia service"""
|
||||
project = mock.Mock()
|
||||
project.id = 'test_project_id'
|
||||
project.name = 'test_project'
|
||||
project.domain = 'default'
|
||||
project.roles = {}
|
||||
|
||||
user = mock.Mock()
|
||||
user.id = 'user_id'
|
||||
user.name = "test@example.com"
|
||||
user.email = "test@example.com"
|
||||
user.domain = 'default'
|
||||
user.password = "test_password"
|
||||
|
||||
setup_identity_cache(projects=[project], users=[user])
|
||||
setup_mock_caches('RegionOne', project.id)
|
||||
|
||||
task = Task.objects.create(
|
||||
ip_address="0.0.0.0", keystone_user={'roles': ['admin']})
|
||||
|
||||
data = {
|
||||
'project_id': 'test_project_id',
|
||||
'size': 'large',
|
||||
'domain_id': 'default',
|
||||
'regions': ['RegionOne'],
|
||||
}
|
||||
|
||||
action = UpdateProjectQuotasAction(data, task=task, order=1)
|
||||
|
||||
action.pre_approve()
|
||||
self.assertEqual(action.valid, True)
|
||||
|
||||
action.post_approve()
|
||||
self.assertEqual(action.valid, True)
|
||||
|
||||
# check the quotas were updated
|
||||
# This relies on test_settings heavily.
|
||||
cinderquota = cinder_cache['RegionOne']['test_project_id']['quota']
|
||||
self.assertEqual(cinderquota['gigabytes'], 50000)
|
||||
novaquota = nova_cache['RegionOne']['test_project_id']['quota']
|
||||
self.assertEqual(novaquota['ram'], 655360)
|
||||
neutronquota = neutron_cache['RegionOne']['test_project_id']['quota']
|
||||
self.assertEqual(neutronquota['network'], 10)
|
||||
octaviaquota = octavia_cache['RegionOne']['test_project_id']['quota']
|
||||
self.assertEqual(octaviaquota['load_balancer'], 10)
|
||||
|
||||
@modify_dict_settings(QUOTA_SERVICES={
|
||||
'operation': 'append',
|
||||
'key_list': ['*'],
|
||||
'value': 'octavia'
|
||||
})
|
||||
def test_update_quota_octavia_over_usage(self):
|
||||
"""When octavia usage is higher than new quota it won't be changed"""
|
||||
project = mock.Mock()
|
||||
project.id = 'test_project_id'
|
||||
project.name = 'test_project'
|
||||
project.domain = 'default'
|
||||
project.roles = {}
|
||||
|
||||
user = mock.Mock()
|
||||
user.id = 'user_id'
|
||||
user.name = "test@example.com"
|
||||
user.email = "test@example.com"
|
||||
user.domain = 'default'
|
||||
user.password = "test_password"
|
||||
|
||||
setup_identity_cache(projects=[project], users=[user])
|
||||
setup_mock_caches('RegionOne', project.id)
|
||||
|
||||
task = Task.objects.create(
|
||||
ip_address="0.0.0.0", keystone_user={'roles': ['admin']})
|
||||
|
||||
data = {
|
||||
'project_id': 'test_project_id',
|
||||
'size': 'small',
|
||||
'domain_id': 'default',
|
||||
'regions': ['RegionOne'],
|
||||
}
|
||||
|
||||
# setup 2 load balancers
|
||||
octavia_cache['RegionOne'][project.id]['load_balancer'] = [
|
||||
{'id': 'fake_id'},
|
||||
{'id': 'fake_id2'}]
|
||||
|
||||
action = UpdateProjectQuotasAction(data, task=task, order=1)
|
||||
|
||||
action.pre_approve()
|
||||
self.assertEqual(action.valid, False)
|
||||
|
||||
action.post_approve()
|
||||
self.assertEqual(action.valid, False)
|
||||
|
||||
# check the quotas were updated
|
||||
# This relies on test_settings heavily.
|
||||
octaviaquota = octavia_cache['RegionOne']['test_project_id']['quota']
|
||||
# Still set to default
|
||||
self.assertEqual(octaviaquota['load_balancer'], 1)
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
import mock
|
||||
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APITestCase
|
||||
|
||||
from django.conf import settings
|
||||
from django.test.utils import modify_settings
|
||||
|
@ -26,16 +25,18 @@ from adjutant.api.models import Token, Task
|
|||
from adjutant.common.tests import fake_clients
|
||||
from adjutant.common.tests.fake_clients import (
|
||||
FakeManager, setup_identity_cache, get_fake_neutron, get_fake_novaclient,
|
||||
get_fake_cinderclient, cinder_cache, nova_cache, neutron_cache,
|
||||
setup_mock_caches, setup_quota_cache, FakeResource)
|
||||
from adjutant.common.tests.utils import modify_dict_settings
|
||||
get_fake_cinderclient, get_fake_octaviaclient, cinder_cache, nova_cache,
|
||||
neutron_cache, octavia_cache, setup_mock_caches, setup_quota_cache,
|
||||
FakeResource)
|
||||
from adjutant.common.tests.utils import (
|
||||
modify_dict_settings, AdjutantAPITestCase)
|
||||
|
||||
from datetime import timedelta
|
||||
|
||||
|
||||
@mock.patch('adjutant.common.user_store.IdentityManager',
|
||||
FakeManager)
|
||||
class OpenstackAPITests(APITestCase):
|
||||
class OpenstackAPITests(AdjutantAPITestCase):
|
||||
"""
|
||||
TaskView tests specific to the openstack style urls.
|
||||
Many of the original TaskView tests are valid and need
|
||||
|
@ -421,34 +422,26 @@ class OpenstackAPITests(APITestCase):
|
|||
'adjutant.common.user_store.IdentityManager',
|
||||
FakeManager)
|
||||
@mock.patch(
|
||||
'adjutant.common.quota.get_novaclient',
|
||||
'adjutant.common.openstack_clients.get_novaclient',
|
||||
get_fake_novaclient)
|
||||
@mock.patch(
|
||||
'adjutant.common.quota.get_neutronclient',
|
||||
'adjutant.common.openstack_clients.get_neutronclient',
|
||||
get_fake_neutron)
|
||||
@mock.patch(
|
||||
'adjutant.common.quota.get_cinderclient',
|
||||
'adjutant.common.openstack_clients.get_cinderclient',
|
||||
get_fake_cinderclient)
|
||||
@mock.patch(
|
||||
'adjutant.actions.v1.resources.' +
|
||||
'openstack_clients.get_neutronclient',
|
||||
get_fake_neutron)
|
||||
@mock.patch(
|
||||
'adjutant.actions.v1.resources.' +
|
||||
'openstack_clients.get_novaclient',
|
||||
get_fake_novaclient)
|
||||
@mock.patch(
|
||||
'adjutant.actions.v1.resources.' +
|
||||
'openstack_clients.get_cinderclient',
|
||||
get_fake_cinderclient)
|
||||
class QuotaAPITests(APITestCase):
|
||||
'adjutant.common.openstack_clients.get_octaviaclient',
|
||||
get_fake_octaviaclient)
|
||||
class QuotaAPITests(AdjutantAPITestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(QuotaAPITests, self).setUp()
|
||||
setup_mock_caches('RegionOne', 'test_project_id')
|
||||
setup_mock_caches('RegionTwo', 'test_project_id')
|
||||
|
||||
def check_quota_cache(self, region_name, project_id, size):
|
||||
def check_quota_cache(self, region_name, project_id, size,
|
||||
extra_services=[]):
|
||||
"""
|
||||
Helper function to check if the global quota caches now match the size
|
||||
defined in the config
|
||||
|
@ -465,6 +458,12 @@ class QuotaAPITests(APITestCase):
|
|||
network = settings.PROJECT_QUOTA_SIZES[size]['neutron']['network']
|
||||
self.assertEqual(neutronquota['network'], network)
|
||||
|
||||
if 'octavia' in extra_services:
|
||||
octaviaquota = octavia_cache[region_name][project_id]['quota']
|
||||
load_balancer = settings.PROJECT_QUOTA_SIZES.get(
|
||||
size)['octavia']['load_balancer']
|
||||
self.assertEqual(octaviaquota['load_balancer'], load_balancer)
|
||||
|
||||
def test_update_quota_no_history(self):
|
||||
""" Update the quota size of a project with no history """
|
||||
|
||||
|
@ -1286,3 +1285,42 @@ class QuotaAPITests(APITestCase):
|
|||
self.assertEqual(
|
||||
response.data['regions'][0]['quota_change_options'],
|
||||
['small', 'medium'])
|
||||
|
||||
@modify_dict_settings(QUOTA_SERVICES={
|
||||
'operation': 'append',
|
||||
'key_list': ['*'],
|
||||
'value': 'octavia'
|
||||
})
|
||||
def test_update_quota_no_history_with_octavia(self):
|
||||
""" Update quota for octavia."""
|
||||
|
||||
project = fake_clients.FakeProject(
|
||||
name="test_project", id='test_project_id')
|
||||
|
||||
user = fake_clients.FakeUser(
|
||||
name="test@example.com", password="123", email="test@example.com")
|
||||
|
||||
setup_identity_cache(projects=[project], users=[user])
|
||||
|
||||
admin_headers = {
|
||||
'project_name': "test_project",
|
||||
'project_id': project.id,
|
||||
'roles': "project_admin,_member_,project_mod",
|
||||
'username': "test@example.com",
|
||||
'user_id': "user_id",
|
||||
'authenticated': True
|
||||
}
|
||||
|
||||
url = "/v1/openstack/quotas/"
|
||||
|
||||
data = {'size': 'medium',
|
||||
'regions': ['RegionOne']}
|
||||
|
||||
response = self.client.post(url, data,
|
||||
headers=admin_headers, format='json')
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
|
||||
# Then check to see the quotas have changed
|
||||
self.check_quota_cache(
|
||||
'RegionOne', project.id, 'medium', extra_services=['octavia'])
|
||||
|
|
|
@ -22,6 +22,7 @@ from keystoneclient import client as ks_client
|
|||
from cinderclient import client as cinderclient
|
||||
from neutronclient.v2_0 import client as neutronclient
|
||||
from novaclient import client as novaclient
|
||||
from octaviaclient.api.v2 import octavia
|
||||
|
||||
# Defined for use locally
|
||||
DEFAULT_COMPUTE_VERSION = "2"
|
||||
|
@ -79,3 +80,14 @@ def get_cinderclient(region, version=DEFAULT_VOLUME_VERSION):
|
|||
version,
|
||||
session=get_auth_session(),
|
||||
region_name=region)
|
||||
|
||||
|
||||
def get_octaviaclient(region):
|
||||
ks = get_keystoneclient()
|
||||
|
||||
service = ks.services.list(name='octavia')[0]
|
||||
endpoint = ks.endpoints.list(service=service,
|
||||
region=region, interface='public')[0]
|
||||
return octavia.OctaviaAPI(
|
||||
session=get_auth_session(),
|
||||
endpoint=endpoint.url)
|
||||
|
|
|
@ -13,8 +13,7 @@
|
|||
# under the License.
|
||||
|
||||
|
||||
from adjutant.common.openstack_clients import (
|
||||
get_novaclient, get_cinderclient, get_neutronclient)
|
||||
from adjutant.common import openstack_clients
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
|
@ -33,7 +32,7 @@ class QuotaManager(object):
|
|||
|
||||
class ServiceQuotaCinderHelper(ServiceQuotaHelper):
|
||||
def __init__(self, region_name, project_id):
|
||||
self.client = get_cinderclient(
|
||||
self.client = openstack_clients.get_cinderclient(
|
||||
region=region_name)
|
||||
self.project_id = project_id
|
||||
|
||||
|
@ -59,7 +58,7 @@ class QuotaManager(object):
|
|||
|
||||
class ServiceQuotaNovaHelper(ServiceQuotaHelper):
|
||||
def __init__(self, region_name, project_id):
|
||||
self.client = get_novaclient(
|
||||
self.client = openstack_clients.get_novaclient(
|
||||
region=region_name)
|
||||
self.project_id = project_id
|
||||
|
||||
|
@ -85,7 +84,7 @@ class QuotaManager(object):
|
|||
|
||||
class ServiceQuotaNeutronHelper(ServiceQuotaHelper):
|
||||
def __init__(self, region_name, project_id):
|
||||
self.client = get_neutronclient(
|
||||
self.client = openstack_clients.get_neutronclient(
|
||||
region=region_name)
|
||||
self.project_id = project_id
|
||||
|
||||
|
@ -123,10 +122,57 @@ class QuotaManager(object):
|
|||
def get_quota(self):
|
||||
return self.client.show_quota(self.project_id)['quota']
|
||||
|
||||
class ServiceQuotaOctaviaHelper(ServiceQuotaNeutronHelper):
|
||||
def __init__(self, region_name, project_id):
|
||||
self.client = openstack_clients.get_octaviaclient(
|
||||
region=region_name)
|
||||
self.project_id = project_id
|
||||
|
||||
def get_quota(self):
|
||||
project_quota = self.client.quota_show(
|
||||
project_id=self.project_id)
|
||||
|
||||
# NOTE(amelia): Instead of returning the default quota if ANY
|
||||
# of the quotas are the default, the endpoint
|
||||
# returns None
|
||||
default_quota = None
|
||||
for name, quota in project_quota.items():
|
||||
if quota is None:
|
||||
if not default_quota:
|
||||
default_quota = self.client.quota_defaults_show()[
|
||||
'quota']
|
||||
project_quota[name] = default_quota[name]
|
||||
|
||||
return project_quota
|
||||
|
||||
def set_quota(self, values):
|
||||
self.client.quota_set(self.project_id, json={'quota': values})
|
||||
|
||||
def get_usage(self):
|
||||
usage = {}
|
||||
usage['load_balancer'] = len(self.client.load_balancer_list(
|
||||
project_id=self.project_id)['loadbalancers'])
|
||||
usage['listener'] = len(self.client.listener_list(
|
||||
project_id=self.project_id)['listeners'])
|
||||
|
||||
pools = self.client.pool_list(
|
||||
project_id=self.project_id)['pools']
|
||||
usage['pool'] = len(pools)
|
||||
|
||||
members = []
|
||||
for pool in pools:
|
||||
members += pool['members']
|
||||
|
||||
usage['member'] = len(members)
|
||||
usage['health_monitor'] = len(self.client.health_monitor_list(
|
||||
project_id=self.project_id)['healthmonitors'])
|
||||
return usage
|
||||
|
||||
_quota_updaters = {
|
||||
'cinder': ServiceQuotaCinderHelper,
|
||||
'nova': ServiceQuotaNovaHelper,
|
||||
'neutron': ServiceQuotaNeutronHelper
|
||||
'neutron': ServiceQuotaNeutronHelper,
|
||||
'octavia': ServiceQuotaOctaviaHelper,
|
||||
}
|
||||
|
||||
def __init__(self, project_id, size_difference_threshold=None):
|
||||
|
@ -175,12 +221,18 @@ class QuotaManager(object):
|
|||
match_percentages = []
|
||||
for service_name, values in setting.items():
|
||||
for name, value in values.items():
|
||||
if value != 0:
|
||||
if value > 0:
|
||||
try:
|
||||
current = current_quota[service_name][name]
|
||||
match_percentages.append(float(current) / value)
|
||||
except KeyError:
|
||||
pass
|
||||
elif value < 0:
|
||||
# NOTE(amelia): Sub-zero quota means unlimited
|
||||
if current_quota[service_name][name] < 0:
|
||||
match_percentages.append(1.0)
|
||||
else:
|
||||
match_percentages.append(0.0)
|
||||
elif current_quota[service_name][name] == 0:
|
||||
match_percentages.append(1.0)
|
||||
else:
|
||||
|
@ -188,8 +240,7 @@ class QuotaManager(object):
|
|||
# Calculate the average of how much it matches the setting
|
||||
difference = abs(
|
||||
(sum(match_percentages) / float(len(match_percentages))) - 1)
|
||||
# TODO(amelia): Nicer form of this due to the new way of doing
|
||||
# per action settings
|
||||
|
||||
if (difference <= self.size_diff_threshold):
|
||||
quota_differences[size] = difference
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ identity_cache = {}
|
|||
neutron_cache = {}
|
||||
nova_cache = {}
|
||||
cinder_cache = {}
|
||||
octavia_cache = {}
|
||||
|
||||
|
||||
class FakeProject(object):
|
||||
|
@ -595,6 +596,75 @@ class FakeNeutronClient(object):
|
|||
return neutron_cache[self.region][tenant_id]
|
||||
|
||||
|
||||
class FakeOctaviaClient(object):
|
||||
# {name in client call: name in response}
|
||||
resource_dict = {'load_balancer': 'loadbalancers',
|
||||
'listener': 'listeners',
|
||||
'member': 'members',
|
||||
'pool': 'pools',
|
||||
'health_monitor': 'healthmonitors'}
|
||||
|
||||
# NOTE(amelia): Using the current octavia client we will get back
|
||||
# dicts for everything, rather than the resources the
|
||||
# other clients wrap.
|
||||
# Additionally the openstacksdk octavia implemenation
|
||||
# does not have quota commands
|
||||
|
||||
def __init__(self, region):
|
||||
global octavia_cache
|
||||
self.region = region
|
||||
if region not in octavia_cache:
|
||||
octavia_cache[region] = {}
|
||||
self.cache = octavia_cache[region]
|
||||
|
||||
def quota_show(self, project_id):
|
||||
self._ensure_project_exists(project_id)
|
||||
quota = self.cache.get(project_id, {}).get('quota', [])
|
||||
for item in self.resource_dict:
|
||||
if item not in quota:
|
||||
quota[item] = None
|
||||
return {'quota': quota}
|
||||
|
||||
def quota_set(self, project_id, json):
|
||||
self._ensure_project_exists(project_id)
|
||||
self.cache[project_id]['quota'] = json['quota']
|
||||
|
||||
def quota_defaults_show(self):
|
||||
return {
|
||||
"quota": {
|
||||
"load_balancer": 10,
|
||||
"listener": -1,
|
||||
"member": 50,
|
||||
"pool": -1,
|
||||
"health_monitor": -1
|
||||
}
|
||||
}
|
||||
|
||||
def lister(self, resource_type):
|
||||
def action(project_id=None):
|
||||
self._ensure_project_exists(project_id)
|
||||
resource = self.cache.get(project_id, {}).get(resource_type, [])
|
||||
links_name = resource_type + '_links'
|
||||
resource_name = self.resource_dict[resource_type]
|
||||
return {resource_name: resource, links_name: []}
|
||||
return action
|
||||
|
||||
def _ensure_project_exists(self, project_id):
|
||||
if project_id not in self.cache:
|
||||
self.cache[project_id] = {
|
||||
name: [] for name in self.resource_dict.keys()}
|
||||
self.cache[project_id]['quota'] = dict(
|
||||
settings.PROJECT_QUOTA_SIZES['small']['octavia'])
|
||||
|
||||
def __getattr__(self, name):
|
||||
# NOTE(amelia): This is out of pure laziness
|
||||
global octavia_cache
|
||||
if name[-5:] == '_list' and name[:-5] in self.resource_dict:
|
||||
return self.lister(name[:-5])
|
||||
else:
|
||||
raise AttributeError
|
||||
|
||||
|
||||
class FakeNovaClient(FakeOpenstackClient):
|
||||
|
||||
def __init__(self, region):
|
||||
|
@ -754,6 +824,10 @@ def setup_mock_caches(region, project_id):
|
|||
setup_nova_cache(region, project_id)
|
||||
setup_cinder_cache(region, project_id)
|
||||
setup_neutron_cache(region, project_id)
|
||||
client = FakeOctaviaClient(region)
|
||||
if project_id in octavia_cache[region]:
|
||||
del octavia_cache[region][project_id]
|
||||
client._ensure_project_exists(project_id)
|
||||
|
||||
|
||||
def get_fake_neutron(region):
|
||||
|
@ -767,3 +841,7 @@ def get_fake_novaclient(region):
|
|||
def get_fake_cinderclient(region):
|
||||
global cinder_cache
|
||||
return FakeCinderClient(region)
|
||||
|
||||
|
||||
def get_fake_octaviaclient(region):
|
||||
return FakeOctaviaClient(region)
|
||||
|
|
|
@ -313,6 +313,13 @@ PROJECT_QUOTA_SIZES = {
|
|||
'security_group_rule': 100,
|
||||
'subnet': 3,
|
||||
},
|
||||
"octavia": {
|
||||
'health_monitor': 5,
|
||||
"listener": 1,
|
||||
"load_balancer": 1,
|
||||
"member": 2,
|
||||
"pool": 1,
|
||||
},
|
||||
},
|
||||
"medium": {
|
||||
"cinder": {
|
||||
|
@ -341,7 +348,14 @@ PROJECT_QUOTA_SIZES = {
|
|||
"security_group": 50,
|
||||
"router": 5,
|
||||
"port": 250
|
||||
}
|
||||
},
|
||||
"octavia": {
|
||||
'health_monitor': 50,
|
||||
"listener": 5,
|
||||
"load_balancer": 5,
|
||||
"member": 5,
|
||||
"pool": 5,
|
||||
},
|
||||
},
|
||||
"large": {
|
||||
"cinder": {
|
||||
|
@ -370,7 +384,14 @@ PROJECT_QUOTA_SIZES = {
|
|||
"security_group": 100,
|
||||
"router": 10,
|
||||
"port": 500
|
||||
}
|
||||
},
|
||||
"octavia": {
|
||||
'health_monitor': 100,
|
||||
"listener": 10,
|
||||
"load_balancer": 10,
|
||||
"member": 10,
|
||||
"pool": 10,
|
||||
},
|
||||
},
|
||||
"large_cinder_only": {
|
||||
"cinder": {
|
||||
|
|
|
@ -424,3 +424,5 @@ QUOTA_SERVICES:
|
|||
- nova
|
||||
- neutron
|
||||
- cinder
|
||||
# Additonal Quota Service
|
||||
# - octavia
|
||||
|
|
|
@ -11,6 +11,7 @@ python-cinderclient>=2.0.1
|
|||
python-neutronclient>=6.2.0
|
||||
python-novaclient>=8.0.0
|
||||
python-keystoneclient>=3.10.0
|
||||
python-octaviaclient>=1.0.0
|
||||
six>=1.10.0
|
||||
jsonfield>=2.0.1
|
||||
django-rest-swagger>=2.1.2
|
||||
|
|
Loading…
Reference in New Issue