Skip to content

Commit bfae864

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Fixing the 500 HTTP code in the metadata service if Nova is down" into stable/2024.1
2 parents 51961e1 + 646270d commit bfae864

File tree

5 files changed

+78
-24
lines changed

5 files changed

+78
-24
lines changed

neutron/agent/metadata/agent.py

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -246,12 +246,18 @@ def _proxy_request(self, instance_id, tenant_id, req):
246246
client_cert = (self.conf.nova_client_cert,
247247
self.conf.nova_client_priv_key)
248248

249-
resp = requests.request(method=req.method, url=url,
250-
headers=headers,
251-
data=req.body,
252-
cert=client_cert,
253-
verify=verify_cert,
254-
timeout=60)
249+
try:
250+
resp = requests.request(method=req.method, url=url,
251+
headers=headers,
252+
data=req.body,
253+
cert=client_cert,
254+
verify=verify_cert,
255+
timeout=60)
256+
except requests.ConnectionError:
257+
msg = _('The remote metadata server is temporarily unavailable. '
258+
'Please try again later.')
259+
explanation = str(msg)
260+
return webob.exc.HTTPServiceUnavailable(explanation=explanation)
255261

256262
if resp.status_code == 200:
257263
req.response.content_type = resp.headers['content-type']
@@ -264,19 +270,16 @@ def _proxy_request(self, instance_id, tenant_id, req):
264270
'response usually occurs when shared secrets do not match.'
265271
)
266272
return webob.exc.HTTPForbidden()
267-
elif resp.status_code == 400:
268-
return webob.exc.HTTPBadRequest()
269-
elif resp.status_code == 404:
270-
return webob.exc.HTTPNotFound()
271-
elif resp.status_code == 409:
272-
return webob.exc.HTTPConflict()
273273
elif resp.status_code == 500:
274274
msg = _(
275275
'Remote metadata server experienced an internal server error.'
276276
)
277277
LOG.warning(msg)
278278
explanation = str(msg)
279279
return webob.exc.HTTPInternalServerError(explanation=explanation)
280+
elif resp.status_code in (400, 404, 409, 502, 503, 504):
281+
webob_exc_cls = webob.exc.status_map.get(resp.status_code)
282+
return webob_exc_cls()
280283
else:
281284
raise Exception(_('Unexpected response code: %s') %
282285
resp.status_code)

neutron/agent/ovn/metadata/server.py

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -168,12 +168,18 @@ def _proxy_request(self, instance_id, tenant_id, req):
168168
client_cert = (self.conf.nova_client_cert,
169169
self.conf.nova_client_priv_key)
170170

171-
resp = requests.request(method=req.method, url=url,
172-
headers=headers,
173-
data=req.body,
174-
cert=client_cert,
175-
verify=verify_cert,
176-
timeout=60)
171+
try:
172+
resp = requests.request(method=req.method, url=url,
173+
headers=headers,
174+
data=req.body,
175+
cert=client_cert,
176+
verify=verify_cert,
177+
timeout=60)
178+
except requests.ConnectionError:
179+
msg = _('The remote metadata server is temporarily unavailable. '
180+
'Please try again later.')
181+
explanation = str(msg)
182+
return webob.exc.HTTPServiceUnavailable(explanation=explanation)
177183

178184
if resp.status_code == 200:
179185
req.response.content_type = resp.headers['content-type']
@@ -186,19 +192,16 @@ def _proxy_request(self, instance_id, tenant_id, req):
186192
'response usually occurs when shared secrets do not match.'
187193
)
188194
return webob.exc.HTTPForbidden()
189-
elif resp.status_code == 400:
190-
return webob.exc.HTTPBadRequest()
191-
elif resp.status_code == 404:
192-
return webob.exc.HTTPNotFound()
193-
elif resp.status_code == 409:
194-
return webob.exc.HTTPConflict()
195195
elif resp.status_code == 500:
196196
msg = _(
197197
'Remote metadata server experienced an internal server error.'
198198
)
199199
LOG.warning(msg)
200200
explanation = str(msg)
201201
return webob.exc.HTTPInternalServerError(explanation=explanation)
202+
elif resp.status_code in (400, 404, 409, 502, 503, 504):
203+
webob_exc_cls = webob.exc.status_map.get(resp.status_code)
204+
return webob_exc_cls()
202205
else:
203206
raise Exception(_('Unexpected response code: %s') %
204207
resp.status_code)

neutron/tests/unit/agent/metadata/test_agent.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import ddt
1818
import netaddr
1919
from neutron_lib import constants as n_const
20+
import requests
2021
import testtools
2122
import webob
2223

@@ -469,10 +470,30 @@ def test_proxy_request_500(self):
469470
self.assertIsInstance(self._proxy_request_test_helper(500),
470471
webob.exc.HTTPInternalServerError)
471472

473+
def test_proxy_request_502(self):
474+
self.assertIsInstance(self._proxy_request_test_helper(502),
475+
webob.exc.HTTPBadGateway)
476+
477+
def test_proxy_request_503(self):
478+
self.assertIsInstance(self._proxy_request_test_helper(503),
479+
webob.exc.HTTPServiceUnavailable)
480+
481+
def test_proxy_request_504(self):
482+
self.assertIsInstance(self._proxy_request_test_helper(504),
483+
webob.exc.HTTPGatewayTimeout)
484+
472485
def test_proxy_request_other_code(self):
473486
with testtools.ExpectedException(Exception):
474487
self._proxy_request_test_helper(302)
475488

489+
def test_proxy_request_conenction_error(self):
490+
req = mock.Mock(path_info='/the_path', query_string='', headers={},
491+
method='GET', body='')
492+
with mock.patch('requests.request') as mock_request:
493+
mock_request.side_effect = requests.ConnectionError()
494+
retval = self.handler._proxy_request('the_id', 'tenant_id', req)
495+
self.assertIsInstance(retval, webob.exc.HTTPServiceUnavailable)
496+
476497

477498
class TestMetadataProxyHandlerNewCache(TestMetadataProxyHandlerBase,
478499
_TestMetadataProxyHandlerCacheMixin):

neutron/tests/unit/agent/ovn/metadata/test_server.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from oslo_config import cfg
1919
from oslo_config import fixture as config_fixture
2020
from oslo_utils import fileutils
21+
import requests
2122
import testtools
2223
import webob
2324

@@ -232,10 +233,30 @@ def test_proxy_request_500(self):
232233
self.assertIsInstance(self._proxy_request_test_helper(500),
233234
webob.exc.HTTPInternalServerError)
234235

236+
def test_proxy_request_502(self):
237+
self.assertIsInstance(self._proxy_request_test_helper(502),
238+
webob.exc.HTTPBadGateway)
239+
240+
def test_proxy_request_503(self):
241+
self.assertIsInstance(self._proxy_request_test_helper(503),
242+
webob.exc.HTTPServiceUnavailable)
243+
244+
def test_proxy_request_504(self):
245+
self.assertIsInstance(self._proxy_request_test_helper(504),
246+
webob.exc.HTTPGatewayTimeout)
247+
235248
def test_proxy_request_other_code(self):
236249
with testtools.ExpectedException(Exception):
237250
self._proxy_request_test_helper(302)
238251

252+
def test_proxy_request_conenction_error(self):
253+
req = mock.Mock(path_info='/the_path', query_string='', headers={},
254+
method='GET', body='')
255+
with mock.patch('requests.request') as mock_request:
256+
mock_request.side_effect = requests.ConnectionError()
257+
retval = self.handler._proxy_request('the_id', 'tenant_id', req)
258+
self.assertIsInstance(retval, webob.exc.HTTPServiceUnavailable)
259+
239260

240261
class TestUnixDomainMetadataProxy(base.BaseTestCase):
241262
def setUp(self):
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
other:
3+
- |
4+
Enhance error handling in the Neutron metadata service for cases when the
5+
Nova metadata service is unavailable, ensuring correct HTTP status codes
6+
are returned.

0 commit comments

Comments
 (0)