summaryrefslogtreecommitdiff
path: root/nova
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2016-03-17 06:18:25 +0000
committerGerrit Code Review <review@openstack.org>2016-03-17 06:18:26 +0000
commit9606ab3e033eb56c6613446c31a3387bb725e24f (patch)
tree3be8a469be50104cd1e199e0707f8848fe0e489c /nova
parentc3210f4c04580d8c64a8280d8095b04c157cf739 (diff)
parentc3d5cf8e76efe73f1630a916e0925672703c1754 (diff)
downloadnova-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.py30
-rw-r--r--nova/volume/cinder.py30
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):