diff options
author | Jenkins <jenkins@review.openstack.org> | 2016-03-17 06:18:25 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2016-03-17 06:18:26 +0000 |
commit | 9606ab3e033eb56c6613446c31a3387bb725e24f (patch) | |
tree | 3be8a469be50104cd1e199e0707f8848fe0e489c /nova | |
parent | c3210f4c04580d8c64a8280d8095b04c157cf739 (diff) | |
parent | c3d5cf8e76efe73f1630a916e0925672703c1754 (diff) | |
download | nova-9606ab3e033eb56c6613446c31a3387bb725e24f.tar.gz |
Merge "Rollback is needed if initialize_connection times out" into stable/liberty
Diffstat (limited to 'nova')
-rw-r--r-- | nova/tests/unit/volume/test_cinder.py | 30 | ||||
-rw-r--r-- | nova/volume/cinder.py | 30 |
2 files changed, 58 insertions, 2 deletions
diff --git a/nova/tests/unit/volume/test_cinder.py b/nova/tests/unit/volume/test_cinder.py index 7b51c2af96..b3802a6d12 100644 --- a/nova/tests/unit/volume/test_cinder.py +++ b/nova/tests/unit/volume/test_cinder.py @@ -286,6 +286,36 @@ class CinderApiTestCase(test.NoDBTestCase): self.api.initialize_connection(self.ctx, 'id1', 'connector') + @mock.patch('nova.volume.cinder.cinderclient') + def test_initialize_connection_rollback(self, mock_cinderclient): + mock_cinderclient.return_value.volumes.\ + initialize_connection.side_effect = ( + cinder_exception.ClientException(500, "500")) + + connector = {'host': 'host1'} + ex = self.assertRaises(cinder_exception.ClientException, + self.api.initialize_connection, + self.ctx, + 'id1', + connector) + self.assertEqual(500, ex.code) + mock_cinderclient.return_value.volumes.\ + terminate_connection.assert_called_once_with('id1', connector) + + @mock.patch('nova.volume.cinder.cinderclient') + def test_initialize_connection_no_rollback(self, mock_cinderclient): + mock_cinderclient.return_value.volumes.\ + initialize_connection.side_effect = test.TestingException + + connector = {'host': 'host1'} + self.assertRaises(test.TestingException, + self.api.initialize_connection, + self.ctx, + 'id1', + connector) + self.assertFalse(mock_cinderclient.return_value.volumes. + terminate_connection.called) + def test_terminate_connection(self): cinder.cinderclient(self.ctx).AndReturn(self.cinderclient) self.mox.StubOutWithMock(self.cinderclient.volumes, diff --git a/nova/volume/cinder.py b/nova/volume/cinder.py index 94775cb20d..4d965b22b0 100644 --- a/nova/volume/cinder.py +++ b/nova/volume/cinder.py @@ -28,12 +28,14 @@ from keystoneclient import exceptions as keystone_exception from keystoneclient import session from oslo_config import cfg from oslo_log import log as logging +from oslo_utils import excutils from oslo_utils import strutils import six from nova import availability_zones as az from nova import exception from nova.i18n import _ +from nova.i18n import _LE from nova.i18n import _LW cinder_opts = [ @@ -337,8 +339,32 @@ class API(object): @translate_volume_exception def initialize_connection(self, context, volume_id, connector): - return cinderclient(context).volumes.initialize_connection(volume_id, - connector) + try: + return cinderclient(context).volumes.initialize_connection( + volume_id, connector) + except cinder_exception.ClientException as ex: + with excutils.save_and_reraise_exception(): + LOG.error(_LE('Initialize connection failed for volume ' + '%(vol)s on host %(host)s. Error: %(msg)s ' + 'Code: %(code)s. Attempting to terminate ' + 'connection.'), + {'vol': volume_id, + 'host': connector.get('host'), + 'msg': six.text_type(ex), + 'code': ex.code}) + try: + self.terminate_connection(context, volume_id, connector) + except Exception as exc: + LOG.error(_LE('Connection between volume %(vol)s and host ' + '%(host)s might have succeeded, but attempt ' + 'to terminate connection has failed. ' + 'Validate the connection and determine if ' + 'manual cleanup is needed. Error: %(msg)s ' + 'Code: %(code)s.'), + {'vol': volume_id, + 'host': connector.get('host'), + 'msg': six.text_type(exc), + 'code': exc.code}) @translate_volume_exception def terminate_connection(self, context, volume_id, connector): |