Merge "Support Subnets that are configured by external RAs"

This commit is contained in:
Jenkins 2014-06-10 18:49:01 +00:00 committed by Gerrit Code Review
commit d2dca92c0e
3 changed files with 52 additions and 7 deletions

View File

@ -26,6 +26,7 @@ from sqlalchemy import sql
from neutron.api.v2 import attributes
from neutron.common import constants
from neutron.common import exceptions as n_exc
from neutron.common import ipv6_utils
from neutron import context as ctx
from neutron.db import api as db
from neutron.db import models_v2
@ -351,6 +352,12 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
ip_address=ip_address,
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
def _generate_ip(context, subnets):
try:
@ -670,6 +677,20 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
v4.append(subnet)
else:
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]
for subnets in version_subnets:
if subnets:
@ -1378,7 +1399,6 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
p = port['port']
port_id = p.get('id') or uuidutils.generate_uuid()
network_id = p['network_id']
mac_address = p['mac_address']
# NOTE(jkoelker) Get the tenant_id outside of the session to avoid
# unneeded db action if the operation raises
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
# network
if mac_address is attributes.ATTR_NOT_SPECIFIED:
mac_address = NeutronDbPluginV2._generate_mac(context,
network_id)
if p['mac_address'] is attributes.ATTR_NOT_SPECIFIED:
#Note(scollins) Add the generated mac_address to the port,
#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:
# Ensure that the mac on the network is unique
if not NeutronDbPluginV2._check_unique_mac(context,
network_id,
mac_address):
p['mac_address']):
raise n_exc.MacAddressInUse(net_id=network_id,
mac=mac_address)
mac=p['mac_address'])
# Returns the IP's for the port
ips = self._allocate_ips_for_port(context, network, port)
@ -1414,7 +1437,7 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
name=p['name'],
id=port_id,
network_id=network_id,
mac_address=mac_address,
mac_address=p['mac_address'],
admin_state_up=p['admin_state_up'],
status=status,
device_id=p['device_id'],

View File

@ -115,6 +115,9 @@ class TestOneConvergencePluginPortsV2(test_plugin.TestPortsV2,
self.assertEqual(port['binding:vif_type'],
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,
OneConvergencePluginV2TestCase):

View File

@ -30,6 +30,7 @@ from neutron.api.v2 import attributes
from neutron.api.v2 import router
from neutron.common import constants
from neutron.common import exceptions as n_exc
from neutron.common import ipv6_utils
from neutron.common import test_lib
from neutron.common import utils
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', 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):
with self.subnet(gateway_ip='10.0.0.3',
cidr='10.0.0.0/29') as subnet: