Merge "Handle single ip port on dual-stack"
This commit is contained in:
commit
59872ebdb4
|
@ -317,11 +317,24 @@ def _create_or_update_port(neutron_network_id, endpoint_id,
|
|||
# For the container boot from dual-net, request_address will
|
||||
# create two ports(v4 and v6 address), we should only allow one
|
||||
# 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:
|
||||
response_port = None
|
||||
for port in filtered_ports.get('ports', []):
|
||||
port_name = port.get('name')
|
||||
if str(port_name).startswith(const.KURYR_UNBOUND_PORT):
|
||||
app.neutron.delete_port(port['id'])
|
||||
else:
|
||||
port_driver = get_driver(port)
|
||||
response_port = port_driver.update_port(port, endpoint_id,
|
||||
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,
|
||||
|
|
|
@ -1723,6 +1723,141 @@ class TestKuryr(base.TestKuryrBase):
|
|||
expected = {'Interface': {}}
|
||||
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'
|
||||
'.create_host_iface')
|
||||
@mock.patch('kuryr_libnetwork.controllers.app.neutron.list_networks')
|
||||
|
|
Loading…
Reference in New Issue