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); }
/// <summary> /// Waits for the specified task to complete /// </summary> public static void WaitForTaskCompletion(BatchController controller, BatchAccountContext context, string jobId, string taskId) { BatchClient client = new BatchClient(controller.BatchManagementClient, controller.ResourceManagementClient); ListTaskOptions options = new ListTaskOptions(context, jobId, null) { TaskId = taskId }; IEnumerable <PSCloudTask> tasks = client.ListTasks(options); // Save time by not waiting during playback scenarios if (HttpMockServer.Mode == HttpRecorderMode.Record) { TaskStateMonitor monitor = context.BatchOMClient.Utilities.CreateTaskStateMonitor(); monitor.WaitAll(tasks.Select(t => t.omObject), TaskState.Completed, TimeSpan.FromMinutes(10), null); } }
/// <summary> /// Create a job and add two simple tasks to it. Wait for completion using the Task state monitor /// </summary> private static void AddJobTwoTasks(BatchClient client, string sharedPoolId) { string jobId = CreateJobId("HelloWorldTwoTaskJob"); Console.WriteLine("Creating job: " + jobId); CloudJob boundJob = CreateBoundJob(client.JobOperations, sharedPoolId, jobId); // add 2 quick tasks. Each task within a job must have a unique ID List <CloudTask> tasksToRun = new List <CloudTask>(2); tasksToRun.Add(new CloudTask("task1", "hostname")); tasksToRun.Add(new CloudTask("task2", "cmd /c dir /s")); client.JobOperations.AddTask(boundJob.Id, tasksToRun); Console.WriteLine("Waiting for all tasks to complete on Job: {0} ...", boundJob.Id); //We use the task state monitor to monitor the state of our tasks -- in this case we will wait for them all to complete. TaskStateMonitor taskStateMonitor = client.Utilities.CreateTaskStateMonitor(); // blocking wait on the list of tasks until all tasks reach completed state or the timeout is reached. // If the pool is being resized then enough time is needed for the VMs to reach the idle state in order // for tasks to run on them. IPagedEnumerable <CloudTask> ourTasks = boundJob.ListTasks(); bool timedOut = taskStateMonitor.WaitAll(ourTasks, TaskState.Completed, new TimeSpan(0, 10, 0)); if (timedOut) { throw new TimeoutException("Timed out waiting for tasks"); } // dump task output foreach (CloudTask t in ourTasks) { Console.WriteLine("Task " + t.Id); Console.WriteLine("stdout:\n" + t.GetNodeFile(Constants.StandardOutFileName).ReadAsString()); Console.WriteLine("\nstderr:\n" + t.GetNodeFile(Constants.StandardErrorFileName).ReadAsString()); } //Delete the job to ensure the tasks are cleaned up Console.WriteLine("Deleting job: {0}", boundJob.Id); client.JobOperations.DeleteJob(boundJob.Id); }
public void TestContainerTask() { void test() { using BatchClient client = TestUtilities.OpenBatchClient(TestUtilities.GetCredentialsFromEnvironment()); string jobId = "ContainerJob" + TestUtilities.GetMyName(); try { CloudJob job = client.JobOperations.CreateJob(jobId, new PoolInformation { PoolId = poolFixture.PoolId }); job.Commit(); CloudTask newTask = new CloudTask("a", "cat /etc/centos-release") { ContainerSettings = new TaskContainerSettings("centos") }; client.JobOperations.AddTask(jobId, newTask); IPagedEnumerable <CloudTask> tasks = client.JobOperations.ListTasks(jobId); TaskStateMonitor monitor = client.Utilities.CreateTaskStateMonitor(); monitor.WaitAll(tasks, TaskState.Completed, TimeSpan.FromMinutes(7)); CloudTask task = tasks.Single(); task.Refresh(); Assert.Equal("ContainerPoolNotSupported", task.ExecutionInformation.FailureInformation.Code); } finally { TestUtilities.DeleteJobIfExistsAsync(client, jobId).Wait(); } } SynchronizationContextHelper.RunTest(test, TimeSpan.FromMinutes(10)); }
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(); } } }
public void TestGetNodeFileByTask() { Action test = () => { using (BatchClient batchCli = TestUtilities.OpenBatchClientAsync(TestUtilities.GetCredentialsFromEnvironment()).Result) { JobOperations jobOperations = batchCli.JobOperations; string jobId = Constants.DefaultConveniencePrefix + TestUtilities.GetMyName() + "-" + nameof(TestGetNodeFileByTask); try { // // Create the job // CloudJob job = jobOperations.CreateJob(jobId, new PoolInformation()); job.PoolInformation = new PoolInformation() { PoolId = this.poolFixture.PoolId }; this.testOutputHelper.WriteLine("Initial job schedule commit()"); job.Commit(); // // Wait for the job // this.testOutputHelper.WriteLine("Waiting for job"); CloudJob boundJob = jobOperations.GetJob(jobId); // // Add task to the job // const string taskId = "T1"; const string taskMessage = "This is a test"; this.testOutputHelper.WriteLine("Adding task: {0}", taskId); CloudTask task = new CloudTask(taskId, string.Format("cmd /c echo {0}", taskMessage)); boundJob.AddTask(task); // // Wait for the task to complete // this.testOutputHelper.WriteLine("Waiting for the task to complete"); Utilities utilities = batchCli.Utilities; TaskStateMonitor taskStateMonitor = utilities.CreateTaskStateMonitor(); //Wait for the task state to be running taskStateMonitor.WaitAll( jobOperations.ListTasks(jobId), TaskState.Completed, TimeSpan.FromSeconds(30)); //Download the data this.testOutputHelper.WriteLine("Downloading the stdout for the file"); NodeFile file = jobOperations.GetNodeFile(jobId, taskId, Constants.StandardOutFileName); string data = file.ReadAsString(); this.testOutputHelper.WriteLine("Data: {0}", data); Assert.Contains(taskMessage, data); // Download the data again using the JobOperations read file content helper data = batchCli.JobOperations.CopyNodeFileContentToString(jobId, taskId, Constants.StandardOutFileName); this.testOutputHelper.WriteLine("Data: {0}", data); Assert.Contains(taskMessage, data); } finally { jobOperations.DeleteJob(jobId); } } }; SynchronizationContextHelper.RunTest(test, TestTimeout); }
public void Bug1480491NodeFileFileProperties() { Action test = () => { using (BatchClient batchCli = TestUtilities.OpenBatchClientAsync(TestUtilities.GetCredentialsFromEnvironment()).Result) { string jobId = "Bug1480491Job-" + TestUtilities.GetMyName(); try { const string taskId = "hiWorld"; // // Create the job // CloudJob unboundJob = batchCli.JobOperations.CreateJob(jobId, new PoolInformation()); unboundJob.PoolInformation.PoolId = this.poolFixture.PoolId; unboundJob.Commit(); CloudJob boundJob = batchCli.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)); const int expectedFileSize = 13; //Magic number based on output generated by the task // // NodeFile by task // NodeFile file = batchCli.JobOperations.GetNodeFile(jobId, taskId, Constants.StandardOutFileName); this.testOutputHelper.WriteLine("File {0} has content length: {1}", Constants.StandardOutFileName, file.Properties.ContentLength); this.testOutputHelper.WriteLine("File {0} has content type: {1}", Constants.StandardOutFileName, file.Properties.ContentType); this.testOutputHelper.WriteLine("File {0} has creation time: {1}", Constants.StandardOutFileName, file.Properties.CreationTime); this.testOutputHelper.WriteLine("File {0} has last modified time: {1}", Constants.StandardOutFileName, file.Properties.LastModified); Assert.Equal(expectedFileSize, file.Properties.ContentLength); Assert.Equal("text/plain", file.Properties.ContentType); // // NodeFile by node // CloudTask boundTask = boundJob.GetTask(taskId); string computeNodeId = boundTask.ComputeNodeInformation.AffinityId.Split(':')[1]; ComputeNode computeNode = batchCli.PoolOperations.GetComputeNode(this.poolFixture.PoolId, computeNodeId); this.testOutputHelper.WriteLine("Task ran on compute node: {0}", computeNodeId); List <NodeFile> files = computeNode.ListNodeFiles(recursive: true).ToList(); foreach (NodeFile nodeFile in files) { this.testOutputHelper.WriteLine("Found file: {0}", nodeFile.Path); } string filePathToGet = string.Format("workitems/{0}/{1}/{2}/{3}", jobId, "job-1", taskId, Constants.StandardOutFileName); file = computeNode.GetNodeFile(filePathToGet); this.testOutputHelper.WriteLine("File {0} has content length: {1}", filePathToGet, file.Properties.ContentLength); this.testOutputHelper.WriteLine("File {0} has content type: {1}", filePathToGet, file.Properties.ContentType); this.testOutputHelper.WriteLine("File {0} has creation time: {1}", filePathToGet, file.Properties.CreationTime); this.testOutputHelper.WriteLine("File {0} has last modified time: {1}", filePathToGet, file.Properties.LastModified); Assert.Equal(expectedFileSize, file.Properties.ContentLength); Assert.Equal("text/plain", file.Properties.ContentType); } finally { batchCli.JobOperations.DeleteJob(jobId); } } }; SynchronizationContextHelper.RunTest(test, TestTimeout); }
public void Bug1480489NodeFileMissingIsDirectory() { Action test = () => { using (BatchClient batchCli = TestUtilities.OpenBatchClientAsync(TestUtilities.GetCredentialsFromEnvironment()).Result) { string jobId = "Bug1480489Job-" + TestUtilities.GetMyName(); try { // here we show how to use an unbound Job + Commit() to run millions of Tasks CloudJob unboundJob = batchCli.JobOperations.CreateJob(jobId, new PoolInformation() { PoolId = this.poolFixture.PoolId }); unboundJob.Commit(); // Open the new Job as bound. CloudJob boundJob = batchCli.JobOperations.GetJob(jobId); CloudTask myTask = new CloudTask(id: "Bug1480489Task", commandline: @"md Bug1480489Directory"); // add the task to the job boundJob.AddTask(myTask); // 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(3)); CloudTask myCompletedTask = new List <CloudTask>(boundJob.ListTasks(null))[0]; string stdOut = myCompletedTask.GetNodeFile(Constants.StandardOutFileName).ReadAsString(); string stdErr = myCompletedTask.GetNodeFile(Constants.StandardErrorFileName).ReadAsString(); this.testOutputHelper.WriteLine("TaskId: " + myCompletedTask.Id); this.testOutputHelper.WriteLine("StdOut: "); this.testOutputHelper.WriteLine(stdOut); this.testOutputHelper.WriteLine("StdErr: "); this.testOutputHelper.WriteLine(stdErr); this.testOutputHelper.WriteLine("Task Files:"); bool foundAtLeastOneDir = false; foreach (NodeFile curFile in myCompletedTask.ListNodeFiles()) { this.testOutputHelper.WriteLine(" Filepath: " + curFile.Path); this.testOutputHelper.WriteLine(" IsDirectory: " + curFile.IsDirectory.ToString()); // turns out wd is created for each task so use it as sentinal if (curFile.Path.Equals("wd") && curFile.IsDirectory.HasValue && curFile.IsDirectory.Value) { foundAtLeastOneDir = true; } } Assert.True(foundAtLeastOneDir); } finally { TestUtilities.DeleteJobIfExistsAsync(batchCli, jobId).Wait(); } } }; SynchronizationContextHelper.RunTest(test, TestTimeout); }
public void Bug230385SupportDeleteNodeFileByTask() { Action test = () => { using (BatchClient batchCli = TestUtilities.OpenBatchClientAsync(TestUtilities.GetCredentialsFromEnvironment()).Result) { string jobId = "Bug230285Job-" + TestUtilities.GetMyName(); try { const string taskId = "hiWorld"; const string directoryCreationTaskId1 = "dirTask1"; const string directoryCreationTaskId2 = "dirTask2"; const string directoryNameOne = "Foo"; const string directoryNameTwo = "Bar"; const string directory2PathOnNode = "wd/" + directoryNameTwo; // // Create the job // CloudJob unboundJob = batchCli.JobOperations.CreateJob(jobId, new PoolInformation()); unboundJob.PoolInformation.PoolId = this.poolFixture.PoolId; unboundJob.Commit(); CloudJob boundJob = batchCli.JobOperations.GetJob(jobId); CloudTask myTask = new CloudTask(taskId, "cmd /c echo hello world"); CloudTask directoryCreationTask1 = new CloudTask(directoryCreationTaskId1, string.Format("cmd /c mkdir {0} && echo test > {0}/testfile.txt", directoryNameOne)); CloudTask directoryCreationTask2 = new CloudTask(directoryCreationTaskId2, string.Format("cmd /c mkdir {0} && echo test > {0}/testfile.txt", directoryNameTwo)); boundJob.AddTask(myTask); boundJob.AddTask(directoryCreationTask1); boundJob.AddTask(directoryCreationTask2); 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)); // // NodeFile delete // //Delete single file NodeFile file = batchCli.JobOperations.GetNodeFile(jobId, taskId, Constants.StandardOutFileName); file.Delete(); //Ensure delete succeeded TestUtilities.AssertThrows <BatchException>(() => batchCli.JobOperations.GetNodeFile(jobId, taskId, Constants.StandardOutFileName)); //Delete directory NodeFile directory = batchCli.JobOperations.ListNodeFiles(jobId, directoryCreationTaskId1, recursive: true).First(item => item.Path.Contains(directoryNameOne)); Assert.True(directory.IsDirectory); TestUtilities.AssertThrows <BatchException>(() => directory.Delete(recursive: false)); directory.Delete(recursive: true); Assert.Null(batchCli.JobOperations.ListNodeFiles(jobId, directoryCreationTaskId1, recursive: true).FirstOrDefault(item => item.Path.Contains(directoryNameOne))); // // JobScheduleOperations delete task file // batchCli.JobOperations.GetNodeFile(jobId, taskId, Constants.StandardErrorFileName); batchCli.JobOperations.DeleteNodeFile(jobId, taskId, Constants.StandardErrorFileName); //Ensure delete succeeded TestUtilities.AssertThrows <BatchException>(() => batchCli.JobOperations.GetNodeFile(jobId, taskId, Constants.StandardErrorFileName)); //Delete directory directory = batchCli.JobOperations.ListNodeFiles(jobId, directoryCreationTaskId2, recursive: true).First(item => item.Path.Contains(directoryNameTwo)); Assert.True(directory.IsDirectory); TestUtilities.AssertThrows <BatchException>(() => batchCli.JobOperations.DeleteNodeFile(jobId, directoryCreationTaskId2, directory2PathOnNode, recursive: false)); batchCli.JobOperations.DeleteNodeFile(jobId, directoryCreationTaskId2, directory2PathOnNode, recursive: true); Assert.Null(batchCli.JobOperations.ListNodeFiles(jobId, directoryCreationTaskId2, recursive: true).FirstOrDefault(item => item.Path.Contains(directoryNameTwo))); } finally { TestUtilities.DeleteJobIfExistsAsync(batchCli, jobId).Wait(); } } }; SynchronizationContextHelper.RunTest(test, TestTimeout); }
public void Bug2329884_ComputeNodeRecentTasksAndComputeNodeError() { Action test = () => { using (BatchClient batchCli = TestUtilities.OpenBatchClientAsync(TestUtilities.GetCredentialsFromEnvironment()).Result) { string jobId = "Bug2329884Job-" + TestUtilities.GetMyName(); Protocol.RequestInterceptor interceptor = null; try { const string taskId = "hiWorld"; // // Create the job // CloudJob unboundJob = batchCli.JobOperations.CreateJob(jobId, new PoolInformation()); unboundJob.PoolInformation.PoolId = this.poolFixture.PoolId; unboundJob.Commit(); CloudJob boundJob = batchCli.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, new TimeSpan(0, 3 /*min*/, 0)); CloudTask boundTask = boundJob.GetTask(taskId); //Since the compute node name comes back as "Node:<computeNodeId>" we need to split on : to get the actual compute node name string computeNodeId = boundTask.ComputeNodeInformation.AffinityId.Split(':')[1]; // // Check recent tasks // ComputeNode computeNode = batchCli.PoolOperations.GetComputeNode(this.poolFixture.PoolId, computeNodeId); this.testOutputHelper.WriteLine("Recent tasks:"); foreach (TaskInformation recentTask in computeNode.RecentTasks) { this.testOutputHelper.WriteLine("Compute node has recent task Job: {0}, Task: {1}, State: {2}, Subtask: {3}", recentTask.JobId, recentTask.TaskId, recentTask.TaskState, recentTask.SubtaskId); } TaskInformation myTaskInfo = computeNode.RecentTasks.First(taskInfo => taskInfo.JobId.Equals( jobId, StringComparison.InvariantCultureIgnoreCase) && taskInfo.TaskId.Equals(taskId, StringComparison.InvariantCultureIgnoreCase)); Assert.Equal(TaskState.Completed, myTaskInfo.TaskState); Assert.NotNull(myTaskInfo.ExecutionInformation); Assert.Equal(0, myTaskInfo.ExecutionInformation.ExitCode); // // Check compute node Error // const string expectedErrorCode = "TestErrorCode"; const string expectedErrorMessage = "Test error message"; const string nvpValue = "Test"; //We use mocking to return a fake compute node object here to test Compute Node Error because we cannot force one easily interceptor = new Protocol.RequestInterceptor((req => { if (req is ComputeNodeGetBatchRequest) { var typedRequest = req as ComputeNodeGetBatchRequest; typedRequest.ServiceRequestFunc = (token) => { var response = new AzureOperationResponse <Protocol.Models.ComputeNode, Protocol.Models.ComputeNodeGetHeaders>(); List <Protocol.Models.ComputeNodeError> errors = new List <Protocol.Models.ComputeNodeError>(); //Generate first Compute Node Error List <Protocol.Models.NameValuePair> nvps = new List <Protocol.Models.NameValuePair>(); nvps.Add(new Protocol.Models.NameValuePair() { Name = nvpValue, Value = nvpValue }); Protocol.Models.ComputeNodeError error1 = new Protocol.Models.ComputeNodeError(); error1.Code = expectedErrorCode; error1.Message = expectedErrorMessage; error1.ErrorDetails = nvps; errors.Add(error1); //Generate second Compute Node Error nvps = new List <Protocol.Models.NameValuePair>(); nvps.Add(new Protocol.Models.NameValuePair() { Name = nvpValue, Value = nvpValue }); Protocol.Models.ComputeNodeError error2 = new Protocol.Models.ComputeNodeError(); error2.Code = expectedErrorCode; error2.Message = expectedErrorMessage; error2.ErrorDetails = nvps; errors.Add(error2); Protocol.Models.ComputeNode protoComputeNode = new Protocol.Models.ComputeNode(); protoComputeNode.Id = computeNodeId; protoComputeNode.State = Protocol.Models.ComputeNodeState.Idle; protoComputeNode.Errors = errors; response.Body = protoComputeNode; return(Task.FromResult(response)); }; } })); batchCli.PoolOperations.CustomBehaviors.Add(interceptor); computeNode = batchCli.PoolOperations.GetComputeNode(this.poolFixture.PoolId, computeNodeId); Assert.Equal(computeNodeId, computeNode.Id); Assert.NotNull(computeNode.Errors); Assert.Equal(2, computeNode.Errors.Count()); foreach (ComputeNodeError computeNodeError in computeNode.Errors) { Assert.Equal(expectedErrorCode, computeNodeError.Code); Assert.Equal(expectedErrorMessage, computeNodeError.Message); Assert.NotNull(computeNodeError.ErrorDetails); Assert.Equal(1, computeNodeError.ErrorDetails.Count()); Assert.Contains(nvpValue, computeNodeError.ErrorDetails.First().Name); } } finally { batchCli.JobOperations.DeleteJob(jobId); } } }; SynchronizationContextHelper.RunTest(test, TestTimeout); }
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); }
public void LongRunning_Bug1965363Wat7OSVersionFeaturesQuickJobWithAutoPool() { void test() { using BatchClient batchCli = TestUtilities.OpenBatchClient(TestUtilities.GetCredentialsFromEnvironment()); string jobId = "Bug1965363Job-" + TestUtilities.GetMyName(); try { PoolInformation poolInfo = new PoolInformation() { AutoPoolSpecification = new AutoPoolSpecification() { PoolLifetimeOption = PoolLifetimeOption.Job, PoolSpecification = new PoolSpecification() { CloudServiceConfiguration = new CloudServiceConfiguration(PoolFixture.OSFamily), VirtualMachineSize = PoolFixture.VMSize, TargetDedicatedComputeNodes = 1 } } }; CloudJob unboundJob = batchCli.JobOperations.CreateJob(jobId, poolInfo); testOutputHelper.WriteLine("Commiting quickjob"); unboundJob.Commit(); CloudTask task = new CloudTask("Bug1965363Wat7OSVersionFeaturesQuickJobWithAutoPoolTask", "cmd /c echo Bug1965363"); CloudJob boundJob = batchCli.JobOperations.GetJob(jobId); boundJob.AddTask(task); testOutputHelper.WriteLine("Getting pool name: {0}", boundJob.ExecutionInformation.PoolId); CloudPool boundPool = batchCli.PoolOperations.GetPool(boundJob.ExecutionInformation.PoolId); TaskStateMonitor tsm = batchCli.Utilities.CreateTaskStateMonitor(); ODATAMonitorControl odControl = new ODATAMonitorControl(); // we know that the autopool compute nodes will take a long time to become scheduleable so we slow down polling/spam odControl.DelayBetweenDataFetch = TimeSpan.FromSeconds(5); testOutputHelper.WriteLine("Invoking TaskStateMonitor"); tsm.WaitAll( boundJob.ListTasks(), TaskState.Completed, TimeSpan.FromMinutes(15), odControl, new[] { // spam/logging interceptor new Protocol.RequestInterceptor((x) => { testOutputHelper.WriteLine("Issuing request type: " + x.GetType().ToString()); // print out the compute node states... we are actually waiting on the compute nodes List <ComputeNode> allComputeNodes = boundPool.ListComputeNodes().ToList(); testOutputHelper.WriteLine(" #comnpute nodes: " + allComputeNodes.Count); allComputeNodes.ForEach((icn) => { testOutputHelper.WriteLine(" computeNode.id: " + icn.Id + ", state: " + icn.State); }); testOutputHelper.WriteLine(""); }) }); // confirm the task ran by inspecting the stdOut string stdOut = boundJob.ListTasks().ToList()[0].GetNodeFile(Constants.StandardOutFileName).ReadAsString(); Assert.Contains("Bug1965363", stdOut); } finally { TestUtilities.DeleteJobIfExistsAsync(batchCli, jobId).Wait(); } } SynchronizationContextHelper.RunTest(test, LongTestTimeout); }
public static void HelloWorld( BatchClient batchCli, ITestOutputHelper testOutputHelper, CloudPool sharedPool, out string jobId, out string taskId, bool deleteJob = true, bool isLinux = false) { jobId = "HelloWorldJob-" + GetMyName() + "-" + GetTimeStamp(); try { // here we show how to use an unbound Job + Commit() to run a simple "Hello World" task // get an empty unbound Job CloudJob quickJob = batchCli.JobOperations.CreateJob(); quickJob.Id = jobId; quickJob.PoolInformation = new PoolInformation() { PoolId = sharedPool.Id }; // Commit Job quickJob.Commit(); // get an empty unbound Task taskId = "dwsHelloWorldTask"; const string winPaasHWTaskCmdLine = "cmd /c echo Hello World"; const string linuxIaasHWTaskCmdLine = "echo Hello World"; string winnerTaskCmdLine = isLinux ? linuxIaasHWTaskCmdLine : winPaasHWTaskCmdLine; CloudTask hwTask = new CloudTask(id: taskId, commandline: winnerTaskCmdLine); // Open the new Job as bound. CloudJob boundJob = batchCli.JobOperations.GetJob(jobId); // add Task to Job boundJob.AddTask(hwTask); // wait for the task to complete Utilities utilities = batchCli.Utilities; TaskStateMonitor taskStateMonitor = utilities.CreateTaskStateMonitor(); taskStateMonitor.WaitAll( boundJob.ListTasks(), TaskState.Completed, TimeSpan.FromMinutes(3)); CloudTask myCompletedTask = new List <CloudTask>(boundJob.ListTasks(null))[0]; string stdOut = myCompletedTask.GetNodeFile(Constants.StandardOutFileName).ReadAsString(); string stdErr = myCompletedTask.GetNodeFile(Constants.StandardErrorFileName).ReadAsString(); // confirm that stdout includes correct value Assert.Contains("Hello World", stdOut); testOutputHelper.WriteLine("StdOut: "); testOutputHelper.WriteLine(stdOut); testOutputHelper.WriteLine("StdErr: "); testOutputHelper.WriteLine(stdErr); } finally { // delete the job to free the Pool compute nodes. if (deleteJob) { TestUtilities.DeleteJobIfExistsAsync(batchCli, jobId).Wait(); } } }
public async Task RunTaskAndUploadFiles_FilesAreSuccessfullyUploaded() { async Task test() { using BatchClient batchCli = TestUtilities.OpenBatchClient(TestUtilities.GetCredentialsFromEnvironment()); string jobId = "RunTaskAndUploadFiles-" + TestUtilities.GetMyName(); string containerName = "runtaskanduploadfiles"; StagingStorageAccount storageAccount = TestUtilities.GetStorageCredentialsFromEnvironment(); BlobServiceClient blobClient = BlobUtilities.GetBlobServiceClient(storageAccount); BlobContainerClient containerClient = BlobUtilities.GetBlobContainerClient(containerName, blobClient, storageAccount); try { // Create container and writeable SAS containerClient.CreateIfNotExists(); string sasUri = BlobUtilities.GetWriteableSasUri(containerClient, storageAccount); CloudJob createJob = batchCli.JobOperations.CreateJob(jobId, new PoolInformation { PoolId = poolFixture.PoolId }); createJob.Commit(); const string blobPrefix = "foo/bar"; const string taskId = "simpletask"; OutputFileBlobContainerDestination containerDestination = new OutputFileBlobContainerDestination(sasUri, blobPrefix); containerDestination.UploadHeaders = new List <HttpHeader> { new HttpHeader("x-ms-blob-content-type", "test-type") }; OutputFileDestination destination = new OutputFileDestination(containerDestination); OutputFileUploadOptions uploadOptions = new OutputFileUploadOptions(uploadCondition: OutputFileUploadCondition.TaskCompletion); CloudTask unboundTask = new CloudTask(taskId, "echo test") { OutputFiles = new List <OutputFile> { new OutputFile(@"../*.txt", destination, uploadOptions) } }; batchCli.JobOperations.AddTask(jobId, unboundTask); IPagedEnumerable <CloudTask> tasks = batchCli.JobOperations.ListTasks(jobId); TaskStateMonitor monitor = batchCli.Utilities.CreateTaskStateMonitor(); monitor.WaitAll(tasks, TaskState.Completed, TimeSpan.FromMinutes(1)); // Ensure that the correct files got uploaded List <BlobItem> blobs = containerClient.GetAllBlobs(); Assert.Equal(4, blobs.Count()); //There are 4 .txt files created, stdout, stderr, fileuploadout, and fileuploaderr foreach (BlobItem blob in blobs) { Assert.StartsWith(blobPrefix, blob.Name); Assert.Equal("test-type", blob.Properties.ContentType); // Ensure test Upload header was applied to blob. } } finally { await TestUtilities.DeleteJobIfExistsAsync(batchCli, jobId).ConfigureAwait(false); containerClient.DeleteIfExists(); } } await SynchronizationContextHelper.RunTestAsync(test, TestTimeout); }
public void TestOMJobReleaseSchedulingError() { string jobId = "TestOMJobReleaseSchedulingError-" + CraftTimeString() + "-" + TestUtilities.GetMyName(); Action test = () => { using (BatchClient client = TestUtilities.OpenBatchClient(TestUtilities.GetCredentialsFromEnvironment())) { try { // create job schedule with prep that succeeds and release the triggers scheduling error { PoolInformation poolInfo = new PoolInformation() { PoolId = this.poolFixture.PoolId }; CloudJob unboundJob = client.JobOperations.CreateJob(jobId, poolInfo); // add the jobPrep task to the job { JobPreparationTask prep = new JobPreparationTask("cmd /c echo the quick job prep jumped over the..."); unboundJob.JobPreparationTask = prep; prep.WaitForSuccess = false; // we don't really care but why not set this } // add a jobRelease task to the job { JobReleaseTask relTask = new JobReleaseTask("cmd /c echo Job Release Task"); unboundJob.JobReleaseTask = relTask; ResourceFile[] badResFiles = { ResourceFile.FromUrl("https://not.a.domain.invalid/file", "bob.txt") }; relTask.ResourceFiles = badResFiles; relTask.Id = "jobRelease"; } // add the job to the service unboundJob.Commit(); } // add a trivial task to force the JP client.JobOperations.AddTask(jobId, new CloudTask("ForceJobPrep", "cmd /c echo TestOMJobReleaseSchedulingError")); // wait for the task to complete TaskStateMonitor tsm = client.Utilities.CreateTaskStateMonitor(); tsm.WaitAll( client.JobOperations.ListTasks(jobId), TaskState.Completed, TimeSpan.FromMinutes(10), additionalBehaviors: new[] { // spam/logging interceptor new Protocol.RequestInterceptor((x) => { this.testOutputHelper.WriteLine("Issuing request type: " + x.GetType().ToString()); // print out the compute node states... we are actually waiting on the compute nodes List <ComputeNode> allComputeNodes = client.PoolOperations.ListComputeNodes(this.poolFixture.PoolId).ToList(); this.testOutputHelper.WriteLine(" #compute nodes: " + allComputeNodes.Count); allComputeNodes.ForEach((icn) => { this.testOutputHelper.WriteLine(" computeNode.id: " + icn.Id + ", state: " + icn.State); }); this.testOutputHelper.WriteLine(""); }) } ); // ok terminate job to trigger job release client.JobOperations.TerminateJob(jobId, "BUG: Server will throw 500 if I don't provide reason"); // the victim compute node. pool should have size 1. List <ComputeNode> computeNodes = client.PoolOperations.ListComputeNodes(this.poolFixture.PoolId).ToList(); Assert.Single(computeNodes); // now we have a job that should be trying to run the JP // poll for the JP to have been run, and it must have a scheduling error bool releaseNotCompleted = true; // gotta poll to find out when the jp has been run while (releaseNotCompleted) { List <JobPreparationAndReleaseTaskExecutionInformation> jrStatusList = client.JobOperations.ListJobPreparationAndReleaseTaskStatus(jobId).ToList(); JobPreparationAndReleaseTaskExecutionInformation prepAndReleaseStatus = jrStatusList.FirstOrDefault(); if (prepAndReleaseStatus != null && null != prepAndReleaseStatus.JobReleaseTaskExecutionInformation) { if (JobReleaseTaskState.Completed == prepAndReleaseStatus.JobReleaseTaskExecutionInformation.State) { releaseNotCompleted = false; // we see a JP has been run // now assert the failure info Assert.NotNull(prepAndReleaseStatus); Assert.NotNull(prepAndReleaseStatus.JobReleaseTaskExecutionInformation.FailureInformation); Assert.Equal(TaskExecutionResult.Failure, prepAndReleaseStatus.JobReleaseTaskExecutionInformation.Result); // spew the failure info this.OutputFailureInfo(prepAndReleaseStatus.JobReleaseTaskExecutionInformation.FailureInformation); } } Thread.Sleep(2000); this.testOutputHelper.WriteLine("Job Release tasks still running (waiting for blob dl to timeout)."); } } finally { client.JobOperations.DeleteJob(jobId); } } }; SynchronizationContextHelper.RunTest(test, LongTestTimeout); }
/// <summary> /// calls the two new get-status REST APIs and asserts their values /// /// 1: add a single quick task (quick because we don't need it to run very long) /// 2: this forces a victim compute node to run the JobPrep /// 3: poll for this compute node, ignore others (sharedPool.size probably > 1) /// 4: check status of JobPrep /// 4a: assert as many values as makes sense... this is not a retry test /// 5: JobPrep succeeds, task runs /// 6: poll for JobRelease.. it is long running /// 7: assert as many values as makes sense. /// </summary> /// <param name="batchCli"></param> private void TestGetPrepReleaseStatusCalls(BatchClient batchCli, CloudJobSchedule boundJobSchedule, string sharedPool, IEnumerable <ResourceFile> correctResFiles) { // need this often enough lets just pull it out string jobId = boundJobSchedule.ExecutionInformation.RecentJob.Id; PoolOperations poolOps = batchCli.PoolOperations; JobScheduleOperations jobScheduleOperations = batchCli.JobScheduleOperations; { DateTime beforeJobPrepRuns = DateTime.UtcNow; // used to test start time // need a task to force JobPrep CloudTask sillyTask = new CloudTask("forceJobPrep", "cmd /c hostname"); // add the task batchCli.JobOperations.AddTask(jobId, sillyTask); bool keepLooking = true; while (keepLooking) { this.testOutputHelper.WriteLine("Waiting for task to be scheduled."); foreach (CloudTask curTask in batchCli.JobOperations.GetJob(jobId).ListTasks()) { if (curTask.State != TaskState.Active) { keepLooking = false; break; } } Thread.Sleep(1000); } List <JobPreparationAndReleaseTaskExecutionInformation> jobPrepStatusList = new List <JobPreparationAndReleaseTaskExecutionInformation>(); while (jobPrepStatusList.Count == 0) { jobPrepStatusList = batchCli.JobOperations.ListJobPreparationAndReleaseTaskStatus(jobId).ToList(); } JobPreparationAndReleaseTaskExecutionInformation jptei = jobPrepStatusList.First(); ComputeNode victimComputeNodeRunningPrepAndRelease = poolOps.GetComputeNode(sharedPool, jptei.ComputeNodeId); // job prep tests { Assert.NotNull(jptei); Assert.Equal(0, jptei.JobPreparationTaskExecutionInformation.RetryCount); Assert.True(beforeJobPrepRuns < jptei.JobPreparationTaskExecutionInformation.StartTime + TimeSpan.FromSeconds(10)); // test that the start time is rational -- 10s of wiggle room Assert.Null(jptei.JobPreparationTaskExecutionInformation.FailureInformation); this.testOutputHelper.WriteLine(""); this.testOutputHelper.WriteLine("listing files for compute node: " + victimComputeNodeRunningPrepAndRelease.Id); // fiter the list so reduce noise List <NodeFile> filteredListJobPrep = new List <NodeFile>(); foreach (NodeFile curTF in victimComputeNodeRunningPrepAndRelease.ListNodeFiles(recursive: true)) { // filter on the jsId since we only run one job per job in this test. if (curTF.Path.IndexOf(boundJobSchedule.Id, StringComparison.InvariantCultureIgnoreCase) >= 0) { this.testOutputHelper.WriteLine(" name:" + curTF.Path + ", size: " + ((curTF.IsDirectory.HasValue && curTF.IsDirectory.Value) ? "<dir>" : curTF.Properties.ContentLength.ToString())); filteredListJobPrep.Add(curTF); } } // confirm resource files made it foreach (ResourceFile curCorrectRF in correctResFiles) { bool found = false; foreach (NodeFile curTF in filteredListJobPrep) { // look for the resfile filepath in the taskfile name found |= curTF.Path.IndexOf(curCorrectRF.FilePath, StringComparison.InvariantCultureIgnoreCase) >= 0; } Assert.True(found, "Looking for resourcefile: " + curCorrectRF.FilePath); } // poll for completion while (JobPreparationTaskState.Completed != jptei.JobPreparationTaskExecutionInformation.State) { this.testOutputHelper.WriteLine("waiting for jopPrep to complete"); Thread.Sleep(2000); // refresh the state info ODATADetailLevel detailLevel = new ODATADetailLevel() { FilterClause = string.Format("nodeId eq '{0}'", victimComputeNodeRunningPrepAndRelease.Id) }; jobPrepStatusList = batchCli.JobOperations.ListJobPreparationAndReleaseTaskStatus(jobId, detailLevel: detailLevel).ToList(); jptei = jobPrepStatusList.First(); } // need success Assert.Equal(0, jptei.JobPreparationTaskExecutionInformation.ExitCode); // check stdout to confirm prep ran //Why do I have to use the hardcoded string job-1 here...? string stdOutFileSpec = Path.Combine("workitems", boundJobSchedule.Id, "job-1", boundJobSchedule.JobSpecification.JobPreparationTask.Id, Constants.StandardOutFileName); string stdOut = victimComputeNodeRunningPrepAndRelease.GetNodeFile(stdOutFileSpec).ReadAsString(); string stdErrFileSpec = Path.Combine("workitems", boundJobSchedule.Id, "job-1", boundJobSchedule.JobSpecification.JobPreparationTask.Id, Constants.StandardErrorFileName); string stdErr = string.Empty; try { stdErr = victimComputeNodeRunningPrepAndRelease.GetNodeFile(stdErrFileSpec).ReadAsString(); } catch (Exception) { //Swallow any exceptions here since stderr may not exist } this.testOutputHelper.WriteLine(stdOut); this.testOutputHelper.WriteLine(stdErr); Assert.True(!string.IsNullOrWhiteSpace(stdOut)); Assert.Contains("jobpreparation", stdOut.ToLower()); } // jobPrep tests completed. let JobPrep complete and task run and wait for JobRelease TaskStateMonitor tsm = batchCli.Utilities.CreateTaskStateMonitor(); // spam/logging interceptor Protocol.RequestInterceptor consoleSpammer = new Protocol.RequestInterceptor((x) => { this.testOutputHelper.WriteLine("TestGetPrepReleaseStatusCalls: waiting for JobPrep and task to complete"); ODATADetailLevel detailLevel = new ODATADetailLevel() { FilterClause = string.Format("nodeId eq '{0}'", victimComputeNodeRunningPrepAndRelease.Id) }; jobPrepStatusList = batchCli.JobOperations.ListJobPreparationAndReleaseTaskStatus(jobId, detailLevel: detailLevel).ToList(); JobPreparationAndReleaseTaskExecutionInformation jpteiInterceptor = jobPrepStatusList.First(); this.testOutputHelper.WriteLine(" JobPrep.State: " + jpteiInterceptor.JobPreparationTaskExecutionInformation.State); this.testOutputHelper.WriteLine(""); }); // waiting for the task to complete means so JobRelease is run. tsm.WaitAll( batchCli.JobOperations.GetJob(jobId).ListTasks(additionalBehaviors: new[] { consoleSpammer }), TaskState.Completed, TimeSpan.FromSeconds(120), additionalBehaviors: new[] { consoleSpammer }); // trigger JobRelease batchCli.JobOperations.TerminateJob(jobId, terminateReason: "die! I want JobRelease to run!"); // now that the task has competed, we are racing with the JobRelease... but it is sleeping so we can can catch it while (true) { ODATADetailLevel detailLevel = new ODATADetailLevel() { FilterClause = string.Format("nodeId eq '{0}'", victimComputeNodeRunningPrepAndRelease.Id) }; jobPrepStatusList = batchCli.JobOperations.ListJobPreparationAndReleaseTaskStatus(jobId, detailLevel: detailLevel).ToList(); JobPreparationAndReleaseTaskExecutionInformation jrtei = jobPrepStatusList.FirstOrDefault(); if ((jrtei == null) || (null == jrtei.JobReleaseTaskExecutionInformation)) { Thread.Sleep(2000); } else { Assert.NotNull(jrtei); if (jrtei.JobReleaseTaskExecutionInformation.State != JobReleaseTaskState.Completed) { this.testOutputHelper.WriteLine("JobReleaseTask state is: " + jrtei.JobReleaseTaskExecutionInformation.State); Thread.Sleep(5000); } else { this.testOutputHelper.WriteLine("JobRelease commpleted!"); // we are done break; } } } } }
public void TestNode_GetListDeleteFiles() { Action test = () => { using (BatchClient batchCli = TestUtilities.OpenBatchClientAsync(TestUtilities.GetCredentialsFromEnvironment()).Result) { string jobId = "TestNodeGetListDeleteFiles-" + TestUtilities.GetMyName(); try { const string taskId = "hiWorld"; const string directoryCreationTaskId1 = "dirTask1"; const string directoryCreationTaskId2 = "dirTask2"; const string directoryNameOne = "Foo"; const string directoryNameTwo = "Bar"; // // Create the job // CloudJob unboundJob = batchCli.JobOperations.CreateJob(jobId, new PoolInformation()); unboundJob.PoolInformation.PoolId = this.poolFixture.PoolId; unboundJob.Commit(); CloudJob boundJob = batchCli.JobOperations.GetJob(jobId); CloudTask myTask = new CloudTask(taskId, "cmd /c echo hello world"); CloudTask directoryCreationTask1 = new CloudTask(directoryCreationTaskId1, string.Format("cmd /c mkdir {0} && echo test > {0}/testfile.txt", directoryNameOne)); CloudTask directoryCreationTask2 = new CloudTask(directoryCreationTaskId2, string.Format("cmd /c mkdir {0} && echo test > {0}/testfile.txt", directoryNameTwo)); boundJob.AddTask(myTask); boundJob.AddTask(directoryCreationTask1); boundJob.AddTask(directoryCreationTask2); 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); //Since the compute node name comes back as "Node:<computeNodeId>" we need to split on : to get the actual compute node name string computeNodeId = boundTask.ComputeNodeInformation.AffinityId.Split(':')[1]; ComputeNode computeNode = batchCli.PoolOperations.GetComputeNode(this.poolFixture.PoolId, computeNodeId); this.testOutputHelper.WriteLine("Task ran on compute node: {0}", computeNodeId); //Ensure that ListFiles done without a recursive option, or with recursive false return the same values { List <NodeFile> filesByComputeNodeRecursiveOmitted = batchCli.PoolOperations.ListNodeFiles( this.poolFixture.PoolId, computeNodeId).ToList(); List <NodeFile> filesByComputeNodeRecursiveFalse = batchCli.PoolOperations.ListNodeFiles( this.poolFixture.PoolId, computeNodeId, recursive: false).ToList(); AssertFileListsMatch(filesByComputeNodeRecursiveOmitted, filesByComputeNodeRecursiveFalse); } { List <NodeFile> filesByTaskRecursiveOmitted = batchCli.JobOperations.ListNodeFiles( jobId, taskId).ToList(); List <NodeFile> filesByTaskRecursiveFalse = batchCli.JobOperations.ListNodeFiles( jobId, taskId, recursive: false).ToList(); AssertFileListsMatch(filesByTaskRecursiveOmitted, filesByTaskRecursiveFalse); } // // List all node files from operations -- recursive true // //TODO: Detail level? List <NodeFile> fileListFromComputeNodeOperations = batchCli.PoolOperations.ListNodeFiles(this.poolFixture.PoolId, computeNodeId, recursive: true).ToList(); foreach (NodeFile f in fileListFromComputeNodeOperations) { this.testOutputHelper.WriteLine("Found file: {0}", f.Path); } //Check to make sure the expected folder named "Shared" exists Assert.Contains("shared", fileListFromComputeNodeOperations.Select(f => f.Path)); // // List all node files from the compute node -- recursive true // List <NodeFile> fileListFromComputeNode = computeNode.ListNodeFiles(recursive: true).ToList(); foreach (NodeFile f in fileListFromComputeNodeOperations) { this.testOutputHelper.WriteLine("Found file: {0}", f.Path); } //Check to make sure the expected folder named "Shared" exists Assert.Contains("shared", fileListFromComputeNode.Select(f => f.Path)); // // Get file from operations // string filePathToGet = fileListFromComputeNode.First(f => !f.IsDirectory.Value && f.Properties.ContentLength > 0).Path; this.testOutputHelper.WriteLine("Getting file: {0}", filePathToGet); NodeFile computeNodeFileFromManager = batchCli.PoolOperations.GetNodeFile(this.poolFixture.PoolId, computeNodeId, filePathToGet); this.testOutputHelper.WriteLine("Successfully retrieved file: {0}", filePathToGet); this.testOutputHelper.WriteLine("---- File data: ----"); var computeNodeFileContentFromManager = computeNodeFileFromManager.ReadAsString(); this.testOutputHelper.WriteLine(computeNodeFileContentFromManager); Assert.NotEmpty(computeNodeFileContentFromManager); // // Get file directly from operations (bypassing the properties call) // var computeNodeFileContentDirect = batchCli.PoolOperations.CopyNodeFileContentToString(this.poolFixture.PoolId, computeNodeId, filePathToGet); this.testOutputHelper.WriteLine("---- File data: ----"); this.testOutputHelper.WriteLine(computeNodeFileContentDirect); Assert.NotEmpty(computeNodeFileContentDirect); // // Get file from compute node // this.testOutputHelper.WriteLine("Getting file: {0}", filePathToGet); NodeFile fileFromComputeNode = computeNode.GetNodeFile(filePathToGet); this.testOutputHelper.WriteLine("Successfully retrieved file: {0}", filePathToGet); this.testOutputHelper.WriteLine("---- File data: ----"); var computeNodeFileContentFromNode = fileFromComputeNode.ReadAsString(); this.testOutputHelper.WriteLine(computeNodeFileContentFromNode); Assert.NotEmpty(computeNodeFileContentFromNode); // // Get file from compute node (bypassing the properties call) // computeNodeFileContentDirect = computeNode.CopyNodeFileContentToString(filePathToGet); this.testOutputHelper.WriteLine("---- File data: ----"); this.testOutputHelper.WriteLine(computeNodeFileContentDirect); Assert.NotEmpty(computeNodeFileContentDirect); // // NodeFile delete // string filePath = Path.Combine(@"workitems", jobId, "job-1", taskId, Constants.StandardOutFileName); NodeFile nodeFile = batchCli.PoolOperations.GetNodeFile(this.poolFixture.PoolId, computeNodeId, filePath); nodeFile.Delete(); //Ensure delete succeeded TestUtilities.AssertThrows <BatchException>(() => nodeFile.Refresh()); //Delete directory NodeFile directory = batchCli.PoolOperations.ListNodeFiles(this.poolFixture.PoolId, computeNodeId, recursive: true).First(item => item.Path.Contains(directoryNameOne)); Assert.True(directory.IsDirectory); TestUtilities.AssertThrows <BatchException>(() => directory.Delete(recursive: false)); directory.Delete(recursive: true); Assert.Null(batchCli.PoolOperations.ListNodeFiles(this.poolFixture.PoolId, computeNodeId, recursive: true).FirstOrDefault(item => item.Path.Contains(directoryNameOne))); // // PoolManager delete node file // filePath = Path.Combine(@"workitems", jobId, "job-1", taskId, Constants.StandardErrorFileName); NodeFile file = batchCli.JobOperations.GetNodeFile(jobId, taskId, Constants.StandardErrorFileName); batchCli.PoolOperations.DeleteNodeFile(this.poolFixture.PoolId, computeNodeId, filePath); //Ensure delete succeeded TestUtilities.AssertThrows <BatchException>(() => batchCli.JobOperations.GetNodeFile(jobId, taskId, Constants.StandardErrorFileName)); //Delete directory directory = batchCli.PoolOperations.ListNodeFiles(this.poolFixture.PoolId, computeNodeId, recursive: true).First(item => item.Path.Contains(directoryNameTwo)); Assert.True(directory.IsDirectory); TestUtilities.AssertThrows <BatchException>(() => batchCli.PoolOperations.DeleteNodeFile(this.poolFixture.PoolId, computeNodeId, directory.Path, recursive: false)); batchCli.PoolOperations.DeleteNodeFile(this.poolFixture.PoolId, computeNodeId, directory.Path, recursive: true); Assert.Null(batchCli.PoolOperations.ListNodeFiles(this.poolFixture.PoolId, computeNodeId, recursive: true).FirstOrDefault(item => item.Path.Contains(directoryNameTwo))); } finally { batchCli.JobOperations.DeleteJob(jobId); } } }; SynchronizationContextHelper.RunTest(test, TestTimeout); }