private static void AssertJobScheduleCorrectness( JobScheduleOperations jobScheduleOperations, CloudJobSchedule boundJobSchedule, string expectedPoolId, int expectedJobPriority, string expectedJobManagerId, string expectedJobManagerCommandLine, TimeSpan?expectedRecurrenceInterval, IEnumerable <MetadataItem> expectedMetadata) { boundJobSchedule.Refresh(); Assert.Equal(expectedPoolId, boundJobSchedule.JobSpecification.PoolInformation.PoolId); Assert.Equal(expectedJobPriority, boundJobSchedule.JobSpecification.Priority); Assert.Equal(expectedJobManagerId, boundJobSchedule.JobSpecification.JobManagerTask.Id); Assert.Equal(expectedJobManagerCommandLine, boundJobSchedule.JobSpecification.JobManagerTask.CommandLine); if (expectedRecurrenceInterval.HasValue) { Assert.Equal(expectedRecurrenceInterval, boundJobSchedule.Schedule.RecurrenceInterval); } else { Assert.Null(boundJobSchedule.Schedule); } Assert.Equal(expectedMetadata.Count(), boundJobSchedule.Metadata.Count()); foreach (MetadataItem metadataItem in expectedMetadata) { Assert.Equal(1, boundJobSchedule.Metadata.Count(item => item.Name == metadataItem.Name && item.Value == metadataItem.Value)); } }
public async Task UnboundJobScheduleCommitAndRefreshWorks() { using (BatchClient batchClient = ClientUnitTestCommon.CreateDummyClient()) { const string id = "Bar"; const string displayName = "Baz"; var jobSpecification = new Protocol.Models.JobSpecification() { DisplayName = displayName }; var protoJobSchedule = new Protocol.Models.CloudJobSchedule( id: id, displayName: displayName, jobSpecification: jobSpecification); CloudJobSchedule jobSchedule = batchClient.JobScheduleOperations.CreateJobSchedule(id, new Schedule(), null); await jobSchedule.CommitAsync(additionalBehaviors : InterceptorFactory.CreateAddJobScheduleRequestInterceptor()); await jobSchedule.RefreshAsync(additionalBehaviors : InterceptorFactory.CreateGetJobScheduleRequestInterceptor(protoJobSchedule)); Assert.Equal(id, jobSchedule.Id); Assert.Equal(displayName, jobSchedule.DisplayName); Assert.Null(jobSchedule.Schedule); Assert.NotNull(jobSchedule.JobSpecification); Assert.Equal(jobSpecification.DisplayName, jobSchedule.JobSpecification.DisplayName); } }
public void CloudJobSchedule_WhenSendingToTheServer_HasExpectedUnboundProperties() { const string jobScheduleId = "id-123"; const string displayName = "DisplayNameFoo"; MetadataItem metadataItem = new MetadataItem("foo", "bar"); BatchSharedKeyCredentials credentials = ClientUnitTestCommon.CreateDummySharedKeyCredential(); using (BatchClient client = BatchClient.Open(credentials)) { CloudJobSchedule jobSchedule = client.JobScheduleOperations.CreateJobSchedule(); jobSchedule.Id = jobScheduleId; jobSchedule.DisplayName = displayName; jobSchedule.Metadata = new List <MetadataItem> { metadataItem }; Assert.Equal(jobSchedule.Id, jobScheduleId); // can set an unbound object Assert.Equal(jobSchedule.Metadata.First().Name, metadataItem.Name); Assert.Equal(jobSchedule.Metadata.First().Value, metadataItem.Value); jobSchedule.Commit(additionalBehaviors: InterceptorFactory.CreateAddJobScheduleRequestInterceptor()); // writing isn't allowed for a jobSchedule that is in an read only state. Assert.Throws <InvalidOperationException>(() => jobSchedule.Id = "cannot-change-id"); Assert.Throws <InvalidOperationException>(() => jobSchedule.DisplayName = "cannot-change-display-name"); //Can still read though Assert.Equal(jobScheduleId, jobSchedule.Id); Assert.Equal(displayName, jobSchedule.DisplayName); } }
public void TestPatchJobSchedule_ThrowsOnUnbound() { using (BatchClient client = ClientUnitTestCommon.CreateDummyClient()) { CloudJobSchedule jobSchedule = client.JobScheduleOperations.CreateJobSchedule(); Assert.Throws <InvalidOperationException>(() => jobSchedule.CommitChanges()); } }
public async Task UnboundJobScheduleDirectRefreshFailsWithMissingPathVariables() { using BatchClient batchClient = ClientUnitTestCommon.CreateDummyClient(); CloudJobSchedule jobSchedule = batchClient.JobScheduleOperations.CreateJobSchedule(); ValidationException e = await Assert.ThrowsAsync <ValidationException>(async() => await jobSchedule.RefreshAsync()); Assert.Contains("'jobScheduleId' cannot be null", e.Message); }
public async Task JobSchedulePatch() { Func <Task> test = async() => { using (BatchClient batchCli = await TestUtilities.OpenBatchClientFromEnvironmentAsync().ConfigureAwait(false)) { string jobScheduleId = "TestPatchJobSchedule-" + TestUtilities.GetMyName(); const string newJobManagerCommandLine = "cmd /c dir"; const string metadataKey = "Foo"; const string metadataValue = "Bar"; TimeSpan newRecurrenceInterval = TimeSpan.FromDays(2); try { CloudJobSchedule jobSchedule = batchCli.JobScheduleOperations.CreateJobSchedule( jobScheduleId, new Schedule() { RecurrenceInterval = TimeSpan.FromDays(1) }, new JobSpecification(new PoolInformation() { PoolId = "DummyPool" }) { JobManagerTask = new JobManagerTask(id: "Foo", commandLine: "Foo") }); await jobSchedule.CommitAsync().ConfigureAwait(false); await jobSchedule.RefreshAsync().ConfigureAwait(false); jobSchedule.JobSpecification.JobManagerTask.CommandLine = newJobManagerCommandLine; jobSchedule.Metadata = new List <MetadataItem>() { new MetadataItem(metadataKey, metadataValue) }; jobSchedule.Schedule.RecurrenceInterval = newRecurrenceInterval; await jobSchedule.CommitChangesAsync().ConfigureAwait(false); await jobSchedule.RefreshAsync().ConfigureAwait(false); Assert.Equal(newRecurrenceInterval, jobSchedule.Schedule.RecurrenceInterval); Assert.Equal(newJobManagerCommandLine, jobSchedule.JobSpecification.JobManagerTask.CommandLine); Assert.Equal(metadataKey, jobSchedule.Metadata.Single().Name); Assert.Equal(metadataValue, jobSchedule.Metadata.Single().Value); } finally { await TestUtilities.DeleteJobScheduleIfExistsAsync(batchCli, jobScheduleId).ConfigureAwait(false); } } }; await SynchronizationContextHelper.RunTestAsync(test, TestTimeout); }
public void TestListJobsByJobSchedule() { Action test = () => { using (BatchClient batchCli = TestUtilities.OpenBatchClientAsync(TestUtilities.GetCredentialsFromEnvironment()).Result) { string jobScheduleId = Microsoft.Azure.Batch.Constants.DefaultConveniencePrefix + TestUtilities.GetMyName() + "-TestListJobsByJobSchedule"; try { Schedule schedule = new Schedule() { DoNotRunAfter = DateTime.UtcNow.Add(TimeSpan.FromDays(1)), RecurrenceInterval = TimeSpan.FromMinutes(1) }; JobSpecification jobSpecification = new JobSpecification(new PoolInformation() { PoolId = "DummyPool" }); CloudJobSchedule unboundJobSchedule = batchCli.JobScheduleOperations.CreateJobSchedule(jobScheduleId, schedule, jobSpecification); unboundJobSchedule.Commit(); //List the jobs under this JobSchedule for (int i = 1; i <= 3; i++) { string expectedJobId = string.Format("{0}:job-{1}", jobScheduleId, i); CloudJobSchedule boundJobSchedule = TestUtilities.WaitForJobOnJobSchedule( batchCli.JobScheduleOperations, jobScheduleId, expectedJobId: expectedJobId, timeout: TimeSpan.FromSeconds(70)); List <CloudJob> jobs = boundJobSchedule.ListJobs().ToList(); Assert.Equal(i, jobs.Count); jobs = batchCli.JobScheduleOperations.ListJobs(jobScheduleId).ToList(); Assert.Equal(i, jobs.Count); //Terminate the current job to force a new job to be created batchCli.JobOperations.TerminateJob(expectedJobId); } } finally { // clean up TestUtilities.DeleteJobScheduleIfExistsAsync(batchCli, jobScheduleId).Wait(); } } }; SynchronizationContextHelper.RunTest(test, LongTestTimeout); }
public void TestRandomBoundCloudJobScheduleProperties() { using BatchClient client = ClientUnitTestCommon.CreateDummyClient(); for (int i = 0; i < TestRunCount; i++) { Protocol.Models.CloudJobSchedule jobScheduleModel = this.customizedObjectFactory.GenerateNew <Protocol.Models.CloudJobSchedule>(); CloudJobSchedule boundJobSchedule = new CloudJobSchedule(client, jobScheduleModel, client.CustomBehaviors); ObjectComparer.CheckEqualityResult result = this.objectComparer.CheckEquality(boundJobSchedule, jobScheduleModel); Assert.True(result.Equal, result.Message); } }
public void CloudJobSchedule_WhenReturnedFromServer_HasExpectedBoundProperties() { const string jobScheduleId = "id-123"; const string displayName = "DisplayNameFoo"; MetadataItem metadataItem = new MetadataItem("foo", "bar"); using (BatchClient client = ClientUnitTestCommon.CreateDummyClient()) { DateTime creationTime = DateTime.Now; var cloudJobSchedule = new Models.CloudJobSchedule { Id = jobScheduleId, DisplayName = displayName, Metadata = new[] { new Models.MetadataItem { Name = metadataItem.Name, Value = metadataItem.Value } }, CreationTime = creationTime, JobSpecification = new Models.JobSpecification { OnAllTasksComplete = Models.OnAllTasksComplete.TerminateJob, OnTaskFailure = Models.OnTaskFailure.PerformExitOptionsJobAction } }; CloudJobSchedule boundJobSchedule = client.JobScheduleOperations.GetJobSchedule( jobScheduleId, additionalBehaviors: InterceptorFactory.CreateGetJobScheduleRequestInterceptor(cloudJobSchedule)); Assert.Equal(jobScheduleId, boundJobSchedule.Id); // reading is allowed from a jobSchedule that is returned from the server. Assert.Equal(creationTime, boundJobSchedule.CreationTime); Assert.Equal(displayName, boundJobSchedule.DisplayName); Assert.Equal(OnAllTasksComplete.TerminateJob, boundJobSchedule.JobSpecification.OnAllTasksComplete); Assert.Equal(OnTaskFailure.PerformExitOptionsJobAction, boundJobSchedule.JobSpecification.OnTaskFailure); Assert.Throws <InvalidOperationException>(() => boundJobSchedule.DisplayName = "cannot-change-display-name"); Assert.Throws <InvalidOperationException>(() => boundJobSchedule.Id = "cannot-change-id"); boundJobSchedule.JobSpecification.OnAllTasksComplete = OnAllTasksComplete.TerminateJob; boundJobSchedule.JobSpecification.OnTaskFailure = OnTaskFailure.NoAction; Assert.Equal(OnAllTasksComplete.TerminateJob, boundJobSchedule.JobSpecification.OnAllTasksComplete); Assert.Equal(OnTaskFailure.NoAction, boundJobSchedule.JobSpecification.OnTaskFailure); } }
public void CloudJobSchedule_WhenSendingToTheServer_HasExpectedUnboundProperties() { const string jobScheduleId = "id-123"; const string displayName = "DisplayNameFoo"; MetadataItem metadataItem = new MetadataItem("foo", "bar"); using (BatchClient client = ClientUnitTestCommon.CreateDummyClient()) { CloudJobSchedule jobSchedule = client.JobScheduleOperations.CreateJobSchedule(); jobSchedule.Id = jobScheduleId; jobSchedule.DisplayName = displayName; jobSchedule.Metadata = new List <MetadataItem> { metadataItem }; jobSchedule.JobSpecification = new JobSpecification { OnAllTasksComplete = OnAllTasksComplete.TerminateJob, OnTaskFailure = OnTaskFailure.PerformExitOptionsJobAction }; Assert.Equal(jobSchedule.Id, jobScheduleId); // can set an unbound object Assert.Equal(jobSchedule.Metadata.First().Name, metadataItem.Name); Assert.Equal(jobSchedule.Metadata.First().Value, metadataItem.Value); Assert.Equal(OnAllTasksComplete.TerminateJob, jobSchedule.JobSpecification.OnAllTasksComplete); Assert.Equal(OnTaskFailure.PerformExitOptionsJobAction, jobSchedule.JobSpecification.OnTaskFailure); jobSchedule.Commit(additionalBehaviors: InterceptorFactory.CreateAddJobScheduleRequestInterceptor()); // writing isn't allowed for a jobSchedule that is in an read only state. Assert.Throws <InvalidOperationException>(() => jobSchedule.Id = "cannot-change-id"); Assert.Throws <InvalidOperationException>(() => jobSchedule.DisplayName = "cannot-change-display-name"); //Can still read though Assert.Equal(jobScheduleId, jobSchedule.Id); Assert.Equal(displayName, jobSchedule.DisplayName); jobSchedule.Refresh(additionalBehaviors: InterceptorFactory.CreateGetJobScheduleRequestInterceptor( new Models.CloudJobSchedule() { JobSpecification = new Models.JobSpecification() })); jobSchedule.JobSpecification.OnAllTasksComplete = OnAllTasksComplete.NoAction; jobSchedule.JobSpecification.OnTaskFailure = OnTaskFailure.NoAction; } }
/// <summary> /// Waits for a job to be created -- This should be removed when we have a Utilities helper which does this /// </summary> public static CloudJobSchedule WaitForJobOnJobSchedule(JobScheduleOperations jobScheduleOperations, string jobScheduleId, string expectedJobId = null, TimeSpan?timeout = null) { //Wait for the job TimeSpan jobCreationTimeout = timeout ?? TimeSpan.FromSeconds(30); CloudJobSchedule refreshableJobSchedule = jobScheduleOperations.GetJobSchedule(jobScheduleId); DateTime jobCreationWaitStartTime = DateTime.UtcNow; while (refreshableJobSchedule.ExecutionInformation == null || refreshableJobSchedule.ExecutionInformation.RecentJob == null || (!string.IsNullOrEmpty(expectedJobId) && refreshableJobSchedule.ExecutionInformation.RecentJob.Id != expectedJobId)) { Thread.Sleep(TimeSpan.FromSeconds(10)); refreshableJobSchedule.Refresh(); if (DateTime.UtcNow > jobCreationWaitStartTime.Add(jobCreationTimeout)) { throw new Exception("Timed out waiting for job"); } } return(refreshableJobSchedule); }
/// <summary> /// Lists the job schedules matching the specified filter options. /// </summary> /// <param name="options">The options to use when querying for job schedules.</param> /// <returns>The workitems matching the specified filter options.</returns> public IEnumerable <PSCloudJobSchedule> ListJobSchedules(ListJobScheduleOptions options) { if (options == null) { throw new ArgumentNullException("options"); } // Get the single job schedule matching the specified id if (!string.IsNullOrWhiteSpace(options.JobScheduleId)) { WriteVerbose(string.Format(Resources.GetJobScheduleById, options.JobScheduleId)); JobScheduleOperations jobScheduleOperations = options.Context.BatchOMClient.JobScheduleOperations; ODATADetailLevel getDetailLevel = new ODATADetailLevel(selectClause: options.Select, expandClause: options.Expand); CloudJobSchedule jobSchedule = jobScheduleOperations.GetJobSchedule(options.JobScheduleId, detailLevel: getDetailLevel, additionalBehaviors: options.AdditionalBehaviors); PSCloudJobSchedule psJobSchedule = new PSCloudJobSchedule(jobSchedule); return(new PSCloudJobSchedule[] { psJobSchedule }); } // List job schedules using the specified filter else { string verboseLogString = null; ODATADetailLevel listDetailLevel = new ODATADetailLevel(selectClause: options.Select, expandClause: options.Expand); if (!string.IsNullOrEmpty(options.Filter)) { verboseLogString = Resources.GetJobScheduleByOData; listDetailLevel.FilterClause = options.Filter; } else { verboseLogString = Resources.GetJobScheduleNoFilter; } WriteVerbose(verboseLogString); JobScheduleOperations jobScheduleOperations = options.Context.BatchOMClient.JobScheduleOperations; IPagedEnumerable <CloudJobSchedule> workItems = jobScheduleOperations.ListJobSchedules(listDetailLevel, options.AdditionalBehaviors); Func <CloudJobSchedule, PSCloudJobSchedule> mappingFunction = j => { return(new PSCloudJobSchedule(j)); }; return(PSPagedEnumerable <PSCloudJobSchedule, CloudJobSchedule> .CreateWithMaxCount( workItems, mappingFunction, options.MaxCount, () => WriteVerbose(string.Format(Resources.MaxCount, options.MaxCount)))); } }
private static void CommonPatchJobScheduleTest( Protocol.Models.CloudJobSchedule startEntity, Action <CloudJobSchedule> modificationFunction, Action <Protocol.Models.JobSchedulePatchParameter> assertAction) { using (BatchClient client = ClientUnitTestCommon.CreateDummyClient()) { CloudJobSchedule jobSchedule = client.JobScheduleOperations.GetJobSchedule( string.Empty, additionalBehaviors: InterceptorFactory.CreateGetJobScheduleRequestInterceptor(startEntity)); modificationFunction(jobSchedule); var patchInterceptor = ShimPatchJobSchedule(assertAction); jobSchedule.CommitChanges(additionalBehaviors: new[] { patchInterceptor }); //Ensure that the job is in readable but unmodifiable state var id = jobSchedule.Id; Assert.Throws <InvalidOperationException>(() => jobSchedule.Metadata = null); } }
public void CloudJobSchedule_WhenReturnedFromServer_HasExpectedBoundProperties() { const string jobScheduleId = "id-123"; const string displayName = "DisplayNameFoo"; MetadataItem metadataItem = new MetadataItem("foo", "bar"); BatchSharedKeyCredentials credentials = ClientUnitTestCommon.CreateDummySharedKeyCredential(); using (BatchClient client = BatchClient.Open(credentials)) { DateTime creationTime = DateTime.Now; var cloudJobSchedule = new Models.CloudJobSchedule { Id = jobScheduleId, DisplayName = displayName, Metadata = new[] { new Models.MetadataItem { Name = metadataItem.Name, Value = metadataItem.Value } }, CreationTime = creationTime }; CloudJobSchedule boundJobSchedule = client.JobScheduleOperations.GetJobSchedule( jobScheduleId, additionalBehaviors: InterceptorFactory.CreateGetJobScheduleRequestInterceptor(cloudJobSchedule)); Assert.Equal(jobScheduleId, boundJobSchedule.Id); // reading is allowed from a jobSchedule that is returned from the server. Assert.Equal(creationTime, boundJobSchedule.CreationTime); Assert.Equal(displayName, boundJobSchedule.DisplayName); Assert.Throws <InvalidOperationException>(() => boundJobSchedule.DisplayName = "cannot-change-display-name"); Assert.Throws <InvalidOperationException>(() => boundJobSchedule.Id = "cannot-change-id"); } }
/// <summary> /// Creates a new job schedule. /// </summary> /// <param name="parameters">The parameters to use when creating the job schedule.</param> public void CreateJobSchedule(NewJobScheduleParameters parameters) { if (parameters == null) { throw new ArgumentNullException("parameters"); } JobScheduleOperations jobScheduleOperations = parameters.Context.BatchOMClient.JobScheduleOperations; CloudJobSchedule jobSchedule = jobScheduleOperations.CreateJobSchedule(); jobSchedule.Id = parameters.JobScheduleId; jobSchedule.DisplayName = parameters.DisplayName; if (parameters.Schedule != null) { jobSchedule.Schedule = parameters.Schedule.omObject; } if (parameters.JobSpecification != null) { Utils.Utils.JobSpecificationSyncCollections(parameters.JobSpecification); jobSchedule.JobSpecification = parameters.JobSpecification.omObject; } if (parameters.Metadata != null) { jobSchedule.Metadata = new List <MetadataItem>(); foreach (DictionaryEntry d in parameters.Metadata) { MetadataItem metadata = new MetadataItem(d.Key.ToString(), d.Value.ToString()); jobSchedule.Metadata.Add(metadata); } } WriteVerbose(string.Format(Resources.CreatingJobSchedule, parameters.JobScheduleId)); jobSchedule.Commit(parameters.AdditionalBehaviors); }
public void Bug1910530_ConcurrentChangeTrackedListThreadsafeTest() { const string testName = "Bug1910530_ConcurrentChangeTrackedListThreadsafeTest"; using (BatchClient batchCli = ClientUnitTestCommon.CreateDummyClient()) { JobScheduleOperations jobScheduleOperations = batchCli.JobScheduleOperations; string jobScheduleId = Microsoft.Azure.Batch.Constants.DefaultConveniencePrefix + "-" + testName; // //Unbound job schedule properties // this.testOutputHelper.WriteLine("Creating job schedule {0}", jobScheduleId); CloudJobSchedule unboundJobSchedule = jobScheduleOperations.CreateJobSchedule(jobScheduleId, null, null); //Create a new threadsafe collection unboundJobSchedule.Metadata = new List <MetadataItem>(); //Now it should be magically threadsafe Action addAction = () => { this.testOutputHelper.WriteLine("Adding an item"); unboundJobSchedule.Metadata.Add(new MetadataItem("test", "test")); }; Action removeAction = () => { this.testOutputHelper.WriteLine("Removing an item"); try { unboundJobSchedule.Metadata.RemoveAt(0); } catch (ArgumentOutOfRangeException) { } }; Random rand = new Random(); object randLock = new object(); Parallel.For(0, 100, new ParallelOptions() { MaxDegreeOfParallelism = 10 }, (i) => { int randomInt; lock (randLock) { randomInt = rand.Next(0, 2); } if (randomInt == 0) { addAction(); } else { removeAction(); } }); } }
public async Task CanCreateAndUpdateJobScheduleWithApplicationReferences() { var jobId = Guid.NewGuid().ToString(); const string newVersion = "2.0"; var poolInformation = new PoolInformation { AutoPoolSpecification = new AutoPoolSpecification { PoolSpecification = new PoolSpecification { ApplicationPackageReferences = new List <ApplicationPackageReference> { new ApplicationPackageReference { ApplicationId = ApplicationId, Version = Version } }, CloudServiceConfiguration = new CloudServiceConfiguration(PoolFixture.OSFamily), VirtualMachineSize = PoolFixture.VMSize, }, PoolLifetimeOption = PoolLifetimeOption.JobSchedule, KeepAlive = false, } }; Schedule schedule = new Schedule { DoNotRunAfter = DateTime.UtcNow.AddMinutes(5), RecurrenceInterval = TimeSpan.FromMinutes(2) }; JobSpecification jobSpecification = new JobSpecification(poolInformation); using BatchClient client = await TestUtilities.OpenBatchClientFromEnvironmentAsync().ConfigureAwait(false); CloudJobSchedule cloudJobSchedule = client.JobScheduleOperations.CreateJobSchedule(jobId, schedule, jobSpecification); async Task test() { CloudJobSchedule updatedBoundJobSchedule = null; try { await cloudJobSchedule.CommitAsync().ConfigureAwait(false); CloudJobSchedule boundJobSchedule = TestUtilities.WaitForJobOnJobSchedule(client.JobScheduleOperations, jobId); ApplicationPackageReference apr = boundJobSchedule.JobSpecification.PoolInformation.AutoPoolSpecification.PoolSpecification.ApplicationPackageReferences.First(); Assert.Equal(ApplicationId, apr.ApplicationId); Assert.Equal(Version, apr.Version); boundJobSchedule.JobSpecification.PoolInformation.AutoPoolSpecification.PoolSpecification.ApplicationPackageReferences = new[] { new ApplicationPackageReference() { ApplicationId = ApplicationId, Version = newVersion } }; await boundJobSchedule.CommitAsync().ConfigureAwait(false); await boundJobSchedule.RefreshAsync().ConfigureAwait(false); updatedBoundJobSchedule = await client.JobScheduleOperations.GetJobScheduleAsync(jobId).ConfigureAwait(false); ApplicationPackageReference updatedApr = updatedBoundJobSchedule.JobSpecification.PoolInformation.AutoPoolSpecification.PoolSpecification.ApplicationPackageReferences .First(); Assert.Equal(ApplicationId, updatedApr.ApplicationId); Assert.Equal(newVersion, updatedApr.Version); } finally { TestUtilities.DeleteJobScheduleIfExistsAsync(client, jobId).Wait(); } } await SynchronizationContextHelper.RunTestAsync(test, LongTestTimeout); }
public static void DisplayJobScheduleLong(ITestOutputHelper testOutputHelper, CloudJobSchedule curWI) { // job schedule top level simple properties testOutputHelper.WriteLine("Id: " + curWI.Id); testOutputHelper.WriteLine(" State: " + curWI.State.ToString()); testOutputHelper.WriteLine(" " + "URL: " + curWI.Url); testOutputHelper.WriteLine(" " + "LastModified: " + (curWI.LastModified.HasValue ? curWI.LastModified.Value.ToLongDateString() : "<null>")); // execution INFO { JobScheduleExecutionInformation wiExInfo = curWI.ExecutionInformation; testOutputHelper.WriteLine(" ExeInfo:"); testOutputHelper.WriteLine(" LastUpdateTime: " + (wiExInfo.EndTime.HasValue ? wiExInfo.EndTime.Value.ToLongDateString() : "<null>")); testOutputHelper.WriteLine(" NextRuntime: " + (wiExInfo.NextRunTime.HasValue ? wiExInfo.NextRunTime.Value.ToLongDateString() : "<null>")); testOutputHelper.WriteLine(" RecentJob:"); // RecentJob RecentJob rj = wiExInfo.RecentJob; if (null == rj) { testOutputHelper.WriteLine(" <null>"); } else { testOutputHelper.WriteLine(" Id: " + rj.Id); testOutputHelper.WriteLine(" Url: " + rj.Url); } } // JobSpecification JobSpecification jobSpec = curWI.JobSpecification; testOutputHelper.WriteLine(" JobSpecification:"); if (null == jobSpec) { testOutputHelper.WriteLine(" <null>"); } else { testOutputHelper.WriteLine(""); testOutputHelper.WriteLine(" Priority: " + (jobSpec.Priority.HasValue ? jobSpec.Priority.ToString() : "<null>")); JobConstraints jobCon = jobSpec.Constraints; testOutputHelper.WriteLine(" Constraints: "); if (null == jobCon) { testOutputHelper.WriteLine("null"); } else { testOutputHelper.WriteLine(""); testOutputHelper.WriteLine(" MaxTaskRetryCount: " + (jobCon.MaxTaskRetryCount.HasValue ? jobSpec.Constraints.MaxTaskRetryCount.Value.ToString() : "<null>")); testOutputHelper.WriteLine(" MaxWallClockTime: " + (jobCon.MaxWallClockTime.HasValue ? jobSpec.Constraints.MaxWallClockTime.Value.TotalMilliseconds.ToString() : "<null>")); } JobManagerTask ijm = jobSpec.JobManagerTask; if (null == ijm) { testOutputHelper.WriteLine("<null>"); } else { testOutputHelper.WriteLine(" JobManagerTask:"); testOutputHelper.WriteLine(" CommandLine : " + ijm.CommandLine); testOutputHelper.WriteLine(" KillJobOnCompletion: " + (ijm.KillJobOnCompletion.HasValue ? ijm.KillJobOnCompletion.Value.ToString() : "<null>")); testOutputHelper.WriteLine(" Id : " + ijm.Id); testOutputHelper.WriteLine(" RunExclusive : " + (ijm.RunExclusive.HasValue ? ijm.RunExclusive.Value.ToString() : "<null>")); IEnumerable <EnvironmentSetting> envSettings = ijm.EnvironmentSettings; if (null != envSettings) { List <EnvironmentSetting> envSettingsList = new List <EnvironmentSetting>(ijm.EnvironmentSettings); testOutputHelper.WriteLine(" EnvironmentSettings.count:" + envSettingsList.Count); } else { testOutputHelper.WriteLine(" EnvironmentSettings: <null>"); } IEnumerable <ResourceFile> resFilesProp = ijm.ResourceFiles; if (null != resFilesProp) { List <ResourceFile> resFiles = new List <ResourceFile>(); testOutputHelper.WriteLine(" ResourceFiles.count:" + resFiles.Count); } else { testOutputHelper.WriteLine(" ResourceFiles: <null>"); } TaskConstraints tc = ijm.Constraints; if (null == tc) { testOutputHelper.WriteLine(" TaskConstraints: <null>"); } else { testOutputHelper.WriteLine(" TaskConstraints: "); testOutputHelper.WriteLine(" MaxTaskRetryCount: " + (tc.MaxTaskRetryCount.HasValue ? tc.MaxTaskRetryCount.Value.ToString() : "<null>")); testOutputHelper.WriteLine(" MaxWallClockTime: " + (tc.MaxWallClockTime.HasValue ? tc.MaxWallClockTime.Value.TotalMilliseconds.ToString() : "<null>")); testOutputHelper.WriteLine(" RetentionTime: " + (tc.RetentionTime.HasValue ? tc.RetentionTime.Value.TotalMilliseconds.ToString() : "<null>")); } if (ijm.UserIdentity != null) { testOutputHelper.WriteLine(" UserIdentity: "); testOutputHelper.WriteLine(" UserName: "******" ElevationLevel: ", ijm.UserIdentity.AutoUser?.ElevationLevel); testOutputHelper.WriteLine(" Scope: ", ijm.UserIdentity.AutoUser?.Scope); } } } // metadata { IEnumerable <MetadataItem> mdis = curWI.Metadata; testOutputHelper.WriteLine(" Metadata: "); if (null == mdis) { testOutputHelper.WriteLine("<null>"); } else { List <MetadataItem> meta = new List <MetadataItem>(curWI.Metadata); testOutputHelper.WriteLine(" count:" + meta.Count); } } // schedule Schedule sched = curWI.Schedule; if (null == sched) { testOutputHelper.WriteLine(" Schedule: <null>"); } else { testOutputHelper.WriteLine(" Schedule:"); testOutputHelper.WriteLine(" DoNotRunAfter:" + (sched.DoNotRunAfter.HasValue ? sched.DoNotRunAfter.Value.ToLongDateString() : "<null>")); testOutputHelper.WriteLine(" DoNotRunUntil: " + (sched.DoNotRunUntil.HasValue ? sched.DoNotRunUntil.Value.ToLongDateString() : "<null>")); testOutputHelper.WriteLine(" RecurrenceInterval: " + (sched.RecurrenceInterval.HasValue ? sched.RecurrenceInterval.Value.TotalMilliseconds.ToString() : "<null>")); testOutputHelper.WriteLine(" StartWindow :" + (sched.StartWindow.HasValue ? sched.StartWindow.Value.TotalMilliseconds.ToString() : "<null>")); } // stats JobScheduleStatistics stats = curWI.Statistics; if (null == stats) { testOutputHelper.WriteLine(" Stats: <null>"); } else { testOutputHelper.WriteLine(" Stats:"); testOutputHelper.WriteLine(" LastUpdateTime: " + stats.LastUpdateTime.ToLongDateString()); testOutputHelper.WriteLine(" KernelCPUTime: " + stats.KernelCpuTime.TotalMilliseconds.ToString()); testOutputHelper.WriteLine(" NumFailedTasks: " + stats.FailedTaskCount.ToString()); testOutputHelper.WriteLine(" NumTimesCalled : " + stats.TaskRetryCount); testOutputHelper.WriteLine(" NumSucceededTasks: " + stats.SucceededTaskCount); testOutputHelper.WriteLine(" ReadIOGiB : " + stats.ReadIOGiB); testOutputHelper.WriteLine(" ReadIOps : " + stats.ReadIOps); testOutputHelper.WriteLine(" StartTime : " + stats.StartTime.ToLongDateString()); testOutputHelper.WriteLine(" Url : " + stats.Url); testOutputHelper.WriteLine(" UserCpuTime : " + stats.UserCpuTime.TotalMilliseconds.ToString()); testOutputHelper.WriteLine(" WaitTime : " + stats.WaitTime.TotalMilliseconds.ToString()); testOutputHelper.WriteLine(" WallClockTime : " + stats.WallClockTime.TotalMilliseconds.ToString()); testOutputHelper.WriteLine(" WriteIOGiB : " + stats.WriteIOGiB); testOutputHelper.WriteLine(" WriteIOps : " + stats.WriteIOps); } }
public void TestJobScheduleVerbs() { Action test = () => { using (BatchClient batchCli = TestUtilities.OpenBatchClientAsync(TestUtilities.GetCredentialsFromEnvironment()).Result) { string jobScheduleId = Microsoft.Azure.Batch.Constants.DefaultConveniencePrefix + TestUtilities.GetMyName() + "-TestEnableDisableDeleteJobSchedule"; try { Schedule schedule = new Schedule() { DoNotRunAfter = DateTime.UtcNow.Add(TimeSpan.FromDays(1)) }; JobSpecification jobSpecification = new JobSpecification(new PoolInformation() { PoolId = "DummyPool" }); CloudJobSchedule unboundJobSchedule = batchCli.JobScheduleOperations.CreateJobSchedule(jobScheduleId, schedule, jobSpecification); unboundJobSchedule.Commit(); CloudJobSchedule boundJobSchedule = batchCli.JobScheduleOperations.GetJobSchedule(jobScheduleId); //Disable the job schedule via instance boundJobSchedule.Disable(); boundJobSchedule.Refresh(); Assert.NotNull(boundJobSchedule.State); Assert.Equal(JobScheduleState.Disabled, boundJobSchedule.State); //Enable the job schedule via instance boundJobSchedule.Enable(); boundJobSchedule.Refresh(); Assert.NotNull(boundJobSchedule.State); Assert.Equal(JobScheduleState.Active, boundJobSchedule.State); //Disable the job schedule via operations batchCli.JobScheduleOperations.DisableJobSchedule(jobScheduleId); boundJobSchedule.Refresh(); Assert.NotNull(boundJobSchedule.State); Assert.Equal(JobScheduleState.Disabled, boundJobSchedule.State); //Enable the job schedule via instance batchCli.JobScheduleOperations.EnableJobSchedule(jobScheduleId); boundJobSchedule.Refresh(); Assert.NotNull(boundJobSchedule.State); Assert.Equal(JobScheduleState.Active, boundJobSchedule.State); //Terminate the job schedule batchCli.JobScheduleOperations.TerminateJobSchedule(jobScheduleId); boundJobSchedule.Refresh(); Assert.True(boundJobSchedule.State == JobScheduleState.Completed || boundJobSchedule.State == JobScheduleState.Terminating); //Delete the job schedule boundJobSchedule.Delete(); //Wait for deletion to take BatchException be = TestUtilities.AssertThrowsEventuallyAsync <BatchException>(() => boundJobSchedule.RefreshAsync(), TimeSpan.FromSeconds(30)).Result; Assert.NotNull(be.RequestInformation); Assert.NotNull(be.RequestInformation.BatchError); Assert.Equal("JobScheduleNotFound", be.RequestInformation.BatchError.Code); } finally { // clean up TestUtilities.DeleteJobScheduleIfExistsAsync(batchCli, jobScheduleId).Wait(); } } }; SynchronizationContextHelper.RunTest(test, TestTimeout); }
public void TestOMJobSpecAndRelease() { Action test = () => { StagingStorageAccount stagingCreds = TestUtilities.GetStorageCredentialsFromEnvironment(); using (BatchClient client = TestUtilities.OpenBatchClient(TestUtilities.GetCredentialsFromEnvironment())) { string jsId = "JobPrepAndRelease-" + /* "OM-static-c" */ "dynamic-" + CraftTimeString() + "-" + TestUtilities.GetMyName(); try { // increase request timeout interceptor Protocol.RequestInterceptor increaseTimeoutInterceptor = new Protocol.RequestInterceptor((x) => { this.testOutputHelper.WriteLine("TestOMJobSpecAndRelease: setting request timeout. Request type: " + x.GetType().ToString() + ", ClientRequestID: " + x.Options.ClientRequestId); var timeoutOptions = x.Options as Protocol.Models.ITimeoutOptions; timeoutOptions.Timeout = 5 * 60; }); // lets use a timer too CallTimerViaInterceptors timerInterceptor = new CallTimerViaInterceptors(); // seeing client side timeouts... so increase the durations on every call client.CustomBehaviors.Add(increaseTimeoutInterceptor); // add a call timer spammer/logger client.CustomBehaviors.Add(timerInterceptor.ReqInterceptor); // get some resource files to play with IList <ResourceFile> resFiles = UploadFilesMakeResFiles(stagingCreds); // create job schedule with prep/release { CloudJobSchedule unboundJobSchedule = client.JobScheduleOperations.CreateJobSchedule(jsId, null, null); unboundJobSchedule.JobSpecification = new JobSpecification(new PoolInformation()); unboundJobSchedule.JobSpecification.PoolInformation.PoolId = this.poolFixture.PoolId; unboundJobSchedule.Schedule = new Schedule() { RecurrenceInterval = TimeSpan.FromMinutes(3) }; // add the jobPrep task to the job schedule { JobPreparationTask prep = new JobPreparationTask(JobPrepCommandLine); unboundJobSchedule.JobSpecification.JobPreparationTask = prep; List <EnvironmentSetting> prepEnvSettings = new List <EnvironmentSetting>(); prepEnvSettings.Add(JobPrepEnvSettingOM); prep.EnvironmentSettings = prepEnvSettings; prep.Id = JobPrepId; prep.RerunOnComputeNodeRebootAfterSuccess = JobPrepRerunOnComputeNodeRebootAfterSuccess; prep.ResourceFiles = resFiles; // bug: incorrect type this should be IList<> /* * prep.ResourceFiles = new List<ResourceFile>(); // this is actually read into our concurrent iList thing * * // why not, merge them in. exersize the concurent IList thing * foreach (ResourceFile curRF in resFiles) * { * prep.ResourceFiles.Add(curRF); * } */ prep.UserIdentity = new UserIdentity(JobPrepUserSpec); prep.Constraints = JobPrepTaskConstraintsOM; prep.WaitForSuccess = JobPrepWaitForSuccessCreate; } // add a jobRelease task to the job schedule { JobReleaseTask relTask = new JobReleaseTask(JobReleaseTaskCommandLine); unboundJobSchedule.JobSpecification.JobReleaseTask = relTask; List <EnvironmentSetting> relEnvSettings = new List <EnvironmentSetting>(); relEnvSettings.Add(JobRelEnvSettingOM); relTask.EnvironmentSettings = relEnvSettings; relTask.MaxWallClockTime = JobRelMaxWallClockTime; relTask.Id = JobRelId; relTask.ResourceFiles = null; relTask.ResourceFiles = new List <ResourceFile>(); // why not, merge them in. work the concurrent IList thing foreach (ResourceFile curRF in resFiles) { relTask.ResourceFiles.Add(curRF); } relTask.RetentionTime = JobRelRetentionTime; relTask.UserIdentity = new UserIdentity(JobRelUserSpec); } // set JobCommonEnvSettings { List <EnvironmentSetting> jobCommonES = new List <EnvironmentSetting>(); jobCommonES.Add(JobCommonEnvSettingOM); unboundJobSchedule.JobSpecification.CommonEnvironmentSettings = jobCommonES; } // add the job schedule to the service unboundJobSchedule.Commit(); } // now we have a jobschedule with jobprep/release...now test the values on the jobschedule { CloudJobSchedule boundJobSchedule = client.JobScheduleOperations.GetJobSchedule(jsId); Assert.NotNull(boundJobSchedule); Assert.NotNull(boundJobSchedule.JobSpecification); Assert.NotNull(boundJobSchedule.JobSpecification.JobPreparationTask); Assert.NotNull(boundJobSchedule.JobSpecification.JobReleaseTask); Assert.NotNull(boundJobSchedule.JobSpecification.CommonEnvironmentSettings); AssertGoodCommonEnvSettingsOM(boundJobSchedule.JobSpecification.CommonEnvironmentSettings); AssertGoodJobPrepTaskOM(boundJobSchedule.JobSpecification.JobPreparationTask); AssertGoodJobReleaseTaskOM(boundJobSchedule.JobSpecification.JobReleaseTask); AssertGoodResourceFiles(resFiles, boundJobSchedule.JobSpecification.JobPreparationTask.ResourceFiles); AssertGoodResourceFiles(resFiles, boundJobSchedule.JobSpecification.JobReleaseTask.ResourceFiles); //todo: test mutability } CloudJobSchedule boundJobScheduleWithJob; // set on job test // test the values on the job { boundJobScheduleWithJob = TestUtilities.WaitForJobOnJobSchedule(client.JobScheduleOperations, jsId); CloudJob bndJob = client.JobOperations.GetJob(boundJobScheduleWithJob.ExecutionInformation.RecentJob.Id); Assert.NotNull(bndJob); Assert.NotNull(bndJob.CommonEnvironmentSettings); Assert.NotNull(bndJob.JobPreparationTask); Assert.NotNull(bndJob.JobReleaseTask); AssertGoodCommonEnvSettingsOM(bndJob.CommonEnvironmentSettings as IList <EnvironmentSetting> /* we know it is our internal IList */); AssertGoodJobPrepTaskOM(bndJob.JobPreparationTask); AssertGoodJobReleaseTaskOM(bndJob.JobReleaseTask); AssertGoodResourceFiles(resFiles, bndJob.JobPreparationTask.ResourceFiles); AssertGoodResourceFiles(resFiles, bndJob.JobReleaseTask.ResourceFiles); //TODO: test immutability } // used for on get-status test CloudJobSchedule updatedJobSchedule; // test update on the WI jobprep/jobrelease { // change props boundJobScheduleWithJob.JobSpecification.JobPreparationTask.WaitForSuccess = JobPrepWaitForSuccessUpdate; // commit changes boundJobScheduleWithJob.Commit(); // get new values updatedJobSchedule = client.JobScheduleOperations.GetJobSchedule(jsId); // confirm values changed Assert.Equal(JobPrepWaitForSuccessUpdate, updatedJobSchedule.JobSpecification.JobPreparationTask.WaitForSuccess); } TestGetPrepReleaseStatusCalls(client, updatedJobSchedule, this.poolFixture.PoolId, resFiles); } finally { // cleanup TestUtilities.DeleteJobScheduleIfExistsAsync(client, jsId).Wait(); } } }; SynchronizationContextHelper.RunTest(test, LongTestTimeout); }
/// <summary> /// Create a JobScheduleModel backed by a CloudJobSchedule /// </summary> public JobScheduleModel(CloudJobSchedule jobSchedule) { this.JobSchedule = jobSchedule; this.LastUpdatedTime = DateTime.UtcNow; }
public void Bug1965363_2384616_Wat7OSVersionFeatures() { Action test = () => { using (BatchClient batchCli = TestUtilities.OpenBatchClientAsync(TestUtilities.GetCredentialsFromEnvironment()).Result) { PoolOperations poolOperations = batchCli.PoolOperations; try { this.testOutputHelper.WriteLine("Listing OS Versions:"); /* bug 2384616 ListOsVersions hidden for wat 8 * * // test ListOSVersion * foreach (OSVersion curOSV in poolMgr.ListOSVersions()) * { * this.testOutputHelper.WriteLine("Label: " + curOSV.Label); * this.testOutputHelper.WriteLine(" Version: " + curOSV.Version); * this.testOutputHelper.WriteLine(" Family: " + curOSV.Family); * this.testOutputHelper.WriteLine(" FamilyLabel: " + curOSV.FamilyLabel); * this.testOutputHelper.WriteLine(" isDefault: " + curOSV.IsDefault); * this.testOutputHelper.WriteLine(" IsActive: " + curOSV.IsActive); * * string expDate; * * if (curOSV.ExpirationDate.HasValue) * { * expDate = curOSV.ExpirationDate.Value.ToString(); * } * else * { * expDate = "<null/novalue>"; * } * * this.testOutputHelper.WriteLine(" ExpirationDate: " + expDate); * } * */ // create pool tests // forget to set CloudServiceConfiguration on Create, get error { CloudPool noArgs = poolOperations.CreatePool("Bug1965363ButNoOSFamily-" + TestUtilities.GetMyName(), PoolFixture.VMSize, default(CloudServiceConfiguration), targetDedicated: 0); BatchException ex = TestUtilities.AssertThrows <BatchException>(() => noArgs.Commit()); string exStr = ex.ToString(); // we are expecting an exception, assert if the exception is not the correct one. Assert.Contains("cloudServiceConfiguration", exStr); } // create a pool WITH an osFamily { string poolIdHOSF = "Bug1965363HasOSF-" + TestUtilities.GetMyName(); try { CloudPool hasOSF = poolOperations.CreatePool(poolIdHOSF, PoolFixture.VMSize, new CloudServiceConfiguration(PoolFixture.OSFamily), targetDedicated: 0); hasOSF.Commit(); } finally { poolOperations.DeletePool(poolIdHOSF); } } // TODO: ultimately we will either need to find (via list) a family with more than one version or // manually update these strings as OS versions are depricated //See here for other OS versions if this test fails: http://azure.microsoft.com/en-us/documentation/articles/cloud-services-guestos-update-matrix/ const string familyVersion0 = "*"; const string familyVersion1 = "WA-GUEST-OS-4.32_201605-01"; // "UpdatePoolOS" tests (ChangeOSVersion in OM) // PoolManager { string poolIdChangeOSV = "Bug1965363ChangeOSVviaMGR-" + TestUtilities.GetMyName(); try { CloudPool unboundPool = poolOperations.CreatePool( poolIdChangeOSV, PoolFixture.VMSize, new CloudServiceConfiguration(PoolFixture.OSFamily, familyVersion0), // start with version 0 targetDedicated: 0); unboundPool.Commit(); // fetch the bound pool CloudPool boundPool = poolOperations.GetPool(poolIdChangeOSV); Assert.Equal(familyVersion0, boundPool.CloudServiceConfiguration.CurrentOSVersion); // switch to new version poolOperations.ChangeOSVersion(poolIdChangeOSV, familyVersion1); // UpdatePoolOS is has latency??? PollForOSVersionChange(boundPool, familyVersion1); // check to make sure the new value is set boundPool.Refresh(); Assert.Equal(familyVersion1, boundPool.CloudServiceConfiguration.CurrentOSVersion); } finally { TestUtilities.DeletePoolIfExistsAsync(batchCli, poolIdChangeOSV).Wait(); } } // ICloudPool { string poolIdChangeOSV = "Bug1965363ChangeOSVviaPool-" + TestUtilities.GetMyName(); try { CloudPool unboundPool = poolOperations.CreatePool( poolIdChangeOSV, PoolFixture.VMSize, new CloudServiceConfiguration(PoolFixture.OSFamily, familyVersion0), // start with version 0 targetDedicated: 0); unboundPool.Commit(); // fetch the bound pool CloudPool boundPool = poolOperations.GetPool(poolIdChangeOSV); Assert.Equal(familyVersion0, boundPool.CloudServiceConfiguration.CurrentOSVersion); // switch to new version boundPool.ChangeOSVersion(familyVersion1); // UpdatePoolOS is has latency??? PollForOSVersionChange(boundPool, familyVersion1); // check to make sure the new value is set boundPool.Refresh(); Assert.Equal(familyVersion1, boundPool.CloudServiceConfiguration.CurrentOSVersion); } finally { TestUtilities.DeletePoolIfExistsAsync(batchCli, poolIdChangeOSV).Wait(); } } // autopoolspec tests { string jobId = "Bug1965363WIName-" + TestUtilities.GetMyName(); // test not setting osversion try { CloudJob unboundJob = batchCli.JobOperations.CreateJob(jobId, new PoolInformation()); AutoPoolSpecification aps = new AutoPoolSpecification(); PoolSpecification ps = new PoolSpecification(); // test unbound set constraint ps.CloudServiceConfiguration = new CloudServiceConfiguration(PoolFixture.OSFamily); // test unbound get constraint this.testOutputHelper.WriteLine("pus.CloudServiceConfiguration.OSFamily == " + ps.CloudServiceConfiguration.OSFamily); ps.VirtualMachineSize = PoolFixture.VMSize; ps.TargetDedicated = 0; // trivial size for testing purposes aps.PoolSpecification = ps; aps.PoolLifetimeOption = PoolLifetimeOption.Job; unboundJob.PoolInformation.AutoPoolSpecification = aps; // commit to test validation unboundJob.Commit(); // get bound job CloudJob boundJob = batchCli.JobOperations.GetJob(jobId); // test bound get constraints this.testOutputHelper.WriteLine(" OSFamily == " + boundJob.PoolInformation.AutoPoolSpecification.PoolSpecification.CloudServiceConfiguration.OSFamily); string targetOSVersion = boundJob.PoolInformation.AutoPoolSpecification.PoolSpecification.CloudServiceConfiguration.TargetOSVersion; if (string.IsNullOrEmpty(targetOSVersion)) { targetOSVersion = "<null or empty"; } this.testOutputHelper.WriteLine(" TargetOSVersion == " + targetOSVersion); } finally { // cleanup TestUtilities.DeleteJobIfExistsAsync(batchCli, jobId).Wait(); } { string jobScheduleId = "Bug1965363WINameSettingAndChanging-" + TestUtilities.GetMyName(); // test setting osversion try { AutoPoolSpecification aps = new AutoPoolSpecification(); PoolSpecification ps = new PoolSpecification(); CloudJobSchedule unboundJobSchedule = batchCli.JobScheduleOperations.CreateJobSchedule( jobScheduleId, new Schedule() { RecurrenceInterval = TimeSpan.FromDays(7) }, new JobSpecification(new PoolInformation() { AutoPoolSpecification = aps })); // test unbound set constraint ps.CloudServiceConfiguration = new CloudServiceConfiguration(PoolFixture.OSFamily, familyVersion0); // test unbound get constraint this.testOutputHelper.WriteLine("pus.CloudServiceConfiguration.OSFamily == " + ps.CloudServiceConfiguration.OSFamily); this.testOutputHelper.WriteLine("pus.CloudServiceConfiguration.TargetOSVersion == " + ps.CloudServiceConfiguration.TargetOSVersion); ps.VirtualMachineSize = PoolFixture.VMSize; ps.TargetDedicated = 0; // trivial size for testing purposes aps.PoolSpecification = ps; aps.PoolLifetimeOption = PoolLifetimeOption.Job; unboundJobSchedule.Commit(); // get bound job schedule CloudJobSchedule boundJobSchedule = batchCli.JobScheduleOperations.GetJobSchedule(jobScheduleId); // test bound get constraints this.testOutputHelper.WriteLine(" OSFamily == " + boundJobSchedule.JobSpecification.PoolInformation.AutoPoolSpecification.PoolSpecification.CloudServiceConfiguration.OSFamily); this.testOutputHelper.WriteLine(" TargetOSVersion == " + boundJobSchedule.JobSpecification.PoolInformation.AutoPoolSpecification.PoolSpecification.CloudServiceConfiguration.TargetOSVersion); // assert the value is as set above Assert.Equal(familyVersion0, boundJobSchedule.JobSpecification.PoolInformation.AutoPoolSpecification.PoolSpecification.CloudServiceConfiguration.TargetOSVersion); // change values const string altFamily = "3"; const string altOSVersion = "WA-GUEST-OS-3.39_201605-01"; // change values on the bound PUS PoolSpecification boundPS = boundJobSchedule.JobSpecification.PoolInformation.AutoPoolSpecification.PoolSpecification; boundPS.CloudServiceConfiguration = new CloudServiceConfiguration(altFamily, altOSVersion); // flush changes boundJobSchedule.Commit(); // confirm changes took boundJobSchedule.Refresh(); Assert.Equal(altFamily, boundJobSchedule.JobSpecification.PoolInformation.AutoPoolSpecification.PoolSpecification.CloudServiceConfiguration.OSFamily); Assert.Equal(altOSVersion, boundJobSchedule.JobSpecification.PoolInformation.AutoPoolSpecification.PoolSpecification.CloudServiceConfiguration.TargetOSVersion); } finally { // cleanup TestUtilities.DeleteJobScheduleIfExistsAsync(batchCli, jobScheduleId).Wait(); } } } } catch (Exception ex) { // special case os version beacuse it is a common failure and requires human intervention/editing // test for expired os version Assert.DoesNotContain("The specified OS Version does not exists", ex.ToString()); throw; } } }; SynchronizationContextHelper.RunTest(test, TestTimeout); }
public void SampleCreateJobScheduleAutoPool() { Action test = () => { using (BatchClient batchCli = TestUtilities.OpenBatchClientAsync(TestUtilities.GetCredentialsFromEnvironment()).Result) { string jsId = Microsoft.Azure.Batch.Constants.DefaultConveniencePrefix + TestUtilities.GetMyName() + "-CreateWiAutoPoolTest"; try { CloudJobSchedule newJobSchedule = batchCli.JobScheduleOperations.CreateJobSchedule(jsId, null, null); { newJobSchedule.Metadata = MakeMetaData("onCreateName", "onCreateValue"); PoolInformation poolInformation = new PoolInformation(); AutoPoolSpecification iaps = new AutoPoolSpecification(); Schedule schedule = new Schedule() { RecurrenceInterval = TimeSpan.FromMinutes(18) }; poolInformation.AutoPoolSpecification = iaps; iaps.AutoPoolIdPrefix = Microsoft.Azure.Batch.Constants.DefaultConveniencePrefix + TestUtilities.GetMyName(); iaps.PoolLifetimeOption = Microsoft.Azure.Batch.Common.PoolLifetimeOption.Job; iaps.KeepAlive = false; PoolSpecification ps = new PoolSpecification(); iaps.PoolSpecification = ps; ps.TargetDedicated = 1; ps.VirtualMachineSize = PoolFixture.VMSize; ps.CloudServiceConfiguration = new CloudServiceConfiguration(PoolFixture.OSFamily); ps.Metadata = MakeMetaData("pusMDIName", "pusMDIValue"); JobSpecification jobSpec = newJobSchedule.JobSpecification; Assert.Null(jobSpec); jobSpec = new JobSpecification(poolInformation); JobManagerTask jobMgr = jobSpec.JobManagerTask; Assert.Null(jobMgr); jobMgr = new JobManagerTask(TestUtilities.GetMyName() + "-JobManagerTest", "hostname"); jobMgr.KillJobOnCompletion = false; // set the JobManagerTask on the JobSpecification jobSpec.JobManagerTask = jobMgr; // set the JobSpecifcation on the Job Schedule newJobSchedule.JobSpecification = jobSpec; newJobSchedule.Schedule = schedule; newJobSchedule.Commit(); } CloudJobSchedule jobSchedule = batchCli.JobScheduleOperations.GetJobSchedule(jsId); { TestUtilities.DisplayJobScheduleLong(this.testOutputHelper, jobSchedule); List <MetadataItem> mdi = new List <MetadataItem>(jobSchedule.Metadata); // check the values specified for AddJobSchedule are correct. foreach (MetadataItem curIMDI in mdi) { Assert.Equal("onCreateName", curIMDI.Name); Assert.Equal("onCreateValue", curIMDI.Value); } // add metadata items mdi.Add(new MetadataItem("modifiedName", "modifiedValue")); jobSchedule.Metadata = mdi; jobSchedule.Commit(); // confirm metadata updated correctly CloudJobSchedule jsUpdated = batchCli.JobScheduleOperations.GetJobSchedule(jsId); { List <MetadataItem> updatedMDI = new List <MetadataItem>(jsUpdated.Metadata); Assert.Equal(2, updatedMDI.Count); Assert.Equal("onCreateName", updatedMDI[0].Name); Assert.Equal("onCreateValue", updatedMDI[0].Value); Assert.Equal("modifiedName", updatedMDI[1].Name); Assert.Equal("modifiedValue", updatedMDI[1].Value); } jobSchedule.Refresh(); TestUtilities.DisplayJobScheduleLong(this.testOutputHelper, jobSchedule); } } finally { // clean up TestUtilities.DeleteJobScheduleIfExistsAsync(batchCli, jsId).Wait(); } } }; SynchronizationContextHelper.RunTest(test, TestTimeout); }
/// <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 Bug1433008JobScheduleScheduleNewable() { Action test = () => { using (BatchClient batchCli = TestUtilities.OpenBatchClientAsync(TestUtilities.GetCredentialsFromEnvironment()).Result) { string jsId = Microsoft.Azure.Batch.Constants.DefaultConveniencePrefix + TestUtilities.GetMyName() + "-Bug1433008JobScheduleScheduleNewable"; try { DateTime unboundDNRU = DateTime.UtcNow.AddYears(1); CloudJobSchedule newJobSchedule = batchCli.JobScheduleOperations.CreateJobSchedule(jsId, null, null); { AutoPoolSpecification iaps = new AutoPoolSpecification(); PoolSpecification ips = new PoolSpecification(); JobSpecification jobSpecification = new JobSpecification(new PoolInformation() { AutoPoolSpecification = iaps }); iaps.PoolSpecification = ips; iaps.AutoPoolIdPrefix = Microsoft.Azure.Batch.Constants.DefaultConveniencePrefix + TestUtilities.GetMyName(); iaps.PoolLifetimeOption = Microsoft.Azure.Batch.Common.PoolLifetimeOption.Job; iaps.KeepAlive = false; PoolSpecification ps = iaps.PoolSpecification; ps.TargetDedicated = 1; ps.VirtualMachineSize = PoolFixture.VMSize; ps.CloudServiceConfiguration = new CloudServiceConfiguration(PoolFixture.OSFamily); Schedule sched = new Schedule(); sched.DoNotRunUntil = unboundDNRU; newJobSchedule.Schedule = sched; newJobSchedule.JobSpecification = jobSpecification; newJobSchedule.Commit(); } CloudJobSchedule jobSchedule = batchCli.JobScheduleOperations.GetJobSchedule(jsId); // confirm that the original value(s) are set TestUtilities.DisplayJobScheduleLong(this.testOutputHelper, jobSchedule); Assert.Equal(unboundDNRU, jobSchedule.Schedule.DoNotRunUntil); // now update the schedule and confirm DateTime boundDNRU = DateTime.UtcNow.AddYears(2); jobSchedule.Schedule.DoNotRunUntil = boundDNRU; jobSchedule.Commit(); jobSchedule.Refresh(); // confirm that the new value(s) are set TestUtilities.DisplayJobScheduleLong(this.testOutputHelper, jobSchedule); Assert.Equal(boundDNRU, jobSchedule.Schedule.DoNotRunUntil); } finally { // clean up TestUtilities.DeleteJobScheduleIfExistsAsync(batchCli, jsId).Wait(); } } }; SynchronizationContextHelper.RunTest(test, TestTimeout); }
/// <summary> /// Creates a job schedule with the specified options. /// </summary> /// <param name="options">The options describing the job schedule to create.</param> /// <returns></returns> public async Task CreateJobScheduleAsync(CreateJobScheduleOptions options) { CloudJobSchedule unboundJobSchedule = this.Client.JobScheduleOperations.CreateJobSchedule(); unboundJobSchedule.Id = options.JobScheduleId; PoolInformation poolInformation = new PoolInformation(); if (options.AutoPoolOptions.UseAutoPool.HasValue && options.AutoPoolOptions.UseAutoPool.Value) { AutoPoolSpecification autoPoolSpecification = new AutoPoolSpecification() { AutoPoolIdPrefix = options.AutoPoolOptions.AutoPoolPrefix, KeepAlive = options.AutoPoolOptions.KeepAlive, PoolLifetimeOption = (PoolLifetimeOption)Enum.Parse(typeof(PoolLifetimeOption), options.AutoPoolOptions.LifeTimeOption), PoolSpecification = new PoolSpecification() { CloudServiceConfiguration = new CloudServiceConfiguration(options.AutoPoolOptions.OSFamily), VirtualMachineSize = options.AutoPoolOptions.VirutalMachineSize, TargetDedicated = options.AutoPoolOptions.TargetDedicated } }; poolInformation.AutoPoolSpecification = autoPoolSpecification; } else { poolInformation.PoolId = options.PoolId; } unboundJobSchedule.JobSpecification = new JobSpecification() { Priority = options.Priority, PoolInformation = poolInformation }; // TODO: These are read only unboundJobSchedule.JobSpecification.Constraints = new JobConstraints(options.MaxWallClockTime, options.MaxRetryCount); Schedule schedule = new Schedule() { DoNotRunAfter = options.DoNotRunAfter, DoNotRunUntil = options.DoNotRunUntil, RecurrenceInterval = options.RecurrenceInterval, StartWindow = options.StartWindow }; unboundJobSchedule.Schedule = schedule; if (options.CreateJobManager.HasValue && options.CreateJobManager.Value == true) { JobManagerTask jobManager = new JobManagerTask() { CommandLine = options.JobManagerOptions.CommandLine, KillJobOnCompletion = options.JobManagerOptions.KillOnCompletion, Id = options.JobManagerOptions.JobManagerId }; jobManager.Constraints = new TaskConstraints(options.JobManagerOptions.MaxTaskWallClockTime, options.JobManagerOptions.RetentionTime, options.JobManagerOptions.MaxTaskRetryCount); unboundJobSchedule.JobSpecification.JobManagerTask = jobManager; } await unboundJobSchedule.CommitAsync(); }
public void TestBoundJobScheduleCommit() { Action test = () => { using (BatchClient batchCli = TestUtilities.OpenBatchClientAsync(TestUtilities.GetCredentialsFromEnvironment()).Result) { string jobScheduleId = Microsoft.Azure.Batch.Constants.DefaultConveniencePrefix + TestUtilities.GetMyName() + "-TestBoundJobScheduleCommit"; try { // // Create the job schedule // const int jobSchedulePriority = 5; const string jobManagerId = "TestBoundJobScheduleCommit"; const string jobManagerCommandLine = "ping 127.0.0.1 -n 500"; IList <MetadataItem> metadata = new List <MetadataItem> { new MetadataItem("key1", "test1"), new MetadataItem("key2", "test2") }; CloudJobSchedule jobSchedule = batchCli.JobScheduleOperations.CreateJobSchedule(jobScheduleId, null, null); TimeSpan firstRecurrenceInterval = TimeSpan.FromMinutes(2); jobSchedule.Schedule = new Schedule() { RecurrenceInterval = firstRecurrenceInterval }; PoolInformation poolInfo = new PoolInformation() { PoolId = this.poolFixture.PoolId }; jobSchedule.JobSpecification = new JobSpecification(poolInfo) { Priority = jobSchedulePriority, JobManagerTask = new JobManagerTask(jobManagerId, jobManagerCommandLine) }; jobSchedule.Metadata = metadata; this.testOutputHelper.WriteLine("Initial job schedule commit()"); jobSchedule.Commit(); //Get the bound job schedule CloudJobSchedule boundJobSchedule = batchCli.JobScheduleOperations.GetJobSchedule(jobScheduleId); //Ensure the job schedule is structured as expected AssertJobScheduleCorrectness(batchCli.JobScheduleOperations, boundJobSchedule, this.poolFixture.PoolId, jobSchedulePriority, jobManagerId, jobManagerCommandLine, firstRecurrenceInterval, metadata); //Update the bound job schedule schedule TimeSpan recurrenceInterval = TimeSpan.FromMinutes(5); boundJobSchedule.Schedule = new Schedule() { RecurrenceInterval = recurrenceInterval }; this.testOutputHelper.WriteLine("Updating JobSchedule Schedule"); boundJobSchedule.Commit(); //Ensure the job schedule is correct after commit AssertJobScheduleCorrectness(batchCli.JobScheduleOperations, boundJobSchedule, this.poolFixture.PoolId, jobSchedulePriority, jobManagerId, jobManagerCommandLine, recurrenceInterval, metadata); //Update the bound job schedule priority const int newJobSchedulePriority = 1; boundJobSchedule.JobSpecification.Priority = newJobSchedulePriority; this.testOutputHelper.WriteLine("Updating JobSpecification.Priority"); boundJobSchedule.Commit(); //Ensure the job schedule is correct after commit AssertJobScheduleCorrectness(batchCli.JobScheduleOperations, boundJobSchedule, this.poolFixture.PoolId, newJobSchedulePriority, jobManagerId, jobManagerCommandLine, recurrenceInterval, metadata); //Update the bound job schedule job manager commandline const string newJobManagerCommandLine = "ping 127.0.0.1 -n 150"; boundJobSchedule.JobSpecification.JobManagerTask.CommandLine = newJobManagerCommandLine; this.testOutputHelper.WriteLine("Updating JobSpecification.JobManagerTask.CommandLine"); boundJobSchedule.Commit(); //Ensure the job schedule is correct after commit AssertJobScheduleCorrectness(batchCli.JobScheduleOperations, boundJobSchedule, this.poolFixture.PoolId, newJobSchedulePriority, jobManagerId, newJobManagerCommandLine, recurrenceInterval, metadata); //Update the bound job schedule PoolInformation const string newPoolId = "TestPool"; boundJobSchedule.JobSpecification.PoolInformation = new PoolInformation() { PoolId = newPoolId }; this.testOutputHelper.WriteLine("Updating PoolInformation"); boundJobSchedule.Commit(); //Ensure the job schedule is correct after commit AssertJobScheduleCorrectness( batchCli.JobScheduleOperations, boundJobSchedule, newPoolId, newJobSchedulePriority, jobManagerId, newJobManagerCommandLine, recurrenceInterval, metadata); //Update the bound job schedule Metadata IList <MetadataItem> newMetadata = new List <MetadataItem> { new MetadataItem("Object", "Model") }; boundJobSchedule.Metadata = newMetadata; this.testOutputHelper.WriteLine("Updating Metadata"); boundJobSchedule.Commit(); //Ensure the job schedule is correct after commit AssertJobScheduleCorrectness( batchCli.JobScheduleOperations, boundJobSchedule, newPoolId, newJobSchedulePriority, jobManagerId, newJobManagerCommandLine, recurrenceInterval, newMetadata); } finally { batchCli.JobScheduleOperations.DeleteJobSchedule(jobScheduleId); } } }; SynchronizationContextHelper.RunTest(test, TestTimeout); }