Public/Test-OSDStageRepositoryAvailability.ps1
|
function Test-OSDStageRepositoryAvailability { [CmdletBinding()] param( [Parameter(Mandatory, Position = 0)] [Alias('Id')] [ValidateNotNullOrEmpty()] [string[]]$Name, [string]$WindowsPath, [switch]$SkipCacheRefresh, [switch]$ThrowOnFailure ) Assert-OSDStageSourceEnabled -Source Repository $names = @($Name | Select-Object -Unique) Assert-OSDStageRepositorySelection -Name $names $architecture = Get-OSDStageHostArchitecture $sourceUri = (Get-OSDStageConfiguration).CatalogUri $cachePath = $null try { $cachePath = Get-OSDStageCachePath } catch { Write-Verbose "USB cache unavailable: $($_.Exception.Message)" } if (-not $cachePath -and $WindowsPath) { $target = Resolve-OSDStageWindowsPath -WindowsPath $WindowsPath $cachePath = Join-Path $target 'Windows\Temp\OSDStage\RepositoryCache' } $catalog = $null $catalogStatus = 'NotConfigured' $catalogError = $null if ($SkipCacheRefresh) { $catalogStatus = 'Skipped' } elseif ($sourceUri) { try { $catalog = Get-OSDStageManifest -Uri $sourceUri -ErrorAction Stop $catalogStatus = 'Available' } catch { $catalogStatus = 'CatalogUnavailable' $catalogError = $_.Exception.Message } } $checks = [System.Collections.Generic.List[object]]::new() foreach ($item in $names) { $id = $item $status = $catalogStatus $detail = $catalogError $catalogAvailable = $false if ($catalogStatus -eq 'Available') { try { $resolved = Get-OSDStageCatalogPackages -CatalogUri $sourceUri -Catalog $catalog -Name $item -ErrorAction Stop $variants = @(Resolve-OSDStageCatalogPackageVariant -Package @($resolved.Packages) -Architecture $architecture -ErrorAction Stop) if ($variants.Count -ne 1) { throw 'Expected exactly one compatible repository package.' } $id = [string]$variants[0].Id $catalogAvailable = $true $status = 'Available' $detail = 'Compatible package metadata is available; archive download has not been tested.' } catch { $status = if ($_.Exception.Data.Contains('OSDStageAvailabilityStatus')) { [string]$_.Exception.Data['OSDStageAvailabilityStatus'] } else { 'CatalogPackageUnavailable' } $detail = $_.Exception.Message } } $checks.Add([pscustomobject]@{ Name = $item Id = $id Available = $catalogAvailable Source = if ($catalogAvailable) { 'Catalog' } else { 'None' } CatalogStatus = $status CatalogDetail = $detail CacheDetail = $null }) } # Add-OSDStage synchronizes a selection as one transaction. If any online # entry fails, its offline fallback must contain EVERY requested package. $needsFallback = @($checks | Where-Object { -not $_.Available }).Count -gt 0 if ($needsFallback) { foreach ($check in $checks) { $check.Available = $false $check.Source = 'None' try { if (-not $cachePath) { throw 'No cache volume or explicit WindowsPath is available.' } $ids = @(Resolve-OSDStageCachedPackageId -CachePath $cachePath -Name $check.Name -ErrorAction Stop) if ($ids.Count -ne 1 -or $ids[0] -notmatch '^[A-Za-z0-9][A-Za-z0-9._-]*$' -or $ids[0] -match '\.\.') { throw 'Cached identity is invalid or ambiguous.' } $cached = @(Test-OSDStageRepositoryCache -CachePath $cachePath -Name $ids[0] -ErrorAction Stop) if ($cached.Count -ne 1 -or -not $cached[0].Valid) { throw 'No unique SHA-256 validated archive is available.' } Resolve-OSDStageCatalogPackageVariant -Package $cached -Architecture $architecture -ErrorAction Stop | Out-Null $check.Id = [string]$ids[0] $check.Available = $true $check.Source = 'Cache' $check.CacheDetail = 'Compatible cached archive passed repository integrity checks.' } catch { $check.CacheDetail = $_.Exception.Message } } } $failed = @($checks | Where-Object { -not $_.Available }) $result = [pscustomobject]@{ PSTypeName = 'OSDStage.RepositoryAvailability' Valid = ($failed.Count -eq 0) Architecture = $architecture CatalogStatus = $catalogStatus CatalogError = $catalogError CachePath = $cachePath UsesCacheFallback = $needsFallback Packages = @($checks) } if ($ThrowOnFailure -and -not $result.Valid) { $reasons = @($failed | ForEach-Object { "[$($_.Name)] catalog: $($_.CatalogStatus) $($_.CatalogDetail); cache: $($_.CacheDetail)" }) throw "Repository availability check failed before staging: $($reasons -join ' | ')" } $result } |