Make _create_ports keys coherent with Neutron API.

OpenStackSDK have renamed some fields for Neutron API to be able to
create port object with attributes named after those fields. In our
workaround, we didn't spot that, so that all of the neutron API port
fields which prefixes started from 'binding_' cause an exception on the
neutron API call side.

In this patch we fix this by changing those fields to be acceptable
directly by Neutron API.

Note, that _create_ports is a workaround, which will be removed when
kuryr-kubernetes will bump openstakcsdk version to minimum 0.42 in
lower constraints.

Closes-bug: 1874276
Change-Id: Id36a00b94f9df837c49ced7155f8117fe9625fc2
(cherry picked from commit 473a606150)
This commit is contained in:
Roman Dobosz 2020-04-23 10:22:41 +02:00 committed by Michał Dulko
parent 6c39f94fd0
commit 4ed3177d15
2 changed files with 93 additions and 1 deletions

View File

@ -86,7 +86,19 @@ def setup_kubernetes_client():
def _create_ports(self, payload):
"""bulk create ports using openstacksdk module"""
# TODO(gryf): this should be implemented on openstacksdk instead.
# TODO(gryf): this function should be removed while we update openstacksdk
# version to 0.42.
key_map = {'binding_host_id': 'binding:host_id',
'binding_profile': 'binding:profile',
'binding_vif_details': 'binding:vif_details',
'binding_vif_type': 'binding:vif_type',
'binding_vnic_type': 'binding:vnic_type'}
for port in payload['ports']:
for key, mapping in key_map.items():
if key in port:
port[mapping] = port.pop(key)
response = self.post(os_port.Port.base_path, json=payload)
if not response.ok:

View File

@ -15,6 +15,8 @@
from unittest import mock
from openstack.network.v2 import port as os_port
from kuryr_kubernetes import clients
from kuryr_kubernetes.tests import base as test_base
@ -48,3 +50,81 @@ class TestK8sClient(test_base.TestCase):
clients.get_network_client())
self.assertIs(openstacksdk_mock.compute,
clients.get_compute_client())
class TestOpenStackSDKHack(test_base.TestCase):
def test_create_ports_incorrect_payload(self):
m_osdk = mock.Mock()
self.assertRaises(KeyError, clients._create_ports, m_osdk, {})
def test_create_no_ports(self):
m_response = mock.Mock()
m_response.json.return_value = {'ports': []}
m_post = mock.Mock()
m_post.return_value = m_response
m_osdk = mock.Mock()
m_osdk.post = m_post
payload = {'ports': []}
clients._create_ports(m_osdk, payload)
m_post.assert_called_once_with(os_port.Port.base_path, json=payload)
def test_create_ports(self):
m_response = mock.Mock()
m_response.json.return_value = {'ports': []}
m_post = mock.Mock()
m_post.return_value = m_response
m_osdk = mock.Mock()
m_osdk.post = m_post
payload = {'ports': [{'admin_state_up': True,
'allowed_address_pairs': [{}],
'binding_host_id': 'binding-host-id-1',
'binding_profile': {},
'binding_vif_details': {},
'binding_vif_type': 'ovs',
'binding_vnic_type': 'normal',
'device_id': 'device-id-1',
'device_owner': 'compute:nova',
'dns_assignment': [{}],
'dns_name': 'dns-name-1',
'extra_dhcp_opts': [{}],
'fixed_ips': [{'subnet_id': 'subnet-id-1',
'ip_address': '10.10.10.01'}],
'id': 'port-id-1',
'mac_address': 'de:ad:be:ef:de:ad',
'name': 'port-name-',
'network_id': 'network-id-1',
'port_security_enabled': True,
'security_groups': [],
'status': 'ACTIVE',
'tenant_id': 'project-id-'}]}
expected = {'ports': [{'admin_state_up': True,
'allowed_address_pairs': [{}],
'binding:host_id': 'binding-host-id-1',
'binding:profile': {},
'binding:vif_details': {},
'binding:vif_type': 'ovs',
'binding:vnic_type': 'normal',
'device_id': 'device-id-1',
'device_owner': 'compute:nova',
'dns_assignment': [{}],
'dns_name': 'dns-name-1',
'extra_dhcp_opts': [{}],
'fixed_ips': [{'subnet_id': 'subnet-id-1',
'ip_address': '10.10.10.01'}],
'id': 'port-id-1',
'mac_address': 'de:ad:be:ef:de:ad',
'name': 'port-name-',
'network_id': 'network-id-1',
'port_security_enabled': True,
'security_groups': [],
'status': 'ACTIVE',
'tenant_id': 'project-id-'}]}
clients._create_ports(m_osdk, payload)
m_post.assert_called_once_with(os_port.Port.base_path, json=expected)