示例#1
0
        public void Bug2338301_CheckStreamPositionAfterFileRead()
        {
            Action test = () =>
            {
                using (BatchClient batchCli = TestUtilities.OpenBatchClientAsync(TestUtilities.GetCredentialsFromEnvironment()).Result)
                {
                    JobOperations jobOperations = batchCli.JobOperations;
                    {
                        string jobId = "Bug2338301Job-" + TestUtilities.GetMyName();

                        try
                        {
                            const string taskId = "hiWorld";

                            //
                            // Create the job
                            //
                            CloudJob unboundJob = jobOperations.CreateJob(jobId, new PoolInformation()
                            {
                                PoolId = this.poolFixture.PoolId
                            });
                            unboundJob.Commit();

                            CloudJob  boundJob = jobOperations.GetJob(jobId);
                            CloudTask myTask   = new CloudTask(taskId, "cmd /c echo hello world");

                            boundJob.AddTask(myTask);

                            this.testOutputHelper.WriteLine("Initial job commit()");

                            //
                            // Wait for task to go to completion
                            //
                            Utilities        utilities        = batchCli.Utilities;
                            TaskStateMonitor taskStateMonitor = utilities.CreateTaskStateMonitor();
                            taskStateMonitor.WaitAll(
                                boundJob.ListTasks(),
                                Microsoft.Azure.Batch.Common.TaskState.Completed,
                                TimeSpan.FromMinutes(3));

                            CloudTask boundTask = boundJob.GetTask(taskId);

                            //Get the task file
                            const string fileToGet = "stdout.txt";
                            NodeFile     file      = boundTask.GetNodeFile(fileToGet);

                            //Download the file data
                            string result = file.ReadAsString();
                            Assert.True(result.Length > 0);
                        }
                        finally
                        {
                            jobOperations.DeleteJob(jobId);
                        }
                    }
                }
            };

            SynchronizationContextHelper.RunTest(test, TestTimeout);
        }
示例#2
0
        private string GetDriverUrlInternal(string filepath)
        {
            CloudTask driverTask = _azurebatchService.GetJobManagerTaskFromJobId(_jobId);

            NodeFile httpEndPointFile;

            try
            {
                httpEndPointFile = driverTask.GetNodeFile(Path.Combine(AzureBatchTaskWorkDirectory, filepath));
            }
            catch (BatchException e)
            {
                throw new InvalidOperationException("driver http endpoint file is not ready.", e);
            }

            string driverHost = httpEndPointFile.ReadAsString().TrimEnd('\r', '\n', ' ');

            //// Get port
            string[] driverIpAndPorts = driverHost.Split(':');
            if (driverIpAndPorts.Length <= 1 || !int.TryParse(driverIpAndPorts[1], out int backendPort))
            {
                LOGGER.Log(Level.Warning, "Unable to get driver http endpoint port from: {0}", driverHost);
                return(null);
            }

            //// Get public Ip
            string      publicIp     = "0.0.0.0";
            int         frontEndPort = 0;
            string      driverNodeId = driverTask.ComputeNodeInformation.ComputeNodeId;
            ComputeNode driverNode   = _azurebatchService.GetComputeNodeFromNodeId(driverNodeId);
            IReadOnlyList <InboundEndpoint> inboundEndpoints = driverNode.EndpointConfiguration.InboundEndpoints;
            InboundEndpoint endpoint = inboundEndpoints.FirstOrDefault(s => s.BackendPort == backendPort);

            if (endpoint != null)
            {
                publicIp     = endpoint.PublicIPAddress;
                frontEndPort = endpoint.FrontendPort;
            }

            return("http://" + publicIp + ':' + frontEndPort + '/');
        }
示例#3
0
        static void AddTasks(BatchClient client)
        {
            CloudJob job = client.JobOperations.GetJob("testjob1");
            ResourceFile programFile = new ResourceFile(
                "https://mystorage00.blob.core.windows.net/testcon1/ProcessTaskData.exe",
                "ProcessTaskData.exe"
                );
            ResourceFile assemblyFile = new ResourceFile(
                  "https://mystorage00.blob.core.windows.net/testcon1/Microsoft.WindowsAzure.Storage.dll",
                  "Microsoft.WindowsAzure.Storage.dll"
                  );
            for (int i = 1; i < 4; ++i)
            {
                string blobName = "taskdata" + i;
                string taskName = "mytask" + i;
                ResourceFile taskData = new ResourceFile("https://mystorage00.blob.core.windows.net/testcon1/" +
                  blobName, blobName);
                CloudTask task = new CloudTask(
                    taskName,
                    "ProcessTaskData.exe https://mystorage00.blob.core.windows.net/testcon1/" +
                    blobName + " 3");
                List<ResourceFile> taskFiles = new List<ResourceFile>();
                taskFiles.Add(taskData);
                taskFiles.Add(programFile);
                taskFiles.Add(assemblyFile);
                task.ResourceFiles = taskFiles;
                job.AddTask(task);
                job.Commit();
                job.Refresh();
            }

            client.Utilities.CreateTaskStateMonitor().WaitAll(job.ListTasks(),
            TaskState.Completed, new TimeSpan(0, 30, 0));
            Console.WriteLine("The tasks completed successfully.");
            foreach (CloudTask task in job.ListTasks())
            {
                Console.WriteLine("Task " + task.Id + " says:\n" + task.GetNodeFile(Constants.StandardOutFileName).ReadAsString());
            }
            Console.WriteLine("Press Enter to continue.");
            Console.ReadLine();
        }
        public void CanAddTaskWithFilesToStage()
        {
            StagingStorageAccount storageCreds = TestUtilities.GetStorageCredentialsFromEnvironment();

            using (BatchClient batchCli = TestUtilities.OpenBatchClient(TestUtilities.GetCredentialsFromEnvironment()))
            {
                string jobId = "TestTaskWithFilesToStage-" + TestUtilities.GetMyName();

                try
                {
                    CloudJob job = batchCli.JobOperations.CreateJob(jobId, new PoolInformation()
                    {
                        PoolId = this.poolFixture.PoolId
                    });
                    job.Commit();
                    CloudJob boundJob = batchCli.JobOperations.GetJob(jobId);

                    CloudTask myTask = new CloudTask(id: "CountWordsTask", commandline: @"cmd /c dir /s .. & dir & wc localwords.txt");

                    myTask.FilesToStage = new List <IFileStagingProvider>
                    {
                        new FileToStage(Resources.LocalWordsDotText, storageCreds)
                    };

                    // add the task to the job
                    var artifacts        = boundJob.AddTask(myTask);
                    var specificArtifact = artifacts[typeof(FileToStage)];
                    SequentialFileStagingArtifact sfsa = specificArtifact as SequentialFileStagingArtifact;

                    Assert.NotNull(sfsa);

                    // Open the new Job as bound.
                    CloudPool boundPool = batchCli.PoolOperations.GetPool(boundJob.ExecutionInformation.PoolId);

                    // wait for the task to complete
                    TaskStateMonitor taskStateMonitor = batchCli.Utilities.CreateTaskStateMonitor();

                    taskStateMonitor.WaitAll(
                        boundJob.ListTasks(),
                        Microsoft.Azure.Batch.Common.TaskState.Completed,
                        TimeSpan.FromMinutes(10),
                        controlParams: null,
                        additionalBehaviors: new[]
                    {
                        // spam/logging interceptor
                        new Microsoft.Azure.Batch.Protocol.RequestInterceptor((x) =>
                        {
                            this.testOutputHelper.WriteLine("Issuing request type: " + x.GetType().ToString());

                            try
                            {
                                // print out the compute node states... we are actually waiting on the compute nodes
                                List <ComputeNode> allComputeNodes = boundPool.ListComputeNodes().ToList();

                                this.testOutputHelper.WriteLine("    #compute nodes: " + allComputeNodes.Count);

                                allComputeNodes.ForEach(
                                    (icn) =>
                                {
                                    this.testOutputHelper.WriteLine("  computeNode.id: " + icn.Id + ", state: " + icn.State);
                                });
                            }
                            catch (Exception ex)
                            {
                                // there is a race between the pool-life-job and the end of the job.. and the ListComputeNodes above
                                Assert.True(false, "SampleWithFilesAndPool probably can ignore this if its pool not found: " + ex.ToString());
                            }
                        })
                    });

                    List <CloudTask> tasks           = boundJob.ListTasks().ToList();
                    CloudTask        myCompletedTask = tasks.Single();

                    foreach (CloudTask curTask in tasks)
                    {
                        this.testOutputHelper.WriteLine("Task Id: " + curTask.Id + ", state: " + curTask.State);
                    }

                    boundPool.Refresh();

                    this.testOutputHelper.WriteLine("Pool Id: " + boundPool.Id + ", state: " + boundPool.State);

                    string stdOut = myCompletedTask.GetNodeFile(Constants.StandardOutFileName).ReadAsString();
                    string stdErr = myCompletedTask.GetNodeFile(Constants.StandardErrorFileName).ReadAsString();

                    this.testOutputHelper.WriteLine("StdOut: ");
                    this.testOutputHelper.WriteLine(stdOut);

                    this.testOutputHelper.WriteLine("StdErr: ");
                    this.testOutputHelper.WriteLine(stdErr);

                    this.testOutputHelper.WriteLine("Task Files:");

                    foreach (NodeFile curFile in myCompletedTask.ListNodeFiles(recursive: true))
                    {
                        this.testOutputHelper.WriteLine("    File path: " + curFile.Path);
                    }

                    var files = myCompletedTask.ListNodeFiles(recursive: true).ToList();

                    // confirm the files are there
                    Assert.True(files.Any(file => file.Path.Contains("localWords.txt")), "missing file: localWords.txt");
                }
                finally
                {
                    TestUtilities.DeleteJobIfExistsAsync(batchCli, jobId).Wait();
                }
            }
        }
示例#5
0
        static void Main(string[] args)
        {
            string storageConnectionString =
                $"DefaultEndpointsProtocol=https;AccountName={StorageAccountName};AccountKey={StorageAccountKey}";

            // Retrieve the storage account
            CloudStorageAccount storageAccount = CloudStorageAccount.Parse(storageConnectionString);

            // Create the blob client
            CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

            // Upload the input files to blob storage
            const string  inputContainerName = "batchinput";
            List <string> inputFilePaths     = new List <string>
            {
                "taskdata0.txt",
                "taskdata1.txt",
                "taskdata2.txt"
            };
            List <ResourceFile> inputFiles = new List <ResourceFile>();

            foreach (string filePath in inputFilePaths)
            {
                inputFiles.Add(UploadFileToContainer(blobClient, inputContainerName, filePath));
            }

            // Get a SAS Url for the output container
            const string outputContainerName   = "batchoutput";
            string       outputContainerSasUrl = GetOutputContainerSasUrl(blobClient, outputContainerName);

            // Specify a container registry
            ContainerRegistry containerRegistry = new ContainerRegistry(
                registryServer: RegistryServer,
                userName: RegistryUserName,
                password: RegistryPassword);

            // Create container configuration, prefetching Docker images from the container registry
            ContainerConfiguration containerConfig = new ContainerConfiguration()
            {
                ContainerImageNames = ContainerImageNames,
                ContainerRegistries = new List <ContainerRegistry> {
                    containerRegistry
                }
            };

            // Create the virtual machine image reference - make sure to choose an image that supports containers
            ImageReference imageReference = new ImageReference(
                publisher: "MicrosoftWindowsServer",
                offer: "WindowsServer",
                sku: "2016-datacenter-with-containers",
                version: "latest");

            // Create the virtual machine configuration for the pool and set the container configuration
            VirtualMachineConfiguration virtualMachineConfiguration = new VirtualMachineConfiguration(
                imageReference: imageReference,
                nodeAgentSkuId: "batch.node.windows amd64");

            virtualMachineConfiguration.ContainerConfiguration = containerConfig;

            BatchSharedKeyCredentials cred = new BatchSharedKeyCredentials(BatchAccountUrl, BatchAccountName, BatchAccountKey);

            using (BatchClient batchClient = BatchClient.Open(cred))
            {
                Console.WriteLine("Creating pool [{0}]...", PoolId);

                try
                {
                    CloudPool pool = batchClient.PoolOperations.CreatePool(
                        poolId: PoolId,
                        targetDedicatedComputeNodes: PoolNodeCount,
                        virtualMachineSize: PoolVMSize,
                        virtualMachineConfiguration: virtualMachineConfiguration);

                    pool.Commit();
                }
                catch (BatchException be)
                {
                    // Accept the specific error code PoolExists as that is expected if the pool already exists
                    if (be.RequestInformation?.BatchError?.Code == BatchErrorCodeStrings.PoolExists)
                    {
                        Console.WriteLine("The pool {0} already existed when we tried to create it", PoolId);
                    }
                    else
                    {
                        throw; // Any other exception is unexpected
                    }
                }

                Console.WriteLine("Creating job [{0}]...", JobId);
                CloudJob job = null;
                try
                {
                    job    = batchClient.JobOperations.CreateJob();
                    job.Id = JobId;
                    job.PoolInformation = new PoolInformation {
                        PoolId = PoolId
                    };

                    // Add job preparation task to remove existing Docker image
                    Console.WriteLine("Adding job preparation task to job [{0}]...", JobId);
                    string             jobPreparationCmdLine = $"cmd /c docker rmi -f {ContainerImageNames[0]}:latest";
                    JobPreparationTask jobPreparationTask    = new JobPreparationTask(jobPreparationCmdLine)
                    {
                        UserIdentity = new UserIdentity(new AutoUserSpecification(elevationLevel: ElevationLevel.Admin, scope: AutoUserScope.Task))
                    };
                    job.JobPreparationTask = jobPreparationTask;

                    job.Commit();
                }
                catch (BatchException be)
                {
                    // Accept the specific error code JobExists as that is expected if the job already exists
                    if (be.RequestInformation?.BatchError?.Code == BatchErrorCodeStrings.JobExists)
                    {
                        Console.WriteLine("The job {0} already existed when we tried to create it", JobId);
                    }
                    else
                    {
                        throw; // Any other exception is unexpected
                    }
                }

                if (job != null)
                {
                    // Create a collection to hold the tasks that we'll be adding to the job
                    Console.WriteLine("Adding {0} tasks to job [{1}]...", inputFiles.Count, JobId);

                    List <CloudTask> tasks = new List <CloudTask>();

                    // Create each of the tasks to process one of the input files.
                    for (int i = 0; i < inputFiles.Count; i++)
                    {
                        string taskId         = String.Format("Task{0}", i);
                        string inputFilename  = inputFiles[i].FilePath;
                        string outputFileName = string.Format("out{0}", inputFilename);

                        // Override the default entrypoint of the container
                        string taskCommandLine = string.Format("C:\\ReadWriteFile\\ReadWriteFile.exe {0} {1}", inputFilename, outputFileName);

                        // Specify the container the task will run
                        TaskContainerSettings cmdContainerSettings = new TaskContainerSettings(
                            imageName: "nimccollftacr.azurecr.io/batch/readwritefile"
                            );

                        CloudTask task = new CloudTask(taskId, taskCommandLine);
                        task.ContainerSettings = cmdContainerSettings;

                        // Set the resource files and output files for the task
                        task.ResourceFiles = new List <ResourceFile> {
                            inputFiles[i]
                        };
                        task.OutputFiles = new List <OutputFile>
                        {
                            new OutputFile(
                                filePattern: outputFileName,
                                destination: new OutputFileDestination(new OutputFileBlobContainerDestination(containerUrl: outputContainerSasUrl, path: outputFileName)),
                                uploadOptions: new OutputFileUploadOptions(OutputFileUploadCondition.TaskCompletion))
                        };

                        // You must elevate the identity of the task in order to run a container
                        task.UserIdentity = new UserIdentity(new AutoUserSpecification(elevationLevel: ElevationLevel.Admin, scope: AutoUserScope.Task));
                        tasks.Add(task);
                    }

                    // Add all tasks to the job.
                    batchClient.JobOperations.AddTask(JobId, tasks);

                    // Monitor task success/failure, specifying a maximum amount of time to wait for the tasks to complete.
                    TimeSpan timeout = TimeSpan.FromMinutes(30);
                    Console.WriteLine("Monitoring all tasks for 'Completed' state, timeout in {0}...", timeout);

                    IEnumerable <CloudTask> addedTasks = batchClient.JobOperations.ListTasks(JobId);

                    batchClient.Utilities.CreateTaskStateMonitor().WaitAll(addedTasks, TaskState.Completed, timeout);

                    Console.WriteLine("All tasks reached state Completed.");

                    // Print task output
                    Console.WriteLine();
                    Console.WriteLine("Printing task output...");

                    IEnumerable <CloudTask> completedtasks = batchClient.JobOperations.ListTasks(JobId);

                    foreach (CloudTask task in completedtasks)
                    {
                        string nodeId = String.Format(task.ComputeNodeInformation.ComputeNodeId);
                        Console.WriteLine("Task: {0}", task.Id);
                        Console.WriteLine("Node: {0}", nodeId);
                        Console.WriteLine("Standard out:");
                        Console.WriteLine(task.GetNodeFile(Constants.StandardOutFileName).ReadAsString());
                    }
                }

                // Clean up Batch resources (if the user so chooses)
                Console.WriteLine();
                Console.Write("Delete job? [yes] no: ");
                string response = Console.ReadLine().ToLower();
                if (response != "n" && response != "no")
                {
                    batchClient.JobOperations.DeleteJob(JobId);
                }

                Console.Write("Delete pool? [yes] no: ");
                response = Console.ReadLine().ToLower();
                if (response != "n" && response != "no")
                {
                    batchClient.PoolOperations.DeletePool(PoolId);
                }
            }
        }
        public void TestSampleWithFilesAndPool()
        {
            Action test = () =>
            {
                StagingStorageAccount storageCreds = TestUtilities.GetStorageCredentialsFromEnvironment();

                using (BatchClient batchCli = TestUtilities.OpenBatchClientAsync(TestUtilities.GetCredentialsFromEnvironment()).Result)
                {
                    string jobId = "SampleWithFilesJob-" + TestUtilities.GetMyName();


                    try
                    {
                        CloudJob quickJob = batchCli.JobOperations.CreateJob();
                        quickJob.Id = jobId;
                        quickJob.PoolInformation = new PoolInformation()
                        {
                            PoolId = this.poolFixture.PoolId
                        };
                        quickJob.Commit();
                        CloudJob boundJob = batchCli.JobOperations.GetJob(jobId);

                        CloudTask myTask = new CloudTask(id: "CountWordsTask", commandline: @"cmd /c dir /s .. & dir & wc localwords.txt");

                        // first we have local files that we want pushed to the compute node before the commandline is invoked
                        FileToStage wordsDotText = new FileToStage(Resources.LocalWordsDotText, storageCreds);                // use "default" mapping to base name of local file

                        myTask.FilesToStage = new List <IFileStagingProvider>();

                        myTask.FilesToStage.Add(wordsDotText);

                        // add the task to the job
                        var artifacts        = boundJob.AddTask(myTask);
                        var specificArtifact = artifacts[typeof(FileToStage)];
                        SequentialFileStagingArtifact sfsa = specificArtifact as SequentialFileStagingArtifact;

                        Assert.NotNull(sfsa);

                        // add a million more tasks...

                        // test to ensure the task is read only
                        TestUtilities.AssertThrows <InvalidOperationException>(() => myTask.FilesToStage = new List <IFileStagingProvider>());

                        // Open the new Job as bound.
                        CloudPool boundPool = batchCli.PoolOperations.GetPool(boundJob.ExecutionInformation.PoolId);

                        // wait for the task to complete
                        Utilities        utilities        = batchCli.Utilities;
                        TaskStateMonitor taskStateMonitor = utilities.CreateTaskStateMonitor();

                        taskStateMonitor.WaitAll(
                            boundJob.ListTasks(),
                            Microsoft.Azure.Batch.Common.TaskState.Completed,
                            TimeSpan.FromMinutes(10),
                            controlParams: null,
                            additionalBehaviors:
                            new[]
                        {
                            // spam/logging interceptor
                            new Microsoft.Azure.Batch.Protocol.RequestInterceptor((x) =>
                            {
                                this.testOutputHelper.WriteLine("Issuing request type: " + x.GetType().ToString());

                                try
                                {
                                    // print out the compute node states... we are actually waiting on the compute nodes
                                    List <ComputeNode> allComputeNodes = boundPool.ListComputeNodes().ToList();

                                    this.testOutputHelper.WriteLine("    #compute nodes: " + allComputeNodes.Count);

                                    allComputeNodes.ForEach(
                                        (icn) =>
                                    {
                                        this.testOutputHelper.WriteLine("  computeNode.id: " + icn.Id + ", state: " + icn.State);
                                    });
                                }
                                catch (Exception ex)
                                {
                                    // there is a race between the pool-life-job and the end of the job.. and the ListComputeNodes above
                                    Assert.True(false, "SampleWithFilesAndPool probably can ignore this if its pool not found: " + ex.ToString());
                                }
                            })
                        });

                        List <CloudTask> tasks           = boundJob.ListTasks(null).ToList();
                        CloudTask        myCompletedTask = tasks[0];

                        foreach (CloudTask curTask in tasks)
                        {
                            this.testOutputHelper.WriteLine("Task Id: " + curTask.Id + ", state: " + curTask.State);
                        }

                        boundPool.Refresh();

                        this.testOutputHelper.WriteLine("Pool Id: " + boundPool.Id + ", state: " + boundPool.State);

                        string stdOut = myCompletedTask.GetNodeFile(Constants.StandardOutFileName).ReadAsString();
                        string stdErr = myCompletedTask.GetNodeFile(Constants.StandardErrorFileName).ReadAsString();

                        this.testOutputHelper.WriteLine("StdOut: ");
                        this.testOutputHelper.WriteLine(stdOut);

                        this.testOutputHelper.WriteLine("StdErr: ");
                        this.testOutputHelper.WriteLine(stdErr);

                        this.testOutputHelper.WriteLine("Task Files:");

                        foreach (NodeFile curFile in myCompletedTask.ListNodeFiles(recursive: true))
                        {
                            this.testOutputHelper.WriteLine("    Filename: " + curFile.Name);
                        }

                        // confirm the files are there
                        Assert.True(FoundFile("localwords.txt", myCompletedTask.ListNodeFiles(recursive: true)), "mising file: localwords.txt");

                        // test validation of StagingStorageAccount

                        TestUtilities.AssertThrows <ArgumentOutOfRangeException>(() => { new StagingStorageAccount(storageAccount: " ", storageAccountKey: "key", blobEndpoint: "blob"); });
                        TestUtilities.AssertThrows <ArgumentOutOfRangeException>(() => { new StagingStorageAccount(storageAccount: "account", storageAccountKey: " ", blobEndpoint: "blob"); });
                        TestUtilities.AssertThrows <ArgumentOutOfRangeException>(() => { new StagingStorageAccount(storageAccount: "account", storageAccountKey: "key", blobEndpoint: ""); });

                        if (null != sfsa)
                        {
                            // TODO: delete the container!
                        }
                    }
                    finally
                    {
                        TestUtilities.DeleteJobIfExistsAsync(batchCli, jobId).Wait();
                    }
                }
            };

            SynchronizationContextHelper.RunTest(test, TestTimeout);
        }
示例#7
0
        public static async Task MainAsync()
        {
            const string poolId = "MultiInstanceSamplePool";
            const string jobId  = "MultiInstanceSampleJob";
            const string taskId = "MultiInstanceSampleTask";

            const int numberOfNodes = 3;

            // The application package and version to deploy to the compute nodes.
            // It should contain your MPIHelloWorld sample MS-MPI program:
            // https://blogs.technet.microsoft.com/windowshpc/2015/02/02/how-to-compile-and-run-a-simple-ms-mpi-program/
            // And the MSMpiSetup.exe installer:
            // https://www.microsoft.com/download/details.aspx?id=52981
            // Then upload it as an application package:
            // https://azure.microsoft.com/documentation/articles/batch-application-packages/
            const string appPackageId      = "MPIHelloWorld";
            const string appPackageVersion = "1.0";

            TimeSpan timeout = TimeSpan.FromMinutes(30);

            // Configure your AccountSettings in the Microsoft.Azure.Batch.Samples.Common project within this solution
            BatchSharedKeyCredentials cred = new BatchSharedKeyCredentials(AccountSettings.Default.BatchServiceUrl,
                                                                           AccountSettings.Default.BatchAccountName,
                                                                           AccountSettings.Default.BatchAccountKey);

            using (BatchClient batchClient = BatchClient.Open(cred))
            {
                // Create the pool of compute nodes and the job to which we add the multi-instance task.
                await CreatePoolAsync(batchClient, poolId, numberOfNodes, appPackageId, appPackageVersion);
                await CreateJobAsync(batchClient, jobId, poolId);

                // Create the multi-instance task. The MultiInstanceSettings property (configured
                // below) tells Batch to create one primary and several subtasks, the total number
                // of which matches the number of instances you specify in the MultiInstanceSettings.
                // This main task's command line is the "application command," and is executed *only*
                // by the primary, and only after the primary and all subtasks have executed the
                // "coordination command" (the MultiInstanceSettings.CoordinationCommandLine).
                CloudTask multiInstanceTask = new CloudTask(id: taskId,
                                                            commandline: $"cmd /c mpiexec.exe -c 1 -wdir %AZ_BATCH_TASK_SHARED_DIR% %AZ_BATCH_APP_PACKAGE_{appPackageId.ToUpper()}#{appPackageVersion}%\\MPIHelloWorld.exe");

                // Configure the task's MultiInstanceSettings. Specify the number of nodes
                // to allocate to the multi-instance task, and the "coordination command".
                // The CoordinationCommandLine is run by the primary and subtasks, and is
                // used in this sample to start SMPD on the compute nodes.
                multiInstanceTask.MultiInstanceSettings =
                    new MultiInstanceSettings(@"cmd /c start cmd /c smpd.exe -d", numberOfNodes);

                // Submit the task to the job. Batch will take care of creating one primary and
                // enough subtasks to match the total number of nodes allocated to the task,
                // and schedule them for execution on the nodes.
                Console.WriteLine($"Adding task [{taskId}] to job [{jobId}]...");
                await batchClient.JobOperations.AddTaskAsync(jobId, multiInstanceTask);

                // Get the "bound" version of the multi-instance task.
                CloudTask mainTask = await batchClient.JobOperations.GetTaskAsync(jobId, taskId);

                // We use a TaskStateMonitor to monitor the state of our tasks. In this case,
                // we will wait for the task to reach the Completed state.
                Console.WriteLine($"Awaiting task completion, timeout in {timeout}...");
                TaskStateMonitor taskStateMonitor = batchClient.Utilities.CreateTaskStateMonitor();
                await taskStateMonitor.WhenAll(new List <CloudTask> {
                    mainTask
                }, TaskState.Completed, timeout);

                // Refresh the task to obtain up-to-date property values from Batch, such as
                // its current state and information about the node on which it executed.
                await mainTask.RefreshAsync();

                string stdOut = mainTask.GetNodeFile(Constants.StandardOutFileName).ReadAsString();
                string stdErr = mainTask.GetNodeFile(Constants.StandardErrorFileName).ReadAsString();

                Console.WriteLine();
                Console.WriteLine($"Main task [{mainTask.Id}] is in state [{mainTask.State}] and ran on compute node [{mainTask.ComputeNodeInformation.ComputeNodeId}]:");
                Console.WriteLine("---- stdout.txt ----");
                Console.WriteLine(stdOut);
                Console.WriteLine("---- stderr.txt ----");
                Console.WriteLine(stdErr);

                // Need to delay a bit to allow the Batch service to mark the subtasks as Complete
                TimeSpan subtaskTimeout = TimeSpan.FromSeconds(10);
                Console.WriteLine($"Main task completed, waiting {subtaskTimeout} for subtasks to complete...");
                System.Threading.Thread.Sleep(subtaskTimeout);

                Console.WriteLine();
                Console.WriteLine("---- Subtask information ----");

                // Obtain the collection of subtasks for the multi-instance task, and print
                // some information about each.
                IPagedEnumerable <SubtaskInformation> subtasks = mainTask.ListSubtasks();
                await subtasks.ForEachAsync(async (subtask) =>
                {
                    Console.WriteLine("subtask: " + subtask.Id);
                    Console.WriteLine("\texit code: " + subtask.ExitCode);

                    if (subtask.State == SubtaskState.Completed)
                    {
                        // Obtain the file from the node on which the subtask executed. For normal CloudTasks,
                        // we could simply call CloudTask.GetNodeFile(Constants.StandardOutFileName), but the
                        // subtasks are not "normal" tasks in Batch, and thus must be handled differently.
                        ComputeNode node =
                            await batchClient.PoolOperations.GetComputeNodeAsync(subtask.ComputeNodeInformation.PoolId,
                                                                                 subtask.ComputeNodeInformation.ComputeNodeId);

                        string outPath = subtask.ComputeNodeInformation.TaskRootDirectory + "\\" + Constants.StandardOutFileName;
                        string errPath = subtask.ComputeNodeInformation.TaskRootDirectory + "\\" + Constants.StandardErrorFileName;

                        NodeFile stdOutFile = await node.GetNodeFileAsync(outPath.Trim('\\'));
                        NodeFile stdErrFile = await node.GetNodeFileAsync(errPath.Trim('\\'));

                        stdOut = await stdOutFile.ReadAsStringAsync();
                        stdErr = await stdErrFile.ReadAsStringAsync();

                        Console.WriteLine($"\tnode: " + node.Id);
                        Console.WriteLine("\tstdout.txt: " + stdOut);
                        Console.WriteLine("\tstderr.txt: " + stdErr);
                    }
                    else
                    {
                        Console.WriteLine($"\tSubtask {subtask.Id} is in state {subtask.State}");
                    }
                });

                // Clean up the resources we've created in the Batch account
                Console.WriteLine();
                Console.Write("Delete job? [yes] no: ");
                string response = Console.ReadLine().ToLower();
                if (response != "n" && response != "no")
                {
                    await batchClient.JobOperations.DeleteJobAsync(jobId);
                }

                Console.Write("Delete pool? [yes] no: ");
                response = Console.ReadLine().ToLower();
                if (response != "n" && response != "no")
                {
                    await batchClient.PoolOperations.DeletePoolAsync(poolId);
                }
            }
        }
示例#8
0
        static void Main(string[] args)
        {
            string storageConnectionString =
                $"DefaultEndpointsProtocol=https;AccountName={StorageAccountName};AccountKey={StorageAccountKey}";

            // Retrieve the storage account
            CloudStorageAccount storageAccount = CloudStorageAccount.Parse(storageConnectionString);

            // Create the blob client
            CloudBlobClient blobClient         = storageAccount.CreateCloudBlobClient();
            const string    inputContainerName = "batchinput";
            List <string>   inputFilePaths     = new List <string>
            {
                "taskdata0.txt",
                "taskdata1.txt",
                "taskdata2.txt"
            };

            // Upload the input files to blob storage
            List <ResourceFile> inputFiles = new List <ResourceFile>();

            foreach (string filePath in inputFilePaths)
            {
                inputFiles.Add(UploadFileToContainer(blobClient, inputContainerName, filePath));
            }

            // Get a SAS Url for the output container
            const string outputContainerName   = "batchoutput";
            string       outputContainerSasUrl = GetOutputContainerSasUrl(blobClient, outputContainerName);

            // Create the virtual machine image reference
            ImageReference imageReference = new ImageReference(
                publisher: "MicrosoftWindowsServer",
                offer: "WindowsServer",
                sku: "2016-datacenter-smalldisk",
                version: "latest");

            // Create the virtual machine configuration for the pool
            VirtualMachineConfiguration virtualMachineConfiguration = new VirtualMachineConfiguration(
                imageReference: imageReference,
                nodeAgentSkuId: "batch.node.windows amd64");

            BatchSharedKeyCredentials cred = new BatchSharedKeyCredentials(BatchAccountUrl, BatchAccountName, BatchAccountKey);

            using (BatchClient batchClient = BatchClient.Open(cred))
            {
                Console.WriteLine("Creating pool [{0}]...", PoolId);
                try
                {
                    CloudPool pool = batchClient.PoolOperations.CreatePool(
                        poolId: PoolId,
                        targetDedicatedComputeNodes: PoolNodeCount,
                        virtualMachineSize: PoolVMSize,
                        virtualMachineConfiguration: virtualMachineConfiguration);

                    // Specify the application packages for the tasks
                    pool.ApplicationPackageReferences = new List <ApplicationPackageReference>
                    {
                        new ApplicationPackageReference {
                            ApplicationId = "ReadWriteFile", Version = "1"
                        }
                    };

                    pool.Commit();
                }
                catch (BatchException be)
                {
                    // Accept the specific error code PoolExists as that is expected if the pool already exists
                    if (be.RequestInformation?.BatchError?.Code == BatchErrorCodeStrings.PoolExists)
                    {
                        Console.WriteLine("The pool {0} already existed when we tried to create it", PoolId);
                    }
                    else
                    {
                        throw; // Any other exception is unexpected
                    }
                }

                Console.WriteLine("Creating job [{0}]...", JobId);
                try
                {
                    CloudJob job = batchClient.JobOperations.CreateJob();
                    job.Id = JobId;
                    job.PoolInformation = new PoolInformation {
                        PoolId = PoolId
                    };

                    job.Commit();
                }
                catch (BatchException be)
                {
                    // Accept the specific error code JobExists as that is expected if the job already exists
                    if (be.RequestInformation?.BatchError?.Code == BatchErrorCodeStrings.JobExists)
                    {
                        Console.WriteLine("The job {0} already existed when we tried to create it", JobId);
                    }
                    else
                    {
                        throw; // Any other exception is unexpected
                    }
                }

                // Create a collection to hold the tasks that we'll be adding to the job
                Console.WriteLine("Adding {0} tasks to job [{1}]...", inputFiles.Count, JobId);

                List <CloudTask> tasks = new List <CloudTask>();

                // Create each of the tasks to process one of the input files.
                for (int i = 0; i < inputFiles.Count; i++)
                {
                    string taskId          = String.Format("Task{0}", i);
                    string inputFilename   = inputFiles[i].FilePath;
                    string outputFileName  = string.Format("out{0}", inputFilename);
                    string taskCommandLine = string.Format("cmd /c %AZ_BATCH_APP_PACKAGE_READWRITEFILE%\\ReadWriteFile.exe {0} {1}", inputFilename, outputFileName);

                    CloudTask task = new CloudTask(taskId, taskCommandLine);

                    // Set the resource files and output files for the task
                    task.ResourceFiles = new List <ResourceFile> {
                        inputFiles[i]
                    };
                    task.OutputFiles = new List <OutputFile>
                    {
                        new OutputFile(
                            filePattern: outputFileName,
                            destination: new OutputFileDestination(new OutputFileBlobContainerDestination(containerUrl: outputContainerSasUrl, path: outputFileName)),
                            uploadOptions: new OutputFileUploadOptions(OutputFileUploadCondition.TaskCompletion))
                    };
                    tasks.Add(task);
                }

                // Add all tasks to the job.
                batchClient.JobOperations.AddTask(JobId, tasks);

                // Monitor task success/failure, specifying a maximum amount of time to wait for the tasks to complete.
                TimeSpan timeout = TimeSpan.FromMinutes(30);
                Console.WriteLine("Monitoring all tasks for 'Completed' state, timeout in {0}...", timeout);

                IEnumerable <CloudTask> addedTasks = batchClient.JobOperations.ListTasks(JobId);

                batchClient.Utilities.CreateTaskStateMonitor().WaitAll(addedTasks, TaskState.Completed, timeout);

                Console.WriteLine("All tasks reached state Completed.");

                // Print task output
                Console.WriteLine();
                Console.WriteLine("Printing task output...");

                IEnumerable <CloudTask> completedtasks = batchClient.JobOperations.ListTasks(JobId);

                foreach (CloudTask task in completedtasks)
                {
                    string nodeId = String.Format(task.ComputeNodeInformation.ComputeNodeId);
                    Console.WriteLine("Task: {0}", task.Id);
                    Console.WriteLine("Node: {0}", nodeId);
                    Console.WriteLine("Standard out:");
                    Console.WriteLine(task.GetNodeFile(Constants.StandardOutFileName).ReadAsString());
                }

                // Clean up Batch resources (if the user so chooses)
                Console.WriteLine();
                Console.Write("Delete job? [yes] no: ");
                string response = Console.ReadLine().ToLower();
                if (response != "n" && response != "no")
                {
                    batchClient.JobOperations.DeleteJob(JobId);
                }

                Console.Write("Delete pool? [yes] no: ");
                response = Console.ReadLine().ToLower();
                if (response != "n" && response != "no")
                {
                    batchClient.PoolOperations.DeletePool(PoolId);
                }
            }
        }
示例#9
0
        private static void StartBatchTasks(List <ResourceFile> inputFiles)
        {
            BatchSharedKeyCredentials cred = new BatchSharedKeyCredentials(BatchAccountUrl, BatchAccountName, BatchAccountKey);

            using (BatchClient batchClient = BatchClient.Open(cred))
            {
                // Create a Windows Server image, VM configuration, Batch pool
                ImageReference imageReference = CreateImageReference();

                VirtualMachineConfiguration vmConfiguration = CreateVirtualMachineConfiguration(imageReference);

                CreateBatchPool(batchClient, vmConfiguration);

                CreateJob(batchClient);

                List <CloudTask> tasks = new List <CloudTask>();

                for (int i = 0; i < inputFiles.Count; i++)
                {
                    string taskId          = String.Format("Task{0}", i);
                    string inputFilename   = inputFiles[i].FilePath;
                    string taskCommandLine = String.Format("cmd /c type {0}", inputFilename);

                    CloudTask task = new CloudTask(taskId, taskCommandLine);
                    task.ResourceFiles = new List <ResourceFile> {
                        inputFiles[i]
                    };
                    tasks.Add(task);
                }

                batchClient.JobOperations.AddTask(JobId, tasks);

                TimeSpan timeout = TimeSpan.FromMinutes(30);
                Console.WriteLine("Monitoring all tasks for 'Completed' state, timeout in {0}...", timeout);

                IEnumerable <CloudTask> addedTasks = batchClient.JobOperations.ListTasks(JobId);

                batchClient.Utilities.CreateTaskStateMonitor().WaitAll(addedTasks, TaskState.Completed, timeout);

                // List tasks

                IEnumerable <CloudTask> completedtasks = batchClient.JobOperations.ListTasks(JobId);

                foreach (CloudTask task in completedtasks)
                {
                    string nodeId = String.Format(task.ComputeNodeInformation.ComputeNodeId);
                    Console.WriteLine("Task: {0}", task.Id);
                    Console.WriteLine("Node: {0}", nodeId);
                    Console.WriteLine("Standard out:");
                    Console.WriteLine(task.GetNodeFile(Constants.StandardOutFileName).ReadAsString());
                }

                // delete job

                batchClient.JobOperations.DeleteJob(JobId);

                // delete pool

                batchClient.PoolOperations.DeletePool(PoolId);
            }
        }
示例#10
0
        static void Main()
        {
            if (String.IsNullOrEmpty(BatchAccountName) ||
                String.IsNullOrEmpty(BatchAccountKey) ||
                String.IsNullOrEmpty(BatchAccountUrl) ||
                String.IsNullOrEmpty(StorageAccountName) ||
                String.IsNullOrEmpty(StorageAccountKey))
            {
                throw new InvalidOperationException("One or more account credential strings have not been populated. Please ensure that your Batch and Storage account credentials have been specified.");
            }

            try
            {
                Console.WriteLine("Sample start: {0}", DateTime.Now);
                Console.WriteLine();
                Stopwatch timer = new Stopwatch();
                timer.Start();

                // Create the blob client, for use in obtaining references to blob storage containers
                CloudBlobClient blobClient = CreateCloudBlobClient(StorageAccountName, StorageAccountKey);

                // Use the blob client to create the input container in Azure Storage
                const string inputContainerName = "input";

                CloudBlobContainer container = blobClient.GetContainerReference(inputContainerName);

                container.CreateIfNotExistsAsync().Wait();

                // The collection of data files that are to be processed by the tasks
                List <string> inputFilePaths = new List <string>
                {
                    "taskdata0.txt",
                    "taskdata1.txt",
                    "taskdata2.txt"
                };

                // Upload the data files to Azure Storage. This is the data that will be processed by each of the tasks that are
                // executed on the compute nodes within the pool.
                List <ResourceFile> inputFiles = new List <ResourceFile>();

                foreach (string filePath in inputFilePaths)
                {
                    inputFiles.Add(UploadFileToContainer(blobClient, inputContainerName, filePath));
                }

                // Get a Batch client using account creds

                BatchSharedKeyCredentials cred = new BatchSharedKeyCredentials(BatchAccountUrl, BatchAccountName, BatchAccountKey);

                using (BatchClient batchClient = BatchClient.Open(cred))
                {
                    Console.WriteLine("Creating pool [{0}]...", PoolId);

                    // Create a Windows Server image, VM configuration, Batch pool
                    ImageReference imageReference = CreateImageReference();

                    VirtualMachineConfiguration vmConfiguration = CreateVirtualMachineConfiguration(imageReference);

                    CreateBatchPool(batchClient, vmConfiguration);

                    // Create a Batch job
                    Console.WriteLine("Creating job [{0}]...", JobId);

                    try
                    {
                        CloudJob job = batchClient.JobOperations.CreateJob();
                        job.Id = JobId;
                        job.PoolInformation = new PoolInformation {
                            PoolId = PoolId
                        };

                        job.Commit();
                    }
                    catch (BatchException be)
                    {
                        // Accept the specific error code JobExists as that is expected if the job already exists
                        if (be.RequestInformation?.BatchError?.Code == BatchErrorCodeStrings.JobExists)
                        {
                            Console.WriteLine("The job {0} already existed when we tried to create it", JobId);
                        }
                        else
                        {
                            throw; // Any other exception is unexpected
                        }
                    }

                    // Create a collection to hold the tasks that we'll be adding to the job

                    Console.WriteLine("Adding {0} tasks to job [{1}]...", inputFiles.Count, JobId);

                    List <CloudTask> tasks = new List <CloudTask>();

                    // Create each of the tasks to process one of the input files.

                    for (int i = 0; i < inputFiles.Count; i++)
                    {
                        string taskId          = String.Format("Task{0}", i);
                        string inputFilename   = inputFiles[i].FilePath;
                        string taskCommandLine = String.Format("cmd /c type {0}", inputFilename);

                        CloudTask task = new CloudTask(taskId, taskCommandLine);
                        task.ResourceFiles = new List <ResourceFile> {
                            inputFiles[i]
                        };
                        tasks.Add(task);
                    }

                    // Add all tasks to the job.
                    batchClient.JobOperations.AddTask(JobId, tasks);


                    // Monitor task success/failure, specifying a maximum amount of time to wait for the tasks to complete.

                    TimeSpan timeout = TimeSpan.FromMinutes(30);
                    Console.WriteLine("Monitoring all tasks for 'Completed' state, timeout in {0}...", timeout);

                    IEnumerable <CloudTask> addedTasks = batchClient.JobOperations.ListTasks(JobId);

                    batchClient.Utilities.CreateTaskStateMonitor().WaitAll(addedTasks, TaskState.Completed, timeout);

                    Console.WriteLine("All tasks reached state Completed.");

                    // Print task output
                    Console.WriteLine();
                    Console.WriteLine("Printing task output...");

                    IEnumerable <CloudTask> completedtasks = batchClient.JobOperations.ListTasks(JobId);

                    foreach (CloudTask task in completedtasks)
                    {
                        string nodeId = String.Format(task.ComputeNodeInformation.ComputeNodeId);
                        Console.WriteLine("Task: {0}", task.Id);
                        Console.WriteLine("Node: {0}", nodeId);
                        Console.WriteLine("Standard out:");
                        Console.WriteLine(task.GetNodeFile(Constants.StandardOutFileName).ReadAsString());
                    }

                    // Print out some timing info
                    timer.Stop();
                    Console.WriteLine();
                    Console.WriteLine("Sample end: {0}", DateTime.Now);
                    Console.WriteLine("Elapsed time: {0}", timer.Elapsed);

                    // Clean up Storage resources
                    container.DeleteIfExistsAsync().Wait();
                    Console.WriteLine("Container [{0}] deleted.", inputContainerName);

                    // Clean up Batch resources (if the user so chooses)
                    Console.WriteLine();
                    Console.Write("Delete job? [yes] no: ");
                    string response = Console.ReadLine().ToLower();
                    if (response != "n" && response != "no")
                    {
                        batchClient.JobOperations.DeleteJob(JobId);
                    }

                    Console.Write("Delete pool? [yes] no: ");
                    response = Console.ReadLine().ToLower();
                    if (response != "n" && response != "no")
                    {
                        batchClient.PoolOperations.DeletePool(PoolId);
                    }
                }
            }
            finally
            {
                Console.WriteLine();
                Console.WriteLine("Sample complete, hit ENTER to exit...");
                Console.ReadLine();
            }
        }
示例#11
0
        public static async Task MainAsync()
        {
            const string poolId = "MultiInstanceSamplePool";
            const string jobId  = "MultiInstanceSampleJob";
            const string taskId = "MultiInstanceSampleTask";

            const int numberOfNodes = 5;


            //jmeno package kterou uploaduju na azure s polu s MSMpiSetup
            const string appPackageId      = "Parallel";
            const string appPackageVersion = "1.0";

            TimeSpan timeout = TimeSpan.FromMinutes(15);

            AccountSettings accountSettings = SampleHelpers.LoadAccountSettings();

            //nakonfigurované batch accounty abych se mohl připojit ke svému účtu
            BatchSharedKeyCredentials cred = new BatchSharedKeyCredentials(
                accountSettings.BatchServiceUrl,
                accountSettings.BatchAccountName,
                accountSettings.BatchAccountKey);

            using (BatchClient batchClient = BatchClient.Open(cred))
            {
                // Vytvoření fondu výpočetních uzlů a úlohu, do které přidáme úlohu s více instancemi.
                await CreatePoolAsync(batchClient, poolId, numberOfNodes, appPackageId, appPackageVersion);
                await CreateJobAsync(batchClient, jobId, poolId);

                //batch vytvoří jednu hlavní a několik dílčích úkolů
                CloudTask multiInstanceTask = new CloudTask(id: taskId,
                                                            commandline: $"cmd /c mpiexec.exe -c 1 -wdir %AZ_BATCH_TASK_SHARED_DIR% %AZ_BATCH_APP_PACKAGE_{appPackageId.ToUpper()}#{appPackageVersion}%\\ParallelMpiApp.exe");

                // příkaz SPMD = více samostatných procesorů současně spouští stejný program
                multiInstanceTask.MultiInstanceSettings =
                    new MultiInstanceSettings(@"cmd /c start cmd /c smpd.exe -d", numberOfNodes);

                //zadání úkolů, vytvoří se jeden primární a několik dílčích,
                //aby odpovídaly počtu uzlů a naplánuje se jejich provedení v uzlech
                Console.WriteLine($"Adding task [{taskId}] to job [{jobId}]...");
                await batchClient.JobOperations.AddTaskAsync(jobId, multiInstanceTask);

                //verze úlohy
                CloudTask mainTask = await batchClient.JobOperations.GetTaskAsync(jobId, taskId);

                // sledování stavu úkolů,čekáme až bude úloha dokončena
                Console.WriteLine($"Awaiting task completion, timeout in {timeout}...");
                TaskStateMonitor taskStateMonitor = batchClient.Utilities.CreateTaskStateMonitor();
                await taskStateMonitor.WhenAll(new List <CloudTask> {
                    mainTask
                }, TaskState.Completed, timeout);

                //aktualizace úlohy
                await mainTask.RefreshAsync();

                string stdOut = mainTask.GetNodeFile(Constants.StandardOutFileName).ReadAsString();
                string stdErr = mainTask.GetNodeFile(Constants.StandardErrorFileName).ReadAsString();

                Console.WriteLine();
                Console.WriteLine($"Main task [{mainTask.Id}] is in state [{mainTask.State}] and ran on compute node [{mainTask.ComputeNodeInformation.ComputeNodeId}]:");
                Console.WriteLine("---- stdout.txt ----");
                Console.WriteLine(stdOut);
                Console.WriteLine("---- stderr.txt ----");
                Console.WriteLine(stdErr);

                // par sekund čas aby se stačily dílčí úlohy dokončit
                TimeSpan subtaskTimeout = TimeSpan.FromSeconds(10);
                Console.WriteLine($"Main task completed, waiting {subtaskTimeout} for subtasks to complete...");
                System.Threading.Thread.Sleep(subtaskTimeout);

                Console.WriteLine();
                Console.WriteLine("---- Subtask information ----");

                //kolekce dílčích úlohů a tisk informací o každém
                IPagedEnumerable <SubtaskInformation> subtasks = mainTask.ListSubtasks();
                await subtasks.ForEachAsync(async (subtask) =>
                {
                    Console.WriteLine("subtask: " + subtask.Id);
                    Console.WriteLine("\texit code: " + subtask.ExitCode);

                    if (subtask.State == SubtaskState.Completed)
                    {
                        //získání souborů z uzlů
                        ComputeNode node =
                            await batchClient.PoolOperations.GetComputeNodeAsync(subtask.ComputeNodeInformation.PoolId,
                                                                                 subtask.ComputeNodeInformation.ComputeNodeId);

                        string outPath = subtask.ComputeNodeInformation.TaskRootDirectory + "\\" + Constants.StandardOutFileName;
                        string errPath = subtask.ComputeNodeInformation.TaskRootDirectory + "\\" + Constants.StandardErrorFileName;

                        NodeFile stdOutFile = await node.GetNodeFileAsync(outPath.Trim('\\'));
                        NodeFile stdErrFile = await node.GetNodeFileAsync(errPath.Trim('\\'));

                        stdOut = await stdOutFile.ReadAsStringAsync();
                        stdErr = await stdErrFile.ReadAsStringAsync();

                        Console.WriteLine($"\tnode: " + node.Id);
                        Console.WriteLine("\tstdout.txt: " + stdOut);
                        Console.WriteLine("\tstderr.txt: " + stdErr);
                    }
                    else
                    {
                        Console.WriteLine($"\tSubtask {subtask.Id} is in state {subtask.State}");
                    }
                });

                // vymazání zdrojů které jsme vytvořili, abychom to nemuseli dělat manuálně(fondy,úlohy)
                Console.WriteLine();
                Console.Write("Delete job? [yes] no: ");
                string response = Console.ReadLine().ToLower();
                if (response != "n" && response != "no")
                {
                    await batchClient.JobOperations.DeleteJobAsync(jobId);
                }

                Console.Write("Delete pool? [yes] no: ");
                response = Console.ReadLine().ToLower();
                if (response != "n" && response != "no")
                {
                    await batchClient.PoolOperations.DeletePoolAsync(poolId);
                }
            }
        }
示例#12
0
        static void Main(string[] args)
        {
            string storageConnectionString =
                $"DefaultEndpointsProtocol=https;AccountName={StorageAccountName};AccountKey={StorageAccountKey}";

            // Retrieve the storage account
            CloudStorageAccount storageAccount = CloudStorageAccount.Parse(storageConnectionString);

            // Create the blob client
            CloudBlobClient blobClient         = storageAccount.CreateCloudBlobClient();
            const string    inputContainerName = "batchinput";
            List <string>   inputFilePaths     = new List <string>
            {
                "taskdata0.txt",
                "taskdata1.txt",
                "taskdata2.txt"
            };

            // Upload the input files to blob storage
            List <ResourceFile> inputFiles = new List <ResourceFile>();

            foreach (string filePath in inputFilePaths)
            {
                inputFiles.Add(UploadFileToContainer(blobClient, inputContainerName, filePath));
            }

            // Get a SAS Url for the output container
            const string outputContainerName   = "batchoutput";
            string       outputContainerSasUrl = GetOutputContainerSasUrl(blobClient, outputContainerName);

            // Retrieve an access token from Azure AD to authenticate with the Azure Batch API
            AuthenticationContext authContext           = new AuthenticationContext(AuthorityUri);
            AuthenticationResult  authResult            = authContext.AcquireTokenAsync(BatchResourceUri, new ClientCredential(ClientId, ClientKey)).Result;
            BatchTokenCredentials batchTokenCredentials = new BatchTokenCredentials(BatchAccountUrl, authResult.AccessToken);

            using (BatchClient batchClient = BatchClient.Open(batchTokenCredentials))
            {
                Console.WriteLine("Creating job [{0}]...", JobId);
                try
                {
                    CloudJob job = batchClient.JobOperations.CreateJob();
                    job.Id = JobId;
                    job.PoolInformation = new PoolInformation {
                        PoolId = PoolId
                    };

                    job.Commit();
                }
                catch (BatchException be)
                {
                    // Accept the specific error code JobExists as that is expected if the job already exists
                    if (be.RequestInformation?.BatchError?.Code == BatchErrorCodeStrings.JobExists)
                    {
                        Console.WriteLine("The job {0} already existed when we tried to create it", JobId);
                    }
                    else
                    {
                        throw; // Any other exception is unexpected
                    }
                }

                // Create a collection to hold the tasks that we'll be adding to the job
                Console.WriteLine("Adding {0} tasks to job [{1}]...", inputFiles.Count, JobId);

                List <CloudTask> tasks = new List <CloudTask>();

                // Create each of the tasks to process one of the input files.
                for (int i = 0; i < inputFiles.Count; i++)
                {
                    string taskId          = String.Format("Task{0}", i);
                    string inputFilename   = inputFiles[i].FilePath;
                    string outputFileName  = string.Format("out{0}", inputFilename);
                    string taskCommandLine = string.Format("cmd /c %AZ_BATCH_APP_PACKAGE_READWRITEFILE%\\ReadWriteFile.exe {0} {1}", inputFilename, outputFileName);

                    CloudTask task = new CloudTask(taskId, taskCommandLine);

                    // Set the resource files and output files for the task
                    task.ResourceFiles = new List <ResourceFile> {
                        inputFiles[i]
                    };
                    task.OutputFiles = new List <OutputFile>
                    {
                        new OutputFile(
                            filePattern: outputFileName,
                            destination: new OutputFileDestination(new OutputFileBlobContainerDestination(containerUrl: outputContainerSasUrl, path: outputFileName)),
                            uploadOptions: new OutputFileUploadOptions(OutputFileUploadCondition.TaskCompletion))
                    };
                    tasks.Add(task);
                }

                // Add all tasks to the job.
                batchClient.JobOperations.AddTask(JobId, tasks);

                // Monitor task success/failure, specifying a maximum amount of time to wait for the tasks to complete.
                TimeSpan timeout = TimeSpan.FromMinutes(30);
                Console.WriteLine("Monitoring all tasks for 'Completed' state, timeout in {0}...", timeout);

                IEnumerable <CloudTask> addedTasks = batchClient.JobOperations.ListTasks(JobId);

                batchClient.Utilities.CreateTaskStateMonitor().WaitAll(addedTasks, TaskState.Completed, timeout);

                Console.WriteLine("All tasks reached state Completed.");

                // Print task output
                Console.WriteLine();
                Console.WriteLine("Printing task output...");

                IEnumerable <CloudTask> completedtasks = batchClient.JobOperations.ListTasks(JobId);

                foreach (CloudTask task in completedtasks)
                {
                    string nodeId = String.Format(task.ComputeNodeInformation.ComputeNodeId);
                    Console.WriteLine("Task: {0}", task.Id);
                    Console.WriteLine("Node: {0}", nodeId);
                    Console.WriteLine("Standard out:");
                    Console.WriteLine(task.GetNodeFile(Constants.StandardOutFileName).ReadAsString());
                }

                // Clean up Batch resources (if the user so chooses)
                Console.WriteLine();
                Console.Write("Delete job? [yes] no: ");
                string response = Console.ReadLine().ToLower();
                if (response != "n" && response != "no")
                {
                    batchClient.JobOperations.DeleteJob(JobId);
                }
            }
        }
示例#13
0
        public async Task <(int retval, string readOnlySas)> StartBatch(bool stream = false, bool unittest = false)
        {
            string applicationPackage = string.Empty;

            if (string.IsNullOrWhiteSpace(cmdLine.BatchArgs.ApplicationPackage))
            {
                switch (cmdLine.BatchArgs.BatchPoolOs)
                {
                case OsType.Linux:
                    applicationPackage = "SqlBuildManagerLinux";
                    break;

                case OsType.Windows:
                default:
                    applicationPackage = "SqlBuildManagerWindows";
                    break;
                }
            }
            else
            {
                applicationPackage = cmdLine.BatchArgs.ApplicationPackage;
            }

            int cmdValid = ValidateBatchArgs(cmdLine, batchType);

            if (cmdValid != 0)
            {
                return(cmdValid, string.Empty);
            }


            //if extracting scripts from a platinum copy.. create the DACPAC here
            if (!string.IsNullOrWhiteSpace(cmdLine.DacPacArgs.PlatinumDbSource) && !string.IsNullOrWhiteSpace(cmdLine.DacPacArgs.PlatinumServerSource)) //using a platinum database as the source
            {
                log.LogInformation($"Extracting Platinum Dacpac from {cmdLine.DacPacArgs.PlatinumServerSource} : {cmdLine.DacPacArgs.PlatinumDbSource}");
                string dacpacName = Path.Combine(cmdLine.RootLoggingPath, cmdLine.DacPacArgs.PlatinumDbSource + ".dacpac");

                if (!DacPacHelper.ExtractDacPac(cmdLine.DacPacArgs.PlatinumDbSource, cmdLine.DacPacArgs.PlatinumServerSource, cmdLine.AuthenticationArgs.AuthenticationType, cmdLine.AuthenticationArgs.UserName, cmdLine.AuthenticationArgs.Password, dacpacName))
                {
                    log.LogError($"Error creating the Platinum dacpac from {cmdLine.DacPacArgs.PlatinumServerSource} : {cmdLine.DacPacArgs.PlatinumDbSource}");
                }
                cmdLine.DacPacArgs.PlatinumDacpac = dacpacName;
            }

            //Check for the platinum dacpac and configure it if necessary
            log.LogInformation("Validating database overrides");
            MultiDbData multiData;
            int?        myExitCode = 0;

            int tmpReturn = 0;

            //TODO: fix this for queue!!!!
            //Validate the override settings (not needed if --servicebusconnection is provided
            string[] errorMessages;
            int      tmpVal = Validation.ValidateAndLoadMultiDbData(cmdLine.MultiDbRunConfigFileName, cmdLine, out multiData, out errorMessages);

            if (tmpVal != 0)
            {
                log.LogError($"Unable to validate database config\r\n{string.Join("\r\n", errorMessages)}");
                return(tmpVal, string.Empty);
            }


            //Validate the platinum dacpac
            var tmpValReturn = Validation.ValidateAndLoadPlatinumDacpac(cmdLine, multiData);

            if (tmpValReturn.Item1 == (int)ExecutionReturn.DacpacDatabasesInSync)
            {
                return((int)ExecutionReturn.DacpacDatabasesInSync, string.Empty);
            }
            else if (tmpReturn != 0)
            {
                return(tmpValReturn.Item1, string.Empty);
            }

            BatchClient batchClient = null;

            //Get the batch and storage values
            string jobId, poolId, storageContainerName;

            (jobId, poolId, storageContainerName) = SetBatchJobAndStorageNames(cmdLine);
            log.LogInformation($"Using Azure Batch account: {cmdLine.ConnectionArgs.BatchAccountName} ({cmdLine.ConnectionArgs.BatchAccountUrl})");
            log.LogInformation($"Setting job id to: {jobId}");

            string readOnlySasToken = string.Empty;

            try
            {
                log.LogInformation($"Batch job start: {DateTime.Now}");
                Stopwatch timer = new Stopwatch();
                timer.Start();

                //Get storage ready
                BlobServiceClient          storageSvcClient = StorageManager.CreateStorageClient(cmdLine.ConnectionArgs.StorageAccountName, cmdLine.ConnectionArgs.StorageAccountKey);
                StorageSharedKeyCredential storageCreds     = new StorageSharedKeyCredential(cmdLine.ConnectionArgs.StorageAccountName, cmdLine.ConnectionArgs.StorageAccountKey);
                string containerSasToken = StorageManager.GetOutputContainerSasUrl(cmdLine.ConnectionArgs.StorageAccountName, storageContainerName, storageCreds, false);
                log.LogDebug($"Output write SAS token: {containerSasToken}");


                // Get a Batch client using account creds, and create the pool
                BatchSharedKeyCredentials cred = new BatchSharedKeyCredentials(cmdLine.ConnectionArgs.BatchAccountUrl, cmdLine.ConnectionArgs.BatchAccountName, cmdLine.ConnectionArgs.BatchAccountKey);
                batchClient = BatchClient.Open(cred);

                // Create a Batch pool, VM configuration, Windows Server image
                //bool success = CreateBatchPoolLegacy(batchClient, poolId, cmdLine.BatchArgs.BatchNodeCount,cmdLine.BatchArgs.BatchVmSize,cmdLine.BatchArgs.BatchPoolOs);
                bool success = await CreateBatchPool(cmdLine, poolId);


                // The collection of data files that are to be processed by the tasks
                List <string> inputFilePaths = new List <string>();
                if (!string.IsNullOrEmpty(cmdLine.DacPacArgs.PlatinumDacpac))
                {
                    inputFilePaths.Add(cmdLine.DacPacArgs.PlatinumDacpac);
                }
                if (!string.IsNullOrEmpty(cmdLine.BuildFileName))
                {
                    inputFilePaths.Add(cmdLine.BuildFileName);
                }
                if (!string.IsNullOrEmpty(cmdLine.MultiDbRunConfigFileName))
                {
                    inputFilePaths.Add(cmdLine.MultiDbRunConfigFileName);
                }
                if (!string.IsNullOrEmpty(this.queryFile))
                {
                    inputFilePaths.Add(this.queryFile);
                }


                //Get the list of DB targets and distribute across batch count
                var splitTargets = new List <string[]>();
                if (string.IsNullOrEmpty(cmdLine.ConnectionArgs.ServiceBusTopicConnectionString))
                {
                    int valRet = Validation.ValidateAndLoadMultiDbData(cmdLine.MultiDbRunConfigFileName, null, out MultiDbData multiDb, out errorMessages);
                    List <IEnumerable <(string, List <DatabaseOverride>)> > concurrencyBuckets = null;
                    if (valRet == 0)
                    {
                        if (cmdLine.ConcurrencyType == ConcurrencyType.Count)
                        {
                            //If it's just by count.. split evenly by the number of nodes
                            concurrencyBuckets = Concurrency.ConcurrencyByType(multiDb, cmdLine.BatchArgs.BatchNodeCount, cmdLine.ConcurrencyType);
                        }
                        else
                        {
                            //splitting by server is a little trickier, but run it and see what it does...
                            concurrencyBuckets = Concurrency.ConcurrencyByType(multiDb, cmdLine.Concurrency, cmdLine.ConcurrencyType);
                        }

                        //If we end up with fewer splits, then reduce the node count...
                        if (concurrencyBuckets.Count() < cmdLine.BatchArgs.BatchNodeCount)
                        {
                            log.LogWarning($"NOTE! The number of targets ({concurrencyBuckets.Count()}) is less than the requested node count ({cmdLine.BatchArgs.BatchNodeCount}). Changing the pool node count to {concurrencyBuckets.Count()}");
                            cmdLine.BatchArgs.BatchNodeCount = concurrencyBuckets.Count();
                        }
                        else if (concurrencyBuckets.Count() > cmdLine.BatchArgs.BatchNodeCount) //need to do some consolidating
                        {
                            log.LogWarning($"NOTE! When splitting by {cmdLine.ConcurrencyType.ToString()}, the number of targets ({concurrencyBuckets.Count()}) is greater than the requested node count ({cmdLine.BatchArgs.BatchNodeCount}). Will consolidate to fit within the number of nodes");
                            concurrencyBuckets = Concurrency.RecombineServersToFixedBucketCount(multiDb, cmdLine.BatchArgs.BatchNodeCount);
                        }
                    }
                    else
                    {
                        throw new ArgumentException($"Error parsing database targets. {String.Join(Environment.NewLine, errorMessages)}");
                    }
                    splitTargets = Concurrency.ConvertBucketsToConfigLines(concurrencyBuckets);

                    //Write out each split file
                    string rootPath = Path.GetDirectoryName(cmdLine.MultiDbRunConfigFileName);
                    for (int i = 0; i < splitTargets.Count; i++)
                    {
                        var tmpName = Path.Combine(rootPath, string.Format(baseTargetFormat, i));
                        File.WriteAllLines(tmpName, splitTargets[i]);
                        inputFilePaths.Add(tmpName);
                    }
                }

                // Upload the data files to Azure Storage. This is the data that will be processed by each of the tasks that are
                // executed on the compute nodes within the pool.
                List <ResourceFile> inputFiles = new List <ResourceFile>();

                foreach (string filePath in inputFilePaths)
                {
                    inputFiles.Add(StorageManager.UploadFileToBatchContainer(cmdLine.ConnectionArgs.StorageAccountName, storageContainerName, storageCreds, filePath));
                }

                //Create the individual command lines for each node
                IList <string> commandLines = CompileCommandLines(cmdLine, inputFiles, containerSasToken, cmdLine.BatchArgs.BatchNodeCount, jobId, cmdLine.BatchArgs.BatchPoolOs, applicationPackage, this.batchType);
                foreach (var s in commandLines)
                {
                    log.LogDebug(s);
                }

                try
                {
                    // Create a Batch job
                    log.LogInformation($"Creating job [{jobId}]...");
                    CloudJob job = batchClient.JobOperations.CreateJob();
                    job.Id = jobId;
                    job.PoolInformation = new PoolInformation {
                        PoolId = poolId
                    };
                    job.Commit();
                }
                catch (BatchException be)
                {
                    // Accept the specific error code JobExists as that is expected if the job already exists
                    if (be.RequestInformation?.BatchError?.Code == BatchErrorCodeStrings.JobExists)
                    {
                        log.LogInformation($"The job {jobId} already existed when we tried to create it");
                    }
                    else
                    {
                        throw; // Any other exception is unexpected
                    }
                }

                // Create a collection to hold the tasks that we'll be adding to the job
                if (splitTargets.Count != 0)
                {
                    log.LogInformation($"Adding {splitTargets.Count} tasks to job [{jobId}]...");
                }
                else if (!string.IsNullOrWhiteSpace(cmdLine.ConnectionArgs.ServiceBusTopicConnectionString))
                {
                    log.LogInformation($"Adding tasks to job [{jobId}]...");
                }

                List <CloudTask> tasks = new List <CloudTask>();

                // Create each of the tasks to process on each node
                for (int i = 0; i < commandLines.Count; i++)
                {
                    string taskId          = String.Format($"Task{i}");
                    string taskCommandLine = commandLines[i];

                    CloudTask task = new CloudTask(taskId, taskCommandLine);
                    task.ResourceFiles = inputFiles;
                    task.ApplicationPackageReferences = new List <ApplicationPackageReference>
                    {
                        new ApplicationPackageReference {
                            ApplicationId = applicationPackage
                        }
                    };
                    task.OutputFiles = new List <OutputFile>
                    {
                        new OutputFile(
                            filePattern: @"../std*.txt",
                            destination: new OutputFileDestination(new OutputFileBlobContainerDestination(containerUrl: containerSasToken, path: taskId)),
                            uploadOptions: new OutputFileUploadOptions(uploadCondition: OutputFileUploadCondition.TaskCompletion))    //,

                        //new OutputFile(
                        //    filePattern: @"../wd/*",
                        //    destination: new OutputFileDestination(new OutputFileBlobContainerDestination(containerUrl: containerSasToken, path: $"{taskId}/wd")),
                        //    uploadOptions: new OutputFileUploadOptions(uploadCondition: OutputFileUploadCondition.TaskCompletion)),

                        //new OutputFile(
                        //    filePattern: @"../wd/working/*",
                        //    destination: new OutputFileDestination(new OutputFileBlobContainerDestination(containerUrl: containerSasToken, path: $"{taskId}/working")),
                        //    uploadOptions: new OutputFileUploadOptions(uploadCondition: OutputFileUploadCondition.TaskCompletion))//,

                        //new OutputFile(
                        //   filePattern: @"../*.cfg",
                        //   destination: new OutputFileDestination(new OutputFileBlobContainerDestination(containerUrl: containerSasToken)),
                        //   uploadOptions: new OutputFileUploadOptions(uploadCondition: OutputFileUploadCondition.TaskCompletion))
                    };

                    tasks.Add(task);
                }

                // Add all tasks to the job.
                batchClient.JobOperations.AddTask(jobId, tasks);

                // Monitor task success/failure, specifying a maximum amount of time to wait for the tasks to complete.
                TimeSpan timeout = TimeSpan.FromMinutes(30);
                log.LogInformation($"Monitoring all tasks for 'Completed' state, timeout in {timeout}...");

                if (this.BatchProcessStartedEvent != null)
                {
                    this.BatchProcessStartedEvent(this, new BatchMonitorEventArgs(this.cmdLine, stream, unittest));
                }

                IEnumerable <CloudTask> addedTasks = batchClient.JobOperations.ListTasks(jobId);

                batchClient.Utilities.CreateTaskStateMonitor().WaitAll(addedTasks, TaskState.Completed, timeout);

                if (this.BatchExecutionCompletedEvent != null)
                {
                    this.BatchExecutionCompletedEvent(this, new BatchMonitorEventArgs(this.cmdLine, stream, unittest));
                }

                log.LogInformation("All tasks reached state Completed.");

                // Print task output
                log.LogInformation("Printing task output...");

                IEnumerable <CloudTask> completedtasks = batchClient.JobOperations.ListTasks(jobId);

                foreach (CloudTask task in completedtasks)
                {
                    string nodeId = String.Format(task.ComputeNodeInformation.ComputeNodeId);
                    log.LogInformation("---------------------------------");
                    log.LogInformation($"Task: {task.Id}");
                    log.LogInformation($"Node: {nodeId}");
                    log.LogInformation($"Exit Code: {task.ExecutionInformation.ExitCode}");
                    if (isDebug)
                    {
                        log.LogDebug("Standard out:");
                        log.LogDebug(task.GetNodeFile(Constants.StandardOutFileName).ReadAsString());
                    }
                    if (task.ExecutionInformation.ExitCode != 0)
                    {
                        myExitCode = task.ExecutionInformation.ExitCode;
                    }
                }
                log.LogInformation("---------------------------------");

                // Print out some timing info
                timer.Stop();
                log.LogInformation($"Batch job end: {DateTime.Now}");
                log.LogInformation($"Elapsed time: {timer.Elapsed}");


                // Clean up Batch resources
                if (cmdLine.BatchArgs.DeleteBatchJob)
                {
                    batchClient.JobOperations.DeleteJob(jobId);
                }
                if (cmdLine.BatchArgs.DeleteBatchPool)
                {
                    batchClient.PoolOperations.DeletePool(poolId);
                }

                SqlBuildManager.Logging.Threaded.Configure.CloseAndFlushAllLoggers();
                log.LogInformation("Consolidating log files");
                StorageManager.ConsolidateLogFiles(storageSvcClient, storageContainerName, inputFilePaths);

                if (batchType == BatchType.Query)
                {
                    StorageManager.CombineQueryOutputfiles(storageSvcClient, storageContainerName, this.outputFile);
                }

                //Finish the job out
                if (myExitCode == 0)
                {
                    log.LogInformation($"Setting job {jobId} status to Finished");
                    CloudJob j = batchClient.JobOperations.GetJob(jobId);
                    j.Terminate("Finished");
                }
                else
                {
                    log.LogInformation($"Setting job {jobId} status to exit code: {myExitCode}");
                    CloudJob j = batchClient.JobOperations.GetJob(jobId);
                    j.Terminate("Error");
                }


                readOnlySasToken = StorageManager.GetOutputContainerSasUrl(cmdLine.ConnectionArgs.StorageAccountName, storageContainerName, storageCreds, true);
                log.LogInformation($"Log files can be found here: {readOnlySasToken}");
                log.LogInformation("The read-only SAS token URL is valid for 7 days.");
                log.LogInformation("You can download \"Azure Storage Explorer\" from here: https://azure.microsoft.com/en-us/features/storage-explorer/");
                log.LogInformation("You can also get details on your Azure Batch execution from the \"Azure Batch Explorer\" found here: https://azure.github.io/BatchExplorer/");
            }
            catch (Exception exe)
            {
                log.LogError($"Exception when running batch job\r\n{exe.ToString()}");
                log.LogInformation($"Setting job {jobId} status to Failed");
                try
                {
                    CloudJob j = batchClient.JobOperations.GetJob(jobId);
                    j.Terminate("Failed");
                }
                catch { }
                myExitCode = 486;
            }
            finally
            {
                log.LogInformation("Batch complete");
                if (batchClient != null)
                {
                    batchClient.Dispose();
                }
            }

            if (myExitCode.HasValue)
            {
                log.LogInformation($"Exit Code: {myExitCode.Value}");
                return(myExitCode.Value, readOnlySasToken);
            }
            else
            {
                log.LogInformation($"Exit Code: {-100009}");
                return(-100009, readOnlySasToken);
            }
        }
示例#14
0
        static void Main(string[] args)
        {
            var batchCredentials = new BatchSharedKeyCredentials(
                Environment.GetEnvironmentVariable("AZURE_BATCH_ENDPOINT"),
                Environment.GetEnvironmentVariable("AZURE_BATCH_ACCOUNT"),
                Environment.GetEnvironmentVariable("AZURE_BATCH_ACCESS_KEY")
                );

            using (var batchClient = BatchClient.Open(batchCredentials))
            {
                // Create a (persistent) pool
                // (Production scenarios: can use auto pools for 'on demand' per-job capacity.)
                var poolExists = batchClient.PoolOperations.ListPools(
                    new ODATADetailLevel(filterClause: $"id eq '{CheatSheetPoolId}'", selectClause: "id")
                    ).Any();

                if (!poolExists)
                {
                    var pool = batchClient.PoolOperations.CreatePool(
                        poolId: CheatSheetPoolId,
                        virtualMachineSize: "small",
                        cloudServiceConfiguration: new CloudServiceConfiguration(osFamily: "4"),  // PaaS - use virtualMachineConfiguration overload for IaaS
                        targetDedicated: 1
                        );
                    pool.Commit();
                }

                // Create a job
                var job = batchClient.JobOperations.CreateJob(
                    "CheatSheet_" + DateTime.UtcNow.ToString("HHmmssfff"),
                    new PoolInformation {
                    PoolId = CheatSheetPoolId
                }
                    );
                job.Commit();
                job.Refresh();

                // Add some demanding and completely realistic work to the job
                // (Production scenarios: often done in a job manager task.)
                var task = new CloudTask(
                    id: "just-some-task",
                    commandline: "ping localhost"
                    );
                job.AddTask(task);
                task = job.GetTask(task.Id);  // quirks, we has them

                // Wait for the tasks to complete
                var taskStateMonitor = batchClient.Utilities.CreateTaskStateMonitor();
                taskStateMonitor.WaitAll(new[] { task }, TaskState.Completed, TimeSpan.FromMinutes(10));

                // Terminate the job when there's no more work to do
                // (Production scenarios: can use auto termination option.)
                job.Terminate(terminateReason: "PingedAllTheLocalhosts");

                // Get the result
                // (Production scenarios: often persist key outputs in blob storage.)
                var stdoutReference = task.GetNodeFile("stdout.txt");
                var stdout          = stdoutReference.ReadAsString();

                Console.WriteLine(stdout);
            }
        }