From 8387b114e38f21922967ba982bb1a25289fdb3ab Mon Sep 17 00:00:00 2001 From: Rodolfo Alonso Hernandez Date: Thu, 24 Sep 2020 14:49:55 +0000 Subject: [PATCH] Add "fields" parameter to ListPort query This new query parameter will allow to send a query to the Neutron server filtering only by those parameters needed by the list command: ID, name, MAC address, fixed IPs and status. When using input parameter "long", security groups IDs, device owner and tags will be added to the fields filter. With 4500 ports, those are the execution times for the command "openstack port list" (average values in a development environment): Neutron API (seconds) CLI (seconds) Without filter: 3.05 10.15 With filter: 2.76 8.19 Depends-On: https://review.opendev.org/#/c/754113/ Change-Id: I1cccf0bc3533f8085e8dd61bf2fbe78c49b74b31 Closes-Bug: #1897100 --- lower-constraints.txt | 2 +- openstackclient/network/v2/port.py | 2 +- .../tests/unit/network/v2/test_port.py | 74 ++++++++++++++----- requirements.txt | 2 +- 4 files changed, 58 insertions(+), 22 deletions(-) diff --git a/lower-constraints.txt b/lower-constraints.txt index 2dae561cc..b489501b8 100644 --- a/lower-constraints.txt +++ b/lower-constraints.txt @@ -45,7 +45,7 @@ msgpack-python==0.4.0 munch==2.1.0 netaddr==0.7.18 netifaces==0.10.4 -openstacksdk==0.48.0 +openstacksdk==0.51.0 os-service-types==1.7.0 os-testr==1.0.0 osc-lib==2.2.0 diff --git a/openstackclient/network/v2/port.py b/openstackclient/network/v2/port.py index 02ab06c1c..cb77759ef 100644 --- a/openstackclient/network/v2/port.py +++ b/openstackclient/network/v2/port.py @@ -665,7 +665,7 @@ class ListPort(command.Lister): _tag.get_tag_filtering_args(parsed_args, filters) - data = network_client.ports(**filters) + data = network_client.ports(fields=columns, **filters) headers, attrs = utils.calculate_header_and_attrs( column_headers, columns, parsed_args) diff --git a/openstackclient/tests/unit/network/v2/test_port.py b/openstackclient/tests/unit/network/v2/test_port.py index d8889ae55..f7685f46e 100644 --- a/openstackclient/tests/unit/network/v2/test_port.py +++ b/openstackclient/tests/unit/network/v2/test_port.py @@ -26,6 +26,10 @@ from openstackclient.tests.unit.network.v2 import fakes as network_fakes from openstackclient.tests.unit import utils as tests_utils +LIST_FIELDS_TO_RETRIEVE = ('id', 'name', 'mac_address', 'fixed_ips', 'status') +LIST_FIELDS_TO_RETRIEVE_LONG = ('security_group_ids', 'device_owner', 'tags') + + class TestPort(network_fakes.TestNetworkV2): def setUp(self): @@ -883,7 +887,8 @@ class TestListPort(TestPort): columns, data = self.cmd.take_action(parsed_args) - self.network.ports.assert_called_once_with() + self.network.ports.assert_called_once_with( + fields=LIST_FIELDS_TO_RETRIEVE) self.assertEqual(self.columns, columns) self.assertListItemEqual(self.data, list(data)) @@ -901,7 +906,8 @@ class TestListPort(TestPort): columns, data = self.cmd.take_action(parsed_args) self.network.ports.assert_called_once_with(**{ - 'device_id': 'fake-router-id' + 'device_id': 'fake-router-id', + 'fields': LIST_FIELDS_TO_RETRIEVE, }) self.assertEqual(self.columns, columns) self.assertListItemEqual(self.data, list(data)) @@ -921,7 +927,8 @@ class TestListPort(TestPort): parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.network.ports.assert_called_once_with( - device_id=fake_server.id) + device_id=fake_server.id, + fields=LIST_FIELDS_TO_RETRIEVE) mock_find.assert_called_once_with(mock.ANY, 'fake-server-name') self.assertEqual(self.columns, columns) self.assertListItemEqual(self.data, list(data)) @@ -940,7 +947,8 @@ class TestListPort(TestPort): columns, data = self.cmd.take_action(parsed_args) self.network.ports.assert_called_once_with(**{ - 'device_id': self._ports[0].device_id + 'device_id': self._ports[0].device_id, + 'fields': LIST_FIELDS_TO_RETRIEVE, }) self.assertEqual(self.columns, columns) self.assertListItemEqual(self.data, list(data)) @@ -959,7 +967,8 @@ class TestListPort(TestPort): columns, data = self.cmd.take_action(parsed_args) self.network.ports.assert_called_once_with(**{ - 'device_owner': self._ports[0].device_owner + 'device_owner': self._ports[0].device_owner, + 'fields': LIST_FIELDS_TO_RETRIEVE, }) self.assertEqual(self.columns, columns) self.assertListItemEqual(self.data, list(data)) @@ -987,7 +996,8 @@ class TestListPort(TestPort): 'device_owner': self._ports[0].device_owner, 'device_id': 'fake-router-id', 'network_id': 'fake-network-id', - 'mac_address': self._ports[0].mac_address + 'mac_address': self._ports[0].mac_address, + 'fields': LIST_FIELDS_TO_RETRIEVE, }) self.assertEqual(self.columns, columns) self.assertListItemEqual(self.data, list(data)) @@ -1006,7 +1016,8 @@ class TestListPort(TestPort): columns, data = self.cmd.take_action(parsed_args) self.network.ports.assert_called_once_with(**{ - 'mac_address': self._ports[0].mac_address + 'mac_address': self._ports[0].mac_address, + 'fields': LIST_FIELDS_TO_RETRIEVE, }) self.assertEqual(self.columns, columns) self.assertListItemEqual(self.data, list(data)) @@ -1025,7 +1036,9 @@ class TestListPort(TestPort): columns, data = self.cmd.take_action(parsed_args) self.network.ports.assert_called_once_with(**{ - 'fixed_ips': ['ip_address=%s' % ip_address]}) + 'fixed_ips': ['ip_address=%s' % ip_address], + 'fields': LIST_FIELDS_TO_RETRIEVE, + }) self.assertEqual(self.columns, columns) self.assertListItemEqual(self.data, list(data)) @@ -1043,7 +1056,9 @@ class TestListPort(TestPort): columns, data = self.cmd.take_action(parsed_args) self.network.ports.assert_called_once_with(**{ - 'fixed_ips': ['ip_address_substr=%s' % ip_address_ss]}) + 'fixed_ips': ['ip_address_substr=%s' % ip_address_ss], + 'fields': LIST_FIELDS_TO_RETRIEVE, + }) self.assertEqual(self.columns, columns) self.assertListItemEqual(self.data, list(data)) @@ -1063,7 +1078,9 @@ class TestListPort(TestPort): columns, data = self.cmd.take_action(parsed_args) self.network.ports.assert_called_once_with(**{ - 'fixed_ips': ['subnet_id=%s' % subnet_id]}) + 'fixed_ips': ['subnet_id=%s' % subnet_id], + 'fields': LIST_FIELDS_TO_RETRIEVE, + }) self.assertEqual(self.columns, columns) self.assertListItemEqual(self.data, list(data)) @@ -1087,7 +1104,9 @@ class TestListPort(TestPort): self.network.ports.assert_called_once_with(**{ 'fixed_ips': ['subnet_id=%s' % subnet_id, - 'ip_address=%s' % ip_address]}) + 'ip_address=%s' % ip_address], + 'fields': LIST_FIELDS_TO_RETRIEVE, + }) self.assertEqual(self.columns, columns) self.assertListItemEqual(self.data, list(data)) @@ -1103,15 +1122,19 @@ class TestListPort(TestPort): {'ip-address': ip_address}]) ] - self.fake_subnet = network_fakes.FakeSubnet.create_one_subnet( - {'id': subnet_id}) + self.fake_subnet = network_fakes.FakeSubnet.create_one_subnet({ + 'id': subnet_id, + 'fields': LIST_FIELDS_TO_RETRIEVE, + }) self.network.find_subnet = mock.Mock(return_value=self.fake_subnet) parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.network.ports.assert_called_once_with(**{ 'fixed_ips': ['subnet_id=%s' % subnet_id, - 'ip_address=%s' % ip_address]}) + 'ip_address=%s' % ip_address], + 'fields': LIST_FIELDS_TO_RETRIEVE, + }) self.assertEqual(self.columns, columns) self.assertListItemEqual(self.data, list(data)) @@ -1128,7 +1151,8 @@ class TestListPort(TestPort): columns, data = self.cmd.take_action(parsed_args) - self.network.ports.assert_called_once_with() + self.network.ports.assert_called_once_with( + fields=LIST_FIELDS_TO_RETRIEVE + LIST_FIELDS_TO_RETRIEVE_LONG) self.assertEqual(self.columns_long, columns) self.assertListItemEqual(self.data_long, list(data)) @@ -1142,7 +1166,10 @@ class TestListPort(TestPort): parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) - filters = {'binding:host_id': 'foobar'} + filters = { + 'binding:host_id': 'foobar', + 'fields': LIST_FIELDS_TO_RETRIEVE, + } self.network.ports.assert_called_once_with(**filters) self.assertEqual(self.columns, columns) @@ -1160,7 +1187,11 @@ class TestListPort(TestPort): parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) - filters = {'tenant_id': project.id, 'project_id': project.id} + filters = { + 'tenant_id': project.id, + 'project_id': project.id, + 'fields': LIST_FIELDS_TO_RETRIEVE, + } self.network.ports.assert_called_once_with(**filters) self.assertEqual(self.columns, columns) @@ -1180,7 +1211,11 @@ class TestListPort(TestPort): parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) - filters = {'tenant_id': project.id, 'project_id': project.id} + filters = { + 'tenant_id': project.id, + 'project_id': project.id, + 'fields': LIST_FIELDS_TO_RETRIEVE, + } self.network.ports.assert_called_once_with(**filters) self.assertEqual(self.columns, columns) @@ -1206,7 +1241,8 @@ class TestListPort(TestPort): **{'tags': 'red,blue', 'any_tags': 'red,green', 'not_tags': 'orange,yellow', - 'not_any_tags': 'black,white'} + 'not_any_tags': 'black,white', + 'fields': LIST_FIELDS_TO_RETRIEVE} ) self.assertEqual(self.columns, columns) self.assertListItemEqual(self.data, list(data)) diff --git a/requirements.txt b/requirements.txt index 99d409bf5..9430a7fde 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,7 +5,7 @@ pbr!=2.1.0,>=2.0.0 # Apache-2.0 cliff>=3.4.0 # Apache-2.0 iso8601>=0.1.11 # MIT -openstacksdk>=0.48.0 # Apache-2.0 +openstacksdk>=0.51.0 # Apache-2.0 osc-lib>=2.2.0 # Apache-2.0 oslo.i18n>=3.15.3 # Apache-2.0 python-keystoneclient>=3.22.0 # Apache-2.0