def wait_for_no_anf_resource(client, resourceId, intervalInSec=10, retries=60): for i in range(0, retries): time.sleep(intervalInSec) try: if resource_uri_utils.is_anf_snapshot(resourceId): client.snapshots.get( resource_uri_utils.get_resource_group(resourceId), resource_uri_utils.get_anf_account(resourceId), resource_uri_utils.get_anf_capacity_pool(resourceId), resource_uri_utils.get_anf_volume(resourceId), resource_uri_utils.get_anf_snapshot(resourceId) ) elif resource_uri_utils.is_anf_volume(resourceId): client.volumes.get( resource_uri_utils.get_resource_group(resourceId), resource_uri_utils.get_anf_account(resourceId), resource_uri_utils.get_anf_capacity_pool(resourceId), resource_uri_utils.get_anf_volume(resourceId) ) elif resource_uri_utils.is_anf_capacity_pool(resourceId): client.pools.get( resource_uri_utils.get_resource_group(resourceId), resource_uri_utils.get_anf_account(resourceId), resource_uri_utils.get_anf_capacity_pool(resourceId) ) elif resource_uri_utils.is_anf_account(resourceId): client.accounts.get( resource_uri_utils.get_resource_group(resourceId), resource_uri_utils.get_anf_account(resourceId) ) except CloudError as ex: break
def wait_for_anf_resource(client, resource_id, interval_in_sec=10, retries=60, replication=None): """Waits for specific anf resource start existing This function checks if a specific ANF resource that was recently created is already being able to be polled. It breaks the wait if resource is found or if polling reached out maximum retries. Args: client (NetAppManagementClient): Azure Resource Provider Client designed to interact with ANF resources resource_id (string): Resource Id of the resource to be checked upon interval_in_sec (int): Interval used between checks retires (int): Number of times a poll will be performed """ for i in range(0, retries): time.sleep(interval_in_sec) try: if resource_uri_utils.is_anf_snapshot(resource_id): client.snapshots.get( resource_uri_utils.get_resource_group(resource_id), resource_uri_utils.get_anf_account(resource_id), resource_uri_utils.get_anf_capacity_pool(resource_id), resource_uri_utils.get_anf_volume(resource_id), resource_uri_utils.get_anf_snapshot(resource_id)) elif resource_uri_utils.is_anf_volume(resource_id): volume = client.volumes.get( resource_uri_utils.get_resource_group(resource_id), resource_uri_utils.get_anf_account(resource_id), resource_uri_utils.get_anf_capacity_pool(resource_id), resource_uri_utils.get_anf_volume(resource_id)) if replication == True: if volume.data_protection == None: continue elif resource_uri_utils.is_anf_capacity_pool(resource_id): client.pools.get( resource_uri_utils.get_resource_group(resource_id), resource_uri_utils.get_anf_account(resource_id), resource_uri_utils.get_anf_capacity_pool(resource_id)) elif resource_uri_utils.is_anf_account(resource_id): client.accounts.get( resource_uri_utils.get_resource_group(resource_id), resource_uri_utils.get_anf_account(resource_id)) break except ResourceNotFoundError as ex: pass
def wait_for_no_anf_resource(client, resource_id, interval_in_sec=10, retries=60): """Waits for specific anf resource don't exist This function checks if a specific ANF resource that was recently delete stops existing. It breaks the wait if resource is not found anymore or if polling reached out maximum retries. Args: client (AzureNetAppFilesManagementClient): Azure Resource Provider Client designed to interact with ANF resources resource_id (string): Resource Id of the resource to be checked upon interval_in_sec (int): Interval used between checks retires (int): Number of times a poll will be performed """ for i in range(0, retries): time.sleep(interval_in_sec) try: if resource_uri_utils.is_anf_snapshot(resource_id): client.snapshots.get( resource_uri_utils.get_resource_group(resource_id), resource_uri_utils.get_anf_account(resource_id), resource_uri_utils.get_anf_capacity_pool(resource_id), resource_uri_utils.get_anf_volume(resource_id), resource_uri_utils.get_anf_snapshot(resource_id) ) elif resource_uri_utils.is_anf_volume(resource_id): client.volumes.get( resource_uri_utils.get_resource_group(resource_id), resource_uri_utils.get_anf_account(resource_id), resource_uri_utils.get_anf_capacity_pool(resource_id), resource_uri_utils.get_anf_volume(resource_id) ) elif resource_uri_utils.is_anf_capacity_pool(resource_id): client.pools.get( resource_uri_utils.get_resource_group(resource_id), resource_uri_utils.get_anf_account(resource_id), resource_uri_utils.get_anf_capacity_pool(resource_id) ) elif resource_uri_utils.is_anf_account(resource_id): client.accounts.get( resource_uri_utils.get_resource_group(resource_id), resource_uri_utils.get_anf_account(resource_id) ) except CloudError as ex: break
def run_example(): """Azure NetApp Files SDK management example.""" print_header("Azure NetAppFiles Python SDK Sample - Sample " "project that creates an NFS v4.1 volume with Azure NetApp " " Files SDK with Python") # Creating the Azure NetApp Files Client with an Application # (service principal) token provider credentials, subscription_id = sample_utils.get_credentials() anf_client = NetAppManagementClient(credentials, subscription_id) # Checking if vnet/subnet information leads to a valid resource resources_client = ResourceManagementClient(credentials, subscription_id) subnet_id = ('/subscriptions/{}' '/resourceGroups/{}' '/providers/Microsoft.Network/virtualNetworks/{}' '/subnets/{}').format(subscription_id, VNET_RESOURCE_GROUP_NAME, VNET_NAME, SUBNET_NAME) result = resource_exists(resources_client, subnet_id, VIRTUAL_NETWORKS_SUBNET_API_VERSION) if not result: console_output( "ERROR: Subnet not with id {} not found".format(subnet_id)) raise Exception( "Subnet not found error. Subnet Id {}".format(subnet_id)) # Creating an Azure NetApp Account console_output('Creating Azure NetApp Files account ...') account = None try: account = create_account(anf_client, RESOURCE_GROUP_NAME, ANF_ACCOUNT_NAME, LOCATION) console_output( '\tAccount successfully created, resource id: {}'.format( account.id)) except AzureError as ex: console_output('An error ocurred. Error details: {}'.format( ex.message)) raise # Creating a Capacity Pool console_output('Creating Capacity Pool ...') capacity_pool = None try: capacity_pool = create_capacitypool_async( anf_client, RESOURCE_GROUP_NAME, account.name, CAPACITYPOOL_NAME, CAPACITYPOOL_SERVICE_LEVEL, CAPACITYPOOL_SIZE, LOCATION) console_output( '\tCapacity Pool successfully created, resource id: {}'.format( capacity_pool.id)) except AzureError as ex: console_output('An error ocurred. Error details: {}'.format( ex.message)) raise # Creating a Volume # Note: With exception of Accounts, all resources with Name property # returns a relative path up to the name and to use this property in # other methods, like Get for example, the argument needs to be # sanitized and just the actual name needs to be used (the hierarchy # needs to be cleaned up in the name). # Capacity Pool Name property example: "pmarques-anf01/pool01" # "pool01" is the actual name that needs to be used instead. Below # you will see a sample function that parses the name from its # resource id: resource_uri_utils.get_anf_capacity_pool() console_output('Creating a Volume ...') subnet_id = ('/subscriptions/{}' '/resourceGroups/{}' '/providers/Microsoft.Network/virtualNetworks/{}' '/subnets/{}').format(subscription_id, VNET_RESOURCE_GROUP_NAME, VNET_NAME, SUBNET_NAME) volume = None try: pool_name = resource_uri_utils.get_anf_capacity_pool(capacity_pool.id) volume = create_volume(anf_client, RESOURCE_GROUP_NAME, account.name, pool_name, VOLUME_NAME, VOLUME_USAGE_QUOTA, CAPACITYPOOL_SERVICE_LEVEL, subnet_id, LOCATION) # ARM Workaround to wait for the creation completion sample_utils.wait_for_anf_resource(anf_client, volume.id) console_output('\tVolume successfully created, resource id: {}'.format( volume.id)) except AzureError as ex: console_output('An error ocurred. Error details: {}'.format( ex.message)) raise # Cleaning up volumes - for this to happen, please change the value of # SHOULD_CLEANUP variable to true. # Note: Volume deletion operations at the RP level are executed serially if SHOULD_CLEANUP: # Cleaning up. This process needs to start the cleanup from the # innermost resources down in the hierarchy chain in our case # Snapshots->Volumes->Capacity Pools->Accounts console_output('Cleaning up...') console_output("\tDeleting Volumes...") try: volume_ids = [volume.id] for volume_id in volume_ids: console_output("\t\tDeleting {}".format(volume_id)) anf_client.volumes.begin_delete( RESOURCE_GROUP_NAME, account.name, resource_uri_utils.get_anf_capacity_pool(capacity_pool.id), resource_uri_utils.get_anf_volume(volume_id)).wait() # ARM Workaround to wait the deletion complete/propagate sample_utils.wait_for_no_anf_resource(anf_client, volume_id) console_output('\t\tDeleted Volume: {}'.format(volume_id)) except AzureError as ex: console_output('An error ocurred. Error details: {}'.format( ex.message)) raise # Cleaning up Capacity Pool console_output("\tDeleting Capacity Pool {} ...".format( resource_uri_utils.get_anf_capacity_pool(capacity_pool.id))) try: anf_client.pools.begin_delete( RESOURCE_GROUP_NAME, account.name, resource_uri_utils.get_anf_capacity_pool( capacity_pool.id)).wait() # ARM Workaround to wait the deletion complete/propagate sample_utils.wait_for_no_anf_resource(anf_client, capacity_pool.id) console_output('\t\tDeleted Capacity Pool: {}'.format( capacity_pool.id)) except AzureError as ex: console_output('An error ocurred. Error details: {}'.format( ex.message)) raise # Cleaning up Account console_output("\tDeleting Account {} ...".format(account.name)) try: anf_client.accounts.begin_delete(RESOURCE_GROUP_NAME, account.name) console_output('\t\tDeleted Account: {}'.format(account.id)) except AzureError as ex: console_output('An error ocurred. Error details: {}'.format( ex.message)) raise
def run_example(): """Azure NetApp Files SDK management example.""" print("Azure NetAppFiles Python SDK Sample") print("Sample project that performs CRUD management operations with Azure NetApp Files SDK with Python") print("-----------------------------------------------------------------------------------------------") # Creating the Azure NetApp Files Client with an Application # (service principal) token provider credentials, subscription_id = sample_utils.get_credentials() anf_client = AzureNetAppFilesManagementClient( credentials, subscription_id) # Creating an Azure NetApp Account console_output('Creating Azure NetApp Files account ...') account = None try: account = create_account( anf_client, RESOURCE_GROUP_NAME, ANF_ACCOUNT_NAME, LOCATION) console_output( '\tAccount successfully created, resource id: {}'.format( account.id)) except CloudError as ex: console_output( 'An error ocurred. Error details: {}'.format(ex.message)) raise # Creating a Capacity Pool console_output('Creating Capacity Pool ...') capacity_pool = None try: capacity_pool = create_capacitypool_async( anf_client, RESOURCE_GROUP_NAME, account.name, CAPACITYPOOL_NAME, CAPACITYPOOL_SERVICE_LEVEL, CAPACITYPOOL_SIZE, LOCATION) console_output('\tCapacity Pool successfully created, resource id: {}' .format(capacity_pool.id)) except CloudError as ex: console_output( 'An error ocurred. Error details: {}'.format(ex.message)) raise # Creating a Volume # # Note: With exception of Accounts, all resources with Name property # returns a relative path up to the name and to use this property in # other methods, like Get for example, the argument needs to be # sanitized and just the actual name needs to be used (the hierarchy # needs to be cleaned up in the name). # Capacity Pool Name property example: "pmarques-anf01/pool01" # "pool01" is the actual name that needs to be used instead. Below you # will see a sample function that parses the name from its # resource id: resource_uri_utils.get_anf_capacity_pool() console_output('Creating a Volume ...') subnet_id = '/subscriptions/{}/resourceGroups/{}/providers/Microsoft.Network/virtualNetworks/{}/subnets/{}'\ .format(subscription_id, VNET_RESOURCE_GROUP_NAME, VNET_NAME, SUBNET_NAME) volume = None try: pool_name = resource_uri_utils.get_anf_capacity_pool(capacity_pool.id) volume = create_volume(anf_client, RESOURCE_GROUP_NAME, account.name, pool_name, VOLUME_NAME, VOLUME_USAGE_QUOTA, CAPACITYPOOL_SERVICE_LEVEL, subnet_id, LOCATION) console_output('\tVolume successfully created, resource id: {}' .format(volume.id)) except CloudError as ex: console_output( 'An error ocurred. Error details: {}'.format(ex.message)) raise # Creating a snapshot console_output('Creating a Snapshot ...') snapshot = None try: volume_name = resource_uri_utils.get_anf_volume(volume.id) snapshot = create_snapshot(anf_client, RESOURCE_GROUP_NAME, account.name, pool_name, VOLUME_NAME, SNAPSHOT_NAME, LOCATION) sample_utils.wait_for_anf_resource(anf_client, snapshot.id) console_output( '\tSnapshot successfully created, resource id: {}' .format(snapshot.id)) except CloudError as ex: console_output( 'An error ocurred. Error details: {}'.format(ex.message)) raise # Creating a new volume from snapshot # # Note: SnapshotId is not the actual resource Id of the snapshot, this # value is the unique identifier (guid) of the snapshot, represented # by the SnapshotId instead. console_output('Creating New Volume from Snapshot ...') volume_from_snapshot = None try: new_volume_name = "Vol-{}".format( resource_uri_utils.get_anf_snapshot(snapshot.id)) volume_from_snapshot = create_volume_from_snapshot(anf_client, RESOURCE_GROUP_NAME, account.name, pool_name, volume, snapshot.snapshot_id, new_volume_name) console_output('\tNew volume from snapshot successfully created, resource id: {}'.format( volume_from_snapshot.id)) except CloudError as ex: console_output( 'An error ocurred. Error details: {}'.format(ex.message)) raise # Updating a Capacity Pool console_output('Performing updates on Capacity Pool and Volume...') new_capacity_pool_size_tib = 10 console_output('\tChanging Capacity Pools size from {}TiB to {}TiB'.format( sample_utils.get_bytes_in_tib(capacity_pool.size), new_capacity_pool_size_tib)) try: capacity_pool_patch = CapacityPoolPatch(location=capacity_pool.location, service_level=capacity_pool.service_level, size=sample_utils.get_tib_in_bytes(new_capacity_pool_size_tib)) capacity_pool = anf_client.pools.update(capacity_pool_patch, RESOURCE_GROUP_NAME, account.name, resource_uri_utils.get_anf_capacity_pool(capacity_pool.id)) console_output('\t\tCapacity Pool successfully updated, new size {}TiB, resource id: {}'.format( sample_utils.get_bytes_in_tib(capacity_pool.size), capacity_pool.id)) except CloudError as ex: console_output( 'An error ocurred. Error details: {}'.format(ex.message)) raise # Volume updates: resize and adding a new export policy new_volume_size_tib = 1 console_output('\tChanging volume size from {}TiB to {}TiB'.format( sample_utils.get_bytes_in_tib(volume.usage_threshold), new_volume_size_tib)) # Getting list of export policies and adding a new one at the end rule_list = sorted(volume.export_policy.rules, key=lambda r: r.rule_index, reverse=True) # Currently, ANF's volume export policy supports up to 5 rules export_policies_patch = None if len(rule_list) <= 4: rule_list.append(ExportPolicyRule( allowed_clients="10.0.0.4/32", cifs=False, nfsv3=True, nfsv41=False, rule_index=rule_list[0].rule_index + 1, unix_read_only=False, unix_read_write=True)) export_policies_patch = VolumePatchPropertiesExportPolicy( rules=rule_list) if export_policies_patch is None: volume_patch = VolumePatch( location=volume.location, service_level=volume.service_level, usage_threshold=sample_utils.get_tib_in_bytes(new_volume_size_tib)) else: volume_patch = VolumePatch( location=volume.location, service_level=volume.service_level, usage_threshold=sample_utils.get_tib_in_bytes(new_volume_size_tib), export_policy=export_policies_patch) try: updated_volume = anf_client.volumes.update(volume_patch, RESOURCE_GROUP_NAME, account.name, resource_uri_utils.get_anf_capacity_pool( capacity_pool.id), resource_uri_utils.get_anf_volume(volume.id)) console_output('\t\tVolume successfully updated, new size: {}TiB, export policy count: {}, resource id: {}' .format(sample_utils.get_bytes_in_tib(updated_volume.usage_threshold), len(updated_volume.export_policy.rules), updated_volume.id)) except CloudError as ex: console_output( 'An error ocurred. Error details: {}'.format(ex.message)) raise # Retrieving resources console_output('Performing retrieval operations ...') # Accounts # Getting a list of ANF Accounts console_output('\tListing accounts...') account_list = None try: account_list = list(anf_client.accounts.list(RESOURCE_GROUP_NAME)) for i, retrieved_account in enumerate(account_list): console_output('\t\t{} - Account Name: {}, Id: {}' .format(i, retrieved_account.name, retrieved_account.id)) except CloudError as ex: console_output( 'An error ocurred. Error details: {}'.format(ex.message)) raise # Getting a single ANF Account console_output('\tGetting a single account...') try: retrieved_account = anf_client.accounts.get( RESOURCE_GROUP_NAME, account.name) console_output('\t\tAccount Name: {}, Id: {}'.format( retrieved_account.name, retrieved_account.id)) except CloudError as ex: console_output( 'An error ocurred. Error details: {}'.format(ex.message)) raise # Capacity Pools # Getting a list of capacity pools from an account console_output('\tListing capacity pools from account {}...' .format(account.name)) capacitypool_list = None try: capacitypool_list = list(anf_client.pools.list(RESOURCE_GROUP_NAME, resource_uri_utils.get_anf_account(account.id))) for i, retrieved_pool in enumerate(capacitypool_list): console_output('\t\t{} - Capacity Pool Name: {}, Id: {}' .format(i, retrieved_pool.name, retrieved_pool.id)) except CloudError as ex: console_output( 'An error ocurred. Error details: {}'.format(ex.message)) raise # Getting a single capacity pool console_output('\tGetting a single capacity pool...') try: retrieved_pool = anf_client.pools.get(RESOURCE_GROUP_NAME, resource_uri_utils.get_anf_account( account.id), resource_uri_utils.get_anf_capacity_pool(capacity_pool.id)) console_output('\t\tCapacity Pool Name: {}, Id: {}'.format( retrieved_pool.name, retrieved_pool.id)) except CloudError as ex: console_output( 'An error ocurred. Error details: {}'.format(ex.message)) raise # Volumes # Getting a list of volumes from a capacity pool console_output('\tListing volumes from capacity pool {}...'.format( capacity_pool.name)) volume_list = None try: volume_list = list(anf_client.volumes.list(RESOURCE_GROUP_NAME, resource_uri_utils.get_anf_account( account.id), resource_uri_utils.get_anf_capacity_pool(capacity_pool.id))) for i, retrieved_volume in enumerate(volume_list): console_output('\t\t{} - Volume Name: {}, Id: {}' .format(i, retrieved_volume.name, retrieved_volume.id)) except CloudError as ex: console_output( 'An error ocurred. Error details: {}'.format(ex.message)) raise # Getting a single volume console_output('\tGetting a single volume...') try: retrieved_volume = anf_client.volumes.get(RESOURCE_GROUP_NAME, resource_uri_utils.get_anf_account( account.id), resource_uri_utils.get_anf_capacity_pool( capacity_pool.id), resource_uri_utils.get_anf_volume(volume.id)) console_output('\t\tVolume Name: {}, Id: {}'.format( retrieved_volume.name, retrieved_volume.id)) except CloudError as ex: console_output( 'An error ocurred. Error details: {}'.format(ex.message)) raise # Snapshots # Getting a list of snapshots from volume console_output( '\tListing snapshots from from volume {}...'.format(volume.name)) snapshot_list = None try: snapshot_list = list(anf_client.snapshots.list(RESOURCE_GROUP_NAME, resource_uri_utils.get_anf_account( account.id), resource_uri_utils.get_anf_capacity_pool( capacity_pool.id), resource_uri_utils.get_anf_volume(volume.id))) for i, retrieved_snapshot in enumerate(snapshot_list): console_output('\t\t{} - Snapshot Name: {}, Id: {}' .format(i, retrieved_snapshot.name, retrieved_snapshot.id)) except CloudError as ex: console_output( 'An error ocurred. Error details: {}'.format(ex.message)) raise # Getting a single snapshot console_output('\tGetting a single snapshot...') try: retrieved_snapshot = anf_client.snapshots.get(RESOURCE_GROUP_NAME, resource_uri_utils.get_anf_account( account.id), resource_uri_utils.get_anf_capacity_pool( capacity_pool.id), resource_uri_utils.get_anf_volume( volume.id), resource_uri_utils.get_anf_snapshot(snapshot.id)) console_output('\t\tSnapshot Name: {}, Id: {}'.format( retrieved_snapshot.name, retrieved_snapshot.id)) except CloudError as ex: console_output( 'An error ocurred. Error details: {}'.format(ex.message)) raise # Cleaning up. This process needs to start the cleanup from the innermost # resources down in the hierarchy chain in our case # Snapshots->Volumes->Capacity Pools->Accounts if SHOULD_CLEANUP: console_output('Cleaning up...') # Cleaning up snapshot console_output( "\tWaiting for 1 minute to let the snapshot used to create a new \ volume to complete the split operation therefore not being locked...") time.sleep(60) console_output("\tDeleting Snapshot {}...".format( resource_uri_utils.get_anf_snapshot(snapshot.id))) try: anf_client.snapshots.delete(RESOURCE_GROUP_NAME, account.name, resource_uri_utils.get_anf_capacity_pool( capacity_pool.id), resource_uri_utils.get_anf_volume( volume.id), resource_uri_utils.get_anf_snapshot(snapshot.id)).wait() # ARM Workaround to wait the deletion complete/propagate sample_utils.wait_for_no_anf_resource(anf_client, snapshot.id) console_output('\t\tDeleted Snapshot: {}'.format(snapshot.id)) except CloudError as ex: console_output( 'An error ocurred. Error details: {}'.format(ex.message)) raise # Cleaning up volumes # Note: Volume deletion operations at the RP level are executed # serially console_output("\tDeleting Volumes...") try: volume_ids = [volume.id, volume_from_snapshot.id] for volume_id in volume_ids: console_output("\t\tDeleting {}".format(volume_id)) anf_client.volumes.delete(RESOURCE_GROUP_NAME, account.name, resource_uri_utils.get_anf_capacity_pool( capacity_pool.id), resource_uri_utils.get_anf_volume(volume_id)).wait() sample_utils.wait_for_no_anf_resource(anf_client, volume_id) console_output('\t\tDeleted Volume: {}'.format(volume_id)) except CloudError as ex: console_output( 'An error ocurred. Error details: {}'.format(ex.message)) raise # Cleaning up Capacity Pool console_output("\tDeleting Capacity Pool {} ...".format( resource_uri_utils.get_anf_capacity_pool(capacity_pool.id))) try: anf_client.pools.delete(RESOURCE_GROUP_NAME, account.name, resource_uri_utils.get_anf_capacity_pool( capacity_pool.id)).wait() sample_utils.wait_for_no_anf_resource(anf_client, capacity_pool.id) console_output( '\t\tDeleted Capacity Pool: {}'.format(capacity_pool.id)) except CloudError as ex: console_output( 'An error ocurred. Error details: {}'.format(ex.message)) raise # Cleaning up Account console_output("\tDeleting Account {} ...".format(account.name)) try: anf_client.accounts.delete(RESOURCE_GROUP_NAME, account.name) sample_utils.wait_for_no_anf_resource(anf_client, account.id) console_output('\t\tDeleted Account: {}'.format(account.id)) except CloudError as ex: console_output( 'An error ocurred. Error details: {}'.format(ex.message)) raise
def run_example(): """Azure NetApp Files SDK management example.""" print_header("Azure NetAppFiles Python SDK Sample - Sample " "project that creates a SMB Volume with Azure NetApp " "Files SDK with Python") # Getting Active Directory Identity's password domain_join_user_password = getpass( ("Please type Active Directory's user password that will " "domain join ANF's SMB server and press [ENTER]:")) if len(domain_join_user_password) == 0: console_output('An error ocurred. Password cannot be empty string') raise Exception('Password cannot be empty string') # Creating the Azure NetApp Files Client with an Application # (service principal) token provider credentials, subscription_id = sample_utils.get_credentials() anf_client = AzureNetAppFilesManagementClient(credentials, subscription_id) # Checking if vnet/subnet information leads to a valid resource resources_client = ResourceManagementClient(credentials, subscription_id) SUBNET_ID = '/subscriptions/{}/resourceGroups/{}/providers/Microsoft.Network/virtualNetworks/{}/subnets/{}'.format( subscription_id, VNET_RESOURCE_GROUP_NAME, VNET_NAME, SUBNET_NAME) result = resource_exists(resources_client, SUBNET_ID, VIRTUAL_NETWORKS_SUBNET_API_VERSION) if not result: console_output( "ERROR: Subnet not with id {} not found".format(SUBNET_ID)) raise Exception( "Subnet not found error. Subnet Id {}".format(SUBNET_ID)) # Creating an Azure NetApp Account ''' Building the ActiveDirectories object to be passed down to create_account() function. Notice that this is a list but only one active directory configuration is supported per subscription and region at the time this sample was first published ''' active_directories = [ ActiveDirectory(dns=DNS_LIST, domain=AD_FQDN, username=DOMAIN_JOIN_USERNAME, password=domain_join_user_password, smb_server_name=SMB_SERVERNAME_PREFIX) ] console_output('Creating Azure NetApp Files account ...') account = None try: account = create_account(anf_client, RESOURCE_GROUP_NAME, ANF_ACCOUNT_NAME, LOCATION, active_directories) console_output( '\tAccount successfully created, resource id: {}'.format( account.id)) except CloudError as ex: console_output('An error ocurred. Error details: {}'.format( ex.message)) raise # Creating a Capacity Pool console_output('Creating Capacity Pool ...') capacity_pool = None try: capacity_pool = create_capacitypool(anf_client, RESOURCE_GROUP_NAME, account.name, CAPACITYPOOL_NAME, CAPACITYPOOL_SERVICE_LEVEL, CAPACITYPOOL_SIZE, LOCATION) console_output( '\tCapacity Pool successfully created, resource id: {}'.format( capacity_pool.id)) except CloudError as ex: console_output('An error ocurred. Error details: {}'.format( ex.message)) raise # Creating a Volume ''' Note: With exception of Accounts, all resources with Name property returns a relative path up to the name and to use this property in other methods, like Get for example, the argument needs to be sanitized and just the actual name needs to be used (the hierarchy needs to be cleaned up in the name). Capacity Pool Name property example: "pmarques-anf01/pool01" "pool01" is the actual name that needs to be used instead. Below you will see a sample function that parses the name from its resource id: resource_uri_utils.get_anf_capacity_pool() ''' console_output('Creating a Volume ...') volume = None try: pool_name = resource_uri_utils.get_anf_capacity_pool(capacity_pool.id) volume = create_volume(anf_client, RESOURCE_GROUP_NAME, account.name, pool_name, VOLUME_NAME, VOLUME_USAGE_QUOTA, CAPACITYPOOL_SERVICE_LEVEL, SUBNET_ID, LOCATION) console_output('\tVolume successfully created, resource id: {}'.format( volume.id)) console_output('\t====> SMB Server FQDN: {}'.format( volume.mount_targets[0].additional_properties["smbServerFQDN"])) except CloudError as ex: console_output('An error ocurred. Error details: {}'.format( ex.message)) raise ''' Cleaning up volumes - for this to happen, please change the value of SHOULD_CLEANUP variable to true. Note: Volume deletion operations at the RP level are executed serially ''' if SHOULD_CLEANUP: ''' Cleaning up. This process needs to start the cleanup from the innermost resources down in the hierarchy chain in our case Snapshots->Volumes->Capacity Pools->Accounts ''' console_output('Cleaning up...') console_output("\tDeleting Volumes...") try: volume_ids = [volume.id] for volume_id in volume_ids: console_output("\t\tDeleting {}".format(volume_id)) anf_client.volumes.delete( RESOURCE_GROUP_NAME, account.name, resource_uri_utils.get_anf_capacitypool(capacity_pool.id), resource_uri_utils.get_anf_volume(volume_id)).wait() # ARM Workaround to wait the deletion complete/propagate sample_utils.wait_for_no_anf_resource(anf_client, volume_id) console_output('\t\tDeleted Volume: {}'.format(volume_id)) except CloudError as ex: console_output('An error ocurred. Error details: {}'.format( ex.message)) raise # Cleaning up Capacity Pool console_output("\tDeleting Capacity Pool {} ...".format( resource_uri_utils.get_anf_capacitypool(capacity_pool.id))) try: anf_client.pools.delete( RESOURCE_GROUP_NAME, account.name, resource_uri_utils.get_anf_capacitypool( capacity_pool.id)).wait() # ARM Workaround to wait the deletion complete/propagate sample_utils.wait_for_no_anf_resource(anf_client, capacity_pool.id) console_output('\t\tDeleted Capacity Pool: {}'.format( capacity_pool.id)) except CloudError as ex: console_output('An error ocurred. Error details: {}'.format( ex.message)) raise # Cleaning up Account console_output("\tDeleting Account {} ...".format(account.name)) try: anf_client.accounts.delete(RESOURCE_GROUP_NAME, account.name) console_output('\t\tDeleted Account: {}'.format(account.id)) except CloudError as ex: console_output('An error ocurred. Error details: {}'.format( ex.message)) raise
def run_example(): """Azure NetApp Files Snapshot Policy SDK management example""" print_header( "Azure NetAppFiles Python SDK Samples - Sample project that creates and updates a Snapshot Policy using " "the Azure NetApp Files SDK") # Authenticating using service principal, refer to README.md file for requirement details credentials, subscription_id = get_credentials() console_output( "Instantiating a new Azure NetApp Files management client...") anf_client = NetAppManagementClient(credentials, subscription_id) console_output("Creating ANF Resources...") # Creating ANF Primary Account console_output("Creating Account...") anf_account = None try: anf_account = create_account(anf_client, RESOURCE_GROUP_NAME, ANF_ACCOUNT_NAME, LOCATION) console_output( "\tAccount successfully created. Resource id: {}".format( anf_account.id)) except AzureError as ex: console_output("An error occurred while creating Account: {}".format( ex.message)) raise # Creating Snapshot Policy console_output("Creating Snapshot Policy...") snapshot_policy = None try: snapshot_policy = create_snapshot_policy(anf_client, RESOURCE_GROUP_NAME, anf_account.name, SNAPSHOT_POLICY_NAME, LOCATION) console_output( "\tSnapshot Policy successfully created. Resource id: {}".format( snapshot_policy.id)) except AzureError as ex: console_output( "An error occurred while creating Snapshot Policy: {}".format( ex.message)) raise # Creating Capacity Pool console_output("Creating Capacity Pool...") capacity_pool = None try: capacity_pool = create_capacity_pool(anf_client, RESOURCE_GROUP_NAME, anf_account.name, CAPACITY_POOL_NAME, CAPACITY_POOL_SIZE, LOCATION) console_output( "\tCapacity Pool successfully created. Resource id: {}".format( capacity_pool.id)) except AzureError as ex: console_output( "An error occurred while creating Capacity Pool: {}".format( ex.message)) raise # Creating Volume console_output("Creating Volume...") subnet_id = '/subscriptions/{}/resourceGroups/{}/providers/Microsoft.Network/virtualNetworks/{}/subnets/{}'.format( subscription_id, RESOURCE_GROUP_NAME, VNET_NAME, SUBNET_NAME) volume = None try: pool_name = resource_uri_utils.get_anf_capacity_pool(capacity_pool.id) volume = create_volume(anf_client, RESOURCE_GROUP_NAME, anf_account.name, pool_name, VOLUME_NAME, VOLUME_SIZE, subnet_id, LOCATION) console_output("\tVolume successfully created. Resource id: {}".format( volume.id)) except AzureError as ex: console_output("An error occurred while creating Volume: {}".format( ex.message)) raise # Update Snapshot Policy console_output("Updating Snapshot Policy...") # Updating number of snapshots to keep for hourly schedule hourly_schedule = snapshot_policy.hourly_schedule hourly_schedule.snapshotsToKeep = 5 snapshot_policy_patch = SnapshotPolicyPatch( hourly_schedule=hourly_schedule, location=snapshot_policy.location, enabled=True) try: anf_client.snapshot_policies.begin_update(RESOURCE_GROUP_NAME, ANF_ACCOUNT_NAME, SNAPSHOT_POLICY_NAME, snapshot_policy_patch) console_output("\tSnapshot Policy successfully updated") except AzureError as ex: console_output( "An error occurred while updating Snapshot Policy: {}".format( ex.message)) raise """ Cleanup process. For this process to take effect please change the value of CLEANUP_RESOURCES global variable to 'True' Note: Volume deletion operations at the RP level are executed serially """ if CLEANUP_RESOURCES: # The cleanup process starts from the innermost resources down in the hierarchy chain. # In this case: Volumes -> Capacity Pools -> (Snapshot Policy) -> Accounts console_output("Cleaning up resources") # Cleaning up Volumes console_output("Deleting Volumes...") try: volume_ids = [volume.id] for volume_id in volume_ids: pool_name = resource_uri_utils.get_resource_value( volume_id, "capacityPools") volume_name = resource_uri_utils.get_anf_volume(volume_id) console_output("\tDeleting {}".format(volume_name)) anf_client.volumes.begin_delete(RESOURCE_GROUP_NAME, anf_account.name, pool_name, volume_name).wait() # ARM Workaround to wait the deletion complete/propagate wait_for_no_anf_resource(anf_client, volume_id) console_output( "\t\tSuccessfully deleted Volume: {}".format(volume_id)) except AzureError as ex: console_output( "An error occurred while deleting volumes: {}".format( ex.message)) raise # Cleaning up Capacity Pools console_output("Deleting Capacity Pools...") try: pool_ids = [capacity_pool.id] for pool_id in pool_ids: pool_name = resource_uri_utils.get_anf_capacity_pool(pool_id) console_output("\tDeleting {}".format(pool_name)) anf_client.pools.begin_delete(RESOURCE_GROUP_NAME, anf_account.name, pool_name).wait() wait_for_no_anf_resource(anf_client, pool_id) console_output( "\t\tSuccessfully deleted Capacity Pool: {}".format( pool_id)) except AzureError as ex: console_output( "An error occurred while deleting capacity pools: {}".format( ex.message)) raise # Cleaning up Snapshot Policy console_output("Deleting Snapshot Policy...") try: console_output("\tDeleting {}".format(snapshot_policy.name)) anf_client.snapshot_policies.begin_delete( RESOURCE_GROUP_NAME, anf_account.name, SNAPSHOT_POLICY_NAME).wait() wait_for_no_anf_resource(anf_client, snapshot_policy.id) console_output( "\t\tSuccessfully deleted Snapshot Policy: {}".format( snapshot_policy.id)) except AzureError as ex: console_output( "An error occurred while deleting snapshot policy: {}".format( ex.message)) raise # Cleaning up Account console_output("Deleting Account...") try: console_output("\tDeleting {}".format(anf_account.name)) anf_client.accounts.begin_delete(RESOURCE_GROUP_NAME, anf_account.name).wait() console_output("\t\tSuccessfully deleted Account: {}".format( anf_account.id)) except AzureError as ex: console_output( "An error occurred while deleting accounts: {}".format( ex.message)) raise console_output("ANF Snapshot Policy sample has completed successfully")
def run_example(): """Azure NetApp Files Cross-Region Replication (CRR) SDK management example""" print_header( "Azure NetApp Files Python CRR SDK Sample - Sample " "project that creates a primary ANF Account, Capacity Pool, and an " "NFS v4.1 Volume. Then it creates secondary resources and a " "Data Replication Volume.") # Authenticating using service principal, refer to README.md file for requirement details credentials, subscription_id = get_credentials() console_output( "Instantiating a new Azure NetApp Files management client...") anf_client = NetAppManagementClient(credentials, subscription_id) console_output("Creating Primary ANF Resources...") # Creating ANF Primary Account console_output("Creating Primary Account...") primary_account = None try: primary_account = create_account(anf_client, PRIMARY_RESOURCE_GROUP_NAME, PRIMARY_ANF_ACCOUNT_NAME, PRIMARY_LOCATION) console_output( "\tAccount successfully created. Resource id: {}".format( primary_account.id)) except AzureError as ex: console_output("An error occurred while creating Account: {}".format( ex.message)) raise # Creating Primary Capacity Pool console_output("Creating Primary Capacity Pool...") primary_capacity_pool = None try: primary_capacity_pool = create_capacity_pool( anf_client, PRIMARY_RESOURCE_GROUP_NAME, primary_account.name, PRIMARY_CAPACITY_POOL_NAME, CAPACITY_POOL_SIZE, PRIMARY_LOCATION) console_output( "\tCapacity Pool successfully created. Resource id: {}".format( primary_capacity_pool.id)) except AzureError as ex: console_output( "An error occurred while creating Capacity Pool: {}".format( ex.message)) raise # Creating Primary Volume console_output("Creating Primary Volume...") primary_subnet_id = '/subscriptions/{}/resourceGroups/{}/providers/Microsoft.Network/virtualNetworks/{}/subnets/{}'.format( subscription_id, PRIMARY_RESOURCE_GROUP_NAME, PRIMARY_VNET_NAME, PRIMARY_SUBNET_NAME) primary_volume = None try: pool_name = resource_uri_utils.get_anf_capacity_pool( primary_capacity_pool.id) primary_volume = create_volume(anf_client, PRIMARY_RESOURCE_GROUP_NAME, primary_account.name, pool_name, PRIMARY_VOLUME_NAME, VOLUME_SIZE, primary_subnet_id, PRIMARY_LOCATION) console_output("\tVolume successfully created. Resource id: {}".format( primary_volume.id)) except AzureError as ex: console_output("An error occurred while creating Volume: {}".format( ex.message)) raise # Wait for primary volume to be ready console_output("Waiting for {} to be available...".format( resource_uri_utils.get_anf_volume(primary_volume.id))) wait_for_anf_resource(anf_client, primary_volume.id) console_output("Creating Secondary ANF Resources...") # Creating ANF Secondary Account console_output("Creating Secondary Account...") secondary_account = None try: secondary_account = create_account(anf_client, SECONDARY_RESOURCE_GROUP_NAME, SECONDARY_ANF_ACCOUNT_NAME, SECONDARY_LOCATION) console_output( "\tAccount successfully created. Resource id: {}".format( secondary_account.id)) except AzureError as ex: console_output("An error occurred while creating Account: {}".format( ex.message)) raise # Creating Secondary Capacity Pool console_output("Creating Secondary Capacity Pool...") secondary_capacity_pool = None try: secondary_capacity_pool = create_capacity_pool( anf_client, SECONDARY_RESOURCE_GROUP_NAME, secondary_account.name, SECONDARY_CAPACITY_POOL_NAME, CAPACITY_POOL_SIZE, SECONDARY_LOCATION) console_output( "\tCapacity Pool successfully created. Resource id: {}".format( secondary_capacity_pool.id)) except AzureError as ex: console_output( "An error occurred while creating Capacity Pool: {}".format( ex.message)) raise # Creating Secondary Volume console_output("Creating Secondary Volume...") secondary_subnet_id = '/subscriptions/{}/resourceGroups/{}/providers/Microsoft.Network/virtualNetworks/{}/subnets/{}'.format( subscription_id, SECONDARY_RESOURCE_GROUP_NAME, SECONDARY_VNET_NAME, SECONDARY_SUBNET_NAME) data_replication_volume = None try: replication_object = ReplicationObject( endpoint_type="dst", remote_volume_region=PRIMARY_LOCATION, remote_volume_resource_id=primary_volume.id, replication_schedule="hourly") data_protection_object = VolumePropertiesDataProtection( replication=replication_object) pool_name = resource_uri_utils.get_anf_capacity_pool( secondary_capacity_pool.id) data_replication_volume = create_volume( anf_client, SECONDARY_RESOURCE_GROUP_NAME, secondary_account.name, pool_name, SECONDARY_VOLUME_NAME, VOLUME_SIZE, secondary_subnet_id, SECONDARY_LOCATION, data_protection_object) console_output("\tVolume successfully created. Resource id: {}".format( data_replication_volume.id)) except AzureError as ex: console_output("An error occurred while creating Volume: {}".format( ex.message)) raise # Wait for data replication volume to be ready console_output("Waiting for {} to be available...".format( resource_uri_utils.get_anf_volume(data_replication_volume.id))) wait_for_anf_resource(anf_client, data_replication_volume.id) console_output("Authorizing replication in source region...") # Authorize replication between the two volumes authorization_replication_body = AuthorizeRequest( remote_volume_resource_id=data_replication_volume.id) anf_client.volumes.begin_authorize_replication( resource_uri_utils.get_resource_group(primary_account.id), resource_uri_utils.get_anf_account(primary_account.id), resource_uri_utils.get_anf_capacity_pool(primary_capacity_pool.id), resource_uri_utils.get_anf_volume(primary_volume.id), authorization_replication_body).wait() # Wait for replication to initialize on source volume wait_for_anf_resource(anf_client, primary_volume.id, replication=True) console_output("\tSuccessfully authorized replication in source region") # """ # Cleanup process. For this process to take effect please change the value of # CLEANUP_RESOURCES global variable to 'True' # Note: Volume deletion operations at the RP level are executed serially # """ if CLEANUP_RESOURCES: # The cleanup process starts from the innermost resources down in the hierarchy chain. # In this case: Volumes -> Capacity Pools -> Accounts console_output("Cleaning up resources") # Cleaning up volumes console_output("Deleting Volumes...") # We need to break and then remove the replication attached to the destination # volume before we can delete either volume in a replication. As a result, volumes # must be deleted in the order of destination and then source in this code. # First, we check if the volume is a destination volume and act accordingly. # Note that we need to delete the replication using the destination volume's id # This erases the replication for both destination and source volumes. try: volume_ids = [data_replication_volume.id, primary_volume.id] for volume_id in volume_ids: resource_group = resource_uri_utils.get_resource_group( volume_id) account_name = resource_uri_utils.get_anf_account(volume_id) pool_name = resource_uri_utils.get_anf_capacity_pool(volume_id) volume_name = resource_uri_utils.get_anf_volume(volume_id) current_volume = anf_client.volumes.get( resource_group, account_name, pool_name, volume_name) # If the volume is a destination volume, the replication must be broken and deleted if current_volume.data_protection.replication is not None and \ (current_volume.data_protection.replication.endpoint_type == "dst" or current_volume.data_protection.replication.additional_properties["endPointType"] == "Dst"): console_output( "Deleting replication on Volume {}".format(volume_id)) try: wait_for_mirror_state(anf_client, resource_group, account_name, pool_name, volume_name, mirror_state.MIRRORED) anf_client.volumes.begin_break_replication( resource_group, account_name, pool_name, volume_name).wait() except AzureError as e: if e.status_code == 404: # If replication is not found then the volume can be safely deleted. Therefore we pass on this error and proceed to delete the volume pass else: # Throw all other exceptions console_output( "An error occurred while breaking replication: {}" .format(e.message)) raise try: wait_for_mirror_state(anf_client, resource_group, account_name, pool_name, volume_name, mirror_state.BROKEN) anf_client.volumes.begin_delete_replication( resource_group, account_name, pool_name, volume_name).wait() # Wait for replication to finish deleting wait_for_no_anf_resource(anf_client, volume_id, replication=True) console_output( "\tSuccessfully deleted replication on Volume {}". format(volume_id)) except AzureError as e: if e.status_code == 404: # If replication is not found then the volume can be safely deleted. Therefore we pass on this error and proceed to delete the volume pass else: # Throw all other exceptions console_output( "An error occurred while deleting replication: {}" .format(e.message)) raise console_output("Deleting Volume {}".format(volume_id)) anf_client.volumes.begin_delete(resource_group, account_name, pool_name, volume_name).wait() # ARM workaround to wait for the deletion to complete wait_for_no_anf_resource(anf_client, volume_id) console_output( "\tSuccessfully deleted Volume {}".format(volume_id)) except AzureError as ex: console_output( "An error occurred while deleting volumes: {}".format( ex.message)) raise # Cleaning up capacity pools console_output("Deleting Capacity Pools...") try: pool_ids = [primary_capacity_pool.id, secondary_capacity_pool.id] for pool_id in pool_ids: resource_group = resource_uri_utils.get_resource_group(pool_id) account_name = resource_uri_utils.get_anf_account(pool_id) pool_name = resource_uri_utils.get_anf_capacity_pool(pool_id) console_output("Deleting Capacity Pool {}".format(pool_id)) anf_client.pools.begin_delete(resource_group, account_name, pool_name).wait() # ARM workaround to wait for the deletion to complete wait_for_no_anf_resource(anf_client, pool_id) console_output( "\tSuccessfully deleted Capacity Pool {}".format(pool_id)) except AzureError as ex: console_output( "An error occurred while deleting capacity pools: {}".format( ex.message)) raise # Cleaning up accounts console_output("Deleting Accounts...") try: account_ids = [primary_account.id, secondary_account.id] for account_id in account_ids: resource_group = resource_uri_utils.get_resource_group( account_id) account_name = resource_uri_utils.get_anf_account(account_id) console_output("Deleting Account {}".format(account_id)) anf_client.accounts.begin_delete(resource_group, account_name).wait() # ARM workaround to wait for the deletion to complete wait_for_no_anf_resource(anf_client, account_id) console_output( "\tSuccessfully deleted Account {}".format(account_id)) except AzureError as ex: console_output( "An error occurred while deleting accounts: {}".format( ex.message)) raise console_output("ANF Cross-Region Replication has completed successfully")