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
|
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):
|
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.
|
"""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(
|
subnets = self._plugin.get_subnets(
|
||||||
context, filters={'id': subnet_ids})
|
context, filters={'id': subnet_ids})
|
||||||
|
address4_scope_id, address6_scope_id = (
|
||||||
|
utils.get_subnets_address_scopes(context, subnets, ip_subnets,
|
||||||
|
self._plugin))
|
||||||
if subnets:
|
if subnets:
|
||||||
for ip in ip_subnets:
|
for ip in ip_subnets:
|
||||||
ip_addr = ip['ip_address']
|
ip_addr = ip['ip_address']
|
||||||
@ -324,26 +327,6 @@ class OVNClient(object):
|
|||||||
ip_addr)
|
ip_addr)
|
||||||
continue
|
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'],
|
cidrs += ' {}/{}'.format(ip['ip_address'],
|
||||||
subnet['cidr'].split('/')[1])
|
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 extra_dhcp_opt as edo_ext
|
||||||
from neutron_lib.api.definitions import portbindings
|
from neutron_lib.api.definitions import portbindings
|
||||||
from neutron_lib import constants as n_const
|
from neutron_lib import constants as n_const
|
||||||
|
from neutron_lib import exceptions as n_exc
|
||||||
from oslo_concurrency import processutils
|
from oslo_concurrency import processutils
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
import testtools
|
import testtools
|
||||||
@ -943,3 +944,62 @@ class TestOvsdbClientCommand(base.BaseTestCase):
|
|||||||
def test_run_bad_schema(self):
|
def test_run_bad_schema(self):
|
||||||
with testtools.ExpectedException(KeyError):
|
with testtools.ExpectedException(KeyError):
|
||||||
self.OvsdbClientTestCommand.run(['foo'])
|
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