Skip to content

Commit 7168314

Browse files
kajinamitmelwitt
authored andcommitted
Fix the wrong exception used to retry detach API calls
When cinderclient receives an error response from API, it raises one of the exceptions from the cinderclient.exceptions module instead of the cinderclient.apiclient.exceptions module. This change fixes the wrong exception used to detect 500 error from cinder API, so that API calls to detach volumes are properly retried. Closes-Bug: #1944043 Change-Id: I741cb6b29a67da8c60708c6251c441d778ca74d0 (cherry picked from commit f620626) (cherry picked from commit 513241a)
1 parent bae7b05 commit 7168314

File tree

2 files changed

+30
-22
lines changed

2 files changed

+30
-22
lines changed

nova/tests/unit/volume/test_cinder.py

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
# under the License.
1515

1616
from cinderclient import api_versions as cinder_api_versions
17-
from cinderclient import apiclient as cinder_apiclient
1817
from cinderclient import exceptions as cinder_exception
1918
from cinderclient.v2 import limits as cinder_limits
2019
from keystoneauth1 import loading as ks_loading
@@ -546,11 +545,12 @@ def test_attachment_delete_unsupported_api_version(self,
546545
mock_cinderclient.assert_called_once_with(self.ctx, '3.44',
547546
skip_version_check=True)
548547

549-
@mock.patch('nova.volume.cinder.cinderclient',
550-
side_effect=cinder_apiclient.exceptions.InternalServerError)
548+
@mock.patch('nova.volume.cinder.cinderclient')
551549
def test_attachment_delete_internal_server_error(self, mock_cinderclient):
550+
mock_cinderclient.return_value.attachments.delete.side_effect = (
551+
cinder_exception.ClientException(500))
552552

553-
self.assertRaises(cinder_apiclient.exceptions.InternalServerError,
553+
self.assertRaises(cinder_exception.ClientException,
554554
self.api.attachment_delete,
555555
self.ctx, uuids.attachment_id)
556556

@@ -561,16 +561,17 @@ def test_attachment_delete_internal_server_error_do_not_raise(
561561
self, mock_cinderclient):
562562
# generate exception, and then have a normal return on the next retry
563563
mock_cinderclient.return_value.attachments.delete.side_effect = [
564-
cinder_apiclient.exceptions.InternalServerError, None]
564+
cinder_exception.ClientException(500), None]
565565

566566
attachment_id = uuids.attachment
567567
self.api.attachment_delete(self.ctx, attachment_id)
568568

569569
self.assertEqual(2, mock_cinderclient.call_count)
570570

571-
@mock.patch('nova.volume.cinder.cinderclient',
572-
side_effect=cinder_exception.BadRequest(code=400))
571+
@mock.patch('nova.volume.cinder.cinderclient')
573572
def test_attachment_delete_bad_request_exception(self, mock_cinderclient):
573+
mock_cinderclient.return_value.attachments.delete.side_effect = (
574+
cinder_exception.BadRequest(400))
574575

575576
self.assertRaises(exception.InvalidInput,
576577
self.api.attachment_delete,
@@ -594,7 +595,7 @@ def test_attachment_complete(self, mock_cinderclient):
594595
@mock.patch('nova.volume.cinder.cinderclient')
595596
def test_attachment_complete_failed(self, mock_cinderclient):
596597
mock_cinderclient.return_value.attachments.complete.side_effect = (
597-
cinder_exception.NotFound(404, '404'))
598+
cinder_exception.NotFound(404))
598599

599600
attachment_id = uuids.attachment
600601
ex = self.assertRaises(exception.VolumeAttachmentNotFound,
@@ -667,27 +668,30 @@ def test_detach_no_attachment_id_multiattach(self, mock_cinderclient):
667668
mock_cinderclient.assert_called_with(self.ctx, microversion=None)
668669
mock_volumes.detach.assert_called_once_with('id1', 'fakeid')
669670

670-
@mock.patch('nova.volume.cinder.cinderclient',
671-
side_effect=cinder_apiclient.exceptions.InternalServerError)
671+
@mock.patch('nova.volume.cinder.cinderclient')
672672
def test_detach_internal_server_error(self, mock_cinderclient):
673+
mock_cinderclient.return_value.volumes.detach.side_effect = (
674+
cinder_exception.ClientException(500))
673675

674-
self.assertRaises(cinder_apiclient.exceptions.InternalServerError,
676+
self.assertRaises(cinder_exception.ClientException,
675677
self.api.detach,
676678
self.ctx, 'id1', instance_uuid='fake_uuid')
677679

678-
self.assertEqual(5, mock_cinderclient.call_count)
680+
self.assertEqual(
681+
5, mock_cinderclient.return_value.volumes.detach.call_count)
679682

680683
@mock.patch('nova.volume.cinder.cinderclient')
681684
def test_detach_internal_server_error_do_not_raise(
682685
self, mock_cinderclient):
683686
# generate exception, and then have a normal return on the next retry
684687
mock_cinderclient.return_value.volumes.detach.side_effect = [
685-
cinder_apiclient.exceptions.InternalServerError, None]
688+
cinder_exception.ClientException(500), None]
686689

687690
self.api.detach(self.ctx, 'id1', instance_uuid='fake_uuid',
688691
attachment_id='fakeid')
689692

690-
self.assertEqual(2, mock_cinderclient.call_count)
693+
self.assertEqual(
694+
2, mock_cinderclient.return_value.volumes.detach.call_count)
691695

692696
@mock.patch('nova.volume.cinder.cinderclient',
693697
side_effect=cinder_exception.BadRequest(code=400))
@@ -818,11 +822,13 @@ def test_terminate_connection(self, mock_cinderclient):
818822
mock_volumes.terminate_connection.assert_called_once_with('id1',
819823
'connector')
820824

821-
@mock.patch('nova.volume.cinder.cinderclient',
822-
side_effect=cinder_apiclient.exceptions.InternalServerError)
825+
@mock.patch('nova.volume.cinder.cinderclient')
823826
def test_terminate_connection_internal_server_error(
824827
self, mock_cinderclient):
825-
self.assertRaises(cinder_apiclient.exceptions.InternalServerError,
828+
mock_cinderclient.return_value.volumes.terminate_connection.\
829+
side_effect = cinder_exception.ClientException(500)
830+
831+
self.assertRaises(cinder_exception.ClientException,
826832
self.api.terminate_connection,
827833
self.ctx, 'id1', 'connector')
828834

@@ -833,7 +839,7 @@ def test_terminate_connection_internal_server_error_do_not_raise(
833839
self, mock_cinderclient):
834840
# generate exception, and then have a normal return on the next retry
835841
mock_cinderclient.return_value.volumes.terminate_connection.\
836-
side_effect = [cinder_apiclient.exceptions.InternalServerError,
842+
side_effect = [cinder_exception.ClientException(500),
837843
None]
838844

839845
self.api.terminate_connection(self.ctx, 'id1', 'connector')

nova/volume/cinder.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
import urllib
2626

2727
from cinderclient import api_versions as cinder_api_versions
28-
from cinderclient import apiclient as cinder_apiclient
2928
from cinderclient import client as cinder_client
3029
from cinderclient import exceptions as cinder_exception
3130
from keystoneauth1 import exceptions as keystone_exception
@@ -567,7 +566,8 @@ def attach(self, context, volume_id, instance_uuid, mountpoint, mode='rw'):
567566
@translate_volume_exception
568567
@retrying.retry(stop_max_attempt_number=5,
569568
retry_on_exception=lambda e:
570-
type(e) == cinder_apiclient.exceptions.InternalServerError)
569+
(isinstance(e, cinder_exception.ClientException) and
570+
e.code == 500))
571571
def detach(self, context, volume_id, instance_uuid=None,
572572
attachment_id=None):
573573
client = cinderclient(context)
@@ -632,7 +632,8 @@ def initialize_connection(self, context, volume_id, connector):
632632
@translate_volume_exception
633633
@retrying.retry(stop_max_attempt_number=5,
634634
retry_on_exception=lambda e:
635-
type(e) == cinder_apiclient.exceptions.InternalServerError)
635+
(isinstance(e, cinder_exception.ClientException) and
636+
e.code == 500))
636637
def terminate_connection(self, context, volume_id, connector):
637638
return cinderclient(context).volumes.terminate_connection(volume_id,
638639
connector)
@@ -881,7 +882,8 @@ def attachment_update(self, context, attachment_id, connector,
881882
@translate_attachment_exception
882883
@retrying.retry(stop_max_attempt_number=5,
883884
retry_on_exception=lambda e:
884-
type(e) == cinder_apiclient.exceptions.InternalServerError)
885+
(isinstance(e, cinder_exception.ClientException) and
886+
e.code == 500))
885887
def attachment_delete(self, context, attachment_id):
886888
try:
887889
cinderclient(

0 commit comments

Comments
 (0)