Update networking quotas before creating network stacks

Change-Id: If97e5e42e0bae0117f52c87c7ae8cba411aa546f
This commit is contained in:
Federico Ressi 2021-07-16 10:32:28 +02:00
parent e59927c461
commit f930d163f2
3 changed files with 67 additions and 20 deletions

View File

@ -31,9 +31,6 @@ from tobiko.shell import sh
from tobiko.shell import ssh from tobiko.shell import ssh
LOG = log.getLogger(__name__)
CONF = config.CONF CONF = config.CONF
LOG = log.getLogger(__name__) LOG = log.getLogger(__name__)
@ -282,6 +279,18 @@ class NetworkStackFixture(heat.HeatStackFixture):
def gateway_network_details(self): def gateway_network_details(self):
return neutron.get_network(self.gateway_network_id) return neutron.get_network(self.gateway_network_id)
@property
def neutron_required_quota_set(self) -> typing.Dict[str, int]:
requirements = super().neutron_required_quota_set
requirements['network'] += 1
if self.has_ipv4:
requirements['subnet'] += 1
if self.has_ipv6:
requirements['subnet'] += 1
if self.has_gateway:
requirements['router'] += 1
return requirements
@neutron.skip_if_missing_networking_extensions('net-mtu-writable') @neutron.skip_if_missing_networking_extensions('net-mtu-writable')
class NetworkWithNetMtuWriteStackFixture(NetworkStackFixture): class NetworkWithNetMtuWriteStackFixture(NetworkStackFixture):

View File

@ -28,7 +28,6 @@ import tobiko
from tobiko import config from tobiko import config
from tobiko.openstack import glance from tobiko.openstack import glance
from tobiko.openstack import heat from tobiko.openstack import heat
from tobiko.openstack import keystone
from tobiko.openstack import neutron from tobiko.openstack import neutron
from tobiko.openstack import nova from tobiko.openstack import nova
from tobiko.openstack.stacks import _hot from tobiko.openstack.stacks import _hot
@ -106,10 +105,6 @@ class ServerStackFixture(heat.HeatStackFixture, abc.ABC):
#: whenever the server will use config-drive to get metadata #: whenever the server will use config-drive to get metadata
config_drive = False config_drive = False
def create_stack(self, retry=None):
self.ensure_quota_limits()
super(ServerStackFixture, self).create_stack(retry=retry)
@property @property
def image_fixture(self) -> glance.GlanceImageFixture: def image_fixture(self) -> glance.GlanceImageFixture:
"""Glance image used to create a Nova server instance""" """Glance image used to create a Nova server instance"""
@ -349,18 +344,12 @@ class ServerStackFixture(heat.HeatStackFixture, abc.ABC):
return server return server
def ensure_quota_limits(self): @property
"""Ensures Nova quota limits before creating a new server def nova_required_quota_set(self) -> typing.Dict[str, int]:
""" requirements = super().nova_required_quota_set
project = keystone.get_project_id( requirements['instances'] += 1
session=self.client.http_client.session) requirements['cores'] += (self.flavor_stack.vcpus or 1)
user = keystone.get_user_id( return requirements
session=self.client.http_client.session)
nova.ensure_nova_quota_limits(
project=project,
user=user,
instances=1,
cores=self.flavor_stack.vcpus or 1)
user_data = None user_data = None

View File

@ -18,11 +18,14 @@ from __future__ import absolute_import
import os import os
import random import random
import string import string
import typing
import testtools import testtools
import tobiko import tobiko
from tobiko.openstack import heat from tobiko.openstack import heat
from tobiko.openstack import neutron
from tobiko.openstack import nova
TEMPLATE_DIRS = [os.path.dirname(__file__)] TEMPLATE_DIRS = [os.path.dirname(__file__)]
@ -66,3 +69,49 @@ class HeatStackFixtureTest(testtools.TestCase):
self.assertEqual(tobiko.get_fixture_name(MyStack), stack_0.stack_name) self.assertEqual(tobiko.get_fixture_name(MyStack), stack_0.stack_name)
self.assertEqual(tobiko.get_fixture_name(MyStack) + '-1', self.assertEqual(tobiko.get_fixture_name(MyStack) + '-1',
stack_1.stack_name) stack_1.stack_name)
class EnsureNeutronQuotaLimitsFixture(MyStack):
requirements = {'network': 100, 'subnet': 100, 'router': 10}
@property
def neutron_required_quota_set(self) -> typing.Dict[str, int]:
return self.requirements
class EnsureNovaQuotaLimitsFixture(MyStack):
requirements = {'cores': 20, 'instances': 10}
@property
def nova_required_quota_set(self) -> typing.Dict[str, int]:
return self.requirements
class EnsureQuotaLimitsTest(testtools.TestCase):
def test_ensure_neutron_quota_limits(self):
stack = EnsureNeutronQuotaLimitsFixture(stack_name=self.id())
self.useFixture(stack)
quota_set = neutron.get_neutron_quota_set(detail=True)
for name, requirement in stack.requirements.items():
quota = quota_set[name]
self.assertGreaterEqual(quota['limit'],
requirement +
max(0, quota['used']) -
max(0, quota['reserved']))
def test_ensure_nova_quota_limits(self):
stack = EnsureNovaQuotaLimitsFixture(stack_name=self.id())
self.useFixture(stack)
quota_set = nova.get_nova_quota_set(detail=True)
for name, requirement in stack.requirements.items():
quota = getattr(quota_set, name)
if quota['limit'] > 0:
self.assertGreaterEqual(quota['limit'],
requirement +
max(0, quota['in_use']) -
max(0, quota['reserved']))
else:
self.assertEqual(quota['limit'], -1)