From 5cdc805b3ece20fe1de83730d40beb84f22c4062 Mon Sep 17 00:00:00 2001 From: Ivan Kolodyazhny Date: Sat, 23 Jan 2016 13:35:15 +0200 Subject: [PATCH] Check for service existance in capabilities API We have to return 404 error code if requested backend is not found and 502 if request failed with timeout. APIImpact Change-Id: Ia392973121800278751642f0a22ee817b3a69b74 Closes-Bug: #1520077 --- cinder/api/contrib/capabilities.py | 14 ++++++++- cinder/exception.py | 6 ++++ .../unit/api/contrib/test_capabilities.py | 31 +++++++++++++++++-- 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/cinder/api/contrib/capabilities.py b/cinder/api/contrib/capabilities.py index 177d73aa5..087aad683 100644 --- a/cinder/api/contrib/capabilities.py +++ b/cinder/api/contrib/capabilities.py @@ -14,10 +14,14 @@ # under the License. from oslo_log import log as logging +import oslo_messaging from cinder.api import extensions from cinder.api.openstack import wsgi from cinder.api.views import capabilities as capabilities_view +from cinder import exception +from cinder.i18n import _ +from cinder import objects from cinder.volume import rpcapi @@ -41,7 +45,15 @@ class CapabilitiesController(wsgi.Controller): """Return capabilities list of given backend.""" context = req.environ['cinder.context'] authorize(context, 'capabilities') - capabilities = self.volume_api.get_capabilities(context, id, False) + filters = {'host': id, 'binary': 'cinder-volume'} + service = objects.ServiceList.get_all(context, filters) + if not service: + msg = (_("Can't find service: %s") % id) + raise exception.NotFound(msg) + try: + capabilities = self.volume_api.get_capabilities(context, id, False) + except oslo_messaging.MessagingTimeout: + raise exception.RPCTimeout(service=id) return self._view_builder.summary(req, capabilities, id) diff --git a/cinder/exception.py b/cinder/exception.py index 6b3f940ef..87a296942 100644 --- a/cinder/exception.py +++ b/cinder/exception.py @@ -256,6 +256,12 @@ class APITimeout(APIException): message = _("Timeout while requesting %(service)s API.") +class RPCTimeout(CinderException): + message = _("Timeout while requesting capabilities from backend " + "%(service)s.") + code = 502 + + class NotFound(CinderException): message = _("Resource could not be found.") code = 404 diff --git a/cinder/tests/unit/api/contrib/test_capabilities.py b/cinder/tests/unit/api/contrib/test_capabilities.py index c5467e749..e02dbb211 100644 --- a/cinder/tests/unit/api/contrib/test_capabilities.py +++ b/cinder/tests/unit/api/contrib/test_capabilities.py @@ -15,8 +15,11 @@ import mock +import oslo_messaging + from cinder.api.contrib import capabilities from cinder import context +from cinder import exception from cinder import test from cinder.tests.unit.api import fakes @@ -54,8 +57,6 @@ def rpcapi_get_capabilities(self, context, host, discover): return capabilities -@mock.patch('cinder.volume.rpcapi.VolumeAPI.get_capabilities', - rpcapi_get_capabilities) class CapabilitiesAPITest(test.TestCase): def setUp(self): super(CapabilitiesAPITest, self).setUp() @@ -63,7 +64,11 @@ class CapabilitiesAPITest(test.TestCase): self.controller = capabilities.CapabilitiesController() self.ctxt = context.RequestContext('admin', 'fake', True) - def test_capabilities_summary(self): + @mock.patch('cinder.db.service_get_all') + @mock.patch('cinder.volume.rpcapi.VolumeAPI.get_capabilities', + rpcapi_get_capabilities) + def test_capabilities_summary(self, mock_services): + mock_services.return_value = [{'name': 'fake'}] req = fakes.HTTPRequest.blank('/fake/capabilities/fake') req.environ['cinder.context'] = self.ctxt res = self.controller.show(req, 'fake') @@ -100,3 +105,23 @@ class CapabilitiesAPITest(test.TestCase): } self.assertDictMatch(expected, res) + + @mock.patch('cinder.db.service_get_all') + @mock.patch('cinder.volume.rpcapi.VolumeAPI.get_capabilities') + def test_get_capabilities_rpc_timeout(self, mock_rpc, mock_services): + mock_rpc.side_effect = oslo_messaging.MessagingTimeout + mock_services.return_value = [{'name': 'fake'}] + + req = fakes.HTTPRequest.blank('/fake/capabilities/fake') + req.environ['cinder.context'] = self.ctxt + self.assertRaises(exception.RPCTimeout, + self.controller.show, req, 'fake') + + @mock.patch('cinder.db.service_get_all') + def test_get_capabilities_service_not_found(self, mock_services): + mock_services.return_value = [] + + req = fakes.HTTPRequest.blank('/fake/capabilities/fake') + req.environ['cinder.context'] = self.ctxt + self.assertRaises(exception.NotFound, + self.controller.show, req, 'fake') -- 2.45.2