Avoid fetching metadata when no subnets found
Metadata service uses the provider id to identify the requesting instance. However, when provider query doesn't find any networks, the request should fail. The same goes to the case where multiple ports are found. Closes-Bug: #1841933 Change-Id: I8ce3703ca86a3a0769edd42a790d82796d1071d7
This commit is contained in:
parent
80539a5e84
commit
3177371568
|
@ -209,16 +209,21 @@ class MetadataRequestHandler(wsgi.Application):
|
|||
advanced_service_providers=[provider_id],
|
||||
fields=['network_id'])
|
||||
|
||||
if not md_subnets or not md_subnets.get('subnets'):
|
||||
msg = _('Could not find any subnets for provider %s') % provider_id
|
||||
LOG.error(msg)
|
||||
raise webob.exc.HTTPBadRequest(explanation=msg)
|
||||
|
||||
md_networks = [subnet['network_id']
|
||||
for subnet in md_subnets['subnets']]
|
||||
|
||||
try:
|
||||
# Retrieve the instance data from the instance's port
|
||||
instance_data = neutron.list_ports(
|
||||
ports = neutron.list_ports(
|
||||
context,
|
||||
fixed_ips='ip_address=' + instance_address,
|
||||
network_id=md_networks,
|
||||
fields=['device_id', 'tenant_id'])['ports'][0]
|
||||
fields=['device_id', 'tenant_id'])['ports']
|
||||
except Exception as e:
|
||||
LOG.error('Failed to get instance id for metadata '
|
||||
'request, provider %(provider)s '
|
||||
|
@ -232,6 +237,17 @@ class MetadataRequestHandler(wsgi.Application):
|
|||
'Please try your request again.')
|
||||
raise webob.exc.HTTPBadRequest(explanation=msg)
|
||||
|
||||
if len(ports) != 1:
|
||||
msg = _('Expected a single port matching provider %(pr)s '
|
||||
'and IP %(ip)s. Found %(count)d.' % {
|
||||
'pr': provider_id,
|
||||
'ip': instance_address,
|
||||
'count': len(ports)})
|
||||
|
||||
LOG.error(msg)
|
||||
raise webob.exc.HTTPBadRequest(explanation=msg)
|
||||
|
||||
instance_data = ports[0]
|
||||
instance_id = instance_data['device_id']
|
||||
tenant_id = instance_data['tenant_id']
|
||||
|
||||
|
|
|
@ -1579,6 +1579,63 @@ class MetadataHandlerTestCase(test.TestCase):
|
|||
'X-Metadata-Provider-Signature': signature})
|
||||
self.assertEqual(403, response.status_int)
|
||||
|
||||
@mock.patch.object(neutronapi, 'get_client', return_value=mock.Mock())
|
||||
def test_metadata_lb_net_not_found(self, mock_get_client):
|
||||
|
||||
self.flags(service_metadata_proxy=True, group='neutron')
|
||||
|
||||
# with X-Metadata-Provider
|
||||
proxy_lb_id = 'edge-x'
|
||||
mock_client = mock_get_client.return_value
|
||||
mock_client.list_ports.return_value = {
|
||||
'ports': [{'device_id': 'a-b-c-d', 'tenant_id': 'test'}]}
|
||||
mock_client.list_subnets.return_value = {
|
||||
'subnets': []}
|
||||
|
||||
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(400, response.status_int)
|
||||
|
||||
def _test_metadata_lb_incorrect_port_count(self, mock_get_client, ports):
|
||||
|
||||
self.flags(service_metadata_proxy=True, group='neutron')
|
||||
|
||||
# with X-Metadata-Provider
|
||||
proxy_lb_id = 'edge-x'
|
||||
mock_client = mock_get_client.return_value
|
||||
mock_client.list_ports.return_value = {'ports': ports}
|
||||
mock_client.list_ports.return_value = {
|
||||
'ports': [{'device_id': 'a-b-c-d', 'tenant_id': 'test'},
|
||||
{'device_id': 'x-y-z', 'tenant_id': 'test'}]}
|
||||
mock_client.list_subnets.return_value = {
|
||||
'subnets': [{'network_id': 'f-f-f-f'}]}
|
||||
|
||||
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(400, response.status_int)
|
||||
|
||||
@mock.patch.object(neutronapi, 'get_client', return_value=mock.Mock())
|
||||
def test_metadata_lb_too_many_ports(self, mock_get_client):
|
||||
self._test_metadata_lb_incorrect_port_count(
|
||||
mock_get_client,
|
||||
[{'device_id': 'a-b-c-d', 'tenant_id': 'test'},
|
||||
{'device_id': 'x-y-z', 'tenant_id': 'test'}])
|
||||
|
||||
@mock.patch.object(neutronapi, 'get_client', return_value=mock.Mock())
|
||||
def test_metadata_no_ports_found(self, mock_get_client):
|
||||
self._test_metadata_lb_incorrect_port_count(
|
||||
mock_get_client, [])
|
||||
|
||||
@mock.patch.object(context, 'get_admin_context')
|
||||
@mock.patch('nova.network.neutron.API')
|
||||
def test_get_metadata_by_address(self, mock_net_api, mock_get_context):
|
||||
|
|
Loading…
Reference in New Issue