public void Bug1771163TestGetComputeNode_RefreshComputeNode() { Action test = () => { using (BatchClient batchCli = TestUtilities.OpenBatchClientAsync(TestUtilities.GetCredentialsFromEnvironment()).Result) { PoolOperations poolOperations = batchCli.PoolOperations; List <ComputeNode> computeNodeList = poolOperations.ListComputeNodes(this.poolFixture.PoolId).ToList(); ComputeNode computeNodeToGet = computeNodeList.First(); string computeNodeId = computeNodeToGet.Id; // // Get compute node via the manager // ComputeNode computeNodeFromManager = poolOperations.GetComputeNode(this.poolFixture.PoolId, computeNodeId); CompareComputeNodeObjects(computeNodeToGet, computeNodeFromManager); // // Get compute node via the pool // CloudPool pool = poolOperations.GetPool(this.poolFixture.PoolId); ComputeNode computeNodeFromPool = pool.GetComputeNode(computeNodeId); CompareComputeNodeObjects(computeNodeToGet, computeNodeFromPool); // // Refresh compute node // //Refresh with a detail level computeNodeToGet.Refresh(new ODATADetailLevel() { SelectClause = "affinityId,id" }); //Confirm we have the reduced detail level Assert.Equal(computeNodeToGet.AffinityId, computeNodeFromManager.AffinityId); Assert.Null(computeNodeToGet.IPAddress); Assert.Null(computeNodeToGet.LastBootTime); Assert.Null(computeNodeToGet.State); Assert.Null(computeNodeToGet.StartTaskInformation); //Refresh again with increased detail level computeNodeToGet.Refresh(); CompareComputeNodeObjects(computeNodeToGet, computeNodeFromManager); } }; SynchronizationContextHelper.RunTest(test, TestTimeout); }
/// <summary> /// Lists the compute nodes matching the specified filter options. /// </summary> /// <param name="options">The options to use when querying for compute nodes.</param> /// <returns>The compute nodes matching the specified filter options.</returns> public IEnumerable <PSComputeNode> ListComputeNodes(ListComputeNodeOptions options) { if (options == null) { throw new ArgumentNullException("options"); } string poolId = options.Pool == null ? options.PoolId : options.Pool.Id; // Get the single compute node matching the specified id if (!string.IsNullOrEmpty(options.ComputeNodeId)) { WriteVerbose(string.Format(Resources.GetComputeNodeById, options.ComputeNodeId, poolId)); PoolOperations poolOperations = options.Context.BatchOMClient.PoolOperations; ODATADetailLevel getDetailLevel = new ODATADetailLevel(selectClause: options.Select); ComputeNode computeNode = poolOperations.GetComputeNode(poolId, options.ComputeNodeId, detailLevel: getDetailLevel, additionalBehaviors: options.AdditionalBehaviors); PSComputeNode psComputeNode = new PSComputeNode(computeNode); return(new PSComputeNode[] { psComputeNode }); } // List compute nodes using the specified filter else { string verboseLogString = null; ODATADetailLevel listDetailLevel = new ODATADetailLevel(selectClause: options.Select); if (!string.IsNullOrEmpty(options.Filter)) { verboseLogString = string.Format(Resources.GetComputeNodeByOData, poolId); listDetailLevel.FilterClause = options.Filter; } else { verboseLogString = string.Format(Resources.GetComputeNodeNoFilter, poolId); } WriteVerbose(verboseLogString); PoolOperations poolOperations = options.Context.BatchOMClient.PoolOperations; IPagedEnumerable <ComputeNode> computeNodes = poolOperations.ListComputeNodes(poolId, listDetailLevel, options.AdditionalBehaviors); return(PSPagedEnumerable <PSComputeNode, ComputeNode> .CreateWithMaxCount ( computeNodes, c => { return new PSComputeNode(c); }, options.MaxCount, () => WriteMaxCount(options.MaxCount) )); } }
/// <summary> /// Lists the compute nodes matching the specified filter options. /// </summary> /// <param name="options">The options to use when querying for compute nodes.</param> /// <returns>The compute nodes matching the specified filter options.</returns> public IEnumerable <PSComputeNode> ListComputeNodes(ListComputeNodeOptions options) { if (options == null) { throw new ArgumentNullException("options"); } string poolId = options.Pool == null ? options.PoolId : options.Pool.Id; // Get the single compute node matching the specified id if (!string.IsNullOrEmpty(options.ComputeNodeId)) { WriteVerbose(string.Format(Resources.GBCN_GetById, options.ComputeNodeId, poolId)); PoolOperations poolOperations = options.Context.BatchOMClient.PoolOperations; ComputeNode computeNode = poolOperations.GetComputeNode(poolId, options.ComputeNodeId, additionalBehaviors: options.AdditionalBehaviors); PSComputeNode psComputeNode = new PSComputeNode(computeNode); return(new PSComputeNode[] { psComputeNode }); } // List compute nodes using the specified filter else { ODATADetailLevel odata = null; string verboseLogString = null; if (!string.IsNullOrEmpty(options.Filter)) { verboseLogString = string.Format(Resources.GBCN_GetByOData, poolId); odata = new ODATADetailLevel(filterClause: options.Filter); } else { verboseLogString = string.Format(Resources.GBCN_NoFilter, poolId); } WriteVerbose(verboseLogString); PoolOperations poolOperations = options.Context.BatchOMClient.PoolOperations; IPagedEnumerable <ComputeNode> computeNodes = poolOperations.ListComputeNodes(poolId, odata, options.AdditionalBehaviors); Func <ComputeNode, PSComputeNode> mappingFunction = c => { return(new PSComputeNode(c)); }; return(PSPagedEnumerable <PSComputeNode, ComputeNode> .CreateWithMaxCount( computeNodes, mappingFunction, options.MaxCount, () => WriteVerbose(string.Format(Resources.MaxCount, options.MaxCount)))); } }
/// <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; } } } } }