test(lab): add the kit that deploys and runs the operating-system matrix
Tests\Lab\Acceptance gets the scripts of Decision 24, which extends the
acceptance of the live tests from one lab to several operating-system builds:
- Deploy-OsMatrixLab.ps1, Add-OsMatrixMachine.ps1, Complete-OsMatrixLab.ps1
and Repair-OsMatrixBoot.ps1 build NtfsSecurityOsMatrixLab with AutomatedLab
(Server 2019, 2022 and 2025 file servers, Windows 11 clients) and repair a
base image whose host-side bcdboot left an empty EFI system partition.
- Test-MatrixReadiness.ps1 and Test-MatrixCleanup.ps1 gate each run and prove
that it left nothing behind (fixture accounts, shares, folders, group
members, orphaned SIDs, profiles); -Mode Repair removes what is left.
- Run-MatrixSequence.ps1 runs the live controller for every cell of the matrix
and stops after an infrastructure failure.
- Run-MatrixLocalSuite.ps1 and Invoke-LocalSuite.ps1 run the module's own
Pester suite on each machine in both editions, elevated and as a basic user,
as scheduled tasks: a process started from a remoting session gets every
privilege enabled, which eight of the tests do not expect.
- Export-MatrixResults.ps1 collates the cells, the skipped tests and the
package hashes into the results table.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
3 weeks ago
[ CmdletBinding ( ) ]
param (
[ Parameter ( Mandatory ) ] [string] $LogPath ,
[ Parameter ( Mandatory ) ] [ ValidatePattern ( '^[A-Za-z][A-Za-z0-9-]{0,14}$' ) ] [string] $VmName ,
[string] $LabName = 'NtfsSecurityOsMatrixLab' ,
[switch] $Start
)
# Repairs the boot files of one virtual machine of the matrix lab. AutomatedLab builds a base image with the bcdboot of the host and
# ignores its exit code; when the host's bcdboot can't process the boot files of an older image (it fails with exit code 193 on Windows
# Server 2019 and on Windows 11 22H2), the EFI system partition stays empty and the generation 2 virtual machine fails with Hyper-V event
# 18603. This script turns the machine off, mounts the machine's own differencing disk (never the shared base image), runs the bcdboot of
# the image itself, adds the removable-media path EFI\Boot\bootx64.efi that a new virtual machine boots from, checks the files, and
# dismounts the disk. It refuses a machine that isn't connected to the switch of the lab. Windows PowerShell 5.1 on the host, elevated.
$ErrorActionPreference = 'Stop'
$stamp = '[{0:yyyy-MM-dd HH:mm:ss}Z]'
function Write-Step { param ( [string] $Message ) ( $stamp -f [DateTime] :: UtcNow ) + ' ' + $Message | Add-Content -LiteralPath $LogPath }
$principal = [Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity] :: GetCurrent ( )
if ( -not $principal . IsInRole ( [Security.Principal.WindowsBuiltInRole] :: Administrator ) ) { throw 'This script must run in an elevated PowerShell session.' }
( $stamp -f [DateTime] :: UtcNow ) + " START repair-os-matrix-boot vm= $ VmName lab= $ LabName " | Set-Content -LiteralPath $LogPath
$diskPath = $null
$letters = @ ( )
try {
$vm = Get-VM -Name $VmName
if ( $vm . Generation -ne 2 ) { throw " $ VmName isn't a generation 2 machine. " }
$switches = @ ( Get-VMNetworkAdapter -VMName $VmName | ForEach-Object -Process { $_ . SwitchName } )
# An array comparison with -ne returns the elements that differ, and an empty result is false: a machine without an adapter, or with an
# adapter that has no switch, would pass, so the guard counts.
if ( $switches . Count -eq 0 -or @ ( $switches | Where-Object -FilterScript { $_ -ne $LabName } ) . Count -gt 0 ) { throw " $ VmName isn't connected only to the switch ' $ LabName' (switches: $( $switches -join ', ' ) ). Refusing. " }
test(lab): add the kit that deploys and runs the operating-system matrix
Tests\Lab\Acceptance gets the scripts of Decision 24, which extends the
acceptance of the live tests from one lab to several operating-system builds:
- Deploy-OsMatrixLab.ps1, Add-OsMatrixMachine.ps1, Complete-OsMatrixLab.ps1
and Repair-OsMatrixBoot.ps1 build NtfsSecurityOsMatrixLab with AutomatedLab
(Server 2019, 2022 and 2025 file servers, Windows 11 clients) and repair a
base image whose host-side bcdboot left an empty EFI system partition.
- Test-MatrixReadiness.ps1 and Test-MatrixCleanup.ps1 gate each run and prove
that it left nothing behind (fixture accounts, shares, folders, group
members, orphaned SIDs, profiles); -Mode Repair removes what is left.
- Run-MatrixSequence.ps1 runs the live controller for every cell of the matrix
and stops after an infrastructure failure.
- Run-MatrixLocalSuite.ps1 and Invoke-LocalSuite.ps1 run the module's own
Pester suite on each machine in both editions, elevated and as a basic user,
as scheduled tasks: a process started from a remoting session gets every
privilege enabled, which eight of the tests do not expect.
- Export-MatrixResults.ps1 collates the cells, the skipped tests and the
package hashes into the results table.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
3 weeks ago
if ( $vm . State -ne 'Off' ) {
Stop-VM -Name $VmName -TurnOff -Force
Write-Step " $ VmName turned off "
}
$drive = Get-VMHardDiskDrive -VMName $VmName | Select-Object -First 1
$diskPath = $drive . Path
$vhd = Get-VHD -Path $diskPath
if ( $vhd . VhdType -ne 'Differencing' ) { throw " $ diskPath isn't a differencing disk; refusing to change a base image. " }
Write-Step " disk $ diskPath (parent $( $vhd . ParentPath ) ) "
$image = Mount-VHD -Path $diskPath -Passthru
$disk = $image | Get-Disk
$partitions = @ ( Get-Partition -DiskNumber $disk . Number )
$esp = $partitions | Where-Object -FilterScript { $_ . GptType -eq '{c12a7328-f81f-11d2-ba4b-00a0c93ec93b}' } | Select-Object -First 1
$system = $partitions | Where-Object -FilterScript { $_ . Type -eq 'Basic' } | Sort-Object -Property Size -Descending | Select-Object -First 1
if ( -not $esp -or -not $system ) { throw 'The disk has no EFI system partition or no Windows partition.' }
foreach ( $partition in $esp , $system ) {
# The host may have assigned a letter to the Windows partition on mount already.
if ( -not ( Get-Partition -DiskNumber $disk . Number -PartitionNumber $partition . PartitionNumber ) . DriveLetter ) {
Add-PartitionAccessPath -DiskNumber $disk . Number -PartitionNumber $partition . PartitionNumber -AssignDriveLetter
}
$letters + = ( Get-Partition -DiskNumber $disk . Number -PartitionNumber $partition . PartitionNumber ) . DriveLetter
}
$espLetter = ( Get-Partition -DiskNumber $disk . Number -PartitionNumber $esp . PartitionNumber ) . DriveLetter
$systemLetter = ( Get-Partition -DiskNumber $disk . Number -PartitionNumber $system . PartitionNumber ) . DriveLetter
$windows = '{0}:\Windows' -f $systemLetter
$bcdboot = Join-Path -Path $windows -ChildPath 'System32\bcdboot.exe'
if ( -not ( Test-Path -LiteralPath $bcdboot ) ) { throw " $ bcdboot is missing. " }
$before = @ ( Get-ChildItem -LiteralPath ( '{0}:\' -f $espLetter ) -Recurse -Force -File -ErrorAction SilentlyContinue ) . Count
Write-Step ( " system partition {0}: {1}; ESP {2}: holds {3} files; image build {4} " -f $systemLetter , $windows , $espLetter , $before , ( Get-Item -LiteralPath $bcdboot ) . VersionInfo . ProductVersion )
$output = & $bcdboot $windows / s ( '{0}:' -f $espLetter ) / f UEFI 2 > & 1 | Out-String
Write-Step ( " bcdboot of the image: exit code {0}: {1} " -f $LASTEXITCODE , ( $output -replace '\s+' , ' ' ) . Trim ( ) )
if ( $LASTEXITCODE -ne 0 ) { throw " bcdboot of the image failed with exit code $ LASTEXITCODE. " }
$bootManager = '{0}:\EFI\Microsoft\Boot\bootmgfw.efi' -f $espLetter
if ( -not ( Test-Path -LiteralPath $bootManager ) ) { throw " $ bootManager is missing after bcdboot. " }
$removable = '{0}:\EFI\Boot' -f $espLetter
$null = New-Item -ItemType Directory -Path $removable -Force
Copy-Item -LiteralPath $bootManager -Destination ( Join-Path -Path $removable -ChildPath 'bootx64.efi' ) -Force
$after = @ ( Get-ChildItem -LiteralPath ( '{0}:\' -f $espLetter ) -Recurse -Force -File -ErrorAction SilentlyContinue ) . Count
$hasBcd = Test-Path -LiteralPath ( '{0}:\EFI\Microsoft\Boot\BCD' -f $espLetter )
Write-Step ( " ESP now holds {0} files; BCD present: {1}; bootx64.efi present: {2} " -f $after , $hasBcd , ( Test-Path -LiteralPath ( Join-Path -Path $removable -ChildPath 'bootx64.efi' ) ) )
if ( $after -lt 20 -or -not $hasBcd ) { throw " The EFI system partition still looks empty ( $ after files, BCD $ hasBcd). " }
}
catch {
Write-Step ( 'repair-os-matrix-boot-FAILED: {0}' -f $_ )
$_ | Format-List -Property * -Force | Out-String | Add-Content -LiteralPath $LogPath
$failed = $true
}
finally {
if ( $diskPath ) {
try {
foreach ( $partition in @ ( Get-Partition -DiskNumber ( Get-VHD -Path $diskPath ) . DiskNumber -ErrorAction SilentlyContinue | Where-Object -FilterScript { $_ . DriveLetter } ) ) {
Remove-PartitionAccessPath -DiskNumber $partition . DiskNumber -PartitionNumber $partition . PartitionNumber -AccessPath ( '{0}:\' -f $partition . DriveLetter ) -ErrorAction SilentlyContinue
}
}
catch { Write-Step ( 'access path cleanup: {0}' -f $_ ) }
Dismount-VHD -Path $diskPath -ErrorAction SilentlyContinue
Write-Step 'disk dismounted'
}
}
if ( $failed ) { exit 1 }
if ( $Start ) {
Start-VM -Name $VmName
Write-Step " $ VmName started "
}
Write-Step 'repair-os-matrix-boot-DONE'
exit 0