/// <summary> /// Creates a pool if it doesn't already exist. If the pool already exists, this method resizes it to meet the expected /// targets specified in settings. /// </summary> /// <param name="batchClient">The BatchClient to use when interacting with the Batch service.</param> /// <returns>An asynchronous <see cref="Task"/> representing the operation.</returns> private async Task CreatePoolIfNotExistAsync(BatchClient batchClient) { bool successfullyCreatedPool = false; // Attempt to create the pool try { // Create an in-memory representation of the Batch pool which we would like to create. We are free to modify/update // this pool object in memory until we commit it to the service via the CommitAsync method. Console.WriteLine("Attempting to create pool: {0}", this.configurationSettings.PoolId); // You can learn more about os families and versions at: // https://azure.microsoft.com/en-us/documentation/articles/cloud-services-guestos-update-matrix/ CloudPool pool = batchClient.PoolOperations.CreatePool( poolId: this.configurationSettings.PoolId, targetDedicated: this.configurationSettings.PoolTargetNodeCount, virtualMachineSize: this.configurationSettings.PoolNodeVirtualMachineSize, osFamily: this.configurationSettings.PoolOSFamily); // Create the pool on the Batch Service await pool.CommitAsync(); successfullyCreatedPool = true; Console.WriteLine("Created pool {0} with {1} {2} nodes", pool, this.configurationSettings.PoolTargetNodeCount, this.configurationSettings.PoolNodeVirtualMachineSize); } catch (BatchException e) { // Swallow the specific error code PoolExists since that is expected if the pool already exists if (e.RequestInformation != null && e.RequestInformation.AzureError != null && e.RequestInformation.AzureError.Code == BatchErrorCodeStrings.PoolExists) { // The pool already existed when we tried to create it successfullyCreatedPool = false; Console.WriteLine("The pool already existed when we tried to create it"); } else { throw; // Any other exception is unexpected } } // If the pool already existed, make sure that its targets are correct if (!successfullyCreatedPool) { CloudPool existingPool = await batchClient.PoolOperations.GetPoolAsync(this.configurationSettings.PoolId); // If the pool doesn't have the right number of nodes and it isn't resizing then we need // to ask it to resize if (existingPool.CurrentDedicated != this.configurationSettings.PoolTargetNodeCount && existingPool.AllocationState != AllocationState.Resizing) { // Resize the pool to the desired target. Note that provisioning the nodes in the pool may take some time await existingPool.ResizeAsync(this.configurationSettings.PoolTargetNodeCount); } } }
/// <summary> /// Creates a <see cref="CloudPool"/> with the specified id and configures its StartTask with the /// specified <see cref="ResourceFile"/> collection. /// </summary> /// <param name="batchClient">A <see cref="BatchClient"/>.</param> /// <param name="poolId">The id of the <see cref="CloudPool"/> to create.</param> /// <param name="resourceFiles">A collection of <see cref="ResourceFile"/> objects representing blobs within /// a Storage account container. The StartTask will download these files from Storage prior to execution.</param> /// <returns>A <see cref="System.Threading.Tasks.Task"/> object that represents the asynchronous operation.</returns> private static async Task CreatePoolIfNotExistAsync(BatchClient batchClient, string poolId, IList <ResourceFile> resourceFiles) { CloudPool pool = null; try { Console.WriteLine("Creating pool [{0}]...", poolId); // Create the unbound pool. Until we call CloudPool.Commit() or CommitAsync(), no pool is actually created in the // Batch service. This CloudPool instance is therefore considered "unbound," and we can modify its properties. pool = batchClient.PoolOperations.CreatePool( poolId: poolId, targetDedicated: targetVMs, // 3 compute nodes virtualMachineSize: "Standard_D2_V2", virtualMachineConfiguration: new VirtualMachineConfiguration(new ImageReference("WindowsServer", "MicrosoftWindowsServer", "2016-Datacenter"), "batch.node.windows amd64")); //Ensure only 1 EncoderSim runs on each node pool.TaskSchedulingPolicy = new TaskSchedulingPolicy(ComputeNodeFillType.Pack); pool.MaxTasksPerComputeNode = 1; // Create and assign the StartTask that will be executed when compute nodes join the pool. // In this case, we copy the StartTask's resource files (that will be automatically downloaded // to the node by the StartTask) into the shared directory that all tasks will have access to. pool.StartTask = new StartTask { // Specify a command line for the StartTask that copies the task application files to the // node's shared directory. Every compute node in a Batch pool is configured with a number // of pre-defined environment variables that can be referenced by commands or applications // run by tasks. // Since a successful execution of robocopy can return a non-zero exit code (e.g. 1 when one or // more files were successfully copied) we need to manually exit with a 0 for Batch to recognize // StartTask execution success. CommandLine = $"cmd /c (robocopy %AZ_BATCH_TASK_WORKING_DIR% %AZ_BATCH_NODE_SHARED_DIR% /it /is) ^& IF %ERRORLEVEL% LEQ 1 exit 0", ResourceFiles = resourceFiles, WaitForSuccess = true, }; await pool.CommitAsync(); } catch (BatchException be) { // Swallow the specific error code PoolExists since that is expected if the pool already exists if (be.RequestInformation?.BatchError != null && be.RequestInformation.BatchError.Code == BatchErrorCodeStrings.PoolExists) { Console.WriteLine("The pool {0} already existed when we tried to create it", poolId); pool = await batchClient.PoolOperations.GetPoolAsync(PoolId); if (pool.TargetDedicated != targetVMs) { Console.WriteLine("The pool {0} is resizing to {1}", poolId, targetVMs); await pool.ResizeAsync(targetVMs); } } else { throw; // Any other exception is unexpected } } }
/// <summary> /// Creates a pool if it doesn't already exist. If the pool already exists, this method resizes it to meet the expected /// targets specified in settings. /// </summary> /// <param name="batchClient">The BatchClient to create the pool with.</param> /// <param name="pool">The pool to create.</param> /// <returns>An asynchronous <see cref="Task"/> representing the operation.</returns> public static async Task CreatePoolIfNotExistAsync(BatchClient batchClient, CloudPool pool) { bool successfullyCreatedPool = false; int poolTargetNodeCount = pool.TargetDedicated ?? 0; string poolNodeVirtualMachineSize = pool.VirtualMachineSize; string poolId = pool.Id; // Attempt to create the pool try { // Create an in-memory representation of the Batch pool which we would like to create. We are free to modify/update // this pool object in memory until we commit it to the service via the CommitAsync method. Console.WriteLine("Attempting to create pool: {0}", pool.Id); // Create the pool on the Batch Service await pool.CommitAsync().ConfigureAwait(continueOnCapturedContext: false); successfullyCreatedPool = true; Console.WriteLine("Created pool {0} with {1} {2} nodes", poolId, poolTargetNodeCount, poolNodeVirtualMachineSize); } catch (BatchException e) { // Swallow the specific error code PoolExists since that is expected if the pool already exists if (e.RequestInformation != null && e.RequestInformation.AzureError != null && e.RequestInformation.AzureError.Code == BatchErrorCodeStrings.PoolExists) { // The pool already existed when we tried to create it successfullyCreatedPool = false; Console.WriteLine("The pool already existed when we tried to create it"); } else { throw; // Any other exception is unexpected } } // If the pool already existed, make sure that its targets are correct if (!successfullyCreatedPool) { CloudPool existingPool = await batchClient.PoolOperations.GetPoolAsync(poolId).ConfigureAwait(continueOnCapturedContext: false); // If the pool doesn't have the right number of nodes, isn't resizing, and doesn't have // automatic scaling enabled, then we need to ask it to resize if (existingPool.CurrentDedicated != poolTargetNodeCount && existingPool.AllocationState != AllocationState.Resizing && existingPool.AutoScaleEnabled == false) { // Resize the pool to the desired target. Note that provisioning the nodes in the pool may take some time await existingPool.ResizeAsync(poolTargetNodeCount).ConfigureAwait(continueOnCapturedContext: false); } } }
/// <summary> /// Creates a pool if it doesn't already exist. If the pool already exists, this method resizes it to meet the expected /// targets specified in settings. /// </summary> /// <param name="batchClient">The BatchClient to use when interacting with the Batch service.</param> /// <param name="cloudStorageAccount">The CloudStorageAccount to upload start task required files to.</param> /// <returns>An asynchronous <see cref="Task"/> representing the operation.</returns> private async Task CreatePoolIfNotExistAsync(BatchClient batchClient, CloudStorageAccount cloudStorageAccount, TestJob testJob) { // You can learn more about os families and versions at: // https://azure.microsoft.com/en-us/documentation/articles/cloud-services-guestos-update-matrix/ // Attempt to create the pool bool poolExisting = false; try { CloudPool pool = batchClient.PoolOperations.CreatePool(TestJob.BatchPoolId, testJob.SizeOfVM.ToString(), new CloudServiceConfiguration(BatchOsFamily), testJob.NumofVm); // azure batch max limitation: times (4x) the number of node cores pool.MaxTasksPerComputeNode = 4 * (int)Math.Pow(2, (int)testJob.SizeOfVM); pool.TaskSchedulingPolicy = new TaskSchedulingPolicy(ComputeNodeFillType.Spread); await pool.CommitAsync(); } catch (BatchException e) { if (e.RequestInformation != null && e.RequestInformation.BatchError != null && e.RequestInformation.BatchError.Code == BatchErrorCodeStrings.PoolExists) { poolExisting = true; } else { throw; // Any other exception is unexpected } } if (poolExisting) { // The pool already existed when we tried to create it CloudPool existingPool = await batchClient.PoolOperations.GetPoolAsync(TestJob.BatchPoolId); // If the pool doesn't have the right number of nodes, isn't resizing, and doesn't have // automatic scaling enabled, then we need to ask it to resize if (existingPool.CurrentDedicated < testJob.NumofVm && existingPool.AllocationState != AllocationState.Resizing && existingPool.AutoScaleEnabled == false) { // Resize the pool to the desired target. Note that provisioning the nodes in the pool may take some time await existingPool.ResizeAsync(testJob.NumofVm); } } }
private static async Task UpScaleAsync(CloudPool pool) { await pool.ResizeAsync(2, 0, TimeSpan.FromMinutes(200), ComputeNodeDeallocationOption.TaskCompletion); }