From ec40894b7670c3b547232895ada88966265186c6 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Mon, 23 Mar 2020 17:20:40 -0700 Subject: [PATCH 01/15] Initial commit of script to generate Virtual Machine Scale Sets. --- azure-devops/create-new-agent-image.ps1 | 221 ++++++++++++++++++ azure-devops/install-scale-set-extension.ps1 | 25 -- azure-devops/provision-agent-bootstrap.cmd | 10 - azure-devops/provision-image-bootstrap.ps1 | 18 ++ ...rovision-agent.ps1 => provision-image.ps1} | 30 +-- 5 files changed, 241 insertions(+), 63 deletions(-) create mode 100644 azure-devops/create-new-agent-image.ps1 delete mode 100644 azure-devops/install-scale-set-extension.ps1 delete mode 100644 azure-devops/provision-agent-bootstrap.cmd create mode 100644 azure-devops/provision-image-bootstrap.ps1 rename azure-devops/{provision-agent.ps1 => provision-image.ps1} (82%) diff --git a/azure-devops/create-new-agent-image.ps1 b/azure-devops/create-new-agent-image.ps1 new file mode 100644 index 00000000000..eec33bf5699 --- /dev/null +++ b/azure-devops/create-new-agent-image.ps1 @@ -0,0 +1,221 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +# This script assumes you have installed Azure tools into Powershell by following the instructions +# at https://docs.microsoft.com/en-us/powershell/azure/install-az-ps?view=azps-3.6.1 +# or are running from Azure Cloud Shell +# + +$Location = 'westus2' +$Prefix = 'CppStlGithubBuild' +$VMSize = 'Standard_D16s_v3' +$ProtoVMName = 'PROTOTYPE' +$LiveVMPrefix = 'BUILD' +$WindowsServerSku = '2019-Datacenter' + +function Find-ResourceGroupName { + Param( + [string] $prefix + ) + + $suffix = 0 + $resources = Get-AzResourceGroup + do { + $collision = $false + $suffix++ + $result = "$prefix$suffix" + foreach ($resource in $resources) { + if ($resource.ResourceGroupName -eq $result) { + $collision = $true + break + } + } + } while ($collision) + return $result +} + +function New-Password { + Param ( + [int] $length = 32 + ) + + $Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + + $result = '' + for ($idx = 0; $idx -lt $length; $idx++) { + $result += $Chars[(Get-Random -Minimum 0 -Maximum ($Chars.Length - 1))] + } + + return $result +} + +$ResourceGroupName = Find-ResourceGroupName $Prefix +$AdminPW = New-Password +Write-Output "Location: $Location" +Write-Output "Resource group name: $ResourceGroupName" +Write-Output "User name: AdminUser" +Write-Output "Using Generated Password: $AdminPW" + +New-AzResourceGroup -Name $ResourceGroupName -Location $Location + +$AdminPWSecure = ConvertTo-SecureString $AdminPW -AsPlainText -Force +$Credential = New-Object System.Management.Automation.PSCredential ("AdminUser", $AdminPWSecure) + +$allowHttp = New-AzNetworkSecurityRuleConfig ` + -Name AllowHTTP ` + -Description 'Allow HTTP(s)' ` + -Access Allow ` + -Protocol Tcp ` + -Direction Outbound ` + -Priority 1008 ` + -SourceAddressPrefix * ` + -SourcePortRange * ` + -DestinationAddressPrefix * ` + -DestinationPortRange @(80, 443) + +$allowDns = New-AzNetworkSecurityRuleConfig ` + -Name AllowDNS ` + -Description 'Allow DNS' ` + -Access Allow ` + -Protocol * ` + -Direction Outbound ` + -Priority 1009 ` + -SourceAddressPrefix * ` + -SourcePortRange * ` + -DestinationAddressPrefix * ` + -DestinationPortRange 53 + +$denyEverythingElse = New-AzNetworkSecurityRuleConfig ` + -Name DenyElse ` + -Description 'Deny everything else' ` + -Access Deny ` + -Protocol * ` + -Direction Outbound ` + -Priority 1010 ` + -SourceAddressPrefix * ` + -SourcePortRange * ` + -DestinationAddressPrefix * ` + -DestinationPortRange * + +$NetworkSecurityGroupName = $ResourceGroupName + 'NetworkSecurity' +$NetworkSecurityGroup = New-AzNetworkSecurityGroup ` + -Name $NetworkSecurityGroupName ` + -ResourceGroupName $ResourceGroupName ` + -Location $Location ` + -SecurityRules @($allowHttp, $allowDns, $denyEverythingElse) + +$SubnetName = $ResourceGroupName + 'Subnet' +$Subnet = New-AzVirtualNetworkSubnetConfig ` + -Name $SubnetName ` + -AddressPrefix "10.0.0.0/16" ` + -NetworkSecurityGroup $NetworkSecurityGroup + +$VirtualNetworkName = $ResourceGroupName + 'Network' +$VirtualNetwork = New-AzVirtualNetwork ` + -Name $VirtualNetworkName ` + -ResourceGroupName $ResourceGroupName ` + -Location $Location ` + -AddressPrefix "10.0.0.0/16" ` + -Subnet $Subnet + +$NicName = $ResourceGroupName + 'NIC' +$Nic = New-AzNetworkInterface ` + -Name $NicName ` + -ResourceGroupName $ResourceGroupName ` + -Location $Location ` + -Subnet $VirtualNetwork.Subnets[0] + +$VM = New-AzVMConfig -Name $ProtoVMName -VMSize $VMSize +$VM = Set-AzVMOperatingSystem ` + -VM $VM ` + -Windows ` + -ComputerName $ProtoVMName ` + -Credential $Credential ` + -ProvisionVMAgent ` + -EnableAutoUpdate + +$VM = Add-AzVMNetworkInterface -VM $VM -Id $Nic.Id +$VM = Set-AzVMSourceImage ` + -VM $VM ` + -PublisherName 'MicrosoftWindowsServer' ` + -Offer 'WindowsServer' ` + -Skus $WindowsServerSku ` + -Version latest + +$VM = Set-AzVMBootDiagnostic -VM $VM -Disable +New-AzVm ` + -ResourceGroupName $ResourceGroupName ` + -Location $Location ` + -VM $VM + +$VM = Get-AzVM -ResourceGroupName $ResourceGroupName -Name $ProtoVMName +$PrototypeOSDiskName = $VM.StorageProfile.OsDisk.Name + +Invoke-AzVMRunCommand ` + -ResourceGroupName $ResourceGroupName ` + -VMName $ProtoVMName ` + -CommandId 'RunPowerShellScript' ` + -ScriptPath 'provision-image-bootstrap.ps1' ` + -Parameter @{AdminUserPassword = $AdminPW } + +Stop-AzVM ` + -ResourceGroupName $ResourceGroupName ` + -Name $ProtoVMName ` + -Force + +Set-AzVM ` + -ResourceGroupName $ResourceGroupName ` + -Name $ProtoVMName ` + -Generalized + +$ImageConfig = New-AzImageConfig -Location $Location -SourceVirtualMachineId $VM.ID +$Image = New-AzImage -Image $ImageConfig -ImageName $ProtoVMName -ResourceGroupName $ResourceGroupName +$Image + +# Clean up stuff we no longer need now that we have an image +Remove-AzVM -Id $VM.ID -Force +Remove-AzDisk -ResourceGroupName $ResourceGroupName -DiskName $PrototypeOSDiskName -Force + +$VmssIpConfigName = $ResourceGroupName + 'VmssIpConfig' +$VmssIpConfig = New-AzVmssIpConfig -SubnetId $Nic.IpConfigurations[0].Subnet.Id -Primary -Name $VmssIpConfigName + +$VmssName = $ResourceGroupName + 'Vmss' +$Vmss = New-AzVmssConfig ` + -Location $Location ` + -SkuCapacity 1 ` + -SkuName $VMSize ` + -SkuTier 'Standard' ` + -UpgradePolicyMode Manual ` + -EvictionPolicy Delete ` + -Priority Spot ` + -MaxPrice -1 + +$Vmss = Add-AzVmssNetworkInterfaceConfiguration +-VirtualMachineScaleSet $Vmss ` + -Primary $true ` + -IpConfiguration $VmssIpConfig ` + -NetworkSecurityGroupId $NetworkSecurityGroup.Id ` + -Name $NicName + +$Vmss = Set-AzVmssOsProfile ` + -VirtualMachineScaleSet $Vmss ` + -ComputerNamePrefix $LiveVMPrefix ` + -AdminUsername 'AdminUser' ` + -AdminPassword $AdminPW ` + -WindowsConfigurationProvisionVMAgent $true ` + -WindowsConfigurationEnableAutomaticUpdate $true + +$Vmss = Set-AzVmssStorageProfile ` + -VirtualMachineScaleSet $Vmss ` + -OsDiskCreateOption 'FromImage' ` + -OsDiskCaching ReadWrite ` + -ImageReferenceId $Image.Id ` + -ManagedDisk Premium_LRS + +New-AzVmss ` + -ResourceGroupName $ResourceGroupName ` + -Name $VmssName ` + -VirtualMachineScaleSet $Vmss + +$VmssResult = Get-AzVmss -ResourceGroupName $ResourceGroupName -Name $VmssName +$VmssResult diff --git a/azure-devops/install-scale-set-extension.ps1 b/azure-devops/install-scale-set-extension.ps1 deleted file mode 100644 index ce5d7cb6a0c..00000000000 --- a/azure-devops/install-scale-set-extension.ps1 +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -# Change "ADMIN_PASSWORD" to the "AdminUser" password on the virtual machines, and "PERSONAL_ACCESS_TOKEN" to -# a PAT with permission to register Azure DevOps agents, then paste the contents of this file into an Azure -# Cloud Shell PowerShell prompt. - -# When demoing changes you may need to change the "STL/master" part of the below URIs to point to your desired -# branch. - -$customConfig = @{ - "fileUris" = @("https://raw.githubusercontent.com/microsoft/STL/master/azure-devops/provision-agent.ps1", - "https://raw.githubusercontent.com/microsoft/STL/master/azure-devops/provision-agent-bootstrap.cmd" - ) -} -$protectedConfig = @{ - "commandToExecute" = - "C:\Windows\System32\cmd.exe /c provision-agent-bootstrap.cmd ADMIN_PASSWORD PERSONAL_ACCESS_TOKEN" -} -$resourceGroupName = 'CppStlGithubBuildMachines' -$vmScaleSetName = 'MSVCSTL-BUILD' -$vmss = Get-AzVmss -ResourceGroupName $resourceGroupName -VMScaleSetName $vmScaleSetName -$vmss = Add-AzVmssExtension -VirtualMachineScaleSet $vmss -Name "DeployAgent" -Publisher "Microsoft.Compute" ` - -Type "CustomScriptExtension" -TypeHandlerVersion 1.10 -Setting $customConfig -ProtectedSetting $protectedConfig -Update-AzVmss -ResourceGroupName $resourceGroupName -Name vmScaleSetName -VirtualMachineScaleSet $vmss diff --git a/azure-devops/provision-agent-bootstrap.cmd b/azure-devops/provision-agent-bootstrap.cmd deleted file mode 100644 index dd65df2080a..00000000000 --- a/azure-devops/provision-agent-bootstrap.cmd +++ /dev/null @@ -1,10 +0,0 @@ -:: Copyright (c) Microsoft Corporation. -:: SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -:: Switches to the "AdminUser" account, then runs provision-agent.ps1 -:: %1 AdminUser password -:: %2 Azure Pipelines PAT - -curl.exe -L -o "%TEMP%\psexec.exe" https://live.sysinternals.com/PsExec64.exe -"%TEMP%\psexec.exe" -u AdminUser -p "%1" -accepteula -h C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe ^ - -ExecutionPolicy Unrestricted -File "%CD%\provision-agent.ps1" "%2" diff --git a/azure-devops/provision-image-bootstrap.ps1 b/azure-devops/provision-image-bootstrap.ps1 new file mode 100644 index 00000000000..4989be3b7d6 --- /dev/null +++ b/azure-devops/provision-image-bootstrap.ps1 @@ -0,0 +1,18 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +# Downloads provision-image.ps1, switches to the "AdminUser" account, then runs provision-image.ps1 +param( + [string]$AdminUserPassword +) + +if ([string]::IsNullOrEmpty($AdminUserPassword)) { + Write-Output "Missing AdminUser password." + exit 1 +} + +$temp = $env:TEMP + +curl.exe -L -o "$temp\psexec.exe" https://live.sysinternals.com/PsExec64.exe +curl.exe -L -o "$temp\provision-image.ps1" https://raw.githubusercontent.com/BillyONeal/STL/autoscale/azure-devops/provision-image.ps1 +& "$temp\psexec.exe" -u AdminUser -p $AdminUserPassword -accepteula -h C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Unrestricted -File "$temp\provision-image.ps1" diff --git a/azure-devops/provision-agent.ps1 b/azure-devops/provision-image.ps1 similarity index 82% rename from azure-devops/provision-agent.ps1 rename to azure-devops/provision-image.ps1 index e477c4c9a09..eda5b56caef 100644 --- a/azure-devops/provision-agent.ps1 +++ b/azure-devops/provision-image.ps1 @@ -1,22 +1,7 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -# Sets up VM for use as a build machine - -# $args[0] Azure Pipelines Personal Access Token - -Write-Output 'Starting...' - -if (Test-Path 'C:\agent') { - Write-Output 'Agent already installed, terminating.' - exit 0 -} - -Write-Output 'Agent does not appear to be installed.' - -$AzureDevOpsUrl = 'https://dev.azure.com/vclibs/' -$AzureDevOpsPool = 'STL' -[string]$PersonalAccessToken = $args[0] +# Sets up VM image for use as a build machine prototype $WorkLoads = '--add Microsoft.VisualStudio.Component.VC.CLI.Support ' + ` '--add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 ' + ` @@ -31,7 +16,6 @@ $CMakeUrl = 'https://github.com/Kitware/CMake/releases/download/v3.16.5/cmake-3. $LlvmUrl = 'https://releases.llvm.org/9.0.0/LLVM-9.0.0-win64.exe' $NinjaUrl = 'https://github.com/ninja-build/ninja/releases/download/v1.10.0/ninja-win.zip' $PythonUrl = 'https://www.python.org/ftp/python/3.8.2/python-3.8.2-amd64.exe' -$VstsAgentUrl = 'https://vstsagentpackage.azureedge.net/agent/2.165.0/vsts-agent-win-x64-2.165.0.zip' $ErrorActionPreference = 'Stop' $ProgressPreference = 'SilentlyContinue' @@ -185,12 +169,6 @@ Function InstallPython } } -if ([string]::IsNullOrEmpty($PersonalAccessToken) ` - -or ($PersonalAccessToken -eq 'PERSONAL_ACCESS_TOKEN')) { - Write-Output 'You forgot to fill in your personal access token.' - exit 1 -} - InstallMSI 'CMake' $CMakeUrl InstallZip 'Ninja' $NinjaUrl 'C:\Program Files\CMake\bin' InstallLLVM $LlvmUrl @@ -201,8 +179,4 @@ $environmentKey = Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment' ` -Name Path ` -Value "$($environmentKey.Path);C:\Program Files\CMake\bin;C:\Program Files\LLVM\bin" -InstallZip 'Azure DevOps Agent' $VstsAgentUrl 'C:\agent' -Add-MpPreference -ExclusionPath C:\agent -& 'C:\agent\config.cmd' --unattended --url $AzureDevOpsUrl --auth pat --token $PersonalAccessToken ` - --pool $AzureDevOpsPool --replace --runAsService --work D:\ -shutdown /r /t 10 +C:\Windows\system32\sysprep\sysprep.exe /oobe /generalize /shutdown From af0ec0e5e037a407fd218e63d3d9e9667dd27f91 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Mon, 23 Mar 2020 18:21:47 -0700 Subject: [PATCH 02/15] Add progress and date. --- azure-devops/create-new-agent-image.ps1 | 79 +++++++++++++++++++------ 1 file changed, 61 insertions(+), 18 deletions(-) diff --git a/azure-devops/create-new-agent-image.ps1 b/azure-devops/create-new-agent-image.ps1 index eec33bf5699..696eea5f679 100644 --- a/azure-devops/create-new-agent-image.ps1 +++ b/azure-devops/create-new-agent-image.ps1 @@ -7,20 +7,32 @@ # $Location = 'westus2' -$Prefix = 'CppStlGithubBuild' +$Prefix = 'CppStlGithubBuild' + (Get-Date -Format 'yyyyMMdd') $VMSize = 'Standard_D16s_v3' $ProtoVMName = 'PROTOTYPE' $LiveVMPrefix = 'BUILD' $WindowsServerSku = '2019-Datacenter' +$TotalProgress = 7 +$CurrentProgress = 1 + function Find-ResourceGroupName { Param( [string] $prefix ) - $suffix = 0 + $result = $prefix $resources = Get-AzResourceGroup - do { + $collision = $false + foreach ($resource in $resources) { + if ($resource.ResourceGroupName -eq $result) { + $collision = $true + break + } + } + + $suffix = 0 + while ($collision) { $collision = $false $suffix++ $result = "$prefix$suffix" @@ -30,7 +42,8 @@ function Find-ResourceGroupName { break } } - } while ($collision) + } + return $result } @@ -49,18 +62,31 @@ function New-Password { return $result } +function Write-Reminders { + Param([string]$AdminPW) + Write-Output "Location: $Location" + Write-Output "Resource group name: $ResourceGroupName" + Write-Output "User name: AdminUser" + Write-Output "Using Generated Password: $AdminPW" +} + +#################################################################################################### +Write-Progress ` + -Activity 'Creating resource group' ` + -PercentComplete (100 / $TotalProgress * $CurrentProgress++) + $ResourceGroupName = Find-ResourceGroupName $Prefix $AdminPW = New-Password -Write-Output "Location: $Location" -Write-Output "Resource group name: $ResourceGroupName" -Write-Output "User name: AdminUser" -Write-Output "Using Generated Password: $AdminPW" - +Write-Reminders $AdminPW New-AzResourceGroup -Name $ResourceGroupName -Location $Location - $AdminPWSecure = ConvertTo-SecureString $AdminPW -AsPlainText -Force $Credential = New-Object System.Management.Automation.PSCredential ("AdminUser", $AdminPWSecure) +#################################################################################################### +Write-Progress ` + -Activity 'Creating prototype VM' ` + -PercentComplete (100 / $TotalProgress * $CurrentProgress++) + $allowHttp = New-AzNetworkSecurityRuleConfig ` -Name AllowHTTP ` -Description 'Allow HTTP(s)' ` @@ -148,9 +174,13 @@ New-AzVm ` -Location $Location ` -VM $VM +#################################################################################################### +Write-Progress ` + -Activity 'Running provisioning script in VM' ` + -PercentComplete (100 / $TotalProgress * $CurrentProgress++) + $VM = Get-AzVM -ResourceGroupName $ResourceGroupName -Name $ProtoVMName $PrototypeOSDiskName = $VM.StorageProfile.OsDisk.Name - Invoke-AzVMRunCommand ` -ResourceGroupName $ResourceGroupName ` -VMName $ProtoVMName ` @@ -158,6 +188,11 @@ Invoke-AzVMRunCommand ` -ScriptPath 'provision-image-bootstrap.ps1' ` -Parameter @{AdminUserPassword = $AdminPW } +#################################################################################################### +Write-Progress ` + -Activity 'Converting VM to Image' ` + -PercentComplete (100 / $TotalProgress * $CurrentProgress++) + Stop-AzVM ` -ResourceGroupName $ResourceGroupName ` -Name $ProtoVMName ` @@ -170,15 +205,22 @@ Set-AzVM ` $ImageConfig = New-AzImageConfig -Location $Location -SourceVirtualMachineId $VM.ID $Image = New-AzImage -Image $ImageConfig -ImageName $ProtoVMName -ResourceGroupName $ResourceGroupName -$Image -# Clean up stuff we no longer need now that we have an image +#################################################################################################### +Write-Progress ` + -Activity 'Deleting unused VM and disk' ` + -PercentComplete (100 / $TotalProgress * $CurrentProgress++) + Remove-AzVM -Id $VM.ID -Force Remove-AzDisk -ResourceGroupName $ResourceGroupName -DiskName $PrototypeOSDiskName -Force +#################################################################################################### +Write-Progress ` + -Activity 'Creating scale set' ` + -PercentComplete (100 / $TotalProgress * $CurrentProgress++) + $VmssIpConfigName = $ResourceGroupName + 'VmssIpConfig' $VmssIpConfig = New-AzVmssIpConfig -SubnetId $Nic.IpConfigurations[0].Subnet.Id -Primary -Name $VmssIpConfigName - $VmssName = $ResourceGroupName + 'Vmss' $Vmss = New-AzVmssConfig ` -Location $Location ` @@ -190,8 +232,8 @@ $Vmss = New-AzVmssConfig ` -Priority Spot ` -MaxPrice -1 -$Vmss = Add-AzVmssNetworkInterfaceConfiguration --VirtualMachineScaleSet $Vmss ` +$Vmss = Add-AzVmssNetworkInterfaceConfiguration ` + -VirtualMachineScaleSet $Vmss ` -Primary $true ` -IpConfiguration $VmssIpConfig ` -NetworkSecurityGroupId $NetworkSecurityGroup.Id ` @@ -217,5 +259,6 @@ New-AzVmss ` -Name $VmssName ` -VirtualMachineScaleSet $Vmss -$VmssResult = Get-AzVmss -ResourceGroupName $ResourceGroupName -Name $VmssName -$VmssResult +#################################################################################################### +Write-Progress -Completed +Write-Reminders $AdminPW From 70f233a6268ab2978f027eedd787dcc3cc6ab401 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Mon, 23 Mar 2020 18:23:14 -0700 Subject: [PATCH 03/15] Remove explicit "pool" from run-build.yml. --- azure-devops/run-build.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/azure-devops/run-build.yml b/azure-devops/run-build.yml index ff2e0668bfa..c47be420241 100644 --- a/azure-devops/run-build.yml +++ b/azure-devops/run-build.yml @@ -3,9 +3,6 @@ jobs: - job: ${{ parameters.targetPlatform }} - pool: - name: STL - variables: vcpkgLocation: '$(Build.SourcesDirectory)/vcpkg' steps: From bd91e4ab924f137fa238ae318a70128a05f2fe8e Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Mon, 23 Mar 2020 18:49:52 -0700 Subject: [PATCH 04/15] No overprovision. --- azure-devops/create-new-agent-image.ps1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/azure-devops/create-new-agent-image.ps1 b/azure-devops/create-new-agent-image.ps1 index 696eea5f679..1792aa44e5a 100644 --- a/azure-devops/create-new-agent-image.ps1 +++ b/azure-devops/create-new-agent-image.ps1 @@ -224,9 +224,10 @@ $VmssIpConfig = New-AzVmssIpConfig -SubnetId $Nic.IpConfigurations[0].Subnet.Id $VmssName = $ResourceGroupName + 'Vmss' $Vmss = New-AzVmssConfig ` -Location $Location ` - -SkuCapacity 1 ` + -SkuCapacity 2 ` -SkuName $VMSize ` -SkuTier 'Standard' ` + -Overprovision $false ` -UpgradePolicyMode Manual ` -EvictionPolicy Delete ` -Priority Spot ` From bc756629dac9076662be92d6feb7af5dce74e92c Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Mon, 23 Mar 2020 20:16:05 -0700 Subject: [PATCH 05/15] Shinier output. --- azure-devops/create-new-agent-image.ps1 | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/azure-devops/create-new-agent-image.ps1 b/azure-devops/create-new-agent-image.ps1 index 1792aa44e5a..89940f5c4b7 100644 --- a/azure-devops/create-new-agent-image.ps1 +++ b/azure-devops/create-new-agent-image.ps1 @@ -7,12 +7,13 @@ # $Location = 'westus2' -$Prefix = 'CppStlGithubBuild' + (Get-Date -Format 'yyyyMMdd') +$Prefix = 'StlBuild' + (Get-Date -Format 'yyyy-MM-dd') $VMSize = 'Standard_D16s_v3' $ProtoVMName = 'PROTOTYPE' $LiveVMPrefix = 'BUILD' $WindowsServerSku = '2019-Datacenter' +$ProgressActivity = 'Creating Scale Set' $TotalProgress = 7 $CurrentProgress = 1 @@ -35,7 +36,7 @@ function Find-ResourceGroupName { while ($collision) { $collision = $false $suffix++ - $result = "$prefix$suffix" + $result = "$prefix-$suffix" foreach ($resource in $resources) { if ($resource.ResourceGroupName -eq $result) { $collision = $true @@ -72,7 +73,8 @@ function Write-Reminders { #################################################################################################### Write-Progress ` - -Activity 'Creating resource group' ` + -Activity $ProgressActivity ` + -Status 'Creating resource group' ` -PercentComplete (100 / $TotalProgress * $CurrentProgress++) $ResourceGroupName = Find-ResourceGroupName $Prefix @@ -176,7 +178,8 @@ New-AzVm ` #################################################################################################### Write-Progress ` - -Activity 'Running provisioning script in VM' ` + -Activity $ProgressActivity ` + -Status 'Running provisioning script in VM' ` -PercentComplete (100 / $TotalProgress * $CurrentProgress++) $VM = Get-AzVM -ResourceGroupName $ResourceGroupName -Name $ProtoVMName @@ -190,7 +193,8 @@ Invoke-AzVMRunCommand ` #################################################################################################### Write-Progress ` - -Activity 'Converting VM to Image' ` + -Activity $ProgressActivity ` + -Status 'Converting VM to Image' ` -PercentComplete (100 / $TotalProgress * $CurrentProgress++) Stop-AzVM ` @@ -208,7 +212,8 @@ $Image = New-AzImage -Image $ImageConfig -ImageName $ProtoVMName -ResourceGroupN #################################################################################################### Write-Progress ` - -Activity 'Deleting unused VM and disk' ` + -Activity $ProgressActivity ` + -Status 'Deleting unused VM and disk' ` -PercentComplete (100 / $TotalProgress * $CurrentProgress++) Remove-AzVM -Id $VM.ID -Force @@ -216,7 +221,8 @@ Remove-AzDisk -ResourceGroupName $ResourceGroupName -DiskName $PrototypeOSDiskNa #################################################################################################### Write-Progress ` - -Activity 'Creating scale set' ` + -Activity $ProgressActivity ` + -Status 'Creating scale set' ` -PercentComplete (100 / $TotalProgress * $CurrentProgress++) $VmssIpConfigName = $ResourceGroupName + 'VmssIpConfig' @@ -261,5 +267,6 @@ New-AzVmss ` -VirtualMachineScaleSet $Vmss #################################################################################################### -Write-Progress -Completed +Write-Progress -Activity $ProgressActivity -Status -Completed Write-Reminders $AdminPW +Write-Output 'Finished! Terminate.' From 36e5d0e7e6b45f9d33bf7cae98135e8fc7cdac66 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Mon, 23 Mar 2020 22:05:44 -0700 Subject: [PATCH 06/15] Added delays due to race between this script and sysprep. --- azure-devops/create-new-agent-image.ps1 | 31 ++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/azure-devops/create-new-agent-image.ps1 b/azure-devops/create-new-agent-image.ps1 index 89940f5c4b7..9cabc8c7e10 100644 --- a/azure-devops/create-new-agent-image.ps1 +++ b/azure-devops/create-new-agent-image.ps1 @@ -7,14 +7,14 @@ # $Location = 'westus2' -$Prefix = 'StlBuild' + (Get-Date -Format 'yyyy-MM-dd') +$Prefix = 'StlBuild-' + (Get-Date -Format 'yyyy-MM-dd') $VMSize = 'Standard_D16s_v3' $ProtoVMName = 'PROTOTYPE' $LiveVMPrefix = 'BUILD' $WindowsServerSku = '2019-Datacenter' $ProgressActivity = 'Creating Scale Set' -$TotalProgress = 7 +$TotalProgress = 8 $CurrentProgress = 1 function Find-ResourceGroupName { @@ -63,6 +63,23 @@ function New-Password { return $result } +function Start-WaitForShutdown { + Param([string]$ResourceGroupName, [string]$Name) + Write-Output "Waiting for $Name to stop..." + while ($true) { + $Vm = Get-AzVM -ResourceGroupName $ResourceGroupName -Name $Name -Status + $highestStatus = $Vm.Statuses.Count + for ($idx = 0; $idx -lt $highestStatus; $idx++) { + if ($Vm.Statuses[$idx].Code -eq 'PowerState/stopped') { + return + } + } + + Write-Output "... not stopped yet, sleeping for 10 seconds" + Start-Sleep -Seconds 10 + } +} + function Write-Reminders { Param([string]$AdminPW) Write-Output "Location: $Location" @@ -188,9 +205,17 @@ Invoke-AzVMRunCommand ` -ResourceGroupName $ResourceGroupName ` -VMName $ProtoVMName ` -CommandId 'RunPowerShellScript' ` - -ScriptPath 'provision-image-bootstrap.ps1' ` + -ScriptPath "$PSScriptRoot\provision-image-bootstrap.ps1" ` -Parameter @{AdminUserPassword = $AdminPW } +#################################################################################################### +Write-Progress ` + -Activity $ProgressActivity ` + -Status 'Waiting for VM to shut down' ` + -PercentComplete (100 / $TotalProgress * $CurrentProgress++) + +Start-WaitForShutdown -ResourceGroupName $ResourceGroupName -Name $ProtoVMName + #################################################################################################### Write-Progress ` -Activity $ProgressActivity ` From 8b8877d9859329cef8ddb6974ecdd3267a8b4299 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Mon, 23 Mar 2020 22:15:00 -0700 Subject: [PATCH 07/15] Set pool name explicitly. --- azure-devops/run-build.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/azure-devops/run-build.yml b/azure-devops/run-build.yml index c47be420241..a62b9e819cd 100644 --- a/azure-devops/run-build.yml +++ b/azure-devops/run-build.yml @@ -3,6 +3,9 @@ jobs: - job: ${{ parameters.targetPlatform }} + pool: + name: StlBuild-2020-03-23-1 + variables: vcpkgLocation: '$(Build.SourcesDirectory)/vcpkg' steps: From 48b19776e0e148dae6bc9d5ae5ef46d961ca41bd Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Mon, 23 Mar 2020 22:20:27 -0700 Subject: [PATCH 08/15] Update script location to Microsoft. --- azure-devops/provision-image-bootstrap.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-devops/provision-image-bootstrap.ps1 b/azure-devops/provision-image-bootstrap.ps1 index 4989be3b7d6..a4343f7c637 100644 --- a/azure-devops/provision-image-bootstrap.ps1 +++ b/azure-devops/provision-image-bootstrap.ps1 @@ -14,5 +14,5 @@ if ([string]::IsNullOrEmpty($AdminUserPassword)) { $temp = $env:TEMP curl.exe -L -o "$temp\psexec.exe" https://live.sysinternals.com/PsExec64.exe -curl.exe -L -o "$temp\provision-image.ps1" https://raw.githubusercontent.com/BillyONeal/STL/autoscale/azure-devops/provision-image.ps1 +curl.exe -L -o "$temp\provision-image.ps1" https://raw.githubusercontent.com/microsoft/STL/autoscale/azure-devops/provision-image.ps1 & "$temp\psexec.exe" -u AdminUser -p $AdminUserPassword -accepteula -h C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Unrestricted -File "$temp\provision-image.ps1" From fc7041ab62c4f3fc8370f4467f0edb309c8dcbde Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Tue, 24 Mar 2020 01:49:20 -0700 Subject: [PATCH 09/15] Fix branch to mention master rather than 'autoscale'. --- azure-devops/provision-image-bootstrap.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-devops/provision-image-bootstrap.ps1 b/azure-devops/provision-image-bootstrap.ps1 index a4343f7c637..efbf81aab8e 100644 --- a/azure-devops/provision-image-bootstrap.ps1 +++ b/azure-devops/provision-image-bootstrap.ps1 @@ -14,5 +14,5 @@ if ([string]::IsNullOrEmpty($AdminUserPassword)) { $temp = $env:TEMP curl.exe -L -o "$temp\psexec.exe" https://live.sysinternals.com/PsExec64.exe -curl.exe -L -o "$temp\provision-image.ps1" https://raw.githubusercontent.com/microsoft/STL/autoscale/azure-devops/provision-image.ps1 +curl.exe -L -o "$temp\provision-image.ps1" https://raw.githubusercontent.com/microsoft/STL/master/azure-devops/provision-image.ps1 & "$temp\psexec.exe" -u AdminUser -p $AdminUserPassword -accepteula -h C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Unrestricted -File "$temp\provision-image.ps1" From 2da977e65f090644480434c04bbdd6c97ef14bd3 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Tue, 24 Mar 2020 02:12:07 -0700 Subject: [PATCH 10/15] Change provision script to invoke itself to avoid needing stable external script access. --- azure-devops/create-new-agent-image.ps1 | 2 +- azure-devops/provision-image-bootstrap.ps1 | 18 ---- azure-devops/provision-image.ps1 | 111 ++++++++++----------- 3 files changed, 55 insertions(+), 76 deletions(-) delete mode 100644 azure-devops/provision-image-bootstrap.ps1 diff --git a/azure-devops/create-new-agent-image.ps1 b/azure-devops/create-new-agent-image.ps1 index 9cabc8c7e10..8f158098c6f 100644 --- a/azure-devops/create-new-agent-image.ps1 +++ b/azure-devops/create-new-agent-image.ps1 @@ -205,7 +205,7 @@ Invoke-AzVMRunCommand ` -ResourceGroupName $ResourceGroupName ` -VMName $ProtoVMName ` -CommandId 'RunPowerShellScript' ` - -ScriptPath "$PSScriptRoot\provision-image-bootstrap.ps1" ` + -ScriptPath "$PSScriptRoot\provision-image.ps1" ` -Parameter @{AdminUserPassword = $AdminPW } #################################################################################################### diff --git a/azure-devops/provision-image-bootstrap.ps1 b/azure-devops/provision-image-bootstrap.ps1 deleted file mode 100644 index efbf81aab8e..00000000000 --- a/azure-devops/provision-image-bootstrap.ps1 +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -# -# Downloads provision-image.ps1, switches to the "AdminUser" account, then runs provision-image.ps1 -param( - [string]$AdminUserPassword -) - -if ([string]::IsNullOrEmpty($AdminUserPassword)) { - Write-Output "Missing AdminUser password." - exit 1 -} - -$temp = $env:TEMP - -curl.exe -L -o "$temp\psexec.exe" https://live.sysinternals.com/PsExec64.exe -curl.exe -L -o "$temp\provision-image.ps1" https://raw.githubusercontent.com/microsoft/STL/master/azure-devops/provision-image.ps1 -& "$temp\psexec.exe" -u AdminUser -p $AdminUserPassword -accepteula -h C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Unrestricted -File "$temp\provision-image.ps1" diff --git a/azure-devops/provision-image.ps1 b/azure-devops/provision-image.ps1 index eda5b56caef..1c351a6709a 100644 --- a/azure-devops/provision-image.ps1 +++ b/azure-devops/provision-image.ps1 @@ -1,13 +1,17 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -# Sets up VM image for use as a build machine prototype - -$WorkLoads = '--add Microsoft.VisualStudio.Component.VC.CLI.Support ' + ` - '--add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 ' + ` - '--add Microsoft.VisualStudio.Component.VC.Tools.ARM64 ' + ` - '--add Microsoft.VisualStudio.Component.VC.Tools.ARM ' + ` - '--add Microsoft.VisualStudio.Component.Windows10SDK.18362 ' +# +# Sets up a machine in preparation to become a build machine image, optionally switching to +# AdminUser first. +param( + [string]$AdminUserPassword = $null +) + +$WorkLoads = '--add Microsoft.VisualStudio.Component.VC.CLI.Support ' + ` + '--add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 ' + ` + '--add Microsoft.VisualStudio.Component.VC.Tools.ARM64 ' + ` + '--add Microsoft.VisualStudio.Component.VC.Tools.ARM ' + ` + '--add Microsoft.VisualStudio.Component.Windows10SDK.18362 ' $ReleaseInPath = 'Preview' $Sku = 'Enterprise' @@ -20,36 +24,31 @@ $PythonUrl = 'https://www.python.org/ftp/python/3.8.2/python-3.8.2-amd64.exe' $ErrorActionPreference = 'Stop' $ProgressPreference = 'SilentlyContinue' -Function PrintMsiExitCodeMessage -{ +Function PrintMsiExitCodeMessage { Param( $ExitCode ) - if ($ExitCode -eq 0 -or $ExitCode -eq 3010) - { + if ($ExitCode -eq 0 -or $ExitCode -eq 3010) { Write-Output "Installation successful! Exited with $ExitCode." } - else - { + else { Write-Output "Installation failed! Exited with $ExitCode." exit $ExitCode } } -Function InstallVisualStudio -{ +Function InstallVisualStudio { Param( [String]$WorkLoads, [String]$Sku, [String]$BootstrapperUrl ) - try - { + try { Write-Output 'Downloading Visual Studio...' [string]$bootstrapperExe = Join-Path ([System.IO.Path]::GetTempPath()) ` - ([System.IO.Path]::GetRandomFileName() + '.exe') + ([System.IO.Path]::GetRandomFileName() + '.exe') curl.exe -L -o $bootstrapperExe $BootstrapperUrl Write-Output "Installing Visual Studio..." @@ -57,23 +56,20 @@ Function InstallVisualStudio $proc = Start-Process -FilePath cmd.exe -ArgumentList $args -Wait -PassThru PrintMsiExitCodeMessage $proc.ExitCode } - catch - { + catch { Write-Output 'Failed to install Visual Studio!' Write-Output $_.Exception.Message exit 1 } } -Function InstallMSI -{ +Function InstallMSI { Param( [String]$Name, [String]$Url ) - try - { + try { Write-Output "Downloading $Name..." [string]$randomRoot = Join-Path ([System.IO.Path]::GetTempPath()) ([System.IO.Path]::GetRandomFileName()) [string]$msiPath = $randomRoot + '.msi' @@ -84,24 +80,21 @@ Function InstallMSI $proc = Start-Process -FilePath 'msiexec.exe' -ArgumentList $args -Wait -PassThru PrintMsiExitCodeMessage $proc.ExitCode } - catch - { + catch { Write-Output "Failed to install $Name!" Write-Output $_.Exception.Message exit -1 } } -Function InstallZip -{ +Function InstallZip { Param( [String]$Name, [String]$Url, [String]$Dir ) - try - { + try { Write-Output "Downloading $Name..." [string]$randomRoot = Join-Path ([System.IO.Path]::GetTempPath()) ([System.IO.Path]::GetRandomFileName()) [string]$zipPath = $randomRoot + '.zip' @@ -110,22 +103,19 @@ Function InstallZip Write-Output "Installing $Name..." Expand-Archive -Path $zipPath -DestinationPath $Dir -Force } - catch - { + catch { Write-Output "Failed to install $Name!" Write-Output $_.Exception.Message exit -1 } } -Function InstallLLVM -{ +Function InstallLLVM { Param( [String]$Url ) - try - { + try { Write-Output 'Downloading LLVM...' [string]$randomRoot = Join-Path ([System.IO.Path]::GetTempPath()) ([System.IO.Path]::GetRandomFileName()) [string]$installerPath = $randomRoot + '.exe' @@ -135,16 +125,14 @@ Function InstallLLVM $proc = Start-Process -FilePath $installerPath -ArgumentList @('/S') -NoNewWindow -Wait -PassThru PrintMsiExitCodeMessage $proc.ExitCode } - catch - { + catch { Write-Output "Failed to install LLVM!" Write-Output $_.Exception.Message exit -1 } } -Function InstallPython -{ +Function InstallPython { Param( [String]$Url ) @@ -156,27 +144,36 @@ Function InstallPython Write-Output 'Installing Python...' $proc = Start-Process -FilePath $installerPath -ArgumentList ` - @('/passive', 'InstallAllUsers=1', 'PrependPath=1', 'CompileAll=1') -Wait -PassThru + @('/passive', 'InstallAllUsers=1', 'PrependPath=1', 'CompileAll=1') -Wait -PassThru $exitCode = $proc.ExitCode - if ($exitCode -eq 0) - { + if ($exitCode -eq 0) { Write-Output 'Installation successful!' } - else - { + else { Write-Output "Installation failed! Exited with $exitCode." exit $exitCode } } -InstallMSI 'CMake' $CMakeUrl -InstallZip 'Ninja' $NinjaUrl 'C:\Program Files\CMake\bin' -InstallLLVM $LlvmUrl -InstallPython $PythonUrl -InstallVisualStudio -WorkLoads $WorkLoads -Sku $Sku -BootstrapperUrl $VisualStudioBootstrapperUrl -Write-Output 'Updating PATH...' -$environmentKey = Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment' -Name Path -Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment' ` - -Name Path ` - -Value "$($environmentKey.Path);C:\Program Files\CMake\bin;C:\Program Files\LLVM\bin" -C:\Windows\system32\sysprep\sysprep.exe /oobe /generalize /shutdown +if ([string]::IsNullOrEmpty($AdminUserPassword)) { + Write-Output "AdminUser password not supplied; assuming already running as AdminUser" + InstallMSI 'CMake' $CMakeUrl + InstallZip 'Ninja' $NinjaUrl 'C:\Program Files\CMake\bin' + InstallLLVM $LlvmUrl + InstallPython $PythonUrl + InstallVisualStudio -WorkLoads $WorkLoads -Sku $Sku -BootstrapperUrl $VisualStudioBootstrapperUrl + Write-Output 'Updating PATH...' + $environmentKey = Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment' -Name Path + Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment' ` + -Name Path ` + -Value "$($environmentKey.Path);C:\Program Files\CMake\bin;C:\Program Files\LLVM\bin" + C:\Windows\system32\sysprep\sysprep.exe /oobe /generalize /shutdown +} +else { + Write-Output "AdminUser password supplied; switching to AdminUser" + $temp = $env:TEMP + curl.exe -L -o "$temp\psexec.exe" https://live.sysinternals.com/PsExec64.exe + & "$temp\psexec.exe" -u AdminUser -p $AdminUserPassword -accepteula -h ` + C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe ` + -ExecutionPolicy Unrestricted -File "$PSCommandPath" +} From 22ada1d5353018b5261428675bdbd12afa7b721b Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Tue, 24 Mar 2020 02:16:15 -0700 Subject: [PATCH 11/15] PowerShell, extract collision detect, New-Password gen 9, HTTPS, remove Terminate, --- azure-devops/create-new-agent-image.ps1 | 60 ++++++++++++------------- 1 file changed, 28 insertions(+), 32 deletions(-) diff --git a/azure-devops/create-new-agent-image.ps1 b/azure-devops/create-new-agent-image.ps1 index 8f158098c6f..1f82d6d4394 100644 --- a/azure-devops/create-new-agent-image.ps1 +++ b/azure-devops/create-new-agent-image.ps1 @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # -# This script assumes you have installed Azure tools into Powershell by following the instructions +# This script assumes you have installed Azure tools into PowerShell by following the instructions # at https://docs.microsoft.com/en-us/powershell/azure/install-az-ps?view=azps-3.6.1 -# or are running from Azure Cloud Shell +# or are running from Azure Cloud Shell. # $Location = 'westus2' @@ -17,47 +17,41 @@ $ProgressActivity = 'Creating Scale Set' $TotalProgress = 8 $CurrentProgress = 1 +function Find-ResourceGroupNameCollision { + Param([string]$Test, $Resources) + + foreach ($resource in $Resources) { + if ($resource.ResourceGroupName -eq $Test) { + return $true + } + } + + return $false +} + function Find-ResourceGroupName { - Param( - [string] $prefix - ) + Param([string] $Prefix) - $result = $prefix $resources = Get-AzResourceGroup - $collision = $false - foreach ($resource in $resources) { - if ($resource.ResourceGroupName -eq $result) { - $collision = $true - break - } + if (Find-ResourceGroupNameCollision -Test $Prefix -Resources $resources) { + return $Prefix } $suffix = 0 - while ($collision) { - $collision = $false + do { $suffix++ - $result = "$prefix-$suffix" - foreach ($resource in $resources) { - if ($resource.ResourceGroupName -eq $result) { - $collision = $true - break - } - } - } - + $result = "$Prefix-$suffix" + } while (Find-ResourceGroupNameCollision -Test $result -Resources $resources) return $result } function New-Password { - Param ( - [int] $length = 32 - ) + Param ([int] $Length = 32) $Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" - $result = '' - for ($idx = 0; $idx -lt $length; $idx++) { - $result += $Chars[(Get-Random -Minimum 0 -Maximum ($Chars.Length - 1))] + for ($idx = 0; $idx -lt $Length; $idx++) { + $result += $Chars[(Get-Random -Minimum 0 -Maximum $Chars.Length)] } return $result @@ -65,6 +59,7 @@ function New-Password { function Start-WaitForShutdown { Param([string]$ResourceGroupName, [string]$Name) + Write-Output "Waiting for $Name to stop..." while ($true) { $Vm = Get-AzVM -ResourceGroupName $ResourceGroupName -Name $Name -Status @@ -82,10 +77,11 @@ function Start-WaitForShutdown { function Write-Reminders { Param([string]$AdminPW) + Write-Output "Location: $Location" Write-Output "Resource group name: $ResourceGroupName" Write-Output "User name: AdminUser" - Write-Output "Using Generated Password: $AdminPW" + Write-Output "Using generated password: $AdminPW" } #################################################################################################### @@ -108,7 +104,7 @@ Write-Progress ` $allowHttp = New-AzNetworkSecurityRuleConfig ` -Name AllowHTTP ` - -Description 'Allow HTTP(s)' ` + -Description 'Allow HTTP(S)' ` -Access Allow ` -Protocol Tcp ` -Direction Outbound ` @@ -294,4 +290,4 @@ New-AzVmss ` #################################################################################################### Write-Progress -Activity $ProgressActivity -Status -Completed Write-Reminders $AdminPW -Write-Output 'Finished! Terminate.' +Write-Output 'Finished!' From 44515e0625e2edfa8d37460af968425aa3c2a8c5 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Tue, 24 Mar 2020 03:13:01 -0700 Subject: [PATCH 12/15] bugs bugs bugs --- azure-devops/create-new-agent-image.ps1 | 10 +- azure-devops/provision-image.ps1 | 288 +++++++++++++----------- 2 files changed, 155 insertions(+), 143 deletions(-) diff --git a/azure-devops/create-new-agent-image.ps1 b/azure-devops/create-new-agent-image.ps1 index 1f82d6d4394..d0be072fde5 100644 --- a/azure-devops/create-new-agent-image.ps1 +++ b/azure-devops/create-new-agent-image.ps1 @@ -33,15 +33,13 @@ function Find-ResourceGroupName { Param([string] $Prefix) $resources = Get-AzResourceGroup - if (Find-ResourceGroupNameCollision -Test $Prefix -Resources $resources) { - return $Prefix - } - + $result = $Prefix $suffix = 0 - do { + while (Find-ResourceGroupNameCollision -Test $result -Resources $resources) { $suffix++ $result = "$Prefix-$suffix" - } while (Find-ResourceGroupNameCollision -Test $result -Resources $resources) + } + return $result } diff --git a/azure-devops/provision-image.ps1 b/azure-devops/provision-image.ps1 index 1c351a6709a..767298414a8 100644 --- a/azure-devops/provision-image.ps1 +++ b/azure-devops/provision-image.ps1 @@ -4,14 +4,37 @@ # Sets up a machine in preparation to become a build machine image, optionally switching to # AdminUser first. param( - [string]$AdminUserPassword = $null + [string]$AdminUserPassword = $null ) +if (-not [string]::IsNullOrEmpty($AdminUserPassword)) { + Write-Output "AdminUser password supplied; switching to AdminUser" + $PsExecPath = $env:TEMP + "\psexec.exe" + Write-Output "Downloading psexec to $PsExecPath" + & curl.exe -L -o $PsExecPath -s -S https://live.sysinternals.com/PsExec64.exe + $PsExecArgs = @( + '-u', + 'AdminUser', + '-p', + $AdminUserPassword, + '-accepteula', + '-h', + 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe', + '-ExecutionPolicy', + 'Unrestricted', + '-File', + $PSCommandPath + ) + Write-Output "Executing $PsExecPath @PsExecArgs" + & $PsExecPath @PsExecArgs + exit $? +} + $WorkLoads = '--add Microsoft.VisualStudio.Component.VC.CLI.Support ' + ` - '--add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 ' + ` - '--add Microsoft.VisualStudio.Component.VC.Tools.ARM64 ' + ` - '--add Microsoft.VisualStudio.Component.VC.Tools.ARM ' + ` - '--add Microsoft.VisualStudio.Component.Windows10SDK.18362 ' + '--add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 ' + ` + '--add Microsoft.VisualStudio.Component.VC.Tools.ARM64 ' + ` + '--add Microsoft.VisualStudio.Component.VC.Tools.ARM ' + ` + '--add Microsoft.VisualStudio.Component.Windows10SDK.18362 ' $ReleaseInPath = 'Preview' $Sku = 'Enterprise' @@ -25,155 +48,146 @@ $ErrorActionPreference = 'Stop' $ProgressPreference = 'SilentlyContinue' Function PrintMsiExitCodeMessage { - Param( - $ExitCode - ) - - if ($ExitCode -eq 0 -or $ExitCode -eq 3010) { - Write-Output "Installation successful! Exited with $ExitCode." - } - else { - Write-Output "Installation failed! Exited with $ExitCode." - exit $ExitCode - } + Param( + $ExitCode + ) + + if ($ExitCode -eq 0 -or $ExitCode -eq 3010) { + Write-Output "Installation successful! Exited with $ExitCode." + } + else { + Write-Output "Installation failed! Exited with $ExitCode." + exit $ExitCode + } } Function InstallVisualStudio { - Param( - [String]$WorkLoads, - [String]$Sku, - [String]$BootstrapperUrl - ) - - try { - Write-Output 'Downloading Visual Studio...' - [string]$bootstrapperExe = Join-Path ([System.IO.Path]::GetTempPath()) ` - ([System.IO.Path]::GetRandomFileName() + '.exe') - curl.exe -L -o $bootstrapperExe $BootstrapperUrl - - Write-Output "Installing Visual Studio..." - $args = ('/c', $bootstrapperExe, $WorkLoads, '--quiet', '--norestart', '--wait', '--nocache') - $proc = Start-Process -FilePath cmd.exe -ArgumentList $args -Wait -PassThru - PrintMsiExitCodeMessage $proc.ExitCode - } - catch { - Write-Output 'Failed to install Visual Studio!' - Write-Output $_.Exception.Message - exit 1 - } + Param( + [String]$WorkLoads, + [String]$Sku, + [String]$BootstrapperUrl + ) + + try { + Write-Output 'Downloading Visual Studio...' + [string]$bootstrapperExe = Join-Path ([System.IO.Path]::GetTempPath()) ` + ([System.IO.Path]::GetRandomFileName() + '.exe') + curl.exe -L -o $bootstrapperExe $BootstrapperUrl + + Write-Output "Installing Visual Studio..." + $args = ('/c', $bootstrapperExe, $WorkLoads, '--quiet', '--norestart', '--wait', '--nocache') + $proc = Start-Process -FilePath cmd.exe -ArgumentList $args -Wait -PassThru + PrintMsiExitCodeMessage $proc.ExitCode + } + catch { + Write-Output 'Failed to install Visual Studio!' + Write-Output $_.Exception.Message + exit 1 + } } Function InstallMSI { - Param( - [String]$Name, - [String]$Url - ) - - try { - Write-Output "Downloading $Name..." - [string]$randomRoot = Join-Path ([System.IO.Path]::GetTempPath()) ([System.IO.Path]::GetRandomFileName()) - [string]$msiPath = $randomRoot + '.msi' - curl.exe -L -o $msiPath $Url - - Write-Output "Installing $Name..." - $args = @('/i', $msiPath, '/norestart', '/quiet', '/qn') - $proc = Start-Process -FilePath 'msiexec.exe' -ArgumentList $args -Wait -PassThru - PrintMsiExitCodeMessage $proc.ExitCode - } - catch { - Write-Output "Failed to install $Name!" - Write-Output $_.Exception.Message - exit -1 - } + Param( + [String]$Name, + [String]$Url + ) + + try { + Write-Output "Downloading $Name..." + [string]$randomRoot = Join-Path ([System.IO.Path]::GetTempPath()) ([System.IO.Path]::GetRandomFileName()) + [string]$msiPath = $randomRoot + '.msi' + curl.exe -L -o $msiPath $Url + + Write-Output "Installing $Name..." + $args = @('/i', $msiPath, '/norestart', '/quiet', '/qn') + $proc = Start-Process -FilePath 'msiexec.exe' -ArgumentList $args -Wait -PassThru + PrintMsiExitCodeMessage $proc.ExitCode + } + catch { + Write-Output "Failed to install $Name!" + Write-Output $_.Exception.Message + exit -1 + } } Function InstallZip { - Param( - [String]$Name, - [String]$Url, - [String]$Dir - ) - - try { - Write-Output "Downloading $Name..." - [string]$randomRoot = Join-Path ([System.IO.Path]::GetTempPath()) ([System.IO.Path]::GetRandomFileName()) - [string]$zipPath = $randomRoot + '.zip' - curl.exe -L -o $zipPath $Url - - Write-Output "Installing $Name..." - Expand-Archive -Path $zipPath -DestinationPath $Dir -Force - } - catch { - Write-Output "Failed to install $Name!" - Write-Output $_.Exception.Message - exit -1 - } + Param( + [String]$Name, + [String]$Url, + [String]$Dir + ) + + try { + Write-Output "Downloading $Name..." + [string]$randomRoot = Join-Path ([System.IO.Path]::GetTempPath()) ([System.IO.Path]::GetRandomFileName()) + [string]$zipPath = $randomRoot + '.zip' + curl.exe -L -o $zipPath $Url + + Write-Output "Installing $Name..." + Expand-Archive -Path $zipPath -DestinationPath $Dir -Force + } + catch { + Write-Output "Failed to install $Name!" + Write-Output $_.Exception.Message + exit -1 + } } Function InstallLLVM { - Param( - [String]$Url - ) - - try { - Write-Output 'Downloading LLVM...' - [string]$randomRoot = Join-Path ([System.IO.Path]::GetTempPath()) ([System.IO.Path]::GetRandomFileName()) - [string]$installerPath = $randomRoot + '.exe' - curl.exe -L -o $installerPath $Url - - Write-Output 'Installing LLVM...' - $proc = Start-Process -FilePath $installerPath -ArgumentList @('/S') -NoNewWindow -Wait -PassThru - PrintMsiExitCodeMessage $proc.ExitCode - } - catch { - Write-Output "Failed to install LLVM!" - Write-Output $_.Exception.Message - exit -1 - } -} + Param( + [String]$Url + ) -Function InstallPython { - Param( - [String]$Url - ) - - Write-Output 'Downloading Python...' + try { + Write-Output 'Downloading LLVM...' [string]$randomRoot = Join-Path ([System.IO.Path]::GetTempPath()) ([System.IO.Path]::GetRandomFileName()) [string]$installerPath = $randomRoot + '.exe' curl.exe -L -o $installerPath $Url - Write-Output 'Installing Python...' - $proc = Start-Process -FilePath $installerPath -ArgumentList ` - @('/passive', 'InstallAllUsers=1', 'PrependPath=1', 'CompileAll=1') -Wait -PassThru - $exitCode = $proc.ExitCode - if ($exitCode -eq 0) { - Write-Output 'Installation successful!' - } - else { - Write-Output "Installation failed! Exited with $exitCode." - exit $exitCode - } + Write-Output 'Installing LLVM...' + $proc = Start-Process -FilePath $installerPath -ArgumentList @('/S') -NoNewWindow -Wait -PassThru + PrintMsiExitCodeMessage $proc.ExitCode + } + catch { + Write-Output "Failed to install LLVM!" + Write-Output $_.Exception.Message + exit -1 + } } -if ([string]::IsNullOrEmpty($AdminUserPassword)) { - Write-Output "AdminUser password not supplied; assuming already running as AdminUser" - InstallMSI 'CMake' $CMakeUrl - InstallZip 'Ninja' $NinjaUrl 'C:\Program Files\CMake\bin' - InstallLLVM $LlvmUrl - InstallPython $PythonUrl - InstallVisualStudio -WorkLoads $WorkLoads -Sku $Sku -BootstrapperUrl $VisualStudioBootstrapperUrl - Write-Output 'Updating PATH...' - $environmentKey = Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment' -Name Path - Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment' ` - -Name Path ` - -Value "$($environmentKey.Path);C:\Program Files\CMake\bin;C:\Program Files\LLVM\bin" - C:\Windows\system32\sysprep\sysprep.exe /oobe /generalize /shutdown -} -else { - Write-Output "AdminUser password supplied; switching to AdminUser" - $temp = $env:TEMP - curl.exe -L -o "$temp\psexec.exe" https://live.sysinternals.com/PsExec64.exe - & "$temp\psexec.exe" -u AdminUser -p $AdminUserPassword -accepteula -h ` - C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe ` - -ExecutionPolicy Unrestricted -File "$PSCommandPath" +Function InstallPython { + Param( + [String]$Url + ) + + Write-Output 'Downloading Python...' + [string]$randomRoot = Join-Path ([System.IO.Path]::GetTempPath()) ([System.IO.Path]::GetRandomFileName()) + [string]$installerPath = $randomRoot + '.exe' + curl.exe -L -o $installerPath $Url + + Write-Output 'Installing Python...' + $proc = Start-Process -FilePath $installerPath -ArgumentList ` + @('/passive', 'InstallAllUsers=1', 'PrependPath=1', 'CompileAll=1') -Wait -PassThru + $exitCode = $proc.ExitCode + if ($exitCode -eq 0) { + Write-Output 'Installation successful!' + } + else { + Write-Output "Installation failed! Exited with $exitCode." + exit $exitCode + } } + + +Write-Output "AdminUser password not supplied; assuming already running as AdminUser" +InstallMSI 'CMake' $CMakeUrl +InstallZip 'Ninja' $NinjaUrl 'C:\Program Files\CMake\bin' +InstallLLVM $LlvmUrl +InstallPython $PythonUrl +InstallVisualStudio -WorkLoads $WorkLoads -Sku $Sku -BootstrapperUrl $VisualStudioBootstrapperUrl +Write-Output 'Updating PATH...' +$environmentKey = Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment' -Name Path +Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment' ` + -Name Path ` + -Value "$($environmentKey.Path);C:\Program Files\CMake\bin;C:\Program Files\LLVM\bin" +C:\Windows\system32\sysprep\sysprep.exe /oobe /generalize /shutdown From 205b8d7f26de29dfa3b92f8cb5588eca6eda7525 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Tue, 24 Mar 2020 12:02:01 -0700 Subject: [PATCH 13/15] Scale in by oldest. --- azure-devops/create-new-agent-image.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/azure-devops/create-new-agent-image.ps1 b/azure-devops/create-new-agent-image.ps1 index d0be072fde5..caedc7a8ec9 100644 --- a/azure-devops/create-new-agent-image.ps1 +++ b/azure-devops/create-new-agent-image.ps1 @@ -255,6 +255,7 @@ $Vmss = New-AzVmssConfig ` -Overprovision $false ` -UpgradePolicyMode Manual ` -EvictionPolicy Delete ` + -ScaleInPolicy OldestVM ` -Priority Spot ` -MaxPrice -1 From d27126f27a58adf9d7cab916da8d3226bde73396 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Tue, 24 Mar 2020 12:22:03 -0700 Subject: [PATCH 14/15] Update pool with changes. --- azure-devops/run-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-devops/run-build.yml b/azure-devops/run-build.yml index a62b9e819cd..426b56de3b2 100644 --- a/azure-devops/run-build.yml +++ b/azure-devops/run-build.yml @@ -4,7 +4,7 @@ jobs: - job: ${{ parameters.targetPlatform }} pool: - name: StlBuild-2020-03-23-1 + name: StlBuild-2020-03-24 variables: vcpkgLocation: '$(Build.SourcesDirectory)/vcpkg' From 59b8a5963f1160e71593ba4cdace6ef096d1d68e Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Tue, 24 Mar 2020 12:24:16 -0700 Subject: [PATCH 15/15] Drop bogus status. --- azure-devops/create-new-agent-image.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-devops/create-new-agent-image.ps1 b/azure-devops/create-new-agent-image.ps1 index caedc7a8ec9..3031771d3e2 100644 --- a/azure-devops/create-new-agent-image.ps1 +++ b/azure-devops/create-new-agent-image.ps1 @@ -287,6 +287,6 @@ New-AzVmss ` -VirtualMachineScaleSet $Vmss #################################################################################################### -Write-Progress -Activity $ProgressActivity -Status -Completed +Write-Progress -Activity $ProgressActivity -Completed Write-Reminders $AdminPW Write-Output 'Finished!'