From ea34833f3c92be22dfbd84882cc8156aa3dcd0e0 Mon Sep 17 00:00:00 2001 From: Matt Cooper Date: Tue, 31 Mar 2020 12:53:47 -0400 Subject: [PATCH] Add an ARM64 agent (#2881) * add an ARM64 agent * add ARM64 agent to release def * break dependency on libcurl for ARM * only layout the requested RID to save time * fixup a few relevant strings and dependencies --- .vsts.ci.yml | 30 +++++++++++++++++++++++ .vsts.release.yml | 29 ++++++++++++++++++++++ assets.json | 8 +++++- releaseNote.md | 10 +++++++- src/Agent.Listener/Program.cs | 9 ++++--- src/Agent.PluginHost/Program.cs | 9 ++++--- src/Agent.Sdk/Util/PlatformUtil.cs | 12 +++++++++ src/Agent.Worker/Program.cs | 10 +++++--- src/Common.props | 7 ++++-- src/Misc/externals.sh | 9 +++++-- src/Misc/layoutbin/installdependencies.sh | 22 +++++++++-------- src/Misc/layoutroot/config.sh | 24 +++++++++--------- src/Test/L0/ConstantGenerationL0.cs | 1 + src/dev.sh | 4 +-- src/dir.proj | 4 +-- 15 files changed, 144 insertions(+), 44 deletions(-) diff --git a/.vsts.ci.yml b/.vsts.ci.yml index 49b5981e26..3bcb910b79 100644 --- a/.vsts.ci.yml +++ b/.vsts.ci.yml @@ -162,6 +162,36 @@ jobs: artifactName: agent artifactType: container +################################################################################ +- job: build_linux_arm64_agent +################################################################################ + displayName: Linux Agent (ARM64) + pool: + name: buildDevs + demands: 'Agent.OSArchitecture -equals ARM64' + timeoutInMinutes: 75 + steps: + + # Steps template for non-windows platform + - template: .vsts.template.nonwindows.yml + parameters: + testLogTitle: 'Linux-ARM64' + + # Create agent package zip + - script: ./dev.sh package Release + workingDirectory: src + displayName: Package Release + condition: and(succeeded(), ne(variables['build.reason'], 'PullRequest')) + + # Upload agent package zip as build artifact + - task: PublishBuildArtifacts@1 + displayName: Publish Artifact (Linux ARM64) + condition: and(succeeded(), ne(variables['build.reason'], 'PullRequest')) + inputs: + pathToPublish: _package + artifactName: agent + artifactType: container + ################################################################################ - job: build_rhel6_x64_agent ################################################################################ diff --git a/.vsts.release.yml b/.vsts.release.yml index 5d74baffd2..b2fdd7d115 100644 --- a/.vsts.release.yml +++ b/.vsts.release.yml @@ -181,6 +181,35 @@ stages: artifactName: agent artifactType: container + ################################################################################ + - job: build_linux_agent_arm64 + ################################################################################ + displayName: Linux Agent (ARM64) + condition: false + pool: + name: buildDevs + demands: 'Agent.OSArchitecture -equals ARM64' + timeoutInMinutes: 75 + steps: + + # Steps template for non-windows platform + - template: .vsts.template.nonwindows.yml + parameters: + testLogTitle: 'Linux-ARM64' + + # Create agent package zip + - script: ./dev.sh package Release + workingDirectory: src + displayName: Package Release + + # Upload agent package zip as build artifact + - task: PublishBuildArtifacts@1 + displayName: Publish Artifact (Linux) + inputs: + pathToPublish: _package + artifactName: agent + artifactType: container + ################################################################################ - job: build_rhel6_agent_x64 ################################################################################ diff --git a/assets.json b/assets.json index 54754607b2..07c481d1cd 100644 --- a/assets.json +++ b/assets.json @@ -29,10 +29,16 @@ "version": "", "downloadUrl": "https://vstsagentpackage.azureedge.net/agent//vsts-agent-linux-arm-.tar.gz" }, + { + "name": "vsts-agent-linux-arm64-.tar.gz", + "platform": "linux-arm64", + "version": "", + "downloadUrl": "https://vstsagentpackage.azureedge.net/agent//vsts-agent-linux-arm64-.tar.gz" + }, { "name": "vsts-agent-rhel.6-x64-.tar.gz", "platform": "rhel.6-x64", "version": "", "downloadUrl": "https://vstsagentpackage.azureedge.net/agent//vsts-agent-rhel.6-x64-.tar.gz" } -] \ No newline at end of file +] diff --git a/releaseNote.md b/releaseNote.md index 6d3f6c98e8..950dc52771 100644 --- a/releaseNote.md +++ b/releaseNote.md @@ -8,6 +8,7 @@ | macOS | [vsts-agent-osx-x64-.tar.gz](https://vstsagentpackage.azureedge.net/agent//vsts-agent-osx-x64-.tar.gz) | | Linux x64 | [vsts-agent-linux-x64-.tar.gz](https://vstsagentpackage.azureedge.net/agent//vsts-agent-linux-x64-.tar.gz) | | Linux ARM | [vsts-agent-linux-arm-.tar.gz](https://vstsagentpackage.azureedge.net/agent//vsts-agent-linux-arm-.tar.gz) | +| Linux ARM64 | [vsts-agent-linux-arm64-.tar.gz](https://vstsagentpackage.azureedge.net/agent//vsts-agent-linux-arm-.tar.gz) | | RHEL 6 x64 | [vsts-agent-rhel.6-x64-.tar.gz](https://vstsagentpackage.azureedge.net/agent//vsts-agent-rhel.6-x64-.tar.gz) | After Download: @@ -26,7 +27,7 @@ C:\> mkdir myagent && cd myagent C:\myagent> Add-Type -AssemblyName System.IO.Compression.FileSystem ; [System.IO.Compression.ZipFile]::ExtractToDirectory("$HOME\Downloads\vsts-agent-win-x86-.zip", "$PWD") ``` -## OSX +## macOS ``` bash ~/$ mkdir myagent && cd myagent @@ -47,6 +48,13 @@ C:\myagent> Add-Type -AssemblyName System.IO.Compression.FileSystem ; [System.IO ~/myagent$ tar xzf ~/Downloads/vsts-agent-linux-arm-.tar.gz ``` +## Linux ARM64 + +``` bash +~/$ mkdir myagent && cd myagent +~/myagent$ tar xzf ~/Downloads/vsts-agent-linux-arm64-.tar.gz +``` + ## RHEL 6 x64 ``` bash diff --git a/src/Agent.Listener/Program.cs b/src/Agent.Listener/Program.cs index 70ae472504..87091e5193 100644 --- a/src/Agent.Listener/Program.cs +++ b/src/Agent.Listener/Program.cs @@ -18,10 +18,11 @@ public static class Program { public static int Main(string[] args) { - // We can't use the new SocketsHttpHandler for now for both Windows and Linux - // On linux, Negotiate auth is not working if the TFS url is behind Https - // On windows, Proxy is not working - AppContext.SetSwitch("System.Net.Http.UseSocketsHttpHandler", false); + if (PlatformUtil.UseLegacyHttpHandler) + { + AppContext.SetSwitch("System.Net.Http.UseSocketsHttpHandler", false); + } + using (HostContext context = new HostContext("Agent")) { return MainAsync(context, args).GetAwaiter().GetResult(); diff --git a/src/Agent.PluginHost/Program.cs b/src/Agent.PluginHost/Program.cs index ff430315a6..9907e433e0 100644 --- a/src/Agent.PluginHost/Program.cs +++ b/src/Agent.PluginHost/Program.cs @@ -24,10 +24,11 @@ public static class Program public static int Main(string[] args) { - // We can't use the new SocketsHttpHandler for now for both Windows and Linux - // On linux, Negotiate auth is not working if the TFS url is behind Https - // On windows, Proxy is not working - AppContext.SetSwitch("System.Net.Http.UseSocketsHttpHandler", false); + if (PlatformUtil.UseLegacyHttpHandler) + { + AppContext.SetSwitch("System.Net.Http.UseSocketsHttpHandler", false); + } + Console.CancelKeyPress += Console_CancelKeyPress; // Set encoding to UTF8, process invoker will use UTF8 write to STDIN diff --git a/src/Agent.Sdk/Util/PlatformUtil.cs b/src/Agent.Sdk/Util/PlatformUtil.cs index 0e785fdcb7..cb77fc62e1 100644 --- a/src/Agent.Sdk/Util/PlatformUtil.cs +++ b/src/Agent.Sdk/Util/PlatformUtil.cs @@ -124,5 +124,17 @@ public static bool IsArm64 { get => PlatformUtil.HostArchitecture == Architecture.Arm64; } + + // remove this after addressing + // https://github.com/microsoft/azure-pipelines-agent/issues/2875 + public static bool UseLegacyHttpHandler + { + // In .NET Core 2.1, we couldn't use the new SocketsHttpHandler for Windows or Linux + // On Linux, negotiate auth didn't work if the TFS URL was HTTPS + // On Windows, proxy was not working + // But on ARM/ARM64 Linux, the legacy curl dependency is problematic + // (see https://github.com/dotnet/runtime/issues/28891) + get => !(PlatformUtil.RunningOnLinux && (PlatformUtil.IsArm || PlatformUtil.IsArm64)); + } } } \ No newline at end of file diff --git a/src/Agent.Worker/Program.cs b/src/Agent.Worker/Program.cs index 0bc14d6eae..4b8ba52261 100644 --- a/src/Agent.Worker/Program.cs +++ b/src/Agent.Worker/Program.cs @@ -5,6 +5,7 @@ using System; using System.Globalization; using System.Threading.Tasks; +using Agent.Sdk; namespace Microsoft.VisualStudio.Services.Agent.Worker { @@ -12,10 +13,11 @@ public static class Program { public static int Main(string[] args) { - // We can't use the new SocketsHttpHandler for now for both Windows and Linux - // On linux, Negotiate auth is not working if the TFS url is behind Https - // On windows, Proxy is not working - AppContext.SetSwitch("System.Net.Http.UseSocketsHttpHandler", false); + if (PlatformUtil.UseLegacyHttpHandler) + { + AppContext.SetSwitch("System.Net.Http.UseSocketsHttpHandler", false); + } + using (HostContext context = new HostContext("Worker")) { return MainAsync(context, args).GetAwaiter().GetResult(); diff --git a/src/Common.props b/src/Common.props index 71d525586c..8a2cb3ac7a 100644 --- a/src/Common.props +++ b/src/Common.props @@ -2,7 +2,7 @@ netcoreapp3.1 3.1.0 - win-x64;win-x86;linux-x64;linux-arm;rhel.6-x64;osx-x64 + $(PackageRuntime) true portable-net45+win8 NU1701;NU1603; @@ -48,6 +48,9 @@ ARM + + ARM64 + ..\rules.ruleset @@ -57,4 +60,4 @@ $(OSPlatform);$(OSArchitecture);$(DebugConstant);TRACE - \ No newline at end of file + diff --git a/src/Misc/externals.sh b/src/Misc/externals.sh index ee6007d5d1..088fd91776 100755 --- a/src/Misc/externals.sh +++ b/src/Misc/externals.sh @@ -170,7 +170,7 @@ if [[ "$PACKAGERUNTIME" == "osx-x64" ]]; then fi # Download the external tools common across OSX and Linux PACKAGERUNTIMEs. -if [[ "$PACKAGERUNTIME" == "linux-x64" || "$PACKAGERUNTIME" == "linux-arm" || "$PACKAGERUNTIME" == "osx-x64" || "$PACKAGERUNTIME" == "rhel.6-x64" ]]; then +if [[ "$PACKAGERUNTIME" == "linux-x64" || "$PACKAGERUNTIME" == "linux-arm" || "$PACKAGERUNTIME" == "linux-arm64" || "$PACKAGERUNTIME" == "osx-x64" || "$PACKAGERUNTIME" == "rhel.6-x64" ]]; then acquireExternalTool "$CONTAINER_URL/tee/14_134_0/TEE-CLC-14.134.0.zip" tee fix_nested_dir acquireExternalTool "$CONTAINER_URL/vso-task-lib/0.5.5/vso-task-lib.tar.gz" vso-task-lib fi @@ -186,6 +186,11 @@ if [[ "$PACKAGERUNTIME" == "linux-arm" ]]; then acquireExternalTool "$NODE_URL/v${NODE10_VERSION}/node-v${NODE10_VERSION}-linux-armv7l.tar.gz" node10 fix_nested_dir fi +if [[ "$PACKAGERUNTIME" == "linux-arm64" ]]; then + acquireExternalTool "$NODE_URL/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-arm64.tar.gz" node fix_nested_dir + acquireExternalTool "$NODE_URL/v${NODE10_VERSION}/node-v${NODE10_VERSION}-linux-arm64.tar.gz" node10 fix_nested_dir +fi + if [[ "$L1_MODE" != "" || "$PRECACHE" != "" ]]; then # cmdline task acquireExternalTool "$CONTAINER_URL/l1Tasks/d9bafed4-0b18-4f58-968d-86655b4d2ce9.zip" "Tasks" false dont_uncompress @@ -196,4 +201,4 @@ if [[ "$L1_MODE" != "" || "$PRECACHE" != "" ]]; then # signed service tree task acquireExternalTool "$CONTAINER_URL/l1Tasks/5515f72c-5faa-4121-8a46-8f42a8f42132.zip" "Tasks" false dont_uncompress fi -fi \ No newline at end of file +fi diff --git a/src/Misc/layoutbin/installdependencies.sh b/src/Misc/layoutbin/installdependencies.sh index 0375c0a43f..a9a3bd265a 100755 --- a/src/Misc/layoutbin/installdependencies.sh +++ b/src/Misc/layoutbin/installdependencies.sh @@ -16,7 +16,7 @@ function print_errormessage() { echo "Can't install dotnet core dependencies." echo "You can manually install all required dependencies based on following documentation" - echo "https://docs.microsoft.com/en-us/dotnet/core/linux-prerequisites?tabs=netcore2x" + echo "https://docs.microsoft.com/en-us/dotnet/core/dependencies?pivots=os-linux&tabs=netcore31" } function print_rhel6message() @@ -31,7 +31,7 @@ function print_rhel6errormessage() { echo "We couldn't install dotnet core dependencies" echo "You can manually install all required dependencies based on following documentation" - echo "https://docs.microsoft.com/en-us/dotnet/core/linux-prerequisites?tabs=netcore2x" + echo "https://docs.microsoft.com/en-us/dotnet/core/dependencies?pivots=os-linux&tabs=netcore31" echo "In addition, there are some dependencies which require manual installation. Please follow this documentation" echo "https://github.com/dotnet/core/blob/master/Documentation/build-and-install-rhel6-prerequisites.md" } @@ -71,9 +71,10 @@ then exit 1 fi - # debian 9 use libssl1.0.2 + # debian 10 uses libssl1.1 + # debian 9 uses libssl1.0.2 # other debian linux use libssl1.0.0 - apt install -y libssl1.0.0 || apt install -y libssl1.0.2 + apt install -y libssl1.0.0 || apt install -y libssl1.0.2 || apt install -y libssl1.1 if [ $? -ne 0 ] then echo "'apt' failed with exit code '$?'" @@ -81,8 +82,8 @@ then exit 1 fi - # libicu version prefer: libicu52 -> libicu55 -> libicu57 -> libicu60 - apt install -y libicu52 || apt install -y libicu55 || apt install -y libicu57 || apt install -y libicu60 + # libicu versions: libicu52 -> libicu55 -> libicu57 -> libicu60 -> libicu63 + apt install -y libicu52 || apt install -y libicu55 || apt install -y libicu57 || apt install -y libicu60 || apt install -y libicu63 if [ $? -ne 0 ] then echo "'apt' failed with exit code '$?'" @@ -111,9 +112,10 @@ then exit 1 fi - # debian 9 use libssl1.0.2 + # debian 10 uses libssl1.1 + # debian 9 uses libssl1.0.2 # other debian linux use libssl1.0.0 - apt-get install -y libssl1.0.0 || apt install -y libssl1.0.2 + apt-get install -y libssl1.0.0 || apt-get install -y libssl1.0.2 || apt-get install -y libssl1.1 if [ $? -ne 0 ] then echo "'apt-get' failed with exit code '$?'" @@ -121,8 +123,8 @@ then exit 1 fi - # libicu version prefer: libicu52 -> libicu55 -> libicu57 -> libicu60 - apt-get install -y libicu52 || apt install -y libicu55 || apt install -y libicu57 || apt install -y libicu60 + # libicu versions: libicu52 -> libicu55 -> libicu57 -> libicu60 -> libicu63 + apt-get install -y libicu52 || apt-get install -y libicu55 || apt-get install -y libicu57 || apt-get install -y libicu60 || apt-get install -y libicu63 if [ $? -ne 0 ] then echo "'apt-get' failed with exit code '$?'" diff --git a/src/Misc/layoutroot/config.sh b/src/Misc/layoutroot/config.sh index 8bd66524fb..6ca7be2f1c 100755 --- a/src/Misc/layoutroot/config.sh +++ b/src/Misc/layoutroot/config.sh @@ -8,7 +8,7 @@ if [ $user_id -eq 0 -a -z "$AGENT_ALLOW_RUNASROOT" ]; then exit 1 fi -# Check dotnet core 2.1 dependencies for Linux +# Check dotnet core 3.1 dependencies for Linux if [[ (`uname` == "Linux") ]] then command -v ldd > /dev/null @@ -20,30 +20,30 @@ then ldd ./bin/libcoreclr.so | grep 'not found' if [ $? -eq 0 ]; then - echo "Dependencies is missing for Dotnet Core 2.1" - echo "Execute ./bin/installdependencies.sh to install any missing Dotnet Core 2.1 dependencies." + echo "Dependencies is missing for .NET Core 3.1" + echo "Execute ./bin/installdependencies.sh to install any missing dependencies." exit 1 fi ldd ./bin/System.Security.Cryptography.Native.OpenSsl.so | grep 'not found' if [ $? -eq 0 ]; then - echo "Dependencies is missing for Dotnet Core 2.1" - echo "Execute ./bin/installdependencies.sh to install any missing Dotnet Core 2.1 dependencies." + echo "Dependencies missing for .NET Core 3.1" + echo "Execute ./bin/installdependencies.sh to install any missing dependencies." exit 1 fi ldd ./bin/System.IO.Compression.Native.so | grep 'not found' if [ $? -eq 0 ]; then - echo "Dependencies is missing for Dotnet Core 2.1" - echo "Execute ./bin/installdependencies.sh to install any missing Dotnet Core 2.1 dependencies." + echo "Dependencies missing for .NET Core 3.1" + echo "Execute ./bin/installdependencies.sh to install any missing dependencies." exit 1 fi ldd ./bin/System.Net.Http.Native.so | grep 'not found' if [ $? -eq 0 ]; then - echo "Dependencies is missing for Dotnet Core 2.1" - echo "Execute ./bin/installdependencies.sh to install any missing Dotnet Core 2.1 dependencies." - exit 1 + echo "Warning: on some platforms, libcurl3 is required." + echo "It was not found." + echo "Execute ./bin/installdependencies.sh to install missing dependencies." fi if ! [ -x "$(command -v ldconfig)" ]; then @@ -59,8 +59,8 @@ then libpath=${LD_LIBRARY_PATH:-} $LDCONFIG_COMMAND -NXv ${libpath//:/} 2>&1 | grep libicu >/dev/null 2>&1 if [ $? -ne 0 ]; then - echo "Libicu's dependencies is missing for Dotnet Core 2.1" - echo "Execute ./bin/installdependencies.sh to install any missing Dotnet Core 2.1 dependencies." + echo "libicu's dependencies missing for .NET Core 3.1" + echo "Execute ./bin/installdependencies.sh to install any missing dependencies." exit 1 fi fi diff --git a/src/Test/L0/ConstantGenerationL0.cs b/src/Test/L0/ConstantGenerationL0.cs index 9ebfe4d8fb..4e3dfb2d26 100644 --- a/src/Test/L0/ConstantGenerationL0.cs +++ b/src/Test/L0/ConstantGenerationL0.cs @@ -19,6 +19,7 @@ public void BuildConstantGenerateSucceed() "win-x86", "linux-x64", "linux-arm", + "linux-arm64", "rhel.6-x64", "osx-x64" }; diff --git a/src/dev.sh b/src/dev.sh index 7bd8a76ef8..22edde661d 100755 --- a/src/dev.sh +++ b/src/dev.sh @@ -51,7 +51,7 @@ function detect_platform_and_runtime_id () local CPU_NAME=$(uname -m) case $CPU_NAME in armv7l) DETECTED_RUNTIME_ID="linux-arm";; - aarch64) DETECTED_RUNTIME_ID="linux-arm";; + aarch64) DETECTED_RUNTIME_ID="linux-arm64";; esac fi @@ -246,7 +246,7 @@ else RUNTIME_ID=$DETECTED_RUNTIME_ID fi -_VALID_RIDS='linux-x64:linux-arm:rhel.6-x64:osx-x64:win-x64:win-x86' +_VALID_RIDS='linux-x64:linux-arm:linux-arm64:rhel.6-x64:osx-x64:win-x64:win-x86' if [[ ":$_VALID_RIDS:" != *:$RUNTIME_ID:* ]]; then failed "must specify a valid target runtime ID (one of: $_VALID_RIDS)" fi diff --git a/src/dir.proj b/src/dir.proj index a6db7c88eb..9c094d5fa8 100644 --- a/src/dir.proj +++ b/src/dir.proj @@ -77,7 +77,7 @@ - + @@ -135,4 +135,4 @@ - \ No newline at end of file +