From c91ee68d493e8c813f4dcc4e46b1794a50f69f32 Mon Sep 17 00:00:00 2001 From: Matt Riedemann Date: Sat, 10 Jun 2017 09:24:48 -0400 Subject: [PATCH] Handle InstanceNotFound when setting password via metadata When setting an instance password via the metadata service, if the instance is not found it results in a 500 response to the caller. This change handles the InstanceNotFound error and returns it as a 400. Note it's a 400 since the instance uuid is part of the POST request body, not on the URL path so it's not a 404 response. Change-Id: I4aa99b563e1a5a87aa3e3dfb28800f107676df92 Partial-Bug: #1696848 --- nova/api/metadata/password.py | 6 +++++- nova/tests/unit/test_metadata.py | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/nova/api/metadata/password.py b/nova/api/metadata/password.py index f180a41225..96531e43a7 100644 --- a/nova/api/metadata/password.py +++ b/nova/api/metadata/password.py @@ -18,6 +18,7 @@ from six.moves import range from webob import exc from nova import context +from nova import exception from nova.i18n import _ from nova import objects from nova import utils @@ -69,7 +70,10 @@ def handle_password(req, meta_data): im = objects.InstanceMapping.get_by_instance_uuid(ctxt, meta_data.uuid) with context.target_cell(ctxt, im.cell_mapping) as cctxt: - instance = objects.Instance.get_by_uuid(cctxt, meta_data.uuid) + try: + instance = objects.Instance.get_by_uuid(cctxt, meta_data.uuid) + except exception.InstanceNotFound as e: + raise exc.HTTPBadRequest(explanation=e.format_message()) instance.system_metadata.update(convert_password(ctxt, req.body)) instance.save() else: diff --git a/nova/tests/unit/test_metadata.py b/nova/tests/unit/test_metadata.py index f90aedec88..ca847eced6 100644 --- a/nova/tests/unit/test_metadata.py +++ b/nova/tests/unit/test_metadata.py @@ -1635,6 +1635,20 @@ class MetadataPasswordTestCase(test.TestCase): result = password.handle_password(request, self.mdinst) self.assertEqual(result, 'foo') + @mock.patch.object(objects.InstanceMapping, 'get_by_instance_uuid', + return_value=objects.InstanceMapping(cell_mapping=None)) + @mock.patch.object(objects.Instance, 'get_by_uuid') + def test_set_password_instance_not_found(self, get_by_uuid, get_mapping): + """Tests that a 400 is returned if the instance can not be found.""" + get_by_uuid.side_effect = exception.InstanceNotFound( + instance_id=self.instance.uuid) + request = webob.Request.blank('') + request.method = 'POST' + request.val = b'foo' + request.content_length = len(request.body) + self.assertRaises(webob.exc.HTTPBadRequest, password.handle_password, + request, self.mdinst) + def test_bad_method(self): request = webob.Request.blank('') request.method = 'PUT'