6
6
7
7
from deepdiff import DeepDiff
8
8
from requests import HTTPError
9
- from tenacity import retry
10
- from tenacity .retry import retry_if_result
9
+ from tenacity import retry , wait_exponential
10
+ from tenacity .retry import retry_if_exception_type , retry_if_result
11
11
from tenacity .stop import stop_after_attempt , stop_after_delay
12
12
from tenacity .wait import wait_chain , wait_fixed
13
13
14
14
from cloudpub .common import BaseService
15
- from cloudpub .error import InvalidStateError , NotFoundError
15
+ from cloudpub .error import ConflictError , InvalidStateError , NotFoundError , RunningSubmissionError
16
16
from cloudpub .models .ms_azure import (
17
17
RESOURCE_MAPING ,
18
18
AzureResource ,
38
38
from cloudpub .ms_azure .session import PartnerPortalSession
39
39
from cloudpub .ms_azure .utils import (
40
40
AzurePublishingMetadata ,
41
+ check_for_conflict ,
42
+ check_for_running_submission ,
41
43
create_disk_version_from_scratch ,
42
44
is_azure_job_not_complete ,
43
45
is_sas_present ,
@@ -180,6 +182,10 @@ def _wait_for_job_completion(self, job_id: str) -> ConfigureStatus:
180
182
job_details = self ._query_job_details (job_id = job_id )
181
183
if job_details .job_result == "failed" :
182
184
error_message = f"Job { job_id } failed: \n { job_details .errors } "
185
+ if check_for_conflict (job_details ):
186
+ self ._raise_error (ConflictError , error_message )
187
+ elif check_for_running_submission (job_details ):
188
+ self ._raise_error (RunningSubmissionError , error_message )
183
189
self ._raise_error (InvalidStateError , error_message )
184
190
elif job_details .job_result == "succeeded" :
185
191
log .debug ("Job %s succeeded" , job_id )
@@ -558,7 +564,7 @@ def _publish_preview(self, product: Product, product_name: str) -> None:
558
564
if res .job_result != 'succeeded' or not self .get_submission_state (
559
565
product .id , state = "preview"
560
566
):
561
- errors = "\n " .join (res .errors )
567
+ errors = "\n " .join ([ "%s: %s" % ( error . code , error . message ) for error in res .errors ] )
562
568
failure_msg = (
563
569
f"Failed to submit the product { product .id } to preview. "
564
570
f"Status: { res .job_result } Errors: { errors } "
@@ -585,13 +591,19 @@ def _publish_live(self, product: Product, product_name: str) -> None:
585
591
res = self .submit_to_status (product_id = product .id , status = 'live' )
586
592
587
593
if res .job_result != 'succeeded' or not self .get_submission_state (product .id , state = "live" ):
588
- errors = "\n " .join (res .errors )
594
+ errors = "\n " .join ([ "%s: %s" % ( error . code , error . message ) for error in res .errors ] )
589
595
failure_msg = (
590
596
f"Failed to submit the product { product .id } to live. "
591
597
f"Status: { res .job_result } Errors: { errors } "
592
598
)
593
599
raise RuntimeError (failure_msg )
594
600
601
+ @retry (
602
+ retry = retry_if_exception_type ((ConflictError , RunningSubmissionError )),
603
+ wait = wait_exponential (multiplier = 1 , min = 60 , max = 60 * 60 * 24 * 7 ),
604
+ stop = stop_after_attempt (3 ),
605
+ reraise = True ,
606
+ )
595
607
def publish (self , metadata : AzurePublishingMetadata ) -> None :
596
608
"""
597
609
Associate a VM image with a given product listing (destination) and publish it if required.
0 commit comments