Merge "Support Subnets that are configured by external RAs"
This commit is contained in:
@@ -26,6 +26,7 @@ from sqlalchemy import sql
|
|||||||
from neutron.api.v2 import attributes
|
from neutron.api.v2 import attributes
|
||||||
from neutron.common import constants
|
from neutron.common import constants
|
||||||
from neutron.common import exceptions as n_exc
|
from neutron.common import exceptions as n_exc
|
||||||
|
from neutron.common import ipv6_utils
|
||||||
from neutron import context as ctx
|
from neutron import context as ctx
|
||||||
from neutron.db import api as db
|
from neutron.db import api as db
|
||||||
from neutron.db import models_v2
|
from neutron.db import models_v2
|
||||||
@@ -351,6 +352,12 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
|
|||||||
ip_address=ip_address,
|
ip_address=ip_address,
|
||||||
subnet_id=subnet_id).delete()
|
subnet_id=subnet_id).delete()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _check_if_subnet_uses_eui64(subnet):
|
||||||
|
"""Check if ipv6 address will be calculated via EUI64."""
|
||||||
|
return (subnet['ipv6_address_mode'] == constants.IPV6_SLAAC
|
||||||
|
or subnet['ipv6_address_mode'] == constants.DHCPV6_STATELESS)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _generate_ip(context, subnets):
|
def _generate_ip(context, subnets):
|
||||||
try:
|
try:
|
||||||
@@ -670,6 +677,20 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
|
|||||||
v4.append(subnet)
|
v4.append(subnet)
|
||||||
else:
|
else:
|
||||||
v6.append(subnet)
|
v6.append(subnet)
|
||||||
|
for subnet in v6:
|
||||||
|
if self._check_if_subnet_uses_eui64(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.
|
||||||
|
mac = p['mac_address']
|
||||||
|
prefix = subnet['cidr']
|
||||||
|
ip_address = ipv6_utils.get_ipv6_addr_by_EUI64(
|
||||||
|
prefix, mac)
|
||||||
|
ips.append({'ip_address': ip_address.format(),
|
||||||
|
'subnet_id': subnet['id']})
|
||||||
|
v6.remove(subnet)
|
||||||
version_subnets = [v4, v6]
|
version_subnets = [v4, v6]
|
||||||
for subnets in version_subnets:
|
for subnets in version_subnets:
|
||||||
if subnets:
|
if subnets:
|
||||||
@@ -1378,7 +1399,6 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
|
|||||||
p = port['port']
|
p = port['port']
|
||||||
port_id = p.get('id') or uuidutils.generate_uuid()
|
port_id = p.get('id') or uuidutils.generate_uuid()
|
||||||
network_id = p['network_id']
|
network_id = p['network_id']
|
||||||
mac_address = p['mac_address']
|
|
||||||
# NOTE(jkoelker) Get the tenant_id outside of the session to avoid
|
# NOTE(jkoelker) Get the tenant_id outside of the session to avoid
|
||||||
# unneeded db action if the operation raises
|
# unneeded db action if the operation raises
|
||||||
tenant_id = self._get_tenant_id_for_create(context, p)
|
tenant_id = self._get_tenant_id_for_create(context, p)
|
||||||
@@ -1391,16 +1411,19 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
|
|||||||
|
|
||||||
# Ensure that a MAC address is defined and it is unique on the
|
# Ensure that a MAC address is defined and it is unique on the
|
||||||
# network
|
# network
|
||||||
if mac_address is attributes.ATTR_NOT_SPECIFIED:
|
if p['mac_address'] is attributes.ATTR_NOT_SPECIFIED:
|
||||||
mac_address = NeutronDbPluginV2._generate_mac(context,
|
#Note(scollins) Add the generated mac_address to the port,
|
||||||
network_id)
|
#since _allocate_ips_for_port will need the mac when
|
||||||
|
#calculating an EUI-64 address for a v6 subnet
|
||||||
|
p['mac_address'] = NeutronDbPluginV2._generate_mac(context,
|
||||||
|
network_id)
|
||||||
else:
|
else:
|
||||||
# Ensure that the mac on the network is unique
|
# Ensure that the mac on the network is unique
|
||||||
if not NeutronDbPluginV2._check_unique_mac(context,
|
if not NeutronDbPluginV2._check_unique_mac(context,
|
||||||
network_id,
|
network_id,
|
||||||
mac_address):
|
p['mac_address']):
|
||||||
raise n_exc.MacAddressInUse(net_id=network_id,
|
raise n_exc.MacAddressInUse(net_id=network_id,
|
||||||
mac=mac_address)
|
mac=p['mac_address'])
|
||||||
|
|
||||||
# Returns the IP's for the port
|
# Returns the IP's for the port
|
||||||
ips = self._allocate_ips_for_port(context, network, port)
|
ips = self._allocate_ips_for_port(context, network, port)
|
||||||
@@ -1414,7 +1437,7 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
|
|||||||
name=p['name'],
|
name=p['name'],
|
||||||
id=port_id,
|
id=port_id,
|
||||||
network_id=network_id,
|
network_id=network_id,
|
||||||
mac_address=mac_address,
|
mac_address=p['mac_address'],
|
||||||
admin_state_up=p['admin_state_up'],
|
admin_state_up=p['admin_state_up'],
|
||||||
status=status,
|
status=status,
|
||||||
device_id=p['device_id'],
|
device_id=p['device_id'],
|
||||||
|
|||||||
@@ -115,6 +115,9 @@ class TestOneConvergencePluginPortsV2(test_plugin.TestPortsV2,
|
|||||||
self.assertEqual(port['binding:vif_type'],
|
self.assertEqual(port['binding:vif_type'],
|
||||||
portbindings.VIF_TYPE_OVS)
|
portbindings.VIF_TYPE_OVS)
|
||||||
|
|
||||||
|
def test_ip_allocation_for_ipv6_subnet_slaac_adddress_mode(self):
|
||||||
|
self.skipTest("NVSD Plugin does not support IPV6.")
|
||||||
|
|
||||||
|
|
||||||
class TestOneConvergenceBasicGet(test_plugin.TestBasicGet,
|
class TestOneConvergenceBasicGet(test_plugin.TestBasicGet,
|
||||||
OneConvergencePluginV2TestCase):
|
OneConvergencePluginV2TestCase):
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ from neutron.api.v2 import attributes
|
|||||||
from neutron.api.v2 import router
|
from neutron.api.v2 import router
|
||||||
from neutron.common import constants
|
from neutron.common import constants
|
||||||
from neutron.common import exceptions as n_exc
|
from neutron.common import exceptions as n_exc
|
||||||
|
from neutron.common import ipv6_utils
|
||||||
from neutron.common import test_lib
|
from neutron.common import test_lib
|
||||||
from neutron.common import utils
|
from neutron.common import utils
|
||||||
from neutron import context
|
from neutron import context
|
||||||
@@ -1397,6 +1398,24 @@ fixed_ips=ip_address%%3D%s&fixed_ips=ip_address%%3D%s&fixed_ips=subnet_id%%3D%s
|
|||||||
self._delete('ports', port3['port']['id'])
|
self._delete('ports', port3['port']['id'])
|
||||||
self._delete('ports', port4['port']['id'])
|
self._delete('ports', port4['port']['id'])
|
||||||
|
|
||||||
|
def test_ip_allocation_for_ipv6_subnet_slaac_adddress_mode(self):
|
||||||
|
res = self._create_network(fmt=self.fmt, name='net',
|
||||||
|
admin_state_up=True)
|
||||||
|
network = self.deserialize(self.fmt, res)
|
||||||
|
v6_subnet = self._make_subnet(self.fmt, network,
|
||||||
|
gateway='fe80::1',
|
||||||
|
cidr='fe80::/80',
|
||||||
|
ip_version=6,
|
||||||
|
ipv6_ra_mode=None,
|
||||||
|
ipv6_address_mode=constants.IPV6_SLAAC)
|
||||||
|
port = self._make_port(self.fmt, network['network']['id'])
|
||||||
|
self.assertEqual(len(port['port']['fixed_ips']), 1)
|
||||||
|
port_mac = port['port']['mac_address']
|
||||||
|
subnet_cidr = v6_subnet['subnet']['cidr']
|
||||||
|
eui_addr = str(ipv6_utils.get_ipv6_addr_by_EUI64(subnet_cidr,
|
||||||
|
port_mac))
|
||||||
|
self.assertEqual(port['port']['fixed_ips'][0]['ip_address'], eui_addr)
|
||||||
|
|
||||||
def test_range_allocation(self):
|
def test_range_allocation(self):
|
||||||
with self.subnet(gateway_ip='10.0.0.3',
|
with self.subnet(gateway_ip='10.0.0.3',
|
||||||
cidr='10.0.0.0/29') as subnet:
|
cidr='10.0.0.0/29') as subnet:
|
||||||
|
|||||||
Reference in New Issue
Block a user