Merge "Handle single ip port on dual-stack"
This commit is contained in:
commit
59872ebdb4
|
@ -317,15 +317,28 @@ def _create_or_update_port(neutron_network_id, endpoint_id,
|
||||||
# For the container boot from dual-net, request_address will
|
# For the container boot from dual-net, request_address will
|
||||||
# create two ports(v4 and v6 address), we should only allow one
|
# create two ports(v4 and v6 address), we should only allow one
|
||||||
# for port bind.
|
# for port bind.
|
||||||
|
# There are two cases:
|
||||||
|
# 1. User specifies an existing port with v4 address only.
|
||||||
|
# In this case, Kuryr creates the v6 port in ipam_request_address.
|
||||||
|
# We will bind the v4 port and remove the v6 port.
|
||||||
|
# 2. Users doesn't specify a port. In this case Kuryr creates
|
||||||
|
# the v4 and v6 ports in ipam_request_address and
|
||||||
|
# we will delete both ports then re-create a dual-port.
|
||||||
elif num_port == 2:
|
elif num_port == 2:
|
||||||
|
response_port = None
|
||||||
for port in filtered_ports.get('ports', []):
|
for port in filtered_ports.get('ports', []):
|
||||||
port_name = port.get('name')
|
port_name = port.get('name')
|
||||||
if str(port_name).startswith(const.KURYR_UNBOUND_PORT):
|
if str(port_name).startswith(const.KURYR_UNBOUND_PORT):
|
||||||
app.neutron.delete_port(port['id'])
|
app.neutron.delete_port(port['id'])
|
||||||
fixed_ips = (
|
else:
|
||||||
lib_utils.get_dict_format_fixed_ips_from_kv_format(fixed_ips))
|
port_driver = get_driver(port)
|
||||||
response_port = _create_port(endpoint_id, neutron_network_id,
|
response_port = port_driver.update_port(port, endpoint_id,
|
||||||
interface_mac, fixed_ips)
|
interface_mac)
|
||||||
|
if not response_port:
|
||||||
|
fixed_ips = (
|
||||||
|
lib_utils.get_dict_format_fixed_ips_from_kv_format(fixed_ips))
|
||||||
|
response_port = _create_port(endpoint_id, neutron_network_id,
|
||||||
|
interface_mac, fixed_ips)
|
||||||
else:
|
else:
|
||||||
raise exceptions.DuplicatedResourceException(
|
raise exceptions.DuplicatedResourceException(
|
||||||
"Multiple ports exist for the cidrs {0} and {1}"
|
"Multiple ports exist for the cidrs {0} and {1}"
|
||||||
|
|
|
@ -1723,6 +1723,141 @@ class TestKuryr(base.TestKuryrBase):
|
||||||
expected = {'Interface': {}}
|
expected = {'Interface': {}}
|
||||||
self.assertEqual(expected, decoded_json)
|
self.assertEqual(expected, decoded_json)
|
||||||
|
|
||||||
|
@mock.patch('kuryr_libnetwork.controllers.DEFAULT_DRIVER'
|
||||||
|
'.create_host_iface')
|
||||||
|
@mock.patch('kuryr_libnetwork.controllers.app.neutron.list_networks')
|
||||||
|
@mock.patch('kuryr_libnetwork.controllers.app.neutron.show_port')
|
||||||
|
@mock.patch('kuryr_libnetwork.controllers.DEFAULT_DRIVER.update_port')
|
||||||
|
@mock.patch('kuryr_libnetwork.controllers.app.neutron.delete_port')
|
||||||
|
@mock.patch('kuryr_libnetwork.controllers.app.neutron.list_ports')
|
||||||
|
@mock.patch('kuryr_libnetwork.controllers.app.neutron.list_subnets')
|
||||||
|
@mock.patch('kuryr_libnetwork.controllers.app')
|
||||||
|
@ddt.data(
|
||||||
|
(False), (True))
|
||||||
|
def test_network_driver_create_v4_endpoint_in_dual_net(
|
||||||
|
self, vif_plug_is_fatal,
|
||||||
|
mock_vif, mock_list_subnets, mock_list_ports, mock_delete_port,
|
||||||
|
mock_update_port, mock_show_port, mock_list_networks,
|
||||||
|
mock_create_host_iface):
|
||||||
|
mock_vif.vif_plug_is_fatal = vif_plug_is_fatal
|
||||||
|
fake_docker_network_id = lib_utils.get_hash()
|
||||||
|
fake_docker_endpoint_id = lib_utils.get_hash()
|
||||||
|
fake_neutron_net_id = uuidutils.generate_uuid()
|
||||||
|
t = utils.make_net_tags(fake_docker_network_id)
|
||||||
|
te = t + ',' + utils.existing_net_tag(fake_docker_network_id)
|
||||||
|
|
||||||
|
def mock_network(*args, **kwargs):
|
||||||
|
if kwargs['tags'] == te:
|
||||||
|
return self._get_fake_list_network(
|
||||||
|
fake_neutron_net_id,
|
||||||
|
check_existing=True)
|
||||||
|
elif kwargs['tags'] == t:
|
||||||
|
return self._get_fake_list_network(
|
||||||
|
fake_neutron_net_id)
|
||||||
|
mock_list_networks.side_effect = mock_network
|
||||||
|
fake_neutron_network = self._get_fake_list_network(
|
||||||
|
fake_neutron_net_id)
|
||||||
|
|
||||||
|
# The following fake response is retrieved from the Neutron doc:
|
||||||
|
# http://developer.openstack.org/api-ref-networking-v2.html#createSubnet # noqa
|
||||||
|
subnet_v4_id = uuidutils.generate_uuid()
|
||||||
|
subnet_v6_id = uuidutils.generate_uuid()
|
||||||
|
fake_v4_subnet = self._get_fake_v4_subnet(
|
||||||
|
fake_neutron_net_id, fake_docker_endpoint_id, subnet_v4_id)
|
||||||
|
fake_v6_subnet = self._get_fake_v6_subnet(
|
||||||
|
fake_neutron_net_id, fake_docker_endpoint_id, subnet_v6_id)
|
||||||
|
fake_v4_subnet_response = {
|
||||||
|
"subnets": [
|
||||||
|
fake_v4_subnet['subnet']
|
||||||
|
]
|
||||||
|
}
|
||||||
|
fake_v6_subnet_response = {
|
||||||
|
"subnets": [
|
||||||
|
fake_v6_subnet['subnet']
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
def mock_fake_subnet(*args, **kwargs):
|
||||||
|
if kwargs['cidr'] == '192.168.1.0/24':
|
||||||
|
return fake_v4_subnet_response
|
||||||
|
elif kwargs['cidr'] == 'fe80::/64':
|
||||||
|
return fake_v6_subnet_response
|
||||||
|
mock_list_subnets.side_effect = mock_fake_subnet
|
||||||
|
|
||||||
|
fake_fixed_ips = ['subnet_id=%s' % subnet_v4_id,
|
||||||
|
'ip_address=192.168.1.2']
|
||||||
|
fake_mac_address = 'fa:16:3e:20:57:c5'
|
||||||
|
fake_v4_port_id = uuidutils.generate_uuid()
|
||||||
|
fake_new_port_response = self._get_fake_port(
|
||||||
|
fake_docker_endpoint_id, fake_neutron_net_id,
|
||||||
|
fake_v4_port_id, lib_const.PORT_STATUS_ACTIVE,
|
||||||
|
subnet_v4_id, neutron_mac_address=fake_mac_address)
|
||||||
|
|
||||||
|
fake_v4_port_response = self._get_fake_port(
|
||||||
|
"fake-name1", fake_neutron_net_id,
|
||||||
|
fake_v4_port_id, lib_const.PORT_STATUS_DOWN,
|
||||||
|
subnet_v4_id)
|
||||||
|
|
||||||
|
fake_v6_port_id = uuidutils.generate_uuid()
|
||||||
|
fake_v6_port_response = self._get_fake_port(
|
||||||
|
"fake-name2", fake_neutron_net_id,
|
||||||
|
fake_v6_port_id, lib_const.PORT_STATUS_DOWN,
|
||||||
|
subnet_v6_id, name=constants.KURYR_UNBOUND_PORT,
|
||||||
|
neutron_mac_address="fa:16:3e:20:57:c4")
|
||||||
|
|
||||||
|
fake_ports_response = {
|
||||||
|
"ports": [
|
||||||
|
fake_v4_port_response['port'],
|
||||||
|
fake_v6_port_response['port']
|
||||||
|
]
|
||||||
|
}
|
||||||
|
mock_list_ports.return_value = fake_ports_response
|
||||||
|
|
||||||
|
mock_update_port.return_value = fake_new_port_response['port']
|
||||||
|
|
||||||
|
fake_neutron_subnets = [fake_v4_subnet['subnet']]
|
||||||
|
fake_create_iface_response = ('fake stdout', '')
|
||||||
|
|
||||||
|
mock_create_host_iface.return_value = fake_create_iface_response
|
||||||
|
|
||||||
|
if vif_plug_is_fatal:
|
||||||
|
fake_neutron_ports_response_2 = self._get_fake_port(
|
||||||
|
fake_docker_endpoint_id, fake_neutron_net_id,
|
||||||
|
fake_v4_port_id, lib_const.PORT_STATUS_ACTIVE,
|
||||||
|
subnet_v4_id, subnet_v6_id)
|
||||||
|
mock_show_port.return_value = fake_neutron_ports_response_2
|
||||||
|
|
||||||
|
data = {
|
||||||
|
'NetworkID': fake_docker_network_id,
|
||||||
|
'EndpointID': fake_docker_endpoint_id,
|
||||||
|
'Options': {},
|
||||||
|
'Interface': {
|
||||||
|
'Address': '192.168.1.2/24',
|
||||||
|
'MacAddress': fake_mac_address
|
||||||
|
}
|
||||||
|
}
|
||||||
|
response = self.app.post('/NetworkDriver.CreateEndpoint',
|
||||||
|
content_type='application/json',
|
||||||
|
data=jsonutils.dumps(data))
|
||||||
|
|
||||||
|
self.assertEqual(200, response.status_code)
|
||||||
|
mock_list_subnets.assert_any_call(
|
||||||
|
network_id=fake_neutron_net_id, cidr='192.168.1.0/24')
|
||||||
|
mock_list_ports.assert_called_with(fixed_ips=fake_fixed_ips)
|
||||||
|
mock_delete_port.assert_any_call(fake_v6_port_id)
|
||||||
|
mock_update_port.assert_called_with(
|
||||||
|
fake_v4_port_response['port'], fake_docker_endpoint_id,
|
||||||
|
fake_mac_address)
|
||||||
|
mock_list_networks.assert_any_call(tags=t)
|
||||||
|
mock_create_host_iface.assert_called_with(fake_docker_endpoint_id,
|
||||||
|
fake_new_port_response['port'], fake_neutron_subnets,
|
||||||
|
fake_neutron_network['networks'][0])
|
||||||
|
if vif_plug_is_fatal:
|
||||||
|
mock_show_port.assert_called_with(fake_v4_port_id)
|
||||||
|
decoded_json = jsonutils.loads(response.data)
|
||||||
|
expected = {'Interface': {}}
|
||||||
|
self.assertEqual(expected, decoded_json)
|
||||||
|
|
||||||
@mock.patch('kuryr_libnetwork.controllers.DEFAULT_DRIVER'
|
@mock.patch('kuryr_libnetwork.controllers.DEFAULT_DRIVER'
|
||||||
'.create_host_iface')
|
'.create_host_iface')
|
||||||
@mock.patch('kuryr_libnetwork.controllers.app.neutron.list_networks')
|
@mock.patch('kuryr_libnetwork.controllers.app.neutron.list_networks')
|
||||||
|
|
Loading…
Reference in New Issue