Merge "Update minimum openstacksdk version to 0.59.0"
This commit is contained in:
commit
af00740229
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue