Merge "Improve port retrieval when validating auto address" into stable/train

This commit is contained in:
Zuul 2020-04-23 04:48:42 +00:00 committed by Gerrit Code Review
commit 1e03227be7
3 changed files with 48 additions and 21 deletions

View File

@ -627,3 +627,10 @@ class Port(base.NeutronDbObject):
query = query.filter(
ml2_models.PortBinding.vif_type.in_(binding_types))
return bool(query.count())
@classmethod
def get_ports_allocated_by_subnet_id(cls, context, subnet_id):
"""Return ports with fixed IPs in a subnet"""
return context.session.query(models_v2.Port).filter(
models_v2.IPAllocation.port_id == models_v2.Port.id).filter(
models_v2.IPAllocation.subnet_id == subnet_id).all()

View File

@ -45,7 +45,6 @@ from oslo_utils import excutils
from neutron._i18n import _
from neutron.common import ipv6_utils
from neutron.db import models_v2
from neutron.extensions import segment
from neutron.notifiers import batch_notifier
from neutron.objects import network as net_obj
@ -146,28 +145,21 @@ class Plugin(db.SegmentDbMixin, segment.SegmentPluginBase):
if not is_auto_addr_subnet or subnet.segment_id is None:
return
net_allocs = (context.session.query(models_v2.IPAllocation.port_id).
filter_by(subnet_id=subnet.id))
port_ids_on_net = [ipalloc.port_id for ipalloc in net_allocs]
for port_id in port_ids_on_net:
try:
port = ports_obj.Port.get_object(context, id=port_id)
fixed_ips = [f for f in port['fixed_ips']
if f['subnet_id'] != subnet.id]
if len(fixed_ips) != 0:
continue
LOG.info("Found port %(port_id)s, with IP auto-allocation "
"only on subnet %(subnet)s which is associated with "
"segment %(segment_id)s, cannot delete",
{'port_id': port_id,
'subnet': subnet.id,
'segment_id': subnet.segment_id})
raise n_exc.SubnetInUse(subnet_id=subnet.id)
except n_exc.PortNotFound:
# port is gone
ports = ports_obj.Port.get_ports_allocated_by_subnet_id(context,
subnet.id)
for port in ports:
fixed_ips = [f for f in port.fixed_ips if f.subnet_id != subnet.id]
if len(fixed_ips) != 0:
continue
LOG.info("Found port %(port_id)s, with IP auto-allocation "
"only on subnet %(subnet)s which is associated with "
"segment %(segment_id)s, cannot delete",
{'port_id': port.id,
'subnet': subnet.id,
'segment_id': subnet.segment_id})
raise n_exc.SubnetInUse(subnet_id=subnet.id)
class Event(object):

View File

@ -11,6 +11,7 @@
# under the License.
import mock
import netaddr
from neutron_lib import constants
from neutron_lib.tests import tools
from oslo_utils import uuidutils
@ -545,3 +546,30 @@ class PortDbObjectTestCase(obj_test_base.BaseDbObjectTestCase,
self.context, network_id,
binding_types=['vif_type1', 'vif_type2'],
negative_search=True))
def test_get_ports_allocated_by_subnet_id(self):
network_id = self._create_test_network_id()
segment_id = self._create_test_segment_id(network_id)
subnet_id = self._create_test_subnet_id(network_id)
self.update_obj_fields(
{'network_id': network_id,
'fixed_ips': {'subnet_id': subnet_id,
'network_id': network_id},
'device_owner': 'not_a_router',
'binding_levels': {'segment_id': segment_id}},
db_objs=[self.db_objs[0]])
objs = []
for idx in range(3):
objs.append(self._make_object(self.obj_fields[idx]))
objs[idx].create()
ipa = ports.IPAllocation(self.context, port_id=objs[0].id,
subnet_id=subnet_id, network_id=network_id,
ip_address=netaddr.IPAddress('10.0.0.1'))
ipa.create()
ports_alloc = ports.Port.get_ports_allocated_by_subnet_id(self.context,
subnet_id)
self.assertEqual(1, len(ports_alloc))
self.assertEqual(objs[0].id, ports_alloc[0].id)