subnets = self.get_subnets(context, filters=filter)
# Split into v4 and v6 subnets
v4 = []
- v6 = []
+ v6_stateful = []
+ v6_stateless = []
for subnet in subnets:
if subnet['ip_version'] == 4:
v4.append(subnet)
else:
- v6.append(subnet)
- for subnet in v6:
- if ipv6_utils.is_auto_address_subnet(subnet):
- #(dzyu) If true, calculate an IPv6 address
- # by mac address and prefix, then remove this
- # subnet from the array of subnets that will be passed
- # to the _generate_ip() function call, since we just
- # generated an IP.
- prefix = subnet['cidr']
- ip_address = ipv6_utils.get_ipv6_addr_by_EUI64(
- prefix, p['mac_address'])
- if not self._check_unique_ip(
- context, p['network_id'],
- subnet['id'], ip_address.format()):
- raise n_exc.IpAddressInUse(
- net_id=p['network_id'],
- ip_address=ip_address.format())
- ips.append({'ip_address': ip_address.format(),
- 'subnet_id': subnet['id']})
- v6.remove(subnet)
- version_subnets = [v4, v6]
+ if ipv6_utils.is_auto_address_subnet(subnet):
+ v6_stateless.append(subnet)
+ else:
+ v6_stateful.append(subnet)
+
+ for subnet in v6_stateless:
+ prefix = subnet['cidr']
+ ip_address = ipv6_utils.get_ipv6_addr_by_EUI64(
+ prefix, p['mac_address'])
+ if not self._check_unique_ip(
+ context, p['network_id'],
+ subnet['id'], ip_address.format()):
+ raise n_exc.IpAddressInUse(
+ net_id=p['network_id'],
+ ip_address=ip_address.format())
+ ips.append({'ip_address': ip_address.format(),
+ 'subnet_id': subnet['id']})
+ version_subnets = [v4, v6_stateful]
for subnets in version_subnets:
if subnets:
result = NeutronDbPluginV2._generate_ip(context, subnets)
port_mac))
self.assertEqual(port['port']['fixed_ips'][0]['ip_address'], eui_addr)
+ def test_ip_allocation_for_ipv6_2_subnet_slaac_mode(self):
+ res = self._create_network(fmt=self.fmt, name='net',
+ admin_state_up=True)
+ network = self.deserialize(self.fmt, res)
+ v6_subnet_1 = self._make_subnet(self.fmt, network,
+ gateway='2001:100::1',
+ cidr='2001:100::0/64',
+ ip_version=6,
+ ipv6_ra_mode=constants.IPV6_SLAAC)
+ v6_subnet_2 = self._make_subnet(self.fmt, network,
+ gateway='2001:200::1',
+ cidr='2001:200::0/64',
+ ip_version=6,
+ ipv6_ra_mode=constants.IPV6_SLAAC)
+ port = self._make_port(self.fmt, network['network']['id'])
+ self.assertEqual(len(port['port']['fixed_ips']), 2)
+ port_mac = port['port']['mac_address']
+ cidr_1 = v6_subnet_1['subnet']['cidr']
+ cidr_2 = v6_subnet_2['subnet']['cidr']
+ eui_addr_1 = str(ipv6_utils.get_ipv6_addr_by_EUI64(cidr_1,
+ port_mac))
+ eui_addr_2 = str(ipv6_utils.get_ipv6_addr_by_EUI64(cidr_2,
+ port_mac))
+ self.assertEqual(port['port']['fixed_ips'][0]['ip_address'],
+ eui_addr_1)
+ self.assertEqual(port['port']['fixed_ips'][1]['ip_address'],
+ eui_addr_2)
+
def test_range_allocation(self):
with self.subnet(gateway_ip='10.0.0.3',
cidr='10.0.0.0/29') as subnet:
self._validate_rebuild_availability_ranges(pools, allocations,
expected)
+ def _test__allocate_ips_for_port(self, subnets, port, expected):
+ plugin = db_base_plugin_v2.NeutronDbPluginV2()
+ with mock.patch.object(db_base_plugin_v2.NeutronDbPluginV2,
+ 'get_subnets') as get_subnets:
+ with mock.patch.object(db_base_plugin_v2.NeutronDbPluginV2,
+ '_check_unique_ip') as check_unique:
+ context = mock.Mock()
+ get_subnets.return_value = subnets
+ check_unique.return_value = True
+ actual = plugin._allocate_ips_for_port(context, port)
+ self.assertEqual(expected, actual)
+
+ def test__allocate_ips_for_port_2_slaac_subnets(self):
+ subnets = [
+ {
+ 'cidr': u'2001:100::/64',
+ 'enable_dhcp': True,
+ 'gateway_ip': u'2001:100::1',
+ 'id': u'd1a28edd-bd83-480a-bd40-93d036c89f13',
+ 'ip_version': 6,
+ 'ipv6_address_mode': None,
+ 'ipv6_ra_mode': u'slaac'},
+ {
+ 'cidr': u'2001:200::/64',
+ 'enable_dhcp': True,
+ 'gateway_ip': u'2001:200::1',
+ 'id': u'dc813d3d-ed66-4184-8570-7325c8195e28',
+ 'ip_version': 6,
+ 'ipv6_address_mode': None,
+ 'ipv6_ra_mode': u'slaac'}]
+ port = {'port': {
+ 'network_id': 'fbb9b578-95eb-4b79-a116-78e5c4927176',
+ 'fixed_ips': attributes.ATTR_NOT_SPECIFIED,
+ 'mac_address': '12:34:56:78:44:ab'}}
+ expected = []
+ for subnet in subnets:
+ addr = str(ipv6_utils.get_ipv6_addr_by_EUI64(
+ subnet['cidr'], port['port']['mac_address']))
+ expected.append({'ip_address': addr, 'subnet_id': subnet['id']})
+
+ self._test__allocate_ips_for_port(subnets, port, expected)
+
class NeutronDbPluginV2AsMixinTestCase(testlib_api.SqlTestCase):
"""Tests for NeutronDbPluginV2 as Mixin.