Merge "Implement `get_subnets_address_scopes
` method"
This commit is contained in:
commit
5bce1ff51a
@ -857,6 +857,48 @@ def get_ovn_chassis_other_config(chassis):
|
||||
return chassis.external_ids
|
||||
|
||||
|
||||
def get_subnets_address_scopes(context, subnets, fixed_ips, ml2_plugin):
|
||||
"""Returns the IPv4 and IPv6 address scopes of several subnets.
|
||||
|
||||
The subnets hosted on the same network must be allocated from the same
|
||||
subnet pool (from ``NetworkSubnetPoolAffinityError`` exception). That
|
||||
applies per IP version (it means it is possible to have two subnet pools,
|
||||
one for IPv4 and one for IPv6).
|
||||
|
||||
:param context: neutron api request context
|
||||
:param subnets: (list of dict) subnet dictionaries
|
||||
:param fixed_ips: (list of dict) fixed IPs of several subnets (usually
|
||||
belonging to a network but not mandatory)
|
||||
:param ml2_plugin: (``Ml2Plugin``) ML2 plugin instance
|
||||
:return: (tuple of 2 strings) IPv4 and IPv6 address scope IDs
|
||||
"""
|
||||
address4_scope_id, address6_scope_id = '', ''
|
||||
if not subnets:
|
||||
return address4_scope_id, address6_scope_id
|
||||
|
||||
subnets_by_id = {subnet['id']: subnet for subnet in subnets}
|
||||
for fixed_ip in fixed_ips:
|
||||
subnet_id = fixed_ip.get('subnet_id')
|
||||
subnet = subnets_by_id.get(subnet_id)
|
||||
if not subnet or not subnet['subnetpool_id']:
|
||||
continue
|
||||
|
||||
try:
|
||||
subnet_pool = ml2_plugin.get_subnetpool(context,
|
||||
id=subnet['subnetpool_id'])
|
||||
if subnet_pool['address_scope_id']:
|
||||
if subnet_pool['ip_version'] == const.IP_VERSION_4:
|
||||
address4_scope_id = subnet_pool['address_scope_id']
|
||||
else:
|
||||
address6_scope_id = subnet_pool['address_scope_id']
|
||||
except n_exc.SubnetPoolNotFound:
|
||||
# swallow the exception and just continue if the
|
||||
# lookup failed
|
||||
pass
|
||||
|
||||
return address4_scope_id, address6_scope_id
|
||||
|
||||
|
||||
def sync_ha_chassis_group(context, network_id, nb_idl, sb_idl, txn):
|
||||
"""Return the UUID of the HA Chassis Group or the HA Chassis Group cmd.
|
||||
|
||||
|
@ -307,6 +307,9 @@ class OVNClient(object):
|
||||
]
|
||||
subnets = self._plugin.get_subnets(
|
||||
context, filters={'id': subnet_ids})
|
||||
address4_scope_id, address6_scope_id = (
|
||||
utils.get_subnets_address_scopes(context, subnets, ip_subnets,
|
||||
self._plugin))
|
||||
if subnets:
|
||||
for ip in ip_subnets:
|
||||
ip_addr = ip['ip_address']
|
||||
@ -324,26 +327,6 @@ class OVNClient(object):
|
||||
ip_addr)
|
||||
continue
|
||||
|
||||
if subnet["subnetpool_id"]:
|
||||
try:
|
||||
subnet_pool = self._plugin.get_subnetpool(
|
||||
context, id=subnet["subnetpool_id"]
|
||||
)
|
||||
if subnet_pool["address_scope_id"]:
|
||||
ip_version = subnet_pool["ip_version"]
|
||||
if ip_version == const.IP_VERSION_4:
|
||||
address4_scope_id = subnet_pool[
|
||||
"address_scope_id"
|
||||
]
|
||||
elif ip_version == const.IP_VERSION_6:
|
||||
address6_scope_id = subnet_pool[
|
||||
"address_scope_id"
|
||||
]
|
||||
except n_exc.SubnetPoolNotFound:
|
||||
# swallow the exception and just continue if the
|
||||
# lookup failed
|
||||
pass
|
||||
|
||||
cidrs += ' {}/{}'.format(ip['ip_address'],
|
||||
subnet['cidr'].split('/')[1])
|
||||
|
||||
|
@ -23,6 +23,7 @@ import neutron_lib
|
||||
from neutron_lib.api.definitions import extra_dhcp_opt as edo_ext
|
||||
from neutron_lib.api.definitions import portbindings
|
||||
from neutron_lib import constants as n_const
|
||||
from neutron_lib import exceptions as n_exc
|
||||
from oslo_concurrency import processutils
|
||||
from oslo_config import cfg
|
||||
import testtools
|
||||
@ -943,3 +944,62 @@ class TestOvsdbClientCommand(base.BaseTestCase):
|
||||
def test_run_bad_schema(self):
|
||||
with testtools.ExpectedException(KeyError):
|
||||
self.OvsdbClientTestCommand.run(['foo'])
|
||||
|
||||
|
||||
class GetSubnetsAddressScopeTestCase(base.BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.ml2_plugin = mock.Mock()
|
||||
|
||||
def test_no_subnets(self):
|
||||
subnets = []
|
||||
fixed_ips = mock.ANY
|
||||
address4, address6 = utils.get_subnets_address_scopes(
|
||||
mock.ANY, subnets, fixed_ips, self.ml2_plugin)
|
||||
self.assertEqual(('', ''), (address4, address6))
|
||||
|
||||
def test_no_subnetpool(self):
|
||||
subnets = [
|
||||
{'id': 'subnet1', 'subnetpool_id': None},
|
||||
{'id': 'subnet2', 'subnetpool_id': None},
|
||||
]
|
||||
fixed_ips = [
|
||||
{'subnet_id': 'subnet1'},
|
||||
{'subnet_id': 'subnet2'},
|
||||
]
|
||||
address4, address6 = utils.get_subnets_address_scopes(
|
||||
mock.ANY, subnets, fixed_ips, self.ml2_plugin)
|
||||
self.assertEqual(('', ''), (address4, address6))
|
||||
|
||||
def test_no_address_scope(self):
|
||||
subnets = [
|
||||
{'id': 'subnet1', 'subnetpool_id': 'pool_ipv4'},
|
||||
{'id': 'subnet2', 'subnetpool_id': 'pool_ipv6'},
|
||||
]
|
||||
fixed_ips = [
|
||||
{'subnet_id': 'subnet1'},
|
||||
{'subnet_id': 'subnet2'},
|
||||
]
|
||||
self.ml2_plugin.get_subnetpool.side_effect = n_exc.SubnetPoolNotFound(
|
||||
subnetpool_id='snp')
|
||||
address4, address6 = utils.get_subnets_address_scopes(
|
||||
mock.ANY, subnets, fixed_ips, self.ml2_plugin)
|
||||
self.assertEqual(('', ''), (address4, address6))
|
||||
|
||||
def test_address_scope(self):
|
||||
subnets = [
|
||||
{'id': 'subnet1', 'subnetpool_id': 'pool_ipv4'},
|
||||
{'id': 'subnet2', 'subnetpool_id': 'pool_ipv6'},
|
||||
]
|
||||
fixed_ips = [
|
||||
{'subnet_id': 'subnet1'},
|
||||
{'subnet_id': 'subnet2'},
|
||||
]
|
||||
self.ml2_plugin.get_subnetpool.side_effect = [
|
||||
{'address_scope_id': 'scope4', 'ip_version': n_const.IP_VERSION_4},
|
||||
{'address_scope_id': 'scope6', 'ip_version': n_const.IP_VERSION_6},
|
||||
]
|
||||
address4, address6 = utils.get_subnets_address_scopes(
|
||||
mock.ANY, subnets, fixed_ips, self.ml2_plugin)
|
||||
self.assertEqual(('scope4', 'scope6'), (address4, address6))
|
||||
|
Loading…
Reference in New Issue
Block a user