def run_circuit_breaker(): # Name of image to use for testing. image_to_upload = "HelloWorld.png" global blob_client global container_name try: # Create a reference to the blob client and container using the storage account name and key blob_client = BlockBlobService(account_name, account_key) # Make the container unique by using a UUID in the name. container_name = "democontainer" + str(uuid.uuid4()) blob_client.create_container(container_name) except Exception as ex: print("Please make sure you have put the correct storage account name and key.") print(ex) # Define a reference to the actual blob and upload the block_blob to the newly created container full_path_to_file = os.path.join(os.path.dirname(__file__), image_to_upload) blob_client.create_blob_from_path(container_name, image_to_upload, full_path_to_file) # Set the location mode to secondary, so you can check just the secondary data center. blob_client.location_mode = LocationMode.SECONDARY blob_client.retry = LinearRetry(backoff=0).retry # Before proceeding, wait until the blob has been replicated to the secondary data center. # Loop and check for the presence of the blob once in a second until it hits 60 seconds # or until it finds it counter = 0 while counter < 60: counter += 1 sys.stdout.write("\nAttempt {0} to see if the blob has replicated to the secondary storage yet.".format(counter)) sys.stdout.flush() if blob_client.exists(container_name, image_to_upload): break # Wait a second, then loop around and try again # When it's finished replicating to the secondary, continue. time.sleep(1) # Set the starting LocationMode to Primary, then Secondary. # Here we use the linear retry by default, but allow it to retry to secondary if # the initial request to primary fails. # Note that the default is Primary. You must have RA-GRS enabled to use this blob_client.location_mode = LocationMode.PRIMARY blob_client.retry = LinearRetry(max_attempts=retry_threshold, backoff=1).retry ''' ************INSTRUCTIONS**************k To perform the test, first replace the 'accountname' and 'accountkey' with your storage account name and key. Every time it calls get_blob_to_path it will hit the response_callback function. Next, run this app. While this loop is running, pause the program by pressing any key, and put the intercept code in Fiddler (that will intercept and return a 503). For instructions on modifying Fiddler, look at the Fiddler_script.text file in this project. There are also full instructions in the ReadMe_Instructions.txt file included in this project. After adding the custom script to Fiddler, calls to primary storage will fail with a retryable error which will trigger the Retrying event (above). Then it will switch over and read the secondary. It will do that 20 times, then try to switch back to the primary. After seeing that happen, pause this again and remove the intercepting Fiddler code Then you'll see it return to the primary and finish. ''' print("\n\nThe application will pause at 200 unit interval") for i in range(0, 1000): if blob_client.location_mode == LocationMode.SECONDARY: sys.stdout.write("S{0} ".format(str(i))) else: sys.stdout.write("P{0} ".format(str(i))) sys.stdout.flush() try: # These function is called immediately after retry evaluation is performed. # It is used to trigger the change from primary to secondary and back blob_client.retry_callback = retry_callback # Download the file blob_client.get_blob_to_path(container_name, image_to_upload, str.replace(full_path_to_file, ".png", "Copy.png")) # Set the application to pause at 200 unit intervals to implement simulated failures if i == 200 or i == 400 or i == 600 or i == 800: sys.stdout.write("\nPress the Enter key to resume") sys.stdout.flush() if sys.version_info[0] < 3: raw_input() else: input() except Exception as ex: print(ex) finally: # Force an exists call to succeed by resetting the status blob_client.response_callback = response_callback # Clean up resources blob_client.delete_container(container_name)