Avoid performing extra query for fetching qos bindings
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
This commit is contained in:
parent
b857c86f3b
commit
c59456734e
@ -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:
|
||||
|
@ -17,9 +17,11 @@
|
||||
# @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_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_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_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']]}
|
||||
|
Loading…
x
Reference in New Issue
Block a user