Skip to content

[WIP] Draft of C# Track 2 conversion #324

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 5 additions & 16 deletions CSharp/GettingStarted/01_HelloWorld/HelloWorld.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,14 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net462</TargetFramework>
<RootNamespace>Microsoft.Azure.Batch.Samples.HelloWorld</RootNamespace>
<TargetFramework>net8.0</TargetFramework>
<RootNamespace>Azure.Compute.Batch.Samples.HelloWorld</RootNamespace>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\Common\Microsoft.Azure.Batch.Samples.Common.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Azure.Batch" Version="14.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="2.1.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.1.0" />
<PackageReference Include="WindowsAzure.Storage" Version="9.3.3" />
</ItemGroup>

<ItemGroup>
<None Update="settings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<PackageReference Include="Azure.Compute.Batch" Version="1.0.0-beta.3" />
<PackageReference Include="Azure.Identity" Version="1.14.1" />
<PackageReference Include="Azure.ResourceManager.Batch" Version="1.5.0" />
</ItemGroup>

</Project>
13 changes: 5 additions & 8 deletions CSharp/GettingStarted/01_HelloWorld/HelloWorld.sln
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26430.12
# Visual Studio Version 17
VisualStudioVersion = 17.9.34728.123
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HelloWorld", "HelloWorld.csproj", "{FE62D509-B9A9-4592-81BB-779306C22F95}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Azure.Batch.Samples.Common", "..\..\Common\Microsoft.Azure.Batch.Samples.Common.csproj", "{612B170A-1697-4C40-BD57-26A6C8AC6534}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -17,12 +15,11 @@ Global
{FE62D509-B9A9-4592-81BB-779306C22F95}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FE62D509-B9A9-4592-81BB-779306C22F95}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FE62D509-B9A9-4592-81BB-779306C22F95}.Release|Any CPU.Build.0 = Release|Any CPU
{612B170A-1697-4C40-BD57-26A6C8AC6534}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{612B170A-1697-4C40-BD57-26A6C8AC6534}.Debug|Any CPU.Build.0 = Debug|Any CPU
{612B170A-1697-4C40-BD57-26A6C8AC6534}.Release|Any CPU.ActiveCfg = Release|Any CPU
{612B170A-1697-4C40-BD57-26A6C8AC6534}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {33B77A65-5D1C-46B7-918E-D922919D6884}
EndGlobalSection
EndGlobal
153 changes: 153 additions & 0 deletions CSharp/GettingStarted/01_HelloWorld/HelloWorldSample.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
// Copyright (c) Microsoft Corporation. All rights reserved.

using Azure.Core;
using Azure.Identity;
using Azure.ResourceManager;
using Azure.ResourceManager.Batch;
using Azure.ResourceManager.Batch.Models;
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

namespace Azure.Compute.Batch.Samples.HelloWorld
{
public class HelloWorldSample
{
private ArmClient _armClient;
private BatchClient _batchClient;

/// <summary>
/// Creates a pool with a configurable number of nodes, then submits tasks which print a 'Hello world' message.
/// The resulting stdout.txt or stderr.txt (depending on each task's exit code) is then printed to the console.
///
/// After running, the job will be terminated and the pool will be deleted.
/// </summary>
/// <param name="batchAccountResourceId">The ARM resource ID of the Batch account.</param>
/// <returns>A task which completes when the sample has finished running.</returns>
public async Task Run(string batchAccountResourceId)
{
var batchAccountIdentifier = ResourceIdentifier.Parse(batchAccountResourceId);

var credential = new DefaultAzureCredential();
_armClient = new ArmClient(credential);

BatchAccountResource batchAccount = await _armClient.GetBatchAccountResource(batchAccountIdentifier).GetAsync();

_batchClient = new BatchClient(new Uri($"https://{batchAccount.Data.AccountEndpoint}"), credential);

var poolName = GenerateUniqueName("HelloWorldPool");
var imageReference = new BatchImageReference()
{
Publisher = "canonical",
Offer = "0001-com-ubuntu-server-jammy",
Sku = "22_04-lts",
Version = "latest"
};
string nodeAgentSku = "batch.node.ubuntu 22.04";
int targetDedicatedNodes = 1;

Console.WriteLine("Creating pool {0} with {1} dedicated {2} in account {3}", poolName, targetDedicatedNodes, targetDedicatedNodes == 1 ? "node" : "nodes", batchAccount.Data.Name);
BatchAccountPoolResource pool = (await batchAccount.GetBatchAccountPools().CreateOrUpdateAsync(WaitUntil.Completed, poolName, new BatchAccountPoolData()
{
VmSize = "Standard_DS1_v2",
DeploymentConfiguration = new BatchDeploymentConfiguration()
{
VmConfiguration = new BatchVmConfiguration(imageReference, nodeAgentSku)
},
ScaleSettings = new BatchAccountPoolScaleSettings()
{
FixedScale = new BatchAccountFixedScaleSettings()
{
TargetDedicatedNodes = targetDedicatedNodes
}
}
})).Value;

string jobId = GenerateUniqueName("HelloWorldJob");

try
{
Console.WriteLine("Creating job {0}", jobId);
await _batchClient.CreateJobAsync(new BatchJobCreateOptions(jobId, new BatchPoolInfo() { PoolId = poolName }));

for (int i = 0; i < 5; i++)
{
string taskId = $"task-{i}";
Console.WriteLine("Submitting {0}", taskId);
await _batchClient.CreateTaskAsync(jobId, new BatchTaskCreateOptions(taskId, $"echo Hello world from {taskId}"));
}

Console.WriteLine("Waiting for all tasks to complete...");
await waitForTasksToComplete(jobId);

var completedTasks = _batchClient.GetTasksAsync(jobId, filter: "state eq 'completed'");
await foreach (BatchTask t in completedTasks)
{
var outputFileName = t.ExecutionInfo.ExitCode == 0 ? "stdout.txt" : "stderr.txt";

Console.WriteLine("Task {0} exited with code {1}. Output ({2}):",
t.Id, t.ExecutionInfo.ExitCode, outputFileName);

BinaryData fileContents = await _batchClient.GetTaskFileAsync(jobId, t.Id, outputFileName);
using (var reader = new StreamReader(fileContents.ToStream()))
{
Console.WriteLine(await reader.ReadLineAsync());
}
}
}
finally
{
Console.WriteLine("Terminating job and deleting pool");
await Task.WhenAll([
_batchClient.TerminateJobAsync(jobId),
pool.DeleteAsync(WaitUntil.Completed)]);
}
}

/// <summary>
/// Poll all the tasks in the given job and wait for them to reach the completed state.
/// </summary>
/// <param name="jobId">The ID of the job to poll</param>
/// <returns>A task that will complete when all Batch tasks have completed.</returns>
/// <exception cref="TimeoutException">Thrown if all tasks haven't reached the completed state after a certain period of time</exception>
private async Task waitForTasksToComplete(String jobId)
{
// Note that this timeout should take into account the time it takes for the pool to scale up
var timeoutAfter = DateTime.Now.AddMinutes(10);
while (DateTime.Now < timeoutAfter)
{
var allComplete = true;
var tasks = _batchClient.GetTasksAsync(jobId, select: ["id", "state"]);
await foreach (BatchTask task in tasks)
{
if (task.State != BatchTaskState.Completed)
{
allComplete = false;
break;
}
}

if (allComplete)
{
return;
}

await Task.Delay(10000);
}

throw new TimeoutException("Task(s) did not complete within the specified time");
}

/// <summary>
/// Generate a unique name with the given prefix using the current user name and a timestamp.
/// </summary>
/// <param name="prefix">The name's prefix.</param>
/// <returns>The generated name.</returns>
private static string GenerateUniqueName(string prefix)
{
string currentUser = new string(Environment.UserName.Where(char.IsLetterOrDigit).ToArray());
return string.Format("{0}-{1}-{2}", prefix, currentUser, DateTime.Now.ToString("yyyyMMdd-HHmmss"));
}
}
}
Loading