/// <summary> /// Submit a job to be run on Azure. /// </summary> /// <param name="job">Job parameters.</param> /// <param name="ct">Cancellation token.</param> /// <param name="UpdateStatus">Action which will display job submission status to the user.</param> public async Task SubmitJobAsync(JobParameters job, CancellationToken ct, Action <string> UpdateStatus) { if (batchClient == null || storageClient == null) { throw new Exception("Unable to submit job to Azure: no credentials provided"); } // Initialise a working directory. UpdateStatus("Initialising job environment..."); string workingDirectory = Path.Combine(Path.GetTempPath(), job.ID.ToString()); Directory.CreateDirectory(workingDirectory); // Set job owner. string owner = Environment.UserName.ToLower(); await SetAzureMetaDataAsync("job-" + job.ID, "Owner", owner, ct); if (ct.IsCancellationRequested) { UpdateStatus("Cancelled"); return; } // If the ApsimX path is a directory it will need to be compressed. if (Directory.Exists(job.ApsimXPath)) { UpdateStatus("Compressing APSIM Next Generation..."); string zipFile = Path.Combine(workingDirectory, $"Apsim-tmp-X-{owner}.zip"); if (File.Exists(zipFile)) { File.Delete(zipFile); } CreateApsimXZip(job.ApsimXPath, zipFile, ct); job.ApsimXPath = zipFile; job.ApsimXVersion = Path.GetFileName(zipFile).Substring(Path.GetFileName(zipFile).IndexOf('-') + 1); } if (ct.IsCancellationRequested) { UpdateStatus("Cancelled"); return; } // Upload tools such as 7zip, AzCopy, CMail, etc. UpdateStatus("Uploading tools..."); string executableDirectory = Path.GetDirectoryName(GetType().Assembly.Location); string toolsDir = Path.Combine(executableDirectory, "tools"); if (!Directory.Exists(toolsDir)) { throw new Exception("Tools Directory not found: " + toolsDir); } foreach (string filePath in Directory.EnumerateFiles(toolsDir)) { await UploadFileIfNeededAsync("tools", filePath, ct); if (ct.IsCancellationRequested) { UpdateStatus("Cancelled"); return; } } // Upload email config file. if (job.SendEmail) { Licence licence = new Licence(AzureSettings.Default.LicenceFilePath); StringBuilder config = new StringBuilder(); config.AppendLine($"EmailRecipient={job.EmailRecipient}"); config.AppendLine($"EmailSender={licence.EmailSender}"); config.AppendLine($"EmailPW={licence.EmailPW}"); // Write these settings to a temporary config file. string configFile = Path.Combine(workingDirectory, "settings.txt"); File.WriteAllText(configFile, config.ToString()); await UploadFileIfNeededAsync("job-" + job.ID, configFile, ct); File.Delete(configFile); } if (ct.IsCancellationRequested) { UpdateStatus("Cancelled"); return; } // Upload job manager. UpdateStatus("Uploading job manager..."); await UploadFileIfNeededAsync("jobmanager", Path.Combine(executableDirectory, "azure-apsim.exe"), ct); if (ct.IsCancellationRequested) { UpdateStatus("Cancelled"); return; } // Upload apsim. UpdateStatus("Uploading APSIM Next Generation..."); await UploadFileIfNeededAsync("apsim", job.ApsimXPath, ct); if (ct.IsCancellationRequested) { UpdateStatus("Cancelled"); return; } // Generate model files. UpdateStatus("Generating model files..."); if (!Directory.Exists(job.ModelPath)) { Directory.CreateDirectory(job.ModelPath); } if (ct.IsCancellationRequested) { UpdateStatus("Cancelled"); return; } // Generate .apsimx file for each simulation to be run. Runner run = new Runner(job.Model); GenerateApsimXFiles.Generate(run, job.ModelPath, p => { /* Don't bother with progress reporting */ }, collectExternalFiles: true); if (ct.IsCancellationRequested) { UpdateStatus("Cancelled"); return; } // Compress model (.apsimx file) directory. UpdateStatus("Compressing model files..."); string tmpZip = Path.Combine(workingDirectory, $"Model-{Guid.NewGuid()}.zip"); ZipFile.CreateFromDirectory(job.ModelPath, tmpZip, CompressionLevel.Fastest, false); job.ModelPath = tmpZip; if (ct.IsCancellationRequested) { UpdateStatus("Cancelled"); return; } // Upload models. UpdateStatus("Uploading model files..."); string modelZipFileSas = await UploadFileIfNeededAsync(job.ID.ToString(), job.ModelPath, ct); if (ct.IsCancellationRequested) { UpdateStatus("Cancelled"); return; } // Clean up temp files. UpdateStatus("Deleting temp files..."); Directory.Delete(workingDirectory, true); // Submit job. UpdateStatus("Submitting Job..."); CloudJob cloudJob = batchClient.JobOperations.CreateJob(job.ID.ToString(), GetPoolInfo(job)); cloudJob.DisplayName = job.DisplayName; cloudJob.JobPreparationTask = CreateJobPreparationTask(job, modelZipFileSas); cloudJob.JobReleaseTask = CreateJobReleaseTask(job, modelZipFileSas); cloudJob.JobManagerTask = CreateJobManagerTask(job); await cloudJob.CommitAsync(cancellationToken : ct); UpdateStatus("Job Successfully submitted"); }
public void TestManagerParameterChanges() { Manager m = new Manager() { Name = "Manager", Code = "using System; namespace Models { using Core; [Serializable] public class Script : Models.Core.Model { [Description(\"x\")] public string X { get; set; } } }" }; Simulations sims = new Simulations() { Children = new List <IModel>() { new DataStore(), new Experiment() { Name = "expt", Children = new List <IModel>() { new Factors() { Children = new List <IModel>() { new Factor() { Name = "x", Specification = "[Manager].Script.X = 1" } } }, new Simulation() { Name = "sim", Children = new List <IModel>() { new Clock() { StartDate = new DateTime(2020, 1, 1), EndDate = new DateTime(2020, 1, 2), Name = "Clock" }, new Summary(), m } } } } } }; sims.ParentAllDescendants(); m.OnCreated(); Runner runner = new Runner(sims); string temp = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); try { IEnumerable <string> files = GenerateApsimXFiles.Generate(runner, 1, temp, _ => {}); Assert.AreEqual(1, files.Count()); string file = files.First(); sims = FileFormat.ReadFromFile <Simulations>(file, e => throw e, false); Assert.AreEqual("1", sims.FindByPath("[Manager].Script.X").Value); } finally { if (Directory.Exists(temp)) { Directory.Delete(temp, true); } } }
public void EnsureFilesAreGeneratedForTwoSimulations() { // Create a folder of 2 simulations. var folder = new Folder() { Children = new List <Model>() { new Simulation() { Name = "Sim1", FileName = Path.GetTempFileName(), Children = new List <Model>() { new Clock() { StartDate = new DateTime(1980, 1, 1), EndDate = new DateTime(1980, 1, 2) }, new MockSummary(), } }, new Simulation() { Name = "Sim2", FileName = Path.GetTempFileName(), Children = new List <Model>() { new Clock() { StartDate = new DateTime(1980, 1, 3), EndDate = new DateTime(1980, 1, 4) }, new MockSummary(), } } } }; var path = Path.Combine(Path.GetTempPath(), "GenerateApsimXFiles"); if (Directory.Exists(path)) { Directory.Delete(path, true); } Directory.CreateDirectory(path); // Create a list of progress ints. var progress = new List <int>(); // Create a runner for our folder. Runner runner = new Runner(folder); GenerateApsimXFiles.Generate(runner, path, (s) => { progress.Add(s); }); Assert.AreEqual(progress.Count, 2); Assert.AreEqual(progress[0], 50); Assert.AreEqual(progress[1], 100); var generatedFiles = Directory.GetFiles(path); Assert.AreEqual(generatedFiles.Length, 2); Assert.AreEqual(Path.GetFileName(generatedFiles[0]), "Sim1.apsimx"); Assert.AreEqual(Path.GetFileName(generatedFiles[1]), "Sim2.apsimx"); Directory.Delete(path, true); }
public void EnsureFilesAreGeneratedForTwoSimulations() { // Create a folder of 2 simulations. var folder = new Folder() { Children = new List <IModel>() { new Simulation() { Name = "Sim1", FileName = Path.GetTempFileName(), Children = new List <IModel>() { new Clock() { StartDate = new DateTime(1980, 1, 1), EndDate = new DateTime(1980, 1, 2) }, new MockSummary(), } }, new Simulation() { Name = "Sim2", FileName = Path.GetTempFileName(), Children = new List <IModel>() { new Clock() { StartDate = new DateTime(1980, 1, 3), EndDate = new DateTime(1980, 1, 4) }, new MockSummary(), } } } }; var path = Path.Combine(Path.GetTempPath(), "GenerateApsimXFiles"); if (Directory.Exists(path)) { Directory.Delete(path, true); } Directory.CreateDirectory(path); // Create a list of progress ints. var progress = new List <double>(); // Create a runner for our folder. Runner runner = new Runner(folder); IEnumerable <string> generatedFiles = GenerateApsimXFiles.Generate(runner, 1, path, (s) => { progress.Add(s); }); Assert.AreEqual(2, progress.Count); Assert.AreEqual(0.5, progress[0]); Assert.AreEqual(1, progress[1]); Assert.AreEqual(2, generatedFiles.Count()); Assert.AreEqual("generated-0.apsimx", Path.GetFileName(generatedFiles.First())); Assert.AreEqual("generated-1.apsimx", Path.GetFileName(generatedFiles.Last())); Directory.Delete(path, true); }