Hide IPv6-addresses when assigning floating IP addresses
A floating IP can only be associated with an IPv4 address, so we should not show IPv6 addresses in the list of ports when assigning floating IP addresses. Change-Id: I7b39a263445204a9efbc8fe113cc79146d9bee8c Closes-Bug: #1703360 Closes-Bug: #1724393
This commit is contained in:
parent
4927f5fae4
commit
9d5be5251f
@ -669,6 +669,9 @@ class FloatingIpManager(object):
|
|||||||
for ip in p.fixed_ips:
|
for ip in p.fixed_ips:
|
||||||
if ip['subnet_id'] not in reachable_subnets:
|
if ip['subnet_id'] not in reachable_subnets:
|
||||||
continue
|
continue
|
||||||
|
# Floating IPs can only target IPv4 addresses.
|
||||||
|
if netaddr.IPAddress(ip['ip_address']).version != 4:
|
||||||
|
continue
|
||||||
targets.append(FloatingIpTarget(p, ip['ip_address'],
|
targets.append(FloatingIpTarget(p, ip['ip_address'],
|
||||||
server_name))
|
server_name))
|
||||||
return targets
|
return targets
|
||||||
|
@ -175,7 +175,7 @@ class NetworkSubnetTests(test.TestCase):
|
|||||||
'subnetpool_list')})
|
'subnetpool_list')})
|
||||||
def test_subnet_create_post_with_additional_attributes(self):
|
def test_subnet_create_post_with_additional_attributes(self):
|
||||||
network = self.networks.list()[1]
|
network = self.networks.list()[1]
|
||||||
subnet = self.subnets.list()[1]
|
subnet = self.subnets.list()[2]
|
||||||
api.neutron.network_get(IsA(http.HttpRequest),
|
api.neutron.network_get(IsA(http.HttpRequest),
|
||||||
network.id)\
|
network.id)\
|
||||||
.AndReturn(self.networks.first())
|
.AndReturn(self.networks.first())
|
||||||
@ -951,7 +951,7 @@ class NetworkSubnetTests(test.TestCase):
|
|||||||
'is_extension_supported',
|
'is_extension_supported',
|
||||||
'subnetpool_list')})
|
'subnetpool_list')})
|
||||||
def test_subnet_update_post_with_additional_attributes(self):
|
def test_subnet_update_post_with_additional_attributes(self):
|
||||||
subnet = self.subnets.list()[1]
|
subnet = self.subnets.list()[2]
|
||||||
api.neutron.subnet_get(IsA(http.HttpRequest), subnet.id)\
|
api.neutron.subnet_get(IsA(http.HttpRequest), subnet.id)\
|
||||||
.AndReturn(subnet)
|
.AndReturn(subnet)
|
||||||
api.neutron.subnet_get(IsA(http.HttpRequest), subnet.id)\
|
api.neutron.subnet_get(IsA(http.HttpRequest), subnet.id)\
|
||||||
|
@ -685,7 +685,7 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
|
|||||||
test_with_subnetpool=False
|
test_with_subnetpool=False
|
||||||
):
|
):
|
||||||
network = self.networks.first()
|
network = self.networks.first()
|
||||||
subnet_v6 = self.subnets.list()[3]
|
subnet_v6 = self.subnets.list()[4]
|
||||||
|
|
||||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||||
'subnet_allocation').\
|
'subnet_allocation').\
|
||||||
@ -936,12 +936,14 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
|
|||||||
network = self.networks.first()
|
network = self.networks.first()
|
||||||
network.subnets = [subnet.id for subnet in network.subnets]
|
network.subnets = [subnet.id for subnet in network.subnets]
|
||||||
subnet_id = network.subnets[0]
|
subnet_id = network.subnets[0]
|
||||||
|
subnetv6_id = network.subnets[1]
|
||||||
api.neutron.network_get(IsA(http.HttpRequest),
|
api.neutron.network_get(IsA(http.HttpRequest),
|
||||||
network.id,
|
network.id,
|
||||||
expand_subnet=False)\
|
expand_subnet=False)\
|
||||||
.AndReturn(network)
|
.AndReturn(network)
|
||||||
self._stub_net_list()
|
self._stub_net_list()
|
||||||
api.neutron.subnet_delete(IsA(http.HttpRequest), subnet_id)
|
api.neutron.subnet_delete(IsA(http.HttpRequest), subnet_id)
|
||||||
|
api.neutron.subnet_delete(IsA(http.HttpRequest), subnetv6_id)
|
||||||
api.neutron.network_delete(IsA(http.HttpRequest), network.id)
|
api.neutron.network_delete(IsA(http.HttpRequest), network.id)
|
||||||
|
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
@ -959,12 +961,14 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
|
|||||||
network = self.networks.first()
|
network = self.networks.first()
|
||||||
network.subnets = [subnet.id for subnet in network.subnets]
|
network.subnets = [subnet.id for subnet in network.subnets]
|
||||||
subnet_id = network.subnets[0]
|
subnet_id = network.subnets[0]
|
||||||
|
subnetv6_id = network.subnets[1]
|
||||||
api.neutron.network_get(IsA(http.HttpRequest),
|
api.neutron.network_get(IsA(http.HttpRequest),
|
||||||
network.id,
|
network.id,
|
||||||
expand_subnet=False)\
|
expand_subnet=False)\
|
||||||
.AndReturn(network)
|
.AndReturn(network)
|
||||||
self._stub_net_list()
|
self._stub_net_list()
|
||||||
api.neutron.subnet_delete(IsA(http.HttpRequest), subnet_id)
|
api.neutron.subnet_delete(IsA(http.HttpRequest), subnet_id)
|
||||||
|
api.neutron.subnet_delete(IsA(http.HttpRequest), subnetv6_id)
|
||||||
api.neutron.network_delete(IsA(http.HttpRequest), network.id)\
|
api.neutron.network_delete(IsA(http.HttpRequest), network.id)\
|
||||||
.AndRaise(self.exceptions.neutron)
|
.AndRaise(self.exceptions.neutron)
|
||||||
|
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
import collections
|
import collections
|
||||||
|
|
||||||
|
import netaddr
|
||||||
|
|
||||||
from django.test.utils import override_settings
|
from django.test.utils import override_settings
|
||||||
|
|
||||||
from openstack_dashboard import api
|
from openstack_dashboard import api
|
||||||
@ -34,23 +36,24 @@ class NetworkApiNeutronTests(NetworkApiNeutronTestBase):
|
|||||||
for p in server_ports:
|
for p in server_ports:
|
||||||
net_name = self.networks.get(id=p['network_id']).name
|
net_name = self.networks.get(id=p['network_id']).name
|
||||||
for ip in p.fixed_ips:
|
for ip in p.fixed_ips:
|
||||||
|
version = netaddr.IPAddress(ip['ip_address']).version
|
||||||
addresses[net_name].append(
|
addresses[net_name].append(
|
||||||
{'version': 4,
|
{'version': version,
|
||||||
'addr': ip['ip_address'],
|
'addr': ip['ip_address'],
|
||||||
'OS-EXT-IPS-MAC:mac_addr': p.mac_address,
|
'OS-EXT-IPS-MAC:mac_addr': p.mac_address,
|
||||||
'OS-EXT-IPS:type': 'fixed'})
|
'OS-EXT-IPS:type': 'fixed'})
|
||||||
if no_fip_expected:
|
if no_fip_expected:
|
||||||
continue
|
continue
|
||||||
fips = self.floating_ips.filter(port_id=p['id'])
|
fips = self.floating_ips.filter(port_id=p['id'])
|
||||||
if not fips:
|
if not fips:
|
||||||
continue
|
continue
|
||||||
# Only one FIP should match.
|
# Only one FIP should match.
|
||||||
fip = fips[0]
|
fip = fips[0]
|
||||||
addresses[net_name].append(
|
addresses[net_name].append(
|
||||||
{'version': 4,
|
{'version': 4,
|
||||||
'addr': fip.floating_ip_address,
|
'addr': fip.floating_ip_address,
|
||||||
'OS-EXT-IPS-MAC:mac_addr': p.mac_address,
|
'OS-EXT-IPS-MAC:mac_addr': p.mac_address,
|
||||||
'OS-EXT-IPS:type': 'floating'})
|
'OS-EXT-IPS:type': 'floating'})
|
||||||
return addresses
|
return addresses
|
||||||
|
|
||||||
def _check_server_address(self, res_server_data, no_fip_expected=False):
|
def _check_server_address(self, res_server_data, no_fip_expected=False):
|
||||||
@ -105,12 +108,14 @@ class NetworkApiNeutronTests(NetworkApiNeutronTestBase):
|
|||||||
# The expected is also calculated, we examine the result manually once.
|
# The expected is also calculated, we examine the result manually once.
|
||||||
addrs = servers[0].addresses['net1']
|
addrs = servers[0].addresses['net1']
|
||||||
if router_enabled:
|
if router_enabled:
|
||||||
|
self.assertEqual(3, len(addrs))
|
||||||
|
self.assertEqual('fixed', addrs[0]['OS-EXT-IPS:type'])
|
||||||
|
self.assertEqual('fixed', addrs[1]['OS-EXT-IPS:type'])
|
||||||
|
self.assertEqual('floating', addrs[2]['OS-EXT-IPS:type'])
|
||||||
|
else:
|
||||||
self.assertEqual(2, len(addrs))
|
self.assertEqual(2, len(addrs))
|
||||||
self.assertEqual('fixed', addrs[0]['OS-EXT-IPS:type'])
|
self.assertEqual('fixed', addrs[0]['OS-EXT-IPS:type'])
|
||||||
self.assertEqual('floating', addrs[1]['OS-EXT-IPS:type'])
|
self.assertEqual('fixed', addrs[1]['OS-EXT-IPS:type'])
|
||||||
else:
|
|
||||||
self.assertEqual(1, len(addrs))
|
|
||||||
self.assertEqual('fixed', addrs[0]['OS-EXT-IPS:type'])
|
|
||||||
|
|
||||||
# server[1] has one fixed IP.
|
# server[1] has one fixed IP.
|
||||||
self._check_server_address(servers[1], no_fip_expected)
|
self._check_server_address(servers[1], no_fip_expected)
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
import copy
|
import copy
|
||||||
|
|
||||||
from mox3.mox import IsA
|
from mox3.mox import IsA
|
||||||
|
import netaddr
|
||||||
from neutronclient.common import exceptions as neutron_exc
|
from neutronclient.common import exceptions as neutron_exc
|
||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
import six
|
import six
|
||||||
@ -165,17 +166,20 @@ class NeutronApiTests(test.APITestCase):
|
|||||||
def test_network_get(self):
|
def test_network_get(self):
|
||||||
network = {'network': self.api_networks.first()}
|
network = {'network': self.api_networks.first()}
|
||||||
subnet = {'subnet': self.api_subnets.first()}
|
subnet = {'subnet': self.api_subnets.first()}
|
||||||
|
subnetv6 = {'subnet': self.api_subnets.list()[1]}
|
||||||
network_id = self.api_networks.first()['id']
|
network_id = self.api_networks.first()['id']
|
||||||
subnet_id = self.api_networks.first()['subnets'][0]
|
subnet_id = self.api_networks.first()['subnets'][0]
|
||||||
|
subnetv6_id = self.api_networks.first()['subnets'][1]
|
||||||
|
|
||||||
neutronclient = self.stub_neutronclient()
|
neutronclient = self.stub_neutronclient()
|
||||||
neutronclient.show_network(network_id).AndReturn(network)
|
neutronclient.show_network(network_id).AndReturn(network)
|
||||||
neutronclient.show_subnet(subnet_id).AndReturn(subnet)
|
neutronclient.show_subnet(subnet_id).AndReturn(subnet)
|
||||||
|
neutronclient.show_subnet(subnetv6_id).AndReturn(subnetv6)
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
ret_val = api.neutron.network_get(self.request, network_id)
|
ret_val = api.neutron.network_get(self.request, network_id)
|
||||||
self.assertIsInstance(ret_val, api.neutron.Network)
|
self.assertIsInstance(ret_val, api.neutron.Network)
|
||||||
self.assertEqual(1, len(ret_val['subnets']))
|
self.assertEqual(2, len(ret_val['subnets']))
|
||||||
self.assertIsInstance(ret_val['subnets'][0], api.neutron.Subnet)
|
self.assertIsInstance(ret_val['subnets'][0], api.neutron.Subnet)
|
||||||
|
|
||||||
def test_network_get_with_subnet_get_notfound(self):
|
def test_network_get_with_subnet_get_notfound(self):
|
||||||
@ -190,7 +194,7 @@ class NeutronApiTests(test.APITestCase):
|
|||||||
|
|
||||||
ret_val = api.neutron.network_get(self.request, network_id)
|
ret_val = api.neutron.network_get(self.request, network_id)
|
||||||
self.assertIsInstance(ret_val, api.neutron.Network)
|
self.assertIsInstance(ret_val, api.neutron.Network)
|
||||||
self.assertEqual(1, len(ret_val['subnets']))
|
self.assertEqual(2, len(ret_val['subnets']))
|
||||||
self.assertNotIsInstance(ret_val['subnets'][0], api.neutron.Subnet)
|
self.assertNotIsInstance(ret_val['subnets'][0], api.neutron.Subnet)
|
||||||
self.assertIsInstance(ret_val['subnets'][0], str)
|
self.assertIsInstance(ret_val['subnets'][0], str)
|
||||||
|
|
||||||
@ -1160,19 +1164,16 @@ class NeutronApiFloatingIpTests(NeutronApiTestBase):
|
|||||||
|
|
||||||
api.neutron.floating_ip_disassociate(self.request, fip['id'])
|
api.neutron.floating_ip_disassociate(self.request, fip['id'])
|
||||||
|
|
||||||
def _get_target_id(self, port):
|
def _get_target_id(self, port, ip=None):
|
||||||
param = {'id': port['id'],
|
param = {'id': port['id'],
|
||||||
'addr': port['fixed_ips'][0]['ip_address']}
|
'addr': ip or port['fixed_ips'][0]['ip_address']}
|
||||||
return '%(id)s_%(addr)s' % param
|
return '%(id)s_%(addr)s' % param
|
||||||
|
|
||||||
def _get_target_name(self, port):
|
def _get_target_name(self, port, ip=None):
|
||||||
param = {'svrid': port['device_id'],
|
param = {'svrid': port['device_id'],
|
||||||
'addr': port['fixed_ips'][0]['ip_address']}
|
'addr': ip or port['fixed_ips'][0]['ip_address']}
|
||||||
return 'server_%(svrid)s: %(addr)s' % param
|
return 'server_%(svrid)s: %(addr)s' % param
|
||||||
|
|
||||||
def _subs_from_port(self, port):
|
|
||||||
return [ip['subnet_id'] for ip in port['fixed_ips']]
|
|
||||||
|
|
||||||
@override_settings(
|
@override_settings(
|
||||||
OPENSTACK_NEUTRON_NETWORK={
|
OPENSTACK_NEUTRON_NETWORK={
|
||||||
'enable_fip_topology_check': True,
|
'enable_fip_topology_check': True,
|
||||||
@ -1185,12 +1186,20 @@ class NeutronApiFloatingIpTests(NeutronApiTestBase):
|
|||||||
subnet_id = self.subnets.first().id
|
subnet_id = self.subnets.first().id
|
||||||
shared_nets = [n for n in self.api_networks.list() if n['shared']]
|
shared_nets = [n for n in self.api_networks.list() if n['shared']]
|
||||||
shared_subnet_ids = [s for n in shared_nets for s in n['subnets']]
|
shared_subnet_ids = [s for n in shared_nets for s in n['subnets']]
|
||||||
target_ports = [
|
target_ports = []
|
||||||
(self._get_target_id(p), self._get_target_name(p)) for p in ports
|
for p in ports:
|
||||||
if (not p['device_owner'].startswith('network:') and
|
if p['device_owner'].startswith('network:'):
|
||||||
(subnet_id in self._subs_from_port(p) or
|
continue
|
||||||
(set(shared_subnet_ids) & set(self._subs_from_port(p)))))
|
port_subnets = [ip['subnet_id'] for ip in p['fixed_ips']]
|
||||||
]
|
if not (subnet_id in port_subnets or
|
||||||
|
(set(shared_subnet_ids) & set(port_subnets))):
|
||||||
|
continue
|
||||||
|
for ip in p['fixed_ips']:
|
||||||
|
if netaddr.IPAddress(ip['ip_address']).version != 4:
|
||||||
|
continue
|
||||||
|
target_ports.append((
|
||||||
|
self._get_target_id(p, ip['ip_address']),
|
||||||
|
self._get_target_name(p, ip['ip_address'])))
|
||||||
filters = {'tenant_id': self.request.user.tenant_id}
|
filters = {'tenant_id': self.request.user.tenant_id}
|
||||||
self.qclient.list_ports(**filters).AndReturn({'ports': ports})
|
self.qclient.list_ports(**filters).AndReturn({'ports': ports})
|
||||||
servers = self.servers.list()
|
servers = self.servers.list()
|
||||||
@ -1219,6 +1228,8 @@ class NeutronApiFloatingIpTests(NeutronApiTestBase):
|
|||||||
rets = api.neutron.floating_ip_target_list(self.request)
|
rets = api.neutron.floating_ip_target_list(self.request)
|
||||||
self.assertEqual(len(target_ports), len(rets))
|
self.assertEqual(len(target_ports), len(rets))
|
||||||
for ret, exp in zip(rets, target_ports):
|
for ret, exp in zip(rets, target_ports):
|
||||||
|
pid, ip_address = ret.id.split('_', 1)
|
||||||
|
self.assertEqual(4, netaddr.IPAddress(ip['ip_address']).version)
|
||||||
self.assertEqual(exp[0], ret.id)
|
self.assertEqual(exp[0], ret.id)
|
||||||
self.assertEqual(exp[1], ret.name)
|
self.assertEqual(exp[1], ret.name)
|
||||||
|
|
||||||
|
@ -74,7 +74,8 @@ def data(TEST):
|
|||||||
'id': '82288d84-e0a5-42ac-95be-e6af08727e42',
|
'id': '82288d84-e0a5-42ac-95be-e6af08727e42',
|
||||||
'name': 'net1',
|
'name': 'net1',
|
||||||
'status': 'ACTIVE',
|
'status': 'ACTIVE',
|
||||||
'subnets': ['e8abc972-eb0c-41f1-9edd-4bc6e3bcd8c9'],
|
'subnets': ['e8abc972-eb0c-41f1-9edd-4bc6e3bcd8c9',
|
||||||
|
'41e53a49-442b-4307-9e9a-88967a6b6657'],
|
||||||
'tenant_id': '1',
|
'tenant_id': '1',
|
||||||
'router:external': False,
|
'router:external': False,
|
||||||
'shared': False}
|
'shared': False}
|
||||||
@ -90,15 +91,34 @@ def data(TEST):
|
|||||||
'name': 'mysubnet1',
|
'name': 'mysubnet1',
|
||||||
'network_id': network_dict['id'],
|
'network_id': network_dict['id'],
|
||||||
'tenant_id': network_dict['tenant_id']}
|
'tenant_id': network_dict['tenant_id']}
|
||||||
|
subnetv6_dict = {
|
||||||
|
'allocation_pools': [{'start': 'fdb6:b88a:488e::2',
|
||||||
|
'end': 'fdb6:b88a:488e:0:ffff:ffff:ffff:ffff'}],
|
||||||
|
'dns_nameservers': [],
|
||||||
|
'host_routes': [],
|
||||||
|
'cidr': 'fdb6:b88a:488e::/64',
|
||||||
|
'enable_dhcp': True,
|
||||||
|
'gateway_ip': 'fdb6:b88a:488e::1',
|
||||||
|
'id': network_dict['subnets'][1],
|
||||||
|
'ip_version': 6,
|
||||||
|
'name': 'myv6subnet',
|
||||||
|
'network_id': network_dict['id'],
|
||||||
|
'tenant_id': network_dict['tenant_id'],
|
||||||
|
'ipv6_ra_mode': 'slaac',
|
||||||
|
'ipv6_address_mode': 'slaac'
|
||||||
|
}
|
||||||
|
|
||||||
TEST.api_networks.add(network_dict)
|
TEST.api_networks.add(network_dict)
|
||||||
TEST.api_subnets.add(subnet_dict)
|
TEST.api_subnets.add(subnet_dict)
|
||||||
|
TEST.api_subnets.add(subnetv6_dict)
|
||||||
|
|
||||||
network = copy.deepcopy(network_dict)
|
network = copy.deepcopy(network_dict)
|
||||||
subnet = neutron.Subnet(subnet_dict)
|
subnet = neutron.Subnet(subnet_dict)
|
||||||
network['subnets'] = [subnet]
|
subnetv6 = neutron.Subnet(subnetv6_dict)
|
||||||
|
network['subnets'] = [subnet, subnetv6]
|
||||||
TEST.networks.add(neutron.Network(network))
|
TEST.networks.add(neutron.Network(network))
|
||||||
TEST.subnets.add(subnet)
|
TEST.subnets.add(subnet)
|
||||||
|
TEST.subnets.add(subnetv6)
|
||||||
|
|
||||||
# Ports on 1st network.
|
# Ports on 1st network.
|
||||||
port_dict = {
|
port_dict = {
|
||||||
@ -130,7 +150,9 @@ def data(TEST):
|
|||||||
'device_id': '1',
|
'device_id': '1',
|
||||||
'device_owner': 'compute:nova',
|
'device_owner': 'compute:nova',
|
||||||
'fixed_ips': [{'ip_address': '10.0.0.4',
|
'fixed_ips': [{'ip_address': '10.0.0.4',
|
||||||
'subnet_id': subnet_dict['id']}],
|
'subnet_id': subnet_dict['id']},
|
||||||
|
{'ip_address': 'fdb6:b88a:488e:0:f816:3eff:fe9d:e62f',
|
||||||
|
'subnet_id': subnetv6_dict['id']}],
|
||||||
'id': '7e6ce62c-7ea2-44f8-b6b4-769af90a8406',
|
'id': '7e6ce62c-7ea2-44f8-b6b4-769af90a8406',
|
||||||
'mac_address': 'fa:16:3e:9d:e6:2f',
|
'mac_address': 'fa:16:3e:9d:e6:2f',
|
||||||
'name': '',
|
'name': '',
|
||||||
@ -168,6 +190,24 @@ def data(TEST):
|
|||||||
}
|
}
|
||||||
TEST.api_ports.add(port_dict)
|
TEST.api_ports.add(port_dict)
|
||||||
TEST.ports.add(neutron.Port(port_dict))
|
TEST.ports.add(neutron.Port(port_dict))
|
||||||
|
port_dict = {
|
||||||
|
'admin_state_up': True,
|
||||||
|
'device_id': '279989f7-54bb-41d9-ba42-0d61f12fda61',
|
||||||
|
'device_owner': 'network:router_interface',
|
||||||
|
'fixed_ips': [{'ip_address': 'fdb6:b88a:488e::1',
|
||||||
|
'subnet_id': subnetv6_dict['id']}],
|
||||||
|
'id': '8047e0d5-5ef5-4b6e-a1a7-d3a52ad980f7',
|
||||||
|
'mac_address': 'fa:16:3e:69:6e:e9',
|
||||||
|
'name': '',
|
||||||
|
'network_id': network_dict['id'],
|
||||||
|
'status': 'ACTIVE',
|
||||||
|
'tenant_id': network_dict['tenant_id'],
|
||||||
|
'binding:vnic_type': 'normal',
|
||||||
|
'binding:host_id': 'host',
|
||||||
|
'security_groups': [],
|
||||||
|
}
|
||||||
|
TEST.api_ports.add(port_dict)
|
||||||
|
TEST.ports.add(neutron.Port(port_dict))
|
||||||
|
|
||||||
# 2nd network.
|
# 2nd network.
|
||||||
network_dict = {'admin_state_up': True,
|
network_dict = {'admin_state_up': True,
|
||||||
|
Loading…
Reference in New Issue
Block a user