NSXv: Reduce DB calls while gathering network edges

get_subnets requires a huge number of backend calls to gather the
networks advanced_service_providers field.
This change should gather the data from DB with a single call and
process it locally at the controller.

Change-Id: Ic7c7fac46c983c1c750108d86a1adefb4c11508c
(cherry picked from commit 52c88252de)
This commit is contained in:
Kobi Samoray 2017-01-16 17:13:05 +02:00 committed by garyk
parent 55e67178d6
commit 78fd9480ee
2 changed files with 27 additions and 5 deletions

View File

@ -135,6 +135,12 @@ def delete_nsxv_router_binding(session, router_id):
session.delete(binding)
def get_edge_vnic_bindings_with_networks(session):
query = session.query(nsxv_models.NsxvEdgeVnicBinding)
return query.filter(
nsxv_models.NsxvEdgeVnicBinding.network_id != expr.null()).all()
def get_edge_vnic_binding(session, edge_id, network_id):
return session.query(nsxv_models.NsxvEdgeVnicBinding).filter_by(
edge_id=edge_id, network_id=network_id).first()

View File

@ -426,14 +426,17 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
pnet.SEGMENTATION_ID: binding.vlan_id}
for binding in bindings]
def _get_subnet_as_providers(self, context, subnet):
def _get_subnet_as_providers(self, context, subnet, nw_dict=None):
net_id = subnet.get('network_id')
if net_id is None:
net_id = self.get_subnet(context, subnet['id']).get('network_id')
as_provider_data = nsxv_db.get_edge_vnic_bindings_by_int_lswitch(
context.session, net_id)
providers = [asp['edge_id'] for asp in as_provider_data]
if nw_dict:
providers = nw_dict.get(net_id, [])
else:
as_provider_data = nsxv_db.get_edge_vnic_bindings_by_int_lswitch(
context.session, net_id)
providers = [asp['edge_id'] for asp in as_provider_data]
return providers
def get_subnet(self, context, id, fields=None):
@ -459,11 +462,24 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
if ((fields and as_providers.ADV_SERVICE_PROVIDERS in fields)
or (filters and filters.get(as_providers.ADV_SERVICE_PROVIDERS))):
# This ugly mess should reduce DB calls with network_id field
# as filter - as network_id is not indexed
vnic_binds = nsxv_db.get_edge_vnic_bindings_with_networks(
context.session)
nw_dict = {}
for vnic_bind in vnic_binds:
if nw_dict.get(vnic_bind['network_id']):
nw_dict[vnic_bind['network_id']].append(
vnic_bind['edge_id'])
else:
nw_dict[vnic_bind['network_id']] = [vnic_bind['edge_id']]
# We only deal metadata provider field when:
# - adv_service_provider is explicitly retrieved
# - adv_service_provider is used in a filter
for subnet in subnets:
as_provider = self._get_subnet_as_providers(context, subnet)
as_provider = self._get_subnet_as_providers(
context, subnet, nw_dict)
md_filter = (
None if filters is None
else filters.get(as_providers.ADV_SERVICE_PROVIDERS))