Handle initialize_connection() exception in volume manager
Due to the fact that several drivers require backend communication to fetch connection information for a volume, it's possile that these driver throw exceptions while doing that. Currently exceptions can bubble up to volume API not being handled. This patch logs exception in volume manager and then raises VolumeBackendAPIException to caller. Change-Id: Ib3cc152e04ba029dd835a64b0cfb0a77b8a6828e Closes-bug: 1256804
This commit is contained in:
parent
e40dafd544
commit
17e556acf5
|
@ -188,9 +188,14 @@ class VolumeActionsController(wsgi.Controller):
|
|||
connector = body['os-initialize_connection']['connector']
|
||||
except KeyError:
|
||||
raise webob.exc.HTTPBadRequest("Must specify 'connector'")
|
||||
info = self.volume_api.initialize_connection(context,
|
||||
volume,
|
||||
connector)
|
||||
try:
|
||||
info = self.volume_api.initialize_connection(context,
|
||||
volume,
|
||||
connector)
|
||||
except exception.VolumeBackendAPIException as error:
|
||||
msg = _("Unable to fetch connection information from backend.")
|
||||
raise webob.exc.HTTPInternalServerError(msg)
|
||||
|
||||
return {'connection_info': info}
|
||||
|
||||
@wsgi.action('os-terminate_connection')
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
import datetime
|
||||
import json
|
||||
import uuid
|
||||
|
||||
import mock
|
||||
import webob
|
||||
|
||||
from cinder.api.contrib import volume_actions
|
||||
|
@ -65,34 +67,44 @@ class VolumeActionsTest(test.TestCase):
|
|||
self.assertEqual(res.status_int, 202)
|
||||
|
||||
def test_initialize_connection(self):
|
||||
def fake_initialize_connection(*args, **kwargs):
|
||||
return {}
|
||||
self.stubs.Set(volume.API, 'initialize_connection',
|
||||
fake_initialize_connection)
|
||||
with mock.patch.object(volume_api.API,
|
||||
'initialize_connection') as init_conn:
|
||||
init_conn.return_value = {}
|
||||
body = {'os-initialize_connection': {'connector': 'fake'}}
|
||||
req = webob.Request.blank('/v2/fake/volumes/1/action')
|
||||
req.method = "POST"
|
||||
req.body = jsonutils.dumps(body)
|
||||
req.headers["content-type"] = "application/json"
|
||||
|
||||
body = {'os-initialize_connection': {'connector': 'fake'}}
|
||||
req = webob.Request.blank('/v2/fake/volumes/1/action')
|
||||
req.method = "POST"
|
||||
req.body = jsonutils.dumps(body)
|
||||
req.headers["content-type"] = "application/json"
|
||||
|
||||
res = req.get_response(fakes.wsgi_app())
|
||||
self.assertEqual(res.status_int, 200)
|
||||
res = req.get_response(fakes.wsgi_app())
|
||||
self.assertEqual(res.status_int, 200)
|
||||
|
||||
def test_initialize_connection_without_connector(self):
|
||||
def fake_initialize_connection(*args, **kwargs):
|
||||
return {}
|
||||
self.stubs.Set(volume.API, 'initialize_connection',
|
||||
fake_initialize_connection)
|
||||
with mock.patch.object(volume_api.API,
|
||||
'initialize_connection') as init_conn:
|
||||
init_conn.return_value = {}
|
||||
body = {'os-initialize_connection': {}}
|
||||
req = webob.Request.blank('/v2/fake/volumes/1/action')
|
||||
req.method = "POST"
|
||||
req.body = jsonutils.dumps(body)
|
||||
req.headers["content-type"] = "application/json"
|
||||
|
||||
body = {'os-initialize_connection': {}}
|
||||
req = webob.Request.blank('/v2/fake/volumes/1/action')
|
||||
req.method = "POST"
|
||||
req.body = jsonutils.dumps(body)
|
||||
req.headers["content-type"] = "application/json"
|
||||
res = req.get_response(fakes.wsgi_app())
|
||||
self.assertEqual(res.status_int, 400)
|
||||
|
||||
res = req.get_response(fakes.wsgi_app())
|
||||
self.assertEqual(res.status_int, 400)
|
||||
def test_initialize_connection_exception(self):
|
||||
with mock.patch.object(volume_api.API,
|
||||
'initialize_connection') as init_conn:
|
||||
init_conn.side_effect = \
|
||||
exception.VolumeBackendAPIException(data=None)
|
||||
body = {'os-initialize_connection': {'connector': 'fake'}}
|
||||
req = webob.Request.blank('/v2/fake/volumes/1/action')
|
||||
req.method = "POST"
|
||||
req.body = jsonutils.dumps(body)
|
||||
req.headers["content-type"] = "application/json"
|
||||
|
||||
res = req.get_response(fakes.wsgi_app())
|
||||
self.assertEqual(res.status_int, 500)
|
||||
|
||||
def test_terminate_connection(self):
|
||||
def fake_terminate_connection(*args, **kwargs):
|
||||
|
|
|
@ -708,7 +708,13 @@ class VolumeManager(manager.SchedulerDependentManager):
|
|||
"""
|
||||
volume = self.db.volume_get(context, volume_id)
|
||||
self.driver.validate_connector(connector)
|
||||
conn_info = self.driver.initialize_connection(volume, connector)
|
||||
try:
|
||||
conn_info = self.driver.initialize_connection(volume, connector)
|
||||
except Exception as err:
|
||||
err_msg = (_('Unable to fetch connection information from '
|
||||
'backend: %(err)s') % {'err': str(err)})
|
||||
LOG.error(err_msg)
|
||||
raise exception.VolumeBackendAPIException(data=err_msg)
|
||||
|
||||
# Add qos_specs to connection info
|
||||
typeid = volume['volume_type_id']
|
||||
|
|
Loading…
Reference in New Issue