Add some bulk lookup methods to ML2 for RPC handling
This adds three methods to make working with bulk port
DB lookups easier in ML2:
* partial_port_ids_to_full_ids: takes short port IDs map to
full port IDs. This will allow us to eliminate many LIKE
queries and do one just once for all ports on an RPC call.
* get_port_db_objects: Takes a list of port IDs and returns
a map to port DB objects. This allows us to get access to
sqla obejcts for a bunch of ports without a custom
session.query call.
* get_network_contexts: Takes a list of network_ids and does
a bulk construction of NetworkContext objects and returns
them as a map of network_id to NetworkContext to avoid
expensive net lookups when constructing lots of PortContext
objects.
Conflicts:
neutron/plugins/ml2/db.py
neutron/plugins/ml2/plugin.py
Partial-Bug: #1665215
Change-Id: I330eefbf429bd62f2a7e8ebadf7037da15c86815
(cherry picked from commit 323eb7f2e1
)
This commit is contained in:
parent
66839cff26
commit
ce0e4b25d5
|
@ -22,10 +22,11 @@ import six
|
||||||
from sqlalchemy import or_
|
from sqlalchemy import or_
|
||||||
from sqlalchemy.orm import exc
|
from sqlalchemy.orm import exc
|
||||||
|
|
||||||
from neutron._i18n import _, _LE
|
from neutron._i18n import _, _LE, _LI
|
||||||
from neutron.callbacks import events
|
from neutron.callbacks import events
|
||||||
from neutron.callbacks import registry
|
from neutron.callbacks import registry
|
||||||
from neutron.callbacks import resources
|
from neutron.callbacks import resources
|
||||||
|
from neutron.db import api as db_api
|
||||||
from neutron.db.models import securitygroup as sg_models
|
from neutron.db.models import securitygroup as sg_models
|
||||||
from neutron.db import models_v2
|
from neutron.db import models_v2
|
||||||
from neutron.extensions import portbindings
|
from neutron.extensions import portbindings
|
||||||
|
@ -276,6 +277,47 @@ def get_distributed_port_bindings(context, port_id):
|
||||||
return bindings
|
return bindings
|
||||||
|
|
||||||
|
|
||||||
|
@db_api.context_manager.reader
|
||||||
|
def partial_port_ids_to_full_ids(context, partial_ids):
|
||||||
|
"""Takes a list of the start of port IDs and returns full IDs.
|
||||||
|
|
||||||
|
Returns dictionary of partial IDs to full IDs if a single match
|
||||||
|
is found.
|
||||||
|
"""
|
||||||
|
result = {}
|
||||||
|
to_full_query = (context.session.query(models_v2.Port.id).
|
||||||
|
filter(or_(*[models_v2.Port.id.startswith(p)
|
||||||
|
for p in partial_ids])))
|
||||||
|
candidates = [match[0] for match in to_full_query]
|
||||||
|
for partial_id in partial_ids:
|
||||||
|
matching = [c for c in candidates if c.startswith(partial_id)]
|
||||||
|
if len(matching) == 1:
|
||||||
|
result[partial_id] = matching[0]
|
||||||
|
continue
|
||||||
|
if len(matching) < 1:
|
||||||
|
LOG.info(_LI("No ports have port_id starting with %s"),
|
||||||
|
partial_id)
|
||||||
|
elif len(matching) > 1:
|
||||||
|
LOG.error(_LE("Multiple ports have port_id starting with %s"),
|
||||||
|
partial_id)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
@db_api.context_manager.reader
|
||||||
|
def get_port_db_objects(context, port_ids):
|
||||||
|
"""Takes a list of port_ids and returns matching port db objects.
|
||||||
|
|
||||||
|
return format is a dictionary keyed by passed in IDs with db objects
|
||||||
|
for values or None if the port was not present.
|
||||||
|
"""
|
||||||
|
port_qry = (context.session.query(models_v2.Port).
|
||||||
|
filter(models_v2.Port.id.in_(port_ids)))
|
||||||
|
result = {p: None for p in port_ids}
|
||||||
|
for port in port_qry:
|
||||||
|
result[port.id] = port
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
def is_dhcp_active_on_any_subnet(context, subnet_ids):
|
def is_dhcp_active_on_any_subnet(context, subnet_ids):
|
||||||
if not subnet_ids:
|
if not subnet_ids:
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -895,6 +895,20 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||||
e,
|
e,
|
||||||
_LE("Exception auto-deleting subnet %s"), subnet_id)
|
_LE("Exception auto-deleting subnet %s"), subnet_id)
|
||||||
|
|
||||||
|
def get_network_contexts(self, context, network_ids):
|
||||||
|
"""Return a map of network_id to NetworkContext for network_ids."""
|
||||||
|
net_filters = {'id': list(set(network_ids))}
|
||||||
|
nets_by_netid = {
|
||||||
|
n['id']: n for n in self.get_networks(context,
|
||||||
|
filters=net_filters)
|
||||||
|
}
|
||||||
|
netctxs_by_netid = {
|
||||||
|
net_id: driver_context.NetworkContext(
|
||||||
|
self, context, nets_by_netid[net_id])
|
||||||
|
for net_id in nets_by_netid.keys()
|
||||||
|
}
|
||||||
|
return netctxs_by_netid
|
||||||
|
|
||||||
@utils.transaction_guard
|
@utils.transaction_guard
|
||||||
@db_api.retry_if_session_inactive()
|
@db_api.retry_if_session_inactive()
|
||||||
def delete_network(self, context, id):
|
def delete_network(self, context, id):
|
||||||
|
|
Loading…
Reference in New Issue