Ejercicio: Carga de los recursos que va a usar un lote con la biblioteca de almacenamiento de .NET

Completado

Importante

Para realizar este ejercicio, se necesita una suscripción de Azure propia y puede que se apliquen cargos. Si aún no tiene una suscripción de Azure, cree una cuenta gratuita antes de comenzar.

La biblioteca de Azure Storage permite controlar mediante programación el almacenamiento de archivos en una cuenta de Azure Storage.

En este ejercicio, se mejorará la aplicación para cargar vídeos al almacenamiento de blobs.

Adición de los detalles de conexión de la cuenta de almacenamiento

  1. En Cloud Shell, agregue el paquete NuGet de Azure Blob Storage:

    dotnet add package Microsoft.Azure.Storage.Blob
    
  2. Modifique el archivo Program.cs en el editor:

    code Program.cs
    
  3. Agregue las siguientes instrucciones using a la parte superior de Program.cs para incluir las bibliotecas necesarias para el trabajo de almacenamiento:

    using Microsoft.Azure.Storage.Blob;
    using Microsoft.Azure.Storage;
    using System.IO;
    

    Microsoft.Azure.Storage.Blob y Microsoft.Azure.Storage ofrecen acceso a la aplicación a la cuenta de Azure Storage. System.IO proporciona acceso a la aplicación al sistema de archivos para el control de los archivos.

  4. Agregue variables para las credenciales de Azure Storage a la clase Program de Program.cs:

    // Storage account credentials
    private const string envVarStorage = "STORAGE_NAME";
    private const string envVarStorageKey = "STORAGE_KEY";
    private static string storageAccountName;
    private static string storageAccountKey;
    

Creación de un contenedor de entrada y salida

  1. En Program.cs, reemplace Main() con la actualización siguiente, que agrega código para administrar la cuenta de almacenamiento:

    static async Task Main(string[] args)
    {
        // Read the environment variables to allow the app to connect to the Azure Batch and Azure Storage accounts
        batchAccountUrl = Environment.GetEnvironmentVariable(envVarBatchURI);
        batchAccountName = Environment.GetEnvironmentVariable(envVarBatchName);
        batchAccountKey = Environment.GetEnvironmentVariable(envVarKey);
        storageAccountName = Environment.GetEnvironmentVariable(envVarStorage);
        storageAccountKey = Environment.GetEnvironmentVariable(envVarStorageKey);
    
        // Show the user the accounts they are attaching to
        Console.WriteLine("BATCH URL: {0}, Name: {1}, Key: {2}", batchAccountUrl, batchAccountName, batchAccountKey);
        Console.WriteLine("Storage Name: {0}, Key: {1}", storageAccountName, storageAccountKey);
    
        // Construct the Storage account connection string
        string storageConnectionString = String.Format("DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}",
                            storageAccountName, storageAccountKey);
    
        // Retrieve the storage account
        CloudStorageAccount storageAccount = CloudStorageAccount.Parse(storageConnectionString);
    
        // Create the blob client, for use in obtaining references to blob storage containers
        CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
    
        // Use the blob client to create the containers in blob storage
        const string inputContainerName = "input";
        const string outputContainerName = "output";
    
        await CreateContainerIfNotExistAsync(blobClient, inputContainerName);
        await CreateContainerIfNotExistAsync(blobClient, outputContainerName);
    
        // RESOURCE FILE SETUP
        // Add *.mp4 files into the \<solutiondir>\InputFiles folder.
    
        string inputPath = Path.Combine(Environment.CurrentDirectory, "InputFiles");
        List<string> inputFilePaths = new List<string>(
            Directory.GetFileSystemEntries(inputPath, "*.mp4", SearchOption.TopDirectoryOnly));
    
        // Upload data files.
        // Upload the data files using UploadResourceFilesToContainer(). This data will be
        // processed by each of the tasks that are executed on the compute nodes within the pool.
        List<ResourceFile> inputFiles = await UploadFilesToContainerAsync(blobClient, inputContainerName, inputFilePaths);
    
        // Obtain a shared access signature that provides write access to the output container to which
        // the tasks will upload their output.
        string outputContainerSasUrl = GetContainerSasUrl(blobClient, outputContainerName, SharedAccessBlobPermissions.Write);
    
        // The batch client requires a BatchSharedKeyCredentials object to open a connection
        var sharedKeyCredentials = new BatchSharedKeyCredentials(batchAccountUrl, batchAccountName, batchAccountKey);
        var batchClient = BatchClient.Open(sharedKeyCredentials);
    
        // Create the Batch pool, which contains the compute nodes that execute tasks.
        await CreateBatchPoolAsync(batchClient, PoolId);
    }
    

    En el código anterior, se crea un objeto CloudStorageAccount para permitir que la aplicación cree un cliente de blob. El cliente se usa para crear los contenedores de almacenamiento, cargar los archivos y conceder acceso al trabajo para escribir en el contenedor de salida.

Creación de contenedores de almacenamiento para la entrada y salida de archivos

  1. Agregue el método siguiente, CreateContainerIfNotExistAsync(), para crear un contenedor con el nombre especificado:

    private static async Task CreateContainerIfNotExistAsync(CloudBlobClient blobClient, string containerName)
    {
        CloudBlobContainer container = blobClient.GetContainerReference(containerName);
        await container.CreateIfNotExistsAsync();
        Console.WriteLine("Creating container [{0}].", containerName);
    }
    

    En el código anterior se usa el objeto CloudBlobClient creado en el método Main para crear contenedores.

Procesamiento de la lista de todos los archivos para cargar

  1. Agregue el método siguiente, UploadFilesToContainerAsync(), para cargar una lista de archivos de entrada en el contenedor:

    private static async Task<List<ResourceFile>> UploadFilesToContainerAsync(CloudBlobClient blobClient, string inputContainerName, List<string> filePaths)
    {
        List<ResourceFile> resourceFiles = new List<ResourceFile>();
    
        foreach (string filePath in filePaths)
        {
            resourceFiles.Add(await UploadResourceFileToContainerAsync(blobClient, inputContainerName, filePath));
        }
    
        return resourceFiles;
    }
    

    En el código anterior se usa la lista creada de rutas de archivo para llamar a un método para cargarlas y almacenar la referencia ResourceFile generada para que la use el trabajo de Batch.

Carga de los archivos

  1. Agregue un método para cargar los archivos locales en Azure Storage:

    private static async Task<ResourceFile> UploadResourceFileToContainerAsync(CloudBlobClient blobClient, string containerName, string filePath)
    {
        Console.WriteLine("Uploading file {0} to container [{1}]...", filePath, containerName);
    
        string blobName = Path.GetFileName(filePath);
        var fileStream = System.IO.File.OpenRead(filePath);
    
        CloudBlobContainer container = blobClient.GetContainerReference(containerName);
        CloudBlockBlob blobData = container.GetBlockBlobReference(blobName);
        await blobData.UploadFromFileAsync(filePath);
    
        // Set the expiry time and permissions for the blob shared access signature. In this case, no start time is specified,
        // so the shared access signature becomes valid immediately
        SharedAccessBlobPolicy sasConstraints = new SharedAccessBlobPolicy
        {
            SharedAccessExpiryTime = DateTime.UtcNow.AddHours(2),
            Permissions = SharedAccessBlobPermissions.Read
        };
    
        // Construct the SAS URL for the blob
        string sasBlobToken = blobData.GetSharedAccessSignature(sasConstraints);
        string blobSasUri = String.Format("{0}{1}", blobData.Uri, sasBlobToken);
    
        return ResourceFile.FromUrl(blobSasUri, blobName);
    }
    

    En el código anterior se usa CloudBlobClient para cargar los archivos de forma asincrónica. Crea un archivo de recursos que se agrega a una lista que usará la tarea añadida en el siguiente ejercicio.

Habilitación del acceso a la carpeta de salida

  1. Cree una referencia de Firma de acceso compartido (SAS) al contenedor de salida en el que las tareas escribirán sus archivos:

    private static string GetContainerSasUrl(CloudBlobClient blobClient, string containerName, SharedAccessBlobPermissions permissions)
    {
        // Set the expiry time and permissions for the container access signature. In this case, no start time is specified,
        // so the shared access signature becomes valid immediately. Expiration is in 2 hours.
        SharedAccessBlobPolicy sasConstraints = new SharedAccessBlobPolicy
        {
            SharedAccessExpiryTime = DateTime.UtcNow.AddHours(2),
            Permissions = permissions
        };
    
        // Generate the shared access signature on the container, setting the constraints directly on the signature
        CloudBlobContainer container = blobClient.GetContainerReference(containerName);
        string sasContainerToken = container.GetSharedAccessSignature(sasConstraints);
    
        // Return the URL string for the container, including the SAS token
        return String.Format("{0}{1}", container.Uri, sasContainerToken);
    }
    

    En el código anterior se crea una dirección URL SAS con acceso limitado (dos horas) para que la tarea pueda escribir los GIF animados convertidos en el almacenamiento de blobs.

  2. En el editor de código, haga clic con el botón derecho y seleccione Guardar, después haga clic con el botón derecho y seleccione Salir.

Prueba de las cargas de archivo

  1. En Cloud Shell, cree una carpeta InputFiles en el directorio de la aplicación:

    mkdir InputFiles
    
  2. Ejecute los comandos curl siguientes en Cloud Shell para copiar un conjunto de vídeos de mascotas de ejemplo desde el repositorio de GitHub del módulo en la carpeta InputFiles local.

    curl -L https://github.com/MicrosoftDocs/mslearn-apps-and-batch/raw/master/cutifypets/InputFiles/1.mp4 > ./InputFiles/1.mp4
    curl -L https://github.com/MicrosoftDocs/mslearn-apps-and-batch/raw/master/cutifypets/InputFiles/2.mp4 > ./InputFiles/2.mp4
    curl -L https://github.com/MicrosoftDocs/mslearn-apps-and-batch/raw/master/cutifypets/InputFiles/3.mp4 > ./InputFiles/3.mp4
    curl -L https://github.com/MicrosoftDocs/mslearn-apps-and-batch/raw/master/cutifypets/InputFiles/4.mp4 > ./InputFiles/4.mp4
    curl -L https://github.com/MicrosoftDocs/mslearn-apps-and-batch/raw/master/cutifypets/InputFiles/5.mp4 > ./InputFiles/5.mp4
    curl -L https://github.com/MicrosoftDocs/mslearn-apps-and-batch/raw/master/cutifypets/InputFiles/6.mp4 > ./InputFiles/6.mp4
    
  3. Guarde las credenciales de Azure Storage en variables de entorno. El segundo comando usa la variable de entorno RESOURCE_GROUP que se definió en la sección Configuración de los detalles de conexión para la aplicación del ejercicio anterior, Ejercicio: Acceso a la cuenta de Batch mediante la biblioteca cliente de .NET. El valor es el nombre del grupo de recursos que seleccionó cuando creó su cuenta de Batch.

    export STORAGE_NAME=$(az storage account list --query "[?contains(name,'cuti')].name" --output tsv)
    export STORAGE_KEY=$(az storage account keys list --account-name $STORAGE_NAME --query [0].value --output tsv --resource-group $RESOURCE_GROUP)
    
  4. Compile y ejecute la aplicación:

    dotnet run
    
  5. El programa debe ejecutar y escribir los mensajes siguientes en el terminal:

    BATCH URL: [your batch url], Name: [your batch account name], Key: [your batch key]
    Storage Name: [your storage account name], Key: [your storage key]
    Creating container [input].
    Creating container [output].
    Uploading file ~\cutifypets\InputFiles\3.mp4 to container [input]...
    Uploading file ~\cutifypets\InputFiles\2.mp4 to container [input]...
    Uploading file ~\cutifypets\InputFiles\4.mp4 to container [input]...
    Uploading file ~\cutifypets\InputFiles\1.mp4 to container [input]...
    Uploading file ~\cutifypets\InputFiles\5.mp4 to container [input]...
    Uploading file ~\cutifypets\InputFiles\6.mp4 to container [input]...
    Creating pool [WinFFmpegPool]...
    

Comprobación de los archivos cargados mediante Azure Portal

  1. Vuelva a Azure Portal. En el menú de la izquierda, seleccione Cuentas de almacenamiento, después seleccione la cuenta de almacenamiento que creó en el primer ejercicio.

    Screenshot that shows a user's storage accounts.

  2. En el menú de la izquierda, seleccione Contenedores en Almacenamiento de datos, después seleccione la carpeta entrada.

    Screenshot that shows the created containers in blob storage.

  3. La carpeta contiene los vídeos cargados.

    Screenshot that shows the uploaded video files.