]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Avoid performing extra query for fetching qos bindings
authorSalvatore Orlando <salv.orlando@gmail.com>
Thu, 22 Aug 2013 16:08:52 +0000 (09:08 -0700)
committerSalvatore Orlando <salv.orlando@gmail.com>
Thu, 12 Sep 2013 10:20:48 +0000 (03:20 -0700)
Bug 1215872

Add a relationship with eager loading in the Port and Network models,
thus preventing the 'extend' functions from performing extra queries.
This patch also slight alters the methods for processing qos_queue
bindings in order to allow them for populating the qos_queue id in
the response being created.

Change-Id: Ie80d12aeed5de94afa61f23d7bcfc21372f23c4f

neutron/plugins/nicira/NeutronPlugin.py
neutron/plugins/nicira/dbexts/nicira_qos_db.py

index f5b276e1b5978faf0bfae63de14f22725ffb0f28..f5ce48f92d5252398e2e0ac918999464a27d79a3 100644 (file)
@@ -430,7 +430,7 @@ class NvpPluginV2(addr_pair_db.AllowedAddressPairsMixin,
                                    port_data['fixed_ips'],
                                    port_data[psec.PORTSECURITY],
                                    port_data[ext_sg.SECURITYGROUPS],
-                                   port_data[ext_qos.QUEUE],
+                                   port_data.get(ext_qos.QUEUE),
                                    port_data.get(mac_ext.MAC_LEARNING),
                                    port_data.get(addr_pair.ADDRESS_PAIRS))
 
@@ -991,12 +991,12 @@ class NvpPluginV2(addr_pair_db.AllowedAddressPairsMixin,
             # DB Operations for setting the network as external
             self._process_l3_create(context, new_net, net_data)
             # Process QoS queue extension
-            if network['network'].get(ext_qos.QUEUE):
-                new_net[ext_qos.QUEUE] = network['network'][ext_qos.QUEUE]
+            net_queue_id = net_data.get(ext_qos.QUEUE)
+            if net_queue_id:
                 # Raises if not found
-                self.get_qos_queue(context, new_net[ext_qos.QUEUE])
-                self._process_network_queue_mapping(context, new_net)
-                self._extend_network_qos_queue(context, new_net)
+                self.get_qos_queue(context, net_queue_id)
+                self._process_network_queue_mapping(
+                    context, new_net, net_queue_id)
 
             if (net_data.get(mpnet.SEGMENTS) and
                 isinstance(provider_type, bool)):
@@ -1078,7 +1078,6 @@ class NvpPluginV2(addr_pair_db.AllowedAddressPairsMixin,
             # to add provider networks fields
             net_result = self._make_network_dict(network)
             self._extend_network_dict_provider(context, net_result)
-            self._extend_network_qos_queue(context, net_result)
         return self._fields(net_result, fields)
 
     def get_networks(self, context, filters=None, fields=None):
@@ -1087,7 +1086,6 @@ class NvpPluginV2(addr_pair_db.AllowedAddressPairsMixin,
             networks = super(NvpPluginV2, self).get_networks(context, filters)
             for net in networks:
                 self._extend_network_dict_provider(context, net)
-                self._extend_network_qos_queue(context, net)
         return [self._fields(network, fields) for network in networks]
 
     def update_network(self, context, id, network):
@@ -1102,23 +1100,14 @@ class NvpPluginV2(addr_pair_db.AllowedAddressPairsMixin,
             if psec.PORTSECURITY in network['network']:
                 self._process_network_port_security_update(
                     context, network['network'], net)
-            if network['network'].get(ext_qos.QUEUE):
-                net[ext_qos.QUEUE] = network['network'][ext_qos.QUEUE]
+            net_queue_id = network['network'].get(ext_qos.QUEUE)
+            if net_queue_id:
                 self._delete_network_queue_mapping(context, id)
-                self._process_network_queue_mapping(context, net)
+                self._process_network_queue_mapping(context, net, net_queue_id)
             self._process_l3_update(context, net, network['network'])
             self._extend_network_dict_provider(context, net)
-            self._extend_network_qos_queue(context, net)
         return net
 
-    def get_ports(self, context, filters=None, fields=None):
-        filters = filters or {}
-        with context.session.begin(subtransactions=True):
-            ports = super(NvpPluginV2, self).get_ports(context, filters)
-            for port in ports:
-                self._extend_port_qos_queue(context, port)
-        return [self._fields(port, fields) for port in ports]
-
     def create_port(self, context, port):
         # If PORTSECURITY is not the default value ATTR_NOT_SPECIFIED
         # then we pass the port to the policy engine. The reason why we don't
@@ -1161,9 +1150,10 @@ class NvpPluginV2(addr_pair_db.AllowedAddressPairsMixin,
             self._process_port_create_security_group(
                 context, port_data, port_data[ext_sg.SECURITYGROUPS])
             # QoS extension checks
-            port_data[ext_qos.QUEUE] = self._check_for_queue_and_create(
+            port_queue_id = self._check_for_queue_and_create(
                 context, port_data)
-            self._process_port_queue_mapping(context, port_data)
+            self._process_port_queue_mapping(
+                context, port_data, port_queue_id)
             if (isinstance(port_data.get(mac_ext.MAC_LEARNING), bool)):
                 self._create_mac_learning_state(context, port_data)
             elif mac_ext.MAC_LEARNING in port_data:
@@ -1172,9 +1162,6 @@ class NvpPluginV2(addr_pair_db.AllowedAddressPairsMixin,
             LOG.debug(_("create_port completed on NVP for tenant "
                         "%(tenant_id)s: (%(id)s)"), port_data)
 
-            # remove since it will be added in extend based on policy
-            del port_data[ext_qos.QUEUE]
-            self._extend_port_qos_queue(context, port_data)
             self._process_portbindings_create_and_update(context,
                                                          port, port_data)
         # DB Operation is complete, perform NVP operation
@@ -1272,7 +1259,7 @@ class NvpPluginV2(addr_pair_db.AllowedAddressPairsMixin,
                 self._process_port_port_security_update(
                     context, port['port'], ret_port)
 
-            ret_port[ext_qos.QUEUE] = self._check_for_queue_and_create(
+            port_queue_id = self._check_for_queue_and_create(
                 context, ret_port)
             # Populate the mac learning attribute
             new_mac_learning_state = port['port'].get(mac_ext.MAC_LEARNING)
@@ -1282,7 +1269,8 @@ class NvpPluginV2(addr_pair_db.AllowedAddressPairsMixin,
                                                 new_mac_learning_state)
                 ret_port[mac_ext.MAC_LEARNING] = new_mac_learning_state
             self._delete_port_queue_mapping(context, ret_port['id'])
-            self._process_port_queue_mapping(context, ret_port)
+            self._process_port_queue_mapping(context, ret_port,
+                                             port_queue_id)
             LOG.warn(_("Update port request: %s"), port)
             nvp_port_id = self._nvp_get_port_id(
                 context, self.cluster, ret_port)
@@ -1317,9 +1305,6 @@ class NvpPluginV2(addr_pair_db.AllowedAddressPairsMixin,
             else:
                 ret_port['status'] = constants.PORT_STATUS_ERROR
 
-            # remove since it will be added in extend based on policy
-            del ret_port[ext_qos.QUEUE]
-            self._extend_port_qos_queue(context, ret_port)
             self._process_portbindings_create_and_update(context,
                                                          port['port'],
                                                          port)
@@ -1371,11 +1356,9 @@ class NvpPluginV2(addr_pair_db.AllowedAddressPairsMixin,
                 db_port = self._get_port(context, id)
                 self._synchronizer.synchronize_port(
                     context, db_port)
-                port = self._make_port_dict(db_port, fields)
+                return self._make_port_dict(db_port, fields)
             else:
-                port = super(NvpPluginV2, self).get_port(context, id, fields)
-            self._extend_port_qos_queue(context, port)
-        return port
+                return super(NvpPluginV2, self).get_port(context, id, fields)
 
     def get_router(self, context, id, fields=None):
         if fields and 'status' in fields:
index 875850a22521abf96e601fe698dcd9d92b3ad87b..86a4cd57ba1e822d3fd8aa7469e1412bd2db5aa2 100644 (file)
 # @author: Aaron Rosen, Nicira, Inc
 
 import sqlalchemy as sa
+from sqlalchemy import orm
 from sqlalchemy.orm import exc
 
 from neutron.api.v2 import attributes as attr
+from neutron.db import db_base_plugin_v2
 from neutron.db import model_base
 from neutron.db import models_v2
 from neutron.openstack.common import log
@@ -49,6 +51,13 @@ class PortQueueMapping(model_base.BASEV2):
     queue_id = sa.Column(sa.String(36), sa.ForeignKey("qosqueues.id"),
                          primary_key=True)
 
+    # Add a relationship to the Port model adding a backref which will
+    # allow SQLAlchemy for eagerly load the queue binding
+    port = orm.relationship(
+        models_v2.Port,
+        backref=orm.backref("qos_queue", uselist=False,
+                            cascade='delete', lazy='joined'))
+
 
 class NetworkQueueMapping(model_base.BASEV2):
     network_id = sa.Column(sa.String(36),
@@ -58,6 +67,13 @@ class NetworkQueueMapping(model_base.BASEV2):
     queue_id = sa.Column(sa.String(36), sa.ForeignKey("qosqueues.id",
                                                       ondelete="CASCADE"))
 
+    # Add a relationship to the Network model adding a backref which will
+    # allow SQLAlcremy for eagerly load the queue binding
+    network = orm.relationship(
+        models_v2.Network,
+        backref=orm.backref("qos_queue", uselist=False,
+                            cascade='delete', lazy='joined'))
+
 
 class NVPQoSDbMixin(ext_qos.QueuePluginBase):
     """Mixin class to add queues."""
@@ -96,13 +112,13 @@ class NVPQoSDbMixin(ext_qos.QueuePluginBase):
         with context.session.begin(subtransactions=True):
             context.session.delete(qos_queue)
 
-    def _process_port_queue_mapping(self, context, p):
-        if not p.get(ext_qos.QUEUE):
+    def _process_port_queue_mapping(self, context, port_data, queue_id):
+        port_data[ext_qos.QUEUE] = queue_id
+        if not queue_id:
             return
         with context.session.begin(subtransactions=True):
-            db = PortQueueMapping(port_id=p['id'],
-                                  queue_id=p.get(ext_qos.QUEUE))
-            context.session.add(db)
+            context.session.add(PortQueueMapping(port_id=port_data['id'],
+                                queue_id=queue_id))
 
     def _get_port_queue_bindings(self, context, filters=None, fields=None):
         return self._get_collection(context, PortQueueMapping,
@@ -121,13 +137,14 @@ class NVPQoSDbMixin(ext_qos.QueuePluginBase):
         with context.session.begin(subtransactions=True):
             context.session.delete(binding)
 
-    def _process_network_queue_mapping(self, context, network):
-        if not network.get(ext_qos.QUEUE):
+    def _process_network_queue_mapping(self, context, net_data, queue_id):
+        net_data[ext_qos.QUEUE] = queue_id
+        if not queue_id:
             return
         with context.session.begin(subtransactions=True):
-            db = NetworkQueueMapping(network_id=network['id'],
-                                     queue_id=network.get(ext_qos.QUEUE))
-            context.session.add(db)
+            context.session.add(
+                NetworkQueueMapping(network_id=net_data['id'],
+                                    queue_id=queue_id))
 
     def _get_network_queue_bindings(self, context, filters=None, fields=None):
         return self._get_collection(context, NetworkQueueMapping,
@@ -141,25 +158,23 @@ class NVPQoSDbMixin(ext_qos.QueuePluginBase):
             if binding:
                 context.session.delete(binding)
 
-    def _extend_port_qos_queue(self, context, port):
-        filters = {'port_id': [port['id']]}
-        fields = ['queue_id']
-        port[ext_qos.QUEUE] = None
-        queue_id = self._get_port_queue_bindings(
-            context, filters, fields)
-        if queue_id:
-            port[ext_qos.QUEUE] = queue_id[0]['queue_id']
-        return port
-
-    def _extend_network_qos_queue(self, context, network):
-        filters = {'network_id': [network['id']]}
-        fields = ['queue_id']
-        network[ext_qos.QUEUE] = None
-        queue_id = self._get_network_queue_bindings(
-            context, filters, fields)
-        if queue_id:
-            network[ext_qos.QUEUE] = queue_id[0]['queue_id']
-        return network
+    def _extend_dict_qos_queue(self, obj_res, obj_db):
+        queue_mapping = obj_db['qos_queue']
+        if queue_mapping:
+            obj_res[ext_qos.QUEUE] = queue_mapping.get('queue_id')
+        return obj_res
+
+    def _extend_port_dict_qos_queue(self, port_res, port_db):
+        self._extend_dict_qos_queue(port_res, port_db)
+
+    def _extend_network_dict_qos_queue(self, network_res, network_db):
+        self._extend_dict_qos_queue(network_res, network_db)
+
+    # Register dict extend functions for networks and ports
+    db_base_plugin_v2.NeutronDbPluginV2.register_dict_extend_funcs(
+        attr.NETWORKS, ['_extend_network_dict_qos_queue'])
+    db_base_plugin_v2.NeutronDbPluginV2.register_dict_extend_funcs(
+        attr.PORTS, ['_extend_port_dict_qos_queue'])
 
     def _make_qos_queue_dict(self, queue, fields=None):
         res = {'id': queue['id'],
@@ -215,7 +230,6 @@ class NVPQoSDbMixin(ext_qos.QueuePluginBase):
         filters = {'network_id': [port['network_id']]}
         network_queue_id = self._get_network_queue_bindings(
             context, filters, ['queue_id'])
-
         if network_queue_id:
             # get networks that queue is assocated with
             filters = {'queue_id': [network_queue_id[0]['queue_id']]}