Merge "Update minimum openstacksdk version to 0.59.0"

This commit is contained in:
Zuul 2022-07-14 17:20:14 +00:00 committed by Gerrit Code Review
commit af00740229
9 changed files with 13 additions and 195 deletions

View File

@ -13,7 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
from functools import partial
import ipaddress
import os
@ -21,11 +20,6 @@ from keystoneauth1 import session as k_session
from kuryr.lib import utils
from openstack import connection
from openstack import exceptions as os_exc
from openstack.load_balancer.v2 import listener as os_listener
from openstack.network.v2 import port as os_port
from openstack.network.v2 import trunk as os_trunk
from openstack import resource as os_resource
from openstack import utils as os_utils
from kuryr_kubernetes import config
from kuryr_kubernetes import k8s_client
@ -82,54 +76,6 @@ def setup_kubernetes_client():
_clients[_KUBERNETES_CLIENT] = k8s_client.K8sClient(api_root)
def _create_ports(self, payload):
"""bulk create ports using openstacksdk module"""
# 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)
os_exc.raise_from_response(response)
return (os_port.Port(**item) for item in response.json()['ports'])
def _add_trunk_subports(self, trunk, subports):
"""Set sub_ports on trunk
The original method on openstacksdk doesn't care about any errors. This is
a replacement that does.
"""
trunk = self._get_resource(os_trunk.Trunk, trunk)
url = os_utils.urljoin('/trunks', trunk.id, 'add_subports')
response = self.put(url, json={'sub_ports': subports})
os_exc.raise_from_response(response)
trunk._body.attributes.update({'sub_ports': subports})
return trunk
def _delete_trunk_subports(self, trunk, subports):
"""Remove sub_ports from trunk
The original method on openstacksdk doesn't care about any errors. This is
a replacement that does.
"""
trunk = self._get_resource(os_trunk.Trunk, trunk)
url = os_utils.urljoin('/trunks', trunk.id, 'remove_subports')
response = self.put(url, json={'sub_ports': subports})
os_exc.raise_from_response(response)
trunk._body.attributes.update({'sub_ports': subports})
return trunk
def get_neutron_error_type(ex):
try:
response = ex.response.json()
@ -170,24 +116,9 @@ def setup_openstacksdk():
session.session.mount(scheme, k_session.TCPKeepAliveAdapter(
pool_maxsize=1000))
# TODO(mdulko): To use Neutron's ability to do compare-and-swap updates we
# need to manually add support for inserting If-Match header
# into requests. At the moment we only need it for ports.
# Remove when lower-constraints openstacksdk supports this.
os_port.Port.if_match = os_resource.Header('If-Match')
# TODO(maysams): We need to manually insert allowed_cidrs option
# as it's only supported from 0.41.0 version. Remove it once
# lower-constraints supports it.
os_listener.Listener.allowed_cidrs = os_resource.Body('allowed_cidrs',
type=list)
conn = connection.Connection(
session=session,
region_name=getattr(config.CONF.neutron, 'region_name', None))
conn.network.create_ports = partial(_create_ports, conn.network)
conn.network.add_trunk_subports = partial(_add_trunk_subports,
conn.network)
conn.network.delete_trunk_subports = partial(_delete_trunk_subports,
conn.network)
_clients[_OPENSTACKSDK] = conn

View File

@ -161,7 +161,7 @@ class NestedMacvlanPodVIFDriver(nested_vif.NestedPodVIFDriver):
revision_number=None):
os_net = clients.get_network_client()
os_net.update_port(port_id, allowed_address_pairs=address_pairs,
if_match=f'revision_number={revision_number}')
if_revision=revision_number)
def _try_update_port(self, attempts, f,
vm_port, container_ips, container_mac):

View File

@ -85,7 +85,7 @@ class NestedVlanPodVIFDriver(nested_vif.NestedPodVIFDriver):
LOG.error("There are no vlan ids available to create subports")
return []
bulk_port_rq = {'ports': [port_rq] * len(subports_info)}
bulk_port_rq = [port_rq] * len(subports_info)
# restrict amount of create Ports in bulk that might be running
# in parallel.
with semaphore:

View File

@ -64,7 +64,7 @@ class NeutronPodVIFDriver(base.PodVIFDriver):
rq = self._get_port_request(pod, project_id, subnets, security_groups,
unbound=True)
bulk_port_rq = {'ports': [rq] * num_ports}
bulk_port_rq = [rq] * num_ports
# restrict amount of create Ports in bulk that might be running
# in parallel.
with semaphore:

View File

@ -436,9 +436,7 @@ class TestNestedMacvlanPodVIFDriver(test_base.TestCase):
revision_number=9)
os_net.update_port.assert_called_with(
port_id,
allowed_address_pairs=pairs,
if_match='revision_number=9')
port_id, allowed_address_pairs=pairs, if_revision=9)
def test_update_port_address_pairs_failure(self):
cls = nested_macvlan_vif.NestedMacvlanPodVIFDriver
@ -454,9 +452,7 @@ class TestNestedMacvlanPodVIFDriver(test_base.TestCase):
port_id, pairs, revision_number=9)
os_net.update_port.assert_called_with(
port_id,
allowed_address_pairs=pairs,
if_match='revision_number=9')
port_id, allowed_address_pairs=pairs, if_revision=9)
@mock.patch('kuryr_kubernetes.controller.drivers.nested_macvlan_vif.'
'NestedMacvlanPodVIFDriver._add_to_allowed_address_pairs')

View File

@ -98,7 +98,7 @@ class TestNestedVlanPodVIFDriver(test_base.TestCase):
port = munch.Munch({'id': mock.sentinel.id})
vif = mock.sentinel.vif
bulk_rq = {'ports': [port_request for _ in range(len(subports_info))]}
bulk_rq = [port_request for _ in range(len(subports_info))]
m_driver._get_parent_port.return_value = parent_port
m_driver._get_trunk_id.return_value = trunk_id
@ -181,7 +181,7 @@ class TestNestedVlanPodVIFDriver(test_base.TestCase):
'port_id': '',
'segmentation_type': 'vlan'}]
bulk_rq = {'ports': [port_request for _ in range(len(subports_info))]}
bulk_rq = [port_request for _ in range(len(subports_info))]
m_driver._get_parent_port.return_value = parent_port
m_driver._get_trunk_id.return_value = trunk_id
@ -226,7 +226,7 @@ class TestNestedVlanPodVIFDriver(test_base.TestCase):
'segmentation_type': 'vlan'}]
port = munch.Munch({'id': mock.sentinel.id})
bulk_rq = {'ports': [port_request for _ in range(len(subports_info))]}
bulk_rq = [port_request for _ in range(len(subports_info))]
m_driver._get_parent_port.return_value = parent_port
m_driver._get_trunk_id.return_value = trunk_id
@ -273,7 +273,7 @@ class TestNestedVlanPodVIFDriver(test_base.TestCase):
'segmentation_type': 'vlan'}]
port = munch.Munch({'id': mock.sentinel.id})
bulk_rq = {'ports': [port_request for _ in range(len(subports_info))]}
bulk_rq = [port_request for _ in range(len(subports_info))]
m_driver._get_parent_port.return_value = parent_port
m_driver._get_trunk_id.return_value = trunk_id

View File

@ -78,7 +78,7 @@ class NeutronPodVIFDriver(test_base.TestCase):
vif_plugin = mock.sentinel.vif_plugin
port.binding_vif_type = vif_plugin
vif = mock.sentinel.vif
bulk_rq = {'ports': [port_request for _ in range(num_ports)]}
bulk_rq = [port_request for _ in range(num_ports)]
os_net.create_ports.return_value = (p for p in [port, port])
m_to_vif.return_value = vif
@ -116,7 +116,7 @@ class NeutronPodVIFDriver(test_base.TestCase):
port2 = munch.Munch({'id': port_id, 'binding_vif_type': vif_plugin})
port1_1 = munch.Munch({'id': port_id, 'binding_vif_type': vif_plugin})
vif = mock.sentinel.vif
bulk_rq = {'ports': [port_request for _ in range(num_ports)]}
bulk_rq = [port_request for _ in range(num_ports)]
semaphore = mock.MagicMock(spec=eventlet.semaphore.Semaphore(20))
os_net.create_ports.return_value = (p for p in [port1, port2])
@ -150,7 +150,7 @@ class NeutronPodVIFDriver(test_base.TestCase):
port_request = mock.sentinel.port_request
m_driver._get_port_request.return_value = port_request
bulk_rq = {'ports': [port_request for _ in range(num_ports)]}
bulk_rq = [port_request for _ in range(num_ports)]
semaphore = mock.MagicMock(spec=eventlet.semaphore.Semaphore(20))
os_net.create_ports.side_effect = os_exc.SDKException

View File

@ -15,9 +15,6 @@
from unittest import mock
from openstack import exceptions as os_exc
from openstack.network.v2 import port as os_port
from kuryr_kubernetes import clients
from kuryr_kubernetes.tests import base as test_base
@ -50,109 +47,3 @@ 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_response.status_code = 201
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_response.status_code = 201
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)
def test_create_ports_out_of_ports(self):
"""Simulate error response from OpenStack SDK"""
m_response = mock.Mock()
m_response.text = ('{"NeutronError": {"type": "OverQuota", "message": '
'"Quota exceeded for resources: [\'port\'].", '
'"detail": ""}}')
m_response.ok = False
m_response.status_code = 409
m_response.headers = {'content-type': 'application/json'}
m_post = mock.Mock()
m_post.return_value = m_response
m_osdk = mock.Mock()
m_osdk.post = m_post
payload = {'ports': []}
try:
clients._create_ports(m_osdk, payload)
except os_exc.ConflictException as ex:
# no additional params passed to the exception class
self.assertIsNone(ex.extra_data)
# no formatting placeholders in message
self.assertNotIn('%s', ex.message)
m_post.assert_called_once_with(os_port.Port.base_path, json=payload)

View File

@ -13,7 +13,7 @@ pbr!=2.1.0,>=2.0.0 # Apache-2.0
requests>=2.18.4 # Apache-2.0
eventlet>=0.22.0 # MIT
netaddr>=0.7.19 # BSD
openstacksdk>=0.36.0 # Apache-2.0
openstacksdk>=0.59.0 # Apache-2.0
oslo.cache>=1.26.0 # Apache-2.0
oslo.config>=6.1.0 # Apache-2.0
oslo.log>=3.36.0 # Apache-2.0