Using cloudbridge across zones
Currently, each instance of a cloudbridge provider is designated to work within a particular zone, for reasons clarified here: Make providers single zone.
To perform cross-zonal operations, we recommend cloning the provider into a different zone as in this example:
all_instances =  for zone in provider.compute.regions.current.zones: new_provider = provider.clone(zone=zone) all_instances.append(list(new_provider.compute.instances)) print(all_instances)
Cleaning up resources/left over resources
The trickiest part about using cloud resources is the orderly cleanup of resources when they are no longer needed. Cleanup is often complicated, as cloud-providers may have delays in responding at certain times, and transient errors at other times. While cloudbridge does not designate a particular strategy to combat this, the controller pattern is a recommended mechanism for handling such scenarios:
Cloudbridge provides some utilities that can aid in simpler scenarios, such as wait_for, the cleanup helper and retries.
The following example demonstrates a scenario where an instance and its attached volume must be deleted.
from cloudbridge.base import helpers as cb_helpers import tenacity def does_instance_or_volume_still_exist(inst, vol): return provider.compute.instances.get(inst.id) or provider.storage.volumes.get(vol.id) def detach_and_delete(inst, vol) with cb_helpers.cleanup_action(lambda: inst.delete()): vol.detach() vol.wait_for( [VolumeState.AVAILABLE], terminal_states=[VolumeState.ERROR, VolumeState.DELETED]) vol.delete() self.wait_for([VolumeState.UNKNOWN, VolumeState.ERROR]) def delete_my_instance_and_attached_volume(provider, instance, vol): retryer = tenacity.Retrying( stop=tenacity.stop_after_delay(300), retry=tenacity.retry_if_result(does_instance_or_volume_still_exist(instance, vol), wait=tenacity.wait_fixed(5)) retryer(detach_and_delete, instance, vol) # invoke with the instance and vol you want to delete delete_my_instance_and_attached_volume(my_inst, my_vol)
The code above attempts to first detach and then delete the volume. If an exception occurs, such as the volume not existing, the cleanup_action code ensures that the inst.delete() code runs regardless of the success or failure of the volume deletion operation. The tenacity.retryer wraps the entire operation so that the overall process will repeat till both the volume nor the instance no longer exist.