Skip to content

Commit d3f3dd8

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Retry attachment delete API call for 504 Gateway Timeout" into stable/xena
2 parents 457c39d + 14f9b76 commit d3f3dd8

File tree

3 files changed

+54
-11
lines changed

3 files changed

+54
-11
lines changed

nova/tests/unit/volume/test_cinder.py

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -520,16 +520,15 @@ def test_attachment_delete(self, mock_cinderclient):
520520
@mock.patch('nova.volume.cinder.cinderclient')
521521
def test_attachment_delete_failed(self, mock_cinderclient, mock_log):
522522
mock_cinderclient.return_value.attachments.delete.side_effect = (
523-
cinder_exception.NotFound(404, '404'))
523+
cinder_exception.BadRequest(400, '400'))
524524

525525
attachment_id = uuids.attachment
526-
ex = self.assertRaises(exception.VolumeAttachmentNotFound,
526+
ex = self.assertRaises(exception.InvalidInput,
527527
self.api.attachment_delete,
528528
self.ctx,
529529
attachment_id)
530530

531-
self.assertEqual(404, ex.code)
532-
self.assertIn(attachment_id, str(ex))
531+
self.assertEqual(400, ex.code)
533532

534533
@mock.patch('nova.volume.cinder.cinderclient',
535534
side_effect=exception.CinderAPIVersionNotAvailable(
@@ -545,6 +544,16 @@ def test_attachment_delete_unsupported_api_version(self,
545544
mock_cinderclient.assert_called_once_with(self.ctx, '3.44',
546545
skip_version_check=True)
547546

547+
@mock.patch('nova.volume.cinder.cinderclient')
548+
def test_attachment_delete_not_found(self, mock_cinderclient):
549+
mock_cinderclient.return_value.attachments.delete.side_effect = (
550+
cinder_exception.ClientException(404))
551+
552+
attachment_id = uuids.attachment
553+
self.api.attachment_delete(self.ctx, attachment_id)
554+
555+
self.assertEqual(1, mock_cinderclient.call_count)
556+
548557
@mock.patch('nova.volume.cinder.cinderclient')
549558
def test_attachment_delete_internal_server_error(self, mock_cinderclient):
550559
mock_cinderclient.return_value.attachments.delete.side_effect = (
@@ -568,6 +577,29 @@ def test_attachment_delete_internal_server_error_do_not_raise(
568577

569578
self.assertEqual(2, mock_cinderclient.call_count)
570579

580+
@mock.patch('nova.volume.cinder.cinderclient')
581+
def test_attachment_delete_gateway_timeout(self, mock_cinderclient):
582+
mock_cinderclient.return_value.attachments.delete.side_effect = (
583+
cinder_exception.ClientException(504))
584+
585+
self.assertRaises(cinder_exception.ClientException,
586+
self.api.attachment_delete,
587+
self.ctx, uuids.attachment_id)
588+
589+
self.assertEqual(5, mock_cinderclient.call_count)
590+
591+
@mock.patch('nova.volume.cinder.cinderclient')
592+
def test_attachment_delete_gateway_timeout_do_not_raise(
593+
self, mock_cinderclient):
594+
# generate exception, and then have a normal return on the next retry
595+
mock_cinderclient.return_value.attachments.delete.side_effect = [
596+
cinder_exception.ClientException(504), None]
597+
598+
attachment_id = uuids.attachment
599+
self.api.attachment_delete(self.ctx, attachment_id)
600+
601+
self.assertEqual(2, mock_cinderclient.call_count)
602+
571603
@mock.patch('nova.volume.cinder.cinderclient')
572604
def test_attachment_delete_bad_request_exception(self, mock_cinderclient):
573605
mock_cinderclient.return_value.attachments.delete.side_effect = (

nova/volume/cinder.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -883,19 +883,23 @@ def attachment_update(self, context, attachment_id, connector,
883883
@retrying.retry(stop_max_attempt_number=5,
884884
retry_on_exception=lambda e:
885885
(isinstance(e, cinder_exception.ClientException) and
886-
e.code == 500))
886+
e.code in (500, 504)))
887887
def attachment_delete(self, context, attachment_id):
888888
try:
889889
cinderclient(
890890
context, '3.44', skip_version_check=True).attachments.delete(
891891
attachment_id)
892892
except cinder_exception.ClientException as ex:
893-
with excutils.save_and_reraise_exception():
894-
LOG.error('Delete attachment failed for attachment '
895-
'%(id)s. Error: %(msg)s Code: %(code)s',
896-
{'id': attachment_id,
897-
'msg': str(ex),
898-
'code': getattr(ex, 'code', None)})
893+
if ex.code == 404:
894+
LOG.warning('Attachment %(id)s does not exist. Ignoring.',
895+
{'id': attachment_id})
896+
else:
897+
with excutils.save_and_reraise_exception():
898+
LOG.error('Delete attachment failed for attachment '
899+
'%(id)s. Error: %(msg)s Code: %(code)s',
900+
{'id': attachment_id,
901+
'msg': str(ex),
902+
'code': getattr(ex, 'code', None)})
899903

900904
@translate_attachment_exception
901905
def attachment_complete(self, context, attachment_id):
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
fixes:
3+
- |
4+
`Bug #1978444 <https://bugs.launchpad.net/nova/+bug/1978444>`_: Now nova
5+
retries deleting a volume attachment in case Cinder API returns
6+
``504 Gateway Timeout``. Also, ``404 Not Found`` is now ignored and
7+
leaves only a warning message.

0 commit comments

Comments
 (0)