diff --git a/openstack_dashboard/api/neutron.py b/openstack_dashboard/api/neutron.py index 884743e13d..c4fd3aedf7 100644 --- a/openstack_dashboard/api/neutron.py +++ b/openstack_dashboard/api/neutron.py @@ -31,8 +31,6 @@ from django.utils.translation import gettext_lazy as _ from keystoneauth1 import exceptions as ks_exceptions from keystoneauth1 import session from keystoneauth1 import token_endpoint -from neutronclient.common import exceptions as neutron_exc -from neutronclient.v2_0 import client as neutron_client from novaclient import exceptions as nova_exc import openstack from openstack import exceptions as sdk_exceptions @@ -511,12 +509,9 @@ class SecurityGroupManager(object): try: rule = self.net_client.create_security_group_rule( **params).to_dict() - except neutron_exc.OverQuotaClient: + except sdk_exceptions.ConflictException: raise exceptions.Conflict( _('Security group rule quota exceeded.')) - except neutron_exc.Conflict: - raise exceptions.Conflict( - _('Security group rule already exists.')) sg_dict = self._sg_name_dict(parent_group_id, [rule]) return SecurityGroupRule(rule, sg_dict) @@ -967,18 +962,6 @@ def get_auth_params_from_request(request): ) -@memoized -def neutronclient(request): - token_id, neutron_url, auth_url = get_auth_params_from_request(request) - insecure = settings.OPENSTACK_SSL_NO_VERIFY - cacert = settings.OPENSTACK_SSL_CACERT - c = neutron_client.Client(token=token_id, - auth_url=auth_url, - endpoint_url=neutron_url, - insecure=insecure, ca_cert=cacert) - return c - - @memoized def networkclient(request): token_id, neutron_url, auth_url = get_auth_params_from_request(request) @@ -1034,36 +1017,52 @@ def list_resources_with_long_filters(list_method, try: params[filter_attr] = filter_values return list_method(**params) - except neutron_exc.RequestURITooLong as uri_len_exc: - # The URI is too long because of too many filter values. - # Use the excess attribute of the exception to know how many - # filter values can be inserted into a single request. + except sdk_exceptions.HttpException as uri_len_exc: + # Note: neutronclient.RequestURITooLong was rised + # in case of http414 + if uri_len_exc.status_code != 414: + pass + else: + # The URI is too long because of too many filter values. + # Use the excess attribute of the exception to know how many + # filter values can be inserted into a single request. - # We consider only the filter condition from (filter_attr, - # filter_values) and do not consider other filter conditions - # which may be specified in **params. + # We consider only the filter condition from (filter_attr, + # filter_values) and do not consider other filter conditions + # which may be specified in **params. - if isinstance(filter_values, str): - filter_values = [filter_values] - elif not isinstance(filter_values, Sequence): - filter_values = list(filter_values) + if isinstance(filter_values, str): + filter_values = [filter_values] + elif not isinstance(filter_values, Sequence): + filter_values = list(filter_values) - # Length of each query filter is: - # =& (e.g., id=) - # The length will be key_len + value_maxlen + 2 - all_filter_len = sum(len(filter_attr) + len(val) + 2 - for val in filter_values) - allowed_filter_len = all_filter_len - uri_len_exc.excess + # Length of each query filter is: + # =& (e.g., id=) + # The length will be key_len + value_maxlen + 2 + all_filter_len = sum(len(filter_attr) + len(val) + 2 + for val in filter_values) + # Note(lajoskatona): with python-neutronclient excess + # was an arg of RequestURITooLong exception, see: + # https://opendev.org/openstack/python-neutronclient/src/commit/ + # 5f7d102f0e8111d6e90d958ab22682d07876a073/neutronclient/ + # client.py#L177 + excess = _get_excess(all_filter_len) + allowed_filter_len = all_filter_len - excess - val_maxlen = max(len(val) for val in filter_values) - filter_maxlen = len(filter_attr) + val_maxlen + 2 - chunk_size = allowed_filter_len // filter_maxlen + val_maxlen = max(len(val) for val in filter_values) + filter_maxlen = len(filter_attr) + val_maxlen + 2 + chunk_size = allowed_filter_len // filter_maxlen - resources = [] - for i in range(0, len(filter_values), chunk_size): - params[filter_attr] = filter_values[i:i + chunk_size] - resources.extend(list_method(**params)) - return resources + resources = [] + for i in range(0, len(filter_values), chunk_size): + params[filter_attr] = filter_values[i:i + chunk_size] + resources.extend(list_method(**params)) + return resources + + +def _get_excess(filter_len): + MAX_URI_LEN = 8192 + return filter_len - MAX_URI_LEN @profiler.trace @@ -2059,27 +2058,28 @@ def router_static_route_add(request, router_id, newroute): @profiler.trace def tenant_quota_get(request, tenant_id): - return base.QuotaSet(neutronclient(request).show_quota(tenant_id)['quota']) + return base.QuotaSet( + networkclient(request).get_quota(tenant_id).to_dict().pop('location')) @profiler.trace def tenant_quota_update(request, tenant_id, **kwargs): - quotas = {'quota': kwargs} - return neutronclient(request).update_quota(tenant_id, quotas) + return networkclient(request).update_quota(tenant_id, **kwargs).to_dict() @profiler.trace def tenant_quota_detail_get(request, tenant_id=None): tenant_id = tenant_id or request.user.tenant_id - response = neutronclient(request).get('/quotas/%s/details' % tenant_id) - return response['quota'] + rsp = networkclient(request).get('/quotas/%s/details' % tenant_id) + return rsp.json()['quota'] @profiler.trace def default_quota_get(request, tenant_id=None): tenant_id = tenant_id or request.user.tenant_id - response = neutronclient(request).show_quota_default(tenant_id) - return base.QuotaSet(response['quota']) + response = networkclient(request).get_quota_default(tenant_id).to_dict() + response.pop('location') + return base.QuotaSet(response) @profiler.trace @@ -2273,7 +2273,7 @@ def servers_update_addresses(request, servers, all_tenants=False): networks = list_resources_with_long_filters( network_list, 'id', frozenset([port.network_id for port in ports]), request=request) - except neutron_exc.NotFound as e: + except sdk_exceptions.NotFoundException as e: LOG.error('Neutron resource does not exist. %s', e) return except Exception as e: diff --git a/openstack_dashboard/dashboards/admin/rbac_policies/forms.py b/openstack_dashboard/dashboards/admin/rbac_policies/forms.py index 0072b39e07..4e9809e8b8 100644 --- a/openstack_dashboard/dashboards/admin/rbac_policies/forms.py +++ b/openstack_dashboard/dashboards/admin/rbac_policies/forms.py @@ -15,7 +15,7 @@ import logging from django.urls import reverse from django.utils.translation import gettext_lazy as _ -from neutronclient.common import exceptions as neutron_exc +from openstack import exceptions as sdk_exceptions from horizon import exceptions from horizon import forms @@ -145,7 +145,7 @@ class CreatePolicyForm(forms.SelfHandlingForm): msg = _('RBAC Policy was successfully created.') messages.success(request, msg) return rbac_policy - except neutron_exc.OverQuotaClient: + except sdk_exceptions.ConflictException: redirect = reverse('horizon:admin:rbac_policies:index') msg = _('RBAC Policy quota exceeded.') exceptions.handle(request, msg, redirect=redirect) diff --git a/openstack_dashboard/dashboards/project/floating_ip_portforwardings/views.py b/openstack_dashboard/dashboards/project/floating_ip_portforwardings/views.py index dc4a64eb1a..dba2b1110e 100644 --- a/openstack_dashboard/dashboards/project/floating_ip_portforwardings/views.py +++ b/openstack_dashboard/dashboards/project/floating_ip_portforwardings/views.py @@ -17,7 +17,7 @@ import logging from django.utils.translation import gettext_lazy as _ -from neutronclient.common import exceptions as neutron_exc +from openstack import exceptions as sdk_exceptions from horizon import exceptions from horizon import tables @@ -59,7 +59,7 @@ class IndexView(tables.DataTableView): "Manage floating IP port forwarding rules : " + str( floating_ip.ip)) return self.get_floating_ip_rules(floating_ip) - except neutron_exc.ConnectionFailed: + except sdk_exceptions.SDKException: exceptions.handle(self.request) except Exception: exceptions.handle( @@ -92,7 +92,7 @@ class AllRulesView(IndexView): def get_data(self): try: return self.get_all_floating_ip_rules() - except neutron_exc.ConnectionFailed: + except sdk_exceptions.SDKException: exceptions.handle(self.request) except Exception: exceptions.handle( diff --git a/openstack_dashboard/dashboards/project/floating_ip_portforwardings/workflows.py b/openstack_dashboard/dashboards/project/floating_ip_portforwardings/workflows.py index a8027b8c91..7259574470 100644 --- a/openstack_dashboard/dashboards/project/floating_ip_portforwardings/workflows.py +++ b/openstack_dashboard/dashboards/project/floating_ip_portforwardings/workflows.py @@ -16,7 +16,7 @@ from django.core.exceptions import ValidationError from django.urls import reverse from django.utils.translation import gettext_lazy as _ -from neutronclient.common import exceptions as neutron_exc +from openstack import exceptions as sdk_exceptions from horizon import exceptions from horizon import forms @@ -228,7 +228,7 @@ class FloatingIpPortForwardingRuleCreationWorkflow(workflows.Workflow): param.update(**api_params) api_method(request, floating_ip_id, **param) - except neutron_exc.Conflict as ex: + except sdk_exceptions.BadRequestException as ex: msg = _('The requested instance port is already' ' associated with another floating IP.') LOG.exception(msg, ex) diff --git a/openstack_dashboard/dashboards/project/floating_ips/views.py b/openstack_dashboard/dashboards/project/floating_ips/views.py index e211181cd4..b8f5aa5f13 100644 --- a/openstack_dashboard/dashboards/project/floating_ips/views.py +++ b/openstack_dashboard/dashboards/project/floating_ips/views.py @@ -25,7 +25,7 @@ import logging from django.urls import reverse_lazy from django.utils.translation import gettext_lazy as _ -from neutronclient.common import exceptions as neutron_exc +from openstack import exceptions as sdk_exceptions from horizon import exceptions from horizon import forms @@ -74,7 +74,7 @@ class AllocateView(forms.ModalFormView): def get_initial(self): try: pools = api.neutron.floating_ip_pools_list(self.request) - except neutron_exc.ConnectionFailed: + except sdk_exceptions.SDKException: pools = [] exceptions.handle(self.request) except Exception: @@ -96,7 +96,7 @@ class IndexView(tables.DataTableView): search_opts = self.get_filters() floating_ips = api.neutron.tenant_floating_ip_list(self.request, **search_opts) - except neutron_exc.ConnectionFailed: + except sdk_exceptions.SDKException: floating_ips = [] exceptions.handle(self.request) except Exception: @@ -107,7 +107,7 @@ class IndexView(tables.DataTableView): try: floating_ip_pools = \ api.neutron.floating_ip_pools_list(self.request) - except neutron_exc.ConnectionFailed: + except sdk_exceptions.SDKException: floating_ip_pools = [] exceptions.handle(self.request) except Exception: diff --git a/openstack_dashboard/dashboards/project/floating_ips/workflows.py b/openstack_dashboard/dashboards/project/floating_ips/workflows.py index c36d6ca13c..09c6e63712 100644 --- a/openstack_dashboard/dashboards/project/floating_ips/workflows.py +++ b/openstack_dashboard/dashboards/project/floating_ips/workflows.py @@ -15,7 +15,7 @@ from django.urls import reverse from django.utils.translation import gettext_lazy as _ -from neutronclient.common import exceptions as neutron_exc +from openstack import exceptions as sdk_exceptions from horizon import exceptions from horizon import forms @@ -88,7 +88,7 @@ class AssociateIPAction(workflows.Action): redirect = reverse('horizon:project:floating_ips:index') try: ips = api.neutron.tenant_floating_ip_list(self.request) - except neutron_exc.ConnectionFailed: + except sdk_exceptions.SDKException: exceptions.handle(self.request, redirect=redirect) except Exception: exceptions.handle(self.request, @@ -170,7 +170,7 @@ class IPAssociationWorkflow(workflows.Workflow): api.neutron.floating_ip_associate(request, data['ip_id'], data['port_id']) - except neutron_exc.Conflict: + except sdk_exceptions.ConflictException: msg = _('The requested instance port is already' ' associated with another floating IP.') exceptions.handle(request, msg) diff --git a/openstack_dashboard/dashboards/project/networks/subnets/tables.py b/openstack_dashboard/dashboards/project/networks/subnets/tables.py index c99aeba4bc..7c4aadf9ec 100644 --- a/openstack_dashboard/dashboards/project/networks/subnets/tables.py +++ b/openstack_dashboard/dashboards/project/networks/subnets/tables.py @@ -14,7 +14,7 @@ import logging -from neutronclient.common import exceptions as neutron_exceptions +from openstack import exceptions as sdk_exceptions from django.urls import reverse from django.urls import reverse_lazy @@ -79,7 +79,7 @@ class DeleteSubnet(SubnetPolicyTargetMixin, tables.DeleteAction): # normal_log_message 'Failed to delete subnet %(id)s: %(exc)s', # target_exception - neutron_exceptions.Conflict, + sdk_exceptions.ConflictException, # target_log_message 'Unable to delete subnet %(id)s with 409 Conflict: %(exc)s', # target_user_message diff --git a/openstack_dashboard/dashboards/project/networks/tables.py b/openstack_dashboard/dashboards/project/networks/tables.py index ebb651cf6f..708db43f16 100644 --- a/openstack_dashboard/dashboards/project/networks/tables.py +++ b/openstack_dashboard/dashboards/project/networks/tables.py @@ -19,7 +19,7 @@ from django.urls import reverse from django.utils.translation import gettext_lazy as _ from django.utils.translation import ngettext_lazy from django.utils.translation import pgettext_lazy -from neutronclient.common import exceptions as neutron_exceptions +from openstack import exceptions as sdk_exceptions from horizon import exceptions from horizon import tables @@ -63,7 +63,7 @@ class DeleteNetwork(policy.PolicyTargetMixin, tables.DeleteAction): # normal_log_message 'Failed to delete network %(id)s: %(exc)s', # target_exception - neutron_exceptions.Conflict, + sdk_exceptions.ConflictException, # target_log_message 'Unable to delete network %(id)s with 409 Conflict: %(exc)s', # target_user_message diff --git a/openstack_dashboard/dashboards/project/routers/extensions/extraroutes/forms.py b/openstack_dashboard/dashboards/project/routers/extensions/extraroutes/forms.py index d48a61b378..ab1f312e35 100644 --- a/openstack_dashboard/dashboards/project/routers/extensions/extraroutes/forms.py +++ b/openstack_dashboard/dashboards/project/routers/extensions/extraroutes/forms.py @@ -17,7 +17,7 @@ import logging from django.urls import reverse from django.utils.translation import gettext_lazy as _ -from neutronclient.common import exceptions as neutron_exc +from openstack import exceptions as sdk_exceptions from horizon import exceptions from horizon import forms @@ -49,7 +49,7 @@ class AddRouterRoute(forms.SelfHandlingForm): msg = _('Static route added') messages.success(request, msg) return True - except neutron_exc.BadRequest as e: + except sdk_exceptions.BadRequestException as e: LOG.info('Invalid format for routes %(route)s: %(exc)s', {'route': route, 'exc': e}) msg = _('Invalid format for routes: %s') % e diff --git a/openstack_dashboard/dashboards/project/routers/tables.py b/openstack_dashboard/dashboards/project/routers/tables.py index 9a697aaa1c..15afcd11e1 100644 --- a/openstack_dashboard/dashboards/project/routers/tables.py +++ b/openstack_dashboard/dashboards/project/routers/tables.py @@ -19,7 +19,7 @@ from django.urls import reverse from django.utils.translation import gettext_lazy as _ from django.utils.translation import ngettext_lazy from django.utils.translation import pgettext_lazy -from neutronclient.common import exceptions as neutron_exceptions +from openstack import exceptions as sdk_exceptions from horizon import exceptions from horizon import tables @@ -57,7 +57,7 @@ class DeleteRouter(policy.PolicyTargetMixin, tables.DeleteAction): # normal_log_message 'Failed to delete router %(id)s: %(exc)s', # target_exception - neutron_exceptions.NeutronClientException, + sdk_exceptions.SDKException, # target_log_message 'Unable to delete router %(id)s: %(exc)s', # target_user_message @@ -151,7 +151,7 @@ class ClearGateway(policy.PolicyTargetMixin, tables.BatchAction): # normal_log_message 'Unable to clear gateway for router %(id)s: %(exc)s', # target_exception - neutron_exceptions.Conflict, + sdk_exceptions.ConflictException, # target_log_message 'Unable to clear gateway for router %(id)s: %(exc)s', # target_user_message diff --git a/openstack_dashboard/dashboards/project/security_groups/views.py b/openstack_dashboard/dashboards/project/security_groups/views.py index 59fdcba9db..eb7f947e71 100644 --- a/openstack_dashboard/dashboards/project/security_groups/views.py +++ b/openstack_dashboard/dashboards/project/security_groups/views.py @@ -22,7 +22,7 @@ Views for managing instances. from django.urls import reverse from django.urls import reverse_lazy from django.utils.translation import gettext_lazy as _ -from neutronclient.common import exceptions as neutron_exc +from openstack import exceptions as sdk_exceptions from horizon import exceptions from horizon import forms @@ -183,7 +183,7 @@ class IndexView(tables.DataTableView): def get_data(self): try: security_groups = api.neutron.security_group_list(self.request) - except neutron_exc.ConnectionFailed: + except sdk_exceptions.SDKException: security_groups = [] exceptions.handle(self.request) except Exception: diff --git a/openstack_dashboard/exceptions.py b/openstack_dashboard/exceptions.py index 4e0b95c45c..097d391faf 100644 --- a/openstack_dashboard/exceptions.py +++ b/openstack_dashboard/exceptions.py @@ -19,8 +19,8 @@ from cinderclient import exceptions as cinderclient from glanceclient import exc as glanceclient from keystoneclient import exceptions as keystoneclient -from neutronclient.common import exceptions as neutronclient from novaclient import exceptions as novaclient +from openstack import exceptions as sdk_exceptions from requests import exceptions as requests from swiftclient import client as swiftclient @@ -30,7 +30,7 @@ UNAUTHORIZED = ( cinderclient.Unauthorized, novaclient.Unauthorized, glanceclient.HTTPUnauthorized, - neutronclient.Unauthorized, + sdk_exceptions.HttpException, ) @@ -39,7 +39,7 @@ NOT_FOUND = ( cinderclient.NotFound, novaclient.NotFound, glanceclient.HTTPNotFound, - neutronclient.NotFound, + sdk_exceptions.NotFoundException, ) @@ -56,8 +56,8 @@ RECOVERABLE = ( novaclient.Forbidden, glanceclient.HTTPException, glanceclient.CommunicationError, - neutronclient.Forbidden, - neutronclient.NeutronClientException, + sdk_exceptions.ForbiddenException, + sdk_exceptions.SDKException, swiftclient.ClientException, requests.RequestException, ) diff --git a/openstack_dashboard/test/selenium/ui/test_actions.py b/openstack_dashboard/test/selenium/ui/test_actions.py index 2f2229d9bf..8bd361c58e 100644 --- a/openstack_dashboard/test/selenium/ui/test_actions.py +++ b/openstack_dashboard/test/selenium/ui/test_actions.py @@ -23,8 +23,8 @@ def test_delete_multiple_instance_rows(live_server, driver, dashboard_data, mock.patch.object( api.nova, 'flavor_list') as mocked_f_l, \ mock.patch( - 'neutronclient.v2_0.client.Client' - '.list_extensions') as mocked_l_e, \ + 'openstack.network.v2._proxy.Proxy.' + 'extensions') as mocked_l_e, \ mock.patch.object( api.nova, 'tenant_absolute_limits') as mocked_t_a_l, \ mock.patch.object( diff --git a/openstack_dashboard/test/test_data/exceptions.py b/openstack_dashboard/test/test_data/exceptions.py index 9defeb3e2e..6f92d8f92f 100644 --- a/openstack_dashboard/test/test_data/exceptions.py +++ b/openstack_dashboard/test/test_data/exceptions.py @@ -15,8 +15,8 @@ from cinderclient import exceptions as cinder_exceptions import glanceclient.exc as glance_exceptions from keystoneclient import exceptions as keystone_exceptions -from neutronclient.common import exceptions as neutron_exceptions from novaclient import exceptions as nova_exceptions +from openstack import exceptions as sdk_exceptions from swiftclient import client as swift_exceptions from openstack_dashboard.test.test_data import utils @@ -67,7 +67,7 @@ def data(TEST): glance_exception = glance_exceptions.ClientException TEST.exceptions.glance = create_stubbed_exception(glance_exception) - neutron_exception = neutron_exceptions.NeutronClientException + neutron_exception = sdk_exceptions.SDKException TEST.exceptions.neutron = create_stubbed_exception(neutron_exception) swift_exception = swift_exceptions.ClientException diff --git a/openstack_dashboard/test/unit/api/test_neutron.py b/openstack_dashboard/test/unit/api/test_neutron.py index 8de129523f..922c0d256c 100644 --- a/openstack_dashboard/test/unit/api/test_neutron.py +++ b/openstack_dashboard/test/unit/api/test_neutron.py @@ -15,7 +15,6 @@ import copy from unittest import mock import netaddr -from neutronclient.common import exceptions as neutron_exc from openstack import exceptions as sdk_exceptions from openstack.network.v2 import port as sdk_port from openstack.network.v2 import subnet_pool as sdk_subnet_pool @@ -33,19 +32,19 @@ from openstack_dashboard.test.test_data import neutron_data class NeutronApiTests(test.APIMockTestCase): @mock.patch.object(api.neutron, 'networkclient') - def test_network_list(self, mock_neutronclient): + def test_network_list(self, mock_networkclient): networks = self.api_networks_sdk subnets = self.api_subnets_sdk - neutronclient = mock_neutronclient.return_value - neutronclient.networks.return_value = networks - neutronclient.subnets.return_value = subnets + networkclient = mock_networkclient.return_value + networkclient.networks.return_value = networks + networkclient.subnets.return_value = subnets ret_val = api.neutron.network_list(self.request) for n in ret_val: self.assertIsInstance(n, api.neutron.Network) - neutronclient.networks.assert_called_once_with() - neutronclient.subnets.assert_called_once_with() + networkclient.networks.assert_called_once_with() + networkclient.subnets.assert_called_once_with() @override_settings(OPENSTACK_NEUTRON_NETWORK={ 'enable_auto_allocated_network': True}) @@ -919,17 +918,17 @@ class NeutronApiTests(test.APIMockTestCase): subnet_id = self.api_networks_sdk[0]['subnets'][0] subnetv6_id = self.api_networks_sdk[0]['subnets'][1] - neutronclient = mock_networkclient.return_value - neutronclient.get_network.return_value = network - neutronclient.get_subnet.side_effect = [subnet, subnetv6] + networkclient = mock_networkclient.return_value + networkclient.get_network.return_value = network + networkclient.get_subnet.side_effect = [subnet, subnetv6] ret_val = api.neutron.network_get(self.request, network_id) self.assertIsInstance(ret_val, api.neutron.Network) self.assertEqual(2, len(ret_val['subnets'])) self.assertIsInstance(ret_val['subnets'][0], api.neutron.Subnet) - neutronclient.get_network.assert_called_once_with(network_id) - neutronclient.get_subnet.assert_has_calls([ + networkclient.get_network.assert_called_once_with(network_id) + networkclient.get_subnet.assert_has_calls([ mock.call(subnet_id), mock.call(subnetv6_id), ]) @@ -940,57 +939,57 @@ class NeutronApiTests(test.APIMockTestCase): network_id = self.api_networks_sdk[0]['id'] subnet_id = self.api_networks_sdk[0]['subnet_ids'][0] - neutronclient = mock_networkclient.return_value - neutronclient.get_network.return_value = network - neutronclient.get_subnet.side_effect = sdk_exceptions.ResourceNotFound + networkclient = mock_networkclient.return_value + networkclient.get_network.return_value = network + networkclient.get_subnet.side_effect = sdk_exceptions.ResourceNotFound ret_val = api.neutron.network_get(self.request, network_id) self.assertIsInstance(ret_val, api.neutron.Network) self.assertEqual(2, len(ret_val['subnet_ids'])) self.assertNotIsInstance(ret_val['subnet_ids'][0], api.neutron.Subnet) self.assertIsInstance(ret_val['subnet_ids'][0], str) - neutronclient.get_network.assert_called_once_with(network_id) - neutronclient.get_subnet.assert_called_once_with(subnet_id) + networkclient.get_network.assert_called_once_with(network_id) + networkclient.get_subnet.assert_called_once_with(subnet_id) @mock.patch.object(api.neutron, 'networkclient') def test_network_create(self, mock_networkclient): network = self.api_networks_sdk[0] form_data = {'name': 'net1', 'tenant_id': self.request.user.project_id} - neutronclient = mock_networkclient.return_value - neutronclient.create_network.return_value = network + networkclient = mock_networkclient.return_value + networkclient.create_network.return_value = network ret_val = api.neutron.network_create(self.request, name='net1') self.assertIsInstance(ret_val, api.neutron.Network) - neutronclient.create_network.assert_called_once_with(**form_data) + networkclient.create_network.assert_called_once_with(**form_data) @mock.patch.object(api.neutron, 'networkclient') def test_network_update(self, mock_networkclient): network = self.api_networks_sdk[0] network_id = self.api_networks_sdk[0]['id'] - neutronclient = mock_networkclient.return_value + networkclient = mock_networkclient.return_value form_data = {'name': 'net1'} - neutronclient.update_network.return_value = network + networkclient.update_network.return_value = network ret_val = api.neutron.network_update(self.request, network_id, name='net1') self.assertIsInstance(ret_val, api.neutron.Network) - neutronclient.update_network.assert_called_once_with(network_id, + networkclient.update_network.assert_called_once_with(network_id, **form_data) @mock.patch.object(api.neutron, 'networkclient') def test_network_delete(self, mock_networkclient): network_id = self.api_networks_sdk[0]['id'] - neutronclient = mock_networkclient.return_value - neutronclient.delete_network.return_value = None + networkclient = mock_networkclient.return_value + networkclient.delete_network.return_value = None api.neutron.network_delete(self.request, network_id) - neutronclient.delete_network.assert_called_once_with(network_id) + networkclient.delete_network.assert_called_once_with(network_id) @mock.patch.object(api.neutron, 'networkclient') def test_get_network_ip_availability(self, mock_networkclient): @@ -1029,27 +1028,27 @@ class NeutronApiTests(test.APIMockTestCase): def test_subnet_list(self, mock_networkclient): subnets = self.api_subnets_sdk - neutronclient = mock_networkclient.return_value - neutronclient.subnets.return_value = subnets + networkclient = mock_networkclient.return_value + networkclient.subnets.return_value = subnets ret_val = api.neutron.subnet_list(self.request) for n in ret_val: self.assertIsInstance(n, api.neutron.Subnet) - neutronclient.subnets.assert_called_once_with() + networkclient.subnets.assert_called_once_with() @mock.patch.object(api.neutron, 'networkclient') def test_subnet_get(self, mock_networkclient): subnet = self.api_subnets_sdk[0] subnet_id = self.api_subnets_sdk[0]['id'] - neutronclient = mock_networkclient.return_value - neutronclient.get_subnet.return_value = subnet + networkclient = mock_networkclient.return_value + networkclient.get_subnet.return_value = subnet ret_val = api.neutron.subnet_get(self.request, subnet_id) self.assertIsInstance(ret_val, api.neutron.Subnet) - neutronclient.get_subnet.assert_called_once_with(subnet_id) + networkclient.get_subnet.assert_called_once_with(subnet_id) @mock.patch.object(api.neutron, 'networkclient') def test_subnet_create(self, mock_networkclient): @@ -1061,13 +1060,13 @@ class NeutronApiTests(test.APIMockTestCase): 'ip_version': subnet_data['ip_version'], 'gateway_ip': subnet_data['gateway_ip']} - neutronclient = mock_networkclient.return_value - neutronclient.create_subnet.return_value = subnet_data + networkclient = mock_networkclient.return_value + networkclient.create_subnet.return_value = subnet_data ret_val = api.neutron.subnet_create(self.request, **params) self.assertIsInstance(ret_val, api.neutron.Subnet) - neutronclient.create_subnet.assert_called_once_with(**params) + networkclient.create_subnet.assert_called_once_with(**params) @mock.patch.object(api.neutron, 'networkclient') def test_subnet_update(self, mock_networkclient): @@ -1076,25 +1075,25 @@ class NeutronApiTests(test.APIMockTestCase): params = {'name': subnet_data['name'], 'gateway_ip': subnet_data['gateway_ip']} - neutronclient = mock_networkclient.return_value - neutronclient.update_subnet.return_value = subnet_data + networkclient = mock_networkclient.return_value + networkclient.update_subnet.return_value = subnet_data ret_val = api.neutron.subnet_update(self.request, subnet_id, **params) self.assertIsInstance(ret_val, api.neutron.Subnet) - neutronclient.update_subnet.assert_called_once_with( + networkclient.update_subnet.assert_called_once_with( subnet_id, **params) @mock.patch.object(api.neutron, 'networkclient') def test_subnet_delete(self, mock_networkclient): subnet_id = self.api_subnets_sdk[0]['id'] - neutronclient = mock_networkclient.return_value - neutronclient.delete_subnet.return_value = None + networkclient = mock_networkclient.return_value + networkclient.delete_subnet.return_value = None api.neutron.subnet_delete(self.request, subnet_id) - neutronclient.delete_subnet.assert_called_once_with(subnet_id) + networkclient.delete_subnet.assert_called_once_with(subnet_id) @mock.patch.object(api.neutron, 'networkclient') def test_subnetpool_list(self, mock_networkclient): @@ -1188,7 +1187,7 @@ class NeutronApiTests(test.APIMockTestCase): trunks = self.api_tp_trunks_sdk # list_extensions is decorated with memoized_with_request, so - # neutronclient() is not called. We need to mock it separately. + # networkclient() is not called. We need to mock it separately. mock_is_extension_supported.return_value = True # trunk network_client = mock_networkclient.return_value @@ -1740,7 +1739,10 @@ class NeutronApiTests(test.APIMockTestCase): self._test_get_router_ha_permission_with_policy_check(False) @mock.patch.object(api.neutron, 'networkclient') - def test_list_resources_with_long_filters(self, mock_networkclient): + @mock.patch.object(api.neutron, '_get_excess') + def test_list_resources_with_long_filters(self, + mock_excess, + mock_networkclient): # In this tests, port_list is called with id=[10 port ID] # filter. It generates about 40*10 char length URI. # Each port ID is converted to "id=&" in URI and @@ -1756,7 +1758,16 @@ class NeutronApiTests(test.APIMockTestCase): port_ids = tuple([port['id'] for port in ports]) network_client = mock_networkclient.return_value - uri_len_exc = neutron_exc.RequestURITooLong(excess=220) + uri_len_exc = sdk_exceptions.HttpException(http_status=414) + + # Note(lajoskatona): with neutronclient http414 (RequestURITooLong) + # had the excess argument, in SDK no such option, so have to + # workaround that and count from the uri and MAX_URI_LEN, 8192, + # see the code in api/neutron.py. From this test mocking can help + # to force the use of smaller excess value. + # This can be a discussion topic to have similar exception in SDK. + mock_excess.return_value = 220 + list_ports_retval = [uri_len_exc] for i in range(0, 10, 4): list_ports_retval.append(ports[i:i + 4]) @@ -2039,9 +2050,7 @@ class NeutronApiSecurityGroupTests(test.APIMockTestCase): def setUp(self): super().setUp() - neutronclient = mock.patch.object(api.neutron, 'neutronclient').start() networkclient = mock.patch.object(api.neutron, 'networkclient').start() - self.qclient = neutronclient.return_value self.netclient = networkclient.return_value self.sg_dict = dict([(sg['id'], sg['name']) for sg in self.api_security_groups_sdk]) diff --git a/requirements.txt b/requirements.txt index 21dc565b14..f5ba70c78a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,6 +12,7 @@ futurist>=1.2.0 # Apache-2.0 iso8601>=0.1.11 # MIT keystoneauth1>=4.3.1 # Apache-2.0 netaddr>=0.7.18 # BSD +openstacksdk>=4.5.0 # Apache-2.0 oslo.concurrency>=4.5.0 # Apache-2.0 oslo.config>=8.8.0 # Apache-2.0 oslo.i18n>=5.1.0 # Apache-2.0 @@ -25,7 +26,6 @@ Pillow>=9.1.0 # PIL License python-cinderclient>=8.0.0 # Apache-2.0 python-glanceclient>=2.8.0 # Apache-2.0 python-keystoneclient>=3.22.0 # Apache-2.0 -python-neutronclient>=8.1.0 # Apache-2.0 python-novaclient>=9.1.0 # Apache-2.0 python-swiftclient>=3.2.0 # Apache-2.0 PyYAML>=6.0 # MIT