automation: transition to Windows Server 2022 stable
authorGregory Szorc <gregory.szorc@gmail.com>
Sat, 04 Jun 2022 11:18:32 -0700
branchstable
changeset 49435 f1dcddb7f328
parent 49434 ef40864bc074
child 49436 c809a77dfa1c
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
contrib/automation/hgautomation/aws.py
--- a/contrib/automation/hgautomation/aws.py	Fri Jun 03 20:25:06 2022 -0700
+++ b/contrib/automation/hgautomation/aws.py	Sat Jun 04 11:18:32 2022 -0700
@@ -59,7 +59,7 @@
 UBUNTU_ACCOUNT_ID = '099720109477'
 
 
-WINDOWS_BASE_IMAGE_NAME = 'Windows_Server-2019-English-Full-Base-*'
+WINDOWS_BASE_IMAGE_NAME = 'Windows_Server-2022-English-Full-Base-*'
 
 
 KEY_PAIRS = {
@@ -174,6 +174,23 @@
 net user Administrator "%s"
 wmic useraccount where "name='Administrator'" set PasswordExpires=FALSE
 
+# And set it via EC2Launch so it persists across reboots.
+$config = & $env:ProgramFiles\Amazon\EC2Launch\EC2Launch.exe get-agent-config --format json | ConvertFrom-Json
+$config | ConvertTo-Json -Depth 6 | Out-File -encoding UTF8 $env:ProgramData/Amazon/EC2Launch/config/agent-config.yml
+$setAdminAccount = @"
+{
+  "task": "setAdminAccount",
+  "inputs": {
+    "password": {
+      "type": "static",
+      "data": "%s"
+    }
+  }
+}
+"@
+$config.config | %%{if($_.stage -eq 'preReady'){$_.tasks += (ConvertFrom-Json -InputObject $setAdminAccount)}}
+$config | ConvertTo-Json -Depth 6 | Out-File -encoding UTF8 $env:ProgramData/Amazon/EC2Launch/config/agent-config.yml
+
 # First, make sure WinRM can't be connected to
 netsh advfirewall firewall set rule name="Windows Remote Management (HTTP-In)" new enable=yes action=block
 
@@ -752,7 +769,7 @@
     )
 
     if bootstrap:
-        config['UserData'] = WINDOWS_USER_DATA % password
+        config['UserData'] = WINDOWS_USER_DATA % (password, password)
 
     with temporary_ec2_instances(c.ec2resource, config) as instances:
         wait_for_ip_addresses(instances)
@@ -1173,28 +1190,16 @@
     with INSTALL_WINDOWS_DEPENDENCIES.open('r', encoding='utf-8') as fh:
         commands.extend(l.rstrip() for l in fh)
 
-    # Schedule run of EC2Launch on next boot. This ensures that UserData
-    # is executed.
-    # We disable setComputerName because it forces a reboot.
-    # We set an explicit admin password because this causes UserData to run
-    # as Administrator instead of System.
-    commands.extend(
-        [
-            r'''Set-Content -Path C:\ProgramData\Amazon\EC2-Windows\Launch\Config\LaunchConfig.json '''
-            r'''-Value '{"setComputerName": false, "setWallpaper": true, "addDnsSuffixList": true, '''
-            r'''"extendBootVolumeSize": true, "handleUserData": true, '''
-            r'''"adminPasswordType": "Specify", "adminPassword": "%s"}' '''
-            % c.automation.default_password(),
-            r'C:\ProgramData\Amazon\EC2-Windows\Launch\Scripts\InitializeInstance.ps1 '
-            r'–Schedule',
-        ]
-    )
-
     # Disable Windows Defender when bootstrapping because it just slows
     # things down.
     commands.insert(0, 'Set-MpPreference -DisableRealtimeMonitoring $true')
     commands.append('Set-MpPreference -DisableRealtimeMonitoring $false')
 
+    # Trigger shutdown to prepare for imaging.
+    commands.append(
+        'Stop-Computer -ComputerName localhost',
+    )
+
     # Compute a deterministic fingerprint to determine whether image needs
     # to be regenerated.
     fingerprint = resolve_fingerprint(