From 0aefe1ccba63faa0d0e7131bbbd3331741e3ec2e Mon Sep 17 00:00:00 2001
From: Mykola Yakovliev <VegasQ@gmail.com>
Date: Fri, 8 Jun 2018 14:35:36 -0500
Subject: [PATCH] Ensure API calls for subnets are in URL length limit

Fix situation when with pagination enabled, neutronclient failed
to read subnets information due to too long URI.

Change-Id: I53240c536d77a95510b5c83b81e21782f29d886a
Closes-Bug: 1775922
---
 neutronclient/neutron/v2_0/network.py          | 5 +++++
 neutronclient/tests/unit/test_cli20_network.py | 8 ++++++--
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/neutronclient/neutron/v2_0/network.py b/neutronclient/neutron/v2_0/network.py
index 3ec3ac6d5..6c68b623a 100644
--- a/neutronclient/neutron/v2_0/network.py
+++ b/neutronclient/neutron/v2_0/network.py
@@ -44,6 +44,9 @@ class ListNetwork(neutronV20.ListCommand):
     # Length of a query filter on subnet id
     # id=<uuid>& (with len(uuid)=36)
     subnet_id_filter_len = 40
+    # Length of a marker in pagination
+    # &marker=<uuid> (with len(uuid)=36)
+    marker_len = 44
     resource = 'network'
     _formatters = {'subnets': _format_subnets, }
     list_columns = ['id', 'name', 'subnets']
@@ -115,6 +118,8 @@ class ListNetwork(neutronV20.ListCommand):
             subnet_count = len(subnet_ids)
             max_size = ((self.subnet_id_filter_len * subnet_count) -
                         uri_len_exc.excess)
+            if self.pagination_support:
+                max_size -= self.marker_len
             chunk_size = max_size // self.subnet_id_filter_len
             subnets = []
             for i in range(0, subnet_count, chunk_size):
diff --git a/neutronclient/tests/unit/test_cli20_network.py b/neutronclient/tests/unit/test_cli20_network.py
index 230c5d49e..2f7a46896 100644
--- a/neutronclient/tests/unit/test_cli20_network.py
+++ b/neutronclient/tests/unit/test_cli20_network.py
@@ -653,8 +653,12 @@ class CLITestV20ExtendListNetworkJSON(test_cli20.CLITestV20Base):
         data = [{'id': 'netid%d' % i, 'name': 'net%d' % i,
                  'subnets': ['mysubid%d' % i]}
                 for i in range(10)]
-        filters1, response1 = self._build_test_data(data[:len(data) - 1])
-        filters2, response2 = self._build_test_data(data[len(data) - 1:])
+        # Since in pagination we add &marker=<uuid> (44 symbols), total change
+        # is 45 symbols. Single subnet takes 40 symbols (id=<uuid>&).
+        # Because of it marker will take more space than single subnet filter,
+        # and we expect neutron to send last 2 subnets in separate response.
+        filters1, response1 = self._build_test_data(data[:len(data) - 2])
+        filters2, response2 = self._build_test_data(data[len(data) - 2:])
         path = getattr(self.client, 'subnets_path')
         cmd = network.ListNetwork(test_cli20.MyApp(sys.stdout), None)
         with mock.patch.object(cmd, "get_client",