Merge "Optimize queries for port operations" into stable/xena
This commit is contained in:
commit
d4acd8f95f
|
@ -364,12 +364,17 @@ class Subnet(base.NeutronDbObject):
|
|||
:raises: FixedIpsSubnetsNotOnSameSegment
|
||||
"""
|
||||
segment_ids = []
|
||||
subnets = query.all()
|
||||
|
||||
for fixed_ip in fixed_ips:
|
||||
subnet = None
|
||||
if 'subnet_id' in fixed_ip:
|
||||
try:
|
||||
subnet = query.filter(
|
||||
cls.db_model.id == fixed_ip['subnet_id']).all()[0]
|
||||
subnet = [
|
||||
sub
|
||||
for sub in subnets
|
||||
if sub['id'] == fixed_ip['subnet_id']
|
||||
][0]
|
||||
except IndexError:
|
||||
# NOTE(hjensas): The subnet is invalid for the network,
|
||||
# return all subnets. This will be detected in following
|
||||
|
@ -378,7 +383,7 @@ class Subnet(base.NeutronDbObject):
|
|||
elif 'ip_address' in fixed_ip:
|
||||
ip = netaddr.IPNetwork(fixed_ip['ip_address'])
|
||||
|
||||
for s in query.all():
|
||||
for s in subnets:
|
||||
if ip in netaddr.IPNetwork(s.cidr):
|
||||
subnet = s
|
||||
break
|
||||
|
|
|
@ -237,27 +237,46 @@ class OVNClient(object):
|
|||
parent_name = binding_prof.get('parent_name', [])
|
||||
tag = binding_prof.get('tag', [])
|
||||
address = port['mac_address']
|
||||
for ip in port.get('fixed_ips', []):
|
||||
try:
|
||||
subnet = self._plugin.get_subnet(context, ip['subnet_id'])
|
||||
except n_exc.SubnetNotFound:
|
||||
continue
|
||||
ip_addr = ip['ip_address']
|
||||
address += ' ' + ip_addr
|
||||
cidrs += ' {}/{}'.format(ip['ip_address'],
|
||||
subnet['cidr'].split('/')[1])
|
||||
|
||||
# Check if the port being created is a virtual port
|
||||
parents = utils.get_virtual_port_parents(
|
||||
self._nb_idl, ip_addr, port['network_id'], port['id'])
|
||||
if not parents:
|
||||
continue
|
||||
ip_subnets = port.get('fixed_ips', [])
|
||||
subnet_ids = [
|
||||
ip['subnet_id']
|
||||
for ip in ip_subnets
|
||||
if 'subnet_id' in ip
|
||||
]
|
||||
subnets = self._plugin.get_subnets(
|
||||
context, filters={'id': subnet_ids})
|
||||
if subnets:
|
||||
for ip in ip_subnets:
|
||||
ip_addr = ip['ip_address']
|
||||
address += ' ' + ip_addr
|
||||
subnet = None
|
||||
|
||||
port_type = ovn_const.LSP_TYPE_VIRTUAL
|
||||
options[ovn_const.LSP_OPTIONS_VIRTUAL_IP_KEY] = ip_addr
|
||||
options[ovn_const.LSP_OPTIONS_VIRTUAL_PARENTS_KEY] = (
|
||||
','.join(parents))
|
||||
break
|
||||
try:
|
||||
subnet = [
|
||||
sub
|
||||
for sub in subnets
|
||||
if sub["id"] == ip["subnet_id"]
|
||||
][0]
|
||||
except IndexError:
|
||||
LOG.debug('Subnet not found for ip address %s',
|
||||
ip_addr)
|
||||
continue
|
||||
|
||||
cidrs += ' {}/{}'.format(ip['ip_address'],
|
||||
subnet['cidr'].split('/')[1])
|
||||
|
||||
# Check if the port being created is a virtual port
|
||||
parents = utils.get_virtual_port_parents(
|
||||
self._nb_idl, ip_addr, port['network_id'], port['id'])
|
||||
if not parents:
|
||||
continue
|
||||
|
||||
port_type = ovn_const.LSP_TYPE_VIRTUAL
|
||||
options[ovn_const.LSP_OPTIONS_VIRTUAL_IP_KEY] = ip_addr
|
||||
options[ovn_const.LSP_OPTIONS_VIRTUAL_PARENTS_KEY] = (
|
||||
','.join(parents))
|
||||
break
|
||||
|
||||
# Only adjust the OVN type if the port is not owned by Neutron
|
||||
# DHCP agents.
|
||||
|
@ -565,9 +584,14 @@ class OVNClient(object):
|
|||
if self.is_metadata_port(port):
|
||||
context = n_context.get_admin_context()
|
||||
network = self._plugin.get_network(context, port['network_id'])
|
||||
subnet_ids = set(_ip['subnet_id'] for _ip in port['fixed_ips'])
|
||||
for subnet_id in subnet_ids:
|
||||
subnet = self._plugin.get_subnet(context, subnet_id)
|
||||
subnet_ids = [
|
||||
_ip['subnet_id']
|
||||
for _ip in port['fixed_ips']
|
||||
if 'subnet_id' in _ip
|
||||
]
|
||||
|
||||
for subnet in self._plugin.get_subnets(
|
||||
context, filters={'id': subnet_ids}):
|
||||
if not subnet['enable_dhcp']:
|
||||
continue
|
||||
self._update_subnet_dhcp_options(subnet, network, txn)
|
||||
|
|
|
@ -268,6 +268,26 @@ class SubnetDbObjectTestCase(obj_test_base.BaseDbObjectTestCase,
|
|||
self.assertEqual([service_type_obj.service_type],
|
||||
obj1.service_types)
|
||||
|
||||
def test_find_candidate_subnets(self):
|
||||
network = self._create_test_network()
|
||||
subnet_data = dict(self.obj_fields[0])
|
||||
subnet_data['network_id'] = network['id']
|
||||
subnet_net = self._make_object(subnet_data)
|
||||
subnet2_data = dict(self.obj_fields[0])
|
||||
subnet2_data['id'] = uuidutils.generate_uuid()
|
||||
subnet2_data['network_id'] = network['id']
|
||||
subnet2_net = self._make_object(subnet2_data)
|
||||
subnet_net.create()
|
||||
subnet2_net.create()
|
||||
fixed_ips = [
|
||||
{'subnet_id': subnet_data['id'], 'ip_address': '10.0.0.2'},
|
||||
{'subnet_id': subnet2_data['id'], 'ip_address': '10.0.1.2'}]
|
||||
candidate_subnet = subnet.Subnet.find_candidate_subnets(
|
||||
self.context, network['id'], None, None, True, fixed_ips)
|
||||
self.assertEqual(2, len(candidate_subnet))
|
||||
self.assertNotEqual(
|
||||
candidate_subnet[0]['id'], candidate_subnet[1]['id'])
|
||||
|
||||
|
||||
class NetworkSubnetLockTestCase(obj_test_base.BaseObjectIfaceTestCase):
|
||||
|
||||
|
|
|
@ -1727,6 +1727,65 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase):
|
|||
context.current, context.network.current, mock.ANY)
|
||||
umd.assert_called_once_with(mock.ANY, 'id', subnet=subnet)
|
||||
|
||||
def test__get_port_options(self):
|
||||
with mock.patch.object(self.mech_driver._plugin, 'get_subnets') as \
|
||||
mock_get_subnets:
|
||||
port = {'id': 'virt-port',
|
||||
'mac_address': '00:00:00:00:00:00',
|
||||
'device_owner': 'device_owner',
|
||||
'network_id': 'foo',
|
||||
'fixed_ips': [{'subnet_id': 'subnet-1',
|
||||
'ip_address': '10.0.0.55'},
|
||||
{'subnet_id': 'subnet-2',
|
||||
'ip_address': '10.0.1.55'},
|
||||
]}
|
||||
subnet_ids = [
|
||||
ip['subnet_id']
|
||||
for ip in port.get('fixed_ips')
|
||||
]
|
||||
self.mech_driver._ovn_client._get_port_options(port)
|
||||
mock_get_subnets.assert_called_once_with(
|
||||
mock.ANY,
|
||||
filters={'id': subnet_ids})
|
||||
|
||||
def test_update_port(self):
|
||||
with mock.patch.object(
|
||||
self.mech_driver._ovn_client, 'is_metadata_port') as \
|
||||
mock_is_metadata_port, \
|
||||
mock.patch.object(self.mech_driver._plugin, 'get_subnets') as \
|
||||
mock_get_subnets, \
|
||||
mock.patch.object(self.mech_driver._plugin, 'get_network') as \
|
||||
mock_get_network:
|
||||
net_attrs = {az_def.AZ_HINTS: ['az0', 'az1', 'az2']}
|
||||
fake_net = (
|
||||
fakes.FakeNetwork.create_one_network(attrs=net_attrs).info())
|
||||
port = {'id': 'virt-port',
|
||||
'mac_address': '00:00:00:00:00:00',
|
||||
'name': 'port-foo',
|
||||
'device_id': 'device_id-foo',
|
||||
'project_id': 'project_id-foo',
|
||||
'device_owner': 'device_owner',
|
||||
'network_id': 'foo',
|
||||
'admin_state_up': True,
|
||||
'fixed_ips': [{'subnet_id': 'subnet-1',
|
||||
'ip_address': '10.0.0.55'},
|
||||
{'subnet_id': 'subnet-2',
|
||||
'ip_address': '10.0.1.55'},
|
||||
]}
|
||||
subnet_ids = [
|
||||
ip['subnet_id']
|
||||
for ip in port.get('fixed_ips')
|
||||
]
|
||||
|
||||
mock_is_metadata_port.return_value = [True]
|
||||
mock_get_network.return_value = fake_net
|
||||
self.mech_driver._ovn_client.update_port(
|
||||
self.context, port)
|
||||
self.assertEqual(mock_get_subnets.call_count, 2)
|
||||
mock_get_subnets.assert_called_with(
|
||||
mock.ANY,
|
||||
filters={'id': subnet_ids})
|
||||
|
||||
def test_update_metadata_port_with_subnet(self):
|
||||
ovn_conf.cfg.CONF.set_override('ovn_metadata_enabled', True,
|
||||
group='ovn')
|
||||
|
|
Loading…
Reference in New Issue