Esempio n. 1
0
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
Esempio n. 2
0
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
Esempio n. 3
0
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
Esempio n. 4
0
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")