Optimize queries for port operations

Port create/update are most time-consuming operations
on subnet creation. As example, in those cases where
several subnets are created over the same network the
response time for those port operations is linearly
increased as the total subnets increases.

This patch improves the number of queries required on port
operations in order to reduce the response time.

Closes-Bug: #1977831
Change-Id: I0fccf36a2035e8f6c2fa8dab0307358da600c8f7
(cherry picked from commit c25097b0b0)
This commit is contained in:
Fernando Royo 2022-06-07 13:51:51 +02:00
parent 7740ed0784
commit 3eed8f9194
2 changed files with 28 additions and 3 deletions

View File

@ -343,12 +343,17 @@ class Subnet(base.NeutronDbObject):
:raises: FixedIpsSubnetsNotOnSameSegment
"""
segment_ids = []
subnets = query.all()
for fixed_ip in fixed_ips:
subnet = None
if 'subnet_id' in fixed_ip:
try:
subnet = query.filter(
cls.db_model.id == fixed_ip['subnet_id']).all()[0]
subnet = [
sub
for sub in subnets
if sub['id'] == fixed_ip['subnet_id']
][0]
except IndexError:
# NOTE(hjensas): The subnet is invalid for the network,
# return all subnets. This will be detected in following
@ -357,7 +362,7 @@ class Subnet(base.NeutronDbObject):
elif 'ip_address' in fixed_ip:
ip = netaddr.IPNetwork(fixed_ip['ip_address'])
for s in query.all():
for s in subnets:
if ip in netaddr.IPNetwork(s.cidr):
subnet = s
break

View File

@ -266,3 +266,23 @@ class SubnetDbObjectTestCase(obj_test_base.BaseDbObjectTestCase,
obj1 = self._make_object(self.obj_fields[0])
self.assertEqual([service_type_obj.service_type],
obj1.service_types)
def test_find_candidate_subnets(self):
network = self._create_test_network()
subnet_data = dict(self.obj_fields[0])
subnet_data['network_id'] = network['id']
subnet_net = self._make_object(subnet_data)
subnet2_data = dict(self.obj_fields[0])
subnet2_data['id'] = uuidutils.generate_uuid()
subnet2_data['network_id'] = network['id']
subnet2_net = self._make_object(subnet2_data)
subnet_net.create()
subnet2_net.create()
fixed_ips = [
{'subnet_id': subnet_data['id'], 'ip_address': '10.0.0.2'},
{'subnet_id': subnet2_data['id'], 'ip_address': '10.0.1.2'}]
candidate_subnet = subnet.Subnet.find_candidate_subnets(
self.context, network['id'], None, None, True, fixed_ips)
self.assertEqual(2, len(candidate_subnet))
self.assertNotEqual(
candidate_subnet[0]['id'], candidate_subnet[1]['id'])