mirror of
https://github.com/microsoft/vcpkg.git
synced 2024-12-02 19:49:02 +08:00
070a18974b
Included is a script that sets up all vcpkg's Azure infrastructure for Windows PR tests, and several updates to baselines. The baseline updates are generally caused by an updated copy of the MSVC++ compiler caused by updating the VMs, but some are caused by missed failures only detected now because this did a cleared out archives directory first. Some of the build infrastructure isn't what I'd call 'pretty' (e.g. we're split into more scripts and such than I'd like) but this mirrors how our existing PR system works. It is expected that the existing vcpkg Windows PR system will hate these baseline updates so we'll need to merge this, then remove that (duplicate) workflow immediately afterwards, then delete all the Windows VMs powering the old infrastructure.
459 lines
14 KiB
PowerShell
459 lines
14 KiB
PowerShell
# Copyright (c) Microsoft Corporation.
|
|
# SPDX-License-Identifier: MIT
|
|
#
|
|
#
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Creates a Windows virtual machine scale set, set up for vcpkg's CI.
|
|
|
|
.DESCRIPTION
|
|
create-vmss.ps1 creates an Azure Windows VM scale set, set up for vcpkg's CI
|
|
system. See https://docs.microsoft.com/en-us/azure/virtual-machine-scale-sets/overview
|
|
for more information.
|
|
|
|
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 = 'SouthCentralUS'
|
|
$Prefix = 'PrWin-' + (Get-Date -Format 'yyyy-MM-dd')
|
|
$VMSize = 'Standard_F16s_v2'
|
|
$ProtoVMName = 'PROTOTYPE'
|
|
$LiveVMPrefix = 'BUILD'
|
|
$WindowsServerSku = '2019-Datacenter'
|
|
$InstalledDiskSizeInGB = 1024
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
$ProgressActivity = 'Creating Scale Set'
|
|
$TotalProgress = 12
|
|
$CurrentProgress = 1
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Returns whether there's a name collision in the resource group.
|
|
|
|
.DESCRIPTION
|
|
Find-ResourceGroupNameCollision takes a list of resources, and checks if $Test
|
|
collides names with any of the resources.
|
|
|
|
.PARAMETER Test
|
|
The name to test.
|
|
|
|
.PARAMETER Resources
|
|
The list of resources.
|
|
#>
|
|
function Find-ResourceGroupNameCollision {
|
|
[CmdletBinding()]
|
|
Param([string]$Test, $Resources)
|
|
|
|
foreach ($resource in $Resources) {
|
|
if ($resource.ResourceGroupName -eq $Test) {
|
|
return $true
|
|
}
|
|
}
|
|
|
|
return $false
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Attempts to find a name that does not collide with any resources in the resource group.
|
|
|
|
.DESCRIPTION
|
|
Find-ResourceGroupName takes a set of resources from Get-AzResourceGroup, and finds the
|
|
first name in {$Prefix, $Prefix-1, $Prefix-2, ...} such that the name doesn't collide with
|
|
any of the resources in the resource group.
|
|
|
|
.PARAMETER Prefix
|
|
The prefix of the final name; the returned name will be of the form "$Prefix(-[1-9][0-9]*)?"
|
|
#>
|
|
function Find-ResourceGroupName {
|
|
[CmdletBinding()]
|
|
Param([string] $Prefix)
|
|
|
|
$resources = Get-AzResourceGroup
|
|
$result = $Prefix
|
|
$suffix = 0
|
|
while (Find-ResourceGroupNameCollision -Test $result -Resources $resources) {
|
|
$suffix++
|
|
$result = "$Prefix-$suffix"
|
|
}
|
|
|
|
return $result
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Creates a randomly generated password.
|
|
|
|
.DESCRIPTION
|
|
New-Password generates a password, randomly, of length $Length, containing
|
|
only alphanumeric characters (both uppercase and lowercase).
|
|
|
|
.PARAMETER Length
|
|
The length of the returned password.
|
|
#>
|
|
function New-Password {
|
|
Param ([int] $Length = 32)
|
|
|
|
$Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
|
|
$result = ''
|
|
for ($idx = 0; $idx -lt $Length; $idx++) {
|
|
# NOTE: this should probably use RNGCryptoServiceProvider
|
|
$result += $Chars[(Get-Random -Minimum 0 -Maximum $Chars.Length)]
|
|
}
|
|
|
|
return $result
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Waits for the shutdown of the specified resource.
|
|
|
|
.DESCRIPTION
|
|
Wait-Shutdown takes a VM, and checks if there's a 'PowerState/stopped'
|
|
code; if there is, it returns. If there isn't, it waits ten seconds and
|
|
tries again.
|
|
|
|
.PARAMETER ResourceGroupName
|
|
The name of the resource group to look up the VM in.
|
|
|
|
.PARAMETER Name
|
|
The name of the virtual machine to wait on.
|
|
#>
|
|
function Wait-Shutdown {
|
|
[CmdletBinding()]
|
|
Param([string]$ResourceGroupName, [string]$Name)
|
|
|
|
Write-Host "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-Host "... not stopped yet, sleeping for 10 seconds"
|
|
Start-Sleep -Seconds 10
|
|
}
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Sanitizes a name to be used in a storage account.
|
|
|
|
.DESCRIPTION
|
|
Sanitize-Name takes a string, and removes all of the '-'s and
|
|
lowercases the string, since storage account names must have no
|
|
'-'s and must be completely lowercase alphanumeric. It then makes
|
|
certain that the length of the string is not greater than 24,
|
|
since that is invalid.
|
|
|
|
.PARAMETER RawName
|
|
The name to sanitize.
|
|
#>
|
|
function Sanitize-Name {
|
|
[CmdletBinding()]
|
|
Param(
|
|
[string]$RawName
|
|
)
|
|
|
|
$result = $RawName.Replace('-', '').ToLowerInvariant()
|
|
if ($result.Length -gt 24) {
|
|
Write-Error 'Sanitized name for storage account $result was too long.'
|
|
}
|
|
|
|
return $result
|
|
}
|
|
|
|
####################################################################################################
|
|
Write-Progress `
|
|
-Activity $ProgressActivity `
|
|
-Status 'Creating resource group' `
|
|
-PercentComplete (100 / $TotalProgress * $CurrentProgress++)
|
|
|
|
$ResourceGroupName = Find-ResourceGroupName $Prefix
|
|
$AdminPW = New-Password
|
|
New-AzResourceGroup -Name $ResourceGroupName -Location $Location
|
|
$AdminPWSecure = ConvertTo-SecureString $AdminPW -AsPlainText -Force
|
|
$Credential = New-Object System.Management.Automation.PSCredential ("AdminUser", $AdminPWSecure)
|
|
|
|
####################################################################################################
|
|
Write-Progress `
|
|
-Activity $ProgressActivity `
|
|
-Status 'Creating virtual network' `
|
|
-PercentComplete (100 / $TotalProgress * $CurrentProgress++)
|
|
|
|
$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
|
|
|
|
$allowStorage = New-AzNetworkSecurityRuleConfig `
|
|
-Name AllowStorage `
|
|
-Description 'Allow Storage' `
|
|
-Access Allow `
|
|
-Protocol * `
|
|
-Direction Outbound `
|
|
-Priority 1010 `
|
|
-SourceAddressPrefix VirtualNetwork `
|
|
-SourcePortRange * `
|
|
-DestinationAddressPrefix Storage `
|
|
-DestinationPortRange *
|
|
|
|
$denyEverythingElse = New-AzNetworkSecurityRuleConfig `
|
|
-Name DenyElse `
|
|
-Description 'Deny everything else' `
|
|
-Access Deny `
|
|
-Protocol * `
|
|
-Direction Outbound `
|
|
-Priority 1011 `
|
|
-SourceAddressPrefix * `
|
|
-SourcePortRange * `
|
|
-DestinationAddressPrefix * `
|
|
-DestinationPortRange *
|
|
|
|
$NetworkSecurityGroupName = $ResourceGroupName + 'NetworkSecurity'
|
|
$NetworkSecurityGroup = New-AzNetworkSecurityGroup `
|
|
-Name $NetworkSecurityGroupName `
|
|
-ResourceGroupName $ResourceGroupName `
|
|
-Location $Location `
|
|
-SecurityRules @($allowHttp, $allowDns, $allowStorage, $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
|
|
|
|
####################################################################################################
|
|
Write-Progress `
|
|
-Activity $ProgressActivity `
|
|
-Status 'Creating archives storage account' `
|
|
-PercentComplete (100 / $TotalProgress * $CurrentProgress++)
|
|
|
|
$StorageAccountName = Sanitize-Name $ResourceGroupName
|
|
|
|
New-AzStorageAccount `
|
|
-ResourceGroupName $ResourceGroupName `
|
|
-Location $Location `
|
|
-Name $StorageAccountName `
|
|
-SkuName 'Standard_LRS' `
|
|
-Kind StorageV2
|
|
|
|
$StorageAccountKeys = Get-AzStorageAccountKey `
|
|
-ResourceGroupName $ResourceGroupName `
|
|
-Name $StorageAccountName
|
|
|
|
$StorageAccountKey = $StorageAccountKeys[0].Value
|
|
|
|
$StorageContext = New-AzStorageContext `
|
|
-StorageAccountName $StorageAccountName `
|
|
-StorageAccountKey $StorageAccountKey
|
|
|
|
$ArchivesFiles = New-AzStorageShare -Name 'archives' -Context $StorageContext
|
|
Set-AzStorageShareQuota -ShareName 'archives' -Context $StorageContext -Quota 5120
|
|
$LogFiles = New-AzStorageShare -Name 'logs' -Context $StorageContext
|
|
Set-AzStorageShareQuota -ShareName 'logs' -Context $StorageContext -Quota 64
|
|
|
|
####################################################################################################
|
|
Write-Progress `
|
|
-Activity 'Creating prototype VM' `
|
|
-PercentComplete (100 / $TotalProgress * $CurrentProgress++)
|
|
|
|
$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
|
|
|
|
$InstallDiskName = $ProtoVMName + "InstallDisk"
|
|
$VM = Add-AzVMDataDisk `
|
|
-Vm $VM `
|
|
-Name $InstallDiskName `
|
|
-Lun 0 `
|
|
-Caching ReadWrite `
|
|
-CreateOption Empty `
|
|
-DiskSizeInGB $InstalledDiskSizeInGB `
|
|
-StorageAccountType 'StandardSSD_LRS'
|
|
|
|
$VM = Set-AzVMBootDiagnostic -VM $VM -Disable
|
|
New-AzVm `
|
|
-ResourceGroupName $ResourceGroupName `
|
|
-Location $Location `
|
|
-VM $VM
|
|
|
|
####################################################################################################
|
|
Write-Progress `
|
|
-Activity $ProgressActivity `
|
|
-Status 'Running provisioning script provision-image.ps1 in VM' `
|
|
-PercentComplete (100 / $TotalProgress * $CurrentProgress++)
|
|
|
|
Invoke-AzVMRunCommand `
|
|
-ResourceGroupName $ResourceGroupName `
|
|
-VMName $ProtoVMName `
|
|
-CommandId 'RunPowerShellScript' `
|
|
-ScriptPath "$PSScriptRoot\provision-image.ps1" `
|
|
-Parameter @{AdminUserPassword = $AdminPW; `
|
|
StorageAccountName=$StorageAccountName; `
|
|
StorageAccountKey=$StorageAccountKey;}
|
|
|
|
####################################################################################################
|
|
Write-Progress `
|
|
-Activity $ProgressActivity `
|
|
-Status 'Restarting VM' `
|
|
-PercentComplete (100 / $TotalProgress * $CurrentProgress++)
|
|
|
|
Restart-AzVM -ResourceGroupName $ResourceGroupName -Name $ProtoVMName
|
|
|
|
####################################################################################################
|
|
Write-Progress `
|
|
-Activity $ProgressActivity `
|
|
-Status 'Running provisioning script sysprep.ps1 in VM' `
|
|
-PercentComplete (100 / $TotalProgress * $CurrentProgress++)
|
|
|
|
Invoke-AzVMRunCommand `
|
|
-ResourceGroupName $ResourceGroupName `
|
|
-VMName $ProtoVMName `
|
|
-CommandId 'RunPowerShellScript' `
|
|
-ScriptPath "$PSScriptRoot\sysprep.ps1"
|
|
|
|
####################################################################################################
|
|
Write-Progress `
|
|
-Activity $ProgressActivity `
|
|
-Status 'Waiting for VM to shut down' `
|
|
-PercentComplete (100 / $TotalProgress * $CurrentProgress++)
|
|
|
|
Wait-Shutdown -ResourceGroupName $ResourceGroupName -Name $ProtoVMName
|
|
|
|
####################################################################################################
|
|
Write-Progress `
|
|
-Activity $ProgressActivity `
|
|
-Status 'Converting VM to Image' `
|
|
-PercentComplete (100 / $TotalProgress * $CurrentProgress++)
|
|
|
|
Stop-AzVM `
|
|
-ResourceGroupName $ResourceGroupName `
|
|
-Name $ProtoVMName `
|
|
-Force
|
|
|
|
Set-AzVM `
|
|
-ResourceGroupName $ResourceGroupName `
|
|
-Name $ProtoVMName `
|
|
-Generalized
|
|
|
|
$VM = Get-AzVM -ResourceGroupName $ResourceGroupName -Name $ProtoVMName
|
|
$PrototypeOSDiskName = $VM.StorageProfile.OsDisk.Name
|
|
$ImageConfig = New-AzImageConfig -Location $Location -SourceVirtualMachineId $VM.ID
|
|
$Image = New-AzImage -Image $ImageConfig -ImageName $ProtoVMName -ResourceGroupName $ResourceGroupName
|
|
|
|
####################################################################################################
|
|
Write-Progress `
|
|
-Activity $ProgressActivity `
|
|
-Status 'Deleting unused VM and disk' `
|
|
-PercentComplete (100 / $TotalProgress * $CurrentProgress++)
|
|
|
|
Remove-AzVM -Id $VM.ID -Force
|
|
Remove-AzDisk -ResourceGroupName $ResourceGroupName -DiskName $PrototypeOSDiskName -Force
|
|
Remove-AzDisk -ResourceGroupName $ResourceGroupName -DiskName $InstallDiskName -Force
|
|
|
|
####################################################################################################
|
|
Write-Progress `
|
|
-Activity $ProgressActivity `
|
|
-Status '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 `
|
|
-SkuCapacity 6 `
|
|
-SkuName $VMSize `
|
|
-SkuTier 'Standard' `
|
|
-Overprovision $false `
|
|
-UpgradePolicyMode Manual
|
|
|
|
$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
|
|
|
|
New-AzVmss `
|
|
-ResourceGroupName $ResourceGroupName `
|
|
-Name $VmssName `
|
|
-VirtualMachineScaleSet $Vmss
|
|
|
|
####################################################################################################
|
|
Write-Progress -Activity $ProgressActivity -Completed
|
|
Write-Host "Location: $Location"
|
|
Write-Host "Resource group name: $ResourceGroupName"
|
|
Write-Host "User name: AdminUser"
|
|
Write-Host "Using generated password: $AdminPW"
|
|
Write-Host 'Finished!'
|