Improve performance of security group DB query
The _select_ips_for_remote_group method was joining the IP allocation, port, allowed address pair, and security group tables together in a single query. Additionally, it was loading all of the port columns and using none of them. This resulted in a very expensive query with no benefit. This patch eliminates the unnecessary use of the port table by joining the IP allocation table directly to the security groups and allowed address pairs tables. In local testing of the method, this sped it up by an order of magnitude. Closes-Bug: #1373851 Change-Id: I12899413004838d2d22b691f1e2f3b18f7ec2c27
This commit is contained in:
parent
0c1223862c
commit
2edad0884f
@ -19,6 +19,7 @@ from sqlalchemy.orm import exc
|
|||||||
from neutron.common import constants as q_const
|
from neutron.common import constants as q_const
|
||||||
from neutron.common import ipv6_utils as ipv6
|
from neutron.common import ipv6_utils as ipv6
|
||||||
from neutron.common import utils
|
from neutron.common import utils
|
||||||
|
from neutron.db import allowedaddresspairs_db as addr_pair
|
||||||
from neutron.db import models_v2
|
from neutron.db import models_v2
|
||||||
from neutron.db import securitygroups_db as sg_db
|
from neutron.db import securitygroups_db as sg_db
|
||||||
from neutron.extensions import securitygroup as ext_sg
|
from neutron.extensions import securitygroup as ext_sg
|
||||||
@ -231,27 +232,32 @@ class SecurityGroupServerRpcMixin(sg_db.SecurityGroupDbMixin):
|
|||||||
if not remote_group_ids:
|
if not remote_group_ids:
|
||||||
return ips_by_group
|
return ips_by_group
|
||||||
for remote_group_id in remote_group_ids:
|
for remote_group_id in remote_group_ids:
|
||||||
ips_by_group[remote_group_id] = []
|
ips_by_group[remote_group_id] = set()
|
||||||
|
|
||||||
ip_port = models_v2.IPAllocation.port_id
|
ip_port = models_v2.IPAllocation.port_id
|
||||||
sg_binding_port = sg_db.SecurityGroupPortBinding.port_id
|
sg_binding_port = sg_db.SecurityGroupPortBinding.port_id
|
||||||
sg_binding_sgid = sg_db.SecurityGroupPortBinding.security_group_id
|
sg_binding_sgid = sg_db.SecurityGroupPortBinding.security_group_id
|
||||||
|
|
||||||
|
# Join the security group binding table directly to the IP allocation
|
||||||
|
# table instead of via the Port table skip an unnecessary intermediary
|
||||||
query = context.session.query(sg_binding_sgid,
|
query = context.session.query(sg_binding_sgid,
|
||||||
models_v2.Port,
|
models_v2.IPAllocation.ip_address,
|
||||||
models_v2.IPAllocation.ip_address)
|
addr_pair.AllowedAddressPair.ip_address)
|
||||||
query = query.join(models_v2.IPAllocation,
|
query = query.join(models_v2.IPAllocation,
|
||||||
ip_port == sg_binding_port)
|
ip_port == sg_binding_port)
|
||||||
query = query.join(models_v2.Port,
|
# Outerjoin because address pairs may be null and we still want the
|
||||||
ip_port == models_v2.Port.id)
|
# IP for the port.
|
||||||
|
query = query.outerjoin(
|
||||||
|
addr_pair.AllowedAddressPair,
|
||||||
|
sg_binding_port == addr_pair.AllowedAddressPair.port_id)
|
||||||
query = query.filter(sg_binding_sgid.in_(remote_group_ids))
|
query = query.filter(sg_binding_sgid.in_(remote_group_ids))
|
||||||
for security_group_id, port, ip_address in query:
|
# Each allowed address pair IP record for a port beyond the 1st
|
||||||
ips_by_group[security_group_id].append(ip_address)
|
# will have a duplicate regular IP in the query response since
|
||||||
# if there are allowed_address_pairs add them
|
# the relationship is 1-to-many. Dedup with a set
|
||||||
if getattr(port, 'allowed_address_pairs', None):
|
for security_group_id, ip_address, allowed_addr_ip in query:
|
||||||
for address_pair in port.allowed_address_pairs:
|
ips_by_group[security_group_id].add(ip_address)
|
||||||
ips_by_group[security_group_id].append(
|
if allowed_addr_ip:
|
||||||
address_pair['ip_address'])
|
ips_by_group[security_group_id].add(allowed_addr_ip)
|
||||||
return ips_by_group
|
return ips_by_group
|
||||||
|
|
||||||
def _select_remote_group_ids(self, ports):
|
def _select_remote_group_ids(self, ports):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user