diff --git a/storops/unity/resource/host.py b/storops/unity/resource/host.py index 0903e11d..9f1d60f1 100644 --- a/storops/unity/resource/host.py +++ b/storops/unity/resource/host.py @@ -236,6 +236,8 @@ def _random_hlu_number(self): max=MAX_HLU_NUMBER)) @version('<4.4.0') # noqa + @retry(limit=6, wait=5, + on_error=ex.UnityLunModifyByAnotherRequestException) @retry(limit=5, on_error=ex.UnityHluNumberInUseError) def _attach_with_retry(self, lun_or_snap, skip_hlu_0): # Before 4.4.0 (Osprey), it didn't support to pass in hlu when @@ -251,6 +253,8 @@ def _attach_with_retry(self, lun_or_snap, skip_hlu_0): return host_lun.hlu @version('>=4.4.0') # noqa + @retry(limit=6, wait=5, + on_error=ex.UnityLunModifyByAnotherRequestException) @retry(limit=5, on_error=ex.UnityHluNumberInUseError) def _attach_with_retry(self, lun_or_snap, skip_hlu_0): # From 4.4.0 (Osprey), it supported to pass in hlu when attaching LUN, diff --git a/storops_test/unity/resource/test_host.py b/storops_test/unity/resource/test_host.py index 95dcbb6e..eaabf8cf 100644 --- a/storops_test/unity/resource/test_host.py +++ b/storops_test/unity/resource/test_host.py @@ -15,12 +15,13 @@ # under the License. from __future__ import unicode_literals +import time from unittest import TestCase import ddt import mock from hamcrest import equal_to, assert_that, instance_of, raises, none, \ - only_contains, not_none, is_not, calling + only_contains, not_none, is_not, calling, greater_than from storops.exception import UnityHostIpInUseError, \ UnityResourceNotFoundError, UnityHostInitiatorNotFoundError, \ @@ -376,7 +377,12 @@ def test_detach_with_retry_lun_modified_by_another_request(self): def f(): host.detach(lun) + start = time.time() assert_that(f, raises(UnityLunModifyByAnotherRequestException)) + end = time.time() + # _detach_with_retry retry 20 times with 5s interval, it will take + # at least (20 - 1) * 5 = 95s to finish the retries. + assert_that(end - start, greater_than(95)) @patch_rest def test_attach_attached_hlu(self): @@ -495,6 +501,24 @@ def test_attach_with_retry_hlu_in_use(self): assert_that(calling(host._attach_with_retry).with_args(lun, True), raises(UnityHluNumberInUseError)) + @patch_rest + def test_attach_with_retry_lun_modify_by_another_request(self): + host = UnityHost(cli=t_rest(), _id='Host_23') + lun = UnityLun(_id='sv_5610', cli=t_rest()) + lun.is_cg_member = False + mock_lun_modifying = mock.Mock( + side_effect=UnityLunModifyByAnotherRequestException) + with mock.patch('storops.unity.resource.host.UnityHost.' + '_modify_hlu', + new=mock_lun_modifying): + start = time.time() + assert_that(calling(host._attach_with_retry).with_args(lun, True), + raises(UnityLunModifyByAnotherRequestException)) + end = time.time() + # _attach_with_retry retry 6 times with 5s interval, it will take + # at least (6 - 1) * 5 = 25s to finish the retries. + assert_that(end - start, greater_than(25)) + @patch_rest def test_attach_with_retry_hlu_in_use_but_no_retry(self): host = UnityHost(cli=t_rest(), _id='Host_24')