From 52c88252ded38b0f34f3cf859be9b9ee7700eff1 Mon Sep 17 00:00:00 2001 From: Kobi Samoray Date: Mon, 16 Jan 2017 17:13:05 +0200 Subject: [PATCH] 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 --- vmware_nsx/db/nsxv_db.py | 6 ++++++ vmware_nsx/plugins/nsx_v/plugin.py | 26 +++++++++++++++++++++----- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/vmware_nsx/db/nsxv_db.py b/vmware_nsx/db/nsxv_db.py index 1a9298d4d2..b193d9d47b 100644 --- a/vmware_nsx/db/nsxv_db.py +++ b/vmware_nsx/db/nsxv_db.py @@ -137,6 +137,12 @@ def clean_edge_router_binding(session, edge_id): filter_by(edge_id=edge_id).delete()) +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() diff --git a/vmware_nsx/plugins/nsx_v/plugin.py b/vmware_nsx/plugins/nsx_v/plugin.py index 5e47467ed0..cc730b76d7 100644 --- a/vmware_nsx/plugins/nsx_v/plugin.py +++ b/vmware_nsx/plugins/nsx_v/plugin.py @@ -654,14 +654,17 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin, network[az_ext.AVAILABILITY_ZONES] = ( self._get_network_availability_zones(context, network)) - 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): @@ -687,11 +690,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))