Mercurial > public > mercurial-scm > hg-stable
comparison contrib/automation/hgautomation/aws.py @ 49402:f1dcddb7f328 stable
automation: transition to Windows Server 2022
Let's keep our Windows build environment modern by upgrading to the
latest OS.
As part of the upgrade, we pick up a migration to EC2Launch Version 2.
This has a different config mechanism. So we need to port how we manage
the administrator password.
As part of migrating to the new YAML/JSON config file mechanism, we move
the code to the powershell script that is run when the instance first
launches. This ensures that the config is retained during the reboot we
perform as part of building the Windows AMI.
The motivation for this is I'm currently unable to build the Windows
2019 AMI due to an issue installing OpenSSH. This _just works_ on
Windows Server 2022. I have no clue what the root cause is. I think
it might have something to do with Microsoft not publishing the files
in the right location.
Differential Revision: https://phab.mercurial-scm.org/D12630
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Sat, 04 Jun 2022 11:18:32 -0700 |
parents | 5c8148cd7f13 |
children | 3e84e001b6c1 |
comparison
equal
deleted
inserted
replaced
49401:ef40864bc074 | 49402:f1dcddb7f328 |
---|---|
57 DEBIAN_ACCOUNT_ID = '379101102735' | 57 DEBIAN_ACCOUNT_ID = '379101102735' |
58 DEBIAN_ACCOUNT_ID_2 = '136693071363' | 58 DEBIAN_ACCOUNT_ID_2 = '136693071363' |
59 UBUNTU_ACCOUNT_ID = '099720109477' | 59 UBUNTU_ACCOUNT_ID = '099720109477' |
60 | 60 |
61 | 61 |
62 WINDOWS_BASE_IMAGE_NAME = 'Windows_Server-2019-English-Full-Base-*' | 62 WINDOWS_BASE_IMAGE_NAME = 'Windows_Server-2022-English-Full-Base-*' |
63 | 63 |
64 | 64 |
65 KEY_PAIRS = { | 65 KEY_PAIRS = { |
66 'automation', | 66 'automation', |
67 } | 67 } |
172 | 172 |
173 # Set administrator password | 173 # Set administrator password |
174 net user Administrator "%s" | 174 net user Administrator "%s" |
175 wmic useraccount where "name='Administrator'" set PasswordExpires=FALSE | 175 wmic useraccount where "name='Administrator'" set PasswordExpires=FALSE |
176 | 176 |
177 # And set it via EC2Launch so it persists across reboots. | |
178 $config = & $env:ProgramFiles\Amazon\EC2Launch\EC2Launch.exe get-agent-config --format json | ConvertFrom-Json | |
179 $config | ConvertTo-Json -Depth 6 | Out-File -encoding UTF8 $env:ProgramData/Amazon/EC2Launch/config/agent-config.yml | |
180 $setAdminAccount = @" | |
181 { | |
182 "task": "setAdminAccount", | |
183 "inputs": { | |
184 "password": { | |
185 "type": "static", | |
186 "data": "%s" | |
187 } | |
188 } | |
189 } | |
190 "@ | |
191 $config.config | %%{if($_.stage -eq 'preReady'){$_.tasks += (ConvertFrom-Json -InputObject $setAdminAccount)}} | |
192 $config | ConvertTo-Json -Depth 6 | Out-File -encoding UTF8 $env:ProgramData/Amazon/EC2Launch/config/agent-config.yml | |
193 | |
177 # First, make sure WinRM can't be connected to | 194 # First, make sure WinRM can't be connected to |
178 netsh advfirewall firewall set rule name="Windows Remote Management (HTTP-In)" new enable=yes action=block | 195 netsh advfirewall firewall set rule name="Windows Remote Management (HTTP-In)" new enable=yes action=block |
179 | 196 |
180 # Delete any existing WinRM listeners | 197 # Delete any existing WinRM listeners |
181 winrm delete winrm/config/listener?Address=*+Transport=HTTP 2>$Null | 198 winrm delete winrm/config/listener?Address=*+Transport=HTTP 2>$Null |
750 'Tags': [{'Key': 'Name', 'Value': 'hg-temp-windows'}], | 767 'Tags': [{'Key': 'Name', 'Value': 'hg-temp-windows'}], |
751 } | 768 } |
752 ) | 769 ) |
753 | 770 |
754 if bootstrap: | 771 if bootstrap: |
755 config['UserData'] = WINDOWS_USER_DATA % password | 772 config['UserData'] = WINDOWS_USER_DATA % (password, password) |
756 | 773 |
757 with temporary_ec2_instances(c.ec2resource, config) as instances: | 774 with temporary_ec2_instances(c.ec2resource, config) as instances: |
758 wait_for_ip_addresses(instances) | 775 wait_for_ip_addresses(instances) |
759 | 776 |
760 print('waiting for Windows Remote Management service...') | 777 print('waiting for Windows Remote Management service...') |
1171 ] | 1188 ] |
1172 | 1189 |
1173 with INSTALL_WINDOWS_DEPENDENCIES.open('r', encoding='utf-8') as fh: | 1190 with INSTALL_WINDOWS_DEPENDENCIES.open('r', encoding='utf-8') as fh: |
1174 commands.extend(l.rstrip() for l in fh) | 1191 commands.extend(l.rstrip() for l in fh) |
1175 | 1192 |
1176 # Schedule run of EC2Launch on next boot. This ensures that UserData | |
1177 # is executed. | |
1178 # We disable setComputerName because it forces a reboot. | |
1179 # We set an explicit admin password because this causes UserData to run | |
1180 # as Administrator instead of System. | |
1181 commands.extend( | |
1182 [ | |
1183 r'''Set-Content -Path C:\ProgramData\Amazon\EC2-Windows\Launch\Config\LaunchConfig.json ''' | |
1184 r'''-Value '{"setComputerName": false, "setWallpaper": true, "addDnsSuffixList": true, ''' | |
1185 r'''"extendBootVolumeSize": true, "handleUserData": true, ''' | |
1186 r'''"adminPasswordType": "Specify", "adminPassword": "%s"}' ''' | |
1187 % c.automation.default_password(), | |
1188 r'C:\ProgramData\Amazon\EC2-Windows\Launch\Scripts\InitializeInstance.ps1 ' | |
1189 r'–Schedule', | |
1190 ] | |
1191 ) | |
1192 | |
1193 # Disable Windows Defender when bootstrapping because it just slows | 1193 # Disable Windows Defender when bootstrapping because it just slows |
1194 # things down. | 1194 # things down. |
1195 commands.insert(0, 'Set-MpPreference -DisableRealtimeMonitoring $true') | 1195 commands.insert(0, 'Set-MpPreference -DisableRealtimeMonitoring $true') |
1196 commands.append('Set-MpPreference -DisableRealtimeMonitoring $false') | 1196 commands.append('Set-MpPreference -DisableRealtimeMonitoring $false') |
1197 | |
1198 # Trigger shutdown to prepare for imaging. | |
1199 commands.append( | |
1200 'Stop-Computer -ComputerName localhost', | |
1201 ) | |
1197 | 1202 |
1198 # Compute a deterministic fingerprint to determine whether image needs | 1203 # Compute a deterministic fingerprint to determine whether image needs |
1199 # to be regenerated. | 1204 # to be regenerated. |
1200 fingerprint = resolve_fingerprint( | 1205 fingerprint = resolve_fingerprint( |
1201 { | 1206 { |