Support large network queries towards neutron
While querying metadata from an LB source, the subnet query may result with a large number of networks. That might exceed the maximum request length on the following port query towards Neutron. The patch addresses such issue. Closes-Bug: #1861087 Change-Id: I9d72c80574d08d8409ed0dcc0476f52a0d173a1e
This commit is contained in:
@@ -39,6 +39,12 @@ from nova.network import neutron as neutronapi
|
||||
CONF = nova.conf.CONF
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
# 160 networks is large enough to satisfy most cases.
|
||||
# Yet while reaching 182 networks Neutron server will break as URL length
|
||||
# exceeds the maximum. Left this at 160 to allow additional parameters when
|
||||
# they're needed.
|
||||
MAX_QUERY_NETWORKS = 160
|
||||
|
||||
|
||||
class MetadataRequestHandler(wsgi.Application):
|
||||
"""Serve metadata."""
|
||||
@@ -219,11 +225,14 @@ class MetadataRequestHandler(wsgi.Application):
|
||||
|
||||
try:
|
||||
# Retrieve the instance data from the instance's port
|
||||
ports = neutron.list_ports(
|
||||
context,
|
||||
fixed_ips='ip_address=' + instance_address,
|
||||
network_id=md_networks,
|
||||
fields=['device_id', 'tenant_id'])['ports']
|
||||
ports = []
|
||||
while md_networks:
|
||||
ports.extend(neutron.list_ports(
|
||||
context,
|
||||
fixed_ips='ip_address=' + instance_address,
|
||||
network_id=md_networks[:MAX_QUERY_NETWORKS],
|
||||
fields=['device_id', 'tenant_id'])['ports'])
|
||||
md_networks = md_networks[MAX_QUERY_NETWORKS:]
|
||||
except Exception as e:
|
||||
LOG.error('Failed to get instance id for metadata '
|
||||
'request, provider %(provider)s '
|
||||
|
||||
@@ -1400,6 +1400,45 @@ class MetadataHandlerTestCase(test.TestCase):
|
||||
|
||||
self.assertEqual(200, response.status_int)
|
||||
|
||||
@mock.patch.object(neutronapi, 'get_client', return_value=mock.Mock())
|
||||
def test_metadata_lb_proxy_many_networks(self, mock_get_client):
|
||||
|
||||
def fake_list_ports(context, fixed_ips, network_id, fields):
|
||||
if 'f-f-f-f' in network_id:
|
||||
return {'ports':
|
||||
[{'device_id': 'a-b-c-d', 'tenant_id': 'test'}]}
|
||||
return {'ports': []}
|
||||
|
||||
self.flags(service_metadata_proxy=True, group='neutron')
|
||||
handler.MAX_QUERY_NETWORKS = 10
|
||||
|
||||
self.expected_instance_id = b'a-b-c-d'
|
||||
|
||||
# with X-Metadata-Provider
|
||||
proxy_lb_id = 'edge-x'
|
||||
|
||||
mock_client = mock_get_client.return_value
|
||||
subnet_list = [{'network_id': 'f-f-f-' + chr(c)}
|
||||
for c in range(ord('a'), ord('z'))]
|
||||
mock_client.list_subnets.return_value = {
|
||||
'subnets': subnet_list}
|
||||
|
||||
with mock.patch.object(
|
||||
mock_client, 'list_ports',
|
||||
side_effect=fake_list_ports) as mock_list_ports:
|
||||
|
||||
response = fake_request(
|
||||
self, self.mdinst,
|
||||
relpath="/2009-04-04/user-data",
|
||||
address="192.192.192.2",
|
||||
fake_get_metadata_by_instance_id=self._fake_x_get_metadata,
|
||||
headers={'X-Forwarded-For': '192.192.192.2',
|
||||
'X-Metadata-Provider': proxy_lb_id})
|
||||
|
||||
self.assertEqual(3, mock_list_ports.call_count)
|
||||
|
||||
self.assertEqual(200, response.status_int)
|
||||
|
||||
@mock.patch.object(neutronapi, 'get_client', return_value=mock.Mock())
|
||||
def _metadata_handler_with_provider_id(self, hnd, mock_get_client):
|
||||
# with X-Metadata-Provider
|
||||
|
||||
Reference in New Issue
Block a user